summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorGravatar Checkmate50 <dgeisler50@gmail.com>2016-06-06 23:14:18 -0600
committerGravatar Checkmate50 <dgeisler50@gmail.com>2016-06-06 23:14:18 -0600
commitd652155ae013f36a1ee17653a8e458baad2d9c2c (patch)
tree067d600fe3cd1723afc11682935f0123a1eab653 /Source
parentd7fc0deb2ca6d7ebee094b6ea5430d9b41f163ec (diff)
Merging complete. Everything looks good *crosses fingers*
Diffstat (limited to 'Source')
-rw-r--r--Source/AIFramework/AIFramework.csproj406
-rw-r--r--Source/AIFramework/CommonFunctionSymbols.cs2464
-rw-r--r--Source/AIFramework/Expr.cs1280
-rw-r--r--Source/AIFramework/Functional.cs860
-rw-r--r--Source/AIFramework/Lattice.cs1918
-rw-r--r--Source/AIFramework/Logger.cs112
-rw-r--r--Source/AIFramework/MultiLattice.cs1294
-rw-r--r--Source/AIFramework/Mutable.cs274
-rw-r--r--Source/AIFramework/Polyhedra/LinearConstraint.cs1088
-rw-r--r--Source/AIFramework/Polyhedra/LinearConstraintSystem.cs3510
-rw-r--r--Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs1524
-rw-r--r--Source/AIFramework/Polyhedra/SimplexTableau.cs1260
-rw-r--r--Source/AIFramework/VariableMap/ConstantAbstraction.cs502
-rw-r--r--Source/AIFramework/VariableMap/ConstantExpressions.cs1056
-rw-r--r--Source/AIFramework/VariableMap/DynamicTypeLattice.cs1022
-rw-r--r--Source/AIFramework/VariableMap/Intervals.cs1742
-rw-r--r--Source/AIFramework/VariableMap/MicroLattice.cs208
-rw-r--r--Source/AIFramework/VariableMap/Nullness.cs520
-rw-r--r--Source/AIFramework/VariableMap/VariableMapLattice.cs1708
-rw-r--r--Source/AIFramework/cce.cs384
-rw-r--r--Source/AbsInt/AbsInt.csproj590
-rw-r--r--Source/AbsInt/IntervalDomain.cs2428
-rw-r--r--Source/AbsInt/NativeLattice.cs670
-rw-r--r--Source/AbsInt/Traverse.cs338
-rw-r--r--Source/AbsInt/TrivialDomain.cs158
-rw-r--r--Source/AbsInt/cce.cs124
-rw-r--r--Source/BVD/App.config10
-rw-r--r--Source/BVD/BVD.csproj212
-rw-r--r--Source/BVD/Program.cs56
-rw-r--r--Source/BVD/Properties/AssemblyInfo.cs72
-rw-r--r--Source/Basetypes/Basetypes.csproj406
-rw-r--r--Source/Basetypes/BigDec.cs760
-rw-r--r--Source/Basetypes/BigNum.cs722
-rw-r--r--Source/Basetypes/Rational.cs496
-rw-r--r--Source/Basetypes/Set.cs570
-rw-r--r--Source/Basetypes/cce.cs384
-rw-r--r--Source/Boogie.sln1286
-rw-r--r--Source/BoogieDriver/BoogieDriver.cs212
-rw-r--r--Source/BoogieDriver/BoogieDriver.csproj646
-rw-r--r--Source/BoogieDriver/cce.cs210
-rw-r--r--Source/CodeContractsExtender/CodeContractsExtender.csproj404
-rw-r--r--Source/CodeContractsExtender/cce.cs366
-rw-r--r--Source/Concurrency/App.config12
-rw-r--r--Source/Concurrency/CivlRefinement.cs (renamed from Source/Concurrency/OwickiGries.cs)2418
-rw-r--r--Source/Concurrency/CivlTypeChecker.cs1160
-rw-r--r--Source/Concurrency/Concurrency.csproj228
-rw-r--r--Source/Concurrency/LinearSets.cs2007
-rw-r--r--Source/Concurrency/MoverCheck.cs1320
-rw-r--r--Source/Concurrency/Program.cs88
-rw-r--r--Source/Concurrency/Properties/AssemblyInfo.cs72
-rw-r--r--Source/Concurrency/SimulationRelation.cs394
-rw-r--r--Source/Concurrency/TypeCheck.cs724
-rw-r--r--Source/Concurrency/YieldTypeChecker.cs731
-rw-r--r--Source/Core/Absy.cs8985
-rw-r--r--Source/Core/AbsyCmd.cs6996
-rw-r--r--Source/Core/AbsyExpr.cs6671
-rw-r--r--Source/Core/AbsyQuant.cs1883
-rw-r--r--Source/Core/AbsyType.cs7812
-rw-r--r--Source/Core/AlphaEquality.cs324
-rw-r--r--Source/Core/BoogiePL.atg3022
-rw-r--r--Source/Core/CommandLineOptions.cs4328
-rw-r--r--Source/Core/Core.csproj470
-rw-r--r--Source/Core/DeadVarElim.cs3513
-rw-r--r--Source/Core/Duplicator.cs1623
-rw-r--r--Source/Core/Graph.as352
-rw-r--r--Source/Core/Inline.cs1538
-rw-r--r--Source/Core/InterProceduralReachabilityGraph.cs612
-rw-r--r--Source/Core/LambdaHelper.cs518
-rw-r--r--Source/Core/LoopUnroll.cs572
-rw-r--r--Source/Core/Makefile40
-rw-r--r--Source/Core/OOLongUtil.cs420
-rw-r--r--Source/Core/Parser.cs4848
-rw-r--r--Source/Core/Readme.txt122
-rw-r--r--Source/Core/ResolutionContext.cs1270
-rw-r--r--Source/Core/Scanner.cs1644
-rw-r--r--Source/Core/StandardVisitor.cs2334
-rw-r--r--Source/Core/TypeAmbiguitySeeker.cs244
-rw-r--r--Source/Core/Util.cs1376
-rw-r--r--Source/Core/VCExp.cs476
-rw-r--r--Source/Core/VariableDependenceAnalyser.cs1292
-rw-r--r--Source/Core/Xml.cs630
-rw-r--r--Source/Core/cce.cs384
-rw-r--r--Source/Doomed/DoomCheck.cs814
-rw-r--r--Source/Doomed/DoomErrorHandler.cs170
-rw-r--r--Source/Doomed/Doomed.csproj378
-rw-r--r--Source/Doomed/DoomedLoopUnrolling.cs1298
-rw-r--r--Source/Doomed/DoomedStrategy.cs1054
-rw-r--r--Source/Doomed/HasseDiagram.cs846
-rw-r--r--Source/Doomed/VCDoomed.cs1652
-rw-r--r--Source/ExecutionEngine/ExecutionEngine.cs3586
-rw-r--r--Source/ExecutionEngine/ExecutionEngine.csproj386
-rw-r--r--Source/ExecutionEngine/Properties/AssemblyInfo.cs72
-rw-r--r--Source/ExecutionEngine/VerificationResultCache.cs1332
-rw-r--r--Source/Forro.sln40
-rw-r--r--Source/Forro/Ast.fs76
-rw-r--r--Source/Forro/BoogieAst.fs80
-rw-r--r--Source/Forro/BoogiePrinter.fs224
-rw-r--r--Source/Forro/Forro.fsproj164
-rw-r--r--Source/Forro/Lexer.fsl120
-rw-r--r--Source/Forro/Main.fs114
-rw-r--r--Source/Forro/Parser.fsy244
-rw-r--r--Source/Forro/Printer.fs214
-rw-r--r--Source/Forro/Resolver.fs246
-rw-r--r--Source/Forro/Translator.fs434
-rw-r--r--Source/Graph/Graph.cs2894
-rw-r--r--Source/Graph/Graph.csproj398
-rw-r--r--Source/Graph/cce.cs384
-rw-r--r--Source/Houdini/AbstractHoudini.cs9323
-rw-r--r--Source/Houdini/AnnotationDependenceAnalyser.cs1756
-rw-r--r--Source/Houdini/Checker.cs911
-rw-r--r--Source/Houdini/ConcurrentHoudini.cs208
-rw-r--r--Source/Houdini/Houdini.cs2658
-rw-r--r--Source/Houdini/Houdini.csproj306
-rw-r--r--Source/Houdini/StagedHoudini.cs854
-rw-r--r--Source/Model/Model.cs1412
-rw-r--r--Source/Model/Model.csproj218
-rw-r--r--Source/Model/ModelParser.cs4
-rw-r--r--Source/Model/Properties/AssemblyInfo.cs46
-rw-r--r--Source/ModelViewer/BCTProvider.cs294
-rw-r--r--Source/ModelViewer/BaseProvider.cs272
-rw-r--r--Source/ModelViewer/DafnyProvider.cs776
-rw-r--r--Source/ModelViewer/DataModel.cs594
-rw-r--r--Source/ModelViewer/Main.Designer.cs998
-rw-r--r--Source/ModelViewer/Main.cs1740
-rw-r--r--Source/ModelViewer/Main.resx4382
-rw-r--r--Source/ModelViewer/ModelViewer.csproj422
-rw-r--r--Source/ModelViewer/Namer.cs1160
-rw-r--r--Source/ModelViewer/Properties/AssemblyInfo.cs50
-rw-r--r--Source/ModelViewer/Properties/Resources.Designer.cs126
-rw-r--r--Source/ModelViewer/Properties/Resources.resx232
-rw-r--r--Source/ModelViewer/Properties/Settings.Designer.cs52
-rw-r--r--Source/ModelViewer/Properties/Settings.settings14
-rw-r--r--Source/ModelViewer/SourceView.Designer.cs124
-rw-r--r--Source/ModelViewer/SourceView.cs104
-rw-r--r--Source/ModelViewer/SourceView.resx238
-rw-r--r--Source/ModelViewer/TreeSkeleton.cs410
-rw-r--r--Source/ModelViewer/VccProvider.cs3052
-rw-r--r--Source/ParserHelper/ParserHelper.cs486
-rw-r--r--Source/ParserHelper/ParserHelper.csproj284
-rw-r--r--Source/Predication/Predication.csproj348
-rw-r--r--Source/Predication/SmartBlockPredicator.cs1274
-rw-r--r--Source/Predication/UniformityAnalyser.cs1082
-rw-r--r--Source/Provers/SMTLib/CVC4.cs142
-rw-r--r--Source/Provers/SMTLib/Inspector.cs314
-rw-r--r--Source/Provers/SMTLib/ProverInterface.cs5075
-rw-r--r--Source/Provers/SMTLib/SExpr.cs526
-rw-r--r--Source/Provers/SMTLib/SMTLib.csproj474
-rw-r--r--Source/Provers/SMTLib/SMTLibLineariser.cs1885
-rw-r--r--Source/Provers/SMTLib/SMTLibNamer.cs289
-rw-r--r--Source/Provers/SMTLib/SMTLibProcess.cs787
-rw-r--r--Source/Provers/SMTLib/SMTLibProverOptions.cs316
-rw-r--r--Source/Provers/SMTLib/TypeDeclCollector.cs803
-rw-r--r--Source/Provers/SMTLib/Z3.cs772
-rw-r--r--Source/Provers/SMTLib/cce.cs384
-rw-r--r--Source/Provers/TPTP/ProverInterface.cs702
-rw-r--r--Source/Provers/TPTP/TPTP.csproj260
-rw-r--r--Source/Provers/TPTP/TPTPLineariser.cs1480
-rw-r--r--Source/Provers/TPTP/TypeDeclCollector.cs270
-rw-r--r--Source/Provers/Z3api/ContextLayer.cs1454
-rw-r--r--Source/Provers/Z3api/ProverLayer.cs706
-rw-r--r--Source/Provers/Z3api/SafeContext.cs30
-rw-r--r--Source/Provers/Z3api/StubContext.cs148
-rw-r--r--Source/Provers/Z3api/TypeAdapter.cs392
-rw-r--r--Source/Provers/Z3api/VCExprVisitor.cs1298
-rw-r--r--Source/Provers/Z3api/Z3api.csproj376
-rw-r--r--Source/Provers/Z3api/cce.cs384
-rw-r--r--Source/UnitTests/BasetypesTests/BasetypesTests.csproj136
-rw-r--r--Source/UnitTests/BasetypesTests/Properties/AssemblyInfo.cs72
-rw-r--r--Source/UnitTests/BasetypesTests/packages.config6
-rw-r--r--Source/UnitTests/CoreTests/CoreTests.csproj166
-rw-r--r--Source/UnitTests/CoreTests/Duplicator.cs8
-rw-r--r--Source/UnitTests/CoreTests/Properties/AssemblyInfo.cs72
-rw-r--r--Source/UnitTests/CoreTests/packages.config6
-rw-r--r--Source/UnitTests/TestUtil/Properties/AssemblyInfo.cs72
-rw-r--r--Source/UnitTests/TestUtil/TestUtil.csproj140
-rw-r--r--Source/UnitTests/TestUtil/packages.config6
-rw-r--r--Source/VCExpr/BigLiteralAbstracter.cs462
-rw-r--r--Source/VCExpr/Boogie2VCExpr.cs2478
-rw-r--r--Source/VCExpr/Clustering.cs1042
-rw-r--r--Source/VCExpr/LetBindingSorter.cs322
-rw-r--r--Source/VCExpr/NameClashResolver.cs392
-rw-r--r--Source/VCExpr/SimplifyLikeLineariser.cs2444
-rw-r--r--Source/VCExpr/TermFormulaFlattening.cs494
-rw-r--r--Source/VCExpr/TypeErasure.cs3420
-rw-r--r--Source/VCExpr/TypeErasureArguments.cs1506
-rw-r--r--Source/VCExpr/TypeErasurePremisses.cs2674
-rw-r--r--Source/VCExpr/VCExpr.csproj446
-rw-r--r--Source/VCExpr/VCExprAST.cs4536
-rw-r--r--Source/VCExpr/VCExprASTPrinter.cs864
-rw-r--r--Source/VCExpr/VCExprASTVisitors.cs3360
-rw-r--r--Source/VCExpr/cce.cs384
-rw-r--r--Source/VCGeneration/Check.cs1381
-rw-r--r--Source/VCGeneration/ConditionGeneration.cs4026
-rw-r--r--Source/VCGeneration/Context.cs510
-rw-r--r--Source/VCGeneration/ExprExtensions.cs706
-rw-r--r--Source/VCGeneration/FixedpointVC.cs4474
-rw-r--r--Source/VCGeneration/OrderingAxioms.cs676
-rw-r--r--Source/VCGeneration/RPFP.cs1218
-rw-r--r--Source/VCGeneration/StratifiedVC.cs5820
-rw-r--r--Source/VCGeneration/VC.cs8027
-rw-r--r--Source/VCGeneration/VCGeneration.csproj448
-rw-r--r--Source/VCGeneration/Wlp.cs530
-rw-r--r--Source/VCGeneration/cce.cs210
-rw-r--r--Source/version.cs8
-rw-r--r--Source/version.ssc12
205 files changed, 117608 insertions, 116348 deletions
diff --git a/Source/AIFramework/AIFramework.csproj b/Source/AIFramework/AIFramework.csproj
index a809b8bf..a04074a6 100644
--- a/Source/AIFramework/AIFramework.csproj
+++ b/Source/AIFramework/AIFramework.csproj
@@ -1,204 +1,204 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>AIFramework</RootNamespace>
- <AssemblyName>AIFramework</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for AIFramework.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\AIFramework.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <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.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>AIFramework</RootNamespace>
+ <AssemblyName>AIFramework</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for AIFramework.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\AIFramework.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <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.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
</Project> \ No newline at end of file
diff --git a/Source/AIFramework/CommonFunctionSymbols.cs b/Source/AIFramework/CommonFunctionSymbols.cs
index 6f7a9f93..6a287810 100644
--- a/Source/AIFramework/CommonFunctionSymbols.cs
+++ b/Source/AIFramework/CommonFunctionSymbols.cs
@@ -1,1232 +1,1232 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.AbstractInterpretationFramework
-{
- using System.Diagnostics.Contracts;
- using System.Collections;
- using System.Collections.Generic;
- //using Microsoft.SpecSharp.Collections;
- using Microsoft.Basetypes;
-
- /// <summary>
- /// A basic class for function symbols.
- /// </summary>
- public class FunctionSymbol : IFunctionSymbol
- {
- private readonly string/*!*/ display;
- private readonly AIType/*!*/ typ;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(display != null);
- Contract.Invariant(typ != null);
- }
-
-
- public FunctionSymbol(AIType/*!*/ typ)
- : this("FunctionSymbol", typ) {
- Contract.Requires(typ != null);
- }
-
- 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 { Contract.Ensures(Contract.Result<AIType>() != null); return typ; } }
-
- [NoDefaultContract]
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return display;
- }
-
- }
-
- /// <summary>
- /// A class for integer constants.
- /// </summary>
- public class IntSymbol : FunctionSymbol
- {
- public readonly BigNum Value;
-
- /// <summary>
- /// The intention is that this constructor be called only from the Int.Const method.
- /// </summary>
- internal IntSymbol(BigNum x)
- : base(cce.NonNull(x.ToString()), Int.Type) {
- this.Value = x;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- IntSymbol isym = other as IntSymbol;
- return isym != null && isym.Value.Equals(this.Value);
- }
-
- [Pure]
- public override int GetHashCode() {
- return Value.GetHashCode();
- }
- }
-
- /// <summary>
- /// A class for bitvector constants.
- /// </summary>
- public class BvSymbol : FunctionSymbol
- {
- public readonly BigNum Value;
- public readonly int Bits;
-
- /// <summary>
- /// The intention is that this constructor be called only from the Int.Const method.
- /// </summary>
- internal BvSymbol(BigNum x, int y)
- : base(x + "bv" + y, Bv.Type) {
- this.Value = x;
- this.Bits = y;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- BvSymbol isym = other as BvSymbol;
- return isym != null && isym.Value == this.Value && isym.Bits == this.Bits;
- }
-
- [Pure]
- public override int GetHashCode() {
- unchecked {
- return Value.GetHashCode() ^ Bits;
- }
- }
- }
-
- public class DoubleSymbol : FunctionSymbol
- {
- public readonly double Value;
-
- /// <summary>
- /// The intention is that this constructor be called only from the Double.Const method.
- /// </summary>
- internal DoubleSymbol(double x)
- : base(cce.NonNull(x.ToString()), Double.Type) {
- this.Value = x;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- DoubleSymbol dsym = other as DoubleSymbol;
- return dsym != null && dsym.Value == this.Value;
- }
-
- [Pure]
- public override int GetHashCode() {
- return Value.GetHashCode();
- }
- }
-
- /// <summary>
- /// Function symbol based on a string. Uses the string equality for determining equality
- /// of symbol.
- /// </summary>
- public class NamedSymbol : FunctionSymbol
- {
- 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) {
- Contract.Requires(typ != null);
- Contract.Requires(symbol != null);
- }
-
- [NoDefaultContract]
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- NamedSymbol nsym = other as NamedSymbol;
- return nsym != null && this.Value.Equals(nsym.Value);
- }
-
- [NoDefaultContract]
- [Pure]
- public override int GetHashCode() {
- return Value.GetHashCode();
- }
- }
-
- //
- // In the following, the classes like Value and Prop serve two
- // roles. The primary role is to be the base types for AIType.
- // The only objects of these classes are the representative
- // objects that denote an AIType, which are given by the
- // "Type" property. Subtypes in the AIType language are
- // encoded by subclassing. This yields some "higher-orderness"
- // for checking subtyping in the AIType language, by using
- // the Spec#/C# subclassing checks.
- //
- // The other role is simply as a module for collecting like function
- // symbols.
- //
-
- //-------------------------- Terms ----------------------------------
-
- /// <summary>
- /// A class with the equality symbol and the ValueType.Type.
- /// </summary>
- public class Value : AIType
- {
- 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];
- if (result != null) {
- return result;
- }
- }
- AIType[] signature = new AIType[1 + inParameterCount];
- for (int i = 0; i < signature.Length; i++) {
- signature[i] = valtype;
- }
- result = new FunctionType(signature);
- if (inParameterCount < funtypeCache.Length) {
- funtypeCache[inParameterCount] = result;
- }
- return result;
- }
-
- [Once]
- private static AIType/*!*/ binreltype;
-
- private static AIType/*!*/ BinrelType {
- get {
- Contract.Ensures(Contract.Result<AIType>() != null);
- if (binreltype == null) {
- binreltype = new FunctionType(Type, Type, Prop.Type);
- }
- return binreltype;
- }
- }
-
- [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 {
- 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 {
- Contract.Ensures(Contract.Result<FunctionSymbol>() != null);
- if (_subtype == null) {
- _subtype = new FunctionSymbol("<:", BinrelType);
- }
- return _subtype;
- }
- }
-
- [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 {
- Contract.Ensures(Contract.Result<FunctionSymbol>() != null);
- if (_typeof == null) {
- _typeof = new FunctionSymbol("typeof", TypeofType);
- }
- return _typeof;
- }
- }
-
- /// <summary>
- /// Value should not be instantiated from the outside, except perhaps in
- /// subclasses.
- /// </summary>
- protected Value() { }
-
- }
-
- public class Int : Value
- {
- private static readonly AIType/*!*/ inttype = new Int();
- public static new 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 { 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);
- }
-
- /// <summary>
- /// Int should not be instantiated from the outside, except perhaps in
- /// subclasses.
- /// </summary>
- private Int() { }
- }
-
- public class Double : Value
- {
- private static readonly AIType/*!*/ doubletype = new Double();
- public static new AIType/*!*/ Type { get { Contract.Ensures(Contract.Result<AIType>() != null); return doubletype; } }
-
- 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);
- }
-
- /// <summary>
- /// Double should not be instantiated from the outside, except perhaps in
- /// subclasses.
- /// </summary>
- private Double() { }
- }
-
- public class Bv : Value
- {
- private static readonly AIType/*!*/ bvtype = new Bv();
- public static new 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 { 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);
- }
-
- /// <summary>
- /// Int should not be instantiated from the outside, except perhaps in
- /// subclasses.
- /// </summary>
- private Bv() { }
- }
-
- public class Ref : Value
- {
- private static readonly AIType/*!*/ reftype = new Ref();
- public static new AIType/*!*/ Type { get { Contract.Ensures(Contract.Result<AIType>() != null); return reftype; } }
-
- private static readonly FunctionSymbol/*!*/ _null = new FunctionSymbol("null", Type);
-
- 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
- /// subclasses.
- /// </summary>
- private Ref() { }
- }
-
- public class HeapStructure : Value
- {
- private static readonly AIType/*!*/ reftype = new HeapStructure();
- public static new AIType/*!*/ Type { get { Contract.Ensures(Contract.Result<AIType>() != null); return reftype; } }
-
-
-
- /// <summary>
- /// HeapStructure should not be instantiated from the outside, except perhaps in
- /// subclasses.
- /// </summary>
- private HeapStructure() { }
- }
-
- public class FieldName : Value
- {
- private static readonly AIType/*!*/ fieldnametype = new FieldName();
- public static new 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 { 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) {
- Contract.Requires(f != null);
- return f.Equals(Allocated);
- }
-
- /// <summary>
- /// FieldName should not be instantiated from the outside, except perhaps in
- /// subclasses.
- /// </summary>
- private FieldName() { }
- }
-
- public class Heap : Value
- {
- private static readonly AIType/*!*/ heaptype = new Heap();
- public static new 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",
- // Heap x FieldName -> Prop
- new FunctionType(Type, FieldName.Type, Prop.Type)
- );
- public static FunctionSymbol/*!*/ Select1 { get { Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _select1; } }
-
- 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 { 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",
- // Heap x FieldName x Value -> Heap
- new FunctionType(Type, FieldName.Type, Value.Type, Type)
- );
- public static FunctionSymbol/*!*/ Update1 { get { Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _update1; } }
-
- 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 { Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _update2; } }
-
- private static readonly FunctionSymbol/*!*/ _unsupportedHeapOp =
- new FunctionSymbol("UnsupportedHeapOp",
- // Heap x FieldName -> Prop
- new FunctionType(Type, FieldName.Type, Prop.Type)
- );
- 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
- /// subclasses.
- /// </summary>
- private Heap() { }
- }
-
- // public class List : Value
- // {
- // private static IDictionary/*<AIType!,AIType!>*/! lists = new Hashtable();
- // public static AIType! Type(AIType! typeParameter)
- // {
- // if (lists.Contains(typeParameter))
- // return lists[typeParameter];
- // else
- // {
- // AIType! result = new List(typeParameter);
- // lists[typeParameter] = result;
- // return result;
- // }
- // }
- //
- // private static IDictionary/*<AIType!,AIType!>*/! nils = new Hashtable();
- // public static FunctionSymbol! Nil(AIType! typeParameter)
- // {
- // if (nils.Contains(typeParameter))
- // return nils[typeParameter];
- // else
- // {
- // FunctionSymbol! result = new FunctionSymbol(Type(typeParameter));
- // nils[typeParameter] = result;
- // return result;
- // }
- // }
- //
- // private static IDictionary/*<AIType!,AIType!>*/! cons = new Hashtable();
- // public static FunctionSymbol! Cons(AIType! typeParameter)
- // {
- // if (cons.Contains(typeParameter))
- // return cons[typeParameter];
- // else
- // {
- // FunctionSymbol! result = new FunctionSymbol(
- // new FunctionType(typeParameter, Type(typeParameter), Type(typeParameter))
- // );
- // cons[typeParameter] = result;
- // return result;
- // }
- // }
- //
- // private AIType! typeParameter;
- // public AIType(TypeParameter/*!*/ ){
- //Contract.Requires( != null);
- //return typeParameter; } }
- //
- // /// <summary>
- // /// List should not be instantiated from the outside.
- // /// </summary>
- // private List(AIType! typeParameter)
- // {
- // this.typeParameter = typeParameter;
- // }
- // }
- //
- // public class Pair : Value
- // {
- // private static IDictionary! pairs = new Hashtable();
- // public static AIType! Type(AIType! type1, AIType! type2)
- // {
- // Microsoft.AbstractInterpretationFramework.Collections.Pair typpair
- // = new Microsoft.AbstractInterpretationFramework.Collections.Pair(type1, type2);
- //
- // if (pairs.Contains(typpair))
- // return pairs[typpair];
- // else
- // {
- // AIType! result = new Pair(type1, type2);
- // pairs[typpair] = result;
- // return result;
- // }
- // }
- //
- // private static IDictionary! constructs = new Hashtable();
- // public static FunctionSymbol! Pair(AIType! type1, AIType! type2)
- // {
- // Microsoft.AbstractInterpretationFramework.Collections.Pair typpair
- // = new Microsoft.AbstractInterpretationFramework.Collections.Pair(type1, type2);
- //
- // if (constructs.Contains(typpair))
- // return constructs[typpair];
- // else
- // {
- // FunctionSymbol! result = new FunctionSymbol(
- // new FunctionType(type1, type2, Type(type1, type2))
- // );
- // constructs[typpair] = result;
- // return result;
- // }
- // }
- //
- // protected AIType! type1;
- // protected AIType! 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.
- // /// </summary>
- // protected Pair(AIType! type1, AIType! type2)
- // {
- // this.type1 = type1;
- // this.type2 = type2;
- // }
- // }
-
- //-------------------------- Propositions ---------------------------
-
-
- /// <summary>
- /// A class with global propositional symbols and the Prop.Type.
- /// </summary>
- public sealed class Prop : AIType
- {
- private static readonly AIType/*!*/ proptype = new Prop();
-
- 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 =
- 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);
-
-
- [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>
- /// Prop should not be instantiated from the outside.
- /// </summary>
- private Prop() { }
-
-
-
- //
- // Utility Methods
- //
-
- 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) {
- if (fun0.FunctionSymbol.Equals(Prop.True)) {
- return e1;
- } else if (fun0.FunctionSymbol.Equals(Prop.False)) {
- return e0;
- }
- }
-
- IFunApp fun1 = e1 as IFunApp;
- if (fun1 != null) {
- if (fun1.FunctionSymbol.Equals(Prop.True)) {
- return e0;
- } else if (fun1.FunctionSymbol.Equals(Prop.False)) {
- return e1;
- }
- }
-
- return factory.And(e0, e1);
- }
-
- 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) {
- 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) {
- if (fun0.FunctionSymbol.Equals(Prop.False)) {
- return e1;
- } else if (fun0.FunctionSymbol.Equals(Prop.True)) {
- return e0;
- }
- }
-
- IFunApp fun1 = e1 as IFunApp;
- if (fun1 != null) {
- if (fun1.FunctionSymbol.Equals(Prop.False)) {
- return e0;
- } else if (fun1.FunctionSymbol.Equals(Prop.True)) {
- return e1;
- }
- }
-
- return factory.Or(e0, e1);
- }
-
- 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;
- }
-
-
-
- /// <summary>
- /// Break top-level conjuncts into a list of sub-expressions.
- /// </summary>
- /// <param name="e">The expression to examine.</param>
- /// <returns>A list of conjuncts.</returns>
- 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);
- }
-
- /// <summary>
- /// Break top-level disjuncts into a list of sub-expressions.
- /// </summary>
- /// <param name="e">The expression to examine.</param>
- /// <returns>A list of conjuncts.</returns>
- 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) {
- 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) {
- // If it is a sym, go down into sub-expressions.
- if (f.FunctionSymbol.Equals(sym)) {
- foreach (IExpr/*!*/ arg in f.Arguments) {
- Contract.Assert(arg != null);
- result.AddRange(BreakJuncts(arg, sym));
- }
- }
- // Otherwise, stop.
- else {
- result.Add(e);
- }
- } else {
- result.Add(e);
- }
-
- return result;
- }
- }
-
- /// <summary>
- /// A callback to produce a function body given the bound variable.
- /// </summary>
- /// <param name="var">The bound variable to use.</param>
- /// <returns>The function body.</returns>
- public delegate IExpr/*!*/ FunctionBody(IVariable/*!*/ var);
-
- /// <summary>
- /// An interface for constructing propositional expressions.
- ///
- /// 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/*!*/ 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/*!*/ 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>
- /// An interface for constructing value expressions.
- ///
- /// 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);*/;
- }
- [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.
- ///
- /// 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);*/ }
- }
- [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.
- ///
- /// 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));*/;
- }
- [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>
- /// An interface for constructing linear integer expressions.
- ///
- /// 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);*/;
- /// <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);
-
- 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.
- /// The types are assumed to be arranged in a rooted tree.
- ///
- /// 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; }
-
- /// <summary>
- /// Returns true iff "t" denotes a type constant.
- /// </summary>
- [Pure]
- 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);
-
- /// <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);
-
- /// <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);
-
- 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
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+ //using Microsoft.SpecSharp.Collections;
+ using Microsoft.Basetypes;
+
+ /// <summary>
+ /// A basic class for function symbols.
+ /// </summary>
+ public class FunctionSymbol : IFunctionSymbol
+ {
+ private readonly string/*!*/ display;
+ private readonly AIType/*!*/ typ;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(display != null);
+ Contract.Invariant(typ != null);
+ }
+
+
+ public FunctionSymbol(AIType/*!*/ typ)
+ : this("FunctionSymbol", typ) {
+ Contract.Requires(typ != null);
+ }
+
+ 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 { Contract.Ensures(Contract.Result<AIType>() != null); return typ; } }
+
+ [NoDefaultContract]
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return display;
+ }
+
+ }
+
+ /// <summary>
+ /// A class for integer constants.
+ /// </summary>
+ public class IntSymbol : FunctionSymbol
+ {
+ public readonly BigNum Value;
+
+ /// <summary>
+ /// The intention is that this constructor be called only from the Int.Const method.
+ /// </summary>
+ internal IntSymbol(BigNum x)
+ : base(cce.NonNull(x.ToString()), Int.Type) {
+ this.Value = x;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ IntSymbol isym = other as IntSymbol;
+ return isym != null && isym.Value.Equals(this.Value);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return Value.GetHashCode();
+ }
+ }
+
+ /// <summary>
+ /// A class for bitvector constants.
+ /// </summary>
+ public class BvSymbol : FunctionSymbol
+ {
+ public readonly BigNum Value;
+ public readonly int Bits;
+
+ /// <summary>
+ /// The intention is that this constructor be called only from the Int.Const method.
+ /// </summary>
+ internal BvSymbol(BigNum x, int y)
+ : base(x + "bv" + y, Bv.Type) {
+ this.Value = x;
+ this.Bits = y;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ BvSymbol isym = other as BvSymbol;
+ return isym != null && isym.Value == this.Value && isym.Bits == this.Bits;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ unchecked {
+ return Value.GetHashCode() ^ Bits;
+ }
+ }
+ }
+
+ public class DoubleSymbol : FunctionSymbol
+ {
+ public readonly double Value;
+
+ /// <summary>
+ /// The intention is that this constructor be called only from the Double.Const method.
+ /// </summary>
+ internal DoubleSymbol(double x)
+ : base(cce.NonNull(x.ToString()), Double.Type) {
+ this.Value = x;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ DoubleSymbol dsym = other as DoubleSymbol;
+ return dsym != null && dsym.Value == this.Value;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return Value.GetHashCode();
+ }
+ }
+
+ /// <summary>
+ /// Function symbol based on a string. Uses the string equality for determining equality
+ /// of symbol.
+ /// </summary>
+ public class NamedSymbol : FunctionSymbol
+ {
+ 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) {
+ Contract.Requires(typ != null);
+ Contract.Requires(symbol != null);
+ }
+
+ [NoDefaultContract]
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ NamedSymbol nsym = other as NamedSymbol;
+ return nsym != null && this.Value.Equals(nsym.Value);
+ }
+
+ [NoDefaultContract]
+ [Pure]
+ public override int GetHashCode() {
+ return Value.GetHashCode();
+ }
+ }
+
+ //
+ // In the following, the classes like Value and Prop serve two
+ // roles. The primary role is to be the base types for AIType.
+ // The only objects of these classes are the representative
+ // objects that denote an AIType, which are given by the
+ // "Type" property. Subtypes in the AIType language are
+ // encoded by subclassing. This yields some "higher-orderness"
+ // for checking subtyping in the AIType language, by using
+ // the Spec#/C# subclassing checks.
+ //
+ // The other role is simply as a module for collecting like function
+ // symbols.
+ //
+
+ //-------------------------- Terms ----------------------------------
+
+ /// <summary>
+ /// A class with the equality symbol and the ValueType.Type.
+ /// </summary>
+ public class Value : AIType
+ {
+ 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];
+ if (result != null) {
+ return result;
+ }
+ }
+ AIType[] signature = new AIType[1 + inParameterCount];
+ for (int i = 0; i < signature.Length; i++) {
+ signature[i] = valtype;
+ }
+ result = new FunctionType(signature);
+ if (inParameterCount < funtypeCache.Length) {
+ funtypeCache[inParameterCount] = result;
+ }
+ return result;
+ }
+
+ [Once]
+ private static AIType/*!*/ binreltype;
+
+ private static AIType/*!*/ BinrelType {
+ get {
+ Contract.Ensures(Contract.Result<AIType>() != null);
+ if (binreltype == null) {
+ binreltype = new FunctionType(Type, Type, Prop.Type);
+ }
+ return binreltype;
+ }
+ }
+
+ [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 {
+ 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 {
+ Contract.Ensures(Contract.Result<FunctionSymbol>() != null);
+ if (_subtype == null) {
+ _subtype = new FunctionSymbol("<:", BinrelType);
+ }
+ return _subtype;
+ }
+ }
+
+ [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 {
+ Contract.Ensures(Contract.Result<FunctionSymbol>() != null);
+ if (_typeof == null) {
+ _typeof = new FunctionSymbol("typeof", TypeofType);
+ }
+ return _typeof;
+ }
+ }
+
+ /// <summary>
+ /// Value should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ protected Value() { }
+
+ }
+
+ public class Int : Value
+ {
+ private static readonly AIType/*!*/ inttype = new Int();
+ public static new 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 { 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);
+ }
+
+ /// <summary>
+ /// Int should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Int() { }
+ }
+
+ public class Double : Value
+ {
+ private static readonly AIType/*!*/ doubletype = new Double();
+ public static new AIType/*!*/ Type { get { Contract.Ensures(Contract.Result<AIType>() != null); return doubletype; } }
+
+ 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);
+ }
+
+ /// <summary>
+ /// Double should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Double() { }
+ }
+
+ public class Bv : Value
+ {
+ private static readonly AIType/*!*/ bvtype = new Bv();
+ public static new 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 { 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);
+ }
+
+ /// <summary>
+ /// Int should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private Bv() { }
+ }
+
+ public class Ref : Value
+ {
+ private static readonly AIType/*!*/ reftype = new Ref();
+ public static new AIType/*!*/ Type { get { Contract.Ensures(Contract.Result<AIType>() != null); return reftype; } }
+
+ private static readonly FunctionSymbol/*!*/ _null = new FunctionSymbol("null", Type);
+
+ 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
+ /// subclasses.
+ /// </summary>
+ private Ref() { }
+ }
+
+ public class HeapStructure : Value
+ {
+ private static readonly AIType/*!*/ reftype = new HeapStructure();
+ public static new AIType/*!*/ Type { get { Contract.Ensures(Contract.Result<AIType>() != null); return reftype; } }
+
+
+
+ /// <summary>
+ /// HeapStructure should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private HeapStructure() { }
+ }
+
+ public class FieldName : Value
+ {
+ private static readonly AIType/*!*/ fieldnametype = new FieldName();
+ public static new 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 { 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) {
+ Contract.Requires(f != null);
+ return f.Equals(Allocated);
+ }
+
+ /// <summary>
+ /// FieldName should not be instantiated from the outside, except perhaps in
+ /// subclasses.
+ /// </summary>
+ private FieldName() { }
+ }
+
+ public class Heap : Value
+ {
+ private static readonly AIType/*!*/ heaptype = new Heap();
+ public static new 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",
+ // Heap x FieldName -> Prop
+ new FunctionType(Type, FieldName.Type, Prop.Type)
+ );
+ public static FunctionSymbol/*!*/ Select1 { get { Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _select1; } }
+
+ 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 { 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",
+ // Heap x FieldName x Value -> Heap
+ new FunctionType(Type, FieldName.Type, Value.Type, Type)
+ );
+ public static FunctionSymbol/*!*/ Update1 { get { Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _update1; } }
+
+ 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 { Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _update2; } }
+
+ private static readonly FunctionSymbol/*!*/ _unsupportedHeapOp =
+ new FunctionSymbol("UnsupportedHeapOp",
+ // Heap x FieldName -> Prop
+ new FunctionType(Type, FieldName.Type, Prop.Type)
+ );
+ 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
+ /// subclasses.
+ /// </summary>
+ private Heap() { }
+ }
+
+ // public class List : Value
+ // {
+ // private static IDictionary/*<AIType!,AIType!>*/! lists = new Hashtable();
+ // public static AIType! Type(AIType! typeParameter)
+ // {
+ // if (lists.Contains(typeParameter))
+ // return lists[typeParameter];
+ // else
+ // {
+ // AIType! result = new List(typeParameter);
+ // lists[typeParameter] = result;
+ // return result;
+ // }
+ // }
+ //
+ // private static IDictionary/*<AIType!,AIType!>*/! nils = new Hashtable();
+ // public static FunctionSymbol! Nil(AIType! typeParameter)
+ // {
+ // if (nils.Contains(typeParameter))
+ // return nils[typeParameter];
+ // else
+ // {
+ // FunctionSymbol! result = new FunctionSymbol(Type(typeParameter));
+ // nils[typeParameter] = result;
+ // return result;
+ // }
+ // }
+ //
+ // private static IDictionary/*<AIType!,AIType!>*/! cons = new Hashtable();
+ // public static FunctionSymbol! Cons(AIType! typeParameter)
+ // {
+ // if (cons.Contains(typeParameter))
+ // return cons[typeParameter];
+ // else
+ // {
+ // FunctionSymbol! result = new FunctionSymbol(
+ // new FunctionType(typeParameter, Type(typeParameter), Type(typeParameter))
+ // );
+ // cons[typeParameter] = result;
+ // return result;
+ // }
+ // }
+ //
+ // private AIType! typeParameter;
+ // public AIType(TypeParameter/*!*/ ){
+ //Contract.Requires( != null);
+ //return typeParameter; } }
+ //
+ // /// <summary>
+ // /// List should not be instantiated from the outside.
+ // /// </summary>
+ // private List(AIType! typeParameter)
+ // {
+ // this.typeParameter = typeParameter;
+ // }
+ // }
+ //
+ // public class Pair : Value
+ // {
+ // private static IDictionary! pairs = new Hashtable();
+ // public static AIType! Type(AIType! type1, AIType! type2)
+ // {
+ // Microsoft.AbstractInterpretationFramework.Collections.Pair typpair
+ // = new Microsoft.AbstractInterpretationFramework.Collections.Pair(type1, type2);
+ //
+ // if (pairs.Contains(typpair))
+ // return pairs[typpair];
+ // else
+ // {
+ // AIType! result = new Pair(type1, type2);
+ // pairs[typpair] = result;
+ // return result;
+ // }
+ // }
+ //
+ // private static IDictionary! constructs = new Hashtable();
+ // public static FunctionSymbol! Pair(AIType! type1, AIType! type2)
+ // {
+ // Microsoft.AbstractInterpretationFramework.Collections.Pair typpair
+ // = new Microsoft.AbstractInterpretationFramework.Collections.Pair(type1, type2);
+ //
+ // if (constructs.Contains(typpair))
+ // return constructs[typpair];
+ // else
+ // {
+ // FunctionSymbol! result = new FunctionSymbol(
+ // new FunctionType(type1, type2, Type(type1, type2))
+ // );
+ // constructs[typpair] = result;
+ // return result;
+ // }
+ // }
+ //
+ // protected AIType! type1;
+ // protected AIType! 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.
+ // /// </summary>
+ // protected Pair(AIType! type1, AIType! type2)
+ // {
+ // this.type1 = type1;
+ // this.type2 = type2;
+ // }
+ // }
+
+ //-------------------------- Propositions ---------------------------
+
+
+ /// <summary>
+ /// A class with global propositional symbols and the Prop.Type.
+ /// </summary>
+ public sealed class Prop : AIType
+ {
+ private static readonly AIType/*!*/ proptype = new Prop();
+
+ 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 =
+ 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);
+
+
+ [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>
+ /// Prop should not be instantiated from the outside.
+ /// </summary>
+ private Prop() { }
+
+
+
+ //
+ // Utility Methods
+ //
+
+ 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) {
+ if (fun0.FunctionSymbol.Equals(Prop.True)) {
+ return e1;
+ } else if (fun0.FunctionSymbol.Equals(Prop.False)) {
+ return e0;
+ }
+ }
+
+ IFunApp fun1 = e1 as IFunApp;
+ if (fun1 != null) {
+ if (fun1.FunctionSymbol.Equals(Prop.True)) {
+ return e0;
+ } else if (fun1.FunctionSymbol.Equals(Prop.False)) {
+ return e1;
+ }
+ }
+
+ return factory.And(e0, e1);
+ }
+
+ 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) {
+ 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) {
+ if (fun0.FunctionSymbol.Equals(Prop.False)) {
+ return e1;
+ } else if (fun0.FunctionSymbol.Equals(Prop.True)) {
+ return e0;
+ }
+ }
+
+ IFunApp fun1 = e1 as IFunApp;
+ if (fun1 != null) {
+ if (fun1.FunctionSymbol.Equals(Prop.False)) {
+ return e0;
+ } else if (fun1.FunctionSymbol.Equals(Prop.True)) {
+ return e1;
+ }
+ }
+
+ return factory.Or(e0, e1);
+ }
+
+ 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;
+ }
+
+
+
+ /// <summary>
+ /// Break top-level conjuncts into a list of sub-expressions.
+ /// </summary>
+ /// <param name="e">The expression to examine.</param>
+ /// <returns>A list of conjuncts.</returns>
+ 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);
+ }
+
+ /// <summary>
+ /// Break top-level disjuncts into a list of sub-expressions.
+ /// </summary>
+ /// <param name="e">The expression to examine.</param>
+ /// <returns>A list of conjuncts.</returns>
+ 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) {
+ 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) {
+ // If it is a sym, go down into sub-expressions.
+ if (f.FunctionSymbol.Equals(sym)) {
+ foreach (IExpr/*!*/ arg in f.Arguments) {
+ Contract.Assert(arg != null);
+ result.AddRange(BreakJuncts(arg, sym));
+ }
+ }
+ // Otherwise, stop.
+ else {
+ result.Add(e);
+ }
+ } else {
+ result.Add(e);
+ }
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// A callback to produce a function body given the bound variable.
+ /// </summary>
+ /// <param name="var">The bound variable to use.</param>
+ /// <returns>The function body.</returns>
+ public delegate IExpr/*!*/ FunctionBody(IVariable/*!*/ var);
+
+ /// <summary>
+ /// An interface for constructing propositional expressions.
+ ///
+ /// 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/*!*/ 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/*!*/ 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>
+ /// An interface for constructing value expressions.
+ ///
+ /// 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);*/;
+ }
+ [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.
+ ///
+ /// 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);*/ }
+ }
+ [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.
+ ///
+ /// 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));*/;
+ }
+ [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>
+ /// An interface for constructing linear integer expressions.
+ ///
+ /// 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);*/;
+ /// <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);
+
+ 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.
+ /// The types are assumed to be arranged in a rooted tree.
+ ///
+ /// 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; }
+
+ /// <summary>
+ /// Returns true iff "t" denotes a type constant.
+ /// </summary>
+ [Pure]
+ 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);
+
+ /// <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);
+
+ /// <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);
+
+ 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
+ }
+}
diff --git a/Source/AIFramework/Expr.cs b/Source/AIFramework/Expr.cs
index 58473592..ae2bd4b7 100644
--- a/Source/AIFramework/Expr.cs
+++ b/Source/AIFramework/Expr.cs
@@ -1,640 +1,640 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-// This file specifies the expression language used by the Abstract
-// Interpretation Framework.
-//
-// expressions e ::= x variables
-// | f(e1,...,en) uninterpreted functions
-// | \x:t.e lambda expressions
-//
-// types t ::= b user-defined/built-in base types
-// | t1 * ... * tn -> t' function type
-
-namespace Microsoft.AbstractInterpretationFramework
-{
- using System.Collections;
- using System;
- using System.Diagnostics.Contracts;
-
- //----------------------------- Expressions -----------------------------
-
- /// <summary>
- /// An interface for expressions. This expression language is specified
- /// by interfaces to allow the client to be able to use their existing
- /// AST nodes as AIF expressions.
- ///
- /// This only serves as a place for operations on expressions. Clients
- /// should implement directly IVariable, IFunApp, ...
- /// </summary>
- [ContractClass(typeof(IExprContracts))]
- public interface IExpr
- {
- /// <summary>
- /// Execute a visit over the expression.
- /// </summary>
- /// <param name="visitor">The expression visitor.</param>
- /// <returns>The result of the visit.</returns>
- [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
- }
- [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
- {
- [Pure][Rep] get;
-
- }
-
- /// <summary>
- /// Provides a method to create a new uninterpreted function
- /// with the same function symbol but with the arguments with
- /// args.
- /// </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 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; }
-
- 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();
- }
- }
-
- 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
- /// as unknown values. They are used when there is no other IExpr corresponding to the
- /// expression to be modeled.
- /// </summary>
- public interface IUnknown : IExpr {}
-
- /// <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 virtual object VisitVariable(IVariable/*!*/ var){
-Contract.Requires(var != null);
- return Default(var);
- }
-
- public virtual object VisitFunApp(IFunApp/*!*/ funapp){
-Contract.Requires(funapp != null);
- return Default(funapp);
- }
-
- 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.
- /// </summary>
- public sealed class ExprUtil
- {
- /// <summary>
- /// Yield an expression that is 'inexpr' with 'var' replaced by 'subst'.
- /// </summary>
- /// <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){
-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)
- {
- result = inexpr.Equals(var) ? subst : inexpr;
- }
- else if (inexpr is IFunApp)
- {
- IFunApp/*!*/ funapp = (IFunApp/*!*/)cce.NonNull(inexpr);
- IList newargs = null;
-
- 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/*!*/)cce.NonNull(inexpr);
-
- if (fun.Param.Equals(var))
- result = fun;
- else
- result = fun.CloneWithBody(Substitute(subst, var, fun.Body));
- }
- else if (inexpr is IUnknown)
- {
- result = inexpr;
- }
- else
- {
- {Contract.Assert(false);throw new cce.UnreachableException();}
- }
-
- return result;
- }
-
-
- //
- // Poor man's pattern matching.
- //
- // The methods below implement pattern matching for AI expressions.
- //
- // Example Usage:
- // Match(e, Prop.Imp,
- // (Matcher)delegate (IExpr e) { return Match(e, Prop.And, out x, out y); }
- // 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);
-
- private static IFunApp/*?*/ MatchFunctionSymbol(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f){
-Contract.Requires(f != null);
-Contract.Requires(expr != null);
- IFunApp app = expr as IFunApp;
- if (app != null)
- {
- if (app.FunctionSymbol.Equals(f))
- return app;
- else
- return null;
- }
- else
- return null;
- }
-
- 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){
-Contract.Assert(s != null);
- if (!s(cce.NonNull((IExpr)app.Arguments[i]))) { return false; }
- i++;
- }
- return true;
- }
- else { return false; }
- }
-
- // Unary Binding
- 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/*!*/)cce.NonNull(app.Arguments[0]);
-
- int i = 1; // Note ***1***
- foreach(Matcher/*!*/ s in subs){
-Contract.Assert(s != null);
- if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; }
- i++;
- }
- return true;
- }
- else { return false; }
- }
-
- // Binary Binding
- 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(cce.NonNull((IExpr/*!*/)app.Arguments[0]))) { return false; }
-
- arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]);
-
- int i = 2; // Note ***2***
- foreach(Matcher/*!*/ s in subs){
-Contract.Assert(s != null);
- if (!s(cce.NonNull((IExpr)app.Arguments[i]))) { return false; }
- i++;
- }
- return true;
- }
- else { return false; }
- }
-
- 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/*!*/)cce.NonNull(app.Arguments[0]);
- arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]);
-
- int i = 2; // Note ***2***
- foreach(Matcher/*!*/ s in subs){
-Contract.Assert(s != null);
- if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; }
- i++;
- }
- return true;
- }
- else { return false; }
- }
-
- // Ternary Binding
- 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;
-
- IFunApp app = MatchFunctionSymbol(expr,f);
- if (app != null)
- {
- 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){
-Contract.Assert(s != null);
- if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; }
- i++;
- }
- return true;
- }
- else { return false; }
- }
-
- /// <summary>
- /// Not intended to be instantiated.
- /// </summary>
- private ExprUtil() { }
- }
-
- //------------------------------ Symbols --------------------------------
-
- /// <summary>
- /// An interface for function symbols. Constants are represented by
- /// 0-ary function symbols.
- ///
- /// 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]
- 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
- /// matching.
- /// </summary>
- public interface IMatchable
- {
- }
-
- //-------------------------------- Types --------------------------------
-
- /// <summary>
- /// Types.
- /// </summary>
- public interface AIType
- {
- }
-
- /// <summary>
- /// Function type constructor.
- /// </summary>
- public sealed class FunctionType : AIType
- {
- /*[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){
-Contract.Requires(types != null);
- Contract.Requires(types.Length >= 2);
- AIType type = types[types.Length-1];
- Contract.Assume(type != null);
- this.retType = type;
- ArrayList argTypes = new ArrayList();
- for (int i = 0; i < types.Length-1; i++)
- {
- type = types[i];
- Contract.Assume(type != null);
- argTypes.Add(types);
- }
- this.argTypes = ArrayList.ReadOnly(argTypes);
- }
-
- public IList/*<AIType!>*//*!*/ Arguments
- {
- [Pure][Rep]
- get
- {
- Contract.Ensures(Contract.Result<IList>() != null);
- Contract.Ensures(Contract.Result<IList>().IsReadOnly);
- return argTypes;
- }
- }
-
- public int Arity
- {
- get { return argTypes.Count; }
- }
-
- public AIType/*!*/ ReturnType
- {
- 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.
- public override bool Equals(object o)
- {
- if (o != null && o is FunctionType)
- {
- FunctionType other = (FunctionType) o;
-
- if (Arity == other.Arity
- && ReturnType.Equals(other.ReturnType))
- {
- for (int i = 0; i < Arity; i++)
- {
- if (!argTypes[i].Equals(other.argTypes[i]))
- return false;
- }
- return true;
- }
- else
- return false;
- }
- else
- return false;
- }
- */
- }
-
- //------------------------------ Queries -------------------------------
-
- public enum Answer { Yes, No, Maybe };
-
- /// <summary>
- /// An interface that specifies a queryable object that can answer
- /// whether a predicate holds.
- /// </summary>
- ///
- [ContractClass(typeof(IQueryableContracts))]
- public interface IQueryable
- {
- /// <summary>
- /// Answers the query whether the given predicate holds.
- /// </summary>
- /// <param name="pred">The given predicate.</param>
- /// <returns>Yes, No, or Maybe.</returns>
- 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);
- }
- [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
- {
- public static Answer Negate(Answer ans)
- {
- switch (ans)
- {
- case Answer.Yes:
- return Answer.No;
- case Answer.No:
- return Answer.Yes;
- default:
- return Answer.Maybe;
- }
- }
- }
-
- //----------------------------- Exceptions -----------------------------
-
- public class CheckedException : System.Exception {
- }
- public class TypeError : CheckedException
- {
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+// This file specifies the expression language used by the Abstract
+// Interpretation Framework.
+//
+// expressions e ::= x variables
+// | f(e1,...,en) uninterpreted functions
+// | \x:t.e lambda expressions
+//
+// types t ::= b user-defined/built-in base types
+// | t1 * ... * tn -> t' function type
+
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Collections;
+ using System;
+ using System.Diagnostics.Contracts;
+
+ //----------------------------- Expressions -----------------------------
+
+ /// <summary>
+ /// An interface for expressions. This expression language is specified
+ /// by interfaces to allow the client to be able to use their existing
+ /// AST nodes as AIF expressions.
+ ///
+ /// This only serves as a place for operations on expressions. Clients
+ /// should implement directly IVariable, IFunApp, ...
+ /// </summary>
+ [ContractClass(typeof(IExprContracts))]
+ public interface IExpr
+ {
+ /// <summary>
+ /// Execute a visit over the expression.
+ /// </summary>
+ /// <param name="visitor">The expression visitor.</param>
+ /// <returns>The result of the visit.</returns>
+ [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
+ }
+ [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
+ {
+ [Pure][Rep] get;
+
+ }
+
+ /// <summary>
+ /// Provides a method to create a new uninterpreted function
+ /// with the same function symbol but with the arguments with
+ /// args.
+ /// </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 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; }
+
+ 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();
+ }
+ }
+
+ 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
+ /// as unknown values. They are used when there is no other IExpr corresponding to the
+ /// expression to be modeled.
+ /// </summary>
+ public interface IUnknown : IExpr {}
+
+ /// <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 virtual object VisitVariable(IVariable/*!*/ var){
+Contract.Requires(var != null);
+ return Default(var);
+ }
+
+ public virtual object VisitFunApp(IFunApp/*!*/ funapp){
+Contract.Requires(funapp != null);
+ return Default(funapp);
+ }
+
+ 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.
+ /// </summary>
+ public sealed class ExprUtil
+ {
+ /// <summary>
+ /// Yield an expression that is 'inexpr' with 'var' replaced by 'subst'.
+ /// </summary>
+ /// <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){
+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)
+ {
+ result = inexpr.Equals(var) ? subst : inexpr;
+ }
+ else if (inexpr is IFunApp)
+ {
+ IFunApp/*!*/ funapp = (IFunApp/*!*/)cce.NonNull(inexpr);
+ IList newargs = null;
+
+ 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/*!*/)cce.NonNull(inexpr);
+
+ if (fun.Param.Equals(var))
+ result = fun;
+ else
+ result = fun.CloneWithBody(Substitute(subst, var, fun.Body));
+ }
+ else if (inexpr is IUnknown)
+ {
+ result = inexpr;
+ }
+ else
+ {
+ {Contract.Assert(false);throw new cce.UnreachableException();}
+ }
+
+ return result;
+ }
+
+
+ //
+ // Poor man's pattern matching.
+ //
+ // The methods below implement pattern matching for AI expressions.
+ //
+ // Example Usage:
+ // Match(e, Prop.Imp,
+ // (Matcher)delegate (IExpr e) { return Match(e, Prop.And, out x, out y); }
+ // 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);
+
+ private static IFunApp/*?*/ MatchFunctionSymbol(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f){
+Contract.Requires(f != null);
+Contract.Requires(expr != null);
+ IFunApp app = expr as IFunApp;
+ if (app != null)
+ {
+ if (app.FunctionSymbol.Equals(f))
+ return app;
+ else
+ return null;
+ }
+ else
+ return null;
+ }
+
+ 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){
+Contract.Assert(s != null);
+ if (!s(cce.NonNull((IExpr)app.Arguments[i]))) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ // Unary Binding
+ 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/*!*/)cce.NonNull(app.Arguments[0]);
+
+ int i = 1; // Note ***1***
+ foreach(Matcher/*!*/ s in subs){
+Contract.Assert(s != null);
+ if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ // Binary Binding
+ 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(cce.NonNull((IExpr/*!*/)app.Arguments[0]))) { return false; }
+
+ arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]);
+
+ int i = 2; // Note ***2***
+ foreach(Matcher/*!*/ s in subs){
+Contract.Assert(s != null);
+ if (!s(cce.NonNull((IExpr)app.Arguments[i]))) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ 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/*!*/)cce.NonNull(app.Arguments[0]);
+ arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]);
+
+ int i = 2; // Note ***2***
+ foreach(Matcher/*!*/ s in subs){
+Contract.Assert(s != null);
+ if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ // Ternary Binding
+ 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;
+
+ IFunApp app = MatchFunctionSymbol(expr,f);
+ if (app != null)
+ {
+ 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){
+Contract.Assert(s != null);
+ if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; }
+ i++;
+ }
+ return true;
+ }
+ else { return false; }
+ }
+
+ /// <summary>
+ /// Not intended to be instantiated.
+ /// </summary>
+ private ExprUtil() { }
+ }
+
+ //------------------------------ Symbols --------------------------------
+
+ /// <summary>
+ /// An interface for function symbols. Constants are represented by
+ /// 0-ary function symbols.
+ ///
+ /// 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]
+ 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
+ /// matching.
+ /// </summary>
+ public interface IMatchable
+ {
+ }
+
+ //-------------------------------- Types --------------------------------
+
+ /// <summary>
+ /// Types.
+ /// </summary>
+ public interface AIType
+ {
+ }
+
+ /// <summary>
+ /// Function type constructor.
+ /// </summary>
+ public sealed class FunctionType : AIType
+ {
+ /*[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){
+Contract.Requires(types != null);
+ Contract.Requires(types.Length >= 2);
+ AIType type = types[types.Length-1];
+ Contract.Assume(type != null);
+ this.retType = type;
+ ArrayList argTypes = new ArrayList();
+ for (int i = 0; i < types.Length-1; i++)
+ {
+ type = types[i];
+ Contract.Assume(type != null);
+ argTypes.Add(types);
+ }
+ this.argTypes = ArrayList.ReadOnly(argTypes);
+ }
+
+ public IList/*<AIType!>*//*!*/ Arguments
+ {
+ [Pure][Rep]
+ get
+ {
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.Ensures(Contract.Result<IList>().IsReadOnly);
+ return argTypes;
+ }
+ }
+
+ public int Arity
+ {
+ get { return argTypes.Count; }
+ }
+
+ public AIType/*!*/ ReturnType
+ {
+ 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.
+ public override bool Equals(object o)
+ {
+ if (o != null && o is FunctionType)
+ {
+ FunctionType other = (FunctionType) o;
+
+ if (Arity == other.Arity
+ && ReturnType.Equals(other.ReturnType))
+ {
+ for (int i = 0; i < Arity; i++)
+ {
+ if (!argTypes[i].Equals(other.argTypes[i]))
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+ }
+ */
+ }
+
+ //------------------------------ Queries -------------------------------
+
+ public enum Answer { Yes, No, Maybe };
+
+ /// <summary>
+ /// An interface that specifies a queryable object that can answer
+ /// whether a predicate holds.
+ /// </summary>
+ ///
+ [ContractClass(typeof(IQueryableContracts))]
+ public interface IQueryable
+ {
+ /// <summary>
+ /// Answers the query whether the given predicate holds.
+ /// </summary>
+ /// <param name="pred">The given predicate.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ 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);
+ }
+ [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
+ {
+ public static Answer Negate(Answer ans)
+ {
+ switch (ans)
+ {
+ case Answer.Yes:
+ return Answer.No;
+ case Answer.No:
+ return Answer.Yes;
+ default:
+ return Answer.Maybe;
+ }
+ }
+ }
+
+ //----------------------------- Exceptions -----------------------------
+
+ public class CheckedException : System.Exception {
+ }
+ public class TypeError : CheckedException
+ {
+ }
+}
diff --git a/Source/AIFramework/Functional.cs b/Source/AIFramework/Functional.cs
index 3b8237bf..51d8562a 100644
--- a/Source/AIFramework/Functional.cs
+++ b/Source/AIFramework/Functional.cs
@@ -1,430 +1,430 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.AbstractInterpretationFramework.Collections {
- using System.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);
-
- /// <summary>
- /// Set the value of the key (that is already in the map)
- /// </summary>
- 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);
-
- /// <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>
- /// <filterpriority>2</filterpriority>
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- new System.Collections.IDictionaryEnumerator GetEnumerator();
-
- /// <summary>Gets an <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
- /// <returns>An <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
- /// <filterpriority>2</filterpriority>
- System.Collections.ICollection Keys {
- get;
- }
-
- /// <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);
-
- /// <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;*/
- }
- }
- [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.Requires(key != 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
- }
-
-
-
- /// <summary>
- /// An implementation of the
- /// <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />
- /// interface with a <see cref="T:System.Collections.Hashtable" /> as the backing store.
- /// </summary>
- class FunctionalHashtable : IFunctionalMap {
- private readonly Hashtable/*!*/ h;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(h != null);
- }
-
-
- /// <summary>
- /// Cannot directly construct an instance of a FunctionalHashtbl.
- /// </summary>
- private FunctionalHashtable() {
- this.h = new Hashtable();
- // base();
- }
-
- /// <summary>
- /// Cannot directly construct an instance of a FunctionalHashtbl.
- /// </summary>
- private FunctionalHashtable(Hashtable/*!*/ h) {
- Contract.Requires(h != null);
- this.h = h;
- // base();
- }
-
- 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) {
- //Contract.Requires(key != null);
- Contract.Ensures(Contract.Result<IFunctionalMap>() != null);
- Hashtable r = h.Clone() as Hashtable;
- Contract.Assume(r != null);
- r.Add(key, value);
- return new FunctionalHashtable(r);
- }
-
- public IFunctionalMap/*!*/ Set(object/*!*/ key, object value) {
- //Contract.Requires(key != null);
- Contract.Ensures(Contract.Result<IFunctionalMap>() != null);
- Hashtable r = h.Clone() as Hashtable;
-
- 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) {
- //Contract.Requires(key != null);
- return h.Contains(key);
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator/*!*/ IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator>() != null);
-
- return h.GetEnumerator();
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IDictionaryEnumerator IFunctionalMap.GetEnumerator() {
- return h.GetEnumerator();
- }
-
- public ICollection Keys {
- get {
- return h.Keys;
- }
- }
-
- public IFunctionalMap/*!*/ Remove(object/*!*/ key) {
- //Contract.Requires(key != null);
- Contract.Ensures(Contract.Result<IFunctionalMap>() != null);
- Hashtable r = h.Clone() as Hashtable;
- Contract.Assume(r != null);
- r.Remove(key);
- return new FunctionalHashtable(r);
- }
-
- public ICollection Values {
- get {
- return h.Values;
- }
- }
-
-
- public object this[object/*!*/ key] {
- get {
- //Contract.Requires(key != null);
- return h[key];
- }
- }
-
- public int Count {
- [Pure]
- get {
- return h.Count;
- }
- }
-
- public bool IsSynchronized {
- [Pure]
- get {
- return h.IsSynchronized;
- }
- }
-
- public object/*!*/ SyncRoot {
- [Pure]
- get {
- Contract.Ensures(Contract.Result<object>() != null);
- return h.SyncRoot;
- }
- }
-
- public void CopyTo(System.Array/*!*/ a, int index) {
- //Contract.Requires(a != null);
- h.CopyTo(a, index);
- }
- }
-
- public struct Pair/*<T1,T2>*/
- {
- private object first;
- private object second;
-
- public object First {
- get {
- return first;
- }
- }
- public object Second {
- get {
- return second;
- }
- }
-
- public Pair(object first, object second) {
- this.first = first;
- this.second = second;
- }
-
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is Pair))
- return false;
-
- Pair other = (Pair)obj;
- return object.Equals(this.first, other.first) && object.Equals(this.second, other.second);
- }
-
- public override int GetHashCode() {
- int h = this.first == null ? 0 : this.first.GetHashCode();
- h ^= this.second == null ? 0 : this.second.GetHashCode();
- return h;
- }
- }
-}
-
-
-namespace Microsoft.AbstractInterpretationFramework.Collections.Generic {
- using System.Collections.Generic;
-
- public struct Pair<T1, T2> {
- private T1 first;
- private T2 second;
-
- public T1 First {
- get {
- return first;
- }
- }
- public T2 Second {
- get {
- return second;
- }
- }
-
- public Pair(T1 first, T2 second) {
- this.first = first;
- this.second = second;
- }
-
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is Pair<T1, T2>))
- return false;
-
- Pair<T1, T2> other = (Pair<T1, T2>)obj;
- return object.Equals(this.first, other.first) && object.Equals(this.second, other.second);
- }
-
- public override int GetHashCode() {
- int h = this.first == null ? 0 : this.first.GetHashCode();
- h ^= this.second == null ? 0 : this.second.GetHashCode();
- return h;
- }
-
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return string.Format("({0},{1})", first, second);
- }
- }
-
- public struct Triple<T1, T2, T3> {
- private T1 first;
- private T2 second;
- private T3 third;
-
- public T1 First {
- get {
- return first;
- }
- }
- public T2 Second {
- get {
- return second;
- }
- }
- public T3 Third {
- get {
- return third;
- }
- }
-
- public Triple(T1 first, T2 second, T3 third) {
- this.first = first;
- this.second = second;
- this.third = third;
- }
-
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is Triple<T1, T2, T3>))
- return false;
-
- Triple<T1, T2, T3> other = (Triple<T1, T2, T3>)obj;
- return object.Equals(this.first, other.first) && object.Equals(this.second, other.second) && object.Equals(this.third, other.third);
- }
-
- public override int GetHashCode() {
- int h = this.first == null ? 0 : this.first.GetHashCode();
- h ^= this.second == null ? 0 : this.second.GetHashCode();
- h ^= this.third == null ? 0 : this.third.GetHashCode();
- return h;
- }
-
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return string.Format("({0},{1},{2})", first, second, third);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.AbstractInterpretationFramework.Collections {
+ using System.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);
+
+ /// <summary>
+ /// Set the value of the key (that is already in the map)
+ /// </summary>
+ 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);
+
+ /// <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>
+ /// <filterpriority>2</filterpriority>
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ new System.Collections.IDictionaryEnumerator GetEnumerator();
+
+ /// <summary>Gets an <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
+ /// <returns>An <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
+ /// <filterpriority>2</filterpriority>
+ System.Collections.ICollection Keys {
+ get;
+ }
+
+ /// <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);
+
+ /// <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;*/
+ }
+ }
+ [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.Requires(key != 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
+ }
+
+
+
+ /// <summary>
+ /// An implementation of the
+ /// <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />
+ /// interface with a <see cref="T:System.Collections.Hashtable" /> as the backing store.
+ /// </summary>
+ class FunctionalHashtable : IFunctionalMap {
+ private readonly Hashtable/*!*/ h;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(h != null);
+ }
+
+
+ /// <summary>
+ /// Cannot directly construct an instance of a FunctionalHashtbl.
+ /// </summary>
+ private FunctionalHashtable() {
+ this.h = new Hashtable();
+ // base();
+ }
+
+ /// <summary>
+ /// Cannot directly construct an instance of a FunctionalHashtbl.
+ /// </summary>
+ private FunctionalHashtable(Hashtable/*!*/ h) {
+ Contract.Requires(h != null);
+ this.h = h;
+ // base();
+ }
+
+ 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) {
+ //Contract.Requires(key != null);
+ Contract.Ensures(Contract.Result<IFunctionalMap>() != null);
+ Hashtable r = h.Clone() as Hashtable;
+ Contract.Assume(r != null);
+ r.Add(key, value);
+ return new FunctionalHashtable(r);
+ }
+
+ public IFunctionalMap/*!*/ Set(object/*!*/ key, object value) {
+ //Contract.Requires(key != null);
+ Contract.Ensures(Contract.Result<IFunctionalMap>() != null);
+ Hashtable r = h.Clone() as Hashtable;
+
+ 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) {
+ //Contract.Requires(key != null);
+ return h.Contains(key);
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator/*!*/ IEnumerable.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+
+ return h.GetEnumerator();
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IDictionaryEnumerator IFunctionalMap.GetEnumerator() {
+ return h.GetEnumerator();
+ }
+
+ public ICollection Keys {
+ get {
+ return h.Keys;
+ }
+ }
+
+ public IFunctionalMap/*!*/ Remove(object/*!*/ key) {
+ //Contract.Requires(key != null);
+ Contract.Ensures(Contract.Result<IFunctionalMap>() != null);
+ Hashtable r = h.Clone() as Hashtable;
+ Contract.Assume(r != null);
+ r.Remove(key);
+ return new FunctionalHashtable(r);
+ }
+
+ public ICollection Values {
+ get {
+ return h.Values;
+ }
+ }
+
+
+ public object this[object/*!*/ key] {
+ get {
+ //Contract.Requires(key != null);
+ return h[key];
+ }
+ }
+
+ public int Count {
+ [Pure]
+ get {
+ return h.Count;
+ }
+ }
+
+ public bool IsSynchronized {
+ [Pure]
+ get {
+ return h.IsSynchronized;
+ }
+ }
+
+ public object/*!*/ SyncRoot {
+ [Pure]
+ get {
+ Contract.Ensures(Contract.Result<object>() != null);
+ return h.SyncRoot;
+ }
+ }
+
+ public void CopyTo(System.Array/*!*/ a, int index) {
+ //Contract.Requires(a != null);
+ h.CopyTo(a, index);
+ }
+ }
+
+ public struct Pair/*<T1,T2>*/
+ {
+ private object first;
+ private object second;
+
+ public object First {
+ get {
+ return first;
+ }
+ }
+ public object Second {
+ get {
+ return second;
+ }
+ }
+
+ public Pair(object first, object second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is Pair))
+ return false;
+
+ Pair other = (Pair)obj;
+ return object.Equals(this.first, other.first) && object.Equals(this.second, other.second);
+ }
+
+ public override int GetHashCode() {
+ int h = this.first == null ? 0 : this.first.GetHashCode();
+ h ^= this.second == null ? 0 : this.second.GetHashCode();
+ return h;
+ }
+ }
+}
+
+
+namespace Microsoft.AbstractInterpretationFramework.Collections.Generic {
+ using System.Collections.Generic;
+
+ public struct Pair<T1, T2> {
+ private T1 first;
+ private T2 second;
+
+ public T1 First {
+ get {
+ return first;
+ }
+ }
+ public T2 Second {
+ get {
+ return second;
+ }
+ }
+
+ public Pair(T1 first, T2 second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is Pair<T1, T2>))
+ return false;
+
+ Pair<T1, T2> other = (Pair<T1, T2>)obj;
+ return object.Equals(this.first, other.first) && object.Equals(this.second, other.second);
+ }
+
+ public override int GetHashCode() {
+ int h = this.first == null ? 0 : this.first.GetHashCode();
+ h ^= this.second == null ? 0 : this.second.GetHashCode();
+ return h;
+ }
+
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return string.Format("({0},{1})", first, second);
+ }
+ }
+
+ public struct Triple<T1, T2, T3> {
+ private T1 first;
+ private T2 second;
+ private T3 third;
+
+ public T1 First {
+ get {
+ return first;
+ }
+ }
+ public T2 Second {
+ get {
+ return second;
+ }
+ }
+ public T3 Third {
+ get {
+ return third;
+ }
+ }
+
+ public Triple(T1 first, T2 second, T3 third) {
+ this.first = first;
+ this.second = second;
+ this.third = third;
+ }
+
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is Triple<T1, T2, T3>))
+ return false;
+
+ Triple<T1, T2, T3> other = (Triple<T1, T2, T3>)obj;
+ return object.Equals(this.first, other.first) && object.Equals(this.second, other.second) && object.Equals(this.third, other.third);
+ }
+
+ public override int GetHashCode() {
+ int h = this.first == null ? 0 : this.first.GetHashCode();
+ h ^= this.second == null ? 0 : this.second.GetHashCode();
+ h ^= this.third == null ? 0 : this.third.GetHashCode();
+ return h;
+ }
+
+ 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 ab10be9a..1796f1f6 100644
--- a/Source/AIFramework/Lattice.cs
+++ b/Source/AIFramework/Lattice.cs
@@ -1,960 +1,960 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-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;
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+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 ArraySet = Microsoft.Boogie.GSet<object>;
- using IMutableSet = Microsoft.Boogie.GSet<object>;
- using HashSet = Microsoft.Boogie.GSet<object>;
- using ISet = Microsoft.Boogie.GSet<object>;
- using Set = Microsoft.Boogie.GSet<object>;
-
-
- /// <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>
- /// Returns true if a &lt;= 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) {
- 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;
- }
-
- // 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' worse information than 'b'?
- //
- public bool HigherThan(Element/*!*/ a, Element/*!*/ b) {
- Contract.Requires(b != null);
- Contract.Requires(a != null);
- 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);
- }
-
- 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 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 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 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 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));
-
- 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();
- }
- }
-
- 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();
- }
-
- public override bool IsBottom(MathematicalLattice.Element e) {
- Contract.Requires(e != null);
- throw new NotImplementedException();
- }
-
- protected override bool AtMost(MathematicalLattice.Element a, MathematicalLattice.Element b) {
- Contract.Requires(a != null);
- Contract.Requires(b != null);
- throw new NotImplementedException();
- }
-
- 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 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 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);
- }
-
-
- public Lattice(IValueExprFactory/*!*/ valueExprFactory) {
- Contract.Requires(valueExprFactory != null);
- this.valueExprFactory = valueExprFactory;
- // base();
- }
-
- #region Primitives that commands translate into
-
- public abstract Element/*!*/ Eliminate(Element/*!*/ e, IVariable/*!*/ variable);
-
- public abstract Element/*!*/ Rename(Element/*!*/ e, IVariable/*!*/ oldName, IVariable/*!*/ newName);
-
- public abstract Element/*!*/ Constrain(Element/*!*/ e, IExpr/*!*/ expr);
-
- #endregion
-
-
- // 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 AtMost
- // overloads. We provide here a default implementation for one given a "real"
- // implementation of the other. Otherwise, there will be an infinite loop!
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- protected override bool AtMost(Element/*!*/ a, Element/*!*/ b) {
- //Contract.Requires(b != null);
- //Contract.Requires(a != null);
- return AtMost(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 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);
- }
-
-
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // 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) {
- //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);
- }
-
-
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // 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>
- /// 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) {
- 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.NonNullDictionaryAndValues(emptyDictionary1) && Contract.ForAll(emptyDictionary1.Values, set =>/*cce.NonNullElements(set)*/set != null));
- Contract.Invariant(cce.NonNullDictionaryAndValues(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>
- /// 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);
-
- 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 IVariable GetSourceName(IVariable resname) {
- Contract.Requires(resname != null);
- throw new NotImplementedException();
- }
-
- public IEnumerable GetSourceToResult() {
- Contract.Ensures(Contract.Result<IEnumerable>() != null);
- throw new NotImplementedException();
- }
-
- 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);
- }
-
- 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 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 bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args) {
- //Contract.Requires(args != null);
- //Contract.Requires(f != null);
- understandsCount++;
- return lattice.Understands(f, args);
- }
-
-
- 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);
- }
-
-
- public override Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred) {
- //Contract.Requires(pred != null);
- //Contract.Requires(e != null);
- checkPredicateCount++;
- return lattice.CheckPredicate(e, pred);
- }
-
-
- 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 IExpr/*!*/ ToPredicate(Element/*!*/ e) {
- //Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<IExpr>() != null);
- toPredicateCount++;
- return lattice.ToPredicate(e);
- }
-
- 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);
- }
-
- protected override bool AtMost(Element/*!*/ a, Element/*!*/ b) {
- //Contract.Requires(b != null);
- //Contract.Requires(a != null);
- atMostCount++;
- return lattice.LowerThan(a, b);
- }
-
- 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 override bool IsTop(Element/*!*/ e) {
- //Contract.Requires(e != null);
- isTopCount++;
- return lattice.IsTop(e);
- }
-
- 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);
- }
- }
-}
+ using IMutableSet = Microsoft.Boogie.GSet<object>;
+ using HashSet = Microsoft.Boogie.GSet<object>;
+ using ISet = Microsoft.Boogie.GSet<object>;
+ using Set = Microsoft.Boogie.GSet<object>;
+
+
+ /// <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>
+ /// Returns true if a &lt;= 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) {
+ 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;
+ }
+
+ // 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' worse information than 'b'?
+ //
+ public bool HigherThan(Element/*!*/ a, Element/*!*/ b) {
+ Contract.Requires(b != null);
+ Contract.Requires(a != null);
+ 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);
+ }
+
+ 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 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 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 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 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));
+
+ 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();
+ }
+ }
+
+ 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();
+ }
+
+ public override bool IsBottom(MathematicalLattice.Element e) {
+ Contract.Requires(e != null);
+ throw new NotImplementedException();
+ }
+
+ protected override bool AtMost(MathematicalLattice.Element a, MathematicalLattice.Element b) {
+ Contract.Requires(a != null);
+ Contract.Requires(b != null);
+ throw new NotImplementedException();
+ }
+
+ 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 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 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);
+ }
+
+
+ public Lattice(IValueExprFactory/*!*/ valueExprFactory) {
+ Contract.Requires(valueExprFactory != null);
+ this.valueExprFactory = valueExprFactory;
+ // base();
+ }
+
+ #region Primitives that commands translate into
+
+ public abstract Element/*!*/ Eliminate(Element/*!*/ e, IVariable/*!*/ variable);
+
+ public abstract Element/*!*/ Rename(Element/*!*/ e, IVariable/*!*/ oldName, IVariable/*!*/ newName);
+
+ public abstract Element/*!*/ Constrain(Element/*!*/ e, IExpr/*!*/ expr);
+
+ #endregion
+
+
+ // 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 AtMost
+ // overloads. We provide here a default implementation for one given a "real"
+ // implementation of the other. Otherwise, there will be an infinite loop!
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ protected override bool AtMost(Element/*!*/ a, Element/*!*/ b) {
+ //Contract.Requires(b != null);
+ //Contract.Requires(a != null);
+ return AtMost(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 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);
+ }
+
+
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // 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) {
+ //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);
+ }
+
+
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // 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>
+ /// 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) {
+ 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.NonNullDictionaryAndValues(emptyDictionary1) && Contract.ForAll(emptyDictionary1.Values, set =>/*cce.NonNullElements(set)*/set != null));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(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>
+ /// 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);
+
+ 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 IVariable GetSourceName(IVariable resname) {
+ Contract.Requires(resname != null);
+ throw new NotImplementedException();
+ }
+
+ public IEnumerable GetSourceToResult() {
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ throw new NotImplementedException();
+ }
+
+ 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);
+ }
+
+ 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 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 bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(f != null);
+ understandsCount++;
+ return lattice.Understands(f, args);
+ }
+
+
+ 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);
+ }
+
+
+ public override Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred) {
+ //Contract.Requires(pred != null);
+ //Contract.Requires(e != null);
+ checkPredicateCount++;
+ return lattice.CheckPredicate(e, pred);
+ }
+
+
+ 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 IExpr/*!*/ ToPredicate(Element/*!*/ e) {
+ //Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ toPredicateCount++;
+ return lattice.ToPredicate(e);
+ }
+
+ 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);
+ }
+
+ protected override bool AtMost(Element/*!*/ a, Element/*!*/ b) {
+ //Contract.Requires(b != null);
+ //Contract.Requires(a != null);
+ atMostCount++;
+ return lattice.LowerThan(a, b);
+ }
+
+ 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 override bool IsTop(Element/*!*/ e) {
+ //Contract.Requires(e != null);
+ isTopCount++;
+ return lattice.IsTop(e);
+ }
+
+ 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 aa7c5979..5b455ab0 100644
--- a/Source/AIFramework/Logger.cs
+++ b/Source/AIFramework/Logger.cs
@@ -1,56 +1,56 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.AbstractInterpretationFramework {
- using System;
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
-
- public class Logger {
- private string/*!*/ dbgmsgContext;
- private static int contextWidth = 0;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(dbgmsgContext != null);
- Contract.Invariant(dbgmsgIndent != null);
- }
-
-
- public bool Enabled = false;
-
- 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);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework {
+ using System;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ public class Logger {
+ private string/*!*/ dbgmsgContext;
+ private static int contextWidth = 0;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(dbgmsgContext != null);
+ Contract.Invariant(dbgmsgIndent != null);
+ }
+
+
+ public bool Enabled = false;
+
+ 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 ba9aa752..4c9de5f0 100644
--- a/Source/AIFramework/MultiLattice.cs
+++ b/Source/AIFramework/MultiLattice.cs
@@ -1,647 +1,647 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-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.GSet<object>;
- using Set = Microsoft.Boogie.GSet<object>;
-
-
- /// <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;
- }
- }
-
- public int Count {
- get {
- return this.elementPerLattice == null ? 0 : this.elementPerLattice.Length;
- }
- }
-
- 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
-
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(lattices != null);
- Contract.Invariant(propExprFactory != null);
- }
-
- ArrayList/*<Lattice>*//*!*/ lattices = new ArrayList();
-
- private readonly IPropExprFactory/*!*/ propExprFactory;
-
-
- public MultiLattice(IPropExprFactory/*!*/ propExprFactory, IValueExprFactory/*!*/ valueExprFactory)
- : base(valueExprFactory) {
- Contract.Requires(valueExprFactory != null);
- Contract.Requires(propExprFactory != null);
- this.propExprFactory = propExprFactory;
- // base(valueExprFactory);
- }
-
-
-
- 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);
- }
- }
-
- public override Element/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return Elt.Bottom(this.lattices);
- }
- }
-
-
-
-
- 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;
- }
-
- 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;
- }
-
- 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;
- }
-
-
- private enum CombineOp {
- Meet,
- Join,
- Widen
- }
-
- 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 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 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 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;
- }
-
-
- 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/*!*/ 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 bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args) {
- //Contract.Requires(args != null);
- //Contract.Requires(f != null);
- bool result = false;
-
- for (int i = 0; i < this.lattices.Count; i++) {
- result = (result || SubLattice(i).Understands(f, args));
- }
-
- return result;
- }
-
-
- 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 IExpr/*!*/ ToPredicate(Element/*!*/ element) {
- //Contract.Requires(element != null);
- Contract.Ensures(Contract.Result<IExpr>() != null);
- Elt e = (Elt)element;
-
- 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);
-
- 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) {
- //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 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);
-
- if (ans == Answer.Yes || ans == Answer.No)
- return ans;
- }
-
- return Answer.Maybe;
- }
-
-
- 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);
-
- for (int i = 0; i < e.Count; i++) {
- Answer ans = SubLattice(i).CheckVariableDisequality(cce.NonNull(e[i]), var1, var2);
-
- if (ans == Answer.Yes || ans == Answer.No)
- return ans;
- }
-
- return Answer.Maybe;
- }
-
-
-
- public override void Validate() {
- base.Validate();
- foreach (Lattice/*!*/ l in lattices) {
- Contract.Assert(l != null);
- l.Validate();
- }
- }
-
- /// <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();
- }
-
- /// <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));
- }
-
- /// <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 DictionaryEntry Entry {
- get {
- return new DictionaryEntry(cce.NonNull(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();
- }
- }
-
- 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);
- }
- }
-
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+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.GSet<object>;
+ using Set = Microsoft.Boogie.GSet<object>;
+
+
+ /// <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;
+ }
+ }
+
+ public int Count {
+ get {
+ return this.elementPerLattice == null ? 0 : this.elementPerLattice.Length;
+ }
+ }
+
+ 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
+
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(lattices != null);
+ Contract.Invariant(propExprFactory != null);
+ }
+
+ ArrayList/*<Lattice>*//*!*/ lattices = new ArrayList();
+
+ private readonly IPropExprFactory/*!*/ propExprFactory;
+
+
+ public MultiLattice(IPropExprFactory/*!*/ propExprFactory, IValueExprFactory/*!*/ valueExprFactory)
+ : base(valueExprFactory) {
+ Contract.Requires(valueExprFactory != null);
+ Contract.Requires(propExprFactory != null);
+ this.propExprFactory = propExprFactory;
+ // base(valueExprFactory);
+ }
+
+
+
+ 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);
+ }
+ }
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return Elt.Bottom(this.lattices);
+ }
+ }
+
+
+
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+
+ private enum CombineOp {
+ Meet,
+ Join,
+ Widen
+ }
+
+ 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 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 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 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;
+ }
+
+
+ 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/*!*/ 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 bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(f != null);
+ bool result = false;
+
+ for (int i = 0; i < this.lattices.Count; i++) {
+ result = (result || SubLattice(i).Understands(f, args));
+ }
+
+ return result;
+ }
+
+
+ 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 IExpr/*!*/ ToPredicate(Element/*!*/ element) {
+ //Contract.Requires(element != null);
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ Elt e = (Elt)element;
+
+ 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);
+
+ 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) {
+ //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 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);
+
+ if (ans == Answer.Yes || ans == Answer.No)
+ return ans;
+ }
+
+ return Answer.Maybe;
+ }
+
+
+ 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);
+
+ for (int i = 0; i < e.Count; i++) {
+ Answer ans = SubLattice(i).CheckVariableDisequality(cce.NonNull(e[i]), var1, var2);
+
+ if (ans == Answer.Yes || ans == Answer.No)
+ return ans;
+ }
+
+ return Answer.Maybe;
+ }
+
+
+
+ public override void Validate() {
+ base.Validate();
+ foreach (Lattice/*!*/ l in lattices) {
+ Contract.Assert(l != null);
+ l.Validate();
+ }
+ }
+
+ /// <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();
+ }
+
+ /// <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));
+ }
+
+ /// <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 DictionaryEntry Entry {
+ get {
+ return new DictionaryEntry(cce.NonNull(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();
+ }
+ }
+
+ 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 7592aa6a..fff0476e 100644
--- a/Source/AIFramework/Mutable.cs
+++ b/Source/AIFramework/Mutable.cs
@@ -1,137 +1,137 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Diagnostics.Contracts;
-namespace Microsoft.AbstractInterpretationFramework.Collections {
- using System.Collections;
- using System.Diagnostics.Contracts;
-
- /// <summary>
- /// Extend sets for using as a IWorkList.
- /// </summary>
- public class WorkSet : Microsoft.Boogie.GSet<object>, Microsoft.Boogie.IWorkList {
-
- // See Bug #148 for an explanation of why this is here.
- // Without it, the contract inheritance rules will complain since it
- // has nowhere to attach the out-of-band contract it gets from
- // ICollection.Count that it gets from IWorkList.
- public override int Count {
- get {
- return base.Count;
- }
- }
-
- [Pure]
- public bool IsEmpty() {
- return Count == 0;
- }
-
- /// <summary>
- /// Pull an element out of the workset.
- /// </summary>
- public object Pull() {
- IEnumerator iter = GetEnumerator();
- iter.MoveNext();
-
- object result = cce.NonNull(iter.Current);
- Remove(result);
-
- return result;
- }
-
- bool Microsoft.Boogie.IWorkList.Add(object o) {
- if (o == null)
- throw new System.ArgumentNullException();
- this.Add(o);
- return true;
- }
- bool Microsoft.Boogie.IWorkList.AddAll(IEnumerable objs) {
- if (objs == null)
- throw new System.ArgumentNullException();
- return this.AddAll(objs);
- }
-
- // ICollection members
- 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) {
- a.SetValue(o, j++);
- }
- return;
- }
- object/*!*/ ICollection.SyncRoot {
- [Pure]
- get {
- Contract.Ensures(Contract.Result<object>() != null);
- return this;
- }
- }
- public bool IsSynchronized {
- get {
- return false;
- }
- }
-
- }
-}
-
-namespace Microsoft.AbstractInterpretationFramework.Collections.Generic {
- using System.Collections.Generic;
-
- public class HashMultiset<T> {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(dict != null);
- }
-
- private readonly IDictionary<T, int>/*!*/ dict;
-
- //Contract.Invariant(Contract.ForAll(dict , entry => entry.Value >= 1));
-
- public HashMultiset() {
- this.dict = new Dictionary<T, int>();
- // base();
- }
-
- public HashMultiset(int size) {
- this.dict = new Dictionary<T, int>(size);
- // base();
- }
-
- public void Add(T t) {
- cce.BeginExpose(this);
- {
- if (dict.ContainsKey(t)) {
- dict[t] = dict[t] + 1;
- } else {
- dict.Add(t, 1);
- }
- }
- cce.EndExpose();
- }
-
- public void Remove(T t) {
- if (dict.ContainsKey(t)) {
- 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) {
- return dict.ContainsKey(t);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+namespace Microsoft.AbstractInterpretationFramework.Collections {
+ using System.Collections;
+ using System.Diagnostics.Contracts;
+
+ /// <summary>
+ /// Extend sets for using as a IWorkList.
+ /// </summary>
+ public class WorkSet : Microsoft.Boogie.GSet<object>, Microsoft.Boogie.IWorkList {
+
+ // See Bug #148 for an explanation of why this is here.
+ // Without it, the contract inheritance rules will complain since it
+ // has nowhere to attach the out-of-band contract it gets from
+ // ICollection.Count that it gets from IWorkList.
+ public override int Count {
+ get {
+ return base.Count;
+ }
+ }
+
+ [Pure]
+ public bool IsEmpty() {
+ return Count == 0;
+ }
+
+ /// <summary>
+ /// Pull an element out of the workset.
+ /// </summary>
+ public object Pull() {
+ IEnumerator iter = GetEnumerator();
+ iter.MoveNext();
+
+ object result = cce.NonNull(iter.Current);
+ Remove(result);
+
+ return result;
+ }
+
+ bool Microsoft.Boogie.IWorkList.Add(object o) {
+ if (o == null)
+ throw new System.ArgumentNullException();
+ this.Add(o);
+ return true;
+ }
+ bool Microsoft.Boogie.IWorkList.AddAll(IEnumerable objs) {
+ if (objs == null)
+ throw new System.ArgumentNullException();
+ return this.AddAll(objs);
+ }
+
+ // ICollection members
+ 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) {
+ a.SetValue(o, j++);
+ }
+ return;
+ }
+ object/*!*/ ICollection.SyncRoot {
+ [Pure]
+ get {
+ Contract.Ensures(Contract.Result<object>() != null);
+ return this;
+ }
+ }
+ public bool IsSynchronized {
+ get {
+ return false;
+ }
+ }
+
+ }
+}
+
+namespace Microsoft.AbstractInterpretationFramework.Collections.Generic {
+ using System.Collections.Generic;
+
+ public class HashMultiset<T> {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(dict != null);
+ }
+
+ private readonly IDictionary<T, int>/*!*/ dict;
+
+ //Contract.Invariant(Contract.ForAll(dict , entry => entry.Value >= 1));
+
+ public HashMultiset() {
+ this.dict = new Dictionary<T, int>();
+ // base();
+ }
+
+ public HashMultiset(int size) {
+ this.dict = new Dictionary<T, int>(size);
+ // base();
+ }
+
+ public void Add(T t) {
+ cce.BeginExpose(this);
+ {
+ if (dict.ContainsKey(t)) {
+ dict[t] = dict[t] + 1;
+ } else {
+ dict.Add(t, 1);
+ }
+ }
+ cce.EndExpose();
+ }
+
+ public void Remove(T t) {
+ if (dict.ContainsKey(t)) {
+ 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) {
+ return dict.ContainsKey(t);
+ }
+ }
+}
diff --git a/Source/AIFramework/Polyhedra/LinearConstraint.cs b/Source/AIFramework/Polyhedra/LinearConstraint.cs
index ab5e14f8..82264364 100644
--- a/Source/AIFramework/Polyhedra/LinearConstraint.cs
+++ b/Source/AIFramework/Polyhedra/LinearConstraint.cs
@@ -1,545 +1,545 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Diagnostics.Contracts;
-namespace Microsoft.AbstractInterpretationFramework {
- using System;
- //using System.Compiler;
- using System.Collections;
- using Microsoft.Basetypes;
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+namespace Microsoft.AbstractInterpretationFramework {
+ using System;
+ //using System.Compiler;
+ using System.Collections;
+ using Microsoft.Basetypes;
using Set = Microsoft.Boogie.GSet<object>;
- using IMutableSet = Microsoft.Boogie.GSet<object>;
- using HashSet = Microsoft.Boogie.GSet<object>;
- using ISet = Microsoft.Boogie.GSet<object>;
-
-
- /// <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 LinearConstraint(ConstraintRelation rel) {
- Relation = rel;
- }
-
- [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
- public bool IsOverIntegers
- {
- get
- {
- foreach (DictionaryEntry /*IVariable->Rational*/ entry in coefficients)
- {
- IVariable var = (IVariable)entry.Key;
- if ( ! var.TypedIdent.Type.IsInt) { return false; }
- }
- return true;
- }
- }
-#endif
-
-
- /// <summary>
- /// Note: This method requires that all dimensions are of type Variable, something that's
- /// not required elsewhere in this class.
- /// </summary>
- /// <returns></returns>
- 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) {
- IVariable var = (IVariable)entry.Key;
- Rational coeff = (Rational)(cce.NonNull(entry.Value));
- if (coeff.IsPositive) {
- leftSum = AddTerm(factory, leftSum, coeff, var);
- } else if (coeff.IsNegative) {
- rightSum = AddTerm(factory, rightSum, -coeff, var);
- } else {
- // ignore the term is coeff==0
- }
- }
-
- if (leftSum == null && rightSum == null) {
- // there are no variables in this constraint
- if (Relation == ConstraintRelation.EQ ? rhs.IsZero : rhs.IsNonNegative) {
- return factory.True;
- } else {
- return factory.False;
- }
- }
-
- 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) {
- // show the constant on the right side
- rightSum = AddTerm(factory, rightSum, rhs, null);
- }
-
- Contract.Assert(leftSum != null);
- Contract.Assert(rightSum != null);
- return Relation == ConstraintRelation.EQ ? factory.Eq(leftSum, rightSum) : factory.AtMost(leftSum, rightSum);
- }
-
- /// <summary>
- /// Returns an expression that denotes sum + r*x.
- /// If sum==null, drops the "sum +".
- /// If x==null, drops the "*x".
- /// if x!=null and r==1, drops the "r*".
- /// </summary>
- /// <param name="factory"></param>
- /// <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) {
- 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;
- }
-
- /// <summary>
- /// Returns true iff all of the coefficients in the constraint are 0. In that
- /// case, the constraint has the form 0 &lt;= 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 &lt;= rhs.
- /// </summary>
- public bool IsConstantSatisfiable() {
- if (Relation == ConstraintRelation.EQ) {
- return rhs.IsZero;
- } 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) {
- 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);
- }
- }
-
- 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
- }
- }
-
- // we expect there to have been some non-zero coefficient, so "m" should have been used by now
- System.Diagnostics.Debug.Assert(m.IsNonZero);
-
- // finally, check the rhs
- if (this.rhs == m * c.rhs) {
- return m; // equivalent
- } else {
- 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);
-
- 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) {
- 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) {
- Contract.Requires(dim != null);
- object val = coefficients[dim];
- if (val != null) {
-#if FIXED_SERIALIZER
- 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 {
- 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) {
- Contract.Requires(newName != null);
- Contract.Requires(oldName != null);
- object /*Rational*/ z = coefficients[oldName];
- if (z == null) {
- return this;
- } else {
- System.Diagnostics.Debug.Assert(z is Rational);
- Hashtable /*IVariable->Rational*/ newCoeffs = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(coefficients.Clone());
- newCoeffs.Remove(oldName);
- newCoeffs.Add(newName, z);
-
- LinearConstraint lc = new LinearConstraint(this.Relation);
- lc.coefficients = newCoeffs;
- lc.rhs = this.rhs;
- return lc;
- }
- }
-
- 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) {
- Contract.Ensures(Contract.Result<LinearConstraint>() != null);
- if (Relation == rel) {
- return this;
- } else {
- LinearConstraint z = new LinearConstraint(rel);
- z.coefficients = (Hashtable)this.coefficients.Clone();
- z.rhs = this.rhs;
- return z;
- }
- }
-
- /// <summary>
- /// Returns a constraint like "this", but, conceptually, with the inequality relation >=.
- /// </summary>
- /// <returns></returns>
- 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)(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) {
- 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.
- /// </summary>
- /// <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) {
- 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 &lt;= B into (A + m*aa)*X &lt;= B + m*bb,
- /// where "cc" is the constraint aa*X &lt;= 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>
- /// 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)(cce.NonNull(e.Value));
- if (r.IsNonZero) {
- newCoefficients.Add(e.Key, Rational.FromBignums(r.Numerator / gcd.Numerator, r.Denominator / gcd.Denominator));
- } else {
- newCoefficients.Add(e.Key, r);
- }
- }
-
- coefficients = newCoefficients;
- rhs = rhs.IsNonZero ? Rational.FromBignums(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);
- }
-
- Hashtable /*IVariable->Rational*//*!*/ terms = new Hashtable /*IVariable->Rational*/ ();
-
- /// <summary>
- /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction.
- /// </summary>
- public FrameElement() {
- }
-
- /// <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);
- }
-
- [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 + ")";
- }
-
- 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) {
- Contract.Requires(newName != null);
- Contract.Requires(oldName != null);
- object /*Rational*/ z = terms[oldName];
- if (z == null) {
- return this;
- } else {
- System.Diagnostics.Debug.Assert(z is Rational);
- Hashtable /*IVariable->Rational*/ newTerms = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(terms.Clone());
- newTerms.Remove(oldName);
- newTerms.Add(newName, z);
-
- FrameElement fe = new FrameElement();
- fe.terms = newTerms;
- return fe;
- }
- }
-
- public FrameElement Clone() {
- FrameElement z = new FrameElement();
- z.terms = (Hashtable /*IVariable->Rational*/)this.terms.Clone();
- return z;
- }
- }
-}
+ using IMutableSet = Microsoft.Boogie.GSet<object>;
+ using HashSet = Microsoft.Boogie.GSet<object>;
+ using ISet = Microsoft.Boogie.GSet<object>;
+
+
+ /// <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 LinearConstraint(ConstraintRelation rel) {
+ Relation = rel;
+ }
+
+ [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
+ public bool IsOverIntegers
+ {
+ get
+ {
+ foreach (DictionaryEntry /*IVariable->Rational*/ entry in coefficients)
+ {
+ IVariable var = (IVariable)entry.Key;
+ if ( ! var.TypedIdent.Type.IsInt) { return false; }
+ }
+ return true;
+ }
+ }
+#endif
+
+
+ /// <summary>
+ /// Note: This method requires that all dimensions are of type Variable, something that's
+ /// not required elsewhere in this class.
+ /// </summary>
+ /// <returns></returns>
+ 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) {
+ IVariable var = (IVariable)entry.Key;
+ Rational coeff = (Rational)(cce.NonNull(entry.Value));
+ if (coeff.IsPositive) {
+ leftSum = AddTerm(factory, leftSum, coeff, var);
+ } else if (coeff.IsNegative) {
+ rightSum = AddTerm(factory, rightSum, -coeff, var);
+ } else {
+ // ignore the term is coeff==0
+ }
+ }
+
+ if (leftSum == null && rightSum == null) {
+ // there are no variables in this constraint
+ if (Relation == ConstraintRelation.EQ ? rhs.IsZero : rhs.IsNonNegative) {
+ return factory.True;
+ } else {
+ return factory.False;
+ }
+ }
+
+ 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) {
+ // show the constant on the right side
+ rightSum = AddTerm(factory, rightSum, rhs, null);
+ }
+
+ Contract.Assert(leftSum != null);
+ Contract.Assert(rightSum != null);
+ return Relation == ConstraintRelation.EQ ? factory.Eq(leftSum, rightSum) : factory.AtMost(leftSum, rightSum);
+ }
+
+ /// <summary>
+ /// Returns an expression that denotes sum + r*x.
+ /// If sum==null, drops the "sum +".
+ /// If x==null, drops the "*x".
+ /// if x!=null and r==1, drops the "r*".
+ /// </summary>
+ /// <param name="factory"></param>
+ /// <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) {
+ 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;
+ }
+
+ /// <summary>
+ /// Returns true iff all of the coefficients in the constraint are 0. In that
+ /// case, the constraint has the form 0 &lt;= 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 &lt;= rhs.
+ /// </summary>
+ public bool IsConstantSatisfiable() {
+ if (Relation == ConstraintRelation.EQ) {
+ return rhs.IsZero;
+ } 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) {
+ 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);
+ }
+ }
+
+ 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
+ }
+ }
+
+ // we expect there to have been some non-zero coefficient, so "m" should have been used by now
+ System.Diagnostics.Debug.Assert(m.IsNonZero);
+
+ // finally, check the rhs
+ if (this.rhs == m * c.rhs) {
+ return m; // equivalent
+ } else {
+ 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);
+
+ 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) {
+ 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) {
+ Contract.Requires(dim != null);
+ object val = coefficients[dim];
+ if (val != null) {
+#if FIXED_SERIALIZER
+ 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 {
+ 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) {
+ Contract.Requires(newName != null);
+ Contract.Requires(oldName != null);
+ object /*Rational*/ z = coefficients[oldName];
+ if (z == null) {
+ return this;
+ } else {
+ System.Diagnostics.Debug.Assert(z is Rational);
+ Hashtable /*IVariable->Rational*/ newCoeffs = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(coefficients.Clone());
+ newCoeffs.Remove(oldName);
+ newCoeffs.Add(newName, z);
+
+ LinearConstraint lc = new LinearConstraint(this.Relation);
+ lc.coefficients = newCoeffs;
+ lc.rhs = this.rhs;
+ return lc;
+ }
+ }
+
+ 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) {
+ Contract.Ensures(Contract.Result<LinearConstraint>() != null);
+ if (Relation == rel) {
+ return this;
+ } else {
+ LinearConstraint z = new LinearConstraint(rel);
+ z.coefficients = (Hashtable)this.coefficients.Clone();
+ z.rhs = this.rhs;
+ return z;
+ }
+ }
+
+ /// <summary>
+ /// Returns a constraint like "this", but, conceptually, with the inequality relation >=.
+ /// </summary>
+ /// <returns></returns>
+ 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)(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) {
+ 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.
+ /// </summary>
+ /// <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) {
+ 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 &lt;= B into (A + m*aa)*X &lt;= B + m*bb,
+ /// where "cc" is the constraint aa*X &lt;= 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>
+ /// 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)(cce.NonNull(e.Value));
+ if (r.IsNonZero) {
+ newCoefficients.Add(e.Key, Rational.FromBignums(r.Numerator / gcd.Numerator, r.Denominator / gcd.Denominator));
+ } else {
+ newCoefficients.Add(e.Key, r);
+ }
+ }
+
+ coefficients = newCoefficients;
+ rhs = rhs.IsNonZero ? Rational.FromBignums(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);
+ }
+
+ Hashtable /*IVariable->Rational*//*!*/ terms = new Hashtable /*IVariable->Rational*/ ();
+
+ /// <summary>
+ /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction.
+ /// </summary>
+ public FrameElement() {
+ }
+
+ /// <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);
+ }
+
+ [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 + ")";
+ }
+
+ 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) {
+ Contract.Requires(newName != null);
+ Contract.Requires(oldName != null);
+ object /*Rational*/ z = terms[oldName];
+ if (z == null) {
+ return this;
+ } else {
+ System.Diagnostics.Debug.Assert(z is Rational);
+ Hashtable /*IVariable->Rational*/ newTerms = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(terms.Clone());
+ newTerms.Remove(oldName);
+ newTerms.Add(newName, z);
+
+ FrameElement fe = new FrameElement();
+ fe.terms = newTerms;
+ return fe;
+ }
+ }
+
+ 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 74e36eae..59aadb86 100644
--- a/Source/AIFramework/Polyhedra/LinearConstraintSystem.cs
+++ b/Source/AIFramework/Polyhedra/LinearConstraintSystem.cs
@@ -1,1756 +1,1756 @@
-//-----------------------------------------------------------------------------
-//
-// 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 System.Diagnostics.Contracts;
- using Microsoft.Basetypes;
-
- using IMutableSet = Microsoft.Boogie.GSet<object>;
- using ISet = Microsoft.Boogie.GSet<object>;
- using HashSet = Microsoft.Boogie.GSet<object>;
-
- /// <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;
- [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
- // FrameLines is mentioned in FrameDimensions.
- // 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) {
- 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 {
- System.Diagnostics.Debug.Assert(FrameVertices != null);
- System.Diagnostics.Debug.Assert(FrameRays != null);
- System.Diagnostics.Debug.Assert(FrameLines != null);
-
- foreach (LinearConstraint/*!*/ cc in Constraints) {
- Contract.Assert(cc != null);
-#if FIXED_DESERIALIZER
- 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 }) {
- Contract.Assert(FrameComponent != null);
- foreach (FrameElement fe in FrameComponent) {
- if (fe == null)
- continue;
-#if FIXED_DESERIALIZER
- Contract.Assert(Contract.ForAll(fe.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
-#endif
- }
- }
- }
- }
-
- // --------------------------------------------------------------------------------------------------------
- // ------------------ Constructors ------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------------------
-
- /// <summary>
- /// Creates a LinearConstraintSystem representing the bottom element, that is, representing
- /// an unsatisfiable system of constraints.
- /// </summary>
- [NotDelayed]
- public LinearConstraintSystem() {
- FrameDimensions = new HashSet /*IVariable!*/ ();
- //:base();
- CheckInvariant();
- }
-
- /// <summary>
- /// Constructs a linear constraint system with constraints "cs".
- /// The constructor captures all constraints in "cs".
- /// </summary>
- /// <param name="cs"></param>
- [NotDelayed]
- public LinearConstraintSystem(ArrayList /*LinearConstraint!*//*!*/ cs) {
- Contract.Requires(cs != null);
-#if BUG_159_HAS_BEEN_FIXED
- Contract.Requires(Contract.ForAll(cs) , cc=> cc.coefficients.Count != 0);
-#endif
-
- ArrayList constraints = new ArrayList /*LinearConstraint!*/ (cs.Count);
- 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();
-
- GenerateFrameFromConstraints();
- SimplifyConstraints();
- CheckInvariant();
-#if DEBUG_PRINT
- Console.WriteLine("LinearConstraintSystem: constructor produced:");
- Dump();
-#endif
- }
-
- /// <summary>
- /// Constructs a linear constraint system corresponding to given vertex. This constructor
- /// is only used in the test harness--it is not needed for abstract interpretation.
- /// </summary>
- /// <param name="v"></param>
- [NotDelayed]
- 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) {
- Contract.Assert(dim != null);
- LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
- lc.SetCoefficient(dim, Rational.ONE);
- lc.rhs = v[dim];
- constraints.Add(lc);
- }
- FrameDimensions = frameDims;
- Constraints = constraints;
-
- ArrayList /*FrameElement*/ frameVertices = new ArrayList /*FrameElement*/ ();
- frameVertices.Add(v);
- FrameVertices = frameVertices;
-
- FrameRays = new ArrayList /*FrameElement*/ ();
- FrameLines = new ArrayList /*FrameElement*/ ();
-
- //:base();
- CheckInvariant();
- }
-
- void ChangeIntoBottom() {
- Constraints = null;
- FrameVertices = null;
- FrameRays = null;
- FrameLines = null;
- FrameDimensions.Clear(); // no implicit lines
- }
-
- // --------------------------------------------------------------------------------------------------------
- // ------------------ Public operations and their support routines ----------------------------------------
- // --------------------------------------------------------------------------------------------------------
-
- public bool IsBottom() {
- return Constraints == null;
- }
-
- public bool IsTop() {
- return Constraints != null && Constraints.Count == 0;
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- if (Constraints == null) {
- return "<bottom>";
- } else if (Constraints.Count == 0) {
- return "<top>";
- } else {
- string z = null;
- foreach (LinearConstraint/*!*/ lc in Constraints) {
- Contract.Assert(lc != null);
- string s = lc.ToString();
- if (z == null) {
- z = s;
- } else {
- z += " AND " + s;
- }
- }
- Contract.Assert(z != null);
- return z;
- }
- }
-
-
- 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>
- /// Note: This method requires that all dimensions are of type Variable, something that's
- /// not required elsewhere in this class.
- /// </summary>
- /// <returns></returns>
- public IExpr/*!*/ ConvertToExpression(ILinearExprFactory/*!*/ factory) {
- Contract.Requires(factory != null);
- Contract.Ensures(Contract.Result<IExpr>() != null);
- if (this.Constraints == null) {
- return factory.False;
- }
- if (this.Constraints.Count == 0) {
- return factory.True;
- }
-
- IExpr result = null;
- foreach (LinearConstraint/*!*/ lc in Constraints) {
- Contract.Assert(lc != null);
- IExpr conjunct = lc.ConvertToExpression(factory);
- result = (result == null) ? conjunct : (IExpr)factory.And(conjunct, result);
- }
- Contract.Assert(result != null);
- return result;
- }
-
-
- /* IsSubset(): determines if 'lcs' is a subset of 'this'
- * -- See Cousot/Halbwachs 1978, section
- */
- public bool IsSubset(LinearConstraintSystem/*!*/ lcs) {
- Contract.Requires(lcs != null);
- if (lcs.IsBottom()) {
- return true;
- } else if (this.IsBottom()) {
- return false;
-#if DEBUG
-#else
- } else if (this.IsTop()) { // optimization -- this case not needed for correctness
- return true;
- } else if (lcs.IsTop()) { // optimization -- this case not needed for correctness
- return false;
-#endif
- } else {
- // phase 0: check if frame dimensions are a superset of the constraint dimensions
- ISet /*IVariable!*//*!*/ frameDims = lcs.GetDefinedDimensions();
- Contract.Assert(frameDims != null);
-#if DEBUG_PRINT
- Console.WriteLine("DEBUG: IsSubset:");
- Console.WriteLine(" --- this:");
- this.Dump();
- Console.WriteLine(" --- lcs:");
- lcs.Dump();
- Console.WriteLine(" ---");
-#endif
- 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 (!Contract.ForAll(cc.GetDefinedDimensionsGeneric(), var => frameDims.Contains(var))) {
-#if DEBUG_PRINT
- Console.WriteLine(" ---> phase 0 subset violated, return false from IsSubset");
-#endif
- return false;
- }
- }
- }
-
- // phase 1: check frame vertices against each constraint...
- 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 DEBUG_PRINT
- Console.WriteLine(" ---> phase 1a subset violated, return false from IsSubset");
-#endif
- return false;
- }
- } else {
- if (!(q == cc.rhs)) {
-#if DEBUG_PRINT
- Console.WriteLine(" ---> phase 1b subset violated, return false from IsSubset");
-#endif
- return false;
- }
- }
- }
- }
-
- // phase 2: check frame rays against each constraint...
- // To check if a ray "r" falls within a constraint "cc", we add the vector "r" to
- // any point "p" on the side of the half-space or plane described by constraint, and
- // then check if the resulting point satisfies the constraint. That is, we check (for
- // an inequality constraint with coefficients a1,a2,...,an and right-hand side
- // constant C):
- // a1*(r1+p1) + a2*(r2+p2) + ... + an*(rn+pn) <= C
- // Equivalently:
- // a1*r1 + a2*r2 + ... + an*rn + a1*p1 + a2*p2 + ... + an*pn <= C
- // To find a point "p", we can pick out a coordinate, call it 1, with a non-zero
- // coefficient in the constraint, and then choose "p" as the point that has the
- // value C/a1 in coordinate 1 and has 0 in all other coordinates. We then check:
- // a1*r1 + a2*r2 + ... + an*rn + a1*(C/a1) + a2*0 + ... + an*0 <= C
- // which simplifies to:
- // a1*r1 + a2*r2 + ... + an*rn + C <= C
- // which in turn simplifies to:
- // a1*r1 + a2*r2 + ... + an*rn <= 0
- // If the constraint is an equality constraint, we simply replace "<=" with "=="
- // above.
- 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) {
- 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 DEBUG_PRINT
- Console.WriteLine(" ---> phase 2a subset violated, return false from IsSubset");
-#endif
- return false;
- }
- } else {
- if (q.IsNonZero) {
-#if DEBUG_PRINT
- Console.WriteLine(" ---> phase 2b subset violated, return false from IsSubset");
-#endif
- return false;
- }
- }
- }
- }
-
- // phase 3: check frame lines against each constraint...
- // To check if a line "L" falls within a constraint "cc", we check if both the
- // vector "L" and "-L", interpreted as rays, fall within the constraint. From
- // the discussion above, this means we check the following two properties:
- // a1*L1 + a2*L2 + ... + an*Ln <= 0 (*)
- // a1*(-L1) + a2*(-L2) + ... + an*(-Ln) <= 0
- // The second of these lines can be rewritten as:
- // - a1*L1 - a2*L2 - ... - an*Ln <= 0
- // which is equivalent to:
- // -1 * (a1*L1 + a2*L2 + ... + an*Ln) <= 0
- // Multiplying both sides by -1 and flipping the direction of the inequality,
- // we have:
- // a1*L1 + a2*L2 + ... + an*Ln >= 0 (**)
- // 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 cce.NonNull(lcs.FrameLines)) {
- Contract.Assert(line != null);
- System.Diagnostics.Debug.Assert(line != null, "encountered a null line...");
- 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 DEBUG_PRINT
- Console.WriteLine(" ---> phase 3 subset violated, return false from IsSubset");
-#endif
- return false;
- }
- }
- }
-
-#if DEBUG_PRINT
- Console.WriteLine(" ---> IsSubset returns true");
-#endif
- return true;
- }
-
- 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);
- return new LinearConstraintSystem(clist);
- }
-
-#if DEBUG_PRINT
- public LinearConstraintSystem Join(LinearConstraintSystem lcs)
- {
- Console.WriteLine("===================================================================================");
- Console.WriteLine("DEBUG: Join");
- Console.WriteLine("Join: this=");
- Dump();
- Console.WriteLine("Join: lcs=");
- lcs.Dump();
- LinearConstraintSystem z = JoinX(lcs);
- Console.WriteLine("----------Join------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- Console.WriteLine("Join: result=");
- z.Dump();
- Console.WriteLine("===================================================================================");
- return z;
- }
-#endif
-
- /// <summary>
- /// The join is computed as described in section 4.4 in Cousot and Halbwachs.
- /// </summary>
- /// <param name="lcs"></param>
- /// <returns></returns>
-#if DEBUG_PRINT
- public LinearConstraintSystem JoinX(LinearConstraintSystem lcs) {
-#else
- public LinearConstraintSystem/*!*/ Join(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*/ ());
- } else {
- LinearConstraintSystem/*!*/ z;
- // Start from the "larger" of the two frames (this is just a heuristic measure intended
- // to save work).
- 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 = cce.NonNull(lcs.Clone());
- lcs = this;
- } else {
- z = cce.NonNull(this.Clone());
- }
-#if DEBUG_PRINT
- Console.WriteLine("DEBUG: LinearConstraintSystem.Join ---------------");
- Console.WriteLine("z:");
- z.Dump();
- Console.WriteLine("lcs:");
- lcs.Dump();
-#endif
-
- // Start by explicating the implicit lines of z for the dimensions dims(lcs)-dims(z).
- 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.
- Contract.Assume(z.FrameLines != null);
- z.FrameLines.Add(line);
-#if DEBUG_PRINT
- Console.WriteLine("Join: After explicating line: {0}", line);
- z.Dump();
-#endif
- }
- }
-
- // Now, the vertices, rays, and lines can be added.
- 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) {
- 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) {
- Contract.Assert(l != null);
- z.AddLine(l);
-#if DEBUG_PRINT
- Console.WriteLine("Join: After adding line: {0}", l);
- z.Dump();
-#endif
- }
- // also add to z the implicit lines of lcs
- 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);
- z.AddLine(line);
-#if DEBUG_PRINT
- Console.WriteLine("Join: After adding lcs's implicit line: {0}", line);
- z.Dump();
-#endif
- }
- }
-
- z.SimplifyFrame();
- z.SimplifyConstraints();
- z.CheckInvariant();
-#if DEBUG_PRINT
- Console.WriteLine("Join: Returning z:");
- z.Dump();
- Console.WriteLine("----------------------------------------");
-#endif
- return z;
- }
- }
-
-#if DEBUG_PRINT
- public LinearConstraintSystem Widen(LinearConstraintSystem lcs)
- {
- Console.WriteLine("===================================================================================");
- Console.WriteLine("DEBUG: Widen");
- Console.WriteLine("Widen: this=");
- Dump();
- Console.WriteLine("Widen: lcs=");
- lcs.Dump();
- LinearConstraintSystem z = WidenX(lcs);
- Console.WriteLine("----------Widen------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- Console.WriteLine("Widen: result=");
- z.Dump();
- Console.WriteLine("===================================================================================");
- return z;
- }
-#endif
-
-#if DEBUG_PRINT
- public LinearConstraintSystem WidenX(LinearConstraintSystem lcs){
-#else
- 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*/ ();
- 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()) {
- // (Can this ever occur in the stable state of a LinearConstraintSystem? --KRML)
- // constraint is unaffected by the frame components
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: --Adding it!");
-#endif
- newConstraints.Add(cc);
- continue;
- }
-
- // PHASE I: verify constraints against all frame vertices...
-
- foreach (FrameElement/*!*/ vertex in cce.NonNull(lcs.FrameVertices)) {
- Contract.Assert(vertex != null);
- Rational lhs = cc.EvaluateLhs(vertex);
- if (lhs > cc.rhs) {
- // the vertex does not satisfy the inequality <=
- 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 {
- // ... but it does satisfy the inequality >=
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: throwing out <= because of vertex: {0}", vertex);
-#endif
- cc = cc.ChangeRelationToAtLeast();
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: left with constraint: {0}", cc);
-#endif
- }
- } 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);
-#endif
- cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE);
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: left with contraint: {0}", cc);
-#endif
- }
- }
-
- // PHASE II: verify constraints against all frame rays...
-
- 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) {
- // the ray does not satisfy the inequality <=
- 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 {
- // ... but it does satisfy the inequality >=
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: throwing out <= because of ray: {0}", ray);
-#endif
- cc = cc.ChangeRelationToAtLeast();
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: left with contraint: {0}", cc);
-#endif
- }
- } 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);
-#endif
- cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE);
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: left with constraint: {0}", cc);
-#endif
- }
- }
-
- // PHASE III: verify constraints against all frame lines...
-
- 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) {
- // The line satisfies neither the inequality <= nor the equality ==
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: throwing out because of line: {0}", line);
-#endif
- goto CHECK_NEXT_CONSTRAINT;
- }
- }
-
- // constraint has been verified, so add to new constraint system
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: --Adding it!");
-#endif
- newConstraints.Add(cc);
-
- CHECK_NEXT_CONSTRAINT: {
- }
-#if DEBUG_PRINT
- Console.WriteLine("Widen checking: done with that constraint");
-#endif
- }
-
- return new LinearConstraintSystem(newConstraints);
- }
-
-#if DEBUG_PRINT
- public LinearConstraintSystem Project(IVariable/*!*/ dim){
-Contract.Requires(dim != null);
- Console.WriteLine("===================================================================================");
- Console.WriteLine("DEBUG: Project(dim={0})", dim);
- Console.WriteLine("Project: this=");
- Dump();
- LinearConstraintSystem z = ProjectX(dim);
- Console.WriteLine("----------Project------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- Console.WriteLine("Project: result=");
- z.Dump();
- Console.WriteLine("===================================================================================");
- return z;
- }
-#endif
-
-#if DEBUG_PRINT
- public LinearConstraintSystem ProjectX(IVariable/*!*/ dim){Contract.Requires(dim != null);Contract.Requires(this.Constraints != null);
-#else
- public LinearConstraintSystem/*!*/ Project(IVariable/*!*/ dim) {
- Contract.Requires(dim != null);
- Contract.Requires(this.Constraints != null);
- Contract.Ensures(Contract.Result<LinearConstraintSystem>() != null);
-#endif
-
-
- ArrayList /*LinearConstraint!*//*!*/ cc = Project(dim, Constraints);
- Contract.Assert(cc != null);
- return new LinearConstraintSystem(cc);
- }
-
-#if DEBUG_PRINT
- 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=");
- Dump();
- LinearConstraintSystem z = RenameX(oldName, newName);
- Console.WriteLine("----------Rename------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- Console.WriteLine("Rename: result=");
- z.Dump();
- Console.WriteLine("===================================================================================");
- return z;
- }
-#endif
-
-#if DEBUG_PRINT
- public LinearConstraintSystem RenameX(IVariable/*!*/ oldName, IVariable/*!*/ newName){Contract.Requires(oldName != null);Contract.Requires(newName != null);
-#else
- 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) {
- 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;
- Contract.Assert(dims != null);
- if (!dims.Contains(oldName)) {
- return this;
- }
-
- LinearConstraintSystem z = new LinearConstraintSystem();
- 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 cce.NonNull(this.Constraints)) {
- Contract.Assert(lc != null);
- z.Constraints.Add(lc.Rename(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) {
- 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);
- return z;
- }
-
- // --------------------------------------------------------------------------------------------------------
- // ------------------ support routines --------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------------------
-
- /// <summary>
- /// Returns a set of constraints that is the given set of constraints with dimension "dim"
- /// projected out. See Cousot and Halbwachs, section 3.3.1.1.
- /// </summary>
- /// <param name="dim"></param>
- /// <param name="constraints"></param>
- /// <returns></returns>
- 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) {
- Contract.Assert(cc != null);
- Rational coeff = cc[dim];
- 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) {
- eq.Add(cc);
- } else if (coeff.IsNegative) {
- negative.Add(cc);
- } else {
- System.Diagnostics.Debug.Assert(coeff.IsPositive);
- positive.Add(cc);
- }
- }
-
- 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 }) {
- 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()) {
- lc.RemoveDimension(dim);
- final.Add(lc);
- } else {
- System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
- }
- }
- }
- } else {
- // Consider all pairs of constraints with (negative,positive) coefficients of "dim".
- foreach (LinearConstraint/*!*/ cn in negative) {
- Contract.Assert(cn != null);
- Rational dn = -cn[dim];
- System.Diagnostics.Debug.Assert(dn.IsNonNegative);
- 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()) {
- lc.RemoveDimension(dim);
- final.Add(lc);
- } else {
- System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
- }
- }
- }
- }
-
- return final;
- }
-
- /// <summary>
- /// Initializes FrameVertices, FrameRays, FrameLines, and FrameDimensions, see
- /// Cousot and Halbwachs, section 3.4. Any previous values of these fields are
- /// ignored and overwritten.
- ///
- /// If the set of Constraints is unsatisfiable, then "this" is changed into Bottom.
- /// </summary>
- 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 ---");
- Console.WriteLine("Constraints:");
- foreach (LinearConstraint cc in Constraints)
- {
- Console.WriteLine(" {0}", cc);
- }
-#endif
- SimplexTableau tableau = new SimplexTableau(Constraints);
-#if DEBUG_PRINT
- Console.WriteLine("Initial tableau:");
- tableau.Dump();
-#endif
- FrameDimensions = tableau.GetDimensions();
-#if DEBUG_PRINT
- Console.WriteLine("Dimensions:");
- foreach (object dim in FrameDimensions)
- {
- Console.Write(" {0}", dim);
- }
- Console.WriteLine();
-#endif
-
- // Step 3 and 2: Put as many initial variables as possible into basis, then check if
- // we reached a feasible basis
- tableau.AddInitialVarsToBasis();
-#if DEBUG_PRINT
- Console.WriteLine("Tableau after Step 3:");
- tableau.Dump();
-#endif
- if (!tableau.IsFeasibleBasis) {
- // The polyhedron is empty (according to Cousot and Halbwachs)
- ChangeIntoBottom();
- return;
- }
-
- FrameVertices = new ArrayList /*FrameElement*/ ();
- FrameRays = new ArrayList /*FrameElement*/ ();
- FrameLines = new ArrayList /*FrameElement*/ ();
- if (FrameDimensions.Count == 0) {
- // top element
- return;
- }
-
- 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 {
- // 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 = cce.NonNull((ArrayList/*!*/ /*LinearConstraint*/)Constraints.Clone());
- tableau.ProduceLines(FrameLines, moreConstraints);
- tableau = new SimplexTableau(moreConstraints);
-#if DEBUG_PRINT
- Console.WriteLine("Lines produced:");
- foreach (FrameElement line in FrameLines)
- {
- Console.WriteLine(" {0}", line);
- }
- Console.WriteLine("The new list of constraints is:");
- foreach (LinearConstraint c in moreConstraints)
- {
- Console.WriteLine(" {0}", c);
- }
- Console.WriteLine("Tableau after producing lines in Step 4.2:");
- tableau.Dump();
-#endif
-
- // Repeat step 3 for the new tableau.
- // Since the new tableau contains no lines, the following call should cause all initial
- // variables to be in basis (see step 4.2 in section 3.4.3 of Cousot and Halbwachs).
- tableau.AddInitialVarsToBasis();
- System.Diagnostics.Debug.Assert(tableau.AllInitialVarsInBasis);
- System.Diagnostics.Debug.Assert(tableau.IsFeasibleBasis); // the new tableau represents a set of feasible constraints, so this basis should be found to be feasible
-#if DEBUG_PRINT
- Console.WriteLine("Tableau after all initial variables have been moved into basis:");
- tableau.Dump();
-#endif
- }
-
- // Step 4.1: One vertex has been found. Find all others, too.
- tableau.TraverseVertices(FrameVertices, FrameRays);
-#if DEBUG_PRINT
- Console.WriteLine("Tableau after vertex traversal:");
- tableau.Dump();
-#endif
- }
-
- class LambdaDimension : IVariable {
- readonly int id;
- static int count = 0;
-
- /// <summary>
- /// Return the name of the variable
- /// </summary>
- public string Name {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return this.ToString();
- }
- }
-
- public LambdaDimension() {
- id = count;
- count++;
- }
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "lambda" + id;
- }
- [Pure]
- public object DoVisit(ExprVisitor/*!*/ visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitVariable(this);
- }
- }
-
- /// <summary>
- /// Adds a vertex to the frame of "this" and updates Constraints accordingly, see
- /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
- /// Constraints after the operation; that remains the caller's responsibility (which
- /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
- /// and AddLine before calling SimplifyConstraints).
- /// Assumes Constraints (and the frame fields) to be non-null.
- /// </summary>
- /// <param name="vertex"></param>
- 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:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
-
- FrameVertices.Add(vertex.Clone());
-#if FIXED_DESERIALIZER
- Contract.Assert(Contract.ForAll(vertex.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
-#endif
-
- // We use a new temporary dimension.
- IVariable/*!*/ lambda = new LambdaDimension();
-
- // We change the constraints A*X <= B into
- // A*X + (A*vector - B)*lambda <= A*vector.
- // That means that each row k in A (which corresponds to one LinearConstraint
- // in Constraints) is changed by adding
- // (A*vector - B)[k] * lambda
- // to row k and changing the right-hand side of row k to
- // (A*vector)[k]
- // Note:
- // (A*vector - B)[k]
- // = { vector subtraction is pointwise }
- // (A*vector)[k] - B[k]
- // = { 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 cce.NonNull(Constraints)) {
- Contract.Assert(cc != null);
- Rational d = cc.EvaluateLhs(vertex);
- cc.SetCoefficient(lambda, d - cc.rhs);
- cc.rhs = d;
- }
-
- // We also add the constraints that lambda lies between 0 ...
- LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
- la.SetCoefficient(lambda, Rational.MINUS_ONE);
- la.rhs = Rational.ZERO;
- Constraints.Add(la);
- // ... and 1.
- la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
- la.SetCoefficient(lambda, Rational.ONE);
- la.rhs = Rational.ONE;
- Constraints.Add(la);
-#if DEBUG_PRINT
- Console.WriteLine(" Constraints after addition:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
-
- // Finally, project out the dummy dimension.
- Constraints = Project(lambda, Constraints);
-
-#if DEBUG_PRINT
- Console.WriteLine(" Resulting constraints:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
- }
-
- /// <summary>
- /// Adds a ray to the frame of "this" and updates Constraints accordingly, see
- /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
- /// Constraints after the operation; that remains the caller's responsibility (which
- /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
- /// and AddLine before calling SimplifyConstraints).
- /// Assumes Constraints (and the frame fields) to be non-null.
- /// </summary>
- /// <param name="ray"></param>
- 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:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
-
- FrameRays.Add(ray.Clone());
-#if FIXED_DESERIALIZER
- Contract.Assert(Contract.ForAll(ray.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
-#endif
-
- // We use a new temporary dimension.
- IVariable/*!*/ lambda = new LambdaDimension();
-
- // We change the constraints A*X <= B into
- // A*X - (A*ray)*lambda <= B.
- // That means that each row k in A (which corresponds to one LinearConstraint
- // in Constraints) is changed by subtracting
- // (A*ray)[k] * lambda
- // from row k.
- // Note:
- // (A*ray)[k]
- // = { 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 cce.NonNull(Constraints)) {
- Contract.Assert(cc != null);
- Rational d = cc.EvaluateLhs(ray);
- cc.SetCoefficient(lambda, -d);
- }
-
- // We also add the constraints that lambda is at least 0.
- LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
- la.SetCoefficient(lambda, Rational.MINUS_ONE);
- la.rhs = Rational.ZERO;
- Constraints.Add(la);
-#if DEBUG_PRINT
- Console.WriteLine(" Constraints after addition:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
-
- // Finally, project out the dummy dimension.
- Constraints = Project(lambda, Constraints);
-
-#if DEBUG_PRINT
- Console.WriteLine(" Resulting constraints:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
- }
-
- /// <summary>
- /// Adds a line to the frame of "this" and updates Constraints accordingly, see
- /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
- /// Constraints after the operation; that remains the caller's responsibility (which
- /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
- /// and AddLine before calling SimplifyConstraints).
- /// Assumes Constraints (and the frame fields) to be non-null.
- /// </summary>
- /// <param name="line"></param>
- 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.)
-#if DEBUG_PRINT
- Console.WriteLine("DEBUG: AddLine called on {0}", line);
- Console.WriteLine(" Initial constraints:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
-
- FrameLines.Add(line.Clone());
-#if FIXED_DESERIALIZER
- Contract.Assert(Contract.ForAll(line.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
-#endif
-
- // We use a new temporary dimension.
- IVariable/*!*/ lambda = new LambdaDimension();
-
- // We change the constraints A*X <= B into
- // A*X - (A*line)*lambda <= B.
- // That means that each row k in A (which corresponds to one LinearConstraint
- // in Constraints) is changed by subtracting
- // (A*line)[k] * lambda
- // from row k.
- // Note:
- // (A*line)[k]
- // = { 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 cce.NonNull(Constraints)) {
- Contract.Assert(cc != null);
- Rational d = cc.EvaluateLhs(line);
- cc.SetCoefficient(lambda, -d);
- }
-
-#if DEBUG_PRINT
- Console.WriteLine(" Constraints after addition:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
-
- // Finally, project out the dummy dimension.
- Constraints = Project(lambda, Constraints);
-
-#if DEBUG_PRINT
- Console.WriteLine(" Resulting constraints:");
- foreach (LinearConstraint cc in Constraints) {
- Console.WriteLine(" {0}", cc);
- }
-#endif
- }
-
- 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);
- }
- }
- }
- }
- return dims;
- }
-
- // --------------------------------------------------------------------------------------------------------
- // ------------------ Simplification routines -------------------------------------------------------------
- // --------------------------------------------------------------------------------------------------------
-
- /// <summary>
- /// Uses the Constraints to simplify the frame. See section 3.4.4 of Cousot and Halbwachs.
- /// </summary>
- void SimplifyFrame() {
- Contract.Requires(this.Constraints != null);
- SimplificationStatus[]/*!*/ status;
-
- SimplifyFrameElements(cce.NonNull(FrameVertices), true, Constraints, out status);
- RemoveIrrelevantFrameElements(FrameVertices, status, null);
-
- SimplifyFrameElements(cce.NonNull(FrameRays), false, Constraints, out status);
- RemoveIrrelevantFrameElements(FrameRays, status, FrameLines);
- }
-
- enum SimplificationStatus {
- Irrelevant,
- Relevant,
- More
- };
-
- /// <summary>
- /// For each i, sets status[i] to:
- /// <ul>
- /// <li>Irrelevant if ff[i] is irrelevant</li>
- /// <li>Relevant if ff[i] is irrelevant</li>
- /// <li>More if vertices is true and ray ff[i] can be replaced by a line ff[i]</li>
- /// </ul>
- /// </summary>
- /// <param name="ff"></param>
- /// <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) {
- Contract.Requires(ff != null);
- Contract.Requires(constraints != null);
- Contract.Ensures(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/*!*/)cce.NonNull(ff[i]);
- int cnt = 0;
- 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;
- cnt++;
- }
- }
- if (!vertices && cnt == constraints.Count) {
- status[i] = SimplificationStatus.More;
- } else {
- status[i] = SimplificationStatus.Relevant;
- }
- }
-
- CheckPairSimplifications(sat, status);
- }
-
- /// <summary>
- /// Requires sat.GetLength(0) == status.Length.
- /// </summary>
- /// <param name="sat"></param>
- /// <param name="status"></param>
- 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) {
- continue;
- }
- 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]) {
- // incomparable
- goto NEXT_PAIR;
- }
- } 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]) {
- cmp = -1;
- } else {
- cmp = 1;
- }
- }
- }
- if (cmp <= 0) {
- // sat[i,*] <= sat[j,*] holds, so mark i as irrelevant
- status[i] = SimplificationStatus.Irrelevant;
- goto NEXT_OUTER;
- } else {
- // sat[i,*] >= sat[j,*] holds, so mark j as irrelevant
- status[j] = SimplificationStatus.Irrelevant;
- }
- NEXT_PAIR: {
- }
- }
- NEXT_OUTER: {
- }
- }
- }
-
- 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:
-#if DEBUG_PRINT
- Console.WriteLine("Removing irrelevant {0}: {1}", lines == null ? "vertex" : "ray", ff[j]);
-#endif
- ff.RemoveAt(j);
- break;
- case SimplificationStatus.More:
- System.Diagnostics.Debug.Assert(lines != null);
- FrameElement f = (FrameElement)ff[j];
-#if DEBUG_PRINT
- Console.WriteLine("Changing ray into line: {0}", f);
-#endif
- ff.RemoveAt(j);
- Contract.Assert(lines != null);
- lines.Add(f);
- break;
- }
- }
- }
-
- /// <summary>
- /// Uses the frame to simplify Constraints. See section 3.3.1.2 of Cousot and Halbwachs.
- ///
- /// 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) {
- return;
- }
- Contract.Assume(this.FrameVertices != null);
- Contract.Assume(this.FrameRays != null);
-
- SimplificationStatus[] status = new SimplificationStatus[Constraints.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++) {
- status[i] = SimplificationStatus.Relevant;
- 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/*!*/)cce.NonNull(FrameVertices[j]);
- if (lc.IsSaturatedBy(vertex, true)) {
- sat[i, j] = true;
- cnt++;
- }
- }
- 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/*!*/)cce.NonNull(FrameRays[j]);
- if (lc.IsSaturatedBy(ray, false)) {
- sat[i, FrameVertices.Count + j] = true;
- cnt++;
- }
- }
- if (cnt == feCount) {
- status[i] = SimplificationStatus.More;
- } 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
- System.Diagnostics.Debug.Assert(lc.Relation == LinearConstraint.ConstraintRelation.LE);
- }
- }
-
- CheckPairSimplifications(sat, status);
-
- // Finally, make the changes to the list of constraints
- for (int i = Constraints.Count - 1; 0 <= i; i--) {
- switch (status[i]) {
- case SimplificationStatus.Relevant:
- break;
- case SimplificationStatus.Irrelevant:
-#if DEBUG_PRINT
- Console.WriteLine("Removing irrelevant constraint: {0}", Constraints[i]);
-#endif
- Constraints.RemoveAt(i);
- break;
- case SimplificationStatus.More:
- 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
- LinearConstraint lcEq = lc.ChangeRelation(LinearConstraint.ConstraintRelation.EQ);
- Constraints[i] = lcEq;
- }
- break;
- }
- }
-
- foreach (LinearConstraint/*!*/ lc in Constraints) {
- Contract.Assert(lc != null);
- lc.Normalize();
- }
- }
-
- // --------------------------------------------------------------------------------------------------------
- // ------------------ Cloning routines --------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------------------
-
- 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) {
- 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) {
- 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);
- }
- }
-
- Console.WriteLine(" FrameRays:");
- if (FrameRays == null) {
- Console.WriteLine(" <null>");
- } else {
- foreach (FrameElement fe in FrameRays) {
- Console.WriteLine(" {0}", fe);
- }
- }
-
- Console.WriteLine(" FrameLines:");
- if (FrameLines == null) {
- Console.WriteLine(" <null>");
- } else {
- foreach (FrameElement fe in FrameLines) {
- Console.WriteLine(" {0}", fe);
- }
- }
- }
-
- 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 TestVariable(string/*!*/ name) {
- Contract.Requires(name != null);
- this.name = name;
- }
- [Pure]
- public object DoVisit(ExprVisitor/*!*/ visitor) {
- //Contract.Requires(visitor != null);
- return visitor.VisitVariable(this);
- }
- }
-
- 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();
-
- 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();
- }
-
- /// <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();
- }
-
- 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(s2);
- lcs.Dump();
-
- lcs.AddRay(r0);
- lcs.Dump();
-
- lcs.AddRay(r1);
- lcs.Dump();
-
- lcs.AddLine(d0);
- lcs.Dump();
-
- lcs.SimplifyConstraints();
- lcs.Dump();
-
-#if LATER
- lcs.GenerateFrameFromConstraints(); // should give us back the original frame...
-#endif
- }
- }
+//-----------------------------------------------------------------------------
+//
+// 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 System.Diagnostics.Contracts;
+ using Microsoft.Basetypes;
+
+ using IMutableSet = Microsoft.Boogie.GSet<object>;
+ using ISet = Microsoft.Boogie.GSet<object>;
+ using HashSet = Microsoft.Boogie.GSet<object>;
+
+ /// <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;
+ [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
+ // FrameLines is mentioned in FrameDimensions.
+ // 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) {
+ 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 {
+ System.Diagnostics.Debug.Assert(FrameVertices != null);
+ System.Diagnostics.Debug.Assert(FrameRays != null);
+ System.Diagnostics.Debug.Assert(FrameLines != null);
+
+ foreach (LinearConstraint/*!*/ cc in Constraints) {
+ Contract.Assert(cc != null);
+#if FIXED_DESERIALIZER
+ 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 }) {
+ Contract.Assert(FrameComponent != null);
+ foreach (FrameElement fe in FrameComponent) {
+ if (fe == null)
+ continue;
+#if FIXED_DESERIALIZER
+ Contract.Assert(Contract.ForAll(fe.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
+#endif
+ }
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Constructors ------------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Creates a LinearConstraintSystem representing the bottom element, that is, representing
+ /// an unsatisfiable system of constraints.
+ /// </summary>
+ [NotDelayed]
+ public LinearConstraintSystem() {
+ FrameDimensions = new HashSet /*IVariable!*/ ();
+ //:base();
+ CheckInvariant();
+ }
+
+ /// <summary>
+ /// Constructs a linear constraint system with constraints "cs".
+ /// The constructor captures all constraints in "cs".
+ /// </summary>
+ /// <param name="cs"></param>
+ [NotDelayed]
+ public LinearConstraintSystem(ArrayList /*LinearConstraint!*//*!*/ cs) {
+ Contract.Requires(cs != null);
+#if BUG_159_HAS_BEEN_FIXED
+ Contract.Requires(Contract.ForAll(cs) , cc=> cc.coefficients.Count != 0);
+#endif
+
+ ArrayList constraints = new ArrayList /*LinearConstraint!*/ (cs.Count);
+ 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();
+
+ GenerateFrameFromConstraints();
+ SimplifyConstraints();
+ CheckInvariant();
+#if DEBUG_PRINT
+ Console.WriteLine("LinearConstraintSystem: constructor produced:");
+ Dump();
+#endif
+ }
+
+ /// <summary>
+ /// Constructs a linear constraint system corresponding to given vertex. This constructor
+ /// is only used in the test harness--it is not needed for abstract interpretation.
+ /// </summary>
+ /// <param name="v"></param>
+ [NotDelayed]
+ 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) {
+ Contract.Assert(dim != null);
+ LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
+ lc.SetCoefficient(dim, Rational.ONE);
+ lc.rhs = v[dim];
+ constraints.Add(lc);
+ }
+ FrameDimensions = frameDims;
+ Constraints = constraints;
+
+ ArrayList /*FrameElement*/ frameVertices = new ArrayList /*FrameElement*/ ();
+ frameVertices.Add(v);
+ FrameVertices = frameVertices;
+
+ FrameRays = new ArrayList /*FrameElement*/ ();
+ FrameLines = new ArrayList /*FrameElement*/ ();
+
+ //:base();
+ CheckInvariant();
+ }
+
+ void ChangeIntoBottom() {
+ Constraints = null;
+ FrameVertices = null;
+ FrameRays = null;
+ FrameLines = null;
+ FrameDimensions.Clear(); // no implicit lines
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Public operations and their support routines ----------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ public bool IsBottom() {
+ return Constraints == null;
+ }
+
+ public bool IsTop() {
+ return Constraints != null && Constraints.Count == 0;
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ if (Constraints == null) {
+ return "<bottom>";
+ } else if (Constraints.Count == 0) {
+ return "<top>";
+ } else {
+ string z = null;
+ foreach (LinearConstraint/*!*/ lc in Constraints) {
+ Contract.Assert(lc != null);
+ string s = lc.ToString();
+ if (z == null) {
+ z = s;
+ } else {
+ z += " AND " + s;
+ }
+ }
+ Contract.Assert(z != null);
+ return z;
+ }
+ }
+
+
+ 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>
+ /// Note: This method requires that all dimensions are of type Variable, something that's
+ /// not required elsewhere in this class.
+ /// </summary>
+ /// <returns></returns>
+ public IExpr/*!*/ ConvertToExpression(ILinearExprFactory/*!*/ factory) {
+ Contract.Requires(factory != null);
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ if (this.Constraints == null) {
+ return factory.False;
+ }
+ if (this.Constraints.Count == 0) {
+ return factory.True;
+ }
+
+ IExpr result = null;
+ foreach (LinearConstraint/*!*/ lc in Constraints) {
+ Contract.Assert(lc != null);
+ IExpr conjunct = lc.ConvertToExpression(factory);
+ result = (result == null) ? conjunct : (IExpr)factory.And(conjunct, result);
+ }
+ Contract.Assert(result != null);
+ return result;
+ }
+
+
+ /* IsSubset(): determines if 'lcs' is a subset of 'this'
+ * -- See Cousot/Halbwachs 1978, section
+ */
+ public bool IsSubset(LinearConstraintSystem/*!*/ lcs) {
+ Contract.Requires(lcs != null);
+ if (lcs.IsBottom()) {
+ return true;
+ } else if (this.IsBottom()) {
+ return false;
+#if DEBUG
+#else
+ } else if (this.IsTop()) { // optimization -- this case not needed for correctness
+ return true;
+ } else if (lcs.IsTop()) { // optimization -- this case not needed for correctness
+ return false;
+#endif
+ } else {
+ // phase 0: check if frame dimensions are a superset of the constraint dimensions
+ ISet /*IVariable!*//*!*/ frameDims = lcs.GetDefinedDimensions();
+ Contract.Assert(frameDims != null);
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: IsSubset:");
+ Console.WriteLine(" --- this:");
+ this.Dump();
+ Console.WriteLine(" --- lcs:");
+ lcs.Dump();
+ Console.WriteLine(" ---");
+#endif
+ 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 (!Contract.ForAll(cc.GetDefinedDimensionsGeneric(), var => frameDims.Contains(var))) {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 0 subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+
+ // phase 1: check frame vertices against each constraint...
+ 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 DEBUG_PRINT
+ Console.WriteLine(" ---> phase 1a subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ } else {
+ if (!(q == cc.rhs)) {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 1b subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+ }
+
+ // phase 2: check frame rays against each constraint...
+ // To check if a ray "r" falls within a constraint "cc", we add the vector "r" to
+ // any point "p" on the side of the half-space or plane described by constraint, and
+ // then check if the resulting point satisfies the constraint. That is, we check (for
+ // an inequality constraint with coefficients a1,a2,...,an and right-hand side
+ // constant C):
+ // a1*(r1+p1) + a2*(r2+p2) + ... + an*(rn+pn) <= C
+ // Equivalently:
+ // a1*r1 + a2*r2 + ... + an*rn + a1*p1 + a2*p2 + ... + an*pn <= C
+ // To find a point "p", we can pick out a coordinate, call it 1, with a non-zero
+ // coefficient in the constraint, and then choose "p" as the point that has the
+ // value C/a1 in coordinate 1 and has 0 in all other coordinates. We then check:
+ // a1*r1 + a2*r2 + ... + an*rn + a1*(C/a1) + a2*0 + ... + an*0 <= C
+ // which simplifies to:
+ // a1*r1 + a2*r2 + ... + an*rn + C <= C
+ // which in turn simplifies to:
+ // a1*r1 + a2*r2 + ... + an*rn <= 0
+ // If the constraint is an equality constraint, we simply replace "<=" with "=="
+ // above.
+ 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) {
+ 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 DEBUG_PRINT
+ Console.WriteLine(" ---> phase 2a subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ } else {
+ if (q.IsNonZero) {
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> phase 2b subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+ }
+
+ // phase 3: check frame lines against each constraint...
+ // To check if a line "L" falls within a constraint "cc", we check if both the
+ // vector "L" and "-L", interpreted as rays, fall within the constraint. From
+ // the discussion above, this means we check the following two properties:
+ // a1*L1 + a2*L2 + ... + an*Ln <= 0 (*)
+ // a1*(-L1) + a2*(-L2) + ... + an*(-Ln) <= 0
+ // The second of these lines can be rewritten as:
+ // - a1*L1 - a2*L2 - ... - an*Ln <= 0
+ // which is equivalent to:
+ // -1 * (a1*L1 + a2*L2 + ... + an*Ln) <= 0
+ // Multiplying both sides by -1 and flipping the direction of the inequality,
+ // we have:
+ // a1*L1 + a2*L2 + ... + an*Ln >= 0 (**)
+ // 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 cce.NonNull(lcs.FrameLines)) {
+ Contract.Assert(line != null);
+ System.Diagnostics.Debug.Assert(line != null, "encountered a null line...");
+ 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 DEBUG_PRINT
+ Console.WriteLine(" ---> phase 3 subset violated, return false from IsSubset");
+#endif
+ return false;
+ }
+ }
+ }
+
+#if DEBUG_PRINT
+ Console.WriteLine(" ---> IsSubset returns true");
+#endif
+ return true;
+ }
+
+ 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);
+ return new LinearConstraintSystem(clist);
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Join(LinearConstraintSystem lcs)
+ {
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Join");
+ Console.WriteLine("Join: this=");
+ Dump();
+ Console.WriteLine("Join: lcs=");
+ lcs.Dump();
+ LinearConstraintSystem z = JoinX(lcs);
+ Console.WriteLine("----------Join------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Join: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+ /// <summary>
+ /// The join is computed as described in section 4.4 in Cousot and Halbwachs.
+ /// </summary>
+ /// <param name="lcs"></param>
+ /// <returns></returns>
+#if DEBUG_PRINT
+ public LinearConstraintSystem JoinX(LinearConstraintSystem lcs) {
+#else
+ public LinearConstraintSystem/*!*/ Join(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*/ ());
+ } else {
+ LinearConstraintSystem/*!*/ z;
+ // Start from the "larger" of the two frames (this is just a heuristic measure intended
+ // to save work).
+ 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 = cce.NonNull(lcs.Clone());
+ lcs = this;
+ } else {
+ z = cce.NonNull(this.Clone());
+ }
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: LinearConstraintSystem.Join ---------------");
+ Console.WriteLine("z:");
+ z.Dump();
+ Console.WriteLine("lcs:");
+ lcs.Dump();
+#endif
+
+ // Start by explicating the implicit lines of z for the dimensions dims(lcs)-dims(z).
+ 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.
+ Contract.Assume(z.FrameLines != null);
+ z.FrameLines.Add(line);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After explicating line: {0}", line);
+ z.Dump();
+#endif
+ }
+ }
+
+ // Now, the vertices, rays, and lines can be added.
+ 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) {
+ 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) {
+ Contract.Assert(l != null);
+ z.AddLine(l);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After adding line: {0}", l);
+ z.Dump();
+#endif
+ }
+ // also add to z the implicit lines of lcs
+ 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);
+ z.AddLine(line);
+#if DEBUG_PRINT
+ Console.WriteLine("Join: After adding lcs's implicit line: {0}", line);
+ z.Dump();
+#endif
+ }
+ }
+
+ z.SimplifyFrame();
+ z.SimplifyConstraints();
+ z.CheckInvariant();
+#if DEBUG_PRINT
+ Console.WriteLine("Join: Returning z:");
+ z.Dump();
+ Console.WriteLine("----------------------------------------");
+#endif
+ return z;
+ }
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Widen(LinearConstraintSystem lcs)
+ {
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Widen");
+ Console.WriteLine("Widen: this=");
+ Dump();
+ Console.WriteLine("Widen: lcs=");
+ lcs.Dump();
+ LinearConstraintSystem z = WidenX(lcs);
+ Console.WriteLine("----------Widen------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Widen: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem WidenX(LinearConstraintSystem lcs){
+#else
+ 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*/ ();
+ 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()) {
+ // (Can this ever occur in the stable state of a LinearConstraintSystem? --KRML)
+ // constraint is unaffected by the frame components
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: --Adding it!");
+#endif
+ newConstraints.Add(cc);
+ continue;
+ }
+
+ // PHASE I: verify constraints against all frame vertices...
+
+ foreach (FrameElement/*!*/ vertex in cce.NonNull(lcs.FrameVertices)) {
+ Contract.Assert(vertex != null);
+ Rational lhs = cc.EvaluateLhs(vertex);
+ if (lhs > cc.rhs) {
+ // the vertex does not satisfy the inequality <=
+ 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 {
+ // ... but it does satisfy the inequality >=
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out <= because of vertex: {0}", vertex);
+#endif
+ cc = cc.ChangeRelationToAtLeast();
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with constraint: {0}", cc);
+#endif
+ }
+ } 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);
+#endif
+ cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE);
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with contraint: {0}", cc);
+#endif
+ }
+ }
+
+ // PHASE II: verify constraints against all frame rays...
+
+ 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) {
+ // the ray does not satisfy the inequality <=
+ 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 {
+ // ... but it does satisfy the inequality >=
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out <= because of ray: {0}", ray);
+#endif
+ cc = cc.ChangeRelationToAtLeast();
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with contraint: {0}", cc);
+#endif
+ }
+ } 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);
+#endif
+ cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE);
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: left with constraint: {0}", cc);
+#endif
+ }
+ }
+
+ // PHASE III: verify constraints against all frame lines...
+
+ 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) {
+ // The line satisfies neither the inequality <= nor the equality ==
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: throwing out because of line: {0}", line);
+#endif
+ goto CHECK_NEXT_CONSTRAINT;
+ }
+ }
+
+ // constraint has been verified, so add to new constraint system
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: --Adding it!");
+#endif
+ newConstraints.Add(cc);
+
+ CHECK_NEXT_CONSTRAINT: {
+ }
+#if DEBUG_PRINT
+ Console.WriteLine("Widen checking: done with that constraint");
+#endif
+ }
+
+ return new LinearConstraintSystem(newConstraints);
+ }
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem Project(IVariable/*!*/ dim){
+Contract.Requires(dim != null);
+ Console.WriteLine("===================================================================================");
+ Console.WriteLine("DEBUG: Project(dim={0})", dim);
+ Console.WriteLine("Project: this=");
+ Dump();
+ LinearConstraintSystem z = ProjectX(dim);
+ Console.WriteLine("----------Project------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Project: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem ProjectX(IVariable/*!*/ dim){Contract.Requires(dim != null);Contract.Requires(this.Constraints != null);
+#else
+ public LinearConstraintSystem/*!*/ Project(IVariable/*!*/ dim) {
+ Contract.Requires(dim != null);
+ Contract.Requires(this.Constraints != null);
+ Contract.Ensures(Contract.Result<LinearConstraintSystem>() != null);
+#endif
+
+
+ ArrayList /*LinearConstraint!*//*!*/ cc = Project(dim, Constraints);
+ Contract.Assert(cc != null);
+ return new LinearConstraintSystem(cc);
+ }
+
+#if DEBUG_PRINT
+ 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=");
+ Dump();
+ LinearConstraintSystem z = RenameX(oldName, newName);
+ Console.WriteLine("----------Rename------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ Console.WriteLine("Rename: result=");
+ z.Dump();
+ Console.WriteLine("===================================================================================");
+ return z;
+ }
+#endif
+
+#if DEBUG_PRINT
+ public LinearConstraintSystem RenameX(IVariable/*!*/ oldName, IVariable/*!*/ newName){Contract.Requires(oldName != null);Contract.Requires(newName != null);
+#else
+ 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) {
+ 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;
+ Contract.Assert(dims != null);
+ if (!dims.Contains(oldName)) {
+ return this;
+ }
+
+ LinearConstraintSystem z = new LinearConstraintSystem();
+ 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 cce.NonNull(this.Constraints)) {
+ Contract.Assert(lc != null);
+ z.Constraints.Add(lc.Rename(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) {
+ 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);
+ return z;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ support routines --------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Returns a set of constraints that is the given set of constraints with dimension "dim"
+ /// projected out. See Cousot and Halbwachs, section 3.3.1.1.
+ /// </summary>
+ /// <param name="dim"></param>
+ /// <param name="constraints"></param>
+ /// <returns></returns>
+ 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) {
+ Contract.Assert(cc != null);
+ Rational coeff = cc[dim];
+ 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) {
+ eq.Add(cc);
+ } else if (coeff.IsNegative) {
+ negative.Add(cc);
+ } else {
+ System.Diagnostics.Debug.Assert(coeff.IsPositive);
+ positive.Add(cc);
+ }
+ }
+
+ 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 }) {
+ 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()) {
+ lc.RemoveDimension(dim);
+ final.Add(lc);
+ } else {
+ System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
+ }
+ }
+ }
+ } else {
+ // Consider all pairs of constraints with (negative,positive) coefficients of "dim".
+ foreach (LinearConstraint/*!*/ cn in negative) {
+ Contract.Assert(cn != null);
+ Rational dn = -cn[dim];
+ System.Diagnostics.Debug.Assert(dn.IsNonNegative);
+ 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()) {
+ lc.RemoveDimension(dim);
+ final.Add(lc);
+ } else {
+ System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
+ }
+ }
+ }
+ }
+
+ return final;
+ }
+
+ /// <summary>
+ /// Initializes FrameVertices, FrameRays, FrameLines, and FrameDimensions, see
+ /// Cousot and Halbwachs, section 3.4. Any previous values of these fields are
+ /// ignored and overwritten.
+ ///
+ /// If the set of Constraints is unsatisfiable, then "this" is changed into Bottom.
+ /// </summary>
+ 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 ---");
+ Console.WriteLine("Constraints:");
+ foreach (LinearConstraint cc in Constraints)
+ {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ SimplexTableau tableau = new SimplexTableau(Constraints);
+#if DEBUG_PRINT
+ Console.WriteLine("Initial tableau:");
+ tableau.Dump();
+#endif
+ FrameDimensions = tableau.GetDimensions();
+#if DEBUG_PRINT
+ Console.WriteLine("Dimensions:");
+ foreach (object dim in FrameDimensions)
+ {
+ Console.Write(" {0}", dim);
+ }
+ Console.WriteLine();
+#endif
+
+ // Step 3 and 2: Put as many initial variables as possible into basis, then check if
+ // we reached a feasible basis
+ tableau.AddInitialVarsToBasis();
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after Step 3:");
+ tableau.Dump();
+#endif
+ if (!tableau.IsFeasibleBasis) {
+ // The polyhedron is empty (according to Cousot and Halbwachs)
+ ChangeIntoBottom();
+ return;
+ }
+
+ FrameVertices = new ArrayList /*FrameElement*/ ();
+ FrameRays = new ArrayList /*FrameElement*/ ();
+ FrameLines = new ArrayList /*FrameElement*/ ();
+ if (FrameDimensions.Count == 0) {
+ // top element
+ return;
+ }
+
+ 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 {
+ // 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 = cce.NonNull((ArrayList/*!*/ /*LinearConstraint*/)Constraints.Clone());
+ tableau.ProduceLines(FrameLines, moreConstraints);
+ tableau = new SimplexTableau(moreConstraints);
+#if DEBUG_PRINT
+ Console.WriteLine("Lines produced:");
+ foreach (FrameElement line in FrameLines)
+ {
+ Console.WriteLine(" {0}", line);
+ }
+ Console.WriteLine("The new list of constraints is:");
+ foreach (LinearConstraint c in moreConstraints)
+ {
+ Console.WriteLine(" {0}", c);
+ }
+ Console.WriteLine("Tableau after producing lines in Step 4.2:");
+ tableau.Dump();
+#endif
+
+ // Repeat step 3 for the new tableau.
+ // Since the new tableau contains no lines, the following call should cause all initial
+ // variables to be in basis (see step 4.2 in section 3.4.3 of Cousot and Halbwachs).
+ tableau.AddInitialVarsToBasis();
+ System.Diagnostics.Debug.Assert(tableau.AllInitialVarsInBasis);
+ System.Diagnostics.Debug.Assert(tableau.IsFeasibleBasis); // the new tableau represents a set of feasible constraints, so this basis should be found to be feasible
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after all initial variables have been moved into basis:");
+ tableau.Dump();
+#endif
+ }
+
+ // Step 4.1: One vertex has been found. Find all others, too.
+ tableau.TraverseVertices(FrameVertices, FrameRays);
+#if DEBUG_PRINT
+ Console.WriteLine("Tableau after vertex traversal:");
+ tableau.Dump();
+#endif
+ }
+
+ class LambdaDimension : IVariable {
+ readonly int id;
+ static int count = 0;
+
+ /// <summary>
+ /// Return the name of the variable
+ /// </summary>
+ public string Name {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return this.ToString();
+ }
+ }
+
+ public LambdaDimension() {
+ id = count;
+ count++;
+ }
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "lambda" + id;
+ }
+ [Pure]
+ public object DoVisit(ExprVisitor/*!*/ visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.VisitVariable(this);
+ }
+ }
+
+ /// <summary>
+ /// Adds a vertex to the frame of "this" and updates Constraints accordingly, see
+ /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
+ /// Constraints after the operation; that remains the caller's responsibility (which
+ /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
+ /// and AddLine before calling SimplifyConstraints).
+ /// Assumes Constraints (and the frame fields) to be non-null.
+ /// </summary>
+ /// <param name="vertex"></param>
+ 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:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ FrameVertices.Add(vertex.Clone());
+#if FIXED_DESERIALIZER
+ Contract.Assert(Contract.ForAll(vertex.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
+#endif
+
+ // We use a new temporary dimension.
+ IVariable/*!*/ lambda = new LambdaDimension();
+
+ // We change the constraints A*X <= B into
+ // A*X + (A*vector - B)*lambda <= A*vector.
+ // That means that each row k in A (which corresponds to one LinearConstraint
+ // in Constraints) is changed by adding
+ // (A*vector - B)[k] * lambda
+ // to row k and changing the right-hand side of row k to
+ // (A*vector)[k]
+ // Note:
+ // (A*vector - B)[k]
+ // = { vector subtraction is pointwise }
+ // (A*vector)[k] - B[k]
+ // = { 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 cce.NonNull(Constraints)) {
+ Contract.Assert(cc != null);
+ Rational d = cc.EvaluateLhs(vertex);
+ cc.SetCoefficient(lambda, d - cc.rhs);
+ cc.rhs = d;
+ }
+
+ // We also add the constraints that lambda lies between 0 ...
+ LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ la.SetCoefficient(lambda, Rational.MINUS_ONE);
+ la.rhs = Rational.ZERO;
+ Constraints.Add(la);
+ // ... and 1.
+ la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ la.SetCoefficient(lambda, Rational.ONE);
+ la.rhs = Rational.ONE;
+ Constraints.Add(la);
+#if DEBUG_PRINT
+ Console.WriteLine(" Constraints after addition:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ // Finally, project out the dummy dimension.
+ Constraints = Project(lambda, Constraints);
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Resulting constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Adds a ray to the frame of "this" and updates Constraints accordingly, see
+ /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
+ /// Constraints after the operation; that remains the caller's responsibility (which
+ /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
+ /// and AddLine before calling SimplifyConstraints).
+ /// Assumes Constraints (and the frame fields) to be non-null.
+ /// </summary>
+ /// <param name="ray"></param>
+ 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:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ FrameRays.Add(ray.Clone());
+#if FIXED_DESERIALIZER
+ Contract.Assert(Contract.ForAll(ray.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
+#endif
+
+ // We use a new temporary dimension.
+ IVariable/*!*/ lambda = new LambdaDimension();
+
+ // We change the constraints A*X <= B into
+ // A*X - (A*ray)*lambda <= B.
+ // That means that each row k in A (which corresponds to one LinearConstraint
+ // in Constraints) is changed by subtracting
+ // (A*ray)[k] * lambda
+ // from row k.
+ // Note:
+ // (A*ray)[k]
+ // = { 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 cce.NonNull(Constraints)) {
+ Contract.Assert(cc != null);
+ Rational d = cc.EvaluateLhs(ray);
+ cc.SetCoefficient(lambda, -d);
+ }
+
+ // We also add the constraints that lambda is at least 0.
+ LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
+ la.SetCoefficient(lambda, Rational.MINUS_ONE);
+ la.rhs = Rational.ZERO;
+ Constraints.Add(la);
+#if DEBUG_PRINT
+ Console.WriteLine(" Constraints after addition:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ // Finally, project out the dummy dimension.
+ Constraints = Project(lambda, Constraints);
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Resulting constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Adds a line to the frame of "this" and updates Constraints accordingly, see
+ /// Cousot and Halbwachs, section 3.3.1.1. However, this method does not simplify
+ /// Constraints after the operation; that remains the caller's responsibility (which
+ /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
+ /// and AddLine before calling SimplifyConstraints).
+ /// Assumes Constraints (and the frame fields) to be non-null.
+ /// </summary>
+ /// <param name="line"></param>
+ 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.)
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: AddLine called on {0}", line);
+ Console.WriteLine(" Initial constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ FrameLines.Add(line.Clone());
+#if FIXED_DESERIALIZER
+ Contract.Assert(Contract.ForAll(line.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
+#endif
+
+ // We use a new temporary dimension.
+ IVariable/*!*/ lambda = new LambdaDimension();
+
+ // We change the constraints A*X <= B into
+ // A*X - (A*line)*lambda <= B.
+ // That means that each row k in A (which corresponds to one LinearConstraint
+ // in Constraints) is changed by subtracting
+ // (A*line)[k] * lambda
+ // from row k.
+ // Note:
+ // (A*line)[k]
+ // = { 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 cce.NonNull(Constraints)) {
+ Contract.Assert(cc != null);
+ Rational d = cc.EvaluateLhs(line);
+ cc.SetCoefficient(lambda, -d);
+ }
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Constraints after addition:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+
+ // Finally, project out the dummy dimension.
+ Constraints = Project(lambda, Constraints);
+
+#if DEBUG_PRINT
+ Console.WriteLine(" Resulting constraints:");
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+#endif
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+ return dims;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Simplification routines -------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// Uses the Constraints to simplify the frame. See section 3.4.4 of Cousot and Halbwachs.
+ /// </summary>
+ void SimplifyFrame() {
+ Contract.Requires(this.Constraints != null);
+ SimplificationStatus[]/*!*/ status;
+
+ SimplifyFrameElements(cce.NonNull(FrameVertices), true, Constraints, out status);
+ RemoveIrrelevantFrameElements(FrameVertices, status, null);
+
+ SimplifyFrameElements(cce.NonNull(FrameRays), false, Constraints, out status);
+ RemoveIrrelevantFrameElements(FrameRays, status, FrameLines);
+ }
+
+ enum SimplificationStatus {
+ Irrelevant,
+ Relevant,
+ More
+ };
+
+ /// <summary>
+ /// For each i, sets status[i] to:
+ /// <ul>
+ /// <li>Irrelevant if ff[i] is irrelevant</li>
+ /// <li>Relevant if ff[i] is irrelevant</li>
+ /// <li>More if vertices is true and ray ff[i] can be replaced by a line ff[i]</li>
+ /// </ul>
+ /// </summary>
+ /// <param name="ff"></param>
+ /// <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) {
+ Contract.Requires(ff != null);
+ Contract.Requires(constraints != null);
+ Contract.Ensures(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/*!*/)cce.NonNull(ff[i]);
+ int cnt = 0;
+ 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;
+ cnt++;
+ }
+ }
+ if (!vertices && cnt == constraints.Count) {
+ status[i] = SimplificationStatus.More;
+ } else {
+ status[i] = SimplificationStatus.Relevant;
+ }
+ }
+
+ CheckPairSimplifications(sat, status);
+ }
+
+ /// <summary>
+ /// Requires sat.GetLength(0) == status.Length.
+ /// </summary>
+ /// <param name="sat"></param>
+ /// <param name="status"></param>
+ 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) {
+ continue;
+ }
+ 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]) {
+ // incomparable
+ goto NEXT_PAIR;
+ }
+ } 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]) {
+ cmp = -1;
+ } else {
+ cmp = 1;
+ }
+ }
+ }
+ if (cmp <= 0) {
+ // sat[i,*] <= sat[j,*] holds, so mark i as irrelevant
+ status[i] = SimplificationStatus.Irrelevant;
+ goto NEXT_OUTER;
+ } else {
+ // sat[i,*] >= sat[j,*] holds, so mark j as irrelevant
+ status[j] = SimplificationStatus.Irrelevant;
+ }
+ NEXT_PAIR: {
+ }
+ }
+ NEXT_OUTER: {
+ }
+ }
+ }
+
+ 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:
+#if DEBUG_PRINT
+ Console.WriteLine("Removing irrelevant {0}: {1}", lines == null ? "vertex" : "ray", ff[j]);
+#endif
+ ff.RemoveAt(j);
+ break;
+ case SimplificationStatus.More:
+ System.Diagnostics.Debug.Assert(lines != null);
+ FrameElement f = (FrameElement)ff[j];
+#if DEBUG_PRINT
+ Console.WriteLine("Changing ray into line: {0}", f);
+#endif
+ ff.RemoveAt(j);
+ Contract.Assert(lines != null);
+ lines.Add(f);
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Uses the frame to simplify Constraints. See section 3.3.1.2 of Cousot and Halbwachs.
+ ///
+ /// 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) {
+ return;
+ }
+ Contract.Assume(this.FrameVertices != null);
+ Contract.Assume(this.FrameRays != null);
+
+ SimplificationStatus[] status = new SimplificationStatus[Constraints.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++) {
+ status[i] = SimplificationStatus.Relevant;
+ 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/*!*/)cce.NonNull(FrameVertices[j]);
+ if (lc.IsSaturatedBy(vertex, true)) {
+ sat[i, j] = true;
+ cnt++;
+ }
+ }
+ 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/*!*/)cce.NonNull(FrameRays[j]);
+ if (lc.IsSaturatedBy(ray, false)) {
+ sat[i, FrameVertices.Count + j] = true;
+ cnt++;
+ }
+ }
+ if (cnt == feCount) {
+ status[i] = SimplificationStatus.More;
+ } 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
+ System.Diagnostics.Debug.Assert(lc.Relation == LinearConstraint.ConstraintRelation.LE);
+ }
+ }
+
+ CheckPairSimplifications(sat, status);
+
+ // Finally, make the changes to the list of constraints
+ for (int i = Constraints.Count - 1; 0 <= i; i--) {
+ switch (status[i]) {
+ case SimplificationStatus.Relevant:
+ break;
+ case SimplificationStatus.Irrelevant:
+#if DEBUG_PRINT
+ Console.WriteLine("Removing irrelevant constraint: {0}", Constraints[i]);
+#endif
+ Constraints.RemoveAt(i);
+ break;
+ case SimplificationStatus.More:
+ 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
+ LinearConstraint lcEq = lc.ChangeRelation(LinearConstraint.ConstraintRelation.EQ);
+ Constraints[i] = lcEq;
+ }
+ break;
+ }
+ }
+
+ foreach (LinearConstraint/*!*/ lc in Constraints) {
+ Contract.Assert(lc != null);
+ lc.Normalize();
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ // ------------------ Cloning routines --------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ 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) {
+ 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) {
+ 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);
+ }
+ }
+
+ Console.WriteLine(" FrameRays:");
+ if (FrameRays == null) {
+ Console.WriteLine(" <null>");
+ } else {
+ foreach (FrameElement fe in FrameRays) {
+ Console.WriteLine(" {0}", fe);
+ }
+ }
+
+ Console.WriteLine(" FrameLines:");
+ if (FrameLines == null) {
+ Console.WriteLine(" <null>");
+ } else {
+ foreach (FrameElement fe in FrameLines) {
+ Console.WriteLine(" {0}", fe);
+ }
+ }
+ }
+
+ 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 TestVariable(string/*!*/ name) {
+ Contract.Requires(name != null);
+ this.name = name;
+ }
+ [Pure]
+ public object DoVisit(ExprVisitor/*!*/ visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.VisitVariable(this);
+ }
+ }
+
+ 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();
+
+ 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();
+ }
+
+ /// <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();
+ }
+
+ 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(s2);
+ lcs.Dump();
+
+ lcs.AddRay(r0);
+ lcs.Dump();
+
+ lcs.AddRay(r1);
+ lcs.Dump();
+
+ lcs.AddLine(d0);
+ 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 06c0f483..6c914a54 100644
--- a/Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs
+++ b/Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs
@@ -1,762 +1,762 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.AbstractInterpretationFramework {
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
- using Microsoft.Basetypes;
-
- using ISet = Microsoft.Boogie.GSet<object>;
- using HashSet = Microsoft.Boogie.GSet<object>;
-
- /// <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");
-
- private class PolyhedraLatticeElement : Element {
-
- public LinearConstraintSystem/*!*/ lcs;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(lcs != null);
- }
-
-
- /// <summary>
- /// Creates a top or bottom elements, according to parameter "top".
- /// </summary>
- public PolyhedraLatticeElement(bool top) {
- if (top) {
- lcs = new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ());
- } else {
- lcs = new LinearConstraintSystem();
- }
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return lcs.ToString();
- }
-
- 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() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
- return lcs.FreeVariables();
- }
-
- public PolyhedraLatticeElement(LinearConstraintSystem/*!*/ lcs) {
- Contract.Requires(lcs != null);
- this.lcs = lcs;
- }
-
- public override Element/*!*/ Clone() {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new PolyhedraLatticeElement(cce.NonNull(lcs.Clone()));
- }
-
- } // class
-
- 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) {
- 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 {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new PolyhedraLatticeElement(true);
- }
- }
-
- public override Element/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
-
- 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) {
- //Contract.Requires(element != null);
- PolyhedraLatticeElement e = (PolyhedraLatticeElement)element;
- return e.lcs.IsTop();
- }
-
-
- /// <summary>
- /// Returns true iff a is a subset of this.
- /// </summary>
- /// <param name="a"></param>
- /// <returns></returns>
- protected override bool AtMost(Element/*!*/ first, Element/*!*/ second) // this <= that
- {
- //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) {
- //Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return ((PolyhedraLatticeElement)e).lcs.ToString();
- }
-
- 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) {
- //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();
- return result;
- }
-
-
- 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) {
- //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) {
- //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()) {
- return ple;
- }
- return new PolyhedraLatticeElement(ple.lcs.Project(variable));
- }
-
-
- 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()) {
- return ple;
- }
- return new PolyhedraLatticeElement(ple.lcs.Rename(oldName, newName));
- }
-
- 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 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;
- }
- }
-
- 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) {
- //Contract.Requires(visitor != null);
- return visitor.VisitFunApp(this);
- }
-
- 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);
- }
- }
-
- 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) {
- //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) {
- //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()) {
- return ple;
- }
- LinearCondition le = LinearExpressionBuilder.AsCondition(expr);
- if (le != null) {
- // update the polyhedron according to the linear expression
- 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);
-
- return new PolyhedraLatticeElement(newLcs);
- }
- return ple;
- }
-
- } // 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>
- /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ
- /// </summary>
- /// <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 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 */
- {
- return GetCond(e, true);
- }
-
- 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;
- 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;
- }
- 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;
- }
-
- public static LinearConstraint MakeConstraint(LinearExpr/*!*/ le0, LinearExpr/*!*/ le1,
- LinearConstraint.ConstraintRelation rel, BigNum constantOffset) /* throws ArithmeticException */
- {
- Contract.Requires(le0 != null);
- Contract.Requires(le1 != null);
- 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 */
- {
- 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;
- }
-
- 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 null;
- }
- }
-
- 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);
- }
-
- 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(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 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;
- }
- if (current != null) {
- z = current.coeff;
- }
- }
- return z;
- }
-
- 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 */
- {
- 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 */
- {
- 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;
-
- NextOuter:
- ;
- }
-
- // 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;
- }
-
- 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) {
- 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;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework {
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using Microsoft.Basetypes;
+
+ using ISet = Microsoft.Boogie.GSet<object>;
+ using HashSet = Microsoft.Boogie.GSet<object>;
+
+ /// <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");
+
+ private class PolyhedraLatticeElement : Element {
+
+ public LinearConstraintSystem/*!*/ lcs;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(lcs != null);
+ }
+
+
+ /// <summary>
+ /// Creates a top or bottom elements, according to parameter "top".
+ /// </summary>
+ public PolyhedraLatticeElement(bool top) {
+ if (top) {
+ lcs = new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ());
+ } else {
+ lcs = new LinearConstraintSystem();
+ }
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return lcs.ToString();
+ }
+
+ 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() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
+ return lcs.FreeVariables();
+ }
+
+ public PolyhedraLatticeElement(LinearConstraintSystem/*!*/ lcs) {
+ Contract.Requires(lcs != null);
+ this.lcs = lcs;
+ }
+
+ public override Element/*!*/ Clone() {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new PolyhedraLatticeElement(cce.NonNull(lcs.Clone()));
+ }
+
+ } // class
+
+ 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) {
+ 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 {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new PolyhedraLatticeElement(true);
+ }
+ }
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+
+ 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) {
+ //Contract.Requires(element != null);
+ PolyhedraLatticeElement e = (PolyhedraLatticeElement)element;
+ return e.lcs.IsTop();
+ }
+
+
+ /// <summary>
+ /// Returns true iff a is a subset of this.
+ /// </summary>
+ /// <param name="a"></param>
+ /// <returns></returns>
+ protected override bool AtMost(Element/*!*/ first, Element/*!*/ second) // this <= that
+ {
+ //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) {
+ //Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return ((PolyhedraLatticeElement)e).lcs.ToString();
+ }
+
+ 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) {
+ //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();
+ return result;
+ }
+
+
+ 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) {
+ //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) {
+ //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()) {
+ return ple;
+ }
+ return new PolyhedraLatticeElement(ple.lcs.Project(variable));
+ }
+
+
+ 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()) {
+ return ple;
+ }
+ return new PolyhedraLatticeElement(ple.lcs.Rename(oldName, newName));
+ }
+
+ 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 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;
+ }
+ }
+
+ 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) {
+ //Contract.Requires(visitor != null);
+ return visitor.VisitFunApp(this);
+ }
+
+ 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);
+ }
+ }
+
+ 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) {
+ //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) {
+ //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()) {
+ return ple;
+ }
+ LinearCondition le = LinearExpressionBuilder.AsCondition(expr);
+ if (le != null) {
+ // update the polyhedron according to the linear expression
+ 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);
+
+ return new PolyhedraLatticeElement(newLcs);
+ }
+ return ple;
+ }
+
+ } // 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>
+ /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ
+ /// </summary>
+ /// <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 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 */
+ {
+ return GetCond(e, true);
+ }
+
+ 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;
+ 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;
+ }
+ 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;
+ }
+
+ public static LinearConstraint MakeConstraint(LinearExpr/*!*/ le0, LinearExpr/*!*/ le1,
+ LinearConstraint.ConstraintRelation rel, BigNum constantOffset) /* throws ArithmeticException */
+ {
+ Contract.Requires(le0 != null);
+ Contract.Requires(le1 != null);
+ 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 */
+ {
+ 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;
+ }
+
+ 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 null;
+ }
+ }
+
+ 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);
+ }
+
+ 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(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 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;
+ }
+ if (current != null) {
+ z = current.coeff;
+ }
+ }
+ return z;
+ }
+
+ 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 */
+ {
+ 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 */
+ {
+ 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;
+
+ NextOuter:
+ ;
+ }
+
+ // 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;
+ }
+
+ 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) {
+ 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;
+ }
+ }
+}
diff --git a/Source/AIFramework/Polyhedra/SimplexTableau.cs b/Source/AIFramework/Polyhedra/SimplexTableau.cs
index 4d734c27..347c7c45 100644
--- a/Source/AIFramework/Polyhedra/SimplexTableau.cs
+++ b/Source/AIFramework/Polyhedra/SimplexTableau.cs
@@ -1,630 +1,630 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.AbstractInterpretationFramework {
- using System.Collections;
- using System;
- using System.Diagnostics.Contracts;
- using Microsoft.Basetypes;
- using IMutableSet = Microsoft.Boogie.GSet<object>;
- using HashSet = Microsoft.Boogie.GSet<object>;
-
-
- /// <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);
- }
-
- 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);
- }
- }
- }
- }
- // 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) {
- Contract.Requires(constraints != null);
-#if DEBUG_PRINT
- Console.WriteLine("DEBUG: SimplexTableau constructor called with:");
- foreach (LinearConstraint lc in constraints)
- {
- Console.WriteLine(" {0}", lc);
- }
-#endif
- // 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++;
- }
- }
-
- 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;
- }
-
- // 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) {
-#if DEBUG_PRINT
- Console.WriteLine("-- About to Pivot({0},{1})", i, j);
-#endif
- 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++) {
- Contract.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();
- }
-
- 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;
- }
-
- public Rational this[int r, int c] {
- get {
- return m[r, c];
- }
- set {
- m[r, c] = value;
- }
- }
-
- /// <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];
- }
-
- // scale the pivot row
- Rational q = m[r, c];
- if (q != Rational.ONE) {
- for (int j = 0; j < columns; j++) {
- m[r, j] /= q;
- }
- }
-
- // 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];
- }
- }
- }
- }
-
- // update basis information
- int prevCol = basisColumns[r];
- undo[rows] = Rational.FromInt(prevCol);
- basisColumns[r] = c;
- if (prevCol != -1) {
- inBasis[prevCol] = -1;
- }
- inBasis[c] = 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
- /// is feasible. May have a side effect of performing a number of pivot operations on the tableau,
- /// but any such pivot operation will be in the columns of slack variables (that is, this routine
- /// does not change the set of initial-variable columns in basis).
- ///
- /// CAVEAT: I have no particular reason to believe that the algorithm used here will terminate. --KRML
- /// </summary>
- /// <returns></returns>
- public bool IsFeasibleBasis {
- get {
- // while there is a slack variable in basis whose row has a negative right-hand side
- while (true) {
- bool feasibleBasis = true;
- for (int c = numInitialVars; c < rhsColumn; c++) {
- int k = inBasis[c];
- 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) {
- 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
- Contract.Assert(inBasis[c] == -1);
- Contract.Assert(inBasis[i] == k);
- Contract.Assert(m[k, rhsColumn].IsNonNegative);
- goto START_ANEW;
- }
- }
- feasibleBasis = false;
- }
- }
- return feasibleBasis;
- START_ANEW:
- ;
- }
- }
- }
-
- /// <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) {
- return false;
- }
- }
- return true;
- }
- }
-
- /// <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: {
- }
- }
- }
-
- /// <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) {
- 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) {
- 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: ");
- foreach (bool t in thisBasis) {
- Console.Write("{0}", t ? "*" : ".");
- }
- 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)cce.NonNull(dims[j]), m[i, rhsColumn]);
- }
- }
-#if DEBUG_PRINT
- Console.WriteLine(" Adding vertex: {0}", v);
-#endif
- vertices.Add(v);
-
- // 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) {
- // 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) {
- // does not correspond to an extreme ray
- goto CHECK_NEXT_SLACK_VAR;
- }
- }
- }
- }
- // corresponds to an extreme ray
- FrameElement ray = new FrameElement();
- for (int i = 0; i < numInitialVars; i++) {
- int j0 = inBasis[i];
- 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: {
- }
- }
-
- // 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("* ");
- 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();
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework {
+ using System.Collections;
+ using System;
+ using System.Diagnostics.Contracts;
+ using Microsoft.Basetypes;
+ using IMutableSet = Microsoft.Boogie.GSet<object>;
+ using HashSet = Microsoft.Boogie.GSet<object>;
+
+
+ /// <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);
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+ // 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) {
+ Contract.Requires(constraints != null);
+#if DEBUG_PRINT
+ Console.WriteLine("DEBUG: SimplexTableau constructor called with:");
+ foreach (LinearConstraint lc in constraints)
+ {
+ Console.WriteLine(" {0}", lc);
+ }
+#endif
+ // 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++;
+ }
+ }
+
+ 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;
+ }
+
+ // 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) {
+#if DEBUG_PRINT
+ Console.WriteLine("-- About to Pivot({0},{1})", i, j);
+#endif
+ 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++) {
+ Contract.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();
+ }
+
+ 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;
+ }
+
+ public Rational this[int r, int c] {
+ get {
+ return m[r, c];
+ }
+ set {
+ m[r, c] = value;
+ }
+ }
+
+ /// <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];
+ }
+
+ // scale the pivot row
+ Rational q = m[r, c];
+ if (q != Rational.ONE) {
+ for (int j = 0; j < columns; j++) {
+ m[r, j] /= q;
+ }
+ }
+
+ // 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];
+ }
+ }
+ }
+ }
+
+ // update basis information
+ int prevCol = basisColumns[r];
+ undo[rows] = Rational.FromInt(prevCol);
+ basisColumns[r] = c;
+ if (prevCol != -1) {
+ inBasis[prevCol] = -1;
+ }
+ inBasis[c] = 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
+ /// is feasible. May have a side effect of performing a number of pivot operations on the tableau,
+ /// but any such pivot operation will be in the columns of slack variables (that is, this routine
+ /// does not change the set of initial-variable columns in basis).
+ ///
+ /// CAVEAT: I have no particular reason to believe that the algorithm used here will terminate. --KRML
+ /// </summary>
+ /// <returns></returns>
+ public bool IsFeasibleBasis {
+ get {
+ // while there is a slack variable in basis whose row has a negative right-hand side
+ while (true) {
+ bool feasibleBasis = true;
+ for (int c = numInitialVars; c < rhsColumn; c++) {
+ int k = inBasis[c];
+ 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) {
+ 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
+ Contract.Assert(inBasis[c] == -1);
+ Contract.Assert(inBasis[i] == k);
+ Contract.Assert(m[k, rhsColumn].IsNonNegative);
+ goto START_ANEW;
+ }
+ }
+ feasibleBasis = false;
+ }
+ }
+ return feasibleBasis;
+ START_ANEW:
+ ;
+ }
+ }
+ }
+
+ /// <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) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /// <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: {
+ }
+ }
+ }
+
+ /// <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) {
+ 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) {
+ 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: ");
+ foreach (bool t in thisBasis) {
+ Console.Write("{0}", t ? "*" : ".");
+ }
+ 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)cce.NonNull(dims[j]), m[i, rhsColumn]);
+ }
+ }
+#if DEBUG_PRINT
+ Console.WriteLine(" Adding vertex: {0}", v);
+#endif
+ vertices.Add(v);
+
+ // 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) {
+ // 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) {
+ // does not correspond to an extreme ray
+ goto CHECK_NEXT_SLACK_VAR;
+ }
+ }
+ }
+ }
+ // corresponds to an extreme ray
+ FrameElement ray = new FrameElement();
+ for (int i = 0; i < numInitialVars; i++) {
+ int j0 = inBasis[i];
+ 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: {
+ }
+ }
+
+ // 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("* ");
+ 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();
+ }
+ }
+ }
+}
diff --git a/Source/AIFramework/VariableMap/ConstantAbstraction.cs b/Source/AIFramework/VariableMap/ConstantAbstraction.cs
index d8f17a3c..d73fc28b 100644
--- a/Source/AIFramework/VariableMap/ConstantAbstraction.cs
+++ b/Source/AIFramework/VariableMap/ConstantAbstraction.cs
@@ -1,251 +1,251 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Diagnostics.Contracts;
-namespace Microsoft.AbstractInterpretationFramework {
- using System.Collections;
- using System.Diagnostics;
- //using System.Compiler.Analysis;
- using Microsoft.Basetypes;
-
- /// <summary>
- /// Represents an invariant over constant variable assignments.
- /// </summary>
- public class ConstantLattice : MicroLattice {
- enum Value {
- Top,
- Bottom,
- Constant
- }
-
- private class Elt : Element {
- public Value domainValue;
- public BigNum constantValue; // valid iff domainValue == Value.Constant
-
- public Elt(Value v) {
- this.domainValue = v;
- }
-
- public Elt(BigNum i) {
- this.domainValue = Value.Constant;
- this.constantValue = i;
- }
-
- public bool IsConstant {
- get {
- return this.domainValue == Value.Constant;
- }
- }
-
- public BigNum Constant {
- get {
- return this.constantValue;
- }
- } // only when IsConstant
-
- [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.IsConstant)
- return new Elt(constantValue);
- else
- return new Elt(domainValue);
- }
- }
-
- readonly IIntExprFactory/*!*/ factory;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(factory != null);
- }
-
-
- public ConstantLattice(IIntExprFactory/*!*/ factory) {
- Contract.Requires(factory != null);
- this.factory = factory;
- // base();
- }
-
- public override Element/*!*/ Top {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(Value.Top);
- }
- }
-
- public override Element/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(Value.Bottom);
- }
- }
-
- 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) {
- //Contract.Requires(element != null);
- Elt e = (Elt)element;
- return e.domainValue == Value.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;
- 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) {
- //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) {
- //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
- {
- //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) {
- //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) {
- //Contract.Requires(element != null);
- Elt e = (Elt)element;
- Contract.Assert(e.domainValue == Value.Constant);
- return factory.Const(e.constantValue);
- }
-
- 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) {
- //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;
- 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 {
- if (arg0 is IVariable) {
- BigNum z;
- if (Fold(arg1, out z)) {
- return new Elt(z);
- }
- } else if (arg1 is IVariable) {
- BigNum z;
- if (Fold(arg0, out z)) {
- return new Elt(z);
- }
- }
- } catch (System.ArithmeticException) {
- // fall through and return Top. (Note, an alternative design may
- // consider returning Bottom.)
- }
- }
- }
- return Top;
- }
-
- /// <summary>
- /// Returns true if "expr" represents a constant integer expressions, in which case
- /// "z" returns as that integer. Otherwise, returns false, in which case "z" should
- /// not be used by the caller.
- ///
- /// 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) {
- Contract.Requires(expr != null);
- IFunApp e = expr as IFunApp;
- if (e == null) {
- z = BigNum.ZERO;
- return false;
- }
-
- if (e.FunctionSymbol is IntSymbol) {
- z = ((IntSymbol)e.FunctionSymbol).Value;
- return true;
-
- } else if (e.FunctionSymbol.Equals(Int.Negate)) {
- 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;
- return true;
- }
-
- } else if (e.Arguments.Count == 2) {
- 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)) {
- z = z0 + z1;
- } else if (e.FunctionSymbol.Equals(Int.Sub)) {
- z = z0 - z1;
- } else if (e.FunctionSymbol.Equals(Int.Mul)) {
- z = z0 * z1;
- } else if (e.FunctionSymbol.Equals(Int.Div)) {
- z = z0 / z1;
- } else if (e.FunctionSymbol.Equals(Int.Mod)) {
- z = z0 % z1;
- } else {
- z = BigNum.ZERO;
- return false;
- }
- return true;
- }
- }
-
- z = BigNum.ZERO;
- return false;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+namespace Microsoft.AbstractInterpretationFramework {
+ using System.Collections;
+ using System.Diagnostics;
+ //using System.Compiler.Analysis;
+ using Microsoft.Basetypes;
+
+ /// <summary>
+ /// Represents an invariant over constant variable assignments.
+ /// </summary>
+ public class ConstantLattice : MicroLattice {
+ enum Value {
+ Top,
+ Bottom,
+ Constant
+ }
+
+ private class Elt : Element {
+ public Value domainValue;
+ public BigNum constantValue; // valid iff domainValue == Value.Constant
+
+ public Elt(Value v) {
+ this.domainValue = v;
+ }
+
+ public Elt(BigNum i) {
+ this.domainValue = Value.Constant;
+ this.constantValue = i;
+ }
+
+ public bool IsConstant {
+ get {
+ return this.domainValue == Value.Constant;
+ }
+ }
+
+ public BigNum Constant {
+ get {
+ return this.constantValue;
+ }
+ } // only when IsConstant
+
+ [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.IsConstant)
+ return new Elt(constantValue);
+ else
+ return new Elt(domainValue);
+ }
+ }
+
+ readonly IIntExprFactory/*!*/ factory;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(factory != null);
+ }
+
+
+ public ConstantLattice(IIntExprFactory/*!*/ factory) {
+ Contract.Requires(factory != null);
+ this.factory = factory;
+ // base();
+ }
+
+ public override Element/*!*/ Top {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(Value.Top);
+ }
+ }
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(Value.Bottom);
+ }
+ }
+
+ 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) {
+ //Contract.Requires(element != null);
+ Elt e = (Elt)element;
+ return e.domainValue == Value.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;
+ 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) {
+ //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) {
+ //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
+ {
+ //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) {
+ //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) {
+ //Contract.Requires(element != null);
+ Elt e = (Elt)element;
+ Contract.Assert(e.domainValue == Value.Constant);
+ return factory.Const(e.constantValue);
+ }
+
+ 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) {
+ //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;
+ 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 {
+ if (arg0 is IVariable) {
+ BigNum z;
+ if (Fold(arg1, out z)) {
+ return new Elt(z);
+ }
+ } else if (arg1 is IVariable) {
+ BigNum z;
+ if (Fold(arg0, out z)) {
+ return new Elt(z);
+ }
+ }
+ } catch (System.ArithmeticException) {
+ // fall through and return Top. (Note, an alternative design may
+ // consider returning Bottom.)
+ }
+ }
+ }
+ return Top;
+ }
+
+ /// <summary>
+ /// Returns true if "expr" represents a constant integer expressions, in which case
+ /// "z" returns as that integer. Otherwise, returns false, in which case "z" should
+ /// not be used by the caller.
+ ///
+ /// 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) {
+ Contract.Requires(expr != null);
+ IFunApp e = expr as IFunApp;
+ if (e == null) {
+ z = BigNum.ZERO;
+ return false;
+ }
+
+ if (e.FunctionSymbol is IntSymbol) {
+ z = ((IntSymbol)e.FunctionSymbol).Value;
+ return true;
+
+ } else if (e.FunctionSymbol.Equals(Int.Negate)) {
+ 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;
+ return true;
+ }
+
+ } else if (e.Arguments.Count == 2) {
+ 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)) {
+ z = z0 + z1;
+ } else if (e.FunctionSymbol.Equals(Int.Sub)) {
+ z = z0 - z1;
+ } else if (e.FunctionSymbol.Equals(Int.Mul)) {
+ z = z0 * z1;
+ } else if (e.FunctionSymbol.Equals(Int.Div)) {
+ z = z0 / z1;
+ } else if (e.FunctionSymbol.Equals(Int.Mod)) {
+ z = z0 % z1;
+ } else {
+ z = BigNum.ZERO;
+ return false;
+ }
+ return true;
+ }
+ }
+
+ z = BigNum.ZERO;
+ return false;
+ }
+ }
+}
diff --git a/Source/AIFramework/VariableMap/ConstantExpressions.cs b/Source/AIFramework/VariableMap/ConstantExpressions.cs
index fcf49b25..185c700e 100644
--- a/Source/AIFramework/VariableMap/ConstantExpressions.cs
+++ b/Source/AIFramework/VariableMap/ConstantExpressions.cs
@@ -1,538 +1,538 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
- /////////////////////////////////////////////////////////////////////////////////
- // The Abstract domain for determining "constant" expressions
- // i.e. It determines which expression are statically binded
- /////////////////////////////////////////////////////////////////////////////////
-/*
-using System;
-
-namespace Microsoft.AbstractInterpretationFramework
-{
- using Microsoft.Contracts;
- using System.Collections.Generic;
- using Microsoft.AbstractInterpretationFramework;
-
- /// <summary>
- /// This is an abstract domain for inferring constant expressions
- /// </summary>
-
- public class ConstantExpressions : Lattice
- {
- /// <summary>
- /// An abstract element is made of two maps:
- /// + A map from variables to expressions \cup top ( i.e. for each variable, the expression it is binded )
- /// + A map from variables to set of variabes ( i.e. for each variable, the set of variables that depends on its value )
- /// </summary>
- private class AbstractElement: Element
- {
- private Dictionary<IVariable!, BindExpr> variableBindings;
- private Dictionary<IVariable!, List<IVariable>> variableDependences;
-
- static private AbstractElement! bottom;
- static public Element! Bottom
- {
- get
- {
- if(bottom == null)
- {
- bottom = new AbstractElement();
- bottom.variableBindings = null;
- bottom.variableDependences = null;
- }
- assert bottom.variableBindings == null && bottom.variableDependences == null;
- return bottom;
- }
- }
-
- static public Element! Top
- {
- get
- {
- return new AbstractElement();
- }
- }
-
- AbstractElement()
- {
- this.variableBindings = new Dictionary<IVariable!, BindExpr>();
- this.variableDependences = new Dictionary<IVariable!, List<IVariable>>();
- }
-
- /// <summary>
- /// Our abstract element is top if and only if it has any constraint on variables
- /// </summary>
- public bool IsTop
- {
- get
- {
- return this.variableBindings.Keys.Count == 0 && this.variableDependences.Keys.Count == 0;
- }
- }
-
- /// <summary>
- /// Our abstract element is bottom if and only if the maps are null
- /// </summary>
- public bool IsBottom
- {
- get
- {
- assert (this.variableBindings == null) <==> (this.variableDependences == null);
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // The Abstract domain for determining "constant" expressions
+ // i.e. It determines which expression are statically binded
+ /////////////////////////////////////////////////////////////////////////////////
+/*
+using System;
+
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using Microsoft.Contracts;
+ using System.Collections.Generic;
+ using Microsoft.AbstractInterpretationFramework;
+
+ /// <summary>
+ /// This is an abstract domain for inferring constant expressions
+ /// </summary>
+
+ public class ConstantExpressions : Lattice
+ {
+ /// <summary>
+ /// An abstract element is made of two maps:
+ /// + A map from variables to expressions \cup top ( i.e. for each variable, the expression it is binded )
+ /// + A map from variables to set of variabes ( i.e. for each variable, the set of variables that depends on its value )
+ /// </summary>
+ private class AbstractElement: Element
+ {
+ private Dictionary<IVariable!, BindExpr> variableBindings;
+ private Dictionary<IVariable!, List<IVariable>> variableDependences;
+
+ static private AbstractElement! bottom;
+ static public Element! Bottom
+ {
+ get
+ {
+ if(bottom == null)
+ {
+ bottom = new AbstractElement();
+ bottom.variableBindings = null;
+ bottom.variableDependences = null;
+ }
+ assert bottom.variableBindings == null && bottom.variableDependences == null;
+ return bottom;
+ }
+ }
+
+ static public Element! Top
+ {
+ get
+ {
+ return new AbstractElement();
+ }
+ }
+
+ AbstractElement()
+ {
+ this.variableBindings = new Dictionary<IVariable!, BindExpr>();
+ this.variableDependences = new Dictionary<IVariable!, List<IVariable>>();
+ }
+
+ /// <summary>
+ /// Our abstract element is top if and only if it has any constraint on variables
+ /// </summary>
+ public bool IsTop
+ {
+ get
+ {
+ return this.variableBindings.Keys.Count == 0 && this.variableDependences.Keys.Count == 0;
+ }
+ }
+
+ /// <summary>
+ /// Our abstract element is bottom if and only if the maps are null
+ /// </summary>
+ public bool IsBottom
+ {
+ get
+ {
+ assert (this.variableBindings == null) <==> (this.variableDependences == null);
return this.variableBindings == null && this.variableDependences == null;
- }
- }
-
- /// <summary>
- /// The pointwise join...
- /// </summary>
- public static AbstractElement! Join(AbstractElement! left, AbstractElement! right)
- {
+ }
+ }
+
+ /// <summary>
+ /// The pointwise join...
+ /// </summary>
+ public static AbstractElement! Join(AbstractElement! left, AbstractElement! right)
+ {
AbstractElement! result = new AbstractElement();
-
- // Put all the variables in the left
- foreach(IVariable! var in left.variableBindings.Keys)
- {
- BindExpr leftVal = left.variableBindings[var];
- assert leftVal != null;
-
- BindExpr rightVal = right.variableBindings[var];
-
- if(rightVal== null) // the expression is not there
- {
+
+ // Put all the variables in the left
+ foreach(IVariable! var in left.variableBindings.Keys)
+ {
+ BindExpr leftVal = left.variableBindings[var];
+ assert leftVal != null;
+
+ BindExpr rightVal = right.variableBindings[var];
+
+ if(rightVal== null) // the expression is not there
+ {
result.variableBindings.Add(var, leftVal);
- }
- else // both abstract elements have a definition for the variable....
- {
- result.variableBindings.Add(var, BindExpr.Join(leftVal, rightVal));
- }
- }
-
- // Put all the variables in the right
- foreach(IVariable! var in right.variableBindings.Keys)
- {
- BindExpr rightVal = right.variableBindings[var];
- assert rightVal != null;
-
- BindExpr leftVal = left.variableBindings[var];
-
- if(rightVal== null) // the expression is not there
- {
+ }
+ else // both abstract elements have a definition for the variable....
+ {
+ result.variableBindings.Add(var, BindExpr.Join(leftVal, rightVal));
+ }
+ }
+
+ // Put all the variables in the right
+ foreach(IVariable! var in right.variableBindings.Keys)
+ {
+ BindExpr rightVal = right.variableBindings[var];
+ assert rightVal != null;
+
+ BindExpr leftVal = left.variableBindings[var];
+
+ if(rightVal== null) // the expression is not there
+ {
result.variableBindings.Add(var, rightVal);
- }
- else // both abstract elements have a definition for the variable....
- {
- result.variableBindings.Add(var, BindExpr.Join(rightVal, leftVal));
- }
- }
-
- // Join the dependencies...
- foreach(IVariable! var in left.variableDependences.Keys)
- {
- List<IVariable> dependencies = left.variableDependences[var];
- List<IVariable> dup = new List<IVariable>(dependencies);
-
- result.variableDependences.Add(var, dup);
- }
-
- foreach(IVariable! var in right.variableDependences.Keys)
- {
- if(result.variableDependences.ContainsKey(var))
- {
- List<IVariable> dependencies = result.variableDependences[var];
- dependencies.AddRange(right.variableDependences[var]);
- }
- else
- {
- List<IVariable> dependencies = right.variableDependences[var];
- List<IVariable> dup = new List<IVariable>(dependencies);
-
- result.variableDependences.Add(var, dup);
- }
- }
-
- // Normalize... i.e. for the variables such thas they point to an unknown expression (top) we have to update also their values
- result.Normalize();
-
- return result;
- }
-
-
- ///<summary>
- /// Normalize the current abstract element, in that it propagetes the "dynamic" information throughtout the abstract element
- ///</summary>
- public void Normalize()
- {
- if(this.IsBottom)
- return;
- if(this.IsTop)
- return;
- assert this.variableBindings != null;
-
- bool atFixpoint = false;
-
- while(!atFixpoint)
- {
- atFixpoint = true; // guess that we've got the fixpoint...
-
- foreach(IVariable x in this.variableBindings.Keys)
- {
- if(this.variableBindings[x].IsTop) // It means that the variable is tied to a dynamic expression
- {
- foreach(IVariable y in this.variableDependences[x]) // The all the variables that depend on x are also dynamic...
- {
- assert x != y; // A variable cannot depend on itself...
- if(!this.variableBindings[y].IsTop)
- {
- this.variableBindings[y] = BindExpr.Top;
- atFixpoint = false; // the assumption that we were at the fixpoint was false, we have still to propagate some information...
- }
- }
- }
- }
- }
- }
-
- /// <summary>
- /// The pointwise meet...
- /// </summary>
- public static AbstractElement! Meet(AbstractElement! left, AbstractElement! right)
- {
- AbstractElement! result = new AbstractElement();
-
- // Put the variables that are both in left and right
- foreach(IVariable var in left.variableBindings.Keys)
- {
- if(right.variableBindings.ContainsKey(var))
- {
- result.variableBindings.Add(var, BindExpr.Meet(left.variableBindings[var], right.variableBindings[var]));
- }
- }
-
- // Intersect the dependencies
- foreach(IVariable var in result.variableBindings.Keys)
- {
- List<IVariable> depLeft = left.variableDependences[var];
- List<IVariable> depRight = right.variableDependences[var];
-
- // Intersect the two sets
+ }
+ else // both abstract elements have a definition for the variable....
+ {
+ result.variableBindings.Add(var, BindExpr.Join(rightVal, leftVal));
+ }
+ }
+
+ // Join the dependencies...
+ foreach(IVariable! var in left.variableDependences.Keys)
+ {
+ List<IVariable> dependencies = left.variableDependences[var];
+ List<IVariable> dup = new List<IVariable>(dependencies);
+
+ result.variableDependences.Add(var, dup);
+ }
+
+ foreach(IVariable! var in right.variableDependences.Keys)
+ {
+ if(result.variableDependences.ContainsKey(var))
+ {
+ List<IVariable> dependencies = result.variableDependences[var];
+ dependencies.AddRange(right.variableDependences[var]);
+ }
+ else
+ {
+ List<IVariable> dependencies = right.variableDependences[var];
+ List<IVariable> dup = new List<IVariable>(dependencies);
+
+ result.variableDependences.Add(var, dup);
+ }
+ }
+
+ // Normalize... i.e. for the variables such thas they point to an unknown expression (top) we have to update also their values
+ result.Normalize();
+
+ return result;
+ }
+
+
+ ///<summary>
+ /// Normalize the current abstract element, in that it propagetes the "dynamic" information throughtout the abstract element
+ ///</summary>
+ public void Normalize()
+ {
+ if(this.IsBottom)
+ return;
+ if(this.IsTop)
+ return;
+ assert this.variableBindings != null;
+
+ bool atFixpoint = false;
+
+ while(!atFixpoint)
+ {
+ atFixpoint = true; // guess that we've got the fixpoint...
+
+ foreach(IVariable x in this.variableBindings.Keys)
+ {
+ if(this.variableBindings[x].IsTop) // It means that the variable is tied to a dynamic expression
+ {
+ foreach(IVariable y in this.variableDependences[x]) // The all the variables that depend on x are also dynamic...
+ {
+ assert x != y; // A variable cannot depend on itself...
+ if(!this.variableBindings[y].IsTop)
+ {
+ this.variableBindings[y] = BindExpr.Top;
+ atFixpoint = false; // the assumption that we were at the fixpoint was false, we have still to propagate some information...
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// The pointwise meet...
+ /// </summary>
+ public static AbstractElement! Meet(AbstractElement! left, AbstractElement! right)
+ {
+ AbstractElement! result = new AbstractElement();
+
+ // Put the variables that are both in left and right
+ foreach(IVariable var in left.variableBindings.Keys)
+ {
+ if(right.variableBindings.ContainsKey(var))
+ {
+ result.variableBindings.Add(var, BindExpr.Meet(left.variableBindings[var], right.variableBindings[var]));
+ }
+ }
+
+ // Intersect the dependencies
+ foreach(IVariable var in result.variableBindings.Keys)
+ {
+ List<IVariable> depLeft = left.variableDependences[var];
+ List<IVariable> depRight = right.variableDependences[var];
+
+ // Intersect the two sets
result.variableDependences.Add(var, depLeft);
- foreach(IVariable v in depRight)
- {
- if(!result.variableDependences.ContainsKey(v))
- {
+ foreach(IVariable v in depRight)
+ {
+ if(!result.variableDependences.ContainsKey(v))
+ {
result.variableDependences.Remove(v);
- }
- }
- }
-
- // Now we remove the dependencies with variables not in variableBindings
+ }
+ }
+ }
+
+ // Now we remove the dependencies with variables not in variableBindings
List<IVariable>! varsToRemove = new List<IVariable>();
-
- foreach(IVariable var in result.
-
-
- }
-
- /// <summary>
- /// Clone the current abstract element
- /// </summary>
- public override Element! Clone()
- {
- AbstractElement cloned = new AbstractElement();
- foreach(IVariable var in this.variableBindings.Keys)
- {
- cloned.variableBindings.Add(var, this.variableBindings[var]);
- }
-
- foreach(IVariable var in this.variableDependences.Keys)
- {
- List<IVariable> dependingVars = this.variableDependences[var];
- List<IVariable> clonedDependingVars = new List<IVariable>(dependingVars);
+
+ foreach(IVariable var in result.
+
+
+ }
+
+ /// <summary>
+ /// Clone the current abstract element
+ /// </summary>
+ public override Element! Clone()
+ {
+ AbstractElement cloned = new AbstractElement();
+ foreach(IVariable var in this.variableBindings.Keys)
+ {
+ cloned.variableBindings.Add(var, this.variableBindings[var]);
+ }
+
+ foreach(IVariable var in this.variableDependences.Keys)
+ {
+ List<IVariable> dependingVars = this.variableDependences[var];
+ List<IVariable> clonedDependingVars = new List<IVariable>(dependingVars);
cloned.variableDependences.Add(var, clonedDependingVars);
- }
- }
-
- /// <summary>
- /// Return the variables that have a binding
- /// </summary>
- public override ICollection<IVariable!>! FreeVariables()
- {
- List<IVariable!> vars = new List<IVariable!>(this.variableBindings.Keys);
-
- return vars;
- }
-
- public override string! ToString()
- {
+ }
+ }
+
+ /// <summary>
+ /// Return the variables that have a binding
+ /// </summary>
+ public override ICollection<IVariable!>! FreeVariables()
+ {
+ List<IVariable!> vars = new List<IVariable!>(this.variableBindings.Keys);
+
+ return vars;
+ }
+
+ public override string! ToString()
+ {
string! retString = "";
- retString += "Bindings";
-
- foreach(IVariable var in this.variableBindings.Keys)
- {
- string! toAdd = var.ToString() + " -> " + this.variableBindings[var];
- retString += toAdd + ",";
- }
-
- retString += "\nDependencies";
- foreach(IVariable var in this.variableDependences.Keys)
- {
- string! toAdd = var.ToString() + " -> " + this.variableDependences[var];
- retString += toAdd + ",";
- }
-
- return retString;
- }
- }
-
- public override Element! Top
- {
- get
- {
- return AbstractElement.Top;
- }
- }
-
- public override Element! Bottom
- {
- get
- {
- return AbstractElement.Bottom;
- }
- }
-
- public override bool IsTop(Element! e)
- {
- assert e is AbstractElement;
- AbstractElement! absElement = (AbstractElement) e;
-
- return absElement.IsTop;
- }
-
- public override bool IsBottom(Element! e)
- {
- assert e is AbstractElement;
- AbstractElement absElement = (AbstractElement) e;
- return absElement.IsBottom;
- }
-
- /// <summary>
- /// Perform the pointwise join of the two abstract elements
- /// </summary>
- public override Element! NontrivialJoin(Element! a, Element! b)
- {
- assert a is AbstractElement;
- assert b is AbstractElement;
-
- AbstractElement! left = (AbstractElement!) a;
- AbstractElement! right = (AbstractElement!) b;
-
- return AbstractElement.Join(left, right);
- }
-
- /// <summary>
- /// Perform the pointwise meet of two abstract elements
- /// </summary>
- public override Element! NontrivialMeet(Element! a, Element!b)
- {
- assert a is AbstractElement;
- assert b is AbstractElement;
-
- AbstractElement! left = (AbstractElement!) a;
- AbstractElement! right = (AbstractElement!) b;
-
- return AbstractElement.Meet(left, right);
- }
-
-
- }
-
- /// <summary>
- /// A wrapper in order to have the algebraic datatype BindExpr := IExpr | Top
- /// </summary>
- abstract class BindExpr
- {
- /// <summary>
- /// True iff this expression is instance of BindExprTop
- /// </summary>
- public bool IsTop
- {
- get
- {
- return this is BindExprTop;
- }
- }
-
- static public BindExpr Top
- {
- get
- {
- return BindExprTop.UniqueTop;
- }
- }
-
- /// <summary>
- /// True iff this expression is instance of BindExprBottom
- /// </summary>
- public bool IsBottom
- {
- get
- {
- return this is BindExprBottom;
- }
- }
-
- static public BindExpr Bottom
- {
- get
- {
- return BindExprBottom.UniqueBottom;
- }
- }
-
- public static BindExpr! Join(BindExpr! left, BindExpr! right)
- {
- if(left.IsTop || right.IsTop)
- {
- return BindExpr.Top;
- }
- else if(left.IsBottom)
- {
- return right;
- }
- else if(right.IsBottom)
- {
- return left;
- }
- else if(left.EmbeddedExpr != right.EmbeddedExpr)
- {
- return BindExpr.Top;
- }
- else // left.EmbeddedExpr == right.EmbeddedExpr
- {
- return left;
- }
- }
-
- public static BindExpr! Meet(BindExpr! left, BindExpr! right)
- {
- if(left.IsTop)
- {
- return right;
- }
- else if(right.IsTop)
- {
- return right;
- }
- else if(left.IsBottom || right.IsBottom)
- {
- return BindExpr.Bottom;
- }
- else if(left.EmbeddedExpr != right.EmbeddedExpr)
- {
- return BindExpr.Bottom;
- }
- else // left.EmbeddedExpr == right.EmbeddedExpr
- {
- return left;
- }
- }
-
- abstract public IExpr! EmbeddedExpr
- {
- get;
- }
-
- }
-
- /// <summary>
- /// A wrapper for an integer
- /// </summary>
- class Expr : BindExpr
- {
- private IExpr! exp;
-
- public Expr(IExpr! exp)
- {
- this.exp = exp;
- }
-
- override public IExpr! EmbeddedExpr
- {
- get
- {
- return this.exp;
- }
- }
-
- public override string! ToString()
- {
- return this.exp.ToString();
- }
- }
-
- /// <summary>
- /// The dynamic expression
- /// </summary>
- class BindExprTop : BindExpr
- {
- private BindExprTop top = new BindExprTop();
- static public BindExprTop! UniqueTop
- {
- get
- {
- return this.top;
- }
- }
-
- private BindExprTop() {}
-
- override public IExpr! EmbeddedExpr
- {
- get
- {
- assert false; // If we get there, we have an error
- }
- }
-
- public override string! ToString()
- {
- return "<dynamic expression>";
- }
- }
-
- /// <summary>
- /// The unreachable expression
- /// </summary>
- class BindExprBottom : BindExpr
- {
- private BindExprBottom! bottom = new BindExprBottom();
- static public BindExprBottom! UniqueBottom
- {
- get
- {
- return this.bottom;
- }
- }
-
- private BindExprBottom() {}
-
- override public IExpr! EmbeddedExpr
- {
- get
- {
- assert false;
- }
- }
-
- public override string! ToString()
- {
- return "<unreachable expression>";
- }
- }
-
-} // end namespace Microsoft.AbstractInterpretationFramework
+ retString += "Bindings";
+
+ foreach(IVariable var in this.variableBindings.Keys)
+ {
+ string! toAdd = var.ToString() + " -> " + this.variableBindings[var];
+ retString += toAdd + ",";
+ }
+
+ retString += "\nDependencies";
+ foreach(IVariable var in this.variableDependences.Keys)
+ {
+ string! toAdd = var.ToString() + " -> " + this.variableDependences[var];
+ retString += toAdd + ",";
+ }
+
+ return retString;
+ }
+ }
+
+ public override Element! Top
+ {
+ get
+ {
+ return AbstractElement.Top;
+ }
+ }
+
+ public override Element! Bottom
+ {
+ get
+ {
+ return AbstractElement.Bottom;
+ }
+ }
+
+ public override bool IsTop(Element! e)
+ {
+ assert e is AbstractElement;
+ AbstractElement! absElement = (AbstractElement) e;
+
+ return absElement.IsTop;
+ }
+
+ public override bool IsBottom(Element! e)
+ {
+ assert e is AbstractElement;
+ AbstractElement absElement = (AbstractElement) e;
+ return absElement.IsBottom;
+ }
+
+ /// <summary>
+ /// Perform the pointwise join of the two abstract elements
+ /// </summary>
+ public override Element! NontrivialJoin(Element! a, Element! b)
+ {
+ assert a is AbstractElement;
+ assert b is AbstractElement;
+
+ AbstractElement! left = (AbstractElement!) a;
+ AbstractElement! right = (AbstractElement!) b;
+
+ return AbstractElement.Join(left, right);
+ }
+
+ /// <summary>
+ /// Perform the pointwise meet of two abstract elements
+ /// </summary>
+ public override Element! NontrivialMeet(Element! a, Element!b)
+ {
+ assert a is AbstractElement;
+ assert b is AbstractElement;
+
+ AbstractElement! left = (AbstractElement!) a;
+ AbstractElement! right = (AbstractElement!) b;
+
+ return AbstractElement.Meet(left, right);
+ }
+
+
+ }
+
+ /// <summary>
+ /// A wrapper in order to have the algebraic datatype BindExpr := IExpr | Top
+ /// </summary>
+ abstract class BindExpr
+ {
+ /// <summary>
+ /// True iff this expression is instance of BindExprTop
+ /// </summary>
+ public bool IsTop
+ {
+ get
+ {
+ return this is BindExprTop;
+ }
+ }
+
+ static public BindExpr Top
+ {
+ get
+ {
+ return BindExprTop.UniqueTop;
+ }
+ }
+
+ /// <summary>
+ /// True iff this expression is instance of BindExprBottom
+ /// </summary>
+ public bool IsBottom
+ {
+ get
+ {
+ return this is BindExprBottom;
+ }
+ }
+
+ static public BindExpr Bottom
+ {
+ get
+ {
+ return BindExprBottom.UniqueBottom;
+ }
+ }
+
+ public static BindExpr! Join(BindExpr! left, BindExpr! right)
+ {
+ if(left.IsTop || right.IsTop)
+ {
+ return BindExpr.Top;
+ }
+ else if(left.IsBottom)
+ {
+ return right;
+ }
+ else if(right.IsBottom)
+ {
+ return left;
+ }
+ else if(left.EmbeddedExpr != right.EmbeddedExpr)
+ {
+ return BindExpr.Top;
+ }
+ else // left.EmbeddedExpr == right.EmbeddedExpr
+ {
+ return left;
+ }
+ }
+
+ public static BindExpr! Meet(BindExpr! left, BindExpr! right)
+ {
+ if(left.IsTop)
+ {
+ return right;
+ }
+ else if(right.IsTop)
+ {
+ return right;
+ }
+ else if(left.IsBottom || right.IsBottom)
+ {
+ return BindExpr.Bottom;
+ }
+ else if(left.EmbeddedExpr != right.EmbeddedExpr)
+ {
+ return BindExpr.Bottom;
+ }
+ else // left.EmbeddedExpr == right.EmbeddedExpr
+ {
+ return left;
+ }
+ }
+
+ abstract public IExpr! EmbeddedExpr
+ {
+ get;
+ }
+
+ }
+
+ /// <summary>
+ /// A wrapper for an integer
+ /// </summary>
+ class Expr : BindExpr
+ {
+ private IExpr! exp;
+
+ public Expr(IExpr! exp)
+ {
+ this.exp = exp;
+ }
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ return this.exp;
+ }
+ }
+
+ public override string! ToString()
+ {
+ return this.exp.ToString();
+ }
+ }
+
+ /// <summary>
+ /// The dynamic expression
+ /// </summary>
+ class BindExprTop : BindExpr
+ {
+ private BindExprTop top = new BindExprTop();
+ static public BindExprTop! UniqueTop
+ {
+ get
+ {
+ return this.top;
+ }
+ }
+
+ private BindExprTop() {}
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ assert false; // If we get there, we have an error
+ }
+ }
+
+ public override string! ToString()
+ {
+ return "<dynamic expression>";
+ }
+ }
+
+ /// <summary>
+ /// The unreachable expression
+ /// </summary>
+ class BindExprBottom : BindExpr
+ {
+ private BindExprBottom! bottom = new BindExprBottom();
+ static public BindExprBottom! UniqueBottom
+ {
+ get
+ {
+ return this.bottom;
+ }
+ }
+
+ private BindExprBottom() {}
+
+ override public IExpr! EmbeddedExpr
+ {
+ get
+ {
+ assert false;
+ }
+ }
+
+ public override string! ToString()
+ {
+ return "<unreachable expression>";
+ }
+ }
+
+} // end namespace Microsoft.AbstractInterpretationFramework
*/ \ No newline at end of file
diff --git a/Source/AIFramework/VariableMap/DynamicTypeLattice.cs b/Source/AIFramework/VariableMap/DynamicTypeLattice.cs
index 78bd61a0..edda7c1e 100644
--- a/Source/AIFramework/VariableMap/DynamicTypeLattice.cs
+++ b/Source/AIFramework/VariableMap/DynamicTypeLattice.cs
@@ -1,511 +1,511 @@
-//-----------------------------------------------------------------------------
-//
-// 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 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
- }
-
- 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;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(factory != null);
- Contract.Invariant(propFactory != 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/*!*/ Top {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(What.Bounds, null);
- }
- }
-
- public override Element/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(What.Bottom, null);
- }
- }
-
- 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 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;
- 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 new Elt(What.Bounds, factory.JoinTypes(a.ty, b.ty));
- }
- }
-
- // The result is going to be a Bounds, since at least one of the operands is a Bounds.
- 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);
- 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) {
- return b;
- } else {
- return new Elt(What.Bounds, join);
- }
- }
-
- // General case
- ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n); // final size
- ArrayList /*IExpr!*/ result = new ArrayList /*IExpr!*/ (n); // a guess at the size, but could be as big as size(a)*size(b)
- 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));
- }
- // compute the join of each pair, putting non-redundant joins into "result"
- 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/*!*/)cce.NonNull(allBounds[j]);
-
- IExpr/*!*/ join = factory.JoinTypes(aBound, bBound);
- Contract.Assert(join != null);
-
- int k = 0;
- while (k < result.Count) {
- 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
- goto NEXT_PAIR;
- } else if (factory.IsSubType(r, join)) {
- // "join" is less restrictive than a bound already placed in "result",
- // so toss out that old bound
- result.RemoveAt(k);
- } else {
- k++;
- }
- }
- result.Add(join);
- NEXT_PAIR: {
- }
- }
- }
- return new Elt(result, result.Count);
- }
-
-
- 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;
- }
-
- } 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;
- }
- 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);
- }
- }
-
- // 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);
- }
-
- 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 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 p;
- }
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- throw new System.Exception();
- }
- }
-
- public override IExpr GetFoldExpr(Element/*!*/ e) {
- //Contract.Requires(e != null);
- // cannot fold into an expression that can be substituted for the variable
- return null;
- }
-
- 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;
- }
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// 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 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
+ }
+
+ 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;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(factory != null);
+ Contract.Invariant(propFactory != 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/*!*/ Top {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(What.Bounds, null);
+ }
+ }
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(What.Bottom, null);
+ }
+ }
+
+ 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 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;
+ 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 new Elt(What.Bounds, factory.JoinTypes(a.ty, b.ty));
+ }
+ }
+
+ // The result is going to be a Bounds, since at least one of the operands is a Bounds.
+ 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);
+ 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) {
+ return b;
+ } else {
+ return new Elt(What.Bounds, join);
+ }
+ }
+
+ // General case
+ ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n); // final size
+ ArrayList /*IExpr!*/ result = new ArrayList /*IExpr!*/ (n); // a guess at the size, but could be as big as size(a)*size(b)
+ 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));
+ }
+ // compute the join of each pair, putting non-redundant joins into "result"
+ 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/*!*/)cce.NonNull(allBounds[j]);
+
+ IExpr/*!*/ join = factory.JoinTypes(aBound, bBound);
+ Contract.Assert(join != null);
+
+ int k = 0;
+ while (k < result.Count) {
+ 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
+ goto NEXT_PAIR;
+ } else if (factory.IsSubType(r, join)) {
+ // "join" is less restrictive than a bound already placed in "result",
+ // so toss out that old bound
+ result.RemoveAt(k);
+ } else {
+ k++;
+ }
+ }
+ result.Add(join);
+ NEXT_PAIR: {
+ }
+ }
+ }
+ return new Elt(result, result.Count);
+ }
+
+
+ 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;
+ }
+
+ } 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;
+ }
+ 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);
+ }
+ }
+
+ // 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);
+ }
+
+ 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 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 p;
+ }
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ throw new System.Exception();
+ }
+ }
+
+ public override IExpr GetFoldExpr(Element/*!*/ e) {
+ //Contract.Requires(e != null);
+ // cannot fold into an expression that can be substituted for the variable
+ return null;
+ }
+
+ 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 0bf82cf4..98bf9007 100644
--- a/Source/AIFramework/VariableMap/Intervals.cs
+++ b/Source/AIFramework/VariableMap/Intervals.cs
@@ -1,871 +1,871 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-//using System.Compiler.Analysis;
-using Microsoft.AbstractInterpretationFramework.Collections;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-/////////////////////////////////////////////////////////////////////////////////
-// An implementation of the interval abstract domain
-/////////////////////////////////////////////////////////////////////////////////
-
-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 {
- return true;
- }
- }
-
- public override Element/*!*/ Top {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
-
- return IntervalElement.Top;
- }
- }
-
- public override Element/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
-
- return IntervalElement.Bottom;
- }
- }
-
- /// <summary>
- /// The paramter is the top?
- /// </summary>
- 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) {
- //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) {
- //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);
-
- return join;
- }
-
- /// <summary>
- /// The classic, pointwise, meet of intervals
- /// </summary>
- 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);
-
- return IntervalElement.Factory(inf, sup);
- }
-
-
- /// <summary>
- /// 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) {
- //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;
-
- IntervalElement widening = IntervalElement.Factory(inf, sup);
-
- return widening;
- }
-
-
- /// <summary>
- /// Return true iff the interval left is containted in right
- /// </summary>
- 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())
- return true;
-
- return rightInterval.Inf <= leftInterval.Inf && leftInterval.Sup <= rightInterval.Sup;
- }
-
- /// <summary>
- /// Return just null
- /// </summary>
- 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) {
- //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;
-
- if (!(interval.Inf is InfinitaryInt)) {
- IExpr constant = this.factory.Const(interval.Inf.Value);
- lowerBound = this.factory.AtMost(constant, var); // inf <= var
- }
- if (!(interval.Sup is InfinitaryInt)) {
- IExpr constant = this.factory.Const(interval.Sup.Value);
- upperBound = this.factory.AtMost(var, constant); // var <= inf
- }
-
- if (lowerBound != null && upperBound != null)
- return this.factory.And(lowerBound, upperBound); // inf <= var && var <= sup
- else
- if (lowerBound != null)
- return lowerBound;
- else
- if (upperBound != null)
- 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) {
- //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) {
- //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) {
- //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/*!*/)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) {
- return Eval(leftArg, state);
- }
- }
- }
- // otherwise we simply return Top
- return IntervalElement.Top;
- }
-
- /// <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) {
- Contract.Requires((exp != null));
- Contract.Ensures(Contract.Result<IntervalElement>() != null);
-
- IntervalElement/*!*/ retVal = (IntervalElement/*!*/)cce.NonNull(Top);
-
- // Eval the expression by structural induction
-
-
- if (exp is IVariable && state != null) // A variable
- {
- object lookup = state[exp];
- if (lookup is IntervalElement)
- retVal = (IntervalElement)lookup;
- else {
- retVal = (IntervalElement)Top;
- }
- } else if (exp is IFunApp) {
- IFunApp fun = (IFunApp)exp;
-
- if (fun.FunctionSymbol is IntSymbol) // An integer
- {
- IntSymbol intSymb = (IntSymbol)fun.FunctionSymbol;
- BigNum val = intSymb.Value;
-
- retVal = IntervalElement.Factory(val);
- } else if (fun.FunctionSymbol.Equals(Int.Negate)) // An unary minus
- {
- 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/*!*/)cce.NonNull(fun.Arguments[0]);
- IExpr/*!*/ right = (IExpr/*!*/)cce.NonNull(fun.Arguments[1]);
-
- 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;
- else if (fun.FunctionSymbol.Equals(Int.Sub))
- retVal = leftVal - rightVal;
- else if (fun.FunctionSymbol.Equals(Int.Mul))
- retVal = leftVal * rightVal;
- else if (fun.FunctionSymbol.Equals(Int.Div))
- retVal = leftVal / rightVal;
- else if (fun.FunctionSymbol.Equals(Int.Mod))
- retVal = leftVal % rightVal;
- }
- }
-
- return retVal;
- }
-
- /// <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 readonly ExtendedInt/*!*/ inf;
- private readonly ExtendedInt/*!*/ sup;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(inf != null);
- Contract.Invariant(sup != null);
- }
-
- public ExtendedInt/*!*/ Inf {
- get {
- Contract.Ensures(Contract.Result<ExtendedInt>() != null);
-
- return inf;
- }
- }
-
- public ExtendedInt/*!*/ Sup {
- get {
- Contract.Ensures(Contract.Result<ExtendedInt>() != null);
-
- return 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 {
- Contract.Ensures(Contract.Result<IntervalElement>() != null);
-
- return TopInterval;
- }
- }
-
- static public IntervalElement/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<IntervalElement>() != null);
-
- return BottomInterval;
- }
- }
-
- public bool IsTop() {
- return this.inf is MinusInfinity && this.sup is PlusInfinity;
- }
-
- 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) {
- 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) {
- 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) {
- 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;
- 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) {
- 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;
- 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);
-
- return Factory(inf, sup);
- }
-
- #endregion
-
- #region Overriden methods
-
- 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);
-
- return Factory(clonedInf, clonedSup);
- */
- }
-
- [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() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "[" + this.inf + ", " + this.sup + "]";
- }
-
- #endregion
- }
- }
-
-
- /// The interface for an extended integer
- ///
- [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 {
- Contract.Ensures(Contract.Result<ExtendedInt>() != null);
-
- return cachedMinusInf;
- }
- }
-
- public abstract BigNum Value {
- get;
- }
-
- public abstract int Signum {
- get;
- }
-
- public bool IsZero {
- get {
- return Signum == 0;
- }
- }
-
- public bool IsPositive {
- get {
- return Signum > 0;
- }
- }
-
- public bool IsNegative {
- get {
- return Signum < 0;
- }
- }
-
-
- #region Below are the extensions of arithmetic operations on extended integers
-
- // Addition
- 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) {
- 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) {
- 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) {
- Contract.Requires(a != null);
- Contract.Ensures(Contract.Result<ExtendedInt>() != null);
- if (a is PlusInfinity)
- return cachedMinusInf;
- 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) {
- 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 {
- 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);
- }
- }
-
- // 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) {
- 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 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) {
- Contract.Requires(sup != null);
- Contract.Requires(inf != null);
- return inf.CompareTo(sup) > 0;
- }
-
- 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) {
- 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) {
- 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) {
- 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) {
- 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) {
- 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);
- }
-
- #endregion
-
- // Return the ExtendedInt corresponding to the value
- 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) {
- this.val = i;
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return this.Value.ToString();
- }
-
- private BigNum val;
- public override BigNum Value {
- get {
- return this.val;
- }
- }
-
- public override int Signum {
- 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 {
- get {
- throw new InvalidOperationException();
- }
- }
- }
-
- class PlusInfinity : InfinitaryInt {
- [Pure]
- 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) {
- //Contract.Requires(that != null);
- if (that is PlusInfinity)
- return 0;
- else
- return 1;
- }
- }
-
- class MinusInfinity : InfinitaryInt {
- [Pure]
- 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) {
- //Contract.Requires(that != null);
- if (that is MinusInfinity)
- return 0;
- else
- return -1;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+//using System.Compiler.Analysis;
+using Microsoft.AbstractInterpretationFramework.Collections;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+/////////////////////////////////////////////////////////////////////////////////
+// An implementation of the interval abstract domain
+/////////////////////////////////////////////////////////////////////////////////
+
+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 {
+ return true;
+ }
+ }
+
+ public override Element/*!*/ Top {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+
+ return IntervalElement.Top;
+ }
+ }
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+
+ return IntervalElement.Bottom;
+ }
+ }
+
+ /// <summary>
+ /// The paramter is the top?
+ /// </summary>
+ 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) {
+ //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) {
+ //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);
+
+ return join;
+ }
+
+ /// <summary>
+ /// The classic, pointwise, meet of intervals
+ /// </summary>
+ 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);
+
+ return IntervalElement.Factory(inf, sup);
+ }
+
+
+ /// <summary>
+ /// 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) {
+ //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;
+
+ IntervalElement widening = IntervalElement.Factory(inf, sup);
+
+ return widening;
+ }
+
+
+ /// <summary>
+ /// Return true iff the interval left is containted in right
+ /// </summary>
+ 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())
+ return true;
+
+ return rightInterval.Inf <= leftInterval.Inf && leftInterval.Sup <= rightInterval.Sup;
+ }
+
+ /// <summary>
+ /// Return just null
+ /// </summary>
+ 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) {
+ //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;
+
+ if (!(interval.Inf is InfinitaryInt)) {
+ IExpr constant = this.factory.Const(interval.Inf.Value);
+ lowerBound = this.factory.AtMost(constant, var); // inf <= var
+ }
+ if (!(interval.Sup is InfinitaryInt)) {
+ IExpr constant = this.factory.Const(interval.Sup.Value);
+ upperBound = this.factory.AtMost(var, constant); // var <= inf
+ }
+
+ if (lowerBound != null && upperBound != null)
+ return this.factory.And(lowerBound, upperBound); // inf <= var && var <= sup
+ else
+ if (lowerBound != null)
+ return lowerBound;
+ else
+ if (upperBound != null)
+ 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) {
+ //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) {
+ //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) {
+ //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/*!*/)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) {
+ return Eval(leftArg, state);
+ }
+ }
+ }
+ // otherwise we simply return Top
+ return IntervalElement.Top;
+ }
+
+ /// <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) {
+ Contract.Requires((exp != null));
+ Contract.Ensures(Contract.Result<IntervalElement>() != null);
+
+ IntervalElement/*!*/ retVal = (IntervalElement/*!*/)cce.NonNull(Top);
+
+ // Eval the expression by structural induction
+
+
+ if (exp is IVariable && state != null) // A variable
+ {
+ object lookup = state[exp];
+ if (lookup is IntervalElement)
+ retVal = (IntervalElement)lookup;
+ else {
+ retVal = (IntervalElement)Top;
+ }
+ } else if (exp is IFunApp) {
+ IFunApp fun = (IFunApp)exp;
+
+ if (fun.FunctionSymbol is IntSymbol) // An integer
+ {
+ IntSymbol intSymb = (IntSymbol)fun.FunctionSymbol;
+ BigNum val = intSymb.Value;
+
+ retVal = IntervalElement.Factory(val);
+ } else if (fun.FunctionSymbol.Equals(Int.Negate)) // An unary minus
+ {
+ 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/*!*/)cce.NonNull(fun.Arguments[0]);
+ IExpr/*!*/ right = (IExpr/*!*/)cce.NonNull(fun.Arguments[1]);
+
+ 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;
+ else if (fun.FunctionSymbol.Equals(Int.Sub))
+ retVal = leftVal - rightVal;
+ else if (fun.FunctionSymbol.Equals(Int.Mul))
+ retVal = leftVal * rightVal;
+ else if (fun.FunctionSymbol.Equals(Int.Div))
+ retVal = leftVal / rightVal;
+ else if (fun.FunctionSymbol.Equals(Int.Mod))
+ retVal = leftVal % rightVal;
+ }
+ }
+
+ return retVal;
+ }
+
+ /// <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 readonly ExtendedInt/*!*/ inf;
+ private readonly ExtendedInt/*!*/ sup;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(inf != null);
+ Contract.Invariant(sup != null);
+ }
+
+ public ExtendedInt/*!*/ Inf {
+ get {
+ Contract.Ensures(Contract.Result<ExtendedInt>() != null);
+
+ return inf;
+ }
+ }
+
+ public ExtendedInt/*!*/ Sup {
+ get {
+ Contract.Ensures(Contract.Result<ExtendedInt>() != null);
+
+ return 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 {
+ Contract.Ensures(Contract.Result<IntervalElement>() != null);
+
+ return TopInterval;
+ }
+ }
+
+ static public IntervalElement/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<IntervalElement>() != null);
+
+ return BottomInterval;
+ }
+ }
+
+ public bool IsTop() {
+ return this.inf is MinusInfinity && this.sup is PlusInfinity;
+ }
+
+ 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) {
+ 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) {
+ 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) {
+ 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;
+ 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) {
+ 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;
+ 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);
+
+ return Factory(inf, sup);
+ }
+
+ #endregion
+
+ #region Overriden methods
+
+ 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);
+
+ return Factory(clonedInf, clonedSup);
+ */
+ }
+
+ [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() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "[" + this.inf + ", " + this.sup + "]";
+ }
+
+ #endregion
+ }
+ }
+
+
+ /// The interface for an extended integer
+ ///
+ [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 {
+ Contract.Ensures(Contract.Result<ExtendedInt>() != null);
+
+ return cachedMinusInf;
+ }
+ }
+
+ public abstract BigNum Value {
+ get;
+ }
+
+ public abstract int Signum {
+ get;
+ }
+
+ public bool IsZero {
+ get {
+ return Signum == 0;
+ }
+ }
+
+ public bool IsPositive {
+ get {
+ return Signum > 0;
+ }
+ }
+
+ public bool IsNegative {
+ get {
+ return Signum < 0;
+ }
+ }
+
+
+ #region Below are the extensions of arithmetic operations on extended integers
+
+ // Addition
+ 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) {
+ 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) {
+ 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) {
+ Contract.Requires(a != null);
+ Contract.Ensures(Contract.Result<ExtendedInt>() != null);
+ if (a is PlusInfinity)
+ return cachedMinusInf;
+ 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) {
+ 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 {
+ 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);
+ }
+ }
+
+ // 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) {
+ 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 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) {
+ Contract.Requires(sup != null);
+ Contract.Requires(inf != null);
+ return inf.CompareTo(sup) > 0;
+ }
+
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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);
+ }
+
+ #endregion
+
+ // Return the ExtendedInt corresponding to the value
+ 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) {
+ this.val = i;
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this.Value.ToString();
+ }
+
+ private BigNum val;
+ public override BigNum Value {
+ get {
+ return this.val;
+ }
+ }
+
+ public override int Signum {
+ 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 {
+ get {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ class PlusInfinity : InfinitaryInt {
+ [Pure]
+ 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) {
+ //Contract.Requires(that != null);
+ if (that is PlusInfinity)
+ return 0;
+ else
+ return 1;
+ }
+ }
+
+ class MinusInfinity : InfinitaryInt {
+ [Pure]
+ 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) {
+ //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 ef98f8f7..f46349b7 100644
--- a/Source/AIFramework/VariableMap/MicroLattice.cs
+++ b/Source/AIFramework/VariableMap/MicroLattice.cs
@@ -1,105 +1,105 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.AbstractInterpretationFramework
-{
- using System.Diagnostics.Contracts;
- using System.Collections;
- using System.Diagnostics;
- //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);
- /* requires !e.IsBottom && !e.IsTop; */
-
- /// <summary>
- /// Allows the lattice to specify whether it understands a particular function symbol.
- ///
- /// The lattice is always allowed to "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>
- /// Set this property to true if the implemented MicroLattice can handle basic arithmetic.
- /// Stated otherwise this property is set to true if the MicroLattice provides a transfer function for a predicate in a given state
- /// </summary>
- public virtual bool UnderstandsBasicArithmetics
- {
- get { return false; }
- }
-
- /// <summary>
- /// Evaluate the predicate e and a yield the lattice element
- /// that is implied by it.
- /// </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);
-
- /// <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){
-Contract.Requires(e != null);
-Contract.Ensures(Contract.Result<Element>() != null);
- return EvaluatePredicate(e);
- }
-
- /// <summary>
- /// Give an expression (often a value) that can be used to substitute for
- /// the variable.
- /// </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);
- }
- [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();
- }
- }
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework
+{
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Diagnostics;
+ //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);
+ /* requires !e.IsBottom && !e.IsTop; */
+
+ /// <summary>
+ /// Allows the lattice to specify whether it understands a particular function symbol.
+ ///
+ /// The lattice is always allowed to "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>
+ /// Set this property to true if the implemented MicroLattice can handle basic arithmetic.
+ /// Stated otherwise this property is set to true if the MicroLattice provides a transfer function for a predicate in a given state
+ /// </summary>
+ public virtual bool UnderstandsBasicArithmetics
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Evaluate the predicate e and a yield the lattice element
+ /// that is implied by it.
+ /// </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);
+
+ /// <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){
+Contract.Requires(e != null);
+Contract.Ensures(Contract.Result<Element>() != null);
+ return EvaluatePredicate(e);
+ }
+
+ /// <summary>
+ /// Give an expression (often a value) that can be used to substitute for
+ /// the variable.
+ /// </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);
+ }
+ [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 613f55e0..474792e0 100644
--- a/Source/AIFramework/VariableMap/Nullness.cs
+++ b/Source/AIFramework/VariableMap/Nullness.cs
@@ -1,260 +1,260 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Diagnostics.Contracts;
-namespace Microsoft.AbstractInterpretationFramework {
- using System.Collections;
- using System.Diagnostics;
- //using System.Compiler.Analysis;
-
- public class NullnessLattice : MicroLattice {
- readonly INullnessFactory/*!*/ factory;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(factory != null);
- }
-
-
- public NullnessLattice(INullnessFactory/*!*/ factory) {
- Contract.Requires(factory != null);
- this.factory = factory;
- // base();
- }
-
- enum Value {
- Bottom,
- NotNull,
- Null,
- MayBeNull
- }
-
- private class Elt : Element {
- public Value value;
-
- public Elt(Value v) {
- this.value = v;
- }
-
- [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);
- return new Elt(this.value);
- }
- }
-
-
- public override Element/*!*/ Top {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(Value.MayBeNull);
- }
- }
-
- public override Element/*!*/ Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(Value.Bottom);
- }
- }
-
- public static Element/*!*/ Null {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(Value.Null);
- }
- }
-
- public static Element/*!*/ NotNull {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(Value.NotNull);
- }
- }
-
- 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) {
- //Contract.Requires(element != null);
- Elt e = (Elt)element;
- return e.value == Value.Bottom;
- }
-
- 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) {
- //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) {
- //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
- {
- //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) {
- //Contract.Requires(element != null);
- //Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<IExpr>() != null);
- Elt e = (Elt)element;
-
- if (e.value == Value.NotNull) {
- return factory.Neq(var, factory.Null);
- }
- if (e.value == Value.Null) {
- return factory.Eq(var, factory.Null);
- }
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- throw new System.Exception();
- }
-
- public override IExpr GetFoldExpr(Element/*!*/ e) {
- //Contract.Requires(e != null);
- Elt elt = (Elt)e;
- if (elt.value == Value.Null) {
- return factory.Null;
- } else {
- // can't fold into an expression
- return null;
- }
- }
-
- 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)) {
-
- 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) {
- return true;
- } else if (arg1 is IVariable && arg0 is IFunApp && ((IFunApp)arg0).FunctionSymbol == Ref.Null) {
- 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.Neq)) {
- 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;
- if (arg0 is IVariable && arg1 is IFunApp && ((IFunApp)arg1).FunctionSymbol == Ref.Null) {
- var = (IVariable)arg0;
- } else if (arg1 is IVariable && arg0 is IFunApp && ((IFunApp)arg0).FunctionSymbol == Ref.Null) {
- var = (IVariable)arg1;
- }
-
- if (var != null) // found the pattern
- {
- return isEq ? Null : NotNull;
- }
- }
- }
- return Top;
- }
- }
-
-#if false
-
- public class NullnessMicroLattice : MicroLattice
- {
- public override MicroLatticeElement Top { get { return NullnessLatticeElement.Top; } }
- public override MicroLatticeElement Bottom { get { return NullnessLatticeElement.Bottom; } }
-
-
- public override MicroLatticeElement EvaluateExpression (Expr e, LookupValue lookup)
- {
- if (e is LiteralExpr && ((LiteralExpr)e).Val == null)
- {
- return NullnessLatticeElement.Null;
- }
- return Top;
- }
-
-
- public override MicroLatticeElement EvaluatePredicate (Expr e, LookupValue lookup)
- {
- NAryExpr nary = e as NAryExpr;
- if (nary != null &&
- (nary.Fun.FunctionName.Equals("==") || nary.Fun.FunctionName.Equals("!=")))
- {
- Debug.Assert(nary.Args.Length == 2);
-
- Expr arg0 = nary.Args[0], arg1 = nary.Args[1];
- Variable var = null;
-
- // Look for "x OP null" or "null OP x" where OP is "==" or "!=".
- if (arg0 is IdentifierExpr && arg1 is LiteralExpr && ((LiteralExpr)arg1).Val == null)
- {
- var = ((IdentifierExpr)arg0).Decl;
- }
- else if (arg1 is IdentifierExpr && arg0 is LiteralExpr && ((LiteralExpr)arg0).Val == null)
- {
- var = ((IdentifierExpr)arg1).Decl;
- }
-
- if (var != null) // found the pattern
- {
- return nary.Fun.FunctionName.Equals("==") ?
- NullnessLatticeElement.Null :
- NullnessLatticeElement.NotNull;
- }
- }
- return Top;
- }
- }
-
-#endif
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+namespace Microsoft.AbstractInterpretationFramework {
+ using System.Collections;
+ using System.Diagnostics;
+ //using System.Compiler.Analysis;
+
+ public class NullnessLattice : MicroLattice {
+ readonly INullnessFactory/*!*/ factory;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(factory != null);
+ }
+
+
+ public NullnessLattice(INullnessFactory/*!*/ factory) {
+ Contract.Requires(factory != null);
+ this.factory = factory;
+ // base();
+ }
+
+ enum Value {
+ Bottom,
+ NotNull,
+ Null,
+ MayBeNull
+ }
+
+ private class Elt : Element {
+ public Value value;
+
+ public Elt(Value v) {
+ this.value = v;
+ }
+
+ [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);
+ return new Elt(this.value);
+ }
+ }
+
+
+ public override Element/*!*/ Top {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(Value.MayBeNull);
+ }
+ }
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(Value.Bottom);
+ }
+ }
+
+ public static Element/*!*/ Null {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(Value.Null);
+ }
+ }
+
+ public static Element/*!*/ NotNull {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(Value.NotNull);
+ }
+ }
+
+ 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) {
+ //Contract.Requires(element != null);
+ Elt e = (Elt)element;
+ return e.value == Value.Bottom;
+ }
+
+ 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) {
+ //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) {
+ //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
+ {
+ //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) {
+ //Contract.Requires(element != null);
+ //Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ Elt e = (Elt)element;
+
+ if (e.value == Value.NotNull) {
+ return factory.Neq(var, factory.Null);
+ }
+ if (e.value == Value.Null) {
+ return factory.Eq(var, factory.Null);
+ }
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ throw new System.Exception();
+ }
+
+ public override IExpr GetFoldExpr(Element/*!*/ e) {
+ //Contract.Requires(e != null);
+ Elt elt = (Elt)e;
+ if (elt.value == Value.Null) {
+ return factory.Null;
+ } else {
+ // can't fold into an expression
+ return null;
+ }
+ }
+
+ 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)) {
+
+ 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) {
+ return true;
+ } else if (arg1 is IVariable && arg0 is IFunApp && ((IFunApp)arg0).FunctionSymbol == Ref.Null) {
+ 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.Neq)) {
+ 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;
+ if (arg0 is IVariable && arg1 is IFunApp && ((IFunApp)arg1).FunctionSymbol == Ref.Null) {
+ var = (IVariable)arg0;
+ } else if (arg1 is IVariable && arg0 is IFunApp && ((IFunApp)arg0).FunctionSymbol == Ref.Null) {
+ var = (IVariable)arg1;
+ }
+
+ if (var != null) // found the pattern
+ {
+ return isEq ? Null : NotNull;
+ }
+ }
+ }
+ return Top;
+ }
+ }
+
+#if false
+
+ public class NullnessMicroLattice : MicroLattice
+ {
+ public override MicroLatticeElement Top { get { return NullnessLatticeElement.Top; } }
+ public override MicroLatticeElement Bottom { get { return NullnessLatticeElement.Bottom; } }
+
+
+ public override MicroLatticeElement EvaluateExpression (Expr e, LookupValue lookup)
+ {
+ if (e is LiteralExpr && ((LiteralExpr)e).Val == null)
+ {
+ return NullnessLatticeElement.Null;
+ }
+ return Top;
+ }
+
+
+ public override MicroLatticeElement EvaluatePredicate (Expr e, LookupValue lookup)
+ {
+ NAryExpr nary = e as NAryExpr;
+ if (nary != null &&
+ (nary.Fun.FunctionName.Equals("==") || nary.Fun.FunctionName.Equals("!=")))
+ {
+ Debug.Assert(nary.Args.Length == 2);
+
+ Expr arg0 = nary.Args[0], arg1 = nary.Args[1];
+ Variable var = null;
+
+ // Look for "x OP null" or "null OP x" where OP is "==" or "!=".
+ if (arg0 is IdentifierExpr && arg1 is LiteralExpr && ((LiteralExpr)arg1).Val == null)
+ {
+ var = ((IdentifierExpr)arg0).Decl;
+ }
+ else if (arg1 is IdentifierExpr && arg0 is LiteralExpr && ((LiteralExpr)arg0).Val == null)
+ {
+ var = ((IdentifierExpr)arg1).Decl;
+ }
+
+ if (var != null) // found the pattern
+ {
+ return nary.Fun.FunctionName.Equals("==") ?
+ NullnessLatticeElement.Null :
+ NullnessLatticeElement.NotNull;
+ }
+ }
+ return Top;
+ }
+ }
+
+#endif
+
+}
diff --git a/Source/AIFramework/VariableMap/VariableMapLattice.cs b/Source/AIFramework/VariableMap/VariableMapLattice.cs
index 172cef01..752d3f01 100644
--- a/Source/AIFramework/VariableMap/VariableMapLattice.cs
+++ b/Source/AIFramework/VariableMap/VariableMapLattice.cs
@@ -1,854 +1,854 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.AbstractInterpretationFramework {
- using System.Diagnostics.Contracts;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
-
- using Microsoft.AbstractInterpretationFramework;
- using Microsoft.AbstractInterpretationFramework.Collections;
-
- using Microsoft.Boogie;
-
- using IMutableSet = Microsoft.Boogie.GSet<object>;
- using ISet = Microsoft.Boogie.GSet<object>;
- using Set = Microsoft.Boogie.GSet<object>;
- using HashSet = Microsoft.Boogie.GSet<object>;
-
- /// <summary>
- /// Creates a lattice that works for several variables given a MicroLattice. Assumes
- /// if one variable is bottom, then all variables are bottom.
- /// </summary>
- public class VariableMapLattice : Lattice {
- private class Elt : Element {
- /// <summary>
- /// IsBottom(e) iff e.constraints == null
- /// </summary>
- /*MayBeNull*/
- private IFunctionalMap constraints; // of type IVariable -> LATTICE_ELEMENT
- public IFunctionalMap Constraints {
- get {
- return this.constraints;
- }
- }
-
- private Elt(bool top) {
- if (top) {
- this.constraints = FunctionalHashtable.Empty;
- } else {
- this.constraints = null;
- }
- }
-
- public override Element/*!*/ Clone() {
- Contract.Ensures(Contract.Result<Element>() != null);
- return new Elt(this.constraints);
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- if (constraints == null) {
- return "<bottom>";
- }
- string s = "[";
- string sep = "";
- foreach (IVariable/*!*/ v in cce.NonNull(constraints.Keys)) {
- Contract.Assert(v != null);
- Element m = (Element)constraints[v];
- s += sep + v.Name + " -> " + m;
- sep = ", ";
- }
- return s + "]";
- }
-
- public static readonly Elt/*!*/ Top = new Elt(true);
- public static readonly Elt/*!*/ Bottom = new Elt(false);
-
-
- public Elt(IFunctionalMap constraints) {
- this.constraints = constraints;
- }
-
- public bool IsBottom {
- get {
- return this.constraints == null;
- }
- }
-
- public int Count {
- get {
- return this.constraints == null ? 0 : this.constraints.Count;
- }
- }
-
- 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) {
- Contract.Ensures(Contract.Result<IEnumerable>() != null);
- if (variableComparer == null) {
- return Variables;
- } else {
- ArrayList /*IVariable*/ vars = new ArrayList /*IVariable*/ (Count);
- foreach (IVariable variable in Variables) {
- vars.Add(variable);
- }
- vars.Sort(variableComparer);
- return vars;
- }
- }
-
- public Element Lookup(IVariable v) {
- if ((v == null) || (this.constraints == null)) {
- return null;
- }
- return (Element)this.constraints[v];
- }
-
- public Element this[IVariable/*!*/ key] {
- get {
- Contract.Requires(!this.IsBottom);
- Contract.Requires(key != null);
- Contract.Assume(this.constraints != null);
- return (Element)constraints[key];
- }
- }
-
- /// <summary>
- /// 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) {
- 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);
- }
-
- return new Elt(this.constraints.Add(var, value));
- }
-
- /// <summary>
- /// 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) {
- 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);
- }
-
- Contract.Assume(this.constraints != null);
- Contract.Assert(this.constraints.Contains(var));
-
- // this.constraints[var] = value;
- IFunctionalMap newMap = this.constraints.Set(var, value);
-
- return new Elt(newMap);
- }
-
- public Elt/*!*/ Remove(IVariable/*!*/ var, MicroLattice microLattice) {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<Elt>() != null);
- if (this.IsBottom) {
- return this;
- }
- Contract.Assume(this.constraints != null);
- return new Elt(this.constraints.Remove(var));
- }
-
- 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'
- 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() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
- throw new System.NotImplementedException();
- }
-
- } // class
-
- private readonly MicroLattice/*!*/ microLattice;
-
- private readonly IPropExprFactory/*!*/ propExprFactory;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(microLattice != null);
- Contract.Invariant(propExprFactory != null);
- }
-
-
- private readonly /*maybe null*/IComparer variableComparer;
-
- 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 {
- Contract.Ensures(Contract.Result<object>() != null);
- return this.microLattice.GetType();
- }
- }
-
- public override Element/*!*/ Top {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return Elt.Top;
- }
- }
-
- public override Element Bottom {
- get {
- Contract.Ensures(Contract.Result<Element>() != null);
- return Elt.Bottom;
- }
- }
-
- 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) {
- //Contract.Requires(element != null);
- return ((Elt)element).IsBottom;
- }
-
- 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) {
- 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
-
- if (this.microLattice.LowerThan(thisValue, thatValue)) {
- continue;
- } // constraint for "var" satisfies AtMost relation
-
- return false;
- }
- 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 = cce.NonNull(b[var]);
- if (this.microLattice.IsTop(thatValue)) {
- continue;
- } // this is a trivial constraint
-
- return false;
- }
- return true;
- }
-
- 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
- {
- /*MicroLattice*/
- Element currentValue = e[var];
-
- if (currentValue == null) {
- // No information currently, so we just add the new info.
- return e.Add(var, newValue, this.microLattice);
- } else {
- // Otherwise, take the meet of the new and current info.
- //return e.Add(var, this.microLattice.Meet(currentValue, newValue), this.microLattice);
- return e.Set(var, this.microLattice.Meet(currentValue, newValue), this.microLattice);
- }
- }
- return e;
- }
-
- 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>";
- }
- if (IsBottom(e)) {
- return "<bottom>";
- }
-
- int k = 0;
- System.Text.StringBuilder buffer = new System.Text.StringBuilder();
- 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) {
- //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) {
- Contract.Assert(key != null);
- Element aValue = a[key];
- Element bValue = b[key];
-
- if (aValue != null && bValue != null) {
- // Keep only the variables known to both elements.
- Element newValue = this.microLattice.Join(aValue, bValue);
- newMap = newMap.Add(key, newValue);
- }
- }
- 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) {
- //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) {
- Contract.Assert(key != null);
- Element/*!*/ aValue = cce.NonNull(a[key]);
- Element bValue = b[key];
-
- Element newValue =
- bValue == null ? aValue :
- this.microLattice.Meet(aValue, bValue);
-
- newMap = newMap.Add(key, newValue);
- }
- foreach (IVariable/*!*/ key in b.Variables) {
- Contract.Assert(key != null);
- Element aValue = a[key];
- Element bValue = b[key];
- Debug.Assert(bValue != null);
-
- if (aValue == null) {
- // It's a variable we didn't cover in the last loop.
- newMap = newMap.Add(key, bValue);
- }
- }
- return new Elt(newMap);
- }
-
- /// <summary>
- /// Perform the pointwise widening of the elements in the map
- /// </summary>
- 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;
-
- // Note we have to add those cases as we do not have a "NonTrivialWiden" method
- if (a.IsBottom)
- return new Elt(b.Constraints);
- if (b.IsBottom)
- return new Elt(a.Constraints);
-
- IFunctionalMap newMap = FunctionalHashtable.Empty;
- foreach (IVariable/*!*/ key in a.Variables) {
- Contract.Assert(key != null);
- Element aValue = a[key];
- Element bValue = b[key];
-
- if (aValue != null && bValue != null) {
- // Keep only the variables known to both elements.
- Element newValue = this.microLattice.Widen(aValue, bValue);
- newMap = newMap.Add(key, newValue);
- }
- }
- 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) {
- Contract.Requires(ignoreVars != null);
- Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<ISet>() != null);
- HashSet s = new HashSet();
-
- IFunApp f = e as IFunApp;
- IFunction lambda = e as IFunction;
-
- if (e is IVariable) {
- if (!ignoreVars.Contains(e))
- s.Add(e);
- } else if (f != null) // e is IFunApp
- {
- foreach (IExpr/*!*/ arg in f.Arguments) {
- Contract.Assert(arg != null);
- s.AddAll(VariablesInExpression(arg, ignoreVars));
- }
- } else if (lambda != null) {
- IMutableSet x = new HashSet(1);
- x.Add(lambda.Param);
-
- // Ignore the bound variable
- s.AddAll(VariablesInExpression(lambda.Body, cce.NonNull(Set.Union(ignoreVars, x))));
- } else if (e is IUnknown) {
- // skip (actually, it would be appropriate to return the universal set of all variables)
- } else {
- Debug.Assert(false, "case not handled: " + e);
- }
- return s;
- }
-
-
- private static ArrayList/*<IExpr>*//*!*/ FindConjuncts(IExpr e) {
- Contract.Ensures(Contract.Result<ArrayList>() != null);
- ArrayList result = new ArrayList();
-
- IFunApp f = e as IFunApp;
- if (f != null) {
- if (f.FunctionSymbol.Equals(Prop.And)) {
- foreach (IExpr arg in f.Arguments) {
- result.AddRange(FindConjuncts(arg));
- }
- } else if (f.FunctionSymbol.Equals(Prop.Or)
- || f.FunctionSymbol.Equals(Prop.Implies)) {
- // Do nothing.
- } else {
- result.Add(e);
- }
- } else {
- result.Add(e);
- }
-
- return result;
- }
-
- private static bool IsSimpleEquality(IExpr expr, out IVariable left, out IVariable right) {
- Contract.Ensures(!Contract.Result<bool>() || Contract.ValueAtReturn(out left) != null && Contract.ValueAtReturn(out right) != null);
- left = null;
- right = null;
-
- // See if we have an equality
- IFunApp nary = expr as IFunApp;
- if (nary == null || !nary.FunctionSymbol.Equals(Value.Eq)) {
- return false;
- }
-
- // See if it is an equality of two variables
- IVariable idLeft = nary.Arguments[0] as IVariable;
- IVariable idRight = nary.Arguments[1] as IVariable;
- if (idLeft == null || idRight == null) {
- return false;
- }
-
- left = idLeft;
- right = idRight;
- return true;
- }
-
- /// <summary>
- /// Returns true iff the expression is in the form var == arithmeticExpr
- /// </summary>
- 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
- return true;
- else if (expr is IFunApp) // may be ==, +, -, /, % or an integer
- {
- IFunApp fun = (IFunApp)expr;
-
- 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/*!*/)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/*!*/)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;
-
- if (fun.FunctionSymbol.Equals(Value.Eq)
- || fun.FunctionSymbol.Equals(Int.Add)
- || fun.FunctionSymbol.Equals(Int.Sub)
- || fun.FunctionSymbol.Equals(Int.Mul)
- || fun.FunctionSymbol.Equals(Int.Div)
- || fun.FunctionSymbol.Equals(Int.Mod))
- return IsArithmeticExpr(left) && IsArithmeticExpr(right);
- else
- return false;
- }
- } else {
- return false;
- }
- }
-
- 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;
- }
-
- Elt e = (Elt)element;
- IExpr truth = propExprFactory.True;
- IExpr result = truth;
-
- 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.
- if (this.microLattice.IsBottom(value)) {
- return propExprFactory.False;
- }
-
- IExpr conjunct = this.microLattice.ToPredicate(variable, value);
-
- result = (result == truth) ? (IExpr)conjunct : (IExpr)propExprFactory.And(result, conjunct);
- }
- return result;
- }
-
-
- 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) {
- //Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<IExpr>() != null);
- return var;
- }
-
- /// <summary>
- /// Return a new expression in which each variable has been
- /// replaced by an expression representing what is known about
- /// that variable.
- /// </summary>
- 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) {
- /*MicroLattice*/
- Element value = element[var];
- if (notInlineable.Contains(var) || value == null || this.microLattice.IsTop(value)) {
- return unableToInline(var); // We don't know anything about this variable.
- } else {
- // GetFoldExpr returns null when it can yield an expression that
- // can be substituted for the variable.
- IExpr valueExpr = this.microLattice.GetFoldExpr(value);
- return (valueExpr == null) ? var : valueExpr;
- }
- }
-
- // else
-
- IFunApp fun = expr as IFunApp;
- if (fun != null) {
- IList newargs = new ArrayList();
- foreach (IExpr/*!*/ arg in fun.Arguments) {
- Contract.Assert(arg != null);
- newargs.Add(InlineVariables(element, arg, notInlineable, unableToInline));
- }
- return fun.CloneWithArguments(newargs);
- }
-
- // else
-
- IFunction lambda = expr as IFunction;
- if (lambda != null) {
- IMutableSet x = new HashSet(1);
- x.Add(lambda.Param);
-
- // Don't inline the bound variable
- return lambda.CloneWithBody(
- InlineVariables(element, lambda.Body,
- cce.NonNull(Set.Union(notInlineable, x)), unableToInline)
- );
- }
-
- // else
-
- if (expr is IUnknown) {
- return expr;
- } else {
- throw
- new System.NotImplementedException("cannot inline identifies in expression " + expr);
- }
- }
-
-
- 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, cce.NonNull(Set.Empty), new OnUnableToInline(IdentityVarToExpr));
-
- foreach (IExpr/*!*/ conjunct in FindConjuncts(expr)) {
- Contract.Assert(conjunct != null);
- IVariable left, right;
-
- if (IsSimpleEquality(conjunct, out left, out right)) {
- #region The conjunct is a simple equality
-
-
- Contract.Assert(left != null && right != null);
-
- Element leftValue = result[left], rightValue = result[right];
- if (leftValue == null) {
- leftValue = this.microLattice.Top;
- }
- if (rightValue == null) {
- rightValue = this.microLattice.Top;
- }
- Element newValue = this.microLattice.Meet(leftValue, rightValue);
- result = AddConstraint(result, left, newValue);
- result = AddConstraint(result, right, newValue);
-
- #endregion
- } else {
- ISet/*<IVariable>*/ variablesInvolved = VariablesInExpression(conjunct, Set.Empty);
-
- if (variablesInvolved.Count == 1) {
- #region We have just one variable
-
- IVariable var = null;
- 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
- } else if (IsArithmeticExpr(conjunct) && this.microLattice.UnderstandsBasicArithmetics) {
- #region We evalaute an arithmetic expression
-
- IFunApp fun = (IFunApp)conjunct;
- if (fun.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) // if it is a symbol of equality
- {
- // get the variable to be assigned
- 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
- }
- }
- }
- return result;
- }
-
-
- 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;
- } else {
- return ((Elt)element).Rename(oldName, newName, this.microLattice);
- }
- }
-
-
- 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 EquivalentExprInlineCallback {
- 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;
- {
- Contract.Requires(othervar != null);
- Contract.Ensures(Contract.Result<IExpr>() != null);
- Contract.EnsuresOnThrow<EquivalentExprException>(true);
- if (othervar.Equals(var))
- throw new EquivalentExprException();
- else
- return othervar;
- }
- }
-
- 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, cce.NonNull(Set.Empty),
- new OnUnableToInline(closure.ThrowOnUnableToInline));
- } catch (EquivalentExprException) {
- return null;
- }
- }
-
-
- /// <summary>
- /// Check to see if the given predicate holds in the given lattice element.
- ///
- /// TODO: We leave this unimplemented for now and just return maybe.
- /// </summary>
- /// <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) {
- //Contract.Requires(pred != null);
- //Contract.Requires(e != null);
- return Answer.Maybe;
- }
-
- /// <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.
- ///
- /// TODO: We leave this unimplemented for now and just return maybe.
- /// </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 override Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2) {
- //Contract.Requires(var2 != null);
- //Contract.Requires(var1 != null);
- //Contract.Requires(e != null);
- return Answer.Maybe;
- }
-
- public override void Validate() {
- base.Validate();
- microLattice.Validate();
- }
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.AbstractInterpretationFramework {
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ using Microsoft.AbstractInterpretationFramework;
+ using Microsoft.AbstractInterpretationFramework.Collections;
+
+ using Microsoft.Boogie;
+
+ using IMutableSet = Microsoft.Boogie.GSet<object>;
+ using ISet = Microsoft.Boogie.GSet<object>;
+ using Set = Microsoft.Boogie.GSet<object>;
+ using HashSet = Microsoft.Boogie.GSet<object>;
+
+ /// <summary>
+ /// Creates a lattice that works for several variables given a MicroLattice. Assumes
+ /// if one variable is bottom, then all variables are bottom.
+ /// </summary>
+ public class VariableMapLattice : Lattice {
+ private class Elt : Element {
+ /// <summary>
+ /// IsBottom(e) iff e.constraints == null
+ /// </summary>
+ /*MayBeNull*/
+ private IFunctionalMap constraints; // of type IVariable -> LATTICE_ELEMENT
+ public IFunctionalMap Constraints {
+ get {
+ return this.constraints;
+ }
+ }
+
+ private Elt(bool top) {
+ if (top) {
+ this.constraints = FunctionalHashtable.Empty;
+ } else {
+ this.constraints = null;
+ }
+ }
+
+ public override Element/*!*/ Clone() {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return new Elt(this.constraints);
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ if (constraints == null) {
+ return "<bottom>";
+ }
+ string s = "[";
+ string sep = "";
+ foreach (IVariable/*!*/ v in cce.NonNull(constraints.Keys)) {
+ Contract.Assert(v != null);
+ Element m = (Element)constraints[v];
+ s += sep + v.Name + " -> " + m;
+ sep = ", ";
+ }
+ return s + "]";
+ }
+
+ public static readonly Elt/*!*/ Top = new Elt(true);
+ public static readonly Elt/*!*/ Bottom = new Elt(false);
+
+
+ public Elt(IFunctionalMap constraints) {
+ this.constraints = constraints;
+ }
+
+ public bool IsBottom {
+ get {
+ return this.constraints == null;
+ }
+ }
+
+ public int Count {
+ get {
+ return this.constraints == null ? 0 : this.constraints.Count;
+ }
+ }
+
+ 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) {
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ if (variableComparer == null) {
+ return Variables;
+ } else {
+ ArrayList /*IVariable*/ vars = new ArrayList /*IVariable*/ (Count);
+ foreach (IVariable variable in Variables) {
+ vars.Add(variable);
+ }
+ vars.Sort(variableComparer);
+ return vars;
+ }
+ }
+
+ public Element Lookup(IVariable v) {
+ if ((v == null) || (this.constraints == null)) {
+ return null;
+ }
+ return (Element)this.constraints[v];
+ }
+
+ public Element this[IVariable/*!*/ key] {
+ get {
+ Contract.Requires(!this.IsBottom);
+ Contract.Requires(key != null);
+ Contract.Assume(this.constraints != null);
+ return (Element)constraints[key];
+ }
+ }
+
+ /// <summary>
+ /// 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) {
+ 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);
+ }
+
+ return new Elt(this.constraints.Add(var, value));
+ }
+
+ /// <summary>
+ /// 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) {
+ 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);
+ }
+
+ Contract.Assume(this.constraints != null);
+ Contract.Assert(this.constraints.Contains(var));
+
+ // this.constraints[var] = value;
+ IFunctionalMap newMap = this.constraints.Set(var, value);
+
+ return new Elt(newMap);
+ }
+
+ public Elt/*!*/ Remove(IVariable/*!*/ var, MicroLattice microLattice) {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<Elt>() != null);
+ if (this.IsBottom) {
+ return this;
+ }
+ Contract.Assume(this.constraints != null);
+ return new Elt(this.constraints.Remove(var));
+ }
+
+ 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'
+ 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() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
+ throw new System.NotImplementedException();
+ }
+
+ } // class
+
+ private readonly MicroLattice/*!*/ microLattice;
+
+ private readonly IPropExprFactory/*!*/ propExprFactory;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(microLattice != null);
+ Contract.Invariant(propExprFactory != null);
+ }
+
+
+ private readonly /*maybe null*/IComparer variableComparer;
+
+ 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 {
+ Contract.Ensures(Contract.Result<object>() != null);
+ return this.microLattice.GetType();
+ }
+ }
+
+ public override Element/*!*/ Top {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return Elt.Top;
+ }
+ }
+
+ public override Element Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return Elt.Bottom;
+ }
+ }
+
+ 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) {
+ //Contract.Requires(element != null);
+ return ((Elt)element).IsBottom;
+ }
+
+ 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) {
+ 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
+
+ if (this.microLattice.LowerThan(thisValue, thatValue)) {
+ continue;
+ } // constraint for "var" satisfies AtMost relation
+
+ return false;
+ }
+ 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 = cce.NonNull(b[var]);
+ if (this.microLattice.IsTop(thatValue)) {
+ continue;
+ } // this is a trivial constraint
+
+ return false;
+ }
+ return true;
+ }
+
+ 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
+ {
+ /*MicroLattice*/
+ Element currentValue = e[var];
+
+ if (currentValue == null) {
+ // No information currently, so we just add the new info.
+ return e.Add(var, newValue, this.microLattice);
+ } else {
+ // Otherwise, take the meet of the new and current info.
+ //return e.Add(var, this.microLattice.Meet(currentValue, newValue), this.microLattice);
+ return e.Set(var, this.microLattice.Meet(currentValue, newValue), this.microLattice);
+ }
+ }
+ return e;
+ }
+
+ 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>";
+ }
+ if (IsBottom(e)) {
+ return "<bottom>";
+ }
+
+ int k = 0;
+ System.Text.StringBuilder buffer = new System.Text.StringBuilder();
+ 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) {
+ //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) {
+ Contract.Assert(key != null);
+ Element aValue = a[key];
+ Element bValue = b[key];
+
+ if (aValue != null && bValue != null) {
+ // Keep only the variables known to both elements.
+ Element newValue = this.microLattice.Join(aValue, bValue);
+ newMap = newMap.Add(key, newValue);
+ }
+ }
+ 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) {
+ //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) {
+ Contract.Assert(key != null);
+ Element/*!*/ aValue = cce.NonNull(a[key]);
+ Element bValue = b[key];
+
+ Element newValue =
+ bValue == null ? aValue :
+ this.microLattice.Meet(aValue, bValue);
+
+ newMap = newMap.Add(key, newValue);
+ }
+ foreach (IVariable/*!*/ key in b.Variables) {
+ Contract.Assert(key != null);
+ Element aValue = a[key];
+ Element bValue = b[key];
+ Debug.Assert(bValue != null);
+
+ if (aValue == null) {
+ // It's a variable we didn't cover in the last loop.
+ newMap = newMap.Add(key, bValue);
+ }
+ }
+ return new Elt(newMap);
+ }
+
+ /// <summary>
+ /// Perform the pointwise widening of the elements in the map
+ /// </summary>
+ 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;
+
+ // Note we have to add those cases as we do not have a "NonTrivialWiden" method
+ if (a.IsBottom)
+ return new Elt(b.Constraints);
+ if (b.IsBottom)
+ return new Elt(a.Constraints);
+
+ IFunctionalMap newMap = FunctionalHashtable.Empty;
+ foreach (IVariable/*!*/ key in a.Variables) {
+ Contract.Assert(key != null);
+ Element aValue = a[key];
+ Element bValue = b[key];
+
+ if (aValue != null && bValue != null) {
+ // Keep only the variables known to both elements.
+ Element newValue = this.microLattice.Widen(aValue, bValue);
+ newMap = newMap.Add(key, newValue);
+ }
+ }
+ 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) {
+ Contract.Requires(ignoreVars != null);
+ Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<ISet>() != null);
+ HashSet s = new HashSet();
+
+ IFunApp f = e as IFunApp;
+ IFunction lambda = e as IFunction;
+
+ if (e is IVariable) {
+ if (!ignoreVars.Contains(e))
+ s.Add(e);
+ } else if (f != null) // e is IFunApp
+ {
+ foreach (IExpr/*!*/ arg in f.Arguments) {
+ Contract.Assert(arg != null);
+ s.AddAll(VariablesInExpression(arg, ignoreVars));
+ }
+ } else if (lambda != null) {
+ IMutableSet x = new HashSet(1);
+ x.Add(lambda.Param);
+
+ // Ignore the bound variable
+ s.AddAll(VariablesInExpression(lambda.Body, cce.NonNull(Set.Union(ignoreVars, x))));
+ } else if (e is IUnknown) {
+ // skip (actually, it would be appropriate to return the universal set of all variables)
+ } else {
+ Debug.Assert(false, "case not handled: " + e);
+ }
+ return s;
+ }
+
+
+ private static ArrayList/*<IExpr>*//*!*/ FindConjuncts(IExpr e) {
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ ArrayList result = new ArrayList();
+
+ IFunApp f = e as IFunApp;
+ if (f != null) {
+ if (f.FunctionSymbol.Equals(Prop.And)) {
+ foreach (IExpr arg in f.Arguments) {
+ result.AddRange(FindConjuncts(arg));
+ }
+ } else if (f.FunctionSymbol.Equals(Prop.Or)
+ || f.FunctionSymbol.Equals(Prop.Implies)) {
+ // Do nothing.
+ } else {
+ result.Add(e);
+ }
+ } else {
+ result.Add(e);
+ }
+
+ return result;
+ }
+
+ private static bool IsSimpleEquality(IExpr expr, out IVariable left, out IVariable right) {
+ Contract.Ensures(!Contract.Result<bool>() || Contract.ValueAtReturn(out left) != null && Contract.ValueAtReturn(out right) != null);
+ left = null;
+ right = null;
+
+ // See if we have an equality
+ IFunApp nary = expr as IFunApp;
+ if (nary == null || !nary.FunctionSymbol.Equals(Value.Eq)) {
+ return false;
+ }
+
+ // See if it is an equality of two variables
+ IVariable idLeft = nary.Arguments[0] as IVariable;
+ IVariable idRight = nary.Arguments[1] as IVariable;
+ if (idLeft == null || idRight == null) {
+ return false;
+ }
+
+ left = idLeft;
+ right = idRight;
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true iff the expression is in the form var == arithmeticExpr
+ /// </summary>
+ 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
+ return true;
+ else if (expr is IFunApp) // may be ==, +, -, /, % or an integer
+ {
+ IFunApp fun = (IFunApp)expr;
+
+ 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/*!*/)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/*!*/)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;
+
+ if (fun.FunctionSymbol.Equals(Value.Eq)
+ || fun.FunctionSymbol.Equals(Int.Add)
+ || fun.FunctionSymbol.Equals(Int.Sub)
+ || fun.FunctionSymbol.Equals(Int.Mul)
+ || fun.FunctionSymbol.Equals(Int.Div)
+ || fun.FunctionSymbol.Equals(Int.Mod))
+ return IsArithmeticExpr(left) && IsArithmeticExpr(right);
+ else
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ 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;
+ }
+
+ Elt e = (Elt)element;
+ IExpr truth = propExprFactory.True;
+ IExpr result = truth;
+
+ 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.
+ if (this.microLattice.IsBottom(value)) {
+ return propExprFactory.False;
+ }
+
+ IExpr conjunct = this.microLattice.ToPredicate(variable, value);
+
+ result = (result == truth) ? (IExpr)conjunct : (IExpr)propExprFactory.And(result, conjunct);
+ }
+ return result;
+ }
+
+
+ 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) {
+ //Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ return var;
+ }
+
+ /// <summary>
+ /// Return a new expression in which each variable has been
+ /// replaced by an expression representing what is known about
+ /// that variable.
+ /// </summary>
+ 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) {
+ /*MicroLattice*/
+ Element value = element[var];
+ if (notInlineable.Contains(var) || value == null || this.microLattice.IsTop(value)) {
+ return unableToInline(var); // We don't know anything about this variable.
+ } else {
+ // GetFoldExpr returns null when it can yield an expression that
+ // can be substituted for the variable.
+ IExpr valueExpr = this.microLattice.GetFoldExpr(value);
+ return (valueExpr == null) ? var : valueExpr;
+ }
+ }
+
+ // else
+
+ IFunApp fun = expr as IFunApp;
+ if (fun != null) {
+ IList newargs = new ArrayList();
+ foreach (IExpr/*!*/ arg in fun.Arguments) {
+ Contract.Assert(arg != null);
+ newargs.Add(InlineVariables(element, arg, notInlineable, unableToInline));
+ }
+ return fun.CloneWithArguments(newargs);
+ }
+
+ // else
+
+ IFunction lambda = expr as IFunction;
+ if (lambda != null) {
+ IMutableSet x = new HashSet(1);
+ x.Add(lambda.Param);
+
+ // Don't inline the bound variable
+ return lambda.CloneWithBody(
+ InlineVariables(element, lambda.Body,
+ cce.NonNull(Set.Union(notInlineable, x)), unableToInline)
+ );
+ }
+
+ // else
+
+ if (expr is IUnknown) {
+ return expr;
+ } else {
+ throw
+ new System.NotImplementedException("cannot inline identifies in expression " + expr);
+ }
+ }
+
+
+ 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, cce.NonNull(Set.Empty), new OnUnableToInline(IdentityVarToExpr));
+
+ foreach (IExpr/*!*/ conjunct in FindConjuncts(expr)) {
+ Contract.Assert(conjunct != null);
+ IVariable left, right;
+
+ if (IsSimpleEquality(conjunct, out left, out right)) {
+ #region The conjunct is a simple equality
+
+
+ Contract.Assert(left != null && right != null);
+
+ Element leftValue = result[left], rightValue = result[right];
+ if (leftValue == null) {
+ leftValue = this.microLattice.Top;
+ }
+ if (rightValue == null) {
+ rightValue = this.microLattice.Top;
+ }
+ Element newValue = this.microLattice.Meet(leftValue, rightValue);
+ result = AddConstraint(result, left, newValue);
+ result = AddConstraint(result, right, newValue);
+
+ #endregion
+ } else {
+ ISet/*<IVariable>*/ variablesInvolved = VariablesInExpression(conjunct, Set.Empty);
+
+ if (variablesInvolved.Count == 1) {
+ #region We have just one variable
+
+ IVariable var = null;
+ 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
+ } else if (IsArithmeticExpr(conjunct) && this.microLattice.UnderstandsBasicArithmetics) {
+ #region We evalaute an arithmetic expression
+
+ IFunApp fun = (IFunApp)conjunct;
+ if (fun.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) // if it is a symbol of equality
+ {
+ // get the variable to be assigned
+ 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
+ }
+ }
+ }
+ return result;
+ }
+
+
+ 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;
+ } else {
+ return ((Elt)element).Rename(oldName, newName, this.microLattice);
+ }
+ }
+
+
+ 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 EquivalentExprInlineCallback {
+ 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;
+ {
+ Contract.Requires(othervar != null);
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ Contract.EnsuresOnThrow<EquivalentExprException>(true);
+ if (othervar.Equals(var))
+ throw new EquivalentExprException();
+ else
+ return othervar;
+ }
+ }
+
+ 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, cce.NonNull(Set.Empty),
+ new OnUnableToInline(closure.ThrowOnUnableToInline));
+ } catch (EquivalentExprException) {
+ return null;
+ }
+ }
+
+
+ /// <summary>
+ /// Check to see if the given predicate holds in the given lattice element.
+ ///
+ /// TODO: We leave this unimplemented for now and just return maybe.
+ /// </summary>
+ /// <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) {
+ //Contract.Requires(pred != null);
+ //Contract.Requires(e != null);
+ return Answer.Maybe;
+ }
+
+ /// <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.
+ ///
+ /// TODO: We leave this unimplemented for now and just return maybe.
+ /// </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 override Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2) {
+ //Contract.Requires(var2 != null);
+ //Contract.Requires(var1 != null);
+ //Contract.Requires(e != null);
+ return Answer.Maybe;
+ }
+
+ public override void Validate() {
+ base.Validate();
+ microLattice.Validate();
+ }
+
+ }
+}
diff --git a/Source/AIFramework/cce.cs b/Source/AIFramework/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/AIFramework/cce.cs
+++ b/Source/AIFramework/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/AbsInt/AbsInt.csproj b/Source/AbsInt/AbsInt.csproj
index 69a2667c..359eb146 100644
--- a/Source/AbsInt/AbsInt.csproj
+++ b/Source/AbsInt/AbsInt.csproj
@@ -1,296 +1,296 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>AbsInt</RootNamespace>
- <AssemblyName>AbsInt</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for AbsInt.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\x86\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
- <OutputPath>bin\x86\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <Optimize>true</Optimize>
- <DebugType>pdbonly</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>bin\Release\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'z3apidebug|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\x86\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>bin\z3apidebug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for AbsInt.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\x86\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Numerics" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="IntervalDomain.cs" />
- <Compile Include="TrivialDomain.cs" />
- <Compile Include="NativeLattice.cs" />
- <Compile Include="Traverse.cs" />
- <Compile Include="..\version.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>AbsInt</RootNamespace>
+ <AssemblyName>BoogieAbsInt</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for AbsInt.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Release\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'z3apidebug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\z3apidebug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for AbsInt.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Numerics" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="IntervalDomain.cs" />
+ <Compile Include="TrivialDomain.cs" />
+ <Compile Include="NativeLattice.cs" />
+ <Compile Include="Traverse.cs" />
+ <Compile Include="..\version.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
</Project> \ No newline at end of file
diff --git a/Source/AbsInt/IntervalDomain.cs b/Source/AbsInt/IntervalDomain.cs
index d5a5efc9..0dd78cbb 100644
--- a/Source/AbsInt/IntervalDomain.cs
+++ b/Source/AbsInt/IntervalDomain.cs
@@ -1,1210 +1,1218 @@
-using System;
-using System.Numerics;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-namespace Microsoft.Boogie.AbstractInterpretation
-{
- class NativeIntervallDomain : NativeLattice
- {
- abstract class E_Common : NativeLattice.Element { }
- class E_Bottom : E_Common
- {
- public override Expr ToExpr() {
- return Expr.False;
- }
- }
- class E : E_Common
- {
- public readonly Node N;
- public E() { }
- public E(Node n) {
- N = n;
- }
-
- public override Expr ToExpr() {
- Expr expr = Expr.True;
- for (var n = N; n != null; n = n.Next) {
- expr = BplAnd(expr, n.ToExpr());
- }
- return expr;
- }
- }
- public class Node
- {
- public readonly Variable V; // variable has type bool or int
- // For an integer variable (Lo,Hi) indicates Lo <= V < Hi, where Lo==null means no lower bound and Hi==null means no upper bound.
- // For a real variable (Lo,Hi) indicates Lo <= V <= Hi, where Lo==null means no lower bound and Hi==null means no upper bound.
- // For a boolean variable, (Lo,Hi) is one of: (null,null) for {false,true}, (null,1) for {false}, and (1,null) for {true}.
- public readonly BigInteger? Lo;
- public readonly BigInteger? Hi;
- public Node Next; // always sorted according to StrictlyBefore; readonly after full initialization
- [Pure]
- public static bool StrictlyBefore(Variable a, Variable b) {
- Contract.Assert(a.UniqueId != b.UniqueId || a == b);
- return a.UniqueId < b.UniqueId;
- }
-
- Node(Variable v, BigInteger? lo, BigInteger? hi, Node next) {
- Contract.Requires(lo != null || hi != null); // don't accept empty constraints
- Contract.Requires(next == null || StrictlyBefore(v, next.V));
- V = v;
- Lo = lo;
- Hi = hi;
- Next = next;
- }
-
- /// <summary>
- /// This constructor leaves Next as null, allowing the caller to fill in Next to finish off the construction.
- /// </summary>
- public Node(Variable v, BigInteger? lo, BigInteger? hi) {
- Contract.Requires(lo != null || hi != null); // don't accept empty constraints
- V = v;
- Lo = lo;
- Hi = hi;
- }
-
- /// <summary>
- /// Returns a Node that has the constraints head.{V,Lo,Hi} plus
- /// all the constraints entailed by Nodes reachable from tail.
- /// Requires that "head" sorts no later than anything in "tail".
- /// Create either returns "head" itself or returns a new Node.
- /// </summary>
- public static Node Create(Node head, Node tail) {
- Contract.Requires(head != null);
- Contract.Requires(tail == null || !StrictlyBefore(tail.V, head.V));
- Contract.Requires(head != tail);
-
- if (head.Next == tail) {
- return head;
- } else if (tail != null && head.V == tail.V) {
- // incorporate both constraints into one Node
- return new Node(head.V, Max(head.Lo, tail.Lo, true), Min(head.Lo, tail.Lo, true), tail.Next);
- } else {
- return new Node(head.V, head.Lo, head.Hi, tail);
- }
- }
-
- public static void GetBounds(Node n, Variable v, out BigInteger? lo, out BigInteger? hi) {
- for (; n != null; n = n.Next) {
- if (n.V == v) {
- lo = n.Lo;
- hi = n.Hi;
- return;
- } else if (StrictlyBefore(v, n.V)) {
- break;
- }
- }
- lo = null;
- hi = null;
- }
-
- /// <summary>
- /// Return the minimum of "a" and "b". If treatNullAsUnit==true, then "null" is
- /// interpreted as positive infinity (the unit element of min); otherwise, it is
- /// treated as negative infinity (the zero element of min).
- /// </summary>
- public static BigInteger? Min(BigInteger? a, BigInteger? b, bool treatNullAsUnit) {
- if (a == null) {
- return treatNullAsUnit ? b : a;
- } else if (b == null) {
- return treatNullAsUnit ? a : b;
- } else {
- return BigInteger.Min((BigInteger)a, (BigInteger)b);
- }
- }
-
- /// <summary>
- /// Return the maximum of "a" and "b". If treatNullAsUnit==true, then "null" is
- /// interpreted as negative infinity (the unit element of max); otherwise, it is
- /// treated as positive infinity (the zero element of max).
- /// </summary>
- public static BigInteger? Max(BigInteger? a, BigInteger? b, bool treatNullAsUnit) {
- if (a == null) {
- return treatNullAsUnit ? b : a;
- } else if (b == null) {
- return treatNullAsUnit ? a : b;
- } else {
- return BigInteger.Max((BigInteger)a, (BigInteger)b);
- }
- }
-
- public static IEnumerable<Tuple<Node, Node>> Merge(Node a, Node b) {
- while (true) {
- if (a == null && b == null) {
- yield break;
- } else if (a == null || b == null) {
- yield return new Tuple<Node, Node>(a, b);
- if (a != null) { a = a.Next; } else { b = b.Next; }
- } else if (a.V == b.V) {
- yield return new Tuple<Node, Node>(a, b);
- a = a.Next; b = b.Next;
- } else if (StrictlyBefore(a.V, b.V)) {
- yield return new Tuple<Node, Node>(a, null);
- a = a.Next;
- } else {
- yield return new Tuple<Node, Node>(null, b);
- b = b.Next;
- }
- }
- }
-
- public Expr ToExpr() {
- if (!V.IsMutable && CommandLineOptions.Clo.InstrumentInfer != CommandLineOptions.InstrumentationPlaces.Everywhere) {
- // omit invariants about readonly variables
- return Expr.True;
- } else if (V.TypedIdent.Type.IsBool) {
- if (Lo == null && Hi == null) {
- return Expr.True;
- } else {
- Contract.Assert((Lo == null && (BigInteger)Hi == 1) || (Hi == null && (BigInteger)Lo == 1));
- var ide = new IdentifierExpr(Token.NoToken, V);
- return Hi == null ? ide : Expr.Not(ide);
- }
- } else if (V.TypedIdent.Type.IsInt) {
- Expr e = Expr.True;
- if (Lo != null && Hi != null && Lo + 1 == Hi) {
- // produce an equality
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type)));
- } else {
- // produce a (possibly empty) conjunction of inequalities
- if (Lo != null) {
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide));
- }
- if (Hi != null) {
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplLt(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type)));
- }
- }
- return e;
- } else if (V.TypedIdent.Type.IsReal){
- Expr e = Expr.True;
- if (Lo != null && Hi != null && Lo == Hi) {
- // produce an equality
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type)));
- } else {
- // produce a (possibly empty) conjunction of inequalities
- if (Lo != null) {
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide));
- }
- if (Hi != null) {
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplLe(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type)));
- }
- }
- return e;
- } else {
- Contract.Assert(V.TypedIdent.Type.IsFloat);
- Expr e = Expr.True;
- if (Lo != null && Hi != null && Lo == Hi)
- {
- // produce an equality
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type)));
- }
- else
- {
- // produce a (possibly empty) conjunction of inequalities
- if (Lo != null)
- {
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide));
- }
- if (Hi != null)
- {
- var ide = new IdentifierExpr(Token.NoToken, V);
- e = Expr.And(e, BplLe(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type)));
- }
- }
- return e;
- }
- }
- }
-
- static Expr NumberToExpr(BigInteger n, Type ty) {
- if (n == null) {
- return null;
- } else if (ty.IsReal) {
- return Expr.Literal(Basetypes.BigDec.FromBigInt(n));
- } else if (ty.IsFloat) {
- return Expr.Literal(Basetypes.BigFloat.FromBigInt(n, ty.FloatExponent, ty.FloatMantissa));
- } else {
- Contract.Assume(ty.IsInt);
- return Expr.Literal(Basetypes.BigNum.FromBigInt(n));
- }
- }
-
- List<BigInteger> upThresholds; // invariant: thresholds are sorted
- List<BigInteger> downThresholds; // invariant: thresholds are sorted
-
- /// <summary>
- /// Requires "thresholds" to be sorted.
- /// </summary>
- public NativeIntervallDomain() {
- upThresholds = new List<BigInteger>();
- downThresholds = new List<BigInteger>();
- }
-
- public override void Specialize(Implementation impl) {
- if (impl == null) {
- // remove thresholds
- upThresholds = new List<BigInteger>();
- downThresholds = new List<BigInteger>();
- } else {
- var tf = new ThresholdFinder(impl);
- tf.Find(out downThresholds, out upThresholds);
-#if DEBUG_PRINT
- Console.Write("DEBUG: for implementation '{0}', setting downs to [", impl.Name);
- foreach (var i in downThresholds) {
- Console.Write(" {0}", i);
- }
- Console.Write(" ] and ups to [");
- foreach (var i in upThresholds) {
- Console.Write(" {0}", i);
- }
- Console.WriteLine(" ]");
-#endif
- }
- base.Specialize(impl);
- }
-
- private E_Common top = new E();
- private E_Common bottom = new E_Bottom();
-
- public override Element Top { get { return top; } }
- public override Element Bottom { get { return bottom; } }
-
- public override bool IsTop(Element element) {
- var e = element as E;
- return e != null && e.N == null;
- }
- public override bool IsBottom(Element element) {
- return element is E_Bottom;
- }
-
- public override bool Below(Element a, Element b) {
- if (a is E_Bottom) {
- return true;
- } else if (b is E_Bottom) {
- return false;
- } else {
- var aa = (E)a;
- var bb = (E)b;
- // check if every constraint in 'bb' is implied by constraints in 'aa'
- foreach (var t in Node.Merge(aa.N, bb.N)) {
- var x = t.Item1;
- var y = t.Item2;
- if (x == null) {
- // bb constrains a variable that aa does not
- return false;
- } else if (y == null) {
- // aa constrains a variable that bb does not; that's fine
- } else if (y.Lo != null && (x.Lo == null || x.Lo < y.Lo)) {
- // bb has a Lo constraint, and either aa has no Lo constraint or it has a weaker Lo constraint
- return false;
- } else if (y.Hi != null && (x.Hi == null || y.Hi < x.Hi)) {
- // bb has a Hi o constraint, and either aa has no Hi constraint or it has a weaker Hi constraint
- return false;
- }
- }
- return true;
- }
- }
-
- public override Element Meet(Element a, Element b) {
- if (a is E_Bottom) {
- return a;
- } else if (b is E_Bottom) {
- return b;
- } else {
- var aa = (E)a;
- var bb = (E)b;
- Node head = null;
- Node prev = null;
- foreach (var t in Node.Merge(aa.N, bb.N)) {
- var x = t.Item1;
- var y = t.Item2;
- Node n;
- if (x == null) {
- n = new Node(y.V, y.Lo, y.Hi);
- } else if (y == null) {
- n = new Node(x.V, x.Lo, x.Hi);
- } else {
- var lo = Node.Max(x.Lo, y.Lo, true);
- var hi = Node.Min(x.Hi, y.Hi, true);
- // if hi<=lo (or hi<lo for reals), then we're overconstrained
- if (lo != null && hi != null && (x.V.TypedIdent.Type.IsReal ? hi < lo : hi <= lo)) {
- return bottom;
- }
- n = new Node(x.V, lo, hi);
- }
- if (head == null) {
- head = n;
- } else {
- prev.Next = n;
- }
- prev = n;
- }
- return new E(head);
- }
- }
-
- public override Element Join(Element a, Element b) {
- if (a is E_Bottom) {
- return b;
- } else if (b is E_Bottom) {
- return a;
- } else {
- var aa = (E)a;
- var bb = (E)b;
- // for each variable, take the weaker of the constraints
- Node head = null;
- Node prev = null;
- foreach (var t in Node.Merge(aa.N, bb.N)) {
- if (t.Item1 != null && t.Item2 != null) {
- var lo = Node.Min(t.Item1.Lo, t.Item2.Lo, false);
- var hi = Node.Max(t.Item1.Hi, t.Item2.Hi, false);
- if (lo != null || hi != null) {
- var n = new Node(t.Item1.V, lo, hi);
- if (head == null) {
- head = n;
- } else {
- prev.Next = n;
- }
- prev = n;
- }
- }
- }
- return new E(head);
- }
- }
-
- public override Element Widen(Element a, Element b) {
- if (a is E_Bottom) {
- return b; // since this is done just once, we maintain the ascending chains property
- } else if (b is E_Bottom) {
- return a;
- } else {
- var aa = (E)a;
- var bb = (E)b;
- // return a subset of the constraints of aa, namely those that are implied by bb
- Node head = null;
- Node prev = null;
- foreach (var t in Node.Merge(aa.N, bb.N)) {
- var x = t.Item1;
- var y = t.Item2;
- if (x != null && y != null) {
- BigInteger? lo, hi;
- lo = hi = null;
- if (x.Lo != null && y.Lo != null) {
- if (x.Lo <= y.Lo) {
- // okay, we keep the lower bound
- lo = x.Lo;
- } else {
- // set "lo" to the threshold that is below (or equal) y.Lo
- lo = RoundDown((BigInteger)y.Lo);
- }
- }
- if (x.Hi != null && y.Hi != null) {
- if (y.Hi <= x.Hi) {
- // okay, we keep the upper bound
- hi = x.Hi;
- } else {
- // set "hi" to the threshold that is above (or equal) y.Hi
- hi = RoundUp((BigInteger)y.Hi);
- }
- }
- if (lo != null || hi != null) {
- var n = new Node(x.V, lo, hi);
- if (head == null) {
- head = n;
- } else {
- prev.Next = n;
- }
- prev = n;
- }
- }
- }
- return new E(head);
- }
- }
-
- /// <summary>
- /// For a proof of correctness of this method, see Test/dafny2/Intervals.dfy.
- /// A difference is that the this method returns:
- /// let d = Dafny_RoundDown(k);
- /// return d == -1 ? null : downThresholds[d];
- /// </summary>
- BigInteger? RoundDown(BigInteger k)
- {
- if (downThresholds.Count == 0 || k < downThresholds[0]) {
- return null;
- }
- var i = 0;
- var j = downThresholds.Count - 1;
- while (i < j)
- {
- var mid = i + (j - i + 1) / 2;
- if (downThresholds[mid] <= k) {
- i = mid;
- } else {
- j = mid - 1;
- }
- }
- return downThresholds[i];
- }
-
- /// <summary>
- /// For a proof of correctness of this method, see Test/dafny2/Intervals.dfy.
- /// A difference is that the this method returns:
- /// let d = Dafny_RoundUp(k);
- /// return d == thresholds.Count ? null : upThresholds[d];
- /// </summary>
- BigInteger? RoundUp(BigInteger k)
- {
- if (upThresholds.Count == 0 || upThresholds[upThresholds.Count - 1] < k) {
- return null;
- }
- var i = 0;
- var j = upThresholds.Count - 1;
- while (i < j)
- {
- var mid = i + (j - i) / 2;
- if (upThresholds[mid] < k) {
- i = mid + 1;
- } else {
- j = mid;
- }
- }
- return upThresholds[i];
- }
-
- public override Element Constrain(Element element, Expr expr) {
- if (element is E_Bottom) {
- return element;
- } else {
- var e = (E)element;
- var c = Constraint(expr, e.N);
- return c == null ? element : Meet(element, c);
- }
- }
-
- /// <summary>
- /// Returns an Element that corresponds to the constraints implied by "expr" in the
- /// state "state".
- /// Return "null" to indicate no constraints.
- /// </summary>
- E_Common Constraint(Expr expr, Node state) {
- Variable v;
- if (IsVariable(expr, out v)) {
- var n = new Node(v, BigInteger.One, null);
- return new E(n);
- } else if (expr is LiteralExpr) {
- var e = (LiteralExpr)expr;
- return (bool)e.Val ? null : new E_Bottom();
- } else if (expr is NAryExpr) {
- var e = (NAryExpr)expr;
- if (e.Fun is UnaryOperator) {
- if (((UnaryOperator)e.Fun).Op == UnaryOperator.Opcode.Not) {
- if (IsVariable(e.Args[0], out v)) {
- var n = new Node(v, null, BigInteger.One);
- return new E(n);
- }
- }
- } else if (e.Fun is BinaryOperator) {
- var op = ((BinaryOperator)e.Fun).Op;
- var arg0 = e.Args[0];
- var arg1 = e.Args[1];
- switch (op) {
- case BinaryOperator.Opcode.Eq:
- case BinaryOperator.Opcode.Iff: {
- E_Common c = null;
- if (IsVariable(arg0, out v)) {
- BigInteger? lo, hi;
- if (PartiallyEvaluate(arg1, state, out lo, out hi)) {
- var n = new Node(v, lo, hi);
- c = new E(n);
- }
- }
- if (IsVariable(arg1, out v)) {
- BigInteger? lo, hi;
- if (PartiallyEvaluate(arg1, state, out lo, out hi)) {
- var n = new Node(v, lo, hi);
- c = c == null ? new E(n) : (E_Common)Meet(c, new E(n));
- }
- }
- return c;
- }
- case BinaryOperator.Opcode.Neq: {
- E_Common c = null;
- if (IsVariable(arg0, out v)) {
- c = ConstrainNeq(state, v, arg1);
- }
- if (IsVariable(arg1, out v)) {
- var cc = ConstrainNeq(state, v, arg0);
- if (cc != null) {
- c = c == null ? cc : (E_Common)Meet(c, cc);
- }
- }
- return c;
- }
- case BinaryOperator.Opcode.Le: {
- E_Common c = null;
- if (IsVariable(arg1, out v)) {
- BigInteger? lo, hi;
- PartiallyEvaluate(arg0, state, out lo, out hi);
- if (lo != null) {
- var n = new Node(v, lo, null);
- c = new E(n);
- }
- }
- if (IsVariable(arg0, out v)) {
- BigInteger? lo, hi;
- PartiallyEvaluate(arg1, state, out lo, out hi);
- if (hi != null) {
- var n = new Node(v, null, hi);
- c = c == null ? new E(n) : (E_Common)Meet(c, new E(n));
- }
- }
- return c;
- }
- case BinaryOperator.Opcode.Lt: {
- E_Common c = null;
- if (IsVariable(arg1, out v)) {
- BigInteger? lo, hi;
- PartiallyEvaluate(arg0, state, out lo, out hi);
- if (lo != null) {
- var n = new Node(v, v.TypedIdent.Type.IsReal ? lo : lo + 1, null);
- c = new E(n);
- }
- }
- if (IsVariable(arg0, out v)) {
- BigInteger? lo, hi;
- PartiallyEvaluate(arg1, state, out lo, out hi);
- if (hi != null) {
- var n = new Node(v, null, v.TypedIdent.Type.IsReal ? hi : hi - 1);
- c = c == null ? new E(n) : (E_Common)Meet(c, new E(n));
- }
- }
- return c;
- }
- case BinaryOperator.Opcode.Ge: {
- var tmp = arg0; arg0 = arg1; arg1 = tmp;
- goto case BinaryOperator.Opcode.Le;
- }
- case BinaryOperator.Opcode.Gt: {
- var tmp = arg0; arg0 = arg1; arg1 = tmp;
- goto case BinaryOperator.Opcode.Lt;
- }
- default:
- break;
- }
- }
- }
- return null; // approximation
- }
-
- private E ConstrainNeq(Node state, Variable v, Expr arg) {
- BigInteger? lo, hi;
- if (PartiallyEvaluate(arg, state, out lo, out hi)) {
- if (!v.TypedIdent.Type.IsReal && lo != null && hi != null && lo + 1 == hi) {
- var exclude = lo;
- // If the partially evaluated arg (whose value is "exclude") is an end-point of
- // the interval known for "v", then produce a constraint that excludes that bound.
- Node.GetBounds(state, v, out lo, out hi);
- if (lo != null && lo == exclude) {
- var n = new Node(v, lo + 1, null);
- return new E(n);
- } else if (hi != null && exclude + 1 == hi) {
- var n = new Node(v, null, exclude);
- return new E(n);
- }
- }
- }
- return null;
- }
-
- bool IsVariable(Expr expr, out Variable v) {
- var e = expr as IdentifierExpr;
- if (e == null) {
- v = null;
- return false;
- } else {
- v = e.Decl;
- return true;
- }
- }
-
- public override Element Update(Element element, AssignCmd cmd) {
- if (element is E_Bottom) {
- return element;
- }
- var e = (E)element;
- var nn = e.N;
- Contract.Assert(cmd.Lhss.Count == cmd.Rhss.Count);
- for (int i = 0; i < cmd.Lhss.Count; i++) {
- var lhs = cmd.Lhss[i];
- var rhs = cmd.Rhss[i];
- BigInteger? lo;
- BigInteger? hi;
- PartiallyEvaluate(rhs, e.N, out lo, out hi);
- nn = UpdateOne(nn, lhs.DeepAssignedVariable, lo, hi);
- }
- return new E(nn);
- }
-
- bool PartiallyEvaluate(Expr rhs, Node node, out BigInteger? lo, out BigInteger? hi) {
- var pe = new PEVisitor(node);
- pe.VisitExpr(rhs);
- lo = pe.Lo;
- hi = pe.Hi;
- return lo != null || hi != null;
- }
-
- class PEVisitor : ReadOnlyVisitor
- {
- public BigInteger? Lo;
- public BigInteger? Hi;
-
- readonly BigInteger one = BigInteger.One;
-
- Node N;
- public PEVisitor(Node n) {
- N = n;
- }
-
- // Override visitors for all expressions that can return a boolean, integer, or real result
-
- public override Expr VisitExpr(Expr node) {
- Lo = Hi = null;
- return base.VisitExpr(node);
- }
- public override Expr VisitLiteralExpr(LiteralExpr node) {
- if (node.Val is BigNum) {
- var n = ((BigNum)node.Val).ToBigInteger;
- Lo = n;
- Hi = n + 1;
- } else if (node.Val is BigDec) {
- BigInteger floor, ceiling;
- ((BigDec)node.Val).FloorCeiling(out floor, out ceiling);
- Lo = floor;
- Hi = ceiling;
- } else if (node.Val is BigFloat) {
- BigNum floor, ceiling;
- ((BigFloat)node.Val).FloorCeiling(out floor, out ceiling);
- Lo = floor.ToBigInteger;
- Hi = ceiling.ToBigInteger;
- } else if (node.Val is bool) {
- if ((bool)node.Val) {
- // true
- Lo = one;
- Hi = null;
- } else {
- // false
- Lo = null;
- Hi = one;
- }
- }
- return node;
- }
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- if (node.Type.IsBool || node.Type.IsInt || node.Type.IsReal) {
- Node.GetBounds(N, node.Decl, out Lo, out Hi);
- }
- return node;
- }
- public override Expr VisitNAryExpr(NAryExpr node) {
- if (node.Fun is UnaryOperator) {
- var op = (UnaryOperator)node.Fun;
- Contract.Assert(node.Args.Count == 1);
- if (op.Op == UnaryOperator.Opcode.Neg) {
- BigInteger? lo, hi;
- VisitExpr(node.Args[0]);
- lo = Lo; hi = Hi;
- if (hi != null) {
- Lo = node.Type.IsReal ? -hi : 1 - hi;
- }
- if (lo != null) {
- Hi = node.Type.IsReal ? -lo : 1 - lo;
- }
- }
- else if (op.Op == UnaryOperator.Opcode.Not) {
- VisitExpr(node.Args[0]);
- Contract.Assert((Lo == null && Hi == null) ||
- (Lo == null && (BigInteger)Hi == 1) ||
- (Hi == null && (BigInteger)Lo == 1));
- var tmp = Lo;
- Lo = Hi;
- Hi = tmp;
- }
- } else if (node.Fun is BinaryOperator) {
- var op = (BinaryOperator)node.Fun;
- Contract.Assert(node.Args.Count == 2);
- BigInteger? lo0, hi0, lo1, hi1;
- VisitExpr(node.Args[0]);
- lo0 = Lo; hi0 = Hi;
- VisitExpr(node.Args[1]);
- lo1 = Lo; hi1 = Hi;
- Lo = Hi = null;
- var isReal = node.Args[0].Type.IsReal;
- switch (op.Op) {
- case BinaryOperator.Opcode.And:
- if (hi0 != null || hi1 != null) {
- // one operand is definitely false, thus so is the result
- Lo = null; Hi = one;
- } else if (lo0 != null && lo1 != null) {
- // both operands are definitely true, thus so is the result
- Lo = one; Hi = null;
- }
- break;
- case BinaryOperator.Opcode.Or:
- if (lo0 != null || lo1 != null) {
- // one operand is definitely true, thus so is the result
- Lo = one; Hi = null;
- } else if (hi0 != null && hi1 != null) {
- // both operands are definitely false, thus so is the result
- Lo = null; Hi = one;
- }
- break;
- case BinaryOperator.Opcode.Imp:
- if (hi0 != null || lo1 != null) {
- // either arg0 false or arg1 is true, so the result is true
- Lo = one; Hi = null;
- } else if (lo0 != null && hi1 != null) {
- // arg0 is true and arg1 is false, so the result is false
- Lo = null; Hi = one;
- }
- break;
- case BinaryOperator.Opcode.Iff:
- if (lo0 != null && lo1 != null) {
- Lo = one; Hi = null;
- } else if (hi0 != null && hi1 != null) {
- Lo = one; Hi = null;
- } else if (lo0 != null && hi1 != null) {
- Lo = null; Hi = one;
- } else if (hi0 != null && lo1 != null) {
- Lo = null; Hi = one;
- }
- if (op.Op == BinaryOperator.Opcode.Neq) {
- var tmp = Lo; Lo = Hi; Hi = tmp;
- }
- break;
- case BinaryOperator.Opcode.Eq:
- case BinaryOperator.Opcode.Neq:
- if (node.Args[0].Type.IsBool) {
- goto case BinaryOperator.Opcode.Iff;
- }
- // For Eq:
- // If the (lo0,hi0) and (lo1,hi1) ranges do not overlap, the answer is false.
- // If both ranges are the same unit range, then the answer is true.
- if (hi0 != null && lo1 != null && (isReal ? hi0 < lo1 : hi0 <= lo1)) {
- // no overlap
- Lo = null; Hi = one;
- } else if (lo0 != null && hi1 != null && (isReal ? hi1 < lo0 : hi1 <= lo0)) {
- Lo = null; Hi = one;
- // no overlaop
- } else if (lo0 != null && hi0 != null && lo1 != null && hi1 != null &&
- lo0 == lo1 && hi0 == hi1 && // ranges are the same
- (isReal ? lo0 == hi0 : lo0 + 1 == hi0)) { // unit range
- // both ranges are the same unit range
- Lo = one; Hi = null;
- }
- if (op.Op == BinaryOperator.Opcode.Neq) {
- var tmp = Lo; Lo = Hi; Hi = tmp;
- }
- break;
- case BinaryOperator.Opcode.Le:
- if (isReal) {
- // If hi0 <= lo1, then the answer is true.
- // If hi1 < lo0, then the answer is false.
- if (hi0 != null && lo1 != null && hi0 <= lo1) {
- Lo = one; Hi = null;
- } else if (hi1 != null && lo0 != null && hi1 < lo0) {
- Lo = null; Hi = one;
- }
- } else {
- // If hi0 - 1 <= lo1, then the answer is true.
- // If hi1 <= lo0, then the answer is false.
- if (hi0 != null && lo1 != null && hi0 - 1 <= lo1) {
- Lo = one; Hi = null;
- } else if (lo0 != null && hi1 != null && hi1 <= lo0) {
- Lo = null; Hi = one;
- }
- }
- break;
- case BinaryOperator.Opcode.Lt:
- if (isReal) {
- // If hi0 < lo1, then the answer is true.
- // If hi1 <= lo0, then the answer is false.
- if (hi0 != null && lo1 != null && hi0 < lo1) {
- Lo = one; Hi = null;
- } else if (hi1 != null && lo0 != null && hi1 <= lo0) {
- Lo = null; Hi = one;
- }
- } else {
- // If hi0 <= lo1, then the answer is true.
- // If hi1 - 1 <= lo0, then the answer is false.
- if (hi0 != null && lo1 != null && hi0 <= lo1) {
- Lo = one; Hi = null;
- } else if (lo0 != null && hi1 != null && hi1 - 1 <= lo0) {
- Lo = null; Hi = one;
- }
- }
- break;
- case BinaryOperator.Opcode.Gt:
- // swap the operands and then continue as Lt
- {
- var tmp = lo0; lo0 = lo1; lo1 = tmp;
- tmp = hi0; hi0 = hi1; hi1 = tmp;
- }
- goto case BinaryOperator.Opcode.Lt;
- case BinaryOperator.Opcode.Ge:
- // swap the operands and then continue as Le
- {
- var tmp = lo0; lo0 = lo1; lo1 = tmp;
- tmp = hi0; hi0 = hi1; hi1 = tmp;
- }
- goto case BinaryOperator.Opcode.Le;
- case BinaryOperator.Opcode.Add:
- if (lo0 != null && lo1 != null) {
- Lo = lo0 + lo1;
- }
- if (hi0 != null && hi1 != null) {
- Hi = isReal ? hi0 + hi1 : hi0 + hi1 - 1;
- }
- break;
- case BinaryOperator.Opcode.Sub:
- if (lo0 != null && hi1 != null) {
- Lo = isReal ? lo0 - hi1 : lo0 - hi1 + 1;
- }
- if (hi0 != null && lo1 != null) {
- Hi = hi0 - lo1;
- }
- break;
- case BinaryOperator.Opcode.Mul:
- // this uses an incomplete approximation that could be tightened up
- if (lo0 != null && lo1 != null) {
- if (0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
- Lo = lo0 * lo1;
- Hi = hi0 == null || hi1 == null ? null : isReal ? hi0 * hi1 : (hi0 - 1) * (hi1 - 1) + 1;
- } else if ((BigInteger)lo0 < 0 && (BigInteger)lo1 < 0) {
- Lo = null; // approximation
- Hi = isReal ? lo0 * lo1 : lo0 * lo1 + 1;
- }
- }
- break;
- case BinaryOperator.Opcode.Div:
- // this uses an incomplete approximation that could be tightened up
- if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
- Lo = BigInteger.Zero;
- Hi = hi0;
- }
- break;
- case BinaryOperator.Opcode.Mod:
- // this uses an incomplete approximation that could be tightened up
- if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
- Lo = BigInteger.Zero;
- Hi = hi1;
- }
- break;
- case BinaryOperator.Opcode.RealDiv:
- // this uses an incomplete approximation that could be tightened up
- if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
- Lo = BigInteger.Zero;
- Hi = 1 <= (BigInteger)lo1 ? hi0 : null;
- }
- break;
- case BinaryOperator.Opcode.Pow:
- // this uses an incomplete approximation that could be tightened up
- if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
- Lo = 1 <= (BigInteger)lo1 ? BigInteger.One : BigInteger.Zero;
- Hi = hi1;
- }
- break;
- default:
- break;
- }
- } else if (node.Fun is IfThenElse) {
- var op = (IfThenElse)node.Fun;
- Contract.Assert(node.Args.Count == 3);
- BigInteger? guardLo, guardHi, lo0, hi0, lo1, hi1;
- VisitExpr(node.Args[0]);
- guardLo = Lo; guardHi = Hi;
- VisitExpr(node.Args[1]);
- lo0 = Lo; hi0 = Hi;
- VisitExpr(node.Args[2]);
- lo1 = Lo; hi1 = Hi;
- Contract.Assert(guardLo == null || guardHi == null); // this is a consequence of the guard being boolean
- if (guardLo != null) {
- // guard is always true
- Lo = lo0; Hi = hi0;
- } else if (guardHi != null) {
- // guard is always false
- Lo = lo1; Hi = hi1;
- } else {
- // we don't know which branch will be taken, so join the information from the two branches
- Lo = Node.Min(lo0, lo1, false);
- Hi = Node.Max(hi0, hi1, false);
- }
- } else if (node.Fun is FunctionCall) {
- var call = (FunctionCall)node.Fun;
- // See if this is an identity function, which we do by checking: that the function has
- // exactly one argument and the function has been marked by the user with the attribute {:identity}
- bool claimsToBeIdentity = false;
- if (call.ArgumentCount == 1 && call.Func.CheckBooleanAttribute("identity", ref claimsToBeIdentity) && claimsToBeIdentity && node.Args[0].Type.Equals(node.Type)) {
- VisitExpr(node.Args[0]);
- }
- }
- return node;
- }
- public override BinderExpr VisitBinderExpr(BinderExpr node) {
- // don't recurse on subexpression
- return node;
- }
- public override Expr VisitOldExpr(OldExpr node) {
- // don't recurse on subexpression
- return node;
- }
- public override Expr VisitCodeExpr(CodeExpr node) {
- // don't recurse on subexpression
- return node;
- }
- public override Expr VisitBvConcatExpr(BvConcatExpr node) {
- // don't recurse on subexpression
- return node;
- }
- public override Expr VisitBvExtractExpr(BvExtractExpr node) {
- // don't recurse on subexpression
- return node;
- }
- }
-
- public override Element Eliminate(Element element, Variable v) {
- if (element is E_Bottom) {
- return element;
- }
- var e = (E)element;
- var nn = UpdateOne(e.N, v, null, null);
- if (nn == e.N) {
- return element;
- } else {
- return new E(nn);
- }
- }
-
- Node UpdateOne(Node nn, Variable v, BigInteger? lo, BigInteger? hi) {
- var orig = nn;
- Node head = null;
- Node prev = null;
- var foundV = false;
- for (; nn != null && !Node.StrictlyBefore(v, nn.V); nn = nn.Next) {
- if (nn.V == v) {
- foundV = true;
- nn = nn.Next;
- break; // we found the place where the new node goes
- } else {
- var n = new Node(nn.V, nn.Lo, nn.Hi); // copy this Node
- if (head == null) {
- head = n;
- } else {
- prev.Next = n;
- }
- prev = n;
- }
- }
- Node rest;
- if (lo == null && hi == null) {
- // eliminate all information about "v"
- if (!foundV) {
- return orig;
- }
- rest = nn;
- } else {
- rest = new Node(v, lo, hi);
- rest.Next = nn;
- }
- if (head == null) {
- head = rest;
- } else {
- prev.Next = rest;
- }
- return head;
- }
-
- /// <summary>
- /// Return a resolved/type-checked expression that represents the conjunction of a and b.
- /// Requires a and b to be resolved and type checked already.
- /// </summary>
- public static Expr BplAnd(Expr a, Expr b) {
- if (a == Expr.True) {
- return b;
- } else if (b == Expr.True) {
- return a;
- } else {
- var nary = Expr.Binary(BinaryOperator.Opcode.And, a, b);
- nary.Type = Type.Bool;
- nary.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- return nary;
- }
- }
-
- /// <summary>
- /// Return a resolved/type-checked expression that represents a EQUALS b.
- /// Requires a and b to be resolved and type checked already.
- /// </summary>
- public static Expr BplEq(Expr a, Expr b) {
- var e = Expr.Eq(a, b);
- e.Type = Type.Bool;
- return e;
- }
-
- /// <summary>
- /// Return a resolved/type-checked expression that represents a LESS-EQUAL b.
- /// Requires a and b to be resolved and type checked already.
- /// </summary>
- public static Expr BplLe(Expr a, Expr b) {
- var e = Expr.Le(a, b);
- e.Type = Type.Bool;
- return e;
- }
- /// <summary>
- /// Return a resolved/type-checked expression that represents a LESS b.
- /// Requires a and b to be resolved and type checked already.
- /// </summary>
- public static Expr BplLt(Expr a, Expr b) {
- var e = Expr.Lt(a, b);
- e.Type = Type.Bool;
- return e;
- }
- }
-
- public class ThresholdFinder : ReadOnlyVisitor
- {
- readonly Implementation Impl;
- public ThresholdFinder(Implementation impl) {
- Contract.Requires(impl != null);
- Impl = impl;
- }
- HashSet<BigInteger> downs = new HashSet<BigInteger>();
- HashSet<BigInteger> ups = new HashSet<BigInteger>();
- public void Find(out List<BigInteger> downThresholds, out List<BigInteger> upThresholds) {
- // always include -1, 0, 1 as down-thresholds
- downs.Clear();
- downs.Add(-1);
- downs.Add(0);
- downs.Add(1);
- // always include 0 and 1 as up-thresholds
- ups.Clear();
- ups.Add(0);
- ups.Add(1);
-
- foreach (Requires p in Impl.Proc.Requires) {
- Visit(p.Condition);
- }
- foreach (Ensures p in Impl.Proc.Ensures) {
- Visit(p.Condition);
- }
- foreach (var b in Impl.Blocks) {
- foreach (Cmd c in b.Cmds) {
- Visit(c);
- }
- }
-
- // convert the HashSets to sorted Lists and return
- downThresholds = new List<BigInteger>();
- foreach (var i in downs) {
- downThresholds.Add(i);
- }
- downThresholds.Sort();
- upThresholds = new List<BigInteger>();
- foreach (var i in ups) {
- upThresholds.Add(i);
- }
- upThresholds.Sort();
- }
-
- public override Expr VisitNAryExpr(NAryExpr node) {
- if (node.Fun is BinaryOperator) {
- var op = (BinaryOperator)node.Fun;
- Contract.Assert(node.Args.Count == 2);
- var arg0 = node.Args[0];
- var arg1 = node.Args[1];
- var offset = arg0.Type.IsReal ? 0 : 1;
- BigInteger? k;
- switch (op.Op) {
- case BinaryOperator.Opcode.Eq:
- case BinaryOperator.Opcode.Neq:
- k = AsIntLiteral(arg0);
- if (k != null) {
- var i = (BigInteger)k;
- downs.Add(i - 1);
- downs.Add(i);
- ups.Add(i + 1);
- ups.Add(i + 2);
- }
- k = AsIntLiteral(arg1);
- if (k != null) {
- var i = (BigInteger)k;
- downs.Add(i - 1);
- downs.Add(i);
- ups.Add(i + 1);
- ups.Add(i + 2);
- }
- break;
- case BinaryOperator.Opcode.Le:
- k = AsIntLiteral(arg0);
- if (k != null) {
- var i = (BigInteger)k;
- downs.Add(i - 1);
- downs.Add(i);
- }
- k = AsIntLiteral(arg1);
- if (k != null) {
- var i = (BigInteger)k;
- ups.Add(i + offset);
- ups.Add(i + 1 + offset);
- }
- break;
- case BinaryOperator.Opcode.Lt:
- k = AsIntLiteral(arg0);
- if (k != null) {
- var i = (BigInteger)k;
- downs.Add(i );
- downs.Add(i + 1);
- }
- k = AsIntLiteral(arg1);
- if (k != null) {
- var i = (BigInteger)k;
- ups.Add(i - 1 + offset);
- ups.Add(i + offset);
- }
- break;
- case BinaryOperator.Opcode.Ge:
- { var tmp = arg0; arg0 = arg1; arg1 = tmp; }
- goto case BinaryOperator.Opcode.Le;
- case BinaryOperator.Opcode.Gt:
- { var tmp = arg0; arg0 = arg1; arg1 = tmp; }
- goto case BinaryOperator.Opcode.Lt;
- default:
- break;
- }
- }
- return base.VisitNAryExpr(node);
- }
-
- BigInteger? AsIntLiteral(Expr e) {
- var lit = e as LiteralExpr;
- if (lit != null && lit.isBigNum) {
- BigNum bn = lit.asBigNum;
- return bn.ToBigInteger;
- }
- return null;
- }
- }
-
-}
+using System;
+using System.Numerics;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+namespace Microsoft.Boogie.AbstractInterpretation
+{
+ class NativeIntervallDomain : NativeLattice
+ {
+ abstract class E_Common : NativeLattice.Element { }
+ class E_Bottom : E_Common
+ {
+ public override Expr ToExpr() {
+ return Expr.False;
+ }
+ }
+ class E : E_Common
+ {
+ public readonly Node N;
+ public E() { }
+ public E(Node n) {
+ N = n;
+ }
+
+ public override Expr ToExpr() {
+ Expr expr = Expr.True;
+ for (var n = N; n != null; n = n.Next) {
+ expr = BplAnd(expr, n.ToExpr());
+ }
+ return expr;
+ }
+ }
+ public class Node
+ {
+ public readonly Variable V; // variable has type bool or int
+ // For an integer variable (Lo,Hi) indicates Lo <= V < Hi, where Lo==null means no lower bound and Hi==null means no upper bound.
+ // For a real variable (Lo,Hi) indicates Lo <= V <= Hi, where Lo==null means no lower bound and Hi==null means no upper bound.
+ // For a boolean variable, (Lo,Hi) is one of: (null,null) for {false,true}, (null,1) for {false}, and (1,null) for {true}.
+ public readonly BigInteger? Lo;
+ public readonly BigInteger? Hi;
+ public Node Next; // always sorted according to StrictlyBefore; readonly after full initialization
+ [Pure]
+ public static bool StrictlyBefore(Variable a, Variable b) {
+ Contract.Assert(a.UniqueId != b.UniqueId || a == b);
+ return a.UniqueId < b.UniqueId;
+ }
+
+ Node(Variable v, BigInteger? lo, BigInteger? hi, Node next) {
+ Contract.Requires(lo != null || hi != null); // don't accept empty constraints
+ Contract.Requires(next == null || StrictlyBefore(v, next.V));
+ V = v;
+ Lo = lo;
+ Hi = hi;
+ Next = next;
+ }
+
+ /// <summary>
+ /// This constructor leaves Next as null, allowing the caller to fill in Next to finish off the construction.
+ /// </summary>
+ public Node(Variable v, BigInteger? lo, BigInteger? hi) {
+ Contract.Requires(lo != null || hi != null); // don't accept empty constraints
+ V = v;
+ Lo = lo;
+ Hi = hi;
+ }
+
+ /// <summary>
+ /// Returns a Node that has the constraints head.{V,Lo,Hi} plus
+ /// all the constraints entailed by Nodes reachable from tail.
+ /// Requires that "head" sorts no later than anything in "tail".
+ /// Create either returns "head" itself or returns a new Node.
+ /// </summary>
+ public static Node Create(Node head, Node tail) {
+ Contract.Requires(head != null);
+ Contract.Requires(tail == null || !StrictlyBefore(tail.V, head.V));
+ Contract.Requires(head != tail);
+
+ if (head.Next == tail) {
+ return head;
+ } else if (tail != null && head.V == tail.V) {
+ // incorporate both constraints into one Node
+ return new Node(head.V, Max(head.Lo, tail.Lo, true), Min(head.Lo, tail.Lo, true), tail.Next);
+ } else {
+ return new Node(head.V, head.Lo, head.Hi, tail);
+ }
+ }
+
+ public static void GetBounds(Node n, Variable v, out BigInteger? lo, out BigInteger? hi) {
+ for (; n != null; n = n.Next) {
+ if (n.V == v) {
+ lo = n.Lo;
+ hi = n.Hi;
+ return;
+ } else if (StrictlyBefore(v, n.V)) {
+ break;
+ }
+ }
+ lo = null;
+ hi = null;
+ }
+
+ /// <summary>
+ /// Return the minimum of "a" and "b". If treatNullAsUnit==true, then "null" is
+ /// interpreted as positive infinity (the unit element of min); otherwise, it is
+ /// treated as negative infinity (the zero element of min).
+ /// </summary>
+ public static BigInteger? Min(BigInteger? a, BigInteger? b, bool treatNullAsUnit) {
+ if (a == null) {
+ return treatNullAsUnit ? b : a;
+ } else if (b == null) {
+ return treatNullAsUnit ? a : b;
+ } else {
+ return BigInteger.Min((BigInteger)a, (BigInteger)b);
+ }
+ }
+
+ /// <summary>
+ /// Return the maximum of "a" and "b". If treatNullAsUnit==true, then "null" is
+ /// interpreted as negative infinity (the unit element of max); otherwise, it is
+ /// treated as positive infinity (the zero element of max).
+ /// </summary>
+ public static BigInteger? Max(BigInteger? a, BigInteger? b, bool treatNullAsUnit) {
+ if (a == null) {
+ return treatNullAsUnit ? b : a;
+ } else if (b == null) {
+ return treatNullAsUnit ? a : b;
+ } else {
+ return BigInteger.Max((BigInteger)a, (BigInteger)b);
+ }
+ }
+
+ public static IEnumerable<Tuple<Node, Node>> Merge(Node a, Node b) {
+ while (true) {
+ if (a == null && b == null) {
+ yield break;
+ } else if (a == null || b == null) {
+ yield return new Tuple<Node, Node>(a, b);
+ if (a != null) { a = a.Next; } else { b = b.Next; }
+ } else if (a.V == b.V) {
+ yield return new Tuple<Node, Node>(a, b);
+ a = a.Next; b = b.Next;
+ } else if (StrictlyBefore(a.V, b.V)) {
+ yield return new Tuple<Node, Node>(a, null);
+ a = a.Next;
+ } else {
+ yield return new Tuple<Node, Node>(null, b);
+ b = b.Next;
+ }
+ }
+ }
+
+ public Expr ToExpr() {
+ if (!V.IsMutable && CommandLineOptions.Clo.InstrumentInfer != CommandLineOptions.InstrumentationPlaces.Everywhere) {
+ // omit invariants about readonly variables
+ return Expr.True;
+ } else if (V.TypedIdent.Type.IsBool) {
+ if (Lo == null && Hi == null) {
+ return Expr.True;
+ } else {
+ Contract.Assert((Lo == null && (BigInteger)Hi == 1) || (Hi == null && (BigInteger)Lo == 1));
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ return Hi == null ? ide : Expr.Not(ide);
+ }
+ } else if (V.TypedIdent.Type.IsInt) {
+ Expr e = Expr.True;
+ if (Lo != null && Hi != null && Lo + 1 == Hi) {
+ // produce an equality
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type)));
+ } else {
+ // produce a (possibly empty) conjunction of inequalities
+ if (Lo != null) {
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide));
+ }
+ if (Hi != null) {
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplLt(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type)));
+ }
+ }
+ return e;
+ } else if (V.TypedIdent.Type.IsReal){
+ Expr e = Expr.True;
+ if (Lo != null && Hi != null && Lo == Hi) {
+ // produce an equality
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type)));
+ } else {
+ // produce a (possibly empty) conjunction of inequalities
+ if (Lo != null) {
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide));
+ }
+ if (Hi != null) {
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplLe(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type)));
+ }
+ }
+ return e;
+ } else {
+ Contract.Assert(V.TypedIdent.Type.IsFloat);
+ Expr e = Expr.True;
+ if (Lo != null && Hi != null && Lo == Hi)
+ {
+ // produce an equality
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type)));
+ }
+ else
+ {
+ // produce a (possibly empty) conjunction of inequalities
+ if (Lo != null)
+ {
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide));
+ }
+ if (Hi != null)
+ {
+ var ide = new IdentifierExpr(Token.NoToken, V);
+ e = Expr.And(e, BplLe(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type)));
+ }
+ }
+ return e;
+ }
+ }
+ }
+
+ static Expr NumberToExpr(BigInteger n, Type ty) {
+ if (n == null) {
+ return null;
+ } else if (ty.IsReal) {
+ return Expr.Literal(Basetypes.BigDec.FromBigInt(n));
+ } else if (ty.IsFloat) {
+ return Expr.Literal(Basetypes.BigFloat.FromBigInt(n, ty.FloatExponent, ty.FloatMantissa));
+ } else {
+ Contract.Assume(ty.IsInt);
+ return Expr.Literal(Basetypes.BigNum.FromBigInt(n));
+ }
+ }
+
+ List<BigInteger> upThresholds; // invariant: thresholds are sorted
+ List<BigInteger> downThresholds; // invariant: thresholds are sorted
+
+ /// <summary>
+ /// Requires "thresholds" to be sorted.
+ /// </summary>
+ public NativeIntervallDomain() {
+ upThresholds = new List<BigInteger>();
+ downThresholds = new List<BigInteger>();
+ }
+
+ public override void Specialize(Implementation impl) {
+ if (impl == null) {
+ // remove thresholds
+ upThresholds = new List<BigInteger>();
+ downThresholds = new List<BigInteger>();
+ } else {
+ var tf = new ThresholdFinder(impl);
+ tf.Find(out downThresholds, out upThresholds);
+#if DEBUG_PRINT
+ Console.Write("DEBUG: for implementation '{0}', setting downs to [", impl.Name);
+ foreach (var i in downThresholds) {
+ Console.Write(" {0}", i);
+ }
+ Console.Write(" ] and ups to [");
+ foreach (var i in upThresholds) {
+ Console.Write(" {0}", i);
+ }
+ Console.WriteLine(" ]");
+#endif
+ }
+ base.Specialize(impl);
+ }
+
+ private E_Common top = new E();
+ private E_Common bottom = new E_Bottom();
+
+ public override Element Top { get { return top; } }
+ public override Element Bottom { get { return bottom; } }
+
+ public override bool IsTop(Element element) {
+ var e = element as E;
+ return e != null && e.N == null;
+ }
+ public override bool IsBottom(Element element) {
+ return element is E_Bottom;
+ }
+
+ public override bool Below(Element a, Element b) {
+ if (a is E_Bottom) {
+ return true;
+ } else if (b is E_Bottom) {
+ return false;
+ } else {
+ var aa = (E)a;
+ var bb = (E)b;
+ // check if every constraint in 'bb' is implied by constraints in 'aa'
+ foreach (var t in Node.Merge(aa.N, bb.N)) {
+ var x = t.Item1;
+ var y = t.Item2;
+ if (x == null) {
+ // bb constrains a variable that aa does not
+ return false;
+ } else if (y == null) {
+ // aa constrains a variable that bb does not; that's fine
+ } else if (y.Lo != null && (x.Lo == null || x.Lo < y.Lo)) {
+ // bb has a Lo constraint, and either aa has no Lo constraint or it has a weaker Lo constraint
+ return false;
+ } else if (y.Hi != null && (x.Hi == null || y.Hi < x.Hi)) {
+ // bb has a Hi o constraint, and either aa has no Hi constraint or it has a weaker Hi constraint
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ public override Element Meet(Element a, Element b) {
+ if (a is E_Bottom) {
+ return a;
+ } else if (b is E_Bottom) {
+ return b;
+ } else {
+ var aa = (E)a;
+ var bb = (E)b;
+ Node head = null;
+ Node prev = null;
+ foreach (var t in Node.Merge(aa.N, bb.N)) {
+ var x = t.Item1;
+ var y = t.Item2;
+ Node n;
+ if (x == null) {
+ n = new Node(y.V, y.Lo, y.Hi);
+ } else if (y == null) {
+ n = new Node(x.V, x.Lo, x.Hi);
+ } else {
+ var lo = Node.Max(x.Lo, y.Lo, true);
+ var hi = Node.Min(x.Hi, y.Hi, true);
+ // if hi<=lo (or hi<lo for reals), then we're overconstrained
+ if (lo != null && hi != null && (x.V.TypedIdent.Type.IsReal ? hi < lo : hi <= lo)) {
+ return bottom;
+ }
+ n = new Node(x.V, lo, hi);
+ }
+ if (head == null) {
+ head = n;
+ } else {
+ prev.Next = n;
+ }
+ prev = n;
+ }
+ return new E(head);
+ }
+ }
+
+ public override Element Join(Element a, Element b) {
+ if (a is E_Bottom) {
+ return b;
+ } else if (b is E_Bottom) {
+ return a;
+ } else {
+ var aa = (E)a;
+ var bb = (E)b;
+ // for each variable, take the weaker of the constraints
+ Node head = null;
+ Node prev = null;
+ foreach (var t in Node.Merge(aa.N, bb.N)) {
+ if (t.Item1 != null && t.Item2 != null) {
+ var lo = Node.Min(t.Item1.Lo, t.Item2.Lo, false);
+ var hi = Node.Max(t.Item1.Hi, t.Item2.Hi, false);
+ if (lo != null || hi != null) {
+ var n = new Node(t.Item1.V, lo, hi);
+ if (head == null) {
+ head = n;
+ } else {
+ prev.Next = n;
+ }
+ prev = n;
+ }
+ }
+ }
+ return new E(head);
+ }
+ }
+
+ public override Element Widen(Element a, Element b) {
+ if (a is E_Bottom) {
+ return b; // since this is done just once, we maintain the ascending chains property
+ } else if (b is E_Bottom) {
+ return a;
+ } else {
+ var aa = (E)a;
+ var bb = (E)b;
+ // return a subset of the constraints of aa, namely those that are implied by bb
+ Node head = null;
+ Node prev = null;
+ foreach (var t in Node.Merge(aa.N, bb.N)) {
+ var x = t.Item1;
+ var y = t.Item2;
+ if (x != null && y != null) {
+ BigInteger? lo, hi;
+ lo = hi = null;
+ if (x.Lo != null && y.Lo != null) {
+ if (x.Lo <= y.Lo) {
+ // okay, we keep the lower bound
+ lo = x.Lo;
+ } else {
+ // set "lo" to the threshold that is below (or equal) y.Lo
+ lo = RoundDown((BigInteger)y.Lo);
+ }
+ }
+ if (x.Hi != null && y.Hi != null) {
+ if (y.Hi <= x.Hi) {
+ // okay, we keep the upper bound
+ hi = x.Hi;
+ } else {
+ // set "hi" to the threshold that is above (or equal) y.Hi
+ hi = RoundUp((BigInteger)y.Hi);
+ }
+ }
+ if (lo != null || hi != null) {
+ var n = new Node(x.V, lo, hi);
+ if (head == null) {
+ head = n;
+ } else {
+ prev.Next = n;
+ }
+ prev = n;
+ }
+ }
+ }
+ return new E(head);
+ }
+ }
+
+ /// <summary>
+ /// For a proof of correctness of this method, see Test/dafny2/Intervals.dfy.
+ /// A difference is that the this method returns:
+ /// let d = Dafny_RoundDown(k);
+ /// return d == -1 ? null : downThresholds[d];
+ /// </summary>
+ BigInteger? RoundDown(BigInteger k)
+ {
+ if (downThresholds.Count == 0 || k < downThresholds[0]) {
+ return null;
+ }
+ var i = 0;
+ var j = downThresholds.Count - 1;
+ while (i < j)
+ {
+ var mid = i + (j - i + 1) / 2;
+ if (downThresholds[mid] <= k) {
+ i = mid;
+ } else {
+ j = mid - 1;
+ }
+ }
+ return downThresholds[i];
+ }
+
+ /// <summary>
+ /// For a proof of correctness of this method, see Test/dafny2/Intervals.dfy.
+ /// A difference is that the this method returns:
+ /// let d = Dafny_RoundUp(k);
+ /// return d == thresholds.Count ? null : upThresholds[d];
+ /// </summary>
+ BigInteger? RoundUp(BigInteger k)
+ {
+ if (upThresholds.Count == 0 || upThresholds[upThresholds.Count - 1] < k) {
+ return null;
+ }
+ var i = 0;
+ var j = upThresholds.Count - 1;
+ while (i < j)
+ {
+ var mid = i + (j - i) / 2;
+ if (upThresholds[mid] < k) {
+ i = mid + 1;
+ } else {
+ j = mid;
+ }
+ }
+ return upThresholds[i];
+ }
+
+ public override Element Constrain(Element element, Expr expr) {
+ if (element is E_Bottom) {
+ return element;
+ } else {
+ var e = (E)element;
+ var c = Constraint(expr, e.N);
+ return c == null ? element : Meet(element, c);
+ }
+ }
+
+ /// <summary>
+ /// Returns an Element that corresponds to the constraints implied by "expr" in the
+ /// state "state".
+ /// Return "null" to indicate no constraints.
+ /// </summary>
+ E_Common Constraint(Expr expr, Node state) {
+ Variable v;
+ if (IsVariable(expr, out v)) {
+ var n = new Node(v, BigInteger.One, null);
+ return new E(n);
+ } else if (expr is LiteralExpr) {
+ var e = (LiteralExpr)expr;
+ return (bool)e.Val ? null : new E_Bottom();
+ } else if (expr is NAryExpr) {
+ var e = (NAryExpr)expr;
+ if (e.Fun is UnaryOperator) {
+ if (((UnaryOperator)e.Fun).Op == UnaryOperator.Opcode.Not) {
+ if (IsVariable(e.Args[0], out v)) {
+ var n = new Node(v, null, BigInteger.One);
+ return new E(n);
+ }
+ }
+ } else if (e.Fun is BinaryOperator) {
+ var op = ((BinaryOperator)e.Fun).Op;
+ var arg0 = e.Args[0];
+ var arg1 = e.Args[1];
+ switch (op) {
+ case BinaryOperator.Opcode.Eq:
+ case BinaryOperator.Opcode.Iff: {
+ E_Common c = null;
+ if (IsVariable(arg0, out v)) {
+ BigInteger? lo, hi;
+ if (PartiallyEvaluate(arg1, state, out lo, out hi)) {
+ var n = new Node(v, lo, hi);
+ c = new E(n);
+ }
+ }
+ if (IsVariable(arg1, out v)) {
+ BigInteger? lo, hi;
+ if (PartiallyEvaluate(arg1, state, out lo, out hi)) {
+ var n = new Node(v, lo, hi);
+ c = c == null ? new E(n) : (E_Common)Meet(c, new E(n));
+ }
+ }
+ return c;
+ }
+ case BinaryOperator.Opcode.Neq: {
+ E_Common c = null;
+ if (IsVariable(arg0, out v)) {
+ c = ConstrainNeq(state, v, arg1);
+ }
+ if (IsVariable(arg1, out v)) {
+ var cc = ConstrainNeq(state, v, arg0);
+ if (cc != null) {
+ c = c == null ? cc : (E_Common)Meet(c, cc);
+ }
+ }
+ return c;
+ }
+ case BinaryOperator.Opcode.Le: {
+ E_Common c = null;
+ if (IsVariable(arg1, out v)) {
+ BigInteger? lo, hi;
+ PartiallyEvaluate(arg0, state, out lo, out hi);
+ if (lo != null) {
+ var n = new Node(v, lo, null);
+ c = new E(n);
+ }
+ }
+ if (IsVariable(arg0, out v)) {
+ BigInteger? lo, hi;
+ PartiallyEvaluate(arg1, state, out lo, out hi);
+ if (hi != null) {
+ var n = new Node(v, null, hi);
+ c = c == null ? new E(n) : (E_Common)Meet(c, new E(n));
+ }
+ }
+ return c;
+ }
+ case BinaryOperator.Opcode.Lt: {
+ E_Common c = null;
+ if (IsVariable(arg1, out v)) {
+ BigInteger? lo, hi;
+ PartiallyEvaluate(arg0, state, out lo, out hi);
+ if (lo != null) {
+ var n = new Node(v, v.TypedIdent.Type.IsReal ? lo : lo + 1, null);
+ c = new E(n);
+ }
+ }
+ if (IsVariable(arg0, out v)) {
+ BigInteger? lo, hi;
+ PartiallyEvaluate(arg1, state, out lo, out hi);
+ if (hi != null) {
+ var n = new Node(v, null, v.TypedIdent.Type.IsReal ? hi : hi - 1);
+ c = c == null ? new E(n) : (E_Common)Meet(c, new E(n));
+ }
+ }
+ return c;
+ }
+ case BinaryOperator.Opcode.Ge: {
+ var tmp = arg0; arg0 = arg1; arg1 = tmp;
+ goto case BinaryOperator.Opcode.Le;
+ }
+ case BinaryOperator.Opcode.Gt: {
+ var tmp = arg0; arg0 = arg1; arg1 = tmp;
+ goto case BinaryOperator.Opcode.Lt;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return null; // approximation
+ }
+
+ private E ConstrainNeq(Node state, Variable v, Expr arg) {
+ BigInteger? lo, hi;
+ if (PartiallyEvaluate(arg, state, out lo, out hi)) {
+ if (!v.TypedIdent.Type.IsReal && lo != null && hi != null && lo + 1 == hi) {
+ var exclude = lo;
+ // If the partially evaluated arg (whose value is "exclude") is an end-point of
+ // the interval known for "v", then produce a constraint that excludes that bound.
+ Node.GetBounds(state, v, out lo, out hi);
+ if (lo != null && lo == exclude) {
+ var n = new Node(v, lo + 1, null);
+ return new E(n);
+ } else if (hi != null && exclude + 1 == hi) {
+ var n = new Node(v, null, exclude);
+ return new E(n);
+ }
+ }
+ }
+ return null;
+ }
+
+ bool IsVariable(Expr expr, out Variable v) {
+ var e = expr as IdentifierExpr;
+ if (e == null) {
+ v = null;
+ return false;
+ } else {
+ v = e.Decl;
+ return true;
+ }
+ }
+
+ public override Element Update(Element element, AssignCmd cmd) {
+ if (element is E_Bottom) {
+ return element;
+ }
+ var e = (E)element;
+ var nn = e.N;
+ Contract.Assert(cmd.Lhss.Count == cmd.Rhss.Count);
+ for (int i = 0; i < cmd.Lhss.Count; i++) {
+ var lhs = cmd.Lhss[i];
+ var rhs = cmd.Rhss[i];
+ BigInteger? lo;
+ BigInteger? hi;
+ PartiallyEvaluate(rhs, e.N, out lo, out hi);
+ nn = UpdateOne(nn, lhs.DeepAssignedVariable, lo, hi);
+ }
+ return new E(nn);
+ }
+
+ bool PartiallyEvaluate(Expr rhs, Node node, out BigInteger? lo, out BigInteger? hi) {
+ var pe = new PEVisitor(node);
+ pe.VisitExpr(rhs);
+ lo = pe.Lo;
+ hi = pe.Hi;
+ return lo != null || hi != null;
+ }
+
+ class PEVisitor : ReadOnlyVisitor
+ {
+ public BigInteger? Lo;
+ public BigInteger? Hi;
+
+ readonly BigInteger one = BigInteger.One;
+
+ Node N;
+ public PEVisitor(Node n) {
+ N = n;
+ }
+
+ // Override visitors for all expressions that can return a boolean, integer, or real result
+
+ public override Expr VisitExpr(Expr node) {
+ Lo = Hi = null;
+ return base.VisitExpr(node);
+ }
+ public override Expr VisitLiteralExpr(LiteralExpr node) {
+ if (node.Val is BigNum) {
+ var n = ((BigNum)node.Val).ToBigInteger;
+ Lo = n;
+ Hi = n + 1;
+ } else if (node.Val is BigDec) {
+ BigInteger floor, ceiling;
+ ((BigDec)node.Val).FloorCeiling(out floor, out ceiling);
+ Lo = floor;
+ Hi = ceiling;
+ } else if (node.Val is BigFloat) {
+ BigNum floor, ceiling;
+ ((BigFloat)node.Val).FloorCeiling(out floor, out ceiling);
+ Lo = floor.ToBigInteger;
+ Hi = ceiling.ToBigInteger;
+ } else if (node.Val is bool) {
+ if ((bool)node.Val) {
+ // true
+ Lo = one;
+ Hi = null;
+ } else {
+ // false
+ Lo = null;
+ Hi = one;
+ }
+ }
+ return node;
+ }
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ if (node.Type.IsBool || node.Type.IsInt || node.Type.IsReal) {
+ Node.GetBounds(N, node.Decl, out Lo, out Hi);
+ }
+ return node;
+ }
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ if (node.Fun is UnaryOperator) {
+ var op = (UnaryOperator)node.Fun;
+ Contract.Assert(node.Args.Count == 1);
+ if (op.Op == UnaryOperator.Opcode.Neg) {
+ BigInteger? lo, hi;
+ VisitExpr(node.Args[0]);
+ lo = Lo; hi = Hi;
+ if (hi != null) {
+ Lo = node.Type.IsReal ? -hi : 1 - hi;
+ } else {
+ Lo = null;
+ }
+ if (lo != null) {
+ Hi = node.Type.IsReal ? -lo : 1 - lo;
+ } else {
+ Hi = null;
+ }
+ }
+ else if (op.Op == UnaryOperator.Opcode.Not) {
+ VisitExpr(node.Args[0]);
+ Contract.Assert((Lo == null && Hi == null) ||
+ (Lo == null && (BigInteger)Hi == 1) ||
+ (Hi == null && (BigInteger)Lo == 1));
+ var tmp = Lo;
+ Lo = Hi;
+ Hi = tmp;
+ }
+ } else if (node.Fun is BinaryOperator) {
+ var op = (BinaryOperator)node.Fun;
+ Contract.Assert(node.Args.Count == 2);
+ BigInteger? lo0, hi0, lo1, hi1;
+ VisitExpr(node.Args[0]);
+ lo0 = Lo; hi0 = Hi;
+ VisitExpr(node.Args[1]);
+ lo1 = Lo; hi1 = Hi;
+ Lo = Hi = null;
+ var isReal = node.Args[0].Type.IsReal;
+ switch (op.Op) {
+ case BinaryOperator.Opcode.And:
+ if (hi0 != null || hi1 != null) {
+ // one operand is definitely false, thus so is the result
+ Lo = null; Hi = one;
+ } else if (lo0 != null && lo1 != null) {
+ // both operands are definitely true, thus so is the result
+ Lo = one; Hi = null;
+ }
+ break;
+ case BinaryOperator.Opcode.Or:
+ if (lo0 != null || lo1 != null) {
+ // one operand is definitely true, thus so is the result
+ Lo = one; Hi = null;
+ } else if (hi0 != null && hi1 != null) {
+ // both operands are definitely false, thus so is the result
+ Lo = null; Hi = one;
+ }
+ break;
+ case BinaryOperator.Opcode.Imp:
+ if (hi0 != null || lo1 != null) {
+ // either arg0 false or arg1 is true, so the result is true
+ Lo = one; Hi = null;
+ } else if (lo0 != null && hi1 != null) {
+ // arg0 is true and arg1 is false, so the result is false
+ Lo = null; Hi = one;
+ }
+ break;
+ case BinaryOperator.Opcode.Iff:
+ if (lo0 != null && lo1 != null) {
+ Lo = one; Hi = null;
+ } else if (hi0 != null && hi1 != null) {
+ Lo = one; Hi = null;
+ } else if (lo0 != null && hi1 != null) {
+ Lo = null; Hi = one;
+ } else if (hi0 != null && lo1 != null) {
+ Lo = null; Hi = one;
+ }
+ if (op.Op == BinaryOperator.Opcode.Neq) {
+ var tmp = Lo; Lo = Hi; Hi = tmp;
+ }
+ break;
+ case BinaryOperator.Opcode.Eq:
+ case BinaryOperator.Opcode.Neq:
+ if (node.Args[0].Type.IsBool) {
+ goto case BinaryOperator.Opcode.Iff;
+ }
+ // For Eq:
+ // If the (lo0,hi0) and (lo1,hi1) ranges do not overlap, the answer is false.
+ // If both ranges are the same unit range, then the answer is true.
+ if (hi0 != null && lo1 != null && (isReal ? hi0 < lo1 : hi0 <= lo1)) {
+ // no overlap
+ Lo = null; Hi = one;
+ } else if (lo0 != null && hi1 != null && (isReal ? hi1 < lo0 : hi1 <= lo0)) {
+ Lo = null; Hi = one;
+ // no overlaop
+ } else if (lo0 != null && hi0 != null && lo1 != null && hi1 != null &&
+ lo0 == lo1 && hi0 == hi1 && // ranges are the same
+ (isReal ? lo0 == hi0 : lo0 + 1 == hi0)) { // unit range
+ // both ranges are the same unit range
+ Lo = one; Hi = null;
+ }
+ if (op.Op == BinaryOperator.Opcode.Neq) {
+ var tmp = Lo; Lo = Hi; Hi = tmp;
+ }
+ break;
+ case BinaryOperator.Opcode.Le:
+ if (isReal) {
+ // If hi0 <= lo1, then the answer is true.
+ // If hi1 < lo0, then the answer is false.
+ if (hi0 != null && lo1 != null && hi0 <= lo1) {
+ Lo = one; Hi = null;
+ } else if (hi1 != null && lo0 != null && hi1 < lo0) {
+ Lo = null; Hi = one;
+ }
+ } else {
+ // If hi0 - 1 <= lo1, then the answer is true.
+ // If hi1 <= lo0, then the answer is false.
+ if (hi0 != null && lo1 != null && hi0 - 1 <= lo1) {
+ Lo = one; Hi = null;
+ } else if (lo0 != null && hi1 != null && hi1 <= lo0) {
+ Lo = null; Hi = one;
+ }
+ }
+ break;
+ case BinaryOperator.Opcode.Lt:
+ if (isReal) {
+ // If hi0 < lo1, then the answer is true.
+ // If hi1 <= lo0, then the answer is false.
+ if (hi0 != null && lo1 != null && hi0 < lo1) {
+ Lo = one; Hi = null;
+ } else if (hi1 != null && lo0 != null && hi1 <= lo0) {
+ Lo = null; Hi = one;
+ }
+ } else {
+ // If hi0 <= lo1, then the answer is true.
+ // If hi1 - 1 <= lo0, then the answer is false.
+ if (hi0 != null && lo1 != null && hi0 <= lo1) {
+ Lo = one; Hi = null;
+ } else if (lo0 != null && hi1 != null && hi1 - 1 <= lo0) {
+ Lo = null; Hi = one;
+ }
+ }
+ break;
+ case BinaryOperator.Opcode.Gt:
+ // swap the operands and then continue as Lt
+ {
+ var tmp = lo0; lo0 = lo1; lo1 = tmp;
+ tmp = hi0; hi0 = hi1; hi1 = tmp;
+ }
+ goto case BinaryOperator.Opcode.Lt;
+ case BinaryOperator.Opcode.Ge:
+ // swap the operands and then continue as Le
+ {
+ var tmp = lo0; lo0 = lo1; lo1 = tmp;
+ tmp = hi0; hi0 = hi1; hi1 = tmp;
+ }
+ goto case BinaryOperator.Opcode.Le;
+ case BinaryOperator.Opcode.Add:
+ if (lo0 != null && lo1 != null) {
+ Lo = lo0 + lo1;
+ }
+ if (hi0 != null && hi1 != null) {
+ Hi = isReal ? hi0 + hi1 : hi0 + hi1 - 1;
+ }
+ break;
+ case BinaryOperator.Opcode.Sub:
+ if (lo0 != null && hi1 != null) {
+ Lo = isReal ? lo0 - hi1 : lo0 - hi1 + 1;
+ }
+ if (hi0 != null && lo1 != null) {
+ Hi = hi0 - lo1;
+ }
+ break;
+ case BinaryOperator.Opcode.Mul:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null) {
+ if (0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = lo0 * lo1;
+ Hi = hi0 == null || hi1 == null ? null : isReal ? hi0 * hi1 : (hi0 - 1) * (hi1 - 1) + 1;
+ } else if ((BigInteger)lo0 < 0 && (BigInteger)lo1 < 0) {
+ Lo = null; // approximation
+ Hi = isReal ? lo0 * lo1 : lo0 * lo1 + 1;
+ }
+ }
+ break;
+ case BinaryOperator.Opcode.Div:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = BigInteger.Zero;
+ Hi = hi0;
+ }
+ break;
+ case BinaryOperator.Opcode.Mod:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = BigInteger.Zero;
+ Hi = hi1;
+ if (lo0 < lo1 && hi0 != null && hi0 < lo1) {
+ Lo = lo0;
+ Hi = hi0;
+ }
+ }
+ break;
+ case BinaryOperator.Opcode.RealDiv:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = BigInteger.Zero;
+ Hi = 1 <= (BigInteger)lo1 ? hi0 : null;
+ }
+ break;
+ case BinaryOperator.Opcode.Pow:
+ // this uses an incomplete approximation that could be tightened up
+ if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) {
+ Lo = 1 <= (BigInteger)lo1 ? BigInteger.One : BigInteger.Zero;
+ Hi = hi1;
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (node.Fun is IfThenElse) {
+ var op = (IfThenElse)node.Fun;
+ Contract.Assert(node.Args.Count == 3);
+ BigInteger? guardLo, guardHi, lo0, hi0, lo1, hi1;
+ VisitExpr(node.Args[0]);
+ guardLo = Lo; guardHi = Hi;
+ VisitExpr(node.Args[1]);
+ lo0 = Lo; hi0 = Hi;
+ VisitExpr(node.Args[2]);
+ lo1 = Lo; hi1 = Hi;
+ Contract.Assert(guardLo == null || guardHi == null); // this is a consequence of the guard being boolean
+ if (guardLo != null) {
+ // guard is always true
+ Lo = lo0; Hi = hi0;
+ } else if (guardHi != null) {
+ // guard is always false
+ Lo = lo1; Hi = hi1;
+ } else {
+ // we don't know which branch will be taken, so join the information from the two branches
+ Lo = Node.Min(lo0, lo1, false);
+ Hi = Node.Max(hi0, hi1, false);
+ }
+ } else if (node.Fun is FunctionCall) {
+ var call = (FunctionCall)node.Fun;
+ // See if this is an identity function, which we do by checking: that the function has
+ // exactly one argument and the function has been marked by the user with the attribute {:identity}
+ bool claimsToBeIdentity = false;
+ if (call.ArgumentCount == 1 && call.Func.CheckBooleanAttribute("identity", ref claimsToBeIdentity) && claimsToBeIdentity && node.Args[0].Type.Equals(node.Type)) {
+ VisitExpr(node.Args[0]);
+ }
+ }
+ return node;
+ }
+ public override BinderExpr VisitBinderExpr(BinderExpr node) {
+ // don't recurse on subexpression
+ return node;
+ }
+ public override Expr VisitOldExpr(OldExpr node) {
+ // don't recurse on subexpression
+ return node;
+ }
+ public override Expr VisitCodeExpr(CodeExpr node) {
+ // don't recurse on subexpression
+ return node;
+ }
+ public override Expr VisitBvConcatExpr(BvConcatExpr node) {
+ // don't recurse on subexpression
+ return node;
+ }
+ public override Expr VisitBvExtractExpr(BvExtractExpr node) {
+ // don't recurse on subexpression
+ return node;
+ }
+ }
+
+ public override Element Eliminate(Element element, Variable v) {
+ if (element is E_Bottom) {
+ return element;
+ }
+ var e = (E)element;
+ var nn = UpdateOne(e.N, v, null, null);
+ if (nn == e.N) {
+ return element;
+ } else {
+ return new E(nn);
+ }
+ }
+
+ Node UpdateOne(Node nn, Variable v, BigInteger? lo, BigInteger? hi) {
+ var orig = nn;
+ Node head = null;
+ Node prev = null;
+ var foundV = false;
+ for (; nn != null && !Node.StrictlyBefore(v, nn.V); nn = nn.Next) {
+ if (nn.V == v) {
+ foundV = true;
+ nn = nn.Next;
+ break; // we found the place where the new node goes
+ } else {
+ var n = new Node(nn.V, nn.Lo, nn.Hi); // copy this Node
+ if (head == null) {
+ head = n;
+ } else {
+ prev.Next = n;
+ }
+ prev = n;
+ }
+ }
+ Node rest;
+ if (lo == null && hi == null) {
+ // eliminate all information about "v"
+ if (!foundV) {
+ return orig;
+ }
+ rest = nn;
+ } else {
+ rest = new Node(v, lo, hi);
+ rest.Next = nn;
+ }
+ if (head == null) {
+ head = rest;
+ } else {
+ prev.Next = rest;
+ }
+ return head;
+ }
+
+ /// <summary>
+ /// Return a resolved/type-checked expression that represents the conjunction of a and b.
+ /// Requires a and b to be resolved and type checked already.
+ /// </summary>
+ public static Expr BplAnd(Expr a, Expr b) {
+ if (a == Expr.True) {
+ return b;
+ } else if (b == Expr.True) {
+ return a;
+ } else {
+ var nary = Expr.Binary(BinaryOperator.Opcode.And, a, b);
+ nary.Type = Type.Bool;
+ nary.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ return nary;
+ }
+ }
+
+ /// <summary>
+ /// Return a resolved/type-checked expression that represents a EQUALS b.
+ /// Requires a and b to be resolved and type checked already.
+ /// </summary>
+ public static Expr BplEq(Expr a, Expr b) {
+ var e = Expr.Eq(a, b);
+ e.Type = Type.Bool;
+ return e;
+ }
+
+ /// <summary>
+ /// Return a resolved/type-checked expression that represents a LESS-EQUAL b.
+ /// Requires a and b to be resolved and type checked already.
+ /// </summary>
+ public static Expr BplLe(Expr a, Expr b) {
+ var e = Expr.Le(a, b);
+ e.Type = Type.Bool;
+ return e;
+ }
+ /// <summary>
+ /// Return a resolved/type-checked expression that represents a LESS b.
+ /// Requires a and b to be resolved and type checked already.
+ /// </summary>
+ public static Expr BplLt(Expr a, Expr b) {
+ var e = Expr.Lt(a, b);
+ e.Type = Type.Bool;
+ return e;
+ }
+ }
+
+ public class ThresholdFinder : ReadOnlyVisitor
+ {
+ readonly Implementation Impl;
+ public ThresholdFinder(Implementation impl) {
+ Contract.Requires(impl != null);
+ Impl = impl;
+ }
+ HashSet<BigInteger> downs = new HashSet<BigInteger>();
+ HashSet<BigInteger> ups = new HashSet<BigInteger>();
+ public void Find(out List<BigInteger> downThresholds, out List<BigInteger> upThresholds) {
+ // always include -1, 0, 1 as down-thresholds
+ downs.Clear();
+ downs.Add(-1);
+ downs.Add(0);
+ downs.Add(1);
+ // always include 0 and 1 as up-thresholds
+ ups.Clear();
+ ups.Add(0);
+ ups.Add(1);
+
+ foreach (Requires p in Impl.Proc.Requires) {
+ Visit(p.Condition);
+ }
+ foreach (Ensures p in Impl.Proc.Ensures) {
+ Visit(p.Condition);
+ }
+ foreach (var b in Impl.Blocks) {
+ foreach (Cmd c in b.Cmds) {
+ Visit(c);
+ }
+ }
+
+ // convert the HashSets to sorted Lists and return
+ downThresholds = new List<BigInteger>();
+ foreach (var i in downs) {
+ downThresholds.Add(i);
+ }
+ downThresholds.Sort();
+ upThresholds = new List<BigInteger>();
+ foreach (var i in ups) {
+ upThresholds.Add(i);
+ }
+ upThresholds.Sort();
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ if (node.Fun is BinaryOperator) {
+ var op = (BinaryOperator)node.Fun;
+ Contract.Assert(node.Args.Count == 2);
+ var arg0 = node.Args[0];
+ var arg1 = node.Args[1];
+ var offset = arg0.Type.IsReal ? 0 : 1;
+ BigInteger? k;
+ switch (op.Op) {
+ case BinaryOperator.Opcode.Eq:
+ case BinaryOperator.Opcode.Neq:
+ k = AsIntLiteral(arg0);
+ if (k != null) {
+ var i = (BigInteger)k;
+ downs.Add(i - 1);
+ downs.Add(i);
+ ups.Add(i + 1);
+ ups.Add(i + 2);
+ }
+ k = AsIntLiteral(arg1);
+ if (k != null) {
+ var i = (BigInteger)k;
+ downs.Add(i - 1);
+ downs.Add(i);
+ ups.Add(i + 1);
+ ups.Add(i + 2);
+ }
+ break;
+ case BinaryOperator.Opcode.Le:
+ k = AsIntLiteral(arg0);
+ if (k != null) {
+ var i = (BigInteger)k;
+ downs.Add(i - 1);
+ downs.Add(i);
+ }
+ k = AsIntLiteral(arg1);
+ if (k != null) {
+ var i = (BigInteger)k;
+ ups.Add(i + offset);
+ ups.Add(i + 1 + offset);
+ }
+ break;
+ case BinaryOperator.Opcode.Lt:
+ k = AsIntLiteral(arg0);
+ if (k != null) {
+ var i = (BigInteger)k;
+ downs.Add(i );
+ downs.Add(i + 1);
+ }
+ k = AsIntLiteral(arg1);
+ if (k != null) {
+ var i = (BigInteger)k;
+ ups.Add(i - 1 + offset);
+ ups.Add(i + offset);
+ }
+ break;
+ case BinaryOperator.Opcode.Ge:
+ { var tmp = arg0; arg0 = arg1; arg1 = tmp; }
+ goto case BinaryOperator.Opcode.Le;
+ case BinaryOperator.Opcode.Gt:
+ { var tmp = arg0; arg0 = arg1; arg1 = tmp; }
+ goto case BinaryOperator.Opcode.Lt;
+ default:
+ break;
+ }
+ }
+ return base.VisitNAryExpr(node);
+ }
+
+ BigInteger? AsIntLiteral(Expr e) {
+ var lit = e as LiteralExpr;
+ if (lit != null && lit.isBigNum) {
+ BigNum bn = lit.asBigNum;
+ return bn.ToBigInteger;
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/Source/AbsInt/NativeLattice.cs b/Source/AbsInt/NativeLattice.cs
index 30014643..d1ae215a 100644
--- a/Source/AbsInt/NativeLattice.cs
+++ b/Source/AbsInt/NativeLattice.cs
@@ -1,335 +1,335 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-
-namespace Microsoft.Boogie.AbstractInterpretation
-{
- /// <summary>
- /// Specifies the operations (e.g., join) on a mathematical lattice that depend
- /// only on the elements of the lattice.
- /// </summary>
- public abstract class NativeLattice
- {
- /// <summary>
- /// An element of the lattice. This class should be derived from in any
- /// implementation of MathematicalLattice.
- /// </summary>
- public abstract class Element
- {
- public abstract Expr ToExpr();
- }
-
- public abstract Element Top { get; }
- public abstract Element Bottom { get; }
-
- public abstract bool IsTop(Element element);
- public abstract bool IsBottom(Element element);
-
- /// <summary>
- /// Is 'a' better (or equal) information than 'b'? That is, is 'a' below 'b' in the lattice?
- /// </summary>
- public abstract bool Below(Element a, Element b);
-
- public abstract Element Meet(Element a, Element b);
- public abstract Element Join(Element a, Element b);
- public abstract Element Widen(Element a, Element b);
-
- public abstract Element Constrain(Element element, Expr expr);
- public abstract Element Update(Element element, AssignCmd cmd); // requiers 'cmd' to be a simple (possibly parallel) assignment command
- public abstract Element Eliminate(Element element, Variable v);
-
- /// <summary>
- /// Specialize the lattice to implementation "impl", if non-null.
- /// If "impl" is null, remove specialization.
- /// </summary>
- public virtual void Specialize(Implementation impl) {
- }
-
- public virtual void Validate() {
- Contract.Assert(IsTop(Top));
- Contract.Assert(IsBottom(Bottom));
- Contract.Assert(!IsBottom(Top));
- Contract.Assert(!IsTop(Bottom));
-
- Contract.Assert(Below(Top, Top));
- Contract.Assert(Below(Bottom, Top));
- Contract.Assert(Below(Bottom, Bottom));
-
- Contract.Assert(IsTop(Join(Top, Top)));
- Contract.Assert(IsBottom(Join(Bottom, Bottom)));
- }
- }
-
- public class NativeAbstractInterpretation
- {
- public static void RunAbstractInterpretation(Program program) {
- Contract.Requires(program != null);
-
- if (!CommandLineOptions.Clo.UseAbstractInterpretation) {
- return;
- }
- Helpers.ExtraTraceInformation("Starting abstract interpretation");
-
- DateTime start = new DateTime(); // to please compiler's definite assignment rules
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine();
- Console.WriteLine("Running abstract interpretation...");
- start = DateTime.UtcNow;
- }
-
- WidenPoints.Compute(program);
-
- NativeLattice lattice = null;
- if (CommandLineOptions.Clo.Ai.J_Trivial) {
- lattice = new TrivialDomain();
- } else if (CommandLineOptions.Clo.Ai.J_Intervals) {
- lattice = new NativeIntervallDomain();
- }
-
- if (lattice != null) {
- Dictionary<Procedure, Implementation[]> procedureImplementations = ComputeProcImplMap(program);
- ComputeProgramInvariants(program, procedureImplementations, lattice);
- if (CommandLineOptions.Clo.Ai.DebugStatistics) {
- Console.Error.WriteLine(lattice);
- }
- }
-
- if (CommandLineOptions.Clo.Trace) {
- DateTime end = DateTime.UtcNow;
- TimeSpan elapsed = end - start;
- Console.WriteLine(" [{0} s]", elapsed.TotalSeconds);
- Console.Out.Flush();
- }
- }
-
- private static Dictionary<Procedure, Implementation[]> ComputeProcImplMap(Program program) {
- Contract.Requires(program != null);
- // Since implementations call procedures (impl. signatures)
- // rather than directly calling other implementations, we first
- // need to compute which implementations implement which
- // procedures and remember which implementations call which
- // procedures.
-
- return program
- .Implementations
- .GroupBy(i => i.Proc).Select(g => g.ToArray()).ToDictionary(a => a[0].Proc);
- }
-
- /// <summary>
- /// Compute and apply the invariants for the program using the underlying abstract domain.
- /// </summary>
- public static void ComputeProgramInvariants(Program program, Dictionary<Procedure, Implementation[]> procedureImplementations, NativeLattice lattice) {
- Contract.Requires(program != null);
- Contract.Requires(procedureImplementations != null);
- Contract.Requires(lattice != null);
-
- // Gather all the axioms to create the initial lattice element
- // Differently stated, it is the \alpha from axioms (i.e. first order formulae) to the underlyng abstract domain
- var initialElement = lattice.Top;
- Contract.Assert(initialElement != null);
- foreach (var ax in program.Axioms) {
- initialElement = lattice.Constrain(initialElement, ax.Expr);
- }
-
- // analyze each procedure
- foreach (var proc in program.Procedures) {
- if (procedureImplementations.ContainsKey(proc)) {
- // analyze each implementation of the procedure
- foreach (var impl in procedureImplementations[proc]) {
- // add the precondition to the axioms
- Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
- var start = initialElement;
- foreach (Requires pre in proc.Requires) {
- Expr e = Substituter.Apply(formalProcImplSubst, pre.Condition);
- start = lattice.Constrain(start, e);
- }
-
- lattice.Specialize(impl);
- Analyze(impl, lattice, start);
- lattice.Specialize(null);
- }
- }
- }
- }
-
- public static void Analyze(Implementation impl, NativeLattice lattice, NativeLattice.Element start) {
- // We need to keep track of some information for each(some) block(s). To do that efficiently,
- // we number the implementation's blocks sequentially, and then we can use arrays to store
- // the additional information.
- var pre = new NativeLattice.Element[impl.Blocks.Count]; // set to null if we never compute a join/widen at this block
- var post = CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere ? new NativeLattice.Element[impl.Blocks.Count] : null;
- var iterations = new int[impl.Blocks.Count];
- var bottom = lattice.Bottom;
- int n = 0;
- foreach (var block in impl.Blocks) {
- block.aiId = n;
- // Note: The forward analysis below will store lattice elements in pre[n] if pre[n] is non-null.
- // Thus, the assignment "pre[n] = bottom;" below must be done under the following condition:
- // n == 0 || block.widenBlock
- // One possible strategy would be to do it only under that condition. Alternatively,
- // one could do the assignment under the following condition:
- // n == 0 || block.widenBlock || block.Predecessors.Length != 1
- // (which would require first setting the Predecessors field). In any case, if
- // CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere
- // then all pre[n] should be set.
- pre[n] = bottom;
- n++;
- }
- Contract.Assert(n == impl.Blocks.Count);
-
- var workItems = new Queue<Tuple<Block, NativeLattice.Element>>();
- workItems.Enqueue(new Tuple<Block, NativeLattice.Element>(impl.Blocks[0], start));
- //ComputeBlockInvariantsNative(impl, );
- // compute a fixpoint here
- while (workItems.Count > 0) {
- var workItem = workItems.Dequeue();
- var b = workItem.Item1;
- var id = b.aiId;
- var e = workItem.Item2;
- if (pre[id] == null) {
- // no pre information stored here, so just go ahead through the block
- } else if (lattice.Below(e, pre[id])) {
- // no change
- continue;
- } else if (b.widenBlock && CommandLineOptions.Clo.StepsBeforeWidening <= iterations[id]) {
- e = lattice.Widen(pre[id], e);
- pre[id] = e;
- iterations[id]++;
- } else {
- e = lattice.Join(pre[id], e);
- pre[id] = e;
- iterations[id]++;
- }
-
- // propagate'e' through b.Cmds
- foreach (Cmd cmd in b.Cmds) {
- e = Step(lattice, cmd, e);
- }
-
- if (post != null && pre[id] != null) {
- post[id] = e;
- }
-
- var g = b.TransferCmd as GotoCmd;
- if (g != null) { // if g==null, it's a pity we didn't pay attention to that earlier, because then we could have skipped analyzing the code in this block
- foreach (Block succ in g.labelTargets) {
- workItems.Enqueue(new Tuple<Block, NativeLattice.Element>(succ, e));
- }
- }
- }
-
- Instrument(impl, pre, post);
- }
-
- static void Instrument(Implementation impl, NativeLattice.Element[] pre, NativeLattice.Element[] post) {
- Contract.Requires(impl != null);
- Contract.Requires(pre != null);
-
- foreach (var b in impl.Blocks) {
- var element = pre[b.aiId];
- if (element != null && (b.widenBlock || CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere)) {
- List<Cmd> newCommands = new List<Cmd>();
- Expr inv = element.ToExpr();
- PredicateCmd cmd;
- var kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null);
- if (CommandLineOptions.Clo.InstrumentWithAsserts) {
- cmd = new AssertCmd(Token.NoToken, inv, kv);
- } else {
- cmd = new AssumeCmd(Token.NoToken, inv, kv);
- }
- newCommands.Add(cmd);
- newCommands.AddRange(b.Cmds);
- if (post != null && post[b.aiId] != null) {
- inv = post[b.aiId].ToExpr();
- kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null);
- if (CommandLineOptions.Clo.InstrumentWithAsserts) {
- cmd = new AssertCmd(Token.NoToken, inv, kv);
- } else {
- cmd = new AssumeCmd(Token.NoToken, inv, kv);
- }
- newCommands.Add(cmd);
- }
- b.Cmds = newCommands; // destructively replace the commands of the block
- }
- }
- }
-
- /// <summary>
- /// The abstract transition relation.
- /// 'cmd' is allowed to be a StateCmd.
- /// </summary>
- static NativeLattice.Element Step(NativeLattice lattice, Cmd cmd, NativeLattice.Element elmt) {
- Contract.Requires(lattice != null);
- Contract.Requires(cmd != null);
- Contract.Requires(elmt != null);
- Contract.Ensures(Contract.Result<NativeLattice.Element>() != null);
-
- if (cmd is AssignCmd) { // parallel assignment
- var c = (AssignCmd)cmd;
- elmt = lattice.Update(elmt, c.AsSimpleAssignCmd);
- } else if (cmd is HavocCmd) {
- var c = (HavocCmd)cmd;
- foreach (IdentifierExpr id in c.Vars) {
- Contract.Assert(id != null);
- elmt = lattice.Eliminate(elmt, id.Decl);
- }
- } else if (cmd is PredicateCmd) {
- var c = (PredicateCmd)cmd;
- var conjuncts = new List<Expr>();
- foreach (var ee in Conjuncts(c.Expr)) {
- Contract.Assert(ee != null);
- elmt = lattice.Constrain(elmt, ee);
- }
- } else if (cmd is StateCmd) {
- var c = (StateCmd)cmd;
- // Iterate the abstract transition on all the commands in the desugaring of the call
- foreach (Cmd callDesug in c.Cmds) {
- Contract.Assert(callDesug != null);
- elmt = Step(lattice, callDesug, elmt);
- }
- // Project out the local variables of the StateCmd
- foreach (Variable local in c.Locals) {
- Contract.Assert(local != null);
- elmt = lattice.Eliminate(elmt, local);
- }
- } else if (cmd is SugaredCmd) {
- var c = (SugaredCmd)cmd;
- elmt = Step(lattice, c.Desugaring, elmt);
- } else if (cmd is CommentCmd) {
- // skip
- } else {
- Contract.Assert(false); // unknown command
- }
- return elmt;
- }
-
- /// <summary>
- /// Yields the conjuncts of 'expr'.
- /// </summary>
- public static IEnumerable<Expr> Conjuncts(Expr expr) {
- Contract.Requires(expr != null);
-
- var e = expr as NAryExpr;
- if (e != null && e.Fun.FunctionName == "&&") { // if it is a conjunction
- foreach (Expr ee in e.Args) {
- Contract.Assert(ee != null);
- foreach (var c in Conjuncts(ee)) {
- yield return c;
- }
- }
- } else {
- yield return expr;
- }
- }
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+
+namespace Microsoft.Boogie.AbstractInterpretation
+{
+ /// <summary>
+ /// Specifies the operations (e.g., join) on a mathematical lattice that depend
+ /// only on the elements of the lattice.
+ /// </summary>
+ public abstract class NativeLattice
+ {
+ /// <summary>
+ /// An element of the lattice. This class should be derived from in any
+ /// implementation of MathematicalLattice.
+ /// </summary>
+ public abstract class Element
+ {
+ public abstract Expr ToExpr();
+ }
+
+ public abstract Element Top { get; }
+ public abstract Element Bottom { get; }
+
+ public abstract bool IsTop(Element element);
+ public abstract bool IsBottom(Element element);
+
+ /// <summary>
+ /// Is 'a' better (or equal) information than 'b'? That is, is 'a' below 'b' in the lattice?
+ /// </summary>
+ public abstract bool Below(Element a, Element b);
+
+ public abstract Element Meet(Element a, Element b);
+ public abstract Element Join(Element a, Element b);
+ public abstract Element Widen(Element a, Element b);
+
+ public abstract Element Constrain(Element element, Expr expr);
+ public abstract Element Update(Element element, AssignCmd cmd); // requiers 'cmd' to be a simple (possibly parallel) assignment command
+ public abstract Element Eliminate(Element element, Variable v);
+
+ /// <summary>
+ /// Specialize the lattice to implementation "impl", if non-null.
+ /// If "impl" is null, remove specialization.
+ /// </summary>
+ public virtual void Specialize(Implementation impl) {
+ }
+
+ public virtual void Validate() {
+ Contract.Assert(IsTop(Top));
+ Contract.Assert(IsBottom(Bottom));
+ Contract.Assert(!IsBottom(Top));
+ Contract.Assert(!IsTop(Bottom));
+
+ Contract.Assert(Below(Top, Top));
+ Contract.Assert(Below(Bottom, Top));
+ Contract.Assert(Below(Bottom, Bottom));
+
+ Contract.Assert(IsTop(Join(Top, Top)));
+ Contract.Assert(IsBottom(Join(Bottom, Bottom)));
+ }
+ }
+
+ public class NativeAbstractInterpretation
+ {
+ public static void RunAbstractInterpretation(Program program) {
+ Contract.Requires(program != null);
+
+ if (!CommandLineOptions.Clo.UseAbstractInterpretation) {
+ return;
+ }
+ Helpers.ExtraTraceInformation("Starting abstract interpretation");
+
+ DateTime start = new DateTime(); // to please compiler's definite assignment rules
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine();
+ Console.WriteLine("Running abstract interpretation...");
+ start = DateTime.UtcNow;
+ }
+
+ WidenPoints.Compute(program);
+
+ NativeLattice lattice = null;
+ if (CommandLineOptions.Clo.Ai.J_Trivial) {
+ lattice = new TrivialDomain();
+ } else if (CommandLineOptions.Clo.Ai.J_Intervals) {
+ lattice = new NativeIntervallDomain();
+ }
+
+ if (lattice != null) {
+ Dictionary<Procedure, Implementation[]> procedureImplementations = ComputeProcImplMap(program);
+ ComputeProgramInvariants(program, procedureImplementations, lattice);
+ if (CommandLineOptions.Clo.Ai.DebugStatistics) {
+ Console.Error.WriteLine(lattice);
+ }
+ }
+
+ if (CommandLineOptions.Clo.Trace) {
+ DateTime end = DateTime.UtcNow;
+ TimeSpan elapsed = end - start;
+ Console.WriteLine(" [{0} s]", elapsed.TotalSeconds);
+ Console.Out.Flush();
+ }
+ }
+
+ private static Dictionary<Procedure, Implementation[]> ComputeProcImplMap(Program program) {
+ Contract.Requires(program != null);
+ // Since implementations call procedures (impl. signatures)
+ // rather than directly calling other implementations, we first
+ // need to compute which implementations implement which
+ // procedures and remember which implementations call which
+ // procedures.
+
+ return program
+ .Implementations
+ .GroupBy(i => i.Proc).Select(g => g.ToArray()).ToDictionary(a => a[0].Proc);
+ }
+
+ /// <summary>
+ /// Compute and apply the invariants for the program using the underlying abstract domain.
+ /// </summary>
+ public static void ComputeProgramInvariants(Program program, Dictionary<Procedure, Implementation[]> procedureImplementations, NativeLattice lattice) {
+ Contract.Requires(program != null);
+ Contract.Requires(procedureImplementations != null);
+ Contract.Requires(lattice != null);
+
+ // Gather all the axioms to create the initial lattice element
+ // Differently stated, it is the \alpha from axioms (i.e. first order formulae) to the underlyng abstract domain
+ var initialElement = lattice.Top;
+ Contract.Assert(initialElement != null);
+ foreach (var ax in program.Axioms) {
+ initialElement = lattice.Constrain(initialElement, ax.Expr);
+ }
+
+ // analyze each procedure
+ foreach (var proc in program.Procedures) {
+ if (procedureImplementations.ContainsKey(proc)) {
+ // analyze each implementation of the procedure
+ foreach (var impl in procedureImplementations[proc]) {
+ // add the precondition to the axioms
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ var start = initialElement;
+ foreach (Requires pre in proc.Requires) {
+ Expr e = Substituter.Apply(formalProcImplSubst, pre.Condition);
+ start = lattice.Constrain(start, e);
+ }
+
+ lattice.Specialize(impl);
+ Analyze(impl, lattice, start);
+ lattice.Specialize(null);
+ }
+ }
+ }
+ }
+
+ public static void Analyze(Implementation impl, NativeLattice lattice, NativeLattice.Element start) {
+ // We need to keep track of some information for each(some) block(s). To do that efficiently,
+ // we number the implementation's blocks sequentially, and then we can use arrays to store
+ // the additional information.
+ var pre = new NativeLattice.Element[impl.Blocks.Count]; // set to null if we never compute a join/widen at this block
+ var post = CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere ? new NativeLattice.Element[impl.Blocks.Count] : null;
+ var iterations = new int[impl.Blocks.Count];
+ var bottom = lattice.Bottom;
+ int n = 0;
+ foreach (var block in impl.Blocks) {
+ block.aiId = n;
+ // Note: The forward analysis below will store lattice elements in pre[n] if pre[n] is non-null.
+ // Thus, the assignment "pre[n] = bottom;" below must be done under the following condition:
+ // n == 0 || block.widenBlock
+ // One possible strategy would be to do it only under that condition. Alternatively,
+ // one could do the assignment under the following condition:
+ // n == 0 || block.widenBlock || block.Predecessors.Length != 1
+ // (which would require first setting the Predecessors field). In any case, if
+ // CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere
+ // then all pre[n] should be set.
+ pre[n] = bottom;
+ n++;
+ }
+ Contract.Assert(n == impl.Blocks.Count);
+
+ var workItems = new Queue<Tuple<Block, NativeLattice.Element>>();
+ workItems.Enqueue(new Tuple<Block, NativeLattice.Element>(impl.Blocks[0], start));
+ //ComputeBlockInvariantsNative(impl, );
+ // compute a fixpoint here
+ while (workItems.Count > 0) {
+ var workItem = workItems.Dequeue();
+ var b = workItem.Item1;
+ var id = b.aiId;
+ var e = workItem.Item2;
+ if (pre[id] == null) {
+ // no pre information stored here, so just go ahead through the block
+ } else if (lattice.Below(e, pre[id])) {
+ // no change
+ continue;
+ } else if (b.widenBlock && CommandLineOptions.Clo.StepsBeforeWidening <= iterations[id]) {
+ e = lattice.Widen(pre[id], e);
+ pre[id] = e;
+ iterations[id]++;
+ } else {
+ e = lattice.Join(pre[id], e);
+ pre[id] = e;
+ iterations[id]++;
+ }
+
+ // propagate'e' through b.Cmds
+ foreach (Cmd cmd in b.Cmds) {
+ e = Step(lattice, cmd, e);
+ }
+
+ if (post != null && pre[id] != null) {
+ post[id] = e;
+ }
+
+ var g = b.TransferCmd as GotoCmd;
+ if (g != null) { // if g==null, it's a pity we didn't pay attention to that earlier, because then we could have skipped analyzing the code in this block
+ foreach (Block succ in g.labelTargets) {
+ workItems.Enqueue(new Tuple<Block, NativeLattice.Element>(succ, e));
+ }
+ }
+ }
+
+ Instrument(impl, pre, post);
+ }
+
+ static void Instrument(Implementation impl, NativeLattice.Element[] pre, NativeLattice.Element[] post) {
+ Contract.Requires(impl != null);
+ Contract.Requires(pre != null);
+
+ foreach (var b in impl.Blocks) {
+ var element = pre[b.aiId];
+ if (element != null && (b.widenBlock || CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere)) {
+ List<Cmd> newCommands = new List<Cmd>();
+ Expr inv = element.ToExpr();
+ PredicateCmd cmd;
+ var kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null);
+ if (CommandLineOptions.Clo.InstrumentWithAsserts) {
+ cmd = new AssertCmd(Token.NoToken, inv, kv);
+ } else {
+ cmd = new AssumeCmd(Token.NoToken, inv, kv);
+ }
+ newCommands.Add(cmd);
+ newCommands.AddRange(b.Cmds);
+ if (post != null && post[b.aiId] != null) {
+ inv = post[b.aiId].ToExpr();
+ kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null);
+ if (CommandLineOptions.Clo.InstrumentWithAsserts) {
+ cmd = new AssertCmd(Token.NoToken, inv, kv);
+ } else {
+ cmd = new AssumeCmd(Token.NoToken, inv, kv);
+ }
+ newCommands.Add(cmd);
+ }
+ b.Cmds = newCommands; // destructively replace the commands of the block
+ }
+ }
+ }
+
+ /// <summary>
+ /// The abstract transition relation.
+ /// 'cmd' is allowed to be a StateCmd.
+ /// </summary>
+ static NativeLattice.Element Step(NativeLattice lattice, Cmd cmd, NativeLattice.Element elmt) {
+ Contract.Requires(lattice != null);
+ Contract.Requires(cmd != null);
+ Contract.Requires(elmt != null);
+ Contract.Ensures(Contract.Result<NativeLattice.Element>() != null);
+
+ if (cmd is AssignCmd) { // parallel assignment
+ var c = (AssignCmd)cmd;
+ elmt = lattice.Update(elmt, c.AsSimpleAssignCmd);
+ } else if (cmd is HavocCmd) {
+ var c = (HavocCmd)cmd;
+ foreach (IdentifierExpr id in c.Vars) {
+ Contract.Assert(id != null);
+ elmt = lattice.Eliminate(elmt, id.Decl);
+ }
+ } else if (cmd is PredicateCmd) {
+ var c = (PredicateCmd)cmd;
+ var conjuncts = new List<Expr>();
+ foreach (var ee in Conjuncts(c.Expr)) {
+ Contract.Assert(ee != null);
+ elmt = lattice.Constrain(elmt, ee);
+ }
+ } else if (cmd is StateCmd) {
+ var c = (StateCmd)cmd;
+ // Iterate the abstract transition on all the commands in the desugaring of the call
+ foreach (Cmd callDesug in c.Cmds) {
+ Contract.Assert(callDesug != null);
+ elmt = Step(lattice, callDesug, elmt);
+ }
+ // Project out the local variables of the StateCmd
+ foreach (Variable local in c.Locals) {
+ Contract.Assert(local != null);
+ elmt = lattice.Eliminate(elmt, local);
+ }
+ } else if (cmd is SugaredCmd) {
+ var c = (SugaredCmd)cmd;
+ elmt = Step(lattice, c.Desugaring, elmt);
+ } else if (cmd is CommentCmd) {
+ // skip
+ } else {
+ Contract.Assert(false); // unknown command
+ }
+ return elmt;
+ }
+
+ /// <summary>
+ /// Yields the conjuncts of 'expr'.
+ /// </summary>
+ public static IEnumerable<Expr> Conjuncts(Expr expr) {
+ Contract.Requires(expr != null);
+
+ var e = expr as NAryExpr;
+ if (e != null && e.Fun.FunctionName == "&&") { // if it is a conjunction
+ foreach (Expr ee in e.Args) {
+ Contract.Assert(ee != null);
+ foreach (var c in Conjuncts(ee)) {
+ yield return c;
+ }
+ }
+ } else {
+ yield return expr;
+ }
+ }
+
+ }
+}
diff --git a/Source/AbsInt/Traverse.cs b/Source/AbsInt/Traverse.cs
index 184a4071..92377e56 100644
--- a/Source/AbsInt/Traverse.cs
+++ b/Source/AbsInt/Traverse.cs
@@ -1,169 +1,169 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
-
-
- /// <summary>
- /// This class provides the functionality of traversing a program to determine which
- /// blocks are blocks where the widening operator may need to be applied. Assumes
- /// all 'currentlyTraversed' bits to be initially false, and leaves them that way in
- /// the end. Assumes the 'widenBlock' bits are initially false, and sets them
- /// appropriately.
- /// </summary>
- public class WidenPoints {
- /// <summary>
- /// Compute the widen points of a program
- /// </summary>
- public static void Compute(Program program) {
- Contract.Requires(program != null);
- cce.BeginExpose(program);
-
- foreach (var impl in program.Implementations) {
- if (impl.Blocks != null && impl.Blocks.Count > 0) {
- Contract.Assume(cce.IsConsistent(impl));
- cce.BeginExpose(impl);
- Block start = impl.Blocks[0];
- Contract.Assume(start != null);
- Contract.Assume(cce.IsConsistent(start));
- Visit(start);
-
- // We reset the state...
- foreach (Block b in impl.Blocks) {
- cce.BeginExpose(b);
- b.TraversingStatus = Block.VisitState.ToVisit;
- cce.EndExpose();
- }
- cce.EndExpose();
- }
- }
- cce.EndExpose();
- }
-
- static void Visit(Block b) {
- Contract.Requires(b != null);
- Contract.Assume(cce.IsExposable(b));
- if (b.TraversingStatus == Block.VisitState.BeingVisited) {
- cce.BeginExpose(b);
- // we got here through a back-edge
- b.widenBlock = true;
- cce.EndExpose();
- } else if (b.TraversingStatus == Block.VisitState.AlreadyVisited) {
- // do nothing... we already saw this node
- } else if (b.TransferCmd is GotoCmd) {
- Contract.Assert(b.TraversingStatus == Block.VisitState.ToVisit);
-
- GotoCmd g = (GotoCmd)b.TransferCmd;
- cce.BeginExpose(b);
-
- cce.BeginExpose(g); //PM: required for the subsequent expose (g.labelTargets)
- b.TraversingStatus = Block.VisitState.BeingVisited;
-
- // labelTargets is made non-null by Resolve, which we assume
- // has already called in a prior pass.
- Contract.Assume(g.labelTargets != null);
- cce.BeginExpose(g.labelTargets);
- foreach (Block succ in g.labelTargets)
- // invariant b.currentlyTraversed;
- //PM: The following loop invariant will work once properties are axiomatized
- //&& (g.labelNames != null && g.labelTargets != null ==> g.labelNames.Length == g.labelTargets.Length);
- {
- Contract.Assert(succ != null);
- Visit(succ);
- }
- cce.EndExpose();
-
- Contract.Assert(b.TraversingStatus == Block.VisitState.BeingVisited);
- // System.Diagnostics.Debug.Assert(b.currentlyTraversed);
-
- b.TraversingStatus = Block.VisitState.AlreadyVisited;
-
- //PM: The folowing assumption is needed because we cannot prove that a simple field update
- //PM: leaves the value of a property unchanged.
- Contract.Assume(g.labelNames == null || g.labelNames.Count == g.labelTargets.Count);
- cce.EndExpose();
- } else {
- Contract.Assert(b.TransferCmd == null || b.TransferCmd is ReturnCmd); // It must be a returnCmd;
- }
- }
-
- static private Block rootBlock = null; // The root point we have to consider
-
- /// <summary>
- /// Compute the blocks in the body loop.
- /// <param name ="block"> Tt is the head of the loop. It must be a widen block </param>
- /// <return> The blocks that are in the loop from block </return>
- /// </summary>
- public static List<Block> ComputeLoopBodyFrom(Block block) {
- Contract.Requires(block.widenBlock);
- Contract.Requires(block != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
-
- Contract.Assert(rootBlock == null);
- rootBlock = block;
-
- List<Block/*!*/> blocksInLoop = new List<Block/*!*/>(); // We use a list just because .net does not define a set
- List<Block/*!*/> visitingPath = new List<Block/*!*/>(); // The order is important, as we want paths
-
- blocksInLoop.Add(block);
-
- DoDFSVisit(block, visitingPath, blocksInLoop);
-
- visitingPath.Add(block);
-
-
- rootBlock = null; // We reset the invariant
-
- return blocksInLoop;
- }
-
- /// <summary>
- /// Perform the Depth-first search of the so to find the loop
- /// <param name = "block"> The block to visit </param>
- /// <param name = "path"> The path we are visiting so far </param>
- /// </summary>
- private static void DoDFSVisit(Block block, List<Block> path, List<Block> blocksInPath) {
- Contract.Requires(block != null);
- Contract.Requires(cce.NonNullElements(path));
- Contract.Requires(cce.NonNullElements(path));
- #region case 1. We visit the root => We are done, "path" is a path inside the loop
- if (block == rootBlock && path.Count > 1) {
- blocksInPath.AddRange(path); // Add all the blocks in this path
- }
-
- #endregion
- #region case 2. We visit a node that ends with a return => "path" is not inside the loop
- if (block.TransferCmd is ReturnCmd) {
- return;
- }
- #endregion
- #region case 3. We visit a node with successors => continue the exploration of its successors
- {
- Contract.Assert(block.TransferCmd is GotoCmd);
- GotoCmd successors = (GotoCmd)block.TransferCmd;
- Contract.Assert(successors != null);
-
- if (successors.labelTargets != null)
- foreach (Block nextBlock in successors.labelTargets) {
- Contract.Assert(nextBlock != null);
- if (path.Contains(nextBlock)) // If the current path has already seen the block, just skip it
- continue;
- // Otherwise we perform the DFS visit
- path.Add(nextBlock);
- DoDFSVisit(nextBlock, path, blocksInPath);
-
- Contract.Assert(nextBlock == path[path.Count - 1]);
- path.RemoveAt(path.Count - 1);
- }
-
- }
-
- #endregion
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+
+ /// <summary>
+ /// This class provides the functionality of traversing a program to determine which
+ /// blocks are blocks where the widening operator may need to be applied. Assumes
+ /// all 'currentlyTraversed' bits to be initially false, and leaves them that way in
+ /// the end. Assumes the 'widenBlock' bits are initially false, and sets them
+ /// appropriately.
+ /// </summary>
+ public class WidenPoints {
+ /// <summary>
+ /// Compute the widen points of a program
+ /// </summary>
+ public static void Compute(Program program) {
+ Contract.Requires(program != null);
+ cce.BeginExpose(program);
+
+ foreach (var impl in program.Implementations) {
+ if (impl.Blocks != null && impl.Blocks.Count > 0) {
+ Contract.Assume(cce.IsConsistent(impl));
+ cce.BeginExpose(impl);
+ Block start = impl.Blocks[0];
+ Contract.Assume(start != null);
+ Contract.Assume(cce.IsConsistent(start));
+ Visit(start);
+
+ // We reset the state...
+ foreach (Block b in impl.Blocks) {
+ cce.BeginExpose(b);
+ b.TraversingStatus = Block.VisitState.ToVisit;
+ cce.EndExpose();
+ }
+ cce.EndExpose();
+ }
+ }
+ cce.EndExpose();
+ }
+
+ static void Visit(Block b) {
+ Contract.Requires(b != null);
+ Contract.Assume(cce.IsExposable(b));
+ if (b.TraversingStatus == Block.VisitState.BeingVisited) {
+ cce.BeginExpose(b);
+ // we got here through a back-edge
+ b.widenBlock = true;
+ cce.EndExpose();
+ } else if (b.TraversingStatus == Block.VisitState.AlreadyVisited) {
+ // do nothing... we already saw this node
+ } else if (b.TransferCmd is GotoCmd) {
+ Contract.Assert(b.TraversingStatus == Block.VisitState.ToVisit);
+
+ GotoCmd g = (GotoCmd)b.TransferCmd;
+ cce.BeginExpose(b);
+
+ cce.BeginExpose(g); //PM: required for the subsequent expose (g.labelTargets)
+ b.TraversingStatus = Block.VisitState.BeingVisited;
+
+ // labelTargets is made non-null by Resolve, which we assume
+ // has already called in a prior pass.
+ Contract.Assume(g.labelTargets != null);
+ cce.BeginExpose(g.labelTargets);
+ foreach (Block succ in g.labelTargets)
+ // invariant b.currentlyTraversed;
+ //PM: The following loop invariant will work once properties are axiomatized
+ //&& (g.labelNames != null && g.labelTargets != null ==> g.labelNames.Length == g.labelTargets.Length);
+ {
+ Contract.Assert(succ != null);
+ Visit(succ);
+ }
+ cce.EndExpose();
+
+ Contract.Assert(b.TraversingStatus == Block.VisitState.BeingVisited);
+ // System.Diagnostics.Debug.Assert(b.currentlyTraversed);
+
+ b.TraversingStatus = Block.VisitState.AlreadyVisited;
+
+ //PM: The folowing assumption is needed because we cannot prove that a simple field update
+ //PM: leaves the value of a property unchanged.
+ Contract.Assume(g.labelNames == null || g.labelNames.Count == g.labelTargets.Count);
+ cce.EndExpose();
+ } else {
+ Contract.Assert(b.TransferCmd == null || b.TransferCmd is ReturnCmd); // It must be a returnCmd;
+ }
+ }
+
+ static private Block rootBlock = null; // The root point we have to consider
+
+ /// <summary>
+ /// Compute the blocks in the body loop.
+ /// <param name ="block"> Tt is the head of the loop. It must be a widen block </param>
+ /// <return> The blocks that are in the loop from block </return>
+ /// </summary>
+ public static List<Block> ComputeLoopBodyFrom(Block block) {
+ Contract.Requires(block.widenBlock);
+ Contract.Requires(block != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+
+ Contract.Assert(rootBlock == null);
+ rootBlock = block;
+
+ List<Block/*!*/> blocksInLoop = new List<Block/*!*/>(); // We use a list just because .net does not define a set
+ List<Block/*!*/> visitingPath = new List<Block/*!*/>(); // The order is important, as we want paths
+
+ blocksInLoop.Add(block);
+
+ DoDFSVisit(block, visitingPath, blocksInLoop);
+
+ visitingPath.Add(block);
+
+
+ rootBlock = null; // We reset the invariant
+
+ return blocksInLoop;
+ }
+
+ /// <summary>
+ /// Perform the Depth-first search of the so to find the loop
+ /// <param name = "block"> The block to visit </param>
+ /// <param name = "path"> The path we are visiting so far </param>
+ /// </summary>
+ private static void DoDFSVisit(Block block, List<Block> path, List<Block> blocksInPath) {
+ Contract.Requires(block != null);
+ Contract.Requires(cce.NonNullElements(path));
+ Contract.Requires(cce.NonNullElements(path));
+ #region case 1. We visit the root => We are done, "path" is a path inside the loop
+ if (block == rootBlock && path.Count > 1) {
+ blocksInPath.AddRange(path); // Add all the blocks in this path
+ }
+
+ #endregion
+ #region case 2. We visit a node that ends with a return => "path" is not inside the loop
+ if (block.TransferCmd is ReturnCmd) {
+ return;
+ }
+ #endregion
+ #region case 3. We visit a node with successors => continue the exploration of its successors
+ {
+ Contract.Assert(block.TransferCmd is GotoCmd);
+ GotoCmd successors = (GotoCmd)block.TransferCmd;
+ Contract.Assert(successors != null);
+
+ if (successors.labelTargets != null)
+ foreach (Block nextBlock in successors.labelTargets) {
+ Contract.Assert(nextBlock != null);
+ if (path.Contains(nextBlock)) // If the current path has already seen the block, just skip it
+ continue;
+ // Otherwise we perform the DFS visit
+ path.Add(nextBlock);
+ DoDFSVisit(nextBlock, path, blocksInPath);
+
+ Contract.Assert(nextBlock == path[path.Count - 1]);
+ path.RemoveAt(path.Count - 1);
+ }
+
+ }
+
+ #endregion
+ }
+ }
+}
diff --git a/Source/AbsInt/TrivialDomain.cs b/Source/AbsInt/TrivialDomain.cs
index f9298e11..123bcefe 100644
--- a/Source/AbsInt/TrivialDomain.cs
+++ b/Source/AbsInt/TrivialDomain.cs
@@ -1,79 +1,79 @@
-using System;
-using System.Numerics;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.AbstractInterpretation
-{
- class TrivialDomain : NativeLattice
- {
- class E : NativeLattice.Element
- {
- public readonly bool IsTop;
- public E(bool isTop) {
- IsTop = isTop;
- }
-
- public override Expr ToExpr() {
- return Expr.Literal(IsTop);
- }
- }
-
- private E top = new E(true);
- private E bottom = new E(false);
-
- public override Element Top { get { return top; } }
- public override Element Bottom { get { return bottom; } }
-
- public override bool IsTop(Element element) {
- var e = (E)element;
- return e.IsTop;
- }
- public override bool IsBottom(Element element) {
- var e = (E)element;
- return !e.IsTop;
- }
-
- public override bool Below(Element a, Element b) {
- return IsBottom(a) || IsTop(b);
- }
-
- public override Element Meet(Element a, Element b) {
- if (IsBottom(b)) {
- return b;
- } else {
- return a;
- }
- }
-
- public override Element Join(Element a, Element b) {
- if (IsTop(b)) {
- return b;
- } else {
- return a;
- }
- }
-
- public override Element Widen(Element a, Element b) {
- return Join(a, b); // it's a finite domain, after all
- }
-
- public override Element Constrain(Element element, Expr expr) {
- var e = (E)element;
- var lit = expr as LiteralExpr;
- if (lit != null && lit.isBool && !(bool)lit.Val) {
- return bottom;
- } else {
- return e;
- }
- }
-
- public override Element Update(Element element, AssignCmd cmd) {
- return element;
- }
-
- public override Element Eliminate(Element element, Variable v) {
- return element;
- }
- }
-}
+using System;
+using System.Numerics;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie.AbstractInterpretation
+{
+ class TrivialDomain : NativeLattice
+ {
+ class E : NativeLattice.Element
+ {
+ public readonly bool IsTop;
+ public E(bool isTop) {
+ IsTop = isTop;
+ }
+
+ public override Expr ToExpr() {
+ return Expr.Literal(IsTop);
+ }
+ }
+
+ private E top = new E(true);
+ private E bottom = new E(false);
+
+ public override Element Top { get { return top; } }
+ public override Element Bottom { get { return bottom; } }
+
+ public override bool IsTop(Element element) {
+ var e = (E)element;
+ return e.IsTop;
+ }
+ public override bool IsBottom(Element element) {
+ var e = (E)element;
+ return !e.IsTop;
+ }
+
+ public override bool Below(Element a, Element b) {
+ return IsBottom(a) || IsTop(b);
+ }
+
+ public override Element Meet(Element a, Element b) {
+ if (IsBottom(b)) {
+ return b;
+ } else {
+ return a;
+ }
+ }
+
+ public override Element Join(Element a, Element b) {
+ if (IsTop(b)) {
+ return b;
+ } else {
+ return a;
+ }
+ }
+
+ public override Element Widen(Element a, Element b) {
+ return Join(a, b); // it's a finite domain, after all
+ }
+
+ public override Element Constrain(Element element, Expr expr) {
+ var e = (E)element;
+ var lit = expr as LiteralExpr;
+ if (lit != null && lit.isBool && !(bool)lit.Val) {
+ return bottom;
+ } else {
+ return e;
+ }
+ }
+
+ public override Element Update(Element element, AssignCmd cmd) {
+ return element;
+ }
+
+ public override Element Eliminate(Element element, Variable v) {
+ return element;
+ }
+ }
+}
diff --git a/Source/AbsInt/cce.cs b/Source/AbsInt/cce.cs
index 693d608c..627add75 100644
--- a/Source/AbsInt/cce.cs
+++ b/Source/AbsInt/cce.cs
@@ -1,62 +1,62 @@
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-using Microsoft.Boogie;
-
- /// <summary>
- /// A class containing static methods to extend the functionality of Code Contracts
- /// </summary>
-
-public static class cce {
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements(VariableSeq collection) {
- return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- }
-
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
-
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
-
- public static bool IsPeerConsistent(this object o) {
- return true;
- }
-
- public static bool IsConsistent(this object o) {
- return true;
- }
-
- public static bool IsExposable(this object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- }
-}
-public class PeerAttribute : System.Attribute {
-}
-public class RepAttribute : System.Attribute {
-}
-public class CapturedAttribute : System.Attribute {
-}
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+using Microsoft.Boogie;
+
+ /// <summary>
+ /// A class containing static methods to extend the functionality of Code Contracts
+ /// </summary>
+
+public static class cce {
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements(VariableSeq collection) {
+ return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ }
+
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+
+ public static bool IsPeerConsistent(this object o) {
+ return true;
+ }
+
+ public static bool IsConsistent(this object o) {
+ return true;
+ }
+
+ public static bool IsExposable(this object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ }
+}
+public class PeerAttribute : System.Attribute {
+}
+public class RepAttribute : System.Attribute {
+}
+public class CapturedAttribute : System.Attribute {
+}
diff --git a/Source/BVD/App.config b/Source/BVD/App.config
index fad249e4..8e156463 100644
--- a/Source/BVD/App.config
+++ b/Source/BVD/App.config
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<configuration>
- <startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
- </startup>
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
</configuration> \ No newline at end of file
diff --git a/Source/BVD/BVD.csproj b/Source/BVD/BVD.csproj
index ccf52191..e83cfdd7 100644
--- a/Source/BVD/BVD.csproj
+++ b/Source/BVD/BVD.csproj
@@ -1,106 +1,106 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{8A05D14E-F2BF-4890-BBE0-D76B18A50797}</ProjectGuid>
- <OutputType>WinExe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.ModelViewer</RootNamespace>
- <AssemblyName>BVD</AssemblyName>
- <FileAlignment>512</FileAlignment>
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <ProductVersion>12.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Data" />
- <Reference Include="System.Deployment" />
- <Reference Include="System.Drawing" />
- <Reference Include="System.Numerics" />
- <Reference Include="System.Windows.Forms" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Program.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="App.config" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\ModelViewer\ModelViewer.csproj">
- <Project>{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}</Project>
- <Name>ModelViewer</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include=".NETFramework,Version=v4.5">
- <Visible>False</Visible>
- <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{8A05D14E-F2BF-4890-BBE0-D76B18A50797}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie.ModelViewer</RootNamespace>
+ <AssemblyName>BVD</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <ProductVersion>12.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Numerics" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\ModelViewer\ModelViewer.csproj">
+ <Project>{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}</Project>
+ <Name>ModelViewer</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.5">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/Source/BVD/Program.cs b/Source/BVD/Program.cs
index 669ea995..a606c863 100644
--- a/Source/BVD/Program.cs
+++ b/Source/BVD/Program.cs
@@ -1,28 +1,28 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows.Forms;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- static class Program
- {
- /// <summary>
- /// The main entry point for the application.
- /// </summary>
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- try
- {
- Application.Run(new Main(System.Environment.GetCommandLineArgs()));
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "Model Viewer Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ try
+ {
+ Application.Run(new Main(System.Environment.GetCommandLineArgs()));
+ }
+ catch (Exception exc)
+ {
+ MessageBox.Show(exc.Message, "Model Viewer Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
+ }
+ }
+ }
+}
diff --git a/Source/BVD/Properties/AssemblyInfo.cs b/Source/BVD/Properties/AssemblyInfo.cs
index 3512374e..0e9c953a 100644
--- a/Source/BVD/Properties/AssemblyInfo.cs
+++ b/Source/BVD/Properties/AssemblyInfo.cs
@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("BVD")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("BVD")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("00610a12-cf4c-4c29-af30-31a99d22b9d8")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BVD")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BVD")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("00610a12-cf4c-4c29-af30-31a99d22b9d8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Basetypes/Basetypes.csproj b/Source/Basetypes/Basetypes.csproj
index 4ecdee8d..5b425bc5 100644
--- a/Source/Basetypes/Basetypes.csproj
+++ b/Source/Basetypes/Basetypes.csproj
@@ -1,204 +1,204 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Basetypes</RootNamespace>
- <AssemblyName>Basetypes</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Basetypes.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Basetypes.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Numerics" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="BigDec.cs" />
- <Compile Include="BigNum.cs" />
- <Compile Include="BigFloat.cs" />
- <Compile Include="Rational.cs" />
- <Compile Include="Set.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Basetypes</RootNamespace>
+ <AssemblyName>BoogieBasetypes</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for Basetypes.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Basetypes.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Numerics" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="BigDec.cs" />
+ <Compile Include="BigNum.cs" />
+ <Compile Include="BigFloat.cs" />
+ <Compile Include="Rational.cs" />
+ <Compile Include="Set.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
</Project> \ No newline at end of file
diff --git a/Source/Basetypes/BigDec.cs b/Source/Basetypes/BigDec.cs
index 0aeea8b1..e4666793 100644
--- a/Source/Basetypes/BigDec.cs
+++ b/Source/Basetypes/BigDec.cs
@@ -1,380 +1,380 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.Diagnostics;
-
-
-namespace Microsoft.Basetypes {
- using BIM = System.Numerics.BigInteger;
-
-
- /// <summary>
- /// A representation of decimal values.
- /// </summary>
- public struct BigDec {
-
- // the internal representation
- [Rep]
- internal readonly BIM mantissa;
- [Rep]
- internal readonly int exponent;
-
- public BIM Mantissa {
- get {
- return mantissa;
- }
- }
-
- public int Exponent {
- get {
- return exponent;
- }
- }
-
- public static readonly BigDec ZERO = FromInt(0);
- private static readonly BIM ten = new BIM(10);
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Constructors
-
- [Pure]
- public static BigDec FromInt(int v) {
- return new BigDec(v, 0);
- }
-
- [Pure]
- public static BigDec FromBigInt(BIM v) {
- return new BigDec(v, 0);
- }
-
- [Pure]
- public static BigDec FromString(string v) {
- if (v == null) throw new FormatException();
-
- BIM integral = BIM.Zero;
- BIM fraction = BIM.Zero;
- int exponent = 0;
-
- int len = v.Length;
-
- int i = v.IndexOf('e');
- if (i >= 0) {
- if (i + 1 == v.Length) throw new FormatException();
- exponent = Int32.Parse(v.Substring(i + 1, len - i - 1));
- len = i;
- }
-
- int fractionLen = 0;
- i = v.IndexOf('.');
- if (i >= 0) {
- if (i + 1 == v.Length) throw new FormatException();
- fractionLen = len - i - 1;
- fraction = BIM.Parse(v.Substring(i + 1, fractionLen));
- len = i;
- }
-
- integral = BIM.Parse(v.Substring(0, len));
-
- if (!fraction.IsZero) {
- while (fractionLen > 0) {
- integral = integral * ten;
- exponent = exponent - 1;
- fractionLen = fractionLen - 1;
- }
- }
-
- if (integral.Sign == -1) {
- return new BigDec(integral - fraction, exponent);
- }
- else {
- return new BigDec(integral + fraction, exponent);
- }
- }
-
- internal BigDec(BIM mantissa, int exponent) {
- if (mantissa.IsZero) {
- this.mantissa = mantissa;
- this.exponent = 0;
- }
- else {
- while (mantissa % ten == BIM.Zero) {
- mantissa = mantissa / ten;
- exponent = exponent + 1;
- }
- this.mantissa = mantissa;
- this.exponent = exponent;
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Basic object operations
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is BigDec))
- return false;
-
- return (this == (BigDec)obj);
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.mantissa.GetHashCode() * 13 + this.exponent.GetHashCode();
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return String.Format("{0}e{1}", this.mantissa.ToString(), this.exponent.ToString());
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Conversion operations
-
- // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int).
- /// <summary>
- /// Computes the floor and ceiling of this BigDec. Note the choice of rounding towards negative
- /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way.
- /// </summary>
- /// <param name="floor">The Floor (rounded towards negative infinity)</param>
- /// <param name="ceiling">Ceiling (rounded towards positive infinity)</param>
- public void FloorCeiling(out BIM floor, out BIM ceiling) {
- BIM n = this.mantissa;
- int e = this.exponent;
- if (n.IsZero) {
- floor = ceiling = n;
- } else if (0 <= e) {
- // it's an integer
- for (; 0 < e; e--) {
- n = n * ten;
- }
- floor = ceiling = n;
- } else {
- // it's a non-zero integer, so the ceiling is one more than the floor
- for (; e < 0 && !n.IsZero; e++) {
- n = n / ten; // Division rounds towards negative infinity
- }
-
- if (this.mantissa >= 0) {
- floor = n;
- ceiling = n + 1;
- } else {
- ceiling = n;
- floor = n - 1;
- }
- }
- Debug.Assert(floor <= ceiling, "Invariant was not maintained");
- }
-
- [Pure]
- public String ToDecimalString(int maxDigits) {
- string s = this.mantissa.ToString();
- int digits = (this.mantissa >= 0) ? s.Length : s.Length - 1;
- BIM max = BIM.Pow(10, maxDigits);
- BIM min = -max;
-
- if (this.exponent >= 0) {
- if (maxDigits < digits || maxDigits - digits < this.exponent) {
- return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString());
- }
- else {
- return String.Format("{0}{1}.0", s, new string('0', this.exponent));
- }
- }
- else {
- int exp = -this.exponent;
-
- if (exp < digits) {
- int intDigits = digits - exp;
- if (maxDigits < intDigits) {
- return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString());
- }
- else {
- int fracDigits = Math.Min(maxDigits, digits - intDigits);
- return String.Format("{0}.{1}", s.Substring(0, intDigits), s.Substring(intDigits, fracDigits));
- }
- }
- else {
- int fracDigits = Math.Min(maxDigits, digits);
- return String.Format("0.{0}{1}", new string('0', exp - fracDigits), s.Substring(0, fracDigits));
- }
- }
- }
-
- [Pure]
- public string ToDecimalString() {
- string m = this.mantissa.ToString();
- var e = this.exponent;
- if (0 <= this.exponent) {
- return m + Zeros(e) + ".0";
- } else {
- e = -e;
- // compute k to be the longest suffix of m consisting of all zeros (but no longer than e, and not the entire string)
- var maxK = e < m.Length ? e : m.Length - 1;
- var last = m.Length - 1;
- var k = 0;
- while (k < maxK && m[last - k] == '0') {
- k++;
- }
- if (0 < k) {
- // chop off the suffix of k zeros from m and adjust e accordingly
- m = m.Substring(0, m.Length - k);
- e -= k;
- }
- if (e == 0) {
- return m;
- } else if (e < m.Length) {
- var n = m.Length - e;
- return m.Substring(0, n) + "." + m.Substring(n);
- } else {
- return "0." + Zeros(e - m.Length) + m;
- }
- }
- }
-
- [Pure]
- public static string Zeros(int n) {
- Contract.Requires(0 <= n);
- if (n <= 10) {
- var tenZeros = "0000000000";
- return tenZeros.Substring(0, n);
- } else {
- var d = n / 2;
- var s = Zeros(d);
- if (n % 2 == 0) {
- return s + s;
- } else {
- return s + s + "0";
- }
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Basic arithmetic operations
-
- [Pure]
- public BigDec Abs {
- get {
- return new BigDec(BIM.Abs(this.mantissa), this.exponent);
- }
- }
-
- [Pure]
- public BigDec Negate {
- get {
- return new BigDec(BIM.Negate(this.mantissa), this.exponent);
- }
- }
-
- [Pure]
- public static BigDec operator -(BigDec x) {
- return x.Negate;
- }
-
- [Pure]
- public static BigDec operator +(BigDec x, BigDec y) {
- BIM m1 = x.mantissa;
- int e1 = x.exponent;
- BIM m2 = y.mantissa;
- int e2 = y.exponent;
- if (e2 < e1) {
- m1 = y.mantissa;
- e1 = y.exponent;
- m2 = x.mantissa;
- e2 = x.exponent;
- }
-
- while (e2 > e1) {
- m2 = m2 * ten;
- e2 = e2 - 1;
- }
-
- return new BigDec(m1 + m2, e1);
- }
-
- [Pure]
- public static BigDec operator -(BigDec x, BigDec y) {
- return x + y.Negate;
- }
-
- [Pure]
- public static BigDec operator *(BigDec x, BigDec y) {
- return new BigDec(x.mantissa * y.mantissa, x.exponent + y.exponent);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Some basic comparison operations
-
- public bool IsPositive {
- get {
- return (this.mantissa > BIM.Zero);
- }
- }
-
- public bool IsNegative {
- get {
- return (this.mantissa < BIM.Zero);
- }
- }
-
- public bool IsZero {
- get {
- return this.mantissa.IsZero;
- }
- }
-
- [Pure]
- public int CompareTo(BigDec that) {
- if (this.mantissa == that.mantissa && this.exponent == that.exponent) {
- return 0;
- }
- else {
- BigDec d = this - that;
- return d.IsNegative ? -1 : 1;
- }
- }
-
- [Pure]
- public static bool operator ==(BigDec x, BigDec y) {
- return x.CompareTo(y) == 0;
- }
-
- [Pure]
- public static bool operator !=(BigDec x, BigDec y) {
- return x.CompareTo(y) != 0;
- }
-
- [Pure]
- public static bool operator <(BigDec x, BigDec y) {
- return x.CompareTo(y) < 0;
- }
-
- [Pure]
- public static bool operator >(BigDec x, BigDec y) {
- return x.CompareTo(y) > 0;
- }
-
- [Pure]
- public static bool operator <=(BigDec x, BigDec y) {
- return x.CompareTo(y) <= 0;
- }
-
- [Pure]
- public static bool operator >=(BigDec x, BigDec y) {
- return x.CompareTo(y) >= 0;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.Diagnostics.Contracts;
+using System.Diagnostics;
+
+
+namespace Microsoft.Basetypes {
+ using BIM = System.Numerics.BigInteger;
+
+
+ /// <summary>
+ /// A representation of decimal values.
+ /// </summary>
+ public struct BigDec {
+
+ // the internal representation
+ [Rep]
+ internal readonly BIM mantissa;
+ [Rep]
+ internal readonly int exponent;
+
+ public BIM Mantissa {
+ get {
+ return mantissa;
+ }
+ }
+
+ public int Exponent {
+ get {
+ return exponent;
+ }
+ }
+
+ public static readonly BigDec ZERO = FromInt(0);
+ private static readonly BIM ten = new BIM(10);
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructors
+
+ [Pure]
+ public static BigDec FromInt(int v) {
+ return new BigDec(v, 0);
+ }
+
+ [Pure]
+ public static BigDec FromBigInt(BIM v) {
+ return new BigDec(v, 0);
+ }
+
+ [Pure]
+ public static BigDec FromString(string v) {
+ if (v == null) throw new FormatException();
+
+ BIM integral = BIM.Zero;
+ BIM fraction = BIM.Zero;
+ int exponent = 0;
+
+ int len = v.Length;
+
+ int i = v.IndexOf('e');
+ if (i >= 0) {
+ if (i + 1 == v.Length) throw new FormatException();
+ exponent = Int32.Parse(v.Substring(i + 1, len - i - 1));
+ len = i;
+ }
+
+ int fractionLen = 0;
+ i = v.IndexOf('.');
+ if (i >= 0) {
+ if (i + 1 == v.Length) throw new FormatException();
+ fractionLen = len - i - 1;
+ fraction = BIM.Parse(v.Substring(i + 1, fractionLen));
+ len = i;
+ }
+
+ integral = BIM.Parse(v.Substring(0, len));
+
+ if (!fraction.IsZero) {
+ while (fractionLen > 0) {
+ integral = integral * ten;
+ exponent = exponent - 1;
+ fractionLen = fractionLen - 1;
+ }
+ }
+
+ if (integral.Sign == -1) {
+ return new BigDec(integral - fraction, exponent);
+ }
+ else {
+ return new BigDec(integral + fraction, exponent);
+ }
+ }
+
+ internal BigDec(BIM mantissa, int exponent) {
+ if (mantissa.IsZero) {
+ this.mantissa = mantissa;
+ this.exponent = 0;
+ }
+ else {
+ while (mantissa % ten == BIM.Zero) {
+ mantissa = mantissa / ten;
+ exponent = exponent + 1;
+ }
+ this.mantissa = mantissa;
+ this.exponent = exponent;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Basic object operations
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is BigDec))
+ return false;
+
+ return (this == (BigDec)obj);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.mantissa.GetHashCode() * 13 + this.exponent.GetHashCode();
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return String.Format("{0}e{1}", this.mantissa.ToString(), this.exponent.ToString());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Conversion operations
+
+ // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int).
+ /// <summary>
+ /// Computes the floor and ceiling of this BigDec. Note the choice of rounding towards negative
+ /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way.
+ /// </summary>
+ /// <param name="floor">The Floor (rounded towards negative infinity)</param>
+ /// <param name="ceiling">Ceiling (rounded towards positive infinity)</param>
+ public void FloorCeiling(out BIM floor, out BIM ceiling) {
+ BIM n = this.mantissa;
+ int e = this.exponent;
+ if (n.IsZero) {
+ floor = ceiling = n;
+ } else if (0 <= e) {
+ // it's an integer
+ for (; 0 < e; e--) {
+ n = n * ten;
+ }
+ floor = ceiling = n;
+ } else {
+ // it's a non-zero integer, so the ceiling is one more than the floor
+ for (; e < 0 && !n.IsZero; e++) {
+ n = n / ten; // Division rounds towards negative infinity
+ }
+
+ if (this.mantissa >= 0) {
+ floor = n;
+ ceiling = n + 1;
+ } else {
+ ceiling = n;
+ floor = n - 1;
+ }
+ }
+ Debug.Assert(floor <= ceiling, "Invariant was not maintained");
+ }
+
+ [Pure]
+ public String ToDecimalString(int maxDigits) {
+ string s = this.mantissa.ToString();
+ int digits = (this.mantissa >= 0) ? s.Length : s.Length - 1;
+ BIM max = BIM.Pow(10, maxDigits);
+ BIM min = -max;
+
+ if (this.exponent >= 0) {
+ if (maxDigits < digits || maxDigits - digits < this.exponent) {
+ return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString());
+ }
+ else {
+ return String.Format("{0}{1}.0", s, new string('0', this.exponent));
+ }
+ }
+ else {
+ int exp = -this.exponent;
+
+ if (exp < digits) {
+ int intDigits = digits - exp;
+ if (maxDigits < intDigits) {
+ return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString());
+ }
+ else {
+ int fracDigits = Math.Min(maxDigits, digits - intDigits);
+ return String.Format("{0}.{1}", s.Substring(0, intDigits), s.Substring(intDigits, fracDigits));
+ }
+ }
+ else {
+ int fracDigits = Math.Min(maxDigits, digits);
+ return String.Format("0.{0}{1}", new string('0', exp - fracDigits), s.Substring(0, fracDigits));
+ }
+ }
+ }
+
+ [Pure]
+ public string ToDecimalString() {
+ string m = this.mantissa.ToString();
+ var e = this.exponent;
+ if (0 <= this.exponent) {
+ return m + Zeros(e) + ".0";
+ } else {
+ e = -e;
+ // compute k to be the longest suffix of m consisting of all zeros (but no longer than e, and not the entire string)
+ var maxK = e < m.Length ? e : m.Length - 1;
+ var last = m.Length - 1;
+ var k = 0;
+ while (k < maxK && m[last - k] == '0') {
+ k++;
+ }
+ if (0 < k) {
+ // chop off the suffix of k zeros from m and adjust e accordingly
+ m = m.Substring(0, m.Length - k);
+ e -= k;
+ }
+ if (e == 0) {
+ return m;
+ } else if (e < m.Length) {
+ var n = m.Length - e;
+ return m.Substring(0, n) + "." + m.Substring(n);
+ } else {
+ return "0." + Zeros(e - m.Length) + m;
+ }
+ }
+ }
+
+ [Pure]
+ public static string Zeros(int n) {
+ Contract.Requires(0 <= n);
+ if (n <= 10) {
+ var tenZeros = "0000000000";
+ return tenZeros.Substring(0, n);
+ } else {
+ var d = n / 2;
+ var s = Zeros(d);
+ if (n % 2 == 0) {
+ return s + s;
+ } else {
+ return s + s + "0";
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Basic arithmetic operations
+
+ [Pure]
+ public BigDec Abs {
+ get {
+ return new BigDec(BIM.Abs(this.mantissa), this.exponent);
+ }
+ }
+
+ [Pure]
+ public BigDec Negate {
+ get {
+ return new BigDec(BIM.Negate(this.mantissa), this.exponent);
+ }
+ }
+
+ [Pure]
+ public static BigDec operator -(BigDec x) {
+ return x.Negate;
+ }
+
+ [Pure]
+ public static BigDec operator +(BigDec x, BigDec y) {
+ BIM m1 = x.mantissa;
+ int e1 = x.exponent;
+ BIM m2 = y.mantissa;
+ int e2 = y.exponent;
+ if (e2 < e1) {
+ m1 = y.mantissa;
+ e1 = y.exponent;
+ m2 = x.mantissa;
+ e2 = x.exponent;
+ }
+
+ while (e2 > e1) {
+ m2 = m2 * ten;
+ e2 = e2 - 1;
+ }
+
+ return new BigDec(m1 + m2, e1);
+ }
+
+ [Pure]
+ public static BigDec operator -(BigDec x, BigDec y) {
+ return x + y.Negate;
+ }
+
+ [Pure]
+ public static BigDec operator *(BigDec x, BigDec y) {
+ return new BigDec(x.mantissa * y.mantissa, x.exponent + y.exponent);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Some basic comparison operations
+
+ public bool IsPositive {
+ get {
+ return (this.mantissa > BIM.Zero);
+ }
+ }
+
+ public bool IsNegative {
+ get {
+ return (this.mantissa < BIM.Zero);
+ }
+ }
+
+ public bool IsZero {
+ get {
+ return this.mantissa.IsZero;
+ }
+ }
+
+ [Pure]
+ public int CompareTo(BigDec that) {
+ if (this.mantissa == that.mantissa && this.exponent == that.exponent) {
+ return 0;
+ }
+ else {
+ BigDec d = this - that;
+ return d.IsNegative ? -1 : 1;
+ }
+ }
+
+ [Pure]
+ public static bool operator ==(BigDec x, BigDec y) {
+ return x.CompareTo(y) == 0;
+ }
+
+ [Pure]
+ public static bool operator !=(BigDec x, BigDec y) {
+ return x.CompareTo(y) != 0;
+ }
+
+ [Pure]
+ public static bool operator <(BigDec x, BigDec y) {
+ return x.CompareTo(y) < 0;
+ }
+
+ [Pure]
+ public static bool operator >(BigDec x, BigDec y) {
+ return x.CompareTo(y) > 0;
+ }
+
+ [Pure]
+ public static bool operator <=(BigDec x, BigDec y) {
+ return x.CompareTo(y) <= 0;
+ }
+
+ [Pure]
+ public static bool operator >=(BigDec x, BigDec y) {
+ return x.CompareTo(y) >= 0;
+ }
+ }
+}
diff --git a/Source/Basetypes/BigNum.cs b/Source/Basetypes/BigNum.cs
index ff676bc6..4469f149 100644
--- a/Source/Basetypes/BigNum.cs
+++ b/Source/Basetypes/BigNum.cs
@@ -1,361 +1,361 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.Diagnostics.Contracts;
-
-
-namespace Microsoft.Basetypes {
- using BIM = System.Numerics.BigInteger;
-
- /// <summary>
- /// A thin wrapper around System.Numerics.BigInteger
- /// (to be able to define equality, etc. properly)
- /// </summary>
- public struct BigNum {
-
- // the internal representation
- [Rep]
- internal readonly System.Numerics.BigInteger val;
- public static readonly BigNum ZERO = new BigNum(BIM.Zero);
- public static readonly BigNum ONE = new BigNum(BIM.One);
- public static readonly BigNum MINUS_ONE = new BigNum(-BIM.One);
-
- [Pure]
- public static BigNum FromInt(int v) {
- return new BigNum(new BIM(v));
- }
-
- [Pure]
- public static BigNum FromUInt(uint v) {
- return new BigNum(new BIM((long)v));
- }
-
- [Pure]
- public static BigNum FromLong(long v) {
- return new BigNum(new BIM(v));
- }
-
- [Pure]
- public static BigNum FromBigInt(System.Numerics.BigInteger v) {
- return new BigNum(v);
- }
-
- [Pure]
- public static BigNum FromULong(ulong v) {
- return FromString("" + v);
- }
-
- [Pure]
- public static BigNum FromString(string v) {
- try {
- return new BigNum(BIM.Parse(v));
- } catch (System.ArgumentException) {
- throw new FormatException();
- }
- }
-
- public static bool TryParse(string v, out BigNum res) {
- try {
- res = BigNum.FromString(v);
- return true;
- } catch (FormatException) {
- res = ZERO;
- return false;
- }
- }
-
- // Convert to int, without checking whether overflows occur
- public int ToInt {
- get {
- return (int)val;
- }
- }
-
- public BIM ToBigInteger {
- get {
- return val;
- }
- }
-
- // Convert to int; assert that no overflows occur
- public int ToIntSafe {
- get {
- Contract.Assert(this.InInt32);
- return this.ToInt;
- }
- }
-
- public Rational ToRational {
- get {
- return Rational.FromBignum(this);
- }
- }
-
- public byte[] ToByteArray()
- {
- return this.val.ToByteArray();
- }
-
- internal BigNum(System.Numerics.BigInteger val) {
- this.val = val;
- }
-
- public static bool operator ==(BigNum x, BigNum y) {
- return (x.val == y.val);
- }
-
- public static bool operator !=(BigNum x, BigNum y) {
- return !(x.val == y.val);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is BigNum))
- return false;
-
- BigNum other = (BigNum)obj;
- return (this.val == other.val);
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.val.GetHashCode();
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return cce.NonNull(val.ToString());
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Very limited support for format strings
- // Note: Negative integers are linearised with a minus "-" in hexadecimal,
- // not in 2-complement notation (in contrast to what the method
- // int32.ToString(format) does)
-
- [Pure]
- public string/*!*/ ToString(string/*!*/ format) {
- Contract.Requires(format != null);
- Contract.Ensures(Contract.Result<string>() != null);
- if (format.StartsWith("d") || format.StartsWith("D")) {
- string res = this.Abs.ToString();
- Contract.Assert(res != null);
- return addMinus(this.Signum,
- prefixWithZeros(extractPrecision(format), res));
- } else if (format.StartsWith("x") || format.StartsWith("X")) {
- string res = this.toHex(format.Substring(0, 1));
- Contract.Assert(res != null);
- return addMinus(this.Signum,
- prefixWithZeros(extractPrecision(format), res));
- } else {
- throw new FormatException("Format " + format + " is not supported");
- }
- }
-
- private static readonly System.Numerics.BigInteger BI_2_TO_24 = new BIM(0x1000000);
-
- [Pure]
- private string/*!*/ toHex(string/*!*/ format) {
- Contract.Requires(format != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string res = "";
- System.Numerics.BigInteger rem = this.Abs.val;
-
- while (rem > BIM.Zero) {
- res = ((int)(rem % BI_2_TO_24)).ToString(format) + res;
- rem = rem / BI_2_TO_24;
- }
-
- return res;
- }
-
- [Pure]
- private int extractPrecision(string/*!*/ format) {
- Contract.Requires(format != null);
- if (format.Length > 1)
- // will throw a FormatException if the precision is invalid;
- // that is ok
- return Int32.Parse(format.Substring(1));
- // always output at least one digit
- return 1;
- }
-
- [Pure]
- private string/*!*/ addMinus(int signum, string/*!*/ suffix) {
- Contract.Requires(suffix != null);
- Contract.Ensures(Contract.Result<string>() != null);
- if (signum < 0)
- return "-" + suffix;
- return suffix;
- }
-
- [Pure]
- private string/*!*/ prefixWithZeros(int minLength, string/*!*/ suffix) {
- Contract.Requires(suffix != null);
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder res = new StringBuilder();
- while (res.Length + suffix.Length < minLength)
- res.Append("0");
- res.Append(suffix);
- return res.ToString();
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Basic arithmetic operations
-
- public BigNum Abs {
- get {
- return new BigNum(BIM.Abs(this.val));
- }
- }
-
- public BigNum Neg {
- get {
- return new BigNum(-this.val);
- }
- }
-
- [Pure]
- public static BigNum operator -(BigNum x) {
- return x.Neg;
- }
-
- [Pure]
- public static BigNum operator +(BigNum x, BigNum y) {
- return new BigNum(x.val + y.val);
- }
-
- [Pure]
- public static BigNum operator -(BigNum x, BigNum y) {
- return new BigNum(x.val - y.val);
- }
-
- [Pure]
- public static BigNum operator *(BigNum x, BigNum y) {
- return new BigNum(x.val * y.val);
- }
-
- // TODO: check that this has a proper semantics (which? :-))
- [Pure]
- public static BigNum operator /(BigNum x, BigNum y) {
- return new BigNum(x.val / y.val);
- }
-
- // TODO: check that this has a proper semantics (which? :-))
- [Pure]
- public static BigNum operator %(BigNum x, BigNum y) {
- return new BigNum(x.val - ((x.val / y.val) * y.val));
- }
-
- [Pure]
- public BigNum Min(BigNum that) {
- return new BigNum(this.val <= that.val ? this.val : that.val);
- }
-
- [Pure]
- public BigNum Max(BigNum that) {
- return new BigNum(this.val >= that.val ? this.val : that.val);
- }
-
- /// <summary>
- /// Returns the greatest common divisor of this and _y.
- /// </summary>
- /// <param name="_y"></param>
- /// <returns></returns>
- public BigNum Gcd(BigNum _y) {
- Contract.Ensures(!Contract.Result<BigNum>().IsNegative);
- BigNum x = this.Abs;
- BigNum y = _y.Abs;
-
- while (true) {
- if (x < y) {
- y = y % x;
- if (y.IsZero) {
- return x;
- }
- } else {
- x = x % y;
- if (x.IsZero) {
- return y;
- }
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Some basic comparison operations
-
- public int Signum {
- get {
- return this.val.Sign;
- }
- }
-
- public bool IsPositive {
- get {
- return (this.val > BIM.Zero);
- }
- }
-
- public bool IsNegative {
- get {
- return (this.val < BIM.Zero);
- }
- }
-
- public bool IsZero {
- get {
- return this.val.IsZero;
- }
- }
-
- [Pure]
- public int CompareTo(BigNum that) {
- if (this.val == that.val)
- return 0;
- if (this.val < that.val)
- return -1;
- return 1;
- }
-
- [Pure]
- public static bool operator <(BigNum x, BigNum y) {
- return (x.val < y.val);
- }
-
- [Pure]
- public static bool operator >(BigNum x, BigNum y) {
- return (x.val > y.val);
- }
-
- [Pure]
- public static bool operator <=(BigNum x, BigNum y) {
- return (x.val <= y.val);
- }
-
- [Pure]
- public static bool operator >=(BigNum x, BigNum y) {
- return (x.val >= y.val);
- }
-
-
- private static readonly System.Numerics.BigInteger MaxInt32 =
- new BIM(Int32.MaxValue);
- private static readonly System.Numerics.BigInteger MinInt32 =
- new BIM(Int32.MinValue);
-
- public bool InInt32 {
- get {
- return (val >= MinInt32) && (val <= MaxInt32);
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.Diagnostics.Contracts;
+
+
+namespace Microsoft.Basetypes {
+ using BIM = System.Numerics.BigInteger;
+
+ /// <summary>
+ /// A thin wrapper around System.Numerics.BigInteger
+ /// (to be able to define equality, etc. properly)
+ /// </summary>
+ public struct BigNum {
+
+ // the internal representation
+ [Rep]
+ internal readonly System.Numerics.BigInteger val;
+ public static readonly BigNum ZERO = new BigNum(BIM.Zero);
+ public static readonly BigNum ONE = new BigNum(BIM.One);
+ public static readonly BigNum MINUS_ONE = new BigNum(-BIM.One);
+
+ [Pure]
+ public static BigNum FromInt(int v) {
+ return new BigNum(new BIM(v));
+ }
+
+ [Pure]
+ public static BigNum FromUInt(uint v) {
+ return new BigNum(new BIM((long)v));
+ }
+
+ [Pure]
+ public static BigNum FromLong(long v) {
+ return new BigNum(new BIM(v));
+ }
+
+ [Pure]
+ public static BigNum FromBigInt(System.Numerics.BigInteger v) {
+ return new BigNum(v);
+ }
+
+ [Pure]
+ public static BigNum FromULong(ulong v) {
+ return FromString("" + v);
+ }
+
+ [Pure]
+ public static BigNum FromString(string v) {
+ try {
+ return new BigNum(BIM.Parse(v));
+ } catch (System.ArgumentException) {
+ throw new FormatException();
+ }
+ }
+
+ public static bool TryParse(string v, out BigNum res) {
+ try {
+ res = BigNum.FromString(v);
+ return true;
+ } catch (FormatException) {
+ res = ZERO;
+ return false;
+ }
+ }
+
+ // Convert to int, without checking whether overflows occur
+ public int ToInt {
+ get {
+ return (int)val;
+ }
+ }
+
+ public BIM ToBigInteger {
+ get {
+ return val;
+ }
+ }
+
+ // Convert to int; assert that no overflows occur
+ public int ToIntSafe {
+ get {
+ Contract.Assert(this.InInt32);
+ return this.ToInt;
+ }
+ }
+
+ public Rational ToRational {
+ get {
+ return Rational.FromBignum(this);
+ }
+ }
+
+ public byte[] ToByteArray()
+ {
+ return this.val.ToByteArray();
+ }
+
+ internal BigNum(System.Numerics.BigInteger val) {
+ this.val = val;
+ }
+
+ public static bool operator ==(BigNum x, BigNum y) {
+ return (x.val == y.val);
+ }
+
+ public static bool operator !=(BigNum x, BigNum y) {
+ return !(x.val == y.val);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is BigNum))
+ return false;
+
+ BigNum other = (BigNum)obj;
+ return (this.val == other.val);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.val.GetHashCode();
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return cce.NonNull(val.ToString());
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Very limited support for format strings
+ // Note: Negative integers are linearised with a minus "-" in hexadecimal,
+ // not in 2-complement notation (in contrast to what the method
+ // int32.ToString(format) does)
+
+ [Pure]
+ public string/*!*/ ToString(string/*!*/ format) {
+ Contract.Requires(format != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ if (format.StartsWith("d") || format.StartsWith("D")) {
+ string res = this.Abs.ToString();
+ Contract.Assert(res != null);
+ return addMinus(this.Signum,
+ prefixWithZeros(extractPrecision(format), res));
+ } else if (format.StartsWith("x") || format.StartsWith("X")) {
+ string res = this.toHex(format.Substring(0, 1));
+ Contract.Assert(res != null);
+ return addMinus(this.Signum,
+ prefixWithZeros(extractPrecision(format), res));
+ } else {
+ throw new FormatException("Format " + format + " is not supported");
+ }
+ }
+
+ private static readonly System.Numerics.BigInteger BI_2_TO_24 = new BIM(0x1000000);
+
+ [Pure]
+ private string/*!*/ toHex(string/*!*/ format) {
+ Contract.Requires(format != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string res = "";
+ System.Numerics.BigInteger rem = this.Abs.val;
+
+ while (rem > BIM.Zero) {
+ res = ((int)(rem % BI_2_TO_24)).ToString(format) + res;
+ rem = rem / BI_2_TO_24;
+ }
+
+ return res;
+ }
+
+ [Pure]
+ private int extractPrecision(string/*!*/ format) {
+ Contract.Requires(format != null);
+ if (format.Length > 1)
+ // will throw a FormatException if the precision is invalid;
+ // that is ok
+ return Int32.Parse(format.Substring(1));
+ // always output at least one digit
+ return 1;
+ }
+
+ [Pure]
+ private string/*!*/ addMinus(int signum, string/*!*/ suffix) {
+ Contract.Requires(suffix != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ if (signum < 0)
+ return "-" + suffix;
+ return suffix;
+ }
+
+ [Pure]
+ private string/*!*/ prefixWithZeros(int minLength, string/*!*/ suffix) {
+ Contract.Requires(suffix != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder res = new StringBuilder();
+ while (res.Length + suffix.Length < minLength)
+ res.Append("0");
+ res.Append(suffix);
+ return res.ToString();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Basic arithmetic operations
+
+ public BigNum Abs {
+ get {
+ return new BigNum(BIM.Abs(this.val));
+ }
+ }
+
+ public BigNum Neg {
+ get {
+ return new BigNum(-this.val);
+ }
+ }
+
+ [Pure]
+ public static BigNum operator -(BigNum x) {
+ return x.Neg;
+ }
+
+ [Pure]
+ public static BigNum operator +(BigNum x, BigNum y) {
+ return new BigNum(x.val + y.val);
+ }
+
+ [Pure]
+ public static BigNum operator -(BigNum x, BigNum y) {
+ return new BigNum(x.val - y.val);
+ }
+
+ [Pure]
+ public static BigNum operator *(BigNum x, BigNum y) {
+ return new BigNum(x.val * y.val);
+ }
+
+ // TODO: check that this has a proper semantics (which? :-))
+ [Pure]
+ public static BigNum operator /(BigNum x, BigNum y) {
+ return new BigNum(x.val / y.val);
+ }
+
+ // TODO: check that this has a proper semantics (which? :-))
+ [Pure]
+ public static BigNum operator %(BigNum x, BigNum y) {
+ return new BigNum(x.val - ((x.val / y.val) * y.val));
+ }
+
+ [Pure]
+ public BigNum Min(BigNum that) {
+ return new BigNum(this.val <= that.val ? this.val : that.val);
+ }
+
+ [Pure]
+ public BigNum Max(BigNum that) {
+ return new BigNum(this.val >= that.val ? this.val : that.val);
+ }
+
+ /// <summary>
+ /// Returns the greatest common divisor of this and _y.
+ /// </summary>
+ /// <param name="_y"></param>
+ /// <returns></returns>
+ public BigNum Gcd(BigNum _y) {
+ Contract.Ensures(!Contract.Result<BigNum>().IsNegative);
+ BigNum x = this.Abs;
+ BigNum y = _y.Abs;
+
+ while (true) {
+ if (x < y) {
+ y = y % x;
+ if (y.IsZero) {
+ return x;
+ }
+ } else {
+ x = x % y;
+ if (x.IsZero) {
+ return y;
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Some basic comparison operations
+
+ public int Signum {
+ get {
+ return this.val.Sign;
+ }
+ }
+
+ public bool IsPositive {
+ get {
+ return (this.val > BIM.Zero);
+ }
+ }
+
+ public bool IsNegative {
+ get {
+ return (this.val < BIM.Zero);
+ }
+ }
+
+ public bool IsZero {
+ get {
+ return this.val.IsZero;
+ }
+ }
+
+ [Pure]
+ public int CompareTo(BigNum that) {
+ if (this.val == that.val)
+ return 0;
+ if (this.val < that.val)
+ return -1;
+ return 1;
+ }
+
+ [Pure]
+ public static bool operator <(BigNum x, BigNum y) {
+ return (x.val < y.val);
+ }
+
+ [Pure]
+ public static bool operator >(BigNum x, BigNum y) {
+ return (x.val > y.val);
+ }
+
+ [Pure]
+ public static bool operator <=(BigNum x, BigNum y) {
+ return (x.val <= y.val);
+ }
+
+ [Pure]
+ public static bool operator >=(BigNum x, BigNum y) {
+ return (x.val >= y.val);
+ }
+
+
+ private static readonly System.Numerics.BigInteger MaxInt32 =
+ new BIM(Int32.MaxValue);
+ private static readonly System.Numerics.BigInteger MinInt32 =
+ new BIM(Int32.MinValue);
+
+ public bool InInt32 {
+ get {
+ return (val >= MinInt32) && (val <= MaxInt32);
+ }
+ }
+ }
+}
diff --git a/Source/Basetypes/Rational.cs b/Source/Basetypes/Rational.cs
index cd0eddce..ef59cf4f 100644
--- a/Source/Basetypes/Rational.cs
+++ b/Source/Basetypes/Rational.cs
@@ -1,248 +1,248 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Basetypes {
- /// <summary>
- /// The representation of a rational number.
- /// </summary>
- public struct Rational {
- public static readonly Rational ZERO = Rational.FromInts(0, 1);
- public static readonly Rational ONE = Rational.FromInts(1, 1);
- public static readonly Rational MINUS_ONE = Rational.FromInts(-1, 1);
-
- private BigNum numerator, denominator;
-
- // int numerator;
- // int denominator;
-
-
- // invariant: 0 < denominator || (numerator == 0 && denominator == 0);
- // invariant: numerator != 0 ==> gcd(abs(numerator),denominator) == 1;
- // invariant: numerator == 0 ==> denominator == 1 || denominator == 0;
-
- public static Rational FromInt(int x) {
- return FromBignum(BigNum.FromInt(x));
- }
-
- public static Rational FromBignum(BigNum n)
- {
- return new Rational(n, BigNum.ONE);
- }
-
- private Rational(BigNum num, BigNum den)
- {
- Contract.Assert(den.Signum > 0);
- Contract.Assert(num == BigNum.ZERO || num.Gcd(den) == BigNum.ONE);
- numerator = num;
- denominator = den;
- }
-
- public static Rational FromBignums(BigNum num, BigNum den) {
- Contract.Assert(!den.IsZero);
- if (num == BigNum.ZERO)
- return ZERO;
- if (den.Signum < 0) {
- den = -den;
- num = -num;
- }
- if (den == BigNum.ONE)
- return new Rational(num, den);
- var gcd = num.Gcd(den);
- if (gcd == BigNum.ONE)
- return new Rational(num, den);
- return new Rational(num / gcd, den / gcd);
- }
-
- public static Rational FromInts(int num, int den) {
- return FromBignums(BigNum.FromInt(num), BigNum.FromInt(den));
- }
-
- /// <summary>
- /// Returns the absolute value of the rational.
- /// </summary>
- public Rational Abs() {
- Contract.Ensures(Contract.Result<Rational>().IsNonNegative);
- if (IsNonNegative) {
- return this;
- } else {
- return -this;
- }
- }
-
- /// <summary>
- /// Returns a rational whose numerator and denominator, resepctively, are the Gcd
- /// of the numerators and denominators of r and s. If one of r and s is 0, the absolute
- /// value of the other is returned. If both are 0, 1 is returned.
- /// </summary>
- public static Rational Gcd(Rational r, Rational s) {
- Contract.Ensures(Contract.Result<Rational>().IsPositive);
- if (r.IsZero) {
- if (s.IsZero) {
- return ONE;
- } else {
- return s.Abs();
- }
- } else if (s.IsZero) {
- return r.Abs();
- } else {
- return new Rational(r.Numerator.Gcd(s.Numerator),
- r.Denominator.Gcd(s.Denominator));
- }
- }
-
- public BigNum Numerator { get { return numerator; } }
- public BigNum Denominator { get { return denominator == BigNum.ZERO ? BigNum.ONE : denominator; } }
-
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return String.Format("{0}/{1}", Numerator, Denominator);
- }
-
-
- public static bool operator ==(Rational r, Rational s) {
- return r.Numerator == s.Numerator && r.Denominator == s.Denominator;
- }
-
- public static bool operator !=(Rational r, Rational s) {
- return !(r == s);
- }
-
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- return obj is Rational && (Rational)obj == this;
- }
-
- public override int GetHashCode() {
- return this.Numerator.GetHashCode() * 13 + this.Denominator.GetHashCode();
- }
-
- public int Signum {
- get {
- return this.Numerator.Signum;
- }
- }
-
- public bool IsZero {
- get {
- return Signum == 0;
- }
- }
-
- public bool IsNonZero {
- get {
- return Signum != 0;
- }
- }
-
- public bool IsIntegral {
- get {
- return Denominator == BigNum.ONE;
- }
- }
-
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public bool HasValue(int n) {
- return this == FromInt(n);
- }
-
- /// <summary>
- /// Returns the rational as an integer. Requires the rational to be integral.
- /// </summary>
- public int AsInteger {
- get {
- Contract.Assert(this.IsIntegral);
- return Numerator.ToIntSafe;
- }
- }
-
- public BigNum AsBigNum {
- get {
- Contract.Assert(this.IsIntegral);
- return Numerator;
- }
- }
-
- public double AsDouble {
- [Pure]
- get {
- if (this.IsZero) {
- return 0.0;
- } else {
- return (double)Numerator.ToIntSafe / (double)Denominator.ToIntSafe;
- }
- }
- }
-
- public bool IsNegative {
- [Pure]
- get {
- return Signum < 0;
- }
- }
-
- public bool IsPositive {
- [Pure]
- get {
- return 0 < Signum;
- }
- }
-
- public bool IsNonNegative {
- [Pure]
- get {
- return 0 <= Signum;
- }
- }
-
- public static Rational operator -(Rational r)
- {
- return new Rational(-r.Numerator, r.Denominator);
- }
-
- public static Rational operator /(Rational r, Rational s)
- {
- return FromBignums(r.Numerator * s.Denominator, r.Denominator * s.Numerator);
- }
-
- public static Rational operator -(Rational r, Rational s)
- {
- return r + (-s);
- }
-
- public static Rational operator +(Rational r, Rational s)
- {
- return FromBignums(r.Numerator * s.Denominator + s.Numerator * r.Denominator, r.Denominator * s.Denominator);
- }
-
- public static Rational operator *(Rational r, Rational s)
- {
- return FromBignums(r.Numerator * s.Numerator, r.Denominator * s.Denominator);
- }
-
- public static bool operator <(Rational r, Rational s)
- {
- return (r - s).Signum < 0;
- }
-
- public static bool operator <=(Rational r, Rational s)
- {
- return !(r > s);
- }
-
- public static bool operator >=(Rational r, Rational s) {
- return !(r < s);
- }
-
- public static bool operator >(Rational r, Rational s) {
- return s < r;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Basetypes {
+ /// <summary>
+ /// The representation of a rational number.
+ /// </summary>
+ public struct Rational {
+ public static readonly Rational ZERO = Rational.FromInts(0, 1);
+ public static readonly Rational ONE = Rational.FromInts(1, 1);
+ public static readonly Rational MINUS_ONE = Rational.FromInts(-1, 1);
+
+ private BigNum numerator, denominator;
+
+ // int numerator;
+ // int denominator;
+
+
+ // invariant: 0 < denominator || (numerator == 0 && denominator == 0);
+ // invariant: numerator != 0 ==> gcd(abs(numerator),denominator) == 1;
+ // invariant: numerator == 0 ==> denominator == 1 || denominator == 0;
+
+ public static Rational FromInt(int x) {
+ return FromBignum(BigNum.FromInt(x));
+ }
+
+ public static Rational FromBignum(BigNum n)
+ {
+ return new Rational(n, BigNum.ONE);
+ }
+
+ private Rational(BigNum num, BigNum den)
+ {
+ Contract.Assert(den.Signum > 0);
+ Contract.Assert(num == BigNum.ZERO || num.Gcd(den) == BigNum.ONE);
+ numerator = num;
+ denominator = den;
+ }
+
+ public static Rational FromBignums(BigNum num, BigNum den) {
+ Contract.Assert(!den.IsZero);
+ if (num == BigNum.ZERO)
+ return ZERO;
+ if (den.Signum < 0) {
+ den = -den;
+ num = -num;
+ }
+ if (den == BigNum.ONE)
+ return new Rational(num, den);
+ var gcd = num.Gcd(den);
+ if (gcd == BigNum.ONE)
+ return new Rational(num, den);
+ return new Rational(num / gcd, den / gcd);
+ }
+
+ public static Rational FromInts(int num, int den) {
+ return FromBignums(BigNum.FromInt(num), BigNum.FromInt(den));
+ }
+
+ /// <summary>
+ /// Returns the absolute value of the rational.
+ /// </summary>
+ public Rational Abs() {
+ Contract.Ensures(Contract.Result<Rational>().IsNonNegative);
+ if (IsNonNegative) {
+ return this;
+ } else {
+ return -this;
+ }
+ }
+
+ /// <summary>
+ /// Returns a rational whose numerator and denominator, resepctively, are the Gcd
+ /// of the numerators and denominators of r and s. If one of r and s is 0, the absolute
+ /// value of the other is returned. If both are 0, 1 is returned.
+ /// </summary>
+ public static Rational Gcd(Rational r, Rational s) {
+ Contract.Ensures(Contract.Result<Rational>().IsPositive);
+ if (r.IsZero) {
+ if (s.IsZero) {
+ return ONE;
+ } else {
+ return s.Abs();
+ }
+ } else if (s.IsZero) {
+ return r.Abs();
+ } else {
+ return new Rational(r.Numerator.Gcd(s.Numerator),
+ r.Denominator.Gcd(s.Denominator));
+ }
+ }
+
+ public BigNum Numerator { get { return numerator; } }
+ public BigNum Denominator { get { return denominator == BigNum.ZERO ? BigNum.ONE : denominator; } }
+
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return String.Format("{0}/{1}", Numerator, Denominator);
+ }
+
+
+ public static bool operator ==(Rational r, Rational s) {
+ return r.Numerator == s.Numerator && r.Denominator == s.Denominator;
+ }
+
+ public static bool operator !=(Rational r, Rational s) {
+ return !(r == s);
+ }
+
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ return obj is Rational && (Rational)obj == this;
+ }
+
+ public override int GetHashCode() {
+ return this.Numerator.GetHashCode() * 13 + this.Denominator.GetHashCode();
+ }
+
+ public int Signum {
+ get {
+ return this.Numerator.Signum;
+ }
+ }
+
+ public bool IsZero {
+ get {
+ return Signum == 0;
+ }
+ }
+
+ public bool IsNonZero {
+ get {
+ return Signum != 0;
+ }
+ }
+
+ public bool IsIntegral {
+ get {
+ return Denominator == BigNum.ONE;
+ }
+ }
+
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public bool HasValue(int n) {
+ return this == FromInt(n);
+ }
+
+ /// <summary>
+ /// Returns the rational as an integer. Requires the rational to be integral.
+ /// </summary>
+ public int AsInteger {
+ get {
+ Contract.Assert(this.IsIntegral);
+ return Numerator.ToIntSafe;
+ }
+ }
+
+ public BigNum AsBigNum {
+ get {
+ Contract.Assert(this.IsIntegral);
+ return Numerator;
+ }
+ }
+
+ public double AsDouble {
+ [Pure]
+ get {
+ if (this.IsZero) {
+ return 0.0;
+ } else {
+ return (double)Numerator.ToIntSafe / (double)Denominator.ToIntSafe;
+ }
+ }
+ }
+
+ public bool IsNegative {
+ [Pure]
+ get {
+ return Signum < 0;
+ }
+ }
+
+ public bool IsPositive {
+ [Pure]
+ get {
+ return 0 < Signum;
+ }
+ }
+
+ public bool IsNonNegative {
+ [Pure]
+ get {
+ return 0 <= Signum;
+ }
+ }
+
+ public static Rational operator -(Rational r)
+ {
+ return new Rational(-r.Numerator, r.Denominator);
+ }
+
+ public static Rational operator /(Rational r, Rational s)
+ {
+ return FromBignums(r.Numerator * s.Denominator, r.Denominator * s.Numerator);
+ }
+
+ public static Rational operator -(Rational r, Rational s)
+ {
+ return r + (-s);
+ }
+
+ public static Rational operator +(Rational r, Rational s)
+ {
+ return FromBignums(r.Numerator * s.Denominator + s.Numerator * r.Denominator, r.Denominator * s.Denominator);
+ }
+
+ public static Rational operator *(Rational r, Rational s)
+ {
+ return FromBignums(r.Numerator * s.Numerator, r.Denominator * s.Denominator);
+ }
+
+ public static bool operator <(Rational r, Rational s)
+ {
+ return (r - s).Signum < 0;
+ }
+
+ public static bool operator <=(Rational r, Rational s)
+ {
+ return !(r > s);
+ }
+
+ public static bool operator >=(Rational r, Rational s) {
+ return !(r < s);
+ }
+
+ public static bool operator >(Rational r, Rational s) {
+ return s < r;
+ }
+ }
+}
diff --git a/Source/Basetypes/Set.cs b/Source/Basetypes/Set.cs
index dfd65b4b..0cc1d103 100644
--- a/Source/Basetypes/Set.cs
+++ b/Source/Basetypes/Set.cs
@@ -1,286 +1,286 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
-
- /// <summary>
- /// A class representing a mathematical set.
- /// </summary>
- public class GSet<T> : ICloneable, IEnumerable, IEnumerable<T> {
- /*[Own]*/
- Dictionary<T, int> ht;
- List<T> arr; // keep elements in a well-defined order; otherwise iteration is non-deterministic
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ht != null);
- Contract.Invariant(arr != null);
- Contract.Invariant(ht.Count == arr.Count);
- }
-
-
- public GSet() {
- ht = new Dictionary<T, int>();
- arr = new List<T>();
- //:base();
- }
-
- private GSet(Dictionary<T,int>/*!*/ ht, List<T> arr) {
- Contract.Requires(ht != null);
- Contract.Requires(arr != null);
- this.ht = ht;
- this.arr = arr;
- //:base();
- }
-
- public GSet(int capacity) {
- ht = new Dictionary<T, int>(capacity);
- arr = new List<T>(capacity);
- //:base();
- }
-
-
- public readonly static GSet<T>/*!*/ Empty = new GSet<T>();
-
- public void Clear() {
- ht.Clear();
- arr.Clear();
- }
-
- /// <summary>
- /// This method idempotently adds "o" to the set.
- /// In notation:
- /// this.SetElements = this.SetElements_old \union {o};
- /// </summary>
- public void Add(T o) {
- if (!ht.ContainsKey(o)) {
- ht[o] = arr.Count;
- arr.Add(o);
- }
- }
-
- /// <summary>
- /// this.SetElements = this.SetElements_old \union s.GSet<T>Elements;
- /// </summary>
- public void AddRange(IEnumerable<T> s) {
- foreach (T o in s) {
- Add(o);
- }
- }
-
- /// <summary>
- /// this.SetElements = this.SetElements_old \setminus {o};
- /// </summary>
- public void Remove(T o) {
- int idx;
- if (ht.TryGetValue(o, out idx)) {
- var last = arr[arr.Count - 1];
- arr.RemoveAt(arr.Count - 1);
- if (idx != arr.Count) {
- arr[idx] = last;
- ht[last] = idx;
- }
- ht.Remove(o);
- }
- }
-
- /// <summary>
- /// this.SetElements = this.SetElements_old \setminus s.SetElements;
- /// </summary>
- public void RemoveRange(IEnumerable<T> s) {
- Contract.Requires(s != null);
- if (s == this) {
- ht.Clear();
- arr.Clear();
- } else {
- foreach (T o in s) {
- Remove(o);
- }
- }
- }
-
- /// <summary>
- /// Returns an arbitrary element from the set.
- /// </summary>
- public T Choose() {
- Contract.Requires((Count > 0));
- foreach(var e in this)
- return e;
- return default(T);
- }
-
- /// <summary>
- /// Picks an arbitrary element from the set, removes it, and returns it.
- /// </summary>
- public T Take() {
- Contract.Requires((Count > 0));
- Contract.Ensures(Count == Contract.OldValue(Count) - 1);
- T r = Choose();
- Remove(r);
- return r;
- }
-
- public void Intersect(GSet<T>/*!*/ s) {
- Contract.Requires(s != null);
- if (s == this) return;
- ht.Clear();
- var newArr = new List<T>();
- foreach (T key in arr) {
- if (s.ht.ContainsKey(key)) {
- ht[key] = newArr.Count;
- newArr.Add(key);
- }
- }
- arr = newArr;
- }
-
- /// <summary>
- /// The getter returns true iff "o" is in the set.
- /// The setter adds the value "o" (for "true") or removes "o" (for "false")
- /// </summary>
- public bool this[T o] {
- get {
- return ht.ContainsKey(o);
- }
- set {
- if (value) {
- Add(o);
- } else {
- Remove(o);
- }
- }
- }
-
- /// <summary>
- /// Returns true iff "o" is an element of "this".
- /// </summary>
- /// <param name="o"></param>
- /// <returns></returns>
- [Pure]
- public bool Contains(T o) {
- return this.ht.ContainsKey(o);
- }
-
- /// <summary>
- /// Returns true iff every element of "s" is an element of "this", that is, if
- /// "s" is a subset of "this".
- /// </summary>
- /// <param name="s"></param>
- /// <returns></returns>
- public bool ContainsRange(IEnumerable<T> s) {
- Contract.Requires(s != null);
- if (s != this) {
- foreach (T key in s) {
- if (!this.ht.ContainsKey(key)) {
- return false;
- }
- }
- }
- return true;
- }
-
- public object/*!*/ Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
- return new GSet<T>(new Dictionary<T,int>(ht), new List<T>(arr));
- }
-
- public virtual int Count {
- get {
- return ht.Count;
- }
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- string s = null;
- foreach (object/*!*/ key in ht.Keys) {
- Contract.Assert(key != null);
- if (s == null) {
- s = "{";
- } else {
- s += ", ";
- }
- s += key.ToString();
- }
- if (s == null) {
- return "{}";
- } else {
- return s + "}";
- }
- }
-
- //----------------------------- Static Methods ---------------------------------
-
- // Functional Intersect
- public static GSet<T>/*!*/ Intersect(GSet<T>/*!*/ a, GSet<T>/*!*/ b) {
- Contract.Requires(b != null);
- Contract.Requires(a != null);
- Contract.Ensures(Contract.Result<GSet<T>>() != null);
- //Contract.Ensures(Contract.ForAll(result, x => a[x] && b[x] ));
- GSet<T>/*!*/ res = (GSet<T>/*!*/)cce.NonNull(a.Clone());
- res.Intersect(b);
- return res;
- }
- // Functional Union
- public static GSet<T>/*!*/ Union(GSet<T>/*!*/ a, GSet<T>/*!*/ b) {
- Contract.Requires(a != null);
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<GSet<T>>() != null);
- // Contract.Ensures(Contract.ForAll(result, x => a[x] || b[x] ));
- GSet<T>/*!*/ res = (GSet<T>/*!*/)cce.NonNull(a.Clone());
- res.AddRange(b);
- return res;
- }
-
- public delegate bool SetFilter(object/*!*/ obj);
-
- public static GSet<T>/*!*/ Filter(GSet<T>/*!*/ a, Func<T,bool> filter) {
- Contract.Requires(filter != null);
- Contract.Requires(a != null);
- Contract.Ensures(Contract.Result<GSet<T>>() != null);
- GSet<T> inter = new GSet<T>();
-
- foreach (T elem in a) {
- Contract.Assert(elem != null);
- if (filter(elem)) {
- inter.Add(elem);
- }
- }
- return inter;
- }
-
- public IEnumerator<T> GetEnumerator()
- {
- return arr.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ((IEnumerable)arr).GetEnumerator();
- }
-
- public bool AddAll(IEnumerable s)
- {
- foreach (T e in s) Add(e);
- return true;
- }
- }
-
-
- public interface IWorkList : ICollection {
- bool Add(object o);
- bool AddAll(IEnumerable objs);
- bool IsEmpty();
- object Pull();
- }
-
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ /// <summary>
+ /// A class representing a mathematical set.
+ /// </summary>
+ public class GSet<T> : ICloneable, IEnumerable, IEnumerable<T> {
+ /*[Own]*/
+ Dictionary<T, int> ht;
+ List<T> arr; // keep elements in a well-defined order; otherwise iteration is non-deterministic
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ht != null);
+ Contract.Invariant(arr != null);
+ Contract.Invariant(ht.Count == arr.Count);
+ }
+
+
+ public GSet() {
+ ht = new Dictionary<T, int>();
+ arr = new List<T>();
+ //:base();
+ }
+
+ private GSet(Dictionary<T,int>/*!*/ ht, List<T> arr) {
+ Contract.Requires(ht != null);
+ Contract.Requires(arr != null);
+ this.ht = ht;
+ this.arr = arr;
+ //:base();
+ }
+
+ public GSet(int capacity) {
+ ht = new Dictionary<T, int>(capacity);
+ arr = new List<T>(capacity);
+ //:base();
+ }
+
+
+ public readonly static GSet<T>/*!*/ Empty = new GSet<T>();
+
+ public void Clear() {
+ ht.Clear();
+ arr.Clear();
+ }
+
+ /// <summary>
+ /// This method idempotently adds "o" to the set.
+ /// In notation:
+ /// this.SetElements = this.SetElements_old \union {o};
+ /// </summary>
+ public void Add(T o) {
+ if (!ht.ContainsKey(o)) {
+ ht[o] = arr.Count;
+ arr.Add(o);
+ }
+ }
+
+ /// <summary>
+ /// this.SetElements = this.SetElements_old \union s.GSet<T>Elements;
+ /// </summary>
+ public void AddRange(IEnumerable<T> s) {
+ foreach (T o in s) {
+ Add(o);
+ }
+ }
+
+ /// <summary>
+ /// this.SetElements = this.SetElements_old \setminus {o};
+ /// </summary>
+ public void Remove(T o) {
+ int idx;
+ if (ht.TryGetValue(o, out idx)) {
+ var last = arr[arr.Count - 1];
+ arr.RemoveAt(arr.Count - 1);
+ if (idx != arr.Count) {
+ arr[idx] = last;
+ ht[last] = idx;
+ }
+ ht.Remove(o);
+ }
+ }
+
+ /// <summary>
+ /// this.SetElements = this.SetElements_old \setminus s.SetElements;
+ /// </summary>
+ public void RemoveRange(IEnumerable<T> s) {
+ Contract.Requires(s != null);
+ if (s == this) {
+ ht.Clear();
+ arr.Clear();
+ } else {
+ foreach (T o in s) {
+ Remove(o);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns an arbitrary element from the set.
+ /// </summary>
+ public T Choose() {
+ Contract.Requires((Count > 0));
+ foreach(var e in this)
+ return e;
+ return default(T);
+ }
+
+ /// <summary>
+ /// Picks an arbitrary element from the set, removes it, and returns it.
+ /// </summary>
+ public T Take() {
+ Contract.Requires((Count > 0));
+ Contract.Ensures(Count == Contract.OldValue(Count) - 1);
+ T r = Choose();
+ Remove(r);
+ return r;
+ }
+
+ public void Intersect(GSet<T>/*!*/ s) {
+ Contract.Requires(s != null);
+ if (s == this) return;
+ ht.Clear();
+ var newArr = new List<T>();
+ foreach (T key in arr) {
+ if (s.ht.ContainsKey(key)) {
+ ht[key] = newArr.Count;
+ newArr.Add(key);
+ }
+ }
+ arr = newArr;
+ }
+
+ /// <summary>
+ /// The getter returns true iff "o" is in the set.
+ /// The setter adds the value "o" (for "true") or removes "o" (for "false")
+ /// </summary>
+ public bool this[T o] {
+ get {
+ return ht.ContainsKey(o);
+ }
+ set {
+ if (value) {
+ Add(o);
+ } else {
+ Remove(o);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns true iff "o" is an element of "this".
+ /// </summary>
+ /// <param name="o"></param>
+ /// <returns></returns>
+ [Pure]
+ public bool Contains(T o) {
+ return this.ht.ContainsKey(o);
+ }
+
+ /// <summary>
+ /// Returns true iff every element of "s" is an element of "this", that is, if
+ /// "s" is a subset of "this".
+ /// </summary>
+ /// <param name="s"></param>
+ /// <returns></returns>
+ public bool ContainsRange(IEnumerable<T> s) {
+ Contract.Requires(s != null);
+ if (s != this) {
+ foreach (T key in s) {
+ if (!this.ht.ContainsKey(key)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public object/*!*/ Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+ return new GSet<T>(new Dictionary<T,int>(ht), new List<T>(arr));
+ }
+
+ public virtual int Count {
+ get {
+ return ht.Count;
+ }
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string s = null;
+ foreach (object/*!*/ key in ht.Keys) {
+ Contract.Assert(key != null);
+ if (s == null) {
+ s = "{";
+ } else {
+ s += ", ";
+ }
+ s += key.ToString();
+ }
+ if (s == null) {
+ return "{}";
+ } else {
+ return s + "}";
+ }
+ }
+
+ //----------------------------- Static Methods ---------------------------------
+
+ // Functional Intersect
+ public static GSet<T>/*!*/ Intersect(GSet<T>/*!*/ a, GSet<T>/*!*/ b) {
+ Contract.Requires(b != null);
+ Contract.Requires(a != null);
+ Contract.Ensures(Contract.Result<GSet<T>>() != null);
+ //Contract.Ensures(Contract.ForAll(result, x => a[x] && b[x] ));
+ GSet<T>/*!*/ res = (GSet<T>/*!*/)cce.NonNull(a.Clone());
+ res.Intersect(b);
+ return res;
+ }
+ // Functional Union
+ public static GSet<T>/*!*/ Union(GSet<T>/*!*/ a, GSet<T>/*!*/ b) {
+ Contract.Requires(a != null);
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<GSet<T>>() != null);
+ // Contract.Ensures(Contract.ForAll(result, x => a[x] || b[x] ));
+ GSet<T>/*!*/ res = (GSet<T>/*!*/)cce.NonNull(a.Clone());
+ res.AddRange(b);
+ return res;
+ }
+
+ public delegate bool SetFilter(object/*!*/ obj);
+
+ public static GSet<T>/*!*/ Filter(GSet<T>/*!*/ a, Func<T,bool> filter) {
+ Contract.Requires(filter != null);
+ Contract.Requires(a != null);
+ Contract.Ensures(Contract.Result<GSet<T>>() != null);
+ GSet<T> inter = new GSet<T>();
+
+ foreach (T elem in a) {
+ Contract.Assert(elem != null);
+ if (filter(elem)) {
+ inter.Add(elem);
+ }
+ }
+ return inter;
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return arr.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)arr).GetEnumerator();
+ }
+
+ public bool AddAll(IEnumerable s)
+ {
+ foreach (T e in s) Add(e);
+ return true;
+ }
+ }
+
+
+ public interface IWorkList : ICollection {
+ bool Add(object o);
+ bool AddAll(IEnumerable objs);
+ bool IsEmpty();
+ object Pull();
+ }
+
+
} \ No newline at end of file
diff --git a/Source/Basetypes/cce.cs b/Source/Basetypes/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/Basetypes/cce.cs
+++ b/Source/Basetypes/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/Boogie.sln b/Source/Boogie.sln
index f16c1032..0823775c 100644
--- a/Source/Boogie.sln
+++ b/Source/Boogie.sln
@@ -1,643 +1,643 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Provers", "Provers", "{B758C1E3-824A-439F-AA2F-0BA1143E8C8D}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoogieDriver", "BoogieDriver\BoogieDriver.csproj", "{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}"
- ProjectSection(ProjectDependencies) = postProject
- {D07B8E38-E172-47F4-AD02-0373014A46D3} = {D07B8E38-E172-47F4-AD02-0373014A46D3}
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbsInt", "AbsInt\AbsInt.csproj", "{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMTLib", "Provers\SMTLib\SMTLib.csproj", "{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCGeneration", "VCGeneration\VCGeneration.csproj", "{E1F10180-C7B9-4147-B51F-FA1B701966DC}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCExpr", "VCExpr\VCExpr.csproj", "{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{B230A69C-C466-4065-B9C1-84D80E76D802}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graph", "Graph\Graph.csproj", "{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basetypes", "Basetypes\Basetypes.csproj", "{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeContractsExtender", "CodeContractsExtender\CodeContractsExtender.csproj", "{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelViewer", "ModelViewer\ModelViewer.csproj", "{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParserHelper", "ParserHelper\ParserHelper.csproj", "{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Houdini", "Houdini\Houdini.csproj", "{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Predication", "Predication\Predication.csproj", "{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doomed", "Doomed\Doomed.csproj", "{884386A3-58E9-40BB-A273-B24976775553}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecutionEngine", "ExecutionEngine\ExecutionEngine.csproj", "{EAA5EB79-D475-4601-A59B-825C191CD25F}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BVD", "BVD\BVD.csproj", "{8A05D14E-F2BF-4890-BBE0-D76B18A50797}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Concurrency", "Concurrency\Concurrency.csproj", "{D07B8E38-E172-47F4-AD02-0373014A46D3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{0C77D814-EC94-45D7-9F9B-213C425D0F15}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreTests", "UnitTests\CoreTests\CoreTests.csproj", "{961B3BCA-2067-43B2-8E43-23C4293F21B9}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtil", "UnitTests\TestUtil\TestUtil.csproj", "{59118E35-4236-495E-AF6E-0D641302ED2C}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasetypesTests", "UnitTests\BasetypesTests\BasetypesTests.csproj", "{D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Checked|.NET = Checked|.NET
- Checked|Any CPU = Checked|Any CPU
- Checked|Mixed Platforms = Checked|Mixed Platforms
- Checked|x86 = Checked|x86
- Debug|.NET = Debug|.NET
- Debug|Any CPU = Debug|Any CPU
- Debug|Mixed Platforms = Debug|Mixed Platforms
- Debug|x86 = Debug|x86
- Release|.NET = Release|.NET
- Release|Any CPU = Release|Any CPU
- Release|Mixed Platforms = Release|Mixed Platforms
- Release|x86 = Release|x86
- z3apidebug|.NET = z3apidebug|.NET
- z3apidebug|Any CPU = z3apidebug|Any CPU
- z3apidebug|Mixed Platforms = z3apidebug|Mixed Platforms
- z3apidebug|x86 = z3apidebug|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|.NET.Build.0 = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|x86.ActiveCfg = Checked|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|.NET.Build.0 = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|x86.ActiveCfg = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|.NET.ActiveCfg = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|.NET.Build.0 = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Any CPU.Build.0 = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|x86.ActiveCfg = Release|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.Build.0 = z3apidebug|x86
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|.NET.Build.0 = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|x86.ActiveCfg = Checked|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|.NET.Build.0 = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|x86.ActiveCfg = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|.NET.ActiveCfg = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|.NET.Build.0 = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Any CPU.Build.0 = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|x86.ActiveCfg = Release|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
- {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.Build.0 = z3apidebug|x86
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|.NET.Build.0 = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|x86.ActiveCfg = Checked|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|.NET.Build.0 = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|x86.ActiveCfg = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|.NET.ActiveCfg = Release|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Any CPU.Build.0 = Release|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|x86.ActiveCfg = Release|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|.NET.Build.0 = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|x86.ActiveCfg = Checked|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|.NET.Build.0 = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|x86.ActiveCfg = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|.NET.ActiveCfg = Release|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Any CPU.Build.0 = Release|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|x86.ActiveCfg = Release|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|.NET.Build.0 = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|x86.ActiveCfg = Checked|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|.NET.Build.0 = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|x86.ActiveCfg = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|.NET.ActiveCfg = Release|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Any CPU.Build.0 = Release|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|x86.ActiveCfg = Release|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|.NET.Build.0 = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|x86.ActiveCfg = Checked|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|.NET.Build.0 = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|x86.ActiveCfg = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|.NET.ActiveCfg = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|.NET.Build.0 = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Any CPU.Build.0 = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|x86.ActiveCfg = Release|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|.NET.Build.0 = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|x86.ActiveCfg = Checked|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|.NET.Build.0 = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|x86.ActiveCfg = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|.NET.ActiveCfg = Release|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Any CPU.Build.0 = Release|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|x86.ActiveCfg = Release|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|.NET.Build.0 = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|x86.ActiveCfg = Checked|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|.NET.Build.0 = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|x86.ActiveCfg = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|.NET.ActiveCfg = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|.NET.Build.0 = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Any CPU.Build.0 = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|x86.ActiveCfg = Release|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|.NET.Build.0 = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|x86.ActiveCfg = Checked|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|.NET.Build.0 = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|x86.ActiveCfg = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|.NET.ActiveCfg = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|.NET.Build.0 = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Any CPU.Build.0 = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|x86.ActiveCfg = Release|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|.NET.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|.NET.Build.0 = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Any CPU.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.Build.0 = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|x86.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|x86.Build.0 = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|.NET.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|.NET.Build.0 = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Any CPU.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Mixed Platforms.Build.0 = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|x86.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|x86.Build.0 = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|.NET.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Any CPU.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Mixed Platforms.Build.0 = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|x86.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|x86.Build.0 = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|.NET.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|Any CPU.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|Mixed Platforms.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|Mixed Platforms.Build.0 = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|x86.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|x86.Build.0 = Release|x86
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|.NET.Build.0 = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|x86.ActiveCfg = Checked|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|.NET.Build.0 = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|x86.ActiveCfg = Debug|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|.NET.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Any CPU.Build.0 = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|x86.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|x86.Build.0 = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|.NET.Build.0 = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|x86.ActiveCfg = Checked|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|.NET.Build.0 = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|x86.ActiveCfg = Debug|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|.NET.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Any CPU.Build.0 = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|x86.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|x86.Build.0 = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|.NET.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|.NET.Build.0 = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Any CPU.Build.0 = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|x86.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|.NET.Build.0 = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|x86.ActiveCfg = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|.NET.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Any CPU.Build.0 = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|x86.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|.NET.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|.NET.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Any CPU.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|x86.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|.NET.Build.0 = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|x86.ActiveCfg = Debug|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|.NET.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Any CPU.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|x86.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|.NET.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|.NET.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|Any CPU.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Checked|x86.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|.NET.Build.0 = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Debug|x86.ActiveCfg = Debug|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|.NET.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|.NET.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|Any CPU.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.Release|x86.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|.NET.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|.NET.Build.0 = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Any CPU.Build.0 = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|x86.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|.NET.Build.0 = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|x86.ActiveCfg = Debug|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|.NET.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Any CPU.Build.0 = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|x86.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|.NET.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|.NET.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Any CPU.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|x86.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|.NET.Build.0 = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|x86.ActiveCfg = Debug|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|.NET.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|.NET.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Any CPU.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|x86.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|.NET.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|.NET.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Any CPU.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|x86.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|.NET.Build.0 = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|x86.ActiveCfg = Debug|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|.NET.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|.NET.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Any CPU.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|x86.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|.NET.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Any CPU.Build.0 = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|x86.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|x86.ActiveCfg = Debug|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|.NET.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Any CPU.Build.0 = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|x86.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|.NET.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Any CPU.Build.0 = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|x86.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|x86.ActiveCfg = Debug|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|.NET.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Any CPU.Build.0 = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|x86.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|.NET.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Any CPU.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Any CPU.Build.0 = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|x86.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|x86.ActiveCfg = Debug|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|.NET.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Any CPU.Build.0 = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|x86.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {9B163AA3-36BC-4AFB-88AB-79BC9E97E401} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
- {961B3BCA-2067-43B2-8E43-23C4293F21B9} = {0C77D814-EC94-45D7-9F9B-213C425D0F15}
- {59118E35-4236-495E-AF6E-0D641302ED2C} = {0C77D814-EC94-45D7-9F9B-213C425D0F15}
- {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9} = {0C77D814-EC94-45D7-9F9B-213C425D0F15}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Provers", "Provers", "{B758C1E3-824A-439F-AA2F-0BA1143E8C8D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoogieDriver", "BoogieDriver\BoogieDriver.csproj", "{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D07B8E38-E172-47F4-AD02-0373014A46D3} = {D07B8E38-E172-47F4-AD02-0373014A46D3}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbsInt", "AbsInt\AbsInt.csproj", "{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMTLib", "Provers\SMTLib\SMTLib.csproj", "{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCGeneration", "VCGeneration\VCGeneration.csproj", "{E1F10180-C7B9-4147-B51F-FA1B701966DC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCExpr", "VCExpr\VCExpr.csproj", "{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{B230A69C-C466-4065-B9C1-84D80E76D802}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graph", "Graph\Graph.csproj", "{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Basetypes", "Basetypes\Basetypes.csproj", "{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeContractsExtender", "CodeContractsExtender\CodeContractsExtender.csproj", "{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelViewer", "ModelViewer\ModelViewer.csproj", "{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParserHelper", "ParserHelper\ParserHelper.csproj", "{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Houdini", "Houdini\Houdini.csproj", "{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Predication", "Predication\Predication.csproj", "{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doomed", "Doomed\Doomed.csproj", "{884386A3-58E9-40BB-A273-B24976775553}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecutionEngine", "ExecutionEngine\ExecutionEngine.csproj", "{EAA5EB79-D475-4601-A59B-825C191CD25F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BVD", "BVD\BVD.csproj", "{8A05D14E-F2BF-4890-BBE0-D76B18A50797}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Concurrency", "Concurrency\Concurrency.csproj", "{D07B8E38-E172-47F4-AD02-0373014A46D3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{0C77D814-EC94-45D7-9F9B-213C425D0F15}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreTests", "UnitTests\CoreTests\CoreTests.csproj", "{961B3BCA-2067-43B2-8E43-23C4293F21B9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtil", "UnitTests\TestUtil\TestUtil.csproj", "{59118E35-4236-495E-AF6E-0D641302ED2C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasetypesTests", "UnitTests\BasetypesTests\BasetypesTests.csproj", "{D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Checked|.NET = Checked|.NET
+ Checked|Any CPU = Checked|Any CPU
+ Checked|Mixed Platforms = Checked|Mixed Platforms
+ Checked|x86 = Checked|x86
+ Debug|.NET = Debug|.NET
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|.NET = Release|.NET
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ z3apidebug|.NET = z3apidebug|.NET
+ z3apidebug|Any CPU = z3apidebug|Any CPU
+ z3apidebug|Mixed Platforms = z3apidebug|Mixed Platforms
+ z3apidebug|x86 = z3apidebug|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|.NET.Build.0 = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|.NET.Build.0 = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|.NET.ActiveCfg = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|.NET.Build.0 = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.Release|x86.ActiveCfg = Release|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.Build.0 = z3apidebug|x86
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|.NET.Build.0 = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|.NET.Build.0 = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|.NET.ActiveCfg = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|.NET.Build.0 = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Release|x86.ActiveCfg = Release|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.Build.0 = z3apidebug|x86
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|.NET.Build.0 = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|.NET.Build.0 = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|.NET.ActiveCfg = Release|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Release|x86.ActiveCfg = Release|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|.NET.Build.0 = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|.NET.Build.0 = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|.NET.ActiveCfg = Release|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.Release|x86.ActiveCfg = Release|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|.NET.Build.0 = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|.NET.Build.0 = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|.NET.ActiveCfg = Release|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|.NET.Build.0 = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|.NET.Build.0 = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|.NET.ActiveCfg = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|.NET.Build.0 = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.Release|x86.ActiveCfg = Release|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|.NET.Build.0 = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|.NET.Build.0 = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|.NET.ActiveCfg = Release|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Release|x86.ActiveCfg = Release|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|.NET.Build.0 = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|.NET.Build.0 = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|.NET.ActiveCfg = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|.NET.Build.0 = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Release|x86.ActiveCfg = Release|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|.NET.Build.0 = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|.NET.Build.0 = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|.NET.ActiveCfg = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|.NET.Build.0 = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Release|x86.ActiveCfg = Release|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|.NET.ActiveCfg = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|.NET.Build.0 = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Any CPU.ActiveCfg = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.ActiveCfg = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.Build.0 = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|x86.ActiveCfg = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|x86.Build.0 = Checked|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|.NET.ActiveCfg = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|.NET.Build.0 = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|x86.ActiveCfg = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|x86.Build.0 = Debug|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|.NET.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Any CPU.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Mixed Platforms.Build.0 = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|x86.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|x86.Build.0 = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|.NET.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|Any CPU.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|Mixed Platforms.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|Mixed Platforms.Build.0 = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|x86.ActiveCfg = Release|x86
+ {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.z3apidebug|x86.Build.0 = Release|x86
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|.NET.Build.0 = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|.NET.Build.0 = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|.NET.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|x86.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|x86.Build.0 = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|.NET.ActiveCfg = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|.NET.Build.0 = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|.NET.Build.0 = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|.NET.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Release|x86.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|x86.Build.0 = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|.NET.Build.0 = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|x86.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|.NET.Build.0 = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|.NET.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Release|x86.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|.NET.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Checked|x86.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|.NET.Build.0 = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|.NET.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.Release|x86.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|.NET.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Checked|x86.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|.NET.Build.0 = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|.NET.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|.NET.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Any CPU.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.Release|x86.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {884386A3-58E9-40BB-A273-B24976775553}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|.NET.Build.0 = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Checked|x86.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|.NET.Build.0 = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|.NET.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.Release|x86.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {EAA5EB79-D475-4601-A59B-825C191CD25F}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|.NET.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Checked|x86.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|.NET.Build.0 = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|.NET.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|.NET.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.Release|x86.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {8A05D14E-F2BF-4890-BBE0-D76B18A50797}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|.NET.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Checked|x86.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|.NET.Build.0 = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|.NET.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|.NET.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.Release|x86.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {D07B8E38-E172-47F4-AD02-0373014A46D3}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Checked|x86.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|.NET.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.Release|x86.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Checked|x86.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|.NET.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.Release|x86.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {59118E35-4236-495E-AF6E-0D641302ED2C}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|.NET.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Any CPU.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Any CPU.Build.0 = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Checked|x86.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|.NET.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.Release|x86.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
+ {961B3BCA-2067-43B2-8E43-23C4293F21B9} = {0C77D814-EC94-45D7-9F9B-213C425D0F15}
+ {59118E35-4236-495E-AF6E-0D641302ED2C} = {0C77D814-EC94-45D7-9F9B-213C425D0F15}
+ {D00C3F22-1EDA-4781-8F0E-81991E9CB0D9} = {0C77D814-EC94-45D7-9F9B-213C425D0F15}
+ EndGlobalSection
+EndGlobal
diff --git a/Source/BoogieDriver/BoogieDriver.cs b/Source/BoogieDriver/BoogieDriver.cs
index fa038803..be88a745 100644
--- a/Source/BoogieDriver/BoogieDriver.cs
+++ b/Source/BoogieDriver/BoogieDriver.cs
@@ -1,106 +1,106 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// OnlyBoogie OnlyBoogie.ssc
-// - main program for taking a BPL program and verifying it
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie {
- using System;
- using System.IO;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
-
- /*
- The following assemblies are referenced because they are needed at runtime, not at compile time:
- BaseTypes
- Provers.Z3
- System.Compiler.Framework
- */
-
- public class OnlyBoogie
- {
-
- public static int Main(string[] args)
- {
- Contract.Requires(cce.NonNullElements(args));
-
- ExecutionEngine.printer = new ConsolePrinter();
-
- CommandLineOptions.Install(new CommandLineOptions());
-
- CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
- if (!CommandLineOptions.Clo.Parse(args)) {
- goto END;
- }
- if (CommandLineOptions.Clo.Files.Count == 0) {
- ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: No input files were specified.");
- goto END;
- }
- if (CommandLineOptions.Clo.XmlSink != null) {
- string errMsg = CommandLineOptions.Clo.XmlSink.Open();
- if (errMsg != null) {
- ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: " + errMsg);
- goto END;
- }
- }
- if (!CommandLineOptions.Clo.DontShowLogo) {
- Console.WriteLine(CommandLineOptions.Clo.Version);
- }
- if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always) {
- Console.WriteLine("---Command arguments");
- foreach (string arg in args) {
- Contract.Assert(arg != null);
- Console.WriteLine(arg);
- }
-
- Console.WriteLine("--------------------");
- }
-
- Helpers.ExtraTraceInformation("Becoming sentient");
-
- List<string> fileList = new List<string>();
- foreach (string file in CommandLineOptions.Clo.Files) {
- string extension = Path.GetExtension(file);
- if (extension != null) {
- extension = extension.ToLower();
- }
- if (extension == ".txt") {
- StreamReader stream = new StreamReader(file);
- string s = stream.ReadToEnd();
- fileList.AddRange(s.Split(new char[3] {' ', '\n', '\r'}, StringSplitOptions.RemoveEmptyEntries));
- }
- else {
- fileList.Add(file);
- }
- }
- foreach (string file in fileList) {
- Contract.Assert(file != null);
- string extension = Path.GetExtension(file);
- if (extension != null) {
- extension = extension.ToLower();
- }
- if (extension != ".bpl") {
- ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be BoogiePL programs (.bpl).", file,
- extension == null ? "" : extension);
- goto END;
- }
- }
- ExecutionEngine.ProcessFiles(fileList);
- return 0;
-
- END:
- if (CommandLineOptions.Clo.XmlSink != null) {
- CommandLineOptions.Clo.XmlSink.Close();
- }
- if (CommandLineOptions.Clo.Wait) {
- Console.WriteLine("Press Enter to exit.");
- Console.ReadLine();
- }
- return 1;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// OnlyBoogie OnlyBoogie.ssc
+// - main program for taking a BPL program and verifying it
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie {
+ using System;
+ using System.IO;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ /*
+ The following assemblies are referenced because they are needed at runtime, not at compile time:
+ BaseTypes
+ Provers.Z3
+ System.Compiler.Framework
+ */
+
+ public class OnlyBoogie
+ {
+
+ public static int Main(string[] args)
+ {
+ Contract.Requires(cce.NonNullElements(args));
+
+ ExecutionEngine.printer = new ConsolePrinter();
+
+ CommandLineOptions.Install(new CommandLineOptions());
+
+ CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
+ if (!CommandLineOptions.Clo.Parse(args)) {
+ goto END;
+ }
+ if (CommandLineOptions.Clo.Files.Count == 0) {
+ ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: No input files were specified.");
+ goto END;
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ string errMsg = CommandLineOptions.Clo.XmlSink.Open();
+ if (errMsg != null) {
+ ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: " + errMsg);
+ goto END;
+ }
+ }
+ if (!CommandLineOptions.Clo.DontShowLogo) {
+ Console.WriteLine(CommandLineOptions.Clo.Version);
+ }
+ if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always) {
+ Console.WriteLine("---Command arguments");
+ foreach (string arg in args) {
+ Contract.Assert(arg != null);
+ Console.WriteLine(arg);
+ }
+
+ Console.WriteLine("--------------------");
+ }
+
+ Helpers.ExtraTraceInformation("Becoming sentient");
+
+ List<string> fileList = new List<string>();
+ foreach (string file in CommandLineOptions.Clo.Files) {
+ string extension = Path.GetExtension(file);
+ if (extension != null) {
+ extension = extension.ToLower();
+ }
+ if (extension == ".txt") {
+ StreamReader stream = new StreamReader(file);
+ string s = stream.ReadToEnd();
+ fileList.AddRange(s.Split(new char[3] {' ', '\n', '\r'}, StringSplitOptions.RemoveEmptyEntries));
+ }
+ else {
+ fileList.Add(file);
+ }
+ }
+ foreach (string file in fileList) {
+ Contract.Assert(file != null);
+ string extension = Path.GetExtension(file);
+ if (extension != null) {
+ extension = extension.ToLower();
+ }
+ if (extension != ".bpl") {
+ ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be BoogiePL programs (.bpl).", file,
+ extension == null ? "" : extension);
+ goto END;
+ }
+ }
+ ExecutionEngine.ProcessFiles(fileList);
+ return 0;
+
+ END:
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.Close();
+ }
+ if (CommandLineOptions.Clo.Wait) {
+ Console.WriteLine("Press Enter to exit.");
+ Console.ReadLine();
+ }
+ return 1;
+ }
+ }
+}
diff --git a/Source/BoogieDriver/BoogieDriver.csproj b/Source/BoogieDriver/BoogieDriver.csproj
index 14d607f9..90e0be41 100644
--- a/Source/BoogieDriver/BoogieDriver.csproj
+++ b/Source/BoogieDriver/BoogieDriver.csproj
@@ -1,324 +1,324 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>BoogieDriver</RootNamespace>
- <AssemblyName>Boogie</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <TargetFrameworkProfile />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>..\Provers\Z3api\bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for BoogieDriver.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\x86\Debug\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
- <OutputPath>bin\x86\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <Optimize>true</Optimize>
- <DebugType>pdbonly</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>bin\Release\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'z3apidebug|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\x86\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>bin\z3apidebug\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for BoogieDriver.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\x86\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>x86</PlatformTarget>
- <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="BoogieDriver.cs" />
- <Compile Include="..\version.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\AbsInt\AbsInt.csproj">
- <Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
- <Name>AbsInt</Name>
- </ProjectReference>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Doomed\Doomed.csproj">
- <Project>{884386A3-58E9-40BB-A273-B24976775553}</Project>
- <Name>Doomed</Name>
- </ProjectReference>
- <ProjectReference Include="..\ExecutionEngine\ExecutionEngine.csproj">
- <Project>{EAA5EB79-D475-4601-A59B-825C191CD25F}</Project>
- <Name>ExecutionEngine</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\Houdini\Houdini.csproj">
- <Project>{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}</Project>
- <Name>Houdini</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\Predication\Predication.csproj">
- <Project>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</Project>
- <Name>Predication</Name>
- </ProjectReference>
- <ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
- <Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
- <Name>SMTLib</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>BoogieDriver</RootNamespace>
+ <AssemblyName>Boogie</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <TargetFrameworkProfile />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\Provers\Z3api\bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for BoogieDriver.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Release\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'z3apidebug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\z3apidebug\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for BoogieDriver.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BoogieDriver.cs" />
+ <Compile Include="..\version.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\AbsInt\AbsInt.csproj">
+ <Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
+ <Name>AbsInt</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Doomed\Doomed.csproj">
+ <Project>{884386A3-58E9-40BB-A273-B24976775553}</Project>
+ <Name>Doomed</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ExecutionEngine\ExecutionEngine.csproj">
+ <Project>{EAA5EB79-D475-4601-A59B-825C191CD25F}</Project>
+ <Name>ExecutionEngine</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Houdini\Houdini.csproj">
+ <Project>{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}</Project>
+ <Name>Houdini</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Predication\Predication.csproj">
+ <Project>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</Project>
+ <Name>Predication</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
+ <Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
+ <Name>SMTLib</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
</Project> \ No newline at end of file
diff --git a/Source/BoogieDriver/cce.cs b/Source/BoogieDriver/cce.cs
index 23d79815..42cabfcb 100644
--- a/Source/BoogieDriver/cce.cs
+++ b/Source/BoogieDriver/cce.cs
@@ -1,105 +1,105 @@
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-using Microsoft.Boogie;
-
- /// <summary>
- /// A class containing static methods to extend the functionality of Code Contracts
- /// </summary>
-
-public static class cce {
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && NonNullElements(collection.Keys) && NonNullElements(collection.Values);
- }
- [Pure]
- public static bool NonNullElements(VariableSeq collection) {
- return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- }
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
-
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
-}
-
-public class PeerAttribute : System.Attribute {
-}
-public class RepAttribute : System.Attribute {
-}
-public class CapturedAttribute : System.Attribute {
-}
-public class NotDelayedAttribute : System.Attribute {
-}
-public class NoDefaultContractAttribute : System.Attribute {
-}
-public class VerifyAttribute : System.Attribute {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : System.Attribute {
- }
-public class AdditiveAttribute : System.Attribute {
-}
-public class ReadsAttribute : System.Attribute {
- public enum Reads {
- Nothing,
- };
- public ReadsAttribute(object o) {
- }
-}
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+using Microsoft.Boogie;
+
+ /// <summary>
+ /// A class containing static methods to extend the functionality of Code Contracts
+ /// </summary>
+
+public static class cce {
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && NonNullElements(collection.Keys) && NonNullElements(collection.Values);
+ }
+ [Pure]
+ public static bool NonNullElements(VariableSeq collection) {
+ return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ }
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+}
+
+public class PeerAttribute : System.Attribute {
+}
+public class RepAttribute : System.Attribute {
+}
+public class CapturedAttribute : System.Attribute {
+}
+public class NotDelayedAttribute : System.Attribute {
+}
+public class NoDefaultContractAttribute : System.Attribute {
+}
+public class VerifyAttribute : System.Attribute {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : System.Attribute {
+ }
+public class AdditiveAttribute : System.Attribute {
+}
+public class ReadsAttribute : System.Attribute {
+ public enum Reads {
+ Nothing,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
diff --git a/Source/CodeContractsExtender/CodeContractsExtender.csproj b/Source/CodeContractsExtender/CodeContractsExtender.csproj
index c87ed8ab..38535dc4 100644
--- a/Source/CodeContractsExtender/CodeContractsExtender.csproj
+++ b/Source/CodeContractsExtender/CodeContractsExtender.csproj
@@ -1,202 +1,202 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>CodeContractsExtender</RootNamespace>
- <AssemblyName>CodeContractsExtender</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for CodeContractsExtender.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\CodeContractsExtender.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Xml.Linq">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data.DataSetExtensions">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="cce.cs" />
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CodeContractsExtender</RootNamespace>
+ <AssemblyName>BoogieCodeContractsExtender</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for CodeContractsExtender.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\CodeContractsExtender.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="cce.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Source/CodeContractsExtender/cce.cs b/Source/CodeContractsExtender/cce.cs
index 02b80458..0e6a0607 100644
--- a/Source/CodeContractsExtender/cce.cs
+++ b/Source/CodeContractsExtender/cce.cs
@@ -1,184 +1,184 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) where T : class {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<T>() != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) where T : class {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullDictionaryAndValues<TKey, TValue>(IDictionary<TKey, TValue> collection) where TValue : class {
- return collection != null && cce.NonNullElements(collection.Values);
- }
- //[Pure]
- //public static bool NonNullElements(List<Variable> collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) where T : class {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) where TKey : class where TValue : class {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) where T : class {
- return iEnumerator != null;
- }
- [Pure]
- public static bool NonNull<T>(HashSet<T> set) where T : class {
- return set != null && !set.Contains(null);
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
-
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) where T : class {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<T>() != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) where T : class {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullDictionaryAndValues<TKey, TValue>(IDictionary<TKey, TValue> collection) where TValue : class {
+ return collection != null && cce.NonNullElements(collection.Values);
+ }
+ //[Pure]
+ //public static bool NonNullElements(List<Variable> collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) where T : class {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) where TKey : class where TValue : class {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) where T : class {
+ return iEnumerator != null;
+ }
+ [Pure]
+ public static bool NonNull<T>(HashSet<T> set) where T : class {
+ return set != null && !set.Contains(null);
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/Concurrency/App.config b/Source/Concurrency/App.config
index 84bc4207..e95ce985 100644
--- a/Source/Concurrency/App.config
+++ b/Source/Concurrency/App.config
@@ -1,6 +1,6 @@
-<?xml version="1.0"?>
-<configuration>
- <startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
- </startup>
-</configuration>
+<?xml version="1.0"?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
+ </startup>
+</configuration>
diff --git a/Source/Concurrency/OwickiGries.cs b/Source/Concurrency/CivlRefinement.cs
index dbd1dcbd..75ff2358 100644
--- a/Source/Concurrency/OwickiGries.cs
+++ b/Source/Concurrency/CivlRefinement.cs
@@ -1,1188 +1,1230 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.Boogie;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie
-{
- public class MyDuplicator : Duplicator
- {
- MoverTypeChecker moverTypeChecker;
- public int layerNum;
- Procedure enclosingProc;
- Implementation enclosingImpl;
- public Dictionary<Procedure, Procedure> procMap; /* Original -> Duplicate */
- public Dictionary<Absy, Absy> absyMap; /* Duplicate -> Original */
- public Dictionary<Implementation, Implementation> implMap; /* Duplicate -> Original */
- public HashSet<Procedure> yieldingProcs;
- public List<Implementation> impls;
-
- public MyDuplicator(MoverTypeChecker moverTypeChecker, int layerNum)
- {
- this.moverTypeChecker = moverTypeChecker;
- this.layerNum = layerNum;
- this.enclosingProc = null;
- this.enclosingImpl = null;
- this.procMap = new Dictionary<Procedure, Procedure>();
- this.absyMap = new Dictionary<Absy, Absy>();
- this.implMap = new Dictionary<Implementation, Implementation>();
- this.yieldingProcs = new HashSet<Procedure>();
- this.impls = new List<Implementation>();
- }
-
- private void ProcessCallCmd(CallCmd originalCallCmd, CallCmd callCmd, List<Cmd> newCmds)
- {
- int enclosingProcLayerNum = moverTypeChecker.procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
- Procedure originalProc = originalCallCmd.Proc;
- if (moverTypeChecker.procToActionInfo.ContainsKey(originalProc))
- {
- AtomicActionInfo atomicActionInfo = moverTypeChecker.procToActionInfo[originalProc] as AtomicActionInfo;
- if (atomicActionInfo != null && atomicActionInfo.thisGate.Count > 0 && layerNum == enclosingProcLayerNum)
- {
- newCmds.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(dummyLocalVar) })));
- Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
- for (int i = 0; i < originalProc.InParams.Count; i++)
- {
- map[originalProc.InParams[i]] = callCmd.Ins[i];
- }
- Substitution subst = Substituter.SubstitutionFromHashtable(map);
- foreach (AssertCmd assertCmd in atomicActionInfo.thisGate)
- {
- newCmds.Add(Substituter.Apply(subst, assertCmd));
- }
- }
- }
- newCmds.Add(callCmd);
- }
-
- private void ProcessParCallCmd(ParCallCmd originalParCallCmd, ParCallCmd parCallCmd, List<Cmd> newCmds)
- {
- int maxCalleeLayerNum = 0;
- foreach (CallCmd iter in originalParCallCmd.CallCmds)
- {
- int calleeLayerNum = moverTypeChecker.procToActionInfo[iter.Proc].createdAtLayerNum;
- if (calleeLayerNum > maxCalleeLayerNum)
- maxCalleeLayerNum = calleeLayerNum;
- }
- if (layerNum > maxCalleeLayerNum)
- {
- for (int i = 0; i < parCallCmd.CallCmds.Count; i++)
- {
- ProcessCallCmd(originalParCallCmd.CallCmds[i], parCallCmd.CallCmds[i], newCmds);
- absyMap[parCallCmd.CallCmds[i]] = originalParCallCmd;
- }
- }
- else
- {
- newCmds.Add(parCallCmd);
- }
- }
-
- public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq)
- {
- List<Cmd> cmds = base.VisitCmdSeq(cmdSeq);
- List<Cmd> newCmds = new List<Cmd>();
- for (int i = 0; i < cmds.Count; i++)
- {
- Cmd originalCmd = cmdSeq[i];
- Cmd cmd = cmds[i];
-
- CallCmd originalCallCmd = originalCmd as CallCmd;
- if (originalCallCmd != null)
- {
- ProcessCallCmd(originalCallCmd, cmd as CallCmd, newCmds);
- continue;
- }
-
- ParCallCmd originalParCallCmd = originalCmd as ParCallCmd;
- if (originalParCallCmd != null)
- {
- ProcessParCallCmd(originalParCallCmd, cmd as ParCallCmd, newCmds);
- continue;
- }
-
- newCmds.Add(cmd);
- }
- return newCmds;
- }
-
- public override YieldCmd VisitYieldCmd(YieldCmd node)
- {
- YieldCmd yieldCmd = base.VisitYieldCmd(node);
- absyMap[yieldCmd] = node;
- return yieldCmd;
- }
-
- public override Block VisitBlock(Block node)
- {
- Block block = base.VisitBlock(node);
- absyMap[block] = node;
- return block;
- }
-
- public override Cmd VisitCallCmd(CallCmd node)
- {
- CallCmd callCmd = (CallCmd) base.VisitCallCmd(node);
- callCmd.Proc = VisitProcedure(callCmd.Proc);
- callCmd.callee = callCmd.Proc.Name;
- absyMap[callCmd] = node;
- return callCmd;
- }
-
- public override Cmd VisitParCallCmd(ParCallCmd node)
- {
- ParCallCmd parCallCmd = (ParCallCmd) base.VisitParCallCmd(node);
- absyMap[parCallCmd] = node;
- return parCallCmd;
- }
-
- public override Procedure VisitProcedure(Procedure node)
- {
- if (!moverTypeChecker.procToActionInfo.ContainsKey(node))
- return node;
- if (!procMap.ContainsKey(node))
- {
- enclosingProc = node;
- Procedure proc = (Procedure)node.Clone();
- proc.Name = string.Format("{0}_{1}", node.Name, layerNum);
- proc.InParams = this.VisitVariableSeq(node.InParams);
- proc.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
- proc.OutParams = this.VisitVariableSeq(node.OutParams);
-
- ActionInfo actionInfo = moverTypeChecker.procToActionInfo[node];
- if (actionInfo.createdAtLayerNum < layerNum)
- {
- proc.Requires = new List<Requires>();
- proc.Ensures = new List<Ensures>();
- Implementation impl;
- AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
- if (atomicActionInfo != null)
- {
- CodeExpr action = (CodeExpr)VisitCodeExpr(atomicActionInfo.thisAction);
- List<Cmd> cmds = new List<Cmd>();
- foreach (AssertCmd assertCmd in atomicActionInfo.thisGate)
- {
- cmds.Add(new AssumeCmd(Token.NoToken, (Expr)Visit(assertCmd.Expr)));
- }
- Block newInitBlock = new Block(Token.NoToken, "_init", cmds,
- new GotoCmd(Token.NoToken, new List<string>(new string[] { action.Blocks[0].Label }),
- new List<Block>(new Block[] { action.Blocks[0] })));
- List<Block> newBlocks = new List<Block>();
- newBlocks.Add(newInitBlock);
- newBlocks.AddRange(action.Blocks);
- impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, action.LocVars, newBlocks);
- }
- else
- {
- Block newInitBlock = new Block(Token.NoToken, "_init", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- List<Block> newBlocks = new List<Block>();
- newBlocks.Add(newInitBlock);
- impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, new List<Variable>(), newBlocks);
- }
- impl.Proc = proc;
- impl.Proc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
- impl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
- impls.Add(impl);
- }
- else
- {
- yieldingProcs.Add(proc);
- proc.Requires = this.VisitRequiresSeq(node.Requires);
- proc.Ensures = this.VisitEnsuresSeq(node.Ensures);
- }
- procMap[node] = proc;
- proc.Modifies = new List<IdentifierExpr>();
- moverTypeChecker.SharedVariables.Iter(x => proc.Modifies.Add(Expr.Ident(x)));
- }
- return procMap[node];
- }
-
- private Variable dummyLocalVar;
- public override Implementation VisitImplementation(Implementation node)
- {
- enclosingImpl = node;
- dummyLocalVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_dummy", Type.Bool));
- Implementation impl = base.VisitImplementation(node);
- implMap[impl] = node;
- impl.LocVars.Add(dummyLocalVar);
- impl.Name = impl.Proc.Name;
- return impl;
- }
-
- public override Requires VisitRequires(Requires node)
- {
- Requires requires = base.VisitRequires(node);
- if (node.Free)
- return requires;
- if (!moverTypeChecker.absyToLayerNums[node].Contains(layerNum))
- requires.Condition = Expr.True;
- return requires;
- }
-
- public override Ensures VisitEnsures(Ensures node)
- {
- Ensures ensures = base.VisitEnsures(node);
- if (node.Free)
- return ensures;
- AtomicActionInfo atomicActionInfo = moverTypeChecker.procToActionInfo[enclosingProc] as AtomicActionInfo;
- bool isAtomicSpecification = atomicActionInfo != null && atomicActionInfo.ensures == node;
- if (isAtomicSpecification || !moverTypeChecker.absyToLayerNums[node].Contains(layerNum))
- {
- ensures.Condition = Expr.True;
- ensures.Attributes = OwickiGries.RemoveMoverAttribute(ensures.Attributes);
- }
- return ensures;
- }
-
- public override Cmd VisitAssertCmd(AssertCmd node)
- {
- AssertCmd assertCmd = (AssertCmd) base.VisitAssertCmd(node);
- if (!moverTypeChecker.absyToLayerNums[node].Contains(layerNum))
- assertCmd.Expr = Expr.True;
- return assertCmd;
- }
- }
-
- public class OwickiGries
- {
- LinearTypeChecker linearTypeChecker;
- MoverTypeChecker moverTypeChecker;
- Dictionary<Absy, Absy> absyMap;
- Dictionary<Implementation, Implementation> implMap;
- HashSet<Procedure> yieldingProcs;
- int layerNum;
- List<IdentifierExpr> globalMods;
- Dictionary<string, Procedure> asyncAndParallelCallDesugarings;
- List<Procedure> yieldCheckerProcs;
- List<Implementation> yieldCheckerImpls;
- Procedure yieldProc;
-
- Variable pc;
- Variable ok;
- Expr alpha;
- Expr beta;
- HashSet<Variable> frame;
-
- public OwickiGries(LinearTypeChecker linearTypeChecker, MoverTypeChecker moverTypeChecker, MyDuplicator duplicator)
- {
- this.linearTypeChecker = linearTypeChecker;
- this.moverTypeChecker = moverTypeChecker;
- this.absyMap = duplicator.absyMap;
- this.layerNum = duplicator.layerNum;
- this.implMap = duplicator.implMap;
- this.yieldingProcs = duplicator.yieldingProcs;
- Program program = linearTypeChecker.program;
- globalMods = new List<IdentifierExpr>();
- foreach (Variable g in moverTypeChecker.SharedVariables)
- {
- globalMods.Add(Expr.Ident(g));
- }
- asyncAndParallelCallDesugarings = new Dictionary<string, Procedure>();
- yieldCheckerProcs = new List<Procedure>();
- yieldCheckerImpls = new List<Implementation>();
- yieldProc = null;
- }
-
- private IEnumerable<Variable> AvailableLinearVars(Absy absy)
- {
- return linearTypeChecker.AvailableLinearVars(absyMap[absy]);
- }
-
- private CallCmd CallToYieldProc(IToken tok, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
- {
- List<Expr> exprSeq = new List<Expr>();
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- exprSeq.Add(Expr.Ident(domainNameToLocalVar[domainName]));
- }
- foreach (IdentifierExpr ie in globalMods)
- {
- exprSeq.Add(Expr.Ident(ogOldGlobalMap[ie.Decl]));
- }
- if (yieldProc == null)
- {
- List<Variable> inputs = new List<Variable>();
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- var domain = linearTypeChecker.linearDomains[domainName];
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
- inputs.Add(f);
- }
- foreach (IdentifierExpr ie in globalMods)
- {
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
- inputs.Add(f);
- }
- yieldProc = new Procedure(Token.NoToken, string.Format("og_yield_{0}", layerNum), new List<TypeVariable>(), inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>());
- yieldProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
- }
- CallCmd yieldCallCmd = new CallCmd(Token.NoToken, yieldProc.Name, exprSeq, new List<IdentifierExpr>());
- yieldCallCmd.Proc = yieldProc;
- return yieldCallCmd;
- }
-
- private void AddCallToYieldProc(IToken tok, List<Cmd> newCmds, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
- {
- if (!CommandLineOptions.Clo.TrustNonInterference)
- {
- CallCmd yieldCallCmd = CallToYieldProc(tok, ogOldGlobalMap, domainNameToLocalVar);
- newCmds.Add(yieldCallCmd);
- }
-
- if (pc != null)
- {
- Expr aa = OldEqualityExprForGlobals(ogOldGlobalMap);
- Expr bb = OldEqualityExpr(ogOldGlobalMap);
-
- // assert pc || g_old == g || beta(i, g_old, o, g);
- Expr assertExpr = Expr.Or(Expr.Ident(pc), Expr.Or(aa, beta));
- assertExpr.Typecheck(new TypecheckingContext(null));
- AssertCmd skipOrBetaAssertCmd = new AssertCmd(tok, assertExpr);
- skipOrBetaAssertCmd.ErrorData = "Transition invariant in initial state violated";
- newCmds.Add(skipOrBetaAssertCmd);
-
- // assert pc ==> o_old == o && g_old == g;
- assertExpr = Expr.Imp(Expr.Ident(pc), bb);
- assertExpr.Typecheck(new TypecheckingContext(null));
- AssertCmd skipAssertCmd = new AssertCmd(tok, assertExpr);
- skipAssertCmd.ErrorData = "Transition invariant in final state violated"; ;
- newCmds.Add(skipAssertCmd);
-
- // pc, ok := g_old == g ==> pc, ok || beta(i, g_old, o, g);
- List<AssignLhs> pcUpdateLHS = new List<AssignLhs>(
- new AssignLhs[] {
- new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)),
- new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))
- });
- List<Expr> pcUpdateRHS = new List<Expr>(
- new Expr[] {
- Expr.Imp(aa, Expr.Ident(pc)),
- Expr.Or(Expr.Ident(ok), beta)
- });
- foreach (Expr e in pcUpdateRHS)
- {
- e.Typecheck(new TypecheckingContext(null));
- }
- newCmds.Add(new AssignCmd(Token.NoToken, pcUpdateLHS, pcUpdateRHS));
- }
- }
-
- private Dictionary<string, Expr> ComputeAvailableExprs(IEnumerable<Variable> availableLinearVars, Dictionary<string, Variable> domainNameToInputVar)
- {
- Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
- foreach (var domainName in linearTypeChecker.linearDomains.Keys)
- {
- var expr = Expr.Ident(domainNameToInputVar[domainName]);
- expr.Resolve(new ResolutionContext(null));
- expr.Typecheck(new TypecheckingContext(null));
- domainNameToExpr[domainName] = expr;
- }
- foreach (Variable v in availableLinearVars)
- {
- var domainName = linearTypeChecker.FindDomainName(v);
- if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
- var domain = linearTypeChecker.linearDomains[domainName];
- if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
- Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
- var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
- expr.Resolve(new ResolutionContext(null));
- expr.Typecheck(new TypecheckingContext(null));
- domainNameToExpr[domainName] = expr;
- }
- return domainNameToExpr;
- }
-
- private void AddUpdatesToOldGlobalVars(List<Cmd> newCmds, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<string, Expr> domainNameToExpr)
- {
- List<AssignLhs> lhss = new List<AssignLhs>();
- List<Expr> rhss = new List<Expr>();
- foreach (var domainName in linearTypeChecker.linearDomains.Keys)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName])));
- rhss.Add(domainNameToExpr[domainName]);
- }
- foreach (Variable g in ogOldGlobalMap.Keys)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g])));
- rhss.Add(Expr.Ident(g));
- }
- if (lhss.Count > 0)
- {
- newCmds.Add(new AssignCmd(Token.NoToken, lhss, rhss));
- }
- }
-
- private Expr OldEqualityExpr(Dictionary<Variable, Variable> ogOldGlobalMap)
- {
- Expr bb = Expr.True;
- foreach (Variable o in ogOldGlobalMap.Keys)
- {
- if (o is GlobalVariable && !frame.Contains(o)) continue;
- bb = Expr.And(bb, Expr.Eq(Expr.Ident(o), Expr.Ident(ogOldGlobalMap[o])));
- bb.Type = Type.Bool;
- }
- return bb;
- }
-
- private Expr OldEqualityExprForGlobals(Dictionary<Variable, Variable> ogOldGlobalMap)
- {
- Expr bb = Expr.True;
- foreach (Variable o in ogOldGlobalMap.Keys)
- {
- if (o is GlobalVariable && frame.Contains(o))
- {
- bb = Expr.And(bb, Expr.Eq(Expr.Ident(o), Expr.Ident(ogOldGlobalMap[o])));
- bb.Type = Type.Bool;
- }
- }
- return bb;
- }
-
- private void DesugarYield(YieldCmd yieldCmd, List<Cmd> cmds, List<Cmd> newCmds, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar)
- {
- AddCallToYieldProc(yieldCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
-
- if (globalMods.Count > 0)
- {
- newCmds.Add(new HavocCmd(Token.NoToken, globalMods));
- if (pc != null)
- {
- // assume pc || alpha(i, g);
- Expr assumeExpr = Expr.Or(Expr.Ident(pc), alpha);
- assumeExpr.Type = Type.Bool;
- newCmds.Add(new AssumeCmd(Token.NoToken, assumeExpr));
- }
- }
-
- Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(AvailableLinearVars(yieldCmd), domainNameToInputVar);
- AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
-
- for (int j = 0; j < cmds.Count; j++)
- {
- PredicateCmd predCmd = (PredicateCmd)cmds[j];
- newCmds.Add(new AssumeCmd(Token.NoToken, predCmd.Expr));
- }
- }
-
- public void DesugarParallelCallCmd(List<Cmd> newCmds, ParCallCmd parCallCmd)
- {
- List<string> parallelCalleeNames = new List<string>();
- List<Expr> ins = new List<Expr>();
- List<IdentifierExpr> outs = new List<IdentifierExpr>();
- string procName = "og";
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- procName = procName + "_" + callCmd.Proc.Name;
- ins.AddRange(callCmd.Ins);
- outs.AddRange(callCmd.Outs);
- }
- Procedure proc;
- if (asyncAndParallelCallDesugarings.ContainsKey(procName))
- {
- proc = asyncAndParallelCallDesugarings[procName];
- }
- else
- {
- List<Variable> inParams = new List<Variable>();
- List<Variable> outParams = new List<Variable>();
- List<Requires> requiresSeq = new List<Requires>();
- List<Ensures> ensuresSeq = new List<Ensures>();
- int count = 0;
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
- foreach (Variable x in callCmd.Proc.InParams)
- {
- Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_{0}_{1}", count, x.Name), x.TypedIdent.Type), true);
- inParams.Add(y);
- map[x] = Expr.Ident(y);
- }
- foreach (Variable x in callCmd.Proc.OutParams)
- {
- Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_{0}_{1}", count, x.Name), x.TypedIdent.Type), false);
- outParams.Add(y);
- map[x] = Expr.Ident(y);
- }
- Contract.Assume(callCmd.Proc.TypeParameters.Count == 0);
- Substitution subst = Substituter.SubstitutionFromHashtable(map);
- foreach (Requires req in callCmd.Proc.Requires)
- {
- requiresSeq.Add(new Requires(req.tok, req.Free, Substituter.Apply(subst, req.Condition), null, req.Attributes));
- }
- foreach (Ensures ens in callCmd.Proc.Ensures)
- {
- ensuresSeq.Add(new Ensures(ens.tok, ens.Free, Substituter.Apply(subst, ens.Condition), null, ens.Attributes));
- }
- count++;
- }
- proc = new Procedure(Token.NoToken, procName, new List<TypeVariable>(), inParams, outParams, requiresSeq, globalMods, ensuresSeq);
- asyncAndParallelCallDesugarings[procName] = proc;
- }
- CallCmd dummyCallCmd = new CallCmd(parCallCmd.tok, proc.Name, ins, outs, parCallCmd.Attributes);
- dummyCallCmd.Proc = proc;
- newCmds.Add(dummyCallCmd);
- }
-
- private void CreateYieldCheckerImpl(Implementation impl, List<List<Cmd>> yields)
- {
- if (yields.Count == 0) return;
-
- Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
- foreach (Variable local in impl.LocVars)
- {
- var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, local.Name, local.TypedIdent.Type));
- map[local] = Expr.Ident(copy);
- }
-
- Program program = linearTypeChecker.program;
- List<Variable> locals = new List<Variable>();
- List<Variable> inputs = new List<Variable>();
- foreach (IdentifierExpr ie in map.Values)
- {
- locals.Add(ie.Decl);
- }
- for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++)
- {
- Variable inParam = impl.InParams[i];
- Variable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type));
- locals.Add(copy);
- map[impl.InParams[i]] = Expr.Ident(copy);
- }
- {
- int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count;
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- Variable inParam = impl.InParams[i];
- Variable copy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type), true);
- inputs.Add(copy);
- map[impl.InParams[i]] = Expr.Ident(copy);
- i++;
- }
- }
- for (int i = 0; i < impl.OutParams.Count; i++)
- {
- Variable outParam = impl.OutParams[i];
- var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, outParam.Name, outParam.TypedIdent.Type));
- locals.Add(copy);
- map[impl.OutParams[i]] = Expr.Ident(copy);
- }
- Dictionary<Variable, Expr> ogOldLocalMap = new Dictionary<Variable, Expr>();
- Dictionary<Variable, Expr> assumeMap = new Dictionary<Variable, Expr>(map);
- foreach (IdentifierExpr ie in globalMods)
- {
- Variable g = ie.Decl;
- var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_local_old_{0}", g.Name), g.TypedIdent.Type));
- locals.Add(copy);
- ogOldLocalMap[g] = Expr.Ident(copy);
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type), true);
- inputs.Add(f);
- assumeMap[g] = Expr.Ident(f);
- }
-
- Substitution assumeSubst = Substituter.SubstitutionFromHashtable(assumeMap);
- Substitution oldSubst = Substituter.SubstitutionFromHashtable(ogOldLocalMap);
- Substitution subst = Substituter.SubstitutionFromHashtable(map);
- List<Block> yieldCheckerBlocks = new List<Block>();
- List<String> labels = new List<String>();
- List<Block> labelTargets = new List<Block>();
- Block yieldCheckerBlock = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- labels.Add(yieldCheckerBlock.Label);
- labelTargets.Add(yieldCheckerBlock);
- yieldCheckerBlocks.Add(yieldCheckerBlock);
- int yieldCount = 0;
- foreach (List<Cmd> cs in yields)
- {
- List<Cmd> newCmds = new List<Cmd>();
- foreach (Cmd cmd in cs)
- {
- PredicateCmd predCmd = (PredicateCmd)cmd;
- newCmds.Add(new AssumeCmd(Token.NoToken, Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr)));
- }
- foreach (Cmd cmd in cs)
- {
- PredicateCmd predCmd = (PredicateCmd)cmd;
- var newExpr = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr);
- if (predCmd is AssertCmd)
- {
- AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes);
- assertCmd.ErrorData = "Non-interference check failed";
- newCmds.Add(assertCmd);
- }
- else
- {
- newCmds.Add(new AssumeCmd(Token.NoToken, newExpr));
- }
- }
- newCmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
- yieldCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken));
- labels.Add(yieldCheckerBlock.Label);
- labelTargets.Add(yieldCheckerBlock);
- yieldCheckerBlocks.Add(yieldCheckerBlock);
- }
- yieldCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets)));
-
- // Create the yield checker procedure
- var yieldCheckerName = string.Format("{0}_YieldChecker_{1}", "Impl", impl.Name);
- var yieldCheckerProc = new Procedure(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>());
- yieldCheckerProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
- yieldCheckerProcs.Add(yieldCheckerProc);
-
- // Create the yield checker implementation
- var yieldCheckerImpl = new Implementation(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), locals, yieldCheckerBlocks);
- yieldCheckerImpl.Proc = yieldCheckerProc;
- yieldCheckerImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
- yieldCheckerImpls.Add(yieldCheckerImpl);
- }
-
- private bool IsYieldingHeader(Graph<Block> graph, Block header)
- {
- foreach (Block backEdgeNode in graph.BackEdgeNodes(header))
- {
- foreach (Block x in graph.NaturalLoops(header, backEdgeNode))
- {
- foreach (Cmd cmd in x.Cmds)
- {
- if (cmd is YieldCmd)
- return true;
- if (cmd is ParCallCmd)
- return true;
- CallCmd callCmd = cmd as CallCmd;
- if (callCmd == null) continue;
- if (yieldingProcs.Contains(callCmd.Proc))
- return true;
- }
- }
- }
- return false;
- }
-
- private Graph<Block> ComputeYieldingLoopHeaders(Implementation impl, out HashSet<Block> yieldingHeaders)
- {
- Graph<Block> graph;
- impl.PruneUnreachableBlocks();
- impl.ComputePredecessorsForBlocks();
- graph = Program.GraphFromImpl(impl);
- graph.ComputeLoops();
- if (!graph.Reducible)
- {
- throw new Exception("Irreducible flow graphs are unsupported.");
- }
- yieldingHeaders = new HashSet<Block>();
- IEnumerable<Block> sortedHeaders = graph.SortHeadersByDominance();
- foreach (Block header in sortedHeaders)
- {
- if (yieldingHeaders.Any(x => graph.DominatorMap.DominatedBy(x, header)))
- {
- yieldingHeaders.Add(header);
- }
- else if (IsYieldingHeader(graph, header))
- {
- yieldingHeaders.Add(header);
- }
- else
- {
- continue;
- }
- }
- return graph;
- }
-
- private void SetupRefinementCheck(Implementation impl,
- out List<Variable> newLocalVars,
- out Dictionary<string, Variable> domainNameToInputVar, out Dictionary<string, Variable> domainNameToLocalVar, out Dictionary<Variable, Variable> ogOldGlobalMap)
- {
- pc = null;
- ok = null;
- alpha = null;
- beta = null;
- frame = null;
-
- newLocalVars = new List<Variable>();
- Program program = linearTypeChecker.program;
- ogOldGlobalMap = new Dictionary<Variable, Variable>();
- foreach (IdentifierExpr ie in globalMods)
- {
- Variable g = ie.Decl;
- LocalVariable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type));
- ogOldGlobalMap[g] = l;
- newLocalVars.Add(l);
- }
-
- Procedure originalProc = implMap[impl].Proc;
- ActionInfo actionInfo = moverTypeChecker.procToActionInfo[originalProc];
- if (actionInfo.createdAtLayerNum == this.layerNum)
- {
- pc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_pc", Type.Bool));
- newLocalVars.Add(pc);
- ok = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_ok", Type.Bool));
- newLocalVars.Add(ok);
- Dictionary<Variable, Expr> alwaysMap = new Dictionary<Variable, Expr>();
- for (int i = 0; i < originalProc.InParams.Count; i++)
- {
- alwaysMap[originalProc.InParams[i]] = Expr.Ident(impl.InParams[i]);
- }
- for (int i = 0; i < originalProc.OutParams.Count; i++)
- {
- alwaysMap[originalProc.OutParams[i]] = Expr.Ident(impl.OutParams[i]);
- }
- Substitution always = Substituter.SubstitutionFromHashtable(alwaysMap);
- Dictionary<Variable, Expr> foroldMap = new Dictionary<Variable, Expr>();
- foreach (IdentifierExpr ie in globalMods)
- {
- foroldMap[ie.Decl] = Expr.Ident(ogOldGlobalMap[ie.Decl]);
- }
- Substitution forold = Substituter.SubstitutionFromHashtable(foroldMap);
- frame = new HashSet<Variable>(moverTypeChecker.SharedVariables);
- HashSet<Variable> introducedVars = new HashSet<Variable>();
- foreach (Variable v in moverTypeChecker.SharedVariables)
- {
- if (moverTypeChecker.globalVarToSharedVarInfo[v].hideLayerNum <= actionInfo.createdAtLayerNum ||
- moverTypeChecker.globalVarToSharedVarInfo[v].introLayerNum > actionInfo.createdAtLayerNum)
- {
- frame.Remove(v);
- }
- if (moverTypeChecker.globalVarToSharedVarInfo[v].introLayerNum == actionInfo.createdAtLayerNum)
- {
- introducedVars.Add(v);
- }
- }
- AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
- if (atomicActionInfo == null)
- {
- beta = Expr.True;
- foreach (var v in frame)
- {
- beta = Expr.And(beta, Expr.Eq(Expr.Ident(v), foroldMap[v]));
- }
- alpha = Expr.True;
- }
- else
- {
- Expr betaExpr = (new MoverCheck.TransitionRelationComputation(moverTypeChecker.program, atomicActionInfo, frame, introducedVars)).TransitionRelationCompute();
- beta = Substituter.ApplyReplacingOldExprs(always, forold, betaExpr);
- Expr alphaExpr = Expr.True;
- foreach (AssertCmd assertCmd in atomicActionInfo.thisGate)
- {
- alphaExpr = Expr.And(alphaExpr, assertCmd.Expr);
- alphaExpr.Type = Type.Bool;
- }
- alpha = Substituter.Apply(always, alphaExpr);
- }
- foreach (Variable f in impl.OutParams)
- {
- LocalVariable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_old_{0}", f.Name), f.TypedIdent.Type));
- newLocalVars.Add(copy);
- ogOldGlobalMap[f] = copy;
- }
- }
-
- domainNameToInputVar = new Dictionary<string, Variable>();
- domainNameToLocalVar = new Dictionary<string, Variable>();
- {
- int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count;
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- Variable inParam = impl.InParams[i];
- domainNameToInputVar[domainName] = inParam;
- Variable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name + "_local", inParam.TypedIdent.Type));
- domainNameToLocalVar[domainName] = l;
- newLocalVars.Add(l);
- i++;
- }
- }
- }
-
- private void TransformImpl(Implementation impl)
- {
- HashSet<Block> yieldingHeaders;
- Graph<Block> graph = ComputeYieldingLoopHeaders(impl, out yieldingHeaders);
-
- List<Variable> newLocalVars;
- Dictionary<string, Variable> domainNameToInputVar, domainNameToLocalVar;
- Dictionary<Variable, Variable> ogOldGlobalMap;
- SetupRefinementCheck(impl, out newLocalVars, out domainNameToInputVar, out domainNameToLocalVar, out ogOldGlobalMap);
-
- List<List<Cmd>> yields = CollectAndDesugarYields(impl, domainNameToInputVar, domainNameToLocalVar, ogOldGlobalMap);
-
- List<Variable> oldPcs, oldOks;
- ProcessLoopHeaders(impl, graph, yieldingHeaders, domainNameToInputVar, domainNameToLocalVar, ogOldGlobalMap, out oldPcs, out oldOks);
-
- AddInitialBlock(impl, oldPcs, oldOks, domainNameToInputVar, domainNameToLocalVar, ogOldGlobalMap);
-
- CreateYieldCheckerImpl(impl, yields);
-
- impl.LocVars.AddRange(newLocalVars);
- impl.LocVars.AddRange(oldPcs);
- impl.LocVars.AddRange(oldOks);
-
- UnifyCallsToYieldProc(impl, ogOldGlobalMap, domainNameToLocalVar);
- }
-
- private void UnifyCallsToYieldProc(Implementation impl, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
- {
- CallCmd yieldCallCmd = CallToYieldProc(Token.NoToken, ogOldGlobalMap, domainNameToLocalVar);
- Block yieldCheckBlock = new Block(Token.NoToken, "CallToYieldProc", new List<Cmd>(new Cmd[] { yieldCallCmd, new AssumeCmd(Token.NoToken, Expr.False) }), new ReturnCmd(Token.NoToken));
- List<Block> newBlocks = new List<Block>();
- foreach (Block b in impl.Blocks)
- {
- TransferCmd transferCmd = b.TransferCmd;
- List<Cmd> newCmds = new List<Cmd>();
- for (int i = b.Cmds.Count-1; i >= 0; i--)
- {
- CallCmd callCmd = b.Cmds[i] as CallCmd;
- if (callCmd == null || callCmd.Proc != yieldProc)
- {
- newCmds.Insert(0, b.Cmds[i]);
- }
- else
- {
- Block newBlock = new Block(Token.NoToken, b.Label + i, newCmds, transferCmd);
- newCmds = new List<Cmd>();
- transferCmd = new GotoCmd(Token.NoToken, new List<string>(new string[] { newBlock.Label, yieldCheckBlock.Label }),
- new List<Block>(new Block[] { newBlock, yieldCheckBlock }));
- newBlocks.Add(newBlock);
- }
- }
- b.Cmds = newCmds;
- b.TransferCmd = transferCmd;
- }
- impl.Blocks.AddRange(newBlocks);
- impl.Blocks.Add(yieldCheckBlock);
- }
-
- private List<List<Cmd>> CollectAndDesugarYields(Implementation impl,
- Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap)
- {
- // Collect the yield predicates and desugar yields
- List<List<Cmd>> yields = new List<List<Cmd>>();
- List<Cmd> cmds = new List<Cmd>();
- foreach (Block b in impl.Blocks)
- {
- YieldCmd yieldCmd = null;
- List<Cmd> newCmds = new List<Cmd>();
- for (int i = 0; i < b.Cmds.Count; i++)
- {
- Cmd cmd = b.Cmds[i];
- if (cmd is YieldCmd)
- {
- yieldCmd = (YieldCmd)cmd;
- continue;
- }
- if (yieldCmd != null)
- {
- PredicateCmd pcmd = cmd as PredicateCmd;
- if (pcmd == null)
- {
- DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar);
- if (cmds.Count > 0)
- {
- yields.Add(cmds);
- cmds = new List<Cmd>();
- }
- yieldCmd = null;
- }
- else
- {
- cmds.Add(pcmd);
- }
- }
-
- if (cmd is CallCmd)
- {
- CallCmd callCmd = cmd as CallCmd;
- if (yieldingProcs.Contains(callCmd.Proc))
- {
- AddCallToYieldProc(callCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
- }
- if (callCmd.IsAsync)
- {
- if (!asyncAndParallelCallDesugarings.ContainsKey(callCmd.Proc.Name))
- {
- asyncAndParallelCallDesugarings[callCmd.Proc.Name] = new Procedure(Token.NoToken, string.Format("DummyAsyncTarget_{0}", callCmd.Proc.Name), callCmd.Proc.TypeParameters, callCmd.Proc.InParams, callCmd.Proc.OutParams, callCmd.Proc.Requires, new List<IdentifierExpr>(), new List<Ensures>());
- }
- var dummyAsyncTargetProc = asyncAndParallelCallDesugarings[callCmd.Proc.Name];
- CallCmd dummyCallCmd = new CallCmd(callCmd.tok, dummyAsyncTargetProc.Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes);
- dummyCallCmd.Proc = dummyAsyncTargetProc;
- newCmds.Add(dummyCallCmd);
- }
- else
- {
- newCmds.Add(callCmd);
- }
- if (yieldingProcs.Contains(callCmd.Proc))
- {
- HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(callCmd));
- linearTypeChecker.AddAvailableVars(callCmd, availableLinearVars);
- Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar);
- AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
- }
- }
- else if (cmd is ParCallCmd)
- {
- ParCallCmd parCallCmd = cmd as ParCallCmd;
- AddCallToYieldProc(parCallCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
- DesugarParallelCallCmd(newCmds, parCallCmd);
- HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(parCallCmd));
- linearTypeChecker.AddAvailableVars(parCallCmd, availableLinearVars);
- Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar);
- AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
- }
- else
- {
- newCmds.Add(cmd);
- }
- }
- if (yieldCmd != null)
- {
- DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar);
- if (cmds.Count > 0)
- {
- yields.Add(cmds);
- cmds = new List<Cmd>();
- }
- }
- if (b.TransferCmd is ReturnCmd)
- {
- AddCallToYieldProc(b.TransferCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
- if (pc != null)
- {
- AssertCmd assertCmd = new AssertCmd(b.TransferCmd.tok, Expr.Ident(ok));
- assertCmd.ErrorData = "Failed to execute atomic action before procedure return";
- newCmds.Add(assertCmd);
- }
- }
- b.Cmds = newCmds;
- }
- return yields;
- }
-
- private void ProcessLoopHeaders(Implementation impl, Graph<Block> graph, HashSet<Block> yieldingHeaders,
- Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap,
- out List<Variable> oldPcs, out List<Variable> oldOks)
- {
- oldPcs = new List<Variable>();
- oldOks = new List<Variable>();
- foreach (Block header in yieldingHeaders)
- {
- LocalVariable oldPc = null;
- LocalVariable oldOk = null;
- if (pc != null)
- {
- oldPc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}", pc.Name, header.Label), Type.Bool));
- oldPcs.Add(oldPc);
- oldOk = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}", ok.Name, header.Label), Type.Bool));
- oldOks.Add(oldOk);
- }
- Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(AvailableLinearVars(header), domainNameToInputVar);
- foreach (Block pred in header.Predecessors)
- {
- AddCallToYieldProc(header.tok, pred.Cmds, ogOldGlobalMap, domainNameToLocalVar);
- if (pc != null && !graph.BackEdgeNodes(header).Contains(pred))
- {
- pred.Cmds.Add(new AssignCmd(Token.NoToken, new List<AssignLhs>(
- new AssignLhs[] { new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc)), new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk)) }),
- new List<Expr>(new Expr[] { Expr.Ident(pc), Expr.Ident(ok) })));
- }
- AddUpdatesToOldGlobalVars(pred.Cmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
- }
- List<Cmd> newCmds = new List<Cmd>();
- if (pc != null)
- {
- AssertCmd assertCmd;
- assertCmd = new AssertCmd(header.tok, Expr.Eq(Expr.Ident(oldPc), Expr.Ident(pc)));
- assertCmd.ErrorData = "Specification state must not change for transitions ending in loop headers";
- newCmds.Add(assertCmd);
- assertCmd = new AssertCmd(header.tok, Expr.Imp(Expr.Ident(oldOk), Expr.Ident(ok)));
- assertCmd.ErrorData = "Specification state must not change for transitions ending in loop headers";
- newCmds.Add(assertCmd);
- }
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(domainNameToLocalVar[domainName]), domainNameToExpr[domainName])));
- }
- foreach (Variable v in ogOldGlobalMap.Keys)
- {
- newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(v), Expr.Ident(ogOldGlobalMap[v]))));
- }
- newCmds.AddRange(header.Cmds);
- header.Cmds = newCmds;
- }
- }
-
- private void AddInitialBlock(Implementation impl, List<Variable> oldPcs, List<Variable> oldOks,
- Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap)
- {
- // Add initial block
- List<AssignLhs> lhss = new List<AssignLhs>();
- List<Expr> rhss = new List<Expr>();
- if (pc != null)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)));
- rhss.Add(Expr.False);
- foreach (Variable oldPc in oldPcs)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc)));
- rhss.Add(Expr.False);
- }
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok)));
- rhss.Add(Expr.False);
- foreach (Variable oldOk in oldOks)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk)));
- rhss.Add(Expr.False);
- }
- }
- Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
- foreach (var domainName in linearTypeChecker.linearDomains.Keys)
- {
- domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]);
- }
- for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++)
- {
- Variable v = impl.InParams[i];
- var domainName = linearTypeChecker.FindDomainName(v);
- if (domainName == null) continue;
- if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
- var domain = linearTypeChecker.linearDomains[domainName];
- if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
- Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
- domainNameToExpr[domainName] = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
- }
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName])));
- rhss.Add(domainNameToExpr[domainName]);
- }
- foreach (Variable g in ogOldGlobalMap.Keys)
- {
- lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g])));
- rhss.Add(Expr.Ident(g));
- }
- if (lhss.Count > 0)
- {
- Block initBlock = new Block(Token.NoToken, "og_init", new List<Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }, new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] }));
- impl.Blocks.Insert(0, initBlock);
- }
- }
-
- private void AddYieldProcAndImpl(List<Declaration> decls)
- {
- if (yieldProc == null) return;
-
- Program program = linearTypeChecker.program;
- List<Variable> inputs = new List<Variable>();
- foreach (string domainName in linearTypeChecker.linearDomains.Keys)
- {
- var domain = linearTypeChecker.linearDomains[domainName];
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
- inputs.Add(f);
- }
- foreach (IdentifierExpr ie in globalMods)
- {
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
- inputs.Add(f);
- }
- List<Block> blocks = new List<Block>();
- TransferCmd transferCmd = new ReturnCmd(Token.NoToken);
- if (yieldCheckerProcs.Count > 0)
- {
- List<Block> blockTargets = new List<Block>();
- List<String> labelTargets = new List<String>();
- int labelCount = 0;
- foreach (Procedure proc in yieldCheckerProcs)
- {
- List<Expr> exprSeq = new List<Expr>();
- foreach (Variable v in inputs)
- {
- exprSeq.Add(Expr.Ident(v));
- }
- CallCmd callCmd = new CallCmd(Token.NoToken, proc.Name, exprSeq, new List<IdentifierExpr>());
- callCmd.Proc = proc;
- string label = string.Format("L_{0}", labelCount++);
- Block block = new Block(Token.NoToken, label, new List<Cmd> { callCmd }, new ReturnCmd(Token.NoToken));
- labelTargets.Add(label);
- blockTargets.Add(block);
- blocks.Add(block);
- }
- transferCmd = new GotoCmd(Token.NoToken, labelTargets, blockTargets);
- }
- blocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), transferCmd));
-
- var yieldImpl = new Implementation(Token.NoToken, yieldProc.Name, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks);
- yieldImpl.Proc = yieldProc;
- yieldImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
- decls.Add(yieldProc);
- decls.Add(yieldImpl);
- }
-
- public static QKeyValue RemoveYieldsAttribute(QKeyValue iter)
- {
- if (iter == null) return null;
- iter.Next = RemoveYieldsAttribute(iter.Next);
- return (iter.Key == "yields") ? iter.Next : iter;
- }
-
- public static QKeyValue RemoveMoverAttribute(QKeyValue iter)
- {
- if (iter == null) return null;
- iter.Next = RemoveMoverAttribute(iter.Next);
- if (iter.Key == "atomic" || iter.Key == "right" || iter.Key == "left" || iter.Key == "both")
- return iter.Next;
- else
- return iter;
- }
-
- private List<Declaration> Collect()
- {
- List<Declaration> decls = new List<Declaration>();
- foreach (Procedure proc in yieldCheckerProcs)
- {
- decls.Add(proc);
- }
- foreach (Implementation impl in yieldCheckerImpls)
- {
- decls.Add(impl);
- }
- foreach (Procedure proc in asyncAndParallelCallDesugarings.Values)
- {
- decls.Add(proc);
- }
- AddYieldProcAndImpl(decls);
- return decls;
- }
-
- public static void AddCheckers(LinearTypeChecker linearTypeChecker, MoverTypeChecker moverTypeChecker, List<Declaration> decls)
- {
- Program program = linearTypeChecker.program;
- foreach (int layerNum in moverTypeChecker.AllCreatedLayerNums.Except(new int[] { moverTypeChecker.leastUnimplementedLayerNum }))
- {
- if (CommandLineOptions.Clo.TrustLayersDownto <= layerNum || layerNum <= CommandLineOptions.Clo.TrustLayersUpto) continue;
-
- MyDuplicator duplicator = new MyDuplicator(moverTypeChecker, layerNum);
- foreach (var proc in program.Procedures)
- {
- if (!moverTypeChecker.procToActionInfo.ContainsKey(proc)) continue;
- Procedure duplicateProc = duplicator.VisitProcedure(proc);
- decls.Add(duplicateProc);
- }
- decls.AddRange(duplicator.impls);
- OwickiGries ogTransform = new OwickiGries(linearTypeChecker, moverTypeChecker, duplicator);
- foreach (var impl in program.Implementations)
- {
- if (!moverTypeChecker.procToActionInfo.ContainsKey(impl.Proc) || moverTypeChecker.procToActionInfo[impl.Proc].createdAtLayerNum < layerNum)
- continue;
- Implementation duplicateImpl = duplicator.VisitImplementation(impl);
- ogTransform.TransformImpl(duplicateImpl);
- decls.Add(duplicateImpl);
- }
- decls.AddRange(ogTransform.Collect());
- }
- }
- }
-}
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Boogie;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie
+{
+ public class MyDuplicator : Duplicator
+ {
+ CivlTypeChecker civlTypeChecker;
+ public int layerNum;
+ Procedure enclosingProc;
+ Implementation enclosingImpl;
+ public Dictionary<Procedure, Procedure> procMap; /* Original -> Duplicate */
+ public Dictionary<Absy, Absy> absyMap; /* Duplicate -> Original */
+ public Dictionary<Implementation, Implementation> implMap; /* Duplicate -> Original */
+ public HashSet<Procedure> yieldingProcs;
+ public List<Implementation> impls;
+
+ public MyDuplicator(CivlTypeChecker civlTypeChecker, int layerNum)
+ {
+ this.civlTypeChecker = civlTypeChecker;
+ this.layerNum = layerNum;
+ this.enclosingProc = null;
+ this.enclosingImpl = null;
+ this.procMap = new Dictionary<Procedure, Procedure>();
+ this.absyMap = new Dictionary<Absy, Absy>();
+ this.implMap = new Dictionary<Implementation, Implementation>();
+ this.yieldingProcs = new HashSet<Procedure>();
+ this.impls = new List<Implementation>();
+ }
+
+ private void ProcessCallCmd(CallCmd originalCallCmd, CallCmd callCmd, List<Cmd> newCmds)
+ {
+ int enclosingProcLayerNum = civlTypeChecker.procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
+ Procedure originalProc = originalCallCmd.Proc;
+
+ if (civlTypeChecker.procToAtomicProcedureInfo.ContainsKey(originalProc))
+ {
+ if (civlTypeChecker.CallExists(originalCallCmd, enclosingProcLayerNum, layerNum))
+ {
+ newCmds.Add(callCmd);
+ }
+ }
+ else if (civlTypeChecker.procToActionInfo.ContainsKey(originalProc))
+ {
+ AtomicActionInfo atomicActionInfo = civlTypeChecker.procToActionInfo[originalProc] as AtomicActionInfo;
+ if (atomicActionInfo != null && atomicActionInfo.gate.Count > 0 && layerNum == enclosingProcLayerNum)
+ {
+ newCmds.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(dummyLocalVar) })));
+ Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
+ for (int i = 0; i < originalProc.InParams.Count; i++)
+ {
+ map[originalProc.InParams[i]] = callCmd.Ins[i];
+ }
+ Substitution subst = Substituter.SubstitutionFromHashtable(map);
+ foreach (AssertCmd assertCmd in atomicActionInfo.gate)
+ {
+ newCmds.Add(Substituter.Apply(subst, assertCmd));
+ }
+ }
+ newCmds.Add(callCmd);
+ }
+ else
+ {
+ Debug.Assert(false);
+ }
+ }
+
+ private void ProcessParCallCmd(ParCallCmd originalParCallCmd, ParCallCmd parCallCmd, List<Cmd> newCmds)
+ {
+ int maxCalleeLayerNum = 0;
+ foreach (CallCmd iter in originalParCallCmd.CallCmds)
+ {
+ int calleeLayerNum = civlTypeChecker.procToActionInfo[iter.Proc].createdAtLayerNum;
+ if (calleeLayerNum > maxCalleeLayerNum)
+ maxCalleeLayerNum = calleeLayerNum;
+ }
+ if (layerNum > maxCalleeLayerNum)
+ {
+ for (int i = 0; i < parCallCmd.CallCmds.Count; i++)
+ {
+ ProcessCallCmd(originalParCallCmd.CallCmds[i], parCallCmd.CallCmds[i], newCmds);
+ absyMap[parCallCmd.CallCmds[i]] = originalParCallCmd;
+ }
+ }
+ else
+ {
+ newCmds.Add(parCallCmd);
+ }
+ }
+
+ public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq)
+ {
+ List<Cmd> cmds = base.VisitCmdSeq(cmdSeq);
+ List<Cmd> newCmds = new List<Cmd>();
+ for (int i = 0; i < cmds.Count; i++)
+ {
+ Cmd originalCmd = cmdSeq[i];
+ Cmd cmd = cmds[i];
+
+ CallCmd originalCallCmd = originalCmd as CallCmd;
+ if (originalCallCmd != null)
+ {
+ ProcessCallCmd(originalCallCmd, cmd as CallCmd, newCmds);
+ continue;
+ }
+
+ ParCallCmd originalParCallCmd = originalCmd as ParCallCmd;
+ if (originalParCallCmd != null)
+ {
+ ProcessParCallCmd(originalParCallCmd, cmd as ParCallCmd, newCmds);
+ continue;
+ }
+
+ newCmds.Add(cmd);
+ }
+ return newCmds;
+ }
+
+ public override YieldCmd VisitYieldCmd(YieldCmd node)
+ {
+ YieldCmd yieldCmd = base.VisitYieldCmd(node);
+ absyMap[yieldCmd] = node;
+ return yieldCmd;
+ }
+
+ public override Block VisitBlock(Block node)
+ {
+ Block block = base.VisitBlock(node);
+ absyMap[block] = node;
+ return block;
+ }
+
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ CallCmd callCmd = (CallCmd) base.VisitCallCmd(node);
+ callCmd.Proc = VisitProcedure(callCmd.Proc);
+ callCmd.callee = callCmd.Proc.Name;
+ absyMap[callCmd] = node;
+ return callCmd;
+ }
+
+ public override Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ ParCallCmd parCallCmd = (ParCallCmd) base.VisitParCallCmd(node);
+ absyMap[parCallCmd] = node;
+ return parCallCmd;
+ }
+
+ public override Procedure VisitProcedure(Procedure node)
+ {
+ if (!civlTypeChecker.procToActionInfo.ContainsKey(node))
+ return node;
+ if (!procMap.ContainsKey(node))
+ {
+ enclosingProc = node;
+ Procedure proc = (Procedure)node.Clone();
+ proc.Name = string.Format("{0}_{1}", node.Name, layerNum);
+ proc.InParams = this.VisitVariableSeq(node.InParams);
+ proc.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
+ proc.OutParams = this.VisitVariableSeq(node.OutParams);
+
+ ActionInfo actionInfo = civlTypeChecker.procToActionInfo[node];
+ if (actionInfo.createdAtLayerNum < layerNum)
+ {
+ proc.Requires = new List<Requires>();
+ proc.Ensures = new List<Ensures>();
+ Implementation impl;
+ AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
+ if (atomicActionInfo != null)
+ {
+ CodeExpr action = (CodeExpr)VisitCodeExpr(atomicActionInfo.action);
+ List<Cmd> cmds = new List<Cmd>();
+ foreach (AssertCmd assertCmd in atomicActionInfo.gate)
+ {
+ cmds.Add(new AssumeCmd(Token.NoToken, (Expr)Visit(assertCmd.Expr)));
+ }
+ Block newInitBlock = new Block(Token.NoToken, "_init", cmds,
+ new GotoCmd(Token.NoToken, new List<string>(new string[] { action.Blocks[0].Label }),
+ new List<Block>(new Block[] { action.Blocks[0] })));
+ List<Block> newBlocks = new List<Block>();
+ newBlocks.Add(newInitBlock);
+ newBlocks.AddRange(action.Blocks);
+ impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, action.LocVars, newBlocks);
+ }
+ else
+ {
+ Block newInitBlock = new Block(Token.NoToken, "_init", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ List<Block> newBlocks = new List<Block>();
+ newBlocks.Add(newInitBlock);
+ impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, new List<Variable>(), newBlocks);
+ }
+ impl.Proc = proc;
+ impl.Proc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
+ impl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
+ impls.Add(impl);
+ }
+ else
+ {
+ yieldingProcs.Add(proc);
+ proc.Requires = this.VisitRequiresSeq(node.Requires);
+ proc.Ensures = this.VisitEnsuresSeq(node.Ensures);
+ }
+ procMap[node] = proc;
+ proc.Modifies = new List<IdentifierExpr>();
+ civlTypeChecker.SharedVariables.Iter(x => proc.Modifies.Add(Expr.Ident(x)));
+ }
+ return procMap[node];
+ }
+
+ private Variable dummyLocalVar;
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ enclosingImpl = node;
+ dummyLocalVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_dummy", Type.Bool));
+ Implementation impl = base.VisitImplementation(node);
+ implMap[impl] = node;
+ impl.LocVars.Add(dummyLocalVar);
+ impl.Name = impl.Proc.Name;
+ return impl;
+ }
+
+ public override Requires VisitRequires(Requires node)
+ {
+ Requires requires = base.VisitRequires(node);
+ if (node.Free)
+ return requires;
+ if (!civlTypeChecker.absyToLayerNums[node].Contains(layerNum))
+ requires.Condition = Expr.True;
+ return requires;
+ }
+
+ public override Ensures VisitEnsures(Ensures node)
+ {
+ Ensures ensures = base.VisitEnsures(node);
+ if (node.Free)
+ return ensures;
+ AtomicActionInfo atomicActionInfo = civlTypeChecker.procToActionInfo[enclosingProc] as AtomicActionInfo;
+ bool isAtomicSpecification = atomicActionInfo != null && atomicActionInfo.ensures == node;
+ if (isAtomicSpecification || !civlTypeChecker.absyToLayerNums[node].Contains(layerNum))
+ {
+ ensures.Condition = Expr.True;
+ ensures.Attributes = CivlRefinement.RemoveMoverAttribute(ensures.Attributes);
+ }
+ return ensures;
+ }
+
+ public override Cmd VisitAssertCmd(AssertCmd node)
+ {
+ AssertCmd assertCmd = (AssertCmd) base.VisitAssertCmd(node);
+ if (!civlTypeChecker.absyToLayerNums[node].Contains(layerNum))
+ assertCmd.Expr = Expr.True;
+ return assertCmd;
+ }
+ }
+
+ public class CivlRefinement
+ {
+ LinearTypeChecker linearTypeChecker;
+ CivlTypeChecker civlTypeChecker;
+ Dictionary<Absy, Absy> absyMap;
+ Dictionary<Implementation, Implementation> implMap;
+ HashSet<Procedure> yieldingProcs;
+ int layerNum;
+ List<IdentifierExpr> globalMods;
+ Dictionary<string, Procedure> asyncAndParallelCallDesugarings;
+ List<Procedure> yieldCheckerProcs;
+ List<Implementation> yieldCheckerImpls;
+ Procedure yieldProc;
+
+ Variable pc;
+ Variable ok;
+ Expr alpha;
+ Expr beta;
+ HashSet<Variable> frame;
+
+ public CivlRefinement(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, MyDuplicator duplicator)
+ {
+ this.linearTypeChecker = linearTypeChecker;
+ this.civlTypeChecker = civlTypeChecker;
+ this.absyMap = duplicator.absyMap;
+ this.layerNum = duplicator.layerNum;
+ this.implMap = duplicator.implMap;
+ this.yieldingProcs = duplicator.yieldingProcs;
+ Program program = linearTypeChecker.program;
+ globalMods = new List<IdentifierExpr>();
+ foreach (Variable g in civlTypeChecker.SharedVariables)
+ {
+ globalMods.Add(Expr.Ident(g));
+ }
+ asyncAndParallelCallDesugarings = new Dictionary<string, Procedure>();
+ yieldCheckerProcs = new List<Procedure>();
+ yieldCheckerImpls = new List<Implementation>();
+ yieldProc = null;
+ }
+
+ private IEnumerable<Variable> AvailableLinearVars(Absy absy)
+ {
+ HashSet<Variable> availableVars = new HashSet<Variable>(linearTypeChecker.AvailableLinearVars(absyMap[absy]));
+ foreach (var g in civlTypeChecker.globalVarToSharedVarInfo.Keys)
+ {
+ SharedVariableInfo info = civlTypeChecker.globalVarToSharedVarInfo[g];
+ if (!(info.introLayerNum <= layerNum && layerNum <= info.hideLayerNum))
+ {
+ availableVars.Remove(g);
+ }
+ }
+ foreach (var v in civlTypeChecker.localVarToLocalVariableInfo.Keys)
+ {
+ LocalVariableInfo info = civlTypeChecker.localVarToLocalVariableInfo[v];
+ if (layerNum < info.layer)
+ {
+ availableVars.Remove(v);
+ }
+ }
+ return availableVars;
+ }
+
+ private CallCmd CallToYieldProc(IToken tok, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
+ {
+ List<Expr> exprSeq = new List<Expr>();
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ exprSeq.Add(Expr.Ident(domainNameToLocalVar[domainName]));
+ }
+ foreach (IdentifierExpr ie in globalMods)
+ {
+ exprSeq.Add(Expr.Ident(ogOldGlobalMap[ie.Decl]));
+ }
+ if (yieldProc == null)
+ {
+ List<Variable> inputs = new List<Variable>();
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ var domain = linearTypeChecker.linearDomains[domainName];
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
+ inputs.Add(f);
+ }
+ foreach (IdentifierExpr ie in globalMods)
+ {
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
+ inputs.Add(f);
+ }
+ yieldProc = new Procedure(Token.NoToken, string.Format("og_yield_{0}", layerNum), new List<TypeVariable>(), inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>());
+ yieldProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
+ }
+ CallCmd yieldCallCmd = new CallCmd(Token.NoToken, yieldProc.Name, exprSeq, new List<IdentifierExpr>());
+ yieldCallCmd.Proc = yieldProc;
+ return yieldCallCmd;
+ }
+
+ private void AddCallToYieldProc(IToken tok, List<Cmd> newCmds, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
+ {
+ if (!CommandLineOptions.Clo.TrustNonInterference)
+ {
+ CallCmd yieldCallCmd = CallToYieldProc(tok, ogOldGlobalMap, domainNameToLocalVar);
+ newCmds.Add(yieldCallCmd);
+ }
+
+ if (pc != null)
+ {
+ Expr aa = OldEqualityExprForGlobals(ogOldGlobalMap);
+ Expr bb = OldEqualityExpr(ogOldGlobalMap);
+
+ // assert pc || g_old == g || beta(i, g_old, o, g);
+ Expr assertExpr = Expr.Or(Expr.Ident(pc), Expr.Or(aa, beta));
+ assertExpr.Typecheck(new TypecheckingContext(null));
+ AssertCmd skipOrBetaAssertCmd = new AssertCmd(tok, assertExpr);
+ skipOrBetaAssertCmd.ErrorData = "Transition invariant in initial state violated";
+ newCmds.Add(skipOrBetaAssertCmd);
+
+ // assert pc ==> o_old == o && g_old == g;
+ assertExpr = Expr.Imp(Expr.Ident(pc), bb);
+ assertExpr.Typecheck(new TypecheckingContext(null));
+ AssertCmd skipAssertCmd = new AssertCmd(tok, assertExpr);
+ skipAssertCmd.ErrorData = "Transition invariant in final state violated"; ;
+ newCmds.Add(skipAssertCmd);
+
+ // pc, ok := g_old == g ==> pc, ok || beta(i, g_old, o, g);
+ List<AssignLhs> pcUpdateLHS = new List<AssignLhs>(
+ new AssignLhs[] {
+ new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)),
+ new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))
+ });
+ List<Expr> pcUpdateRHS = new List<Expr>(
+ new Expr[] {
+ Expr.Imp(aa, Expr.Ident(pc)),
+ Expr.Or(Expr.Ident(ok), beta)
+ });
+ foreach (Expr e in pcUpdateRHS)
+ {
+ e.Typecheck(new TypecheckingContext(null));
+ }
+ newCmds.Add(new AssignCmd(Token.NoToken, pcUpdateLHS, pcUpdateRHS));
+ }
+ }
+
+ private Dictionary<string, Expr> ComputeAvailableExprs(IEnumerable<Variable> availableLinearVars, Dictionary<string, Variable> domainNameToInputVar)
+ {
+ Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
+ foreach (var domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ var expr = Expr.Ident(domainNameToInputVar[domainName]);
+ expr.Resolve(new ResolutionContext(null));
+ expr.Typecheck(new TypecheckingContext(null));
+ domainNameToExpr[domainName] = expr;
+ }
+ foreach (Variable v in availableLinearVars)
+ {
+ var domainName = linearTypeChecker.FindDomainName(v);
+ if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
+ var domain = linearTypeChecker.linearDomains[domainName];
+ if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
+ Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
+ var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
+ expr.Resolve(new ResolutionContext(null));
+ expr.Typecheck(new TypecheckingContext(null));
+ domainNameToExpr[domainName] = expr;
+ }
+ return domainNameToExpr;
+ }
+
+ private void AddUpdatesToOldGlobalVars(List<Cmd> newCmds, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<string, Expr> domainNameToExpr)
+ {
+ List<AssignLhs> lhss = new List<AssignLhs>();
+ List<Expr> rhss = new List<Expr>();
+ foreach (var domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName])));
+ rhss.Add(domainNameToExpr[domainName]);
+ }
+ foreach (Variable g in ogOldGlobalMap.Keys)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g])));
+ rhss.Add(Expr.Ident(g));
+ }
+ if (lhss.Count > 0)
+ {
+ newCmds.Add(new AssignCmd(Token.NoToken, lhss, rhss));
+ }
+ }
+
+ private Expr OldEqualityExpr(Dictionary<Variable, Variable> ogOldGlobalMap)
+ {
+ Expr bb = Expr.True;
+ foreach (Variable o in ogOldGlobalMap.Keys)
+ {
+ if (o is GlobalVariable && !frame.Contains(o)) continue;
+ bb = Expr.And(bb, Expr.Eq(Expr.Ident(o), Expr.Ident(ogOldGlobalMap[o])));
+ bb.Type = Type.Bool;
+ }
+ return bb;
+ }
+
+ private Expr OldEqualityExprForGlobals(Dictionary<Variable, Variable> ogOldGlobalMap)
+ {
+ Expr bb = Expr.True;
+ foreach (Variable o in ogOldGlobalMap.Keys)
+ {
+ if (o is GlobalVariable && frame.Contains(o))
+ {
+ bb = Expr.And(bb, Expr.Eq(Expr.Ident(o), Expr.Ident(ogOldGlobalMap[o])));
+ bb.Type = Type.Bool;
+ }
+ }
+ return bb;
+ }
+
+ private void DesugarYield(YieldCmd yieldCmd, List<Cmd> cmds, List<Cmd> newCmds, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar)
+ {
+ AddCallToYieldProc(yieldCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
+
+ if (globalMods.Count > 0)
+ {
+ newCmds.Add(new HavocCmd(Token.NoToken, globalMods));
+ if (pc != null)
+ {
+ // assume pc || alpha(i, g);
+ Expr assumeExpr = Expr.Or(Expr.Ident(pc), alpha);
+ assumeExpr.Type = Type.Bool;
+ newCmds.Add(new AssumeCmd(Token.NoToken, assumeExpr));
+ }
+ }
+
+ Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(AvailableLinearVars(yieldCmd), domainNameToInputVar);
+ AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
+
+ for (int j = 0; j < cmds.Count; j++)
+ {
+ PredicateCmd predCmd = (PredicateCmd)cmds[j];
+ newCmds.Add(new AssumeCmd(Token.NoToken, predCmd.Expr));
+ }
+ }
+
+ public void DesugarParallelCallCmd(List<Cmd> newCmds, ParCallCmd parCallCmd)
+ {
+ List<string> parallelCalleeNames = new List<string>();
+ List<Expr> ins = new List<Expr>();
+ List<IdentifierExpr> outs = new List<IdentifierExpr>();
+ string procName = "og";
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ procName = procName + "_" + callCmd.Proc.Name;
+ ins.AddRange(callCmd.Ins);
+ outs.AddRange(callCmd.Outs);
+ }
+ Procedure proc;
+ if (asyncAndParallelCallDesugarings.ContainsKey(procName))
+ {
+ proc = asyncAndParallelCallDesugarings[procName];
+ }
+ else
+ {
+ List<Variable> inParams = new List<Variable>();
+ List<Variable> outParams = new List<Variable>();
+ List<Requires> requiresSeq = new List<Requires>();
+ List<Ensures> ensuresSeq = new List<Ensures>();
+ int count = 0;
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
+ foreach (Variable x in callCmd.Proc.InParams)
+ {
+ Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_{0}_{1}", count, x.Name), x.TypedIdent.Type), true);
+ inParams.Add(y);
+ map[x] = Expr.Ident(y);
+ }
+ foreach (Variable x in callCmd.Proc.OutParams)
+ {
+ Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_{0}_{1}", count, x.Name), x.TypedIdent.Type), false);
+ outParams.Add(y);
+ map[x] = Expr.Ident(y);
+ }
+ Contract.Assume(callCmd.Proc.TypeParameters.Count == 0);
+ Substitution subst = Substituter.SubstitutionFromHashtable(map);
+ foreach (Requires req in callCmd.Proc.Requires)
+ {
+ requiresSeq.Add(new Requires(req.tok, req.Free, Substituter.Apply(subst, req.Condition), null, req.Attributes));
+ }
+ foreach (Ensures ens in callCmd.Proc.Ensures)
+ {
+ ensuresSeq.Add(new Ensures(ens.tok, ens.Free, Substituter.Apply(subst, ens.Condition), null, ens.Attributes));
+ }
+ count++;
+ }
+ proc = new Procedure(Token.NoToken, procName, new List<TypeVariable>(), inParams, outParams, requiresSeq, globalMods, ensuresSeq);
+ asyncAndParallelCallDesugarings[procName] = proc;
+ }
+ CallCmd dummyCallCmd = new CallCmd(parCallCmd.tok, proc.Name, ins, outs, parCallCmd.Attributes);
+ dummyCallCmd.Proc = proc;
+ newCmds.Add(dummyCallCmd);
+ }
+
+ private void CreateYieldCheckerImpl(Implementation impl, List<List<Cmd>> yields)
+ {
+ if (yields.Count == 0) return;
+
+ Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
+ foreach (Variable local in impl.LocVars)
+ {
+ var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, local.Name, local.TypedIdent.Type));
+ map[local] = Expr.Ident(copy);
+ }
+
+ Program program = linearTypeChecker.program;
+ List<Variable> locals = new List<Variable>();
+ List<Variable> inputs = new List<Variable>();
+ foreach (IdentifierExpr ie in map.Values)
+ {
+ locals.Add(ie.Decl);
+ }
+ for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++)
+ {
+ Variable inParam = impl.InParams[i];
+ Variable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type));
+ locals.Add(copy);
+ map[impl.InParams[i]] = Expr.Ident(copy);
+ }
+ {
+ int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count;
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ Variable inParam = impl.InParams[i];
+ Variable copy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type), true);
+ inputs.Add(copy);
+ map[impl.InParams[i]] = Expr.Ident(copy);
+ i++;
+ }
+ }
+ for (int i = 0; i < impl.OutParams.Count; i++)
+ {
+ Variable outParam = impl.OutParams[i];
+ var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, outParam.Name, outParam.TypedIdent.Type));
+ locals.Add(copy);
+ map[impl.OutParams[i]] = Expr.Ident(copy);
+ }
+ Dictionary<Variable, Expr> ogOldLocalMap = new Dictionary<Variable, Expr>();
+ Dictionary<Variable, Expr> assumeMap = new Dictionary<Variable, Expr>(map);
+ foreach (IdentifierExpr ie in globalMods)
+ {
+ Variable g = ie.Decl;
+ var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_local_old_{0}", g.Name), g.TypedIdent.Type));
+ locals.Add(copy);
+ ogOldLocalMap[g] = Expr.Ident(copy);
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type), true);
+ inputs.Add(f);
+ assumeMap[g] = Expr.Ident(f);
+ }
+
+ Substitution assumeSubst = Substituter.SubstitutionFromHashtable(assumeMap);
+ Substitution oldSubst = Substituter.SubstitutionFromHashtable(ogOldLocalMap);
+ Substitution subst = Substituter.SubstitutionFromHashtable(map);
+ List<Block> yieldCheckerBlocks = new List<Block>();
+ List<String> labels = new List<String>();
+ List<Block> labelTargets = new List<Block>();
+ Block yieldCheckerBlock = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ labels.Add(yieldCheckerBlock.Label);
+ labelTargets.Add(yieldCheckerBlock);
+ yieldCheckerBlocks.Add(yieldCheckerBlock);
+ int yieldCount = 0;
+ foreach (List<Cmd> cs in yields)
+ {
+ List<Cmd> newCmds = new List<Cmd>();
+ foreach (Cmd cmd in cs)
+ {
+ PredicateCmd predCmd = (PredicateCmd)cmd;
+ newCmds.Add(new AssumeCmd(Token.NoToken, Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr)));
+ }
+ foreach (Cmd cmd in cs)
+ {
+ PredicateCmd predCmd = (PredicateCmd)cmd;
+ var newExpr = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr);
+ if (predCmd is AssertCmd)
+ {
+ AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes);
+ assertCmd.ErrorData = "Non-interference check failed";
+ newCmds.Add(assertCmd);
+ }
+ else
+ {
+ newCmds.Add(new AssumeCmd(Token.NoToken, newExpr));
+ }
+ }
+ newCmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
+ yieldCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken));
+ labels.Add(yieldCheckerBlock.Label);
+ labelTargets.Add(yieldCheckerBlock);
+ yieldCheckerBlocks.Add(yieldCheckerBlock);
+ }
+ yieldCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets)));
+
+ // Create the yield checker procedure
+ var yieldCheckerName = string.Format("{0}_YieldChecker_{1}", "Impl", impl.Name);
+ var yieldCheckerProc = new Procedure(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>());
+ yieldCheckerProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
+ yieldCheckerProcs.Add(yieldCheckerProc);
+
+ // Create the yield checker implementation
+ var yieldCheckerImpl = new Implementation(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), locals, yieldCheckerBlocks);
+ yieldCheckerImpl.Proc = yieldCheckerProc;
+ yieldCheckerImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
+ yieldCheckerImpls.Add(yieldCheckerImpl);
+ }
+
+ private bool IsYieldingHeader(Graph<Block> graph, Block header)
+ {
+ foreach (Block backEdgeNode in graph.BackEdgeNodes(header))
+ {
+ foreach (Block x in graph.NaturalLoops(header, backEdgeNode))
+ {
+ foreach (Cmd cmd in x.Cmds)
+ {
+ if (cmd is YieldCmd)
+ return true;
+ if (cmd is ParCallCmd)
+ return true;
+ CallCmd callCmd = cmd as CallCmd;
+ if (callCmd == null) continue;
+ if (yieldingProcs.Contains(callCmd.Proc))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private Graph<Block> ComputeYieldingLoopHeaders(Implementation impl, out HashSet<Block> yieldingHeaders)
+ {
+ Graph<Block> graph;
+ impl.PruneUnreachableBlocks();
+ impl.ComputePredecessorsForBlocks();
+ graph = Program.GraphFromImpl(impl);
+ graph.ComputeLoops();
+ if (!graph.Reducible)
+ {
+ throw new Exception("Irreducible flow graphs are unsupported.");
+ }
+ yieldingHeaders = new HashSet<Block>();
+ IEnumerable<Block> sortedHeaders = graph.SortHeadersByDominance();
+ foreach (Block header in sortedHeaders)
+ {
+ if (yieldingHeaders.Any(x => graph.DominatorMap.DominatedBy(x, header)))
+ {
+ yieldingHeaders.Add(header);
+ }
+ else if (IsYieldingHeader(graph, header))
+ {
+ yieldingHeaders.Add(header);
+ }
+ else
+ {
+ continue;
+ }
+ }
+ return graph;
+ }
+
+ private void SetupRefinementCheck(Implementation impl,
+ out List<Variable> newLocalVars,
+ out Dictionary<string, Variable> domainNameToInputVar, out Dictionary<string, Variable> domainNameToLocalVar, out Dictionary<Variable, Variable> ogOldGlobalMap)
+ {
+ pc = null;
+ ok = null;
+ alpha = null;
+ beta = null;
+ frame = null;
+
+ newLocalVars = new List<Variable>();
+ Program program = linearTypeChecker.program;
+ ogOldGlobalMap = new Dictionary<Variable, Variable>();
+ foreach (IdentifierExpr ie in globalMods)
+ {
+ Variable g = ie.Decl;
+ LocalVariable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type));
+ ogOldGlobalMap[g] = l;
+ newLocalVars.Add(l);
+ }
+
+ Procedure originalProc = implMap[impl].Proc;
+ ActionInfo actionInfo = civlTypeChecker.procToActionInfo[originalProc];
+ if (actionInfo.createdAtLayerNum == this.layerNum)
+ {
+ pc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_pc", Type.Bool));
+ newLocalVars.Add(pc);
+ ok = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_ok", Type.Bool));
+ newLocalVars.Add(ok);
+ Dictionary<Variable, Expr> alwaysMap = new Dictionary<Variable, Expr>();
+ for (int i = 0; i < originalProc.InParams.Count; i++)
+ {
+ alwaysMap[originalProc.InParams[i]] = Expr.Ident(impl.InParams[i]);
+ }
+ for (int i = 0; i < originalProc.OutParams.Count; i++)
+ {
+ alwaysMap[originalProc.OutParams[i]] = Expr.Ident(impl.OutParams[i]);
+ }
+ Substitution always = Substituter.SubstitutionFromHashtable(alwaysMap);
+ Dictionary<Variable, Expr> foroldMap = new Dictionary<Variable, Expr>();
+ foreach (IdentifierExpr ie in globalMods)
+ {
+ foroldMap[ie.Decl] = Expr.Ident(ogOldGlobalMap[ie.Decl]);
+ }
+ Substitution forold = Substituter.SubstitutionFromHashtable(foroldMap);
+ frame = new HashSet<Variable>(civlTypeChecker.SharedVariables);
+ foreach (Variable v in civlTypeChecker.SharedVariables)
+ {
+ if (civlTypeChecker.globalVarToSharedVarInfo[v].hideLayerNum <= actionInfo.createdAtLayerNum ||
+ civlTypeChecker.globalVarToSharedVarInfo[v].introLayerNum > actionInfo.createdAtLayerNum)
+ {
+ frame.Remove(v);
+ }
+ }
+ AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
+ if (atomicActionInfo == null)
+ {
+ beta = Expr.True;
+ foreach (var v in frame)
+ {
+ beta = Expr.And(beta, Expr.Eq(Expr.Ident(v), foroldMap[v]));
+ }
+ alpha = Expr.True;
+ }
+ else
+ {
+ Expr betaExpr = (new MoverCheck.TransitionRelationComputation(civlTypeChecker.program, atomicActionInfo, frame, new HashSet<Variable>())).TransitionRelationCompute(true);
+ beta = Substituter.ApplyReplacingOldExprs(always, forold, betaExpr);
+ Expr alphaExpr = Expr.True;
+ foreach (AssertCmd assertCmd in atomicActionInfo.gate)
+ {
+ alphaExpr = Expr.And(alphaExpr, assertCmd.Expr);
+ alphaExpr.Type = Type.Bool;
+ }
+ alpha = Substituter.Apply(always, alphaExpr);
+ }
+ foreach (Variable f in impl.OutParams)
+ {
+ LocalVariable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_old_{0}", f.Name), f.TypedIdent.Type));
+ newLocalVars.Add(copy);
+ ogOldGlobalMap[f] = copy;
+ }
+ }
+
+ domainNameToInputVar = new Dictionary<string, Variable>();
+ domainNameToLocalVar = new Dictionary<string, Variable>();
+ {
+ int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count;
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ Variable inParam = impl.InParams[i];
+ domainNameToInputVar[domainName] = inParam;
+ Variable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name + "_local", inParam.TypedIdent.Type));
+ domainNameToLocalVar[domainName] = l;
+ newLocalVars.Add(l);
+ i++;
+ }
+ }
+ }
+
+ private void TransformImpl(Implementation impl)
+ {
+ HashSet<Block> yieldingHeaders;
+ Graph<Block> graph = ComputeYieldingLoopHeaders(impl, out yieldingHeaders);
+
+ List<Variable> newLocalVars;
+ Dictionary<string, Variable> domainNameToInputVar, domainNameToLocalVar;
+ Dictionary<Variable, Variable> ogOldGlobalMap;
+ SetupRefinementCheck(impl, out newLocalVars, out domainNameToInputVar, out domainNameToLocalVar, out ogOldGlobalMap);
+
+ List<List<Cmd>> yields = CollectAndDesugarYields(impl, domainNameToInputVar, domainNameToLocalVar, ogOldGlobalMap);
+
+ List<Variable> oldPcs, oldOks;
+ ProcessLoopHeaders(impl, graph, yieldingHeaders, domainNameToInputVar, domainNameToLocalVar, ogOldGlobalMap, out oldPcs, out oldOks);
+
+ AddInitialBlock(impl, oldPcs, oldOks, domainNameToInputVar, domainNameToLocalVar, ogOldGlobalMap);
+
+ CreateYieldCheckerImpl(impl, yields);
+
+ impl.LocVars.AddRange(newLocalVars);
+ impl.LocVars.AddRange(oldPcs);
+ impl.LocVars.AddRange(oldOks);
+
+ UnifyCallsToYieldProc(impl, ogOldGlobalMap, domainNameToLocalVar);
+ }
+
+ private void UnifyCallsToYieldProc(Implementation impl, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
+ {
+ CallCmd yieldCallCmd = CallToYieldProc(Token.NoToken, ogOldGlobalMap, domainNameToLocalVar);
+ Block yieldCheckBlock = new Block(Token.NoToken, "CallToYieldProc", new List<Cmd>(new Cmd[] { yieldCallCmd, new AssumeCmd(Token.NoToken, Expr.False) }), new ReturnCmd(Token.NoToken));
+ List<Block> newBlocks = new List<Block>();
+ foreach (Block b in impl.Blocks)
+ {
+ TransferCmd transferCmd = b.TransferCmd;
+ List<Cmd> newCmds = new List<Cmd>();
+ for (int i = b.Cmds.Count-1; i >= 0; i--)
+ {
+ CallCmd callCmd = b.Cmds[i] as CallCmd;
+ if (callCmd == null || callCmd.Proc != yieldProc)
+ {
+ newCmds.Insert(0, b.Cmds[i]);
+ }
+ else
+ {
+ Block newBlock = new Block(Token.NoToken, b.Label + i, newCmds, transferCmd);
+ newCmds = new List<Cmd>();
+ transferCmd = new GotoCmd(Token.NoToken, new List<string>(new string[] { newBlock.Label, yieldCheckBlock.Label }),
+ new List<Block>(new Block[] { newBlock, yieldCheckBlock }));
+ newBlocks.Add(newBlock);
+ }
+ }
+ b.Cmds = newCmds;
+ b.TransferCmd = transferCmd;
+ }
+ impl.Blocks.AddRange(newBlocks);
+ impl.Blocks.Add(yieldCheckBlock);
+ }
+
+ private List<List<Cmd>> CollectAndDesugarYields(Implementation impl,
+ Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap)
+ {
+ // Collect the yield predicates and desugar yields
+ List<List<Cmd>> yields = new List<List<Cmd>>();
+ List<Cmd> cmds = new List<Cmd>();
+ foreach (Block b in impl.Blocks)
+ {
+ YieldCmd yieldCmd = null;
+ List<Cmd> newCmds = new List<Cmd>();
+ for (int i = 0; i < b.Cmds.Count; i++)
+ {
+ Cmd cmd = b.Cmds[i];
+ if (cmd is YieldCmd)
+ {
+ yieldCmd = (YieldCmd)cmd;
+ continue;
+ }
+ if (yieldCmd != null)
+ {
+ PredicateCmd pcmd = cmd as PredicateCmd;
+ if (pcmd == null)
+ {
+ DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar);
+ if (cmds.Count > 0)
+ {
+ yields.Add(cmds);
+ cmds = new List<Cmd>();
+ }
+ yieldCmd = null;
+ }
+ else
+ {
+ cmds.Add(pcmd);
+ }
+ }
+
+ if (cmd is CallCmd)
+ {
+ CallCmd callCmd = cmd as CallCmd;
+ if (yieldingProcs.Contains(callCmd.Proc))
+ {
+ AddCallToYieldProc(callCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
+ }
+ if (callCmd.IsAsync)
+ {
+ if (!asyncAndParallelCallDesugarings.ContainsKey(callCmd.Proc.Name))
+ {
+ asyncAndParallelCallDesugarings[callCmd.Proc.Name] = new Procedure(Token.NoToken, string.Format("DummyAsyncTarget_{0}", callCmd.Proc.Name), callCmd.Proc.TypeParameters, callCmd.Proc.InParams, callCmd.Proc.OutParams, callCmd.Proc.Requires, new List<IdentifierExpr>(), new List<Ensures>());
+ }
+ var dummyAsyncTargetProc = asyncAndParallelCallDesugarings[callCmd.Proc.Name];
+ CallCmd dummyCallCmd = new CallCmd(callCmd.tok, dummyAsyncTargetProc.Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes);
+ dummyCallCmd.Proc = dummyAsyncTargetProc;
+ newCmds.Add(dummyCallCmd);
+ }
+ else
+ {
+ newCmds.Add(callCmd);
+ }
+ if (yieldingProcs.Contains(callCmd.Proc))
+ {
+ HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(callCmd));
+ linearTypeChecker.AddAvailableVars(callCmd, availableLinearVars);
+
+ if (!callCmd.IsAsync && globalMods.Count > 0 && pc != null)
+ {
+ // assume pc || alpha(i, g);
+ Expr assumeExpr = Expr.Or(Expr.Ident(pc), alpha);
+ assumeExpr.Type = Type.Bool;
+ newCmds.Add(new AssumeCmd(Token.NoToken, assumeExpr));
+ }
+
+ Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar);
+ AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
+ }
+ }
+ else if (cmd is ParCallCmd)
+ {
+ ParCallCmd parCallCmd = cmd as ParCallCmd;
+ AddCallToYieldProc(parCallCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
+ DesugarParallelCallCmd(newCmds, parCallCmd);
+ HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(parCallCmd));
+ linearTypeChecker.AddAvailableVars(parCallCmd, availableLinearVars);
+
+ if (globalMods.Count > 0 && pc != null)
+ {
+ // assume pc || alpha(i, g);
+ Expr assumeExpr = Expr.Or(Expr.Ident(pc), alpha);
+ assumeExpr.Type = Type.Bool;
+ newCmds.Add(new AssumeCmd(Token.NoToken, assumeExpr));
+ }
+
+ Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar);
+ AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
+ }
+ else
+ {
+ newCmds.Add(cmd);
+ }
+ }
+ if (yieldCmd != null)
+ {
+ DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar);
+ if (cmds.Count > 0)
+ {
+ yields.Add(cmds);
+ cmds = new List<Cmd>();
+ }
+ }
+ if (b.TransferCmd is ReturnCmd)
+ {
+ AddCallToYieldProc(b.TransferCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
+ if (pc != null)
+ {
+ AssertCmd assertCmd = new AssertCmd(b.TransferCmd.tok, Expr.Ident(ok));
+ assertCmd.ErrorData = "Failed to execute atomic action before procedure return";
+ newCmds.Add(assertCmd);
+ }
+ }
+ b.Cmds = newCmds;
+ }
+ return yields;
+ }
+
+ private void ProcessLoopHeaders(Implementation impl, Graph<Block> graph, HashSet<Block> yieldingHeaders,
+ Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap,
+ out List<Variable> oldPcs, out List<Variable> oldOks)
+ {
+ oldPcs = new List<Variable>();
+ oldOks = new List<Variable>();
+ foreach (Block header in yieldingHeaders)
+ {
+ LocalVariable oldPc = null;
+ LocalVariable oldOk = null;
+ if (pc != null)
+ {
+ oldPc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}", pc.Name, header.Label), Type.Bool));
+ oldPcs.Add(oldPc);
+ oldOk = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}", ok.Name, header.Label), Type.Bool));
+ oldOks.Add(oldOk);
+ }
+ Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(AvailableLinearVars(header), domainNameToInputVar);
+ foreach (Block pred in header.Predecessors)
+ {
+ AddCallToYieldProc(header.tok, pred.Cmds, ogOldGlobalMap, domainNameToLocalVar);
+ if (pc != null && !graph.BackEdgeNodes(header).Contains(pred))
+ {
+ pred.Cmds.Add(new AssignCmd(Token.NoToken, new List<AssignLhs>(
+ new AssignLhs[] { new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc)), new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk)) }),
+ new List<Expr>(new Expr[] { Expr.Ident(pc), Expr.Ident(ok) })));
+ }
+ AddUpdatesToOldGlobalVars(pred.Cmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
+ }
+ List<Cmd> newCmds = new List<Cmd>();
+ if (pc != null)
+ {
+ AssertCmd assertCmd;
+ assertCmd = new AssertCmd(header.tok, Expr.Eq(Expr.Ident(oldPc), Expr.Ident(pc)));
+ assertCmd.ErrorData = "Specification state must not change for transitions ending in loop headers";
+ newCmds.Add(assertCmd);
+ assertCmd = new AssertCmd(header.tok, Expr.Imp(Expr.Ident(oldOk), Expr.Ident(ok)));
+ assertCmd.ErrorData = "Specification state must not change for transitions ending in loop headers";
+ newCmds.Add(assertCmd);
+ }
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(domainNameToLocalVar[domainName]), domainNameToExpr[domainName])));
+ }
+ foreach (Variable v in ogOldGlobalMap.Keys)
+ {
+ newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(v), Expr.Ident(ogOldGlobalMap[v]))));
+ }
+ newCmds.AddRange(header.Cmds);
+ header.Cmds = newCmds;
+ }
+ }
+
+ private void AddInitialBlock(Implementation impl, List<Variable> oldPcs, List<Variable> oldOks,
+ Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap)
+ {
+ // Add initial block
+ List<AssignLhs> lhss = new List<AssignLhs>();
+ List<Expr> rhss = new List<Expr>();
+ if (pc != null)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)));
+ rhss.Add(Expr.False);
+ foreach (Variable oldPc in oldPcs)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc)));
+ rhss.Add(Expr.False);
+ }
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok)));
+ rhss.Add(Expr.False);
+ foreach (Variable oldOk in oldOks)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk)));
+ rhss.Add(Expr.False);
+ }
+ }
+ Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
+ foreach (var domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]);
+ }
+ for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++)
+ {
+ Variable v = impl.InParams[i];
+ var domainName = linearTypeChecker.FindDomainName(v);
+ if (domainName == null) continue;
+ if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
+ var domain = linearTypeChecker.linearDomains[domainName];
+ if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
+ Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
+ domainNameToExpr[domainName] = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
+ }
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName])));
+ rhss.Add(domainNameToExpr[domainName]);
+ }
+ foreach (Variable g in ogOldGlobalMap.Keys)
+ {
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g])));
+ rhss.Add(Expr.Ident(g));
+ }
+ if (lhss.Count > 0)
+ {
+ Block initBlock = new Block(Token.NoToken, "og_init", new List<Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }, new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] }));
+ impl.Blocks.Insert(0, initBlock);
+ }
+ }
+
+ private void AddYieldProcAndImpl(List<Declaration> decls)
+ {
+ if (yieldProc == null) return;
+
+ Program program = linearTypeChecker.program;
+ List<Variable> inputs = new List<Variable>();
+ foreach (string domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ var domain = linearTypeChecker.linearDomains[domainName];
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
+ inputs.Add(f);
+ }
+ foreach (IdentifierExpr ie in globalMods)
+ {
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
+ inputs.Add(f);
+ }
+ List<Block> blocks = new List<Block>();
+ TransferCmd transferCmd = new ReturnCmd(Token.NoToken);
+ if (yieldCheckerProcs.Count > 0)
+ {
+ List<Block> blockTargets = new List<Block>();
+ List<String> labelTargets = new List<String>();
+ int labelCount = 0;
+ foreach (Procedure proc in yieldCheckerProcs)
+ {
+ List<Expr> exprSeq = new List<Expr>();
+ foreach (Variable v in inputs)
+ {
+ exprSeq.Add(Expr.Ident(v));
+ }
+ CallCmd callCmd = new CallCmd(Token.NoToken, proc.Name, exprSeq, new List<IdentifierExpr>());
+ callCmd.Proc = proc;
+ string label = string.Format("L_{0}", labelCount++);
+ Block block = new Block(Token.NoToken, label, new List<Cmd> { callCmd }, new ReturnCmd(Token.NoToken));
+ labelTargets.Add(label);
+ blockTargets.Add(block);
+ blocks.Add(block);
+ }
+ transferCmd = new GotoCmd(Token.NoToken, labelTargets, blockTargets);
+ }
+ blocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), transferCmd));
+
+ var yieldImpl = new Implementation(Token.NoToken, yieldProc.Name, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks);
+ yieldImpl.Proc = yieldProc;
+ yieldImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
+ decls.Add(yieldProc);
+ decls.Add(yieldImpl);
+ }
+
+ public static QKeyValue RemoveYieldsAttribute(QKeyValue iter)
+ {
+ if (iter == null) return null;
+ iter.Next = RemoveYieldsAttribute(iter.Next);
+ return (iter.Key == "yields") ? iter.Next : iter;
+ }
+
+ public static QKeyValue RemoveMoverAttribute(QKeyValue iter)
+ {
+ if (iter == null) return null;
+ iter.Next = RemoveMoverAttribute(iter.Next);
+ if (iter.Key == "atomic" || iter.Key == "right" || iter.Key == "left" || iter.Key == "both")
+ return iter.Next;
+ else
+ return iter;
+ }
+
+ private List<Declaration> Collect()
+ {
+ List<Declaration> decls = new List<Declaration>();
+ foreach (Procedure proc in yieldCheckerProcs)
+ {
+ decls.Add(proc);
+ }
+ foreach (Implementation impl in yieldCheckerImpls)
+ {
+ decls.Add(impl);
+ }
+ foreach (Procedure proc in asyncAndParallelCallDesugarings.Values)
+ {
+ decls.Add(proc);
+ }
+ AddYieldProcAndImpl(decls);
+ return decls;
+ }
+
+ public static void AddCheckers(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List<Declaration> decls)
+ {
+ Program program = linearTypeChecker.program;
+ foreach (int layerNum in civlTypeChecker.AllLayerNums)
+ {
+ if (CommandLineOptions.Clo.TrustLayersDownto <= layerNum || layerNum <= CommandLineOptions.Clo.TrustLayersUpto) continue;
+
+ MyDuplicator duplicator = new MyDuplicator(civlTypeChecker, layerNum);
+ foreach (var proc in program.Procedures)
+ {
+ if (!civlTypeChecker.procToActionInfo.ContainsKey(proc)) continue;
+ Procedure duplicateProc = duplicator.VisitProcedure(proc);
+ decls.Add(duplicateProc);
+ }
+ decls.AddRange(duplicator.impls);
+ CivlRefinement civlTransform = new CivlRefinement(linearTypeChecker, civlTypeChecker, duplicator);
+ foreach (var impl in program.Implementations)
+ {
+ if (!civlTypeChecker.procToActionInfo.ContainsKey(impl.Proc) || civlTypeChecker.procToActionInfo[impl.Proc].createdAtLayerNum < layerNum)
+ continue;
+ Implementation duplicateImpl = duplicator.VisitImplementation(impl);
+ civlTransform.TransformImpl(duplicateImpl);
+ decls.Add(duplicateImpl);
+ }
+ decls.AddRange(civlTransform.Collect());
+ }
+ }
+ }
+}
diff --git a/Source/Concurrency/CivlTypeChecker.cs b/Source/Concurrency/CivlTypeChecker.cs
new file mode 100644
index 00000000..b426d9ed
--- /dev/null
+++ b/Source/Concurrency/CivlTypeChecker.cs
@@ -0,0 +1,1160 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+using System.Diagnostics;
+
+namespace Microsoft.Boogie
+{
+ public enum MoverType
+ {
+ Top,
+ Atomic,
+ Right,
+ Left,
+ Both
+ }
+
+ public class ActionInfo
+ {
+ public Procedure proc;
+ public int createdAtLayerNum;
+ public int availableUptoLayerNum;
+ public bool hasImplementation;
+ public bool isExtern;
+
+ public ActionInfo(Procedure proc, int createdAtLayerNum, int availableUptoLayerNum)
+ {
+ this.proc = proc;
+ this.createdAtLayerNum = createdAtLayerNum;
+ this.availableUptoLayerNum = availableUptoLayerNum;
+ this.hasImplementation = false;
+ this.isExtern = QKeyValue.FindBoolAttribute(proc.Attributes, "extern");
+ }
+
+ public virtual bool IsRightMover
+ {
+ get { return true; }
+ }
+
+ public virtual bool IsLeftMover
+ {
+ get { return true; }
+ }
+ }
+
+ public class AtomicActionInfo : ActionInfo
+ {
+ public Ensures ensures;
+ public MoverType moverType;
+ public List<AssertCmd> gate;
+ public CodeExpr action;
+ public List<AssertCmd> thisGate;
+ public CodeExpr thisAction;
+ public List<Variable> thisInParams;
+ public List<Variable> thisOutParams;
+ public List<AssertCmd> thatGate;
+ public CodeExpr thatAction;
+ public List<Variable> thatInParams;
+ public List<Variable> thatOutParams;
+ public HashSet<Variable> actionUsedGlobalVars;
+ public HashSet<Variable> modifiedGlobalVars;
+ public HashSet<Variable> gateUsedGlobalVars;
+ public bool hasAssumeCmd;
+ public Dictionary<Variable, Expr> thisMap;
+ public Dictionary<Variable, Expr> thatMap;
+
+ public bool CommutesWith(AtomicActionInfo actionInfo)
+ {
+ if (this.modifiedGlobalVars.Intersect(actionInfo.actionUsedGlobalVars).Count() > 0)
+ return false;
+ if (this.actionUsedGlobalVars.Intersect(actionInfo.modifiedGlobalVars).Count() > 0)
+ return false;
+ return true;
+ }
+
+ public override bool IsRightMover
+ {
+ get { return moverType == MoverType.Right || moverType == MoverType.Both; }
+ }
+
+ public override bool IsLeftMover
+ {
+ get { return moverType == MoverType.Left || moverType == MoverType.Both; }
+ }
+
+ public AtomicActionInfo(Procedure proc, Ensures ensures, MoverType moverType, int layerNum, int availableUptoLayerNum)
+ : base(proc, layerNum, availableUptoLayerNum)
+ {
+ this.ensures = ensures;
+ this.moverType = moverType;
+ this.gate = new List<AssertCmd>();
+ this.action = ensures.Condition as CodeExpr;
+ this.thisGate = new List<AssertCmd>();
+ this.thisInParams = new List<Variable>();
+ this.thisOutParams = new List<Variable>();
+ this.thatGate = new List<AssertCmd>();
+ this.thatInParams = new List<Variable>();
+ this.thatOutParams = new List<Variable>();
+ this.hasAssumeCmd = false;
+ this.thisMap = new Dictionary<Variable, Expr>();
+ this.thatMap = new Dictionary<Variable, Expr>();
+
+ foreach (Block block in this.action.Blocks)
+ {
+ block.Cmds.ForEach(x => this.hasAssumeCmd = this.hasAssumeCmd || x is AssumeCmd);
+ }
+
+ foreach (Block block in this.action.Blocks)
+ {
+ if (block.TransferCmd is ReturnExprCmd)
+ {
+ block.TransferCmd = new ReturnCmd(block.TransferCmd.tok);
+ }
+ }
+
+ var cmds = this.action.Blocks[0].Cmds;
+ for (int i = 0; i < cmds.Count; i++)
+ {
+ AssertCmd assertCmd = cmds[i] as AssertCmd;
+ if (assertCmd == null) break;
+ this.gate.Add(assertCmd);
+ cmds[i] = new AssumeCmd(assertCmd.tok, Expr.True);
+ }
+
+ foreach (Variable x in proc.InParams)
+ {
+ Variable thisx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "this_" + x.Name, x.TypedIdent.Type), true, x.Attributes);
+ this.thisInParams.Add(thisx);
+ this.thisMap[x] = Expr.Ident(thisx);
+ Variable thatx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true, x.Attributes);
+ this.thatInParams.Add(thatx);
+ this.thatMap[x] = Expr.Ident(thatx);
+ }
+ foreach (Variable x in proc.OutParams)
+ {
+ Variable thisx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "this_" + x.Name, x.TypedIdent.Type), false, x.Attributes);
+ this.thisOutParams.Add(thisx);
+ this.thisMap[x] = Expr.Ident(thisx);
+ Variable thatx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false, x.Attributes);
+ this.thatOutParams.Add(thatx);
+ this.thatMap[x] = Expr.Ident(thatx);
+ }
+ List<Variable> thisLocVars = new List<Variable>();
+ List<Variable> thatLocVars = new List<Variable>();
+ foreach (Variable x in this.action.LocVars)
+ {
+ Variable thisx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "this_" + x.Name, x.TypedIdent.Type), false);
+ thisMap[x] = Expr.Ident(thisx);
+ thisLocVars.Add(thisx);
+ Variable thatx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false);
+ thatMap[x] = Expr.Ident(thatx);
+ thatLocVars.Add(thatx);
+ }
+ Contract.Assume(proc.TypeParameters.Count == 0);
+ Substitution thisSubst = Substituter.SubstitutionFromHashtable(this.thisMap);
+ Substitution thatSubst = Substituter.SubstitutionFromHashtable(this.thatMap);
+ foreach (AssertCmd assertCmd in this.gate)
+ {
+ this.thisGate.Add((AssertCmd)Substituter.Apply(thisSubst, assertCmd));
+ this.thatGate.Add((AssertCmd)Substituter.Apply(thatSubst, assertCmd));
+ }
+ this.thisAction = new CodeExpr(thisLocVars, SubstituteBlocks(this.action.Blocks, thisSubst, "this_"));
+ this.thatAction = new CodeExpr(thatLocVars, SubstituteBlocks(this.action.Blocks, thatSubst, "that_"));
+
+ {
+ VariableCollector collector = new VariableCollector();
+ collector.Visit(this.action);
+ this.actionUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable));
+ }
+
+ List<Variable> modifiedVars = new List<Variable>();
+ foreach (Block block in this.action.Blocks)
+ {
+ block.Cmds.ForEach(cmd => cmd.AddAssignedVariables(modifiedVars));
+ }
+ this.modifiedGlobalVars = new HashSet<Variable>(modifiedVars.Where(x => x is GlobalVariable));
+
+ {
+ VariableCollector collector = new VariableCollector();
+ this.gate.ForEach(assertCmd => collector.Visit(assertCmd));
+ this.gateUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable));
+ }
+ }
+
+ private List<Block> SubstituteBlocks(List<Block> blocks, Substitution subst, string blockLabelPrefix)
+ {
+ Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
+ List<Block> otherBlocks = new List<Block>();
+ foreach (Block block in blocks)
+ {
+ List<Cmd> otherCmds = new List<Cmd>();
+ foreach (Cmd cmd in block.Cmds)
+ {
+ otherCmds.Add(Substituter.Apply(subst, cmd));
+ }
+ Block otherBlock = new Block();
+ otherBlock.Cmds = otherCmds;
+ otherBlock.Label = blockLabelPrefix + block.Label;
+ otherBlocks.Add(otherBlock);
+ blockMap[block] = otherBlock;
+ }
+ foreach (Block block in blocks)
+ {
+ if (block.TransferCmd is ReturnCmd)
+ {
+ blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok);
+ continue;
+ }
+ List<Block> otherGotoCmdLabelTargets = new List<Block>();
+ List<string> otherGotoCmdLabelNames = new List<string>();
+ GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
+ foreach (Block target in gotoCmd.labelTargets)
+ {
+ otherGotoCmdLabelTargets.Add(blockMap[target]);
+ otherGotoCmdLabelNames.Add(blockMap[target].Label);
+ }
+ blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets);
+ }
+ return otherBlocks;
+ }
+ }
+
+ public class SharedVariableInfo
+ {
+ public int introLayerNum;
+ public int hideLayerNum;
+
+ public SharedVariableInfo(int introLayerNum, int hideLayerNum)
+ {
+ this.introLayerNum = introLayerNum;
+ this.hideLayerNum = hideLayerNum;
+ }
+ }
+
+ public class LayerEraser : ReadOnlyVisitor
+ {
+ private QKeyValue RemoveLayerAttribute(QKeyValue iter)
+ {
+ if (iter == null) return null;
+ iter.Next = RemoveLayerAttribute(iter.Next);
+ return (iter.Key == "layer") ? iter.Next : iter;
+ }
+
+ public override Variable VisitVariable(Variable node)
+ {
+ node.Attributes = RemoveLayerAttribute(node.Attributes);
+ return base.VisitVariable(node);
+ }
+
+ public override Procedure VisitProcedure(Procedure node)
+ {
+ node.Attributes = RemoveLayerAttribute(node.Attributes);
+ return base.VisitProcedure(node);
+ }
+
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ node.Attributes = RemoveLayerAttribute(node.Attributes);
+ return base.VisitImplementation(node);
+ }
+
+ public override Requires VisitRequires(Requires node)
+ {
+ node.Attributes = RemoveLayerAttribute(node.Attributes);
+ return base.VisitRequires(node);
+ }
+
+ public override Ensures VisitEnsures(Ensures node)
+ {
+ node.Attributes = RemoveLayerAttribute(node.Attributes);
+ return base.VisitEnsures(node);
+ }
+
+ public override Cmd VisitAssertCmd(AssertCmd node)
+ {
+ node.Attributes = RemoveLayerAttribute(node.Attributes);
+ return base.VisitAssertCmd(node);
+ }
+ }
+
+ public class LayerRange
+ {
+ public int lowerLayerNum;
+ public int upperLayerNum;
+ public LayerRange(int layer)
+ {
+ this.lowerLayerNum = layer;
+ this.upperLayerNum = layer;
+ }
+ public LayerRange(int lower, int upper)
+ {
+ this.lowerLayerNum = lower;
+ this.upperLayerNum = upper;
+ }
+ public LayerRange(IEnumerable<int> layerNums)
+ {
+ int min = int.MaxValue;
+ int max = int.MinValue;
+ foreach (var layerNum in layerNums)
+ {
+ if (layerNum < min)
+ {
+ min = layerNum;
+ }
+ if (max < layerNum)
+ {
+ max = layerNum;
+ }
+ }
+ this.lowerLayerNum = min;
+ this.upperLayerNum = max;
+ }
+ public bool Contains(int layerNum)
+ {
+ return lowerLayerNum <= layerNum && layerNum <= upperLayerNum;
+ }
+ public bool Subset(int lower, int upper)
+ {
+ return lower <= lowerLayerNum && upperLayerNum <= upper;
+ }
+ public bool Equal(int lower, int upper)
+ {
+ return lower == lowerLayerNum && upperLayerNum == upper;
+ }
+ public bool Subset(LayerRange info)
+ {
+ return info.lowerLayerNum <= lowerLayerNum && upperLayerNum <= info.upperLayerNum;
+ }
+ }
+
+ public class AtomicProcedureInfo
+ {
+ public bool isPure;
+ public LayerRange layerRange;
+ public AtomicProcedureInfo()
+ {
+ this.isPure = true;
+ this.layerRange = null;
+ }
+ public AtomicProcedureInfo(LayerRange layerRange)
+ {
+ this.isPure = false;
+ this.layerRange = layerRange;
+ }
+ }
+
+ public class LocalVariableInfo
+ {
+ public int layer;
+ public LocalVariableInfo(int layer)
+ {
+ this.layer = layer;
+ }
+ }
+
+ public class CivlTypeChecker : ReadOnlyVisitor
+ {
+ CheckingContext checkingContext;
+ Procedure enclosingProc;
+ Implementation enclosingImpl;
+ HashSet<Variable> sharedVarsAccessed;
+ int introducedLocalVarsUpperBound;
+
+ public Program program;
+ public int errorCount;
+ public Dictionary<Variable, SharedVariableInfo> globalVarToSharedVarInfo;
+ public Dictionary<Procedure, ActionInfo> procToActionInfo;
+ public Dictionary<Procedure, AtomicProcedureInfo> procToAtomicProcedureInfo;
+ public Dictionary<Absy, HashSet<int>> absyToLayerNums;
+ public Dictionary<Variable, LocalVariableInfo> localVarToLocalVariableInfo;
+ Dictionary<CallCmd, int> pureCallLayer;
+
+ public bool CallExists(CallCmd callCmd, int enclosingProcLayerNum, int layerNum)
+ {
+ Debug.Assert(procToAtomicProcedureInfo.ContainsKey(callCmd.Proc));
+ var atomicProcedureInfo = procToAtomicProcedureInfo[callCmd.Proc];
+ if (atomicProcedureInfo.isPure)
+ {
+ return pureCallLayer[callCmd] <= layerNum;
+ }
+ else
+ {
+ return enclosingProcLayerNum == layerNum;
+ }
+ }
+
+ private static List<int> FindLayers(QKeyValue kv)
+ {
+ List<int> layers = new List<int>();
+ for (; kv != null; kv = kv.Next)
+ {
+ if (kv.Key != "layer") continue;
+ foreach (var o in kv.Params)
+ {
+ Expr e = o as Expr;
+ if (e == null) return null;
+ LiteralExpr l = e as LiteralExpr;
+ if (l == null) return null;
+ if (!l.isBigNum) return null;
+ layers.Add(l.asBigNum.ToIntSafe);
+ }
+ }
+ return layers;
+ }
+
+ private static int Least(IEnumerable<int> layerNums)
+ {
+ int least = int.MaxValue;
+ foreach (var layer in layerNums)
+ {
+ if (layer < least)
+ {
+ least = layer;
+ }
+ }
+ return least;
+ }
+
+ private static MoverType GetMoverType(Ensures e)
+ {
+ if (QKeyValue.FindBoolAttribute(e.Attributes, "atomic"))
+ return MoverType.Atomic;
+ if (QKeyValue.FindBoolAttribute(e.Attributes, "right"))
+ return MoverType.Right;
+ if (QKeyValue.FindBoolAttribute(e.Attributes, "left"))
+ return MoverType.Left;
+ if (QKeyValue.FindBoolAttribute(e.Attributes, "both"))
+ return MoverType.Both;
+ return MoverType.Top;
+ }
+
+ public CivlTypeChecker(Program program)
+ {
+ this.errorCount = 0;
+ this.checkingContext = new CheckingContext(null);
+ this.program = program;
+ this.enclosingProc = null;
+ this.enclosingImpl = null;
+ this.sharedVarsAccessed = null;
+ this.introducedLocalVarsUpperBound = int.MinValue;
+
+ this.localVarToLocalVariableInfo = new Dictionary<Variable, LocalVariableInfo>();
+ this.absyToLayerNums = new Dictionary<Absy, HashSet<int>>();
+ this.globalVarToSharedVarInfo = new Dictionary<Variable, SharedVariableInfo>();
+ this.procToActionInfo = new Dictionary<Procedure, ActionInfo>();
+ this.procToAtomicProcedureInfo = new Dictionary<Procedure, AtomicProcedureInfo>();
+ this.pureCallLayer = new Dictionary<CallCmd, int>();
+
+ foreach (var g in program.GlobalVariables)
+ {
+ List<int> layerNums = FindLayers(g.Attributes);
+ if (layerNums.Count == 0)
+ {
+ // Inaccessible from yielding and atomic procedures
+ }
+ else if (layerNums.Count == 1)
+ {
+ this.globalVarToSharedVarInfo[g] = new SharedVariableInfo(layerNums[0], int.MaxValue);
+ }
+ else if (layerNums.Count == 2)
+ {
+ this.globalVarToSharedVarInfo[g] = new SharedVariableInfo(layerNums[0], layerNums[1]);
+ }
+ else
+ {
+ Error(g, "Too many layer numbers");
+ }
+ }
+ }
+
+ private HashSet<int> allLayerNums;
+ public IEnumerable<int> AllLayerNums
+ {
+ get
+ {
+ if (allLayerNums == null)
+ {
+ allLayerNums = new HashSet<int>();
+ foreach (ActionInfo actionInfo in procToActionInfo.Values)
+ {
+ allLayerNums.Add(actionInfo.createdAtLayerNum);
+ }
+ foreach (var layerNums in absyToLayerNums.Values)
+ {
+ foreach (var layer in layerNums)
+ {
+ allLayerNums.Add(layer);
+ }
+ }
+ }
+ return allLayerNums;
+ }
+ }
+
+ private LayerRange FindLayerRange()
+ {
+ int maxIntroLayerNum = int.MinValue;
+ int minHideLayerNum = int.MaxValue;
+ foreach (var g in sharedVarsAccessed)
+ {
+ if (globalVarToSharedVarInfo[g].introLayerNum > maxIntroLayerNum)
+ {
+ maxIntroLayerNum = globalVarToSharedVarInfo[g].introLayerNum;
+ }
+ if (globalVarToSharedVarInfo[g].hideLayerNum < minHideLayerNum)
+ {
+ minHideLayerNum = globalVarToSharedVarInfo[g].hideLayerNum;
+ }
+ }
+ return new LayerRange(maxIntroLayerNum, minHideLayerNum);
+ }
+
+ public void TypeCheck()
+ {
+ foreach (var proc in program.Procedures)
+ {
+ if (!QKeyValue.FindBoolAttribute(proc.Attributes, "pure")) continue;
+ if (QKeyValue.FindBoolAttribute(proc.Attributes, "yields"))
+ {
+ Error(proc, "Pure procedure must not yield");
+ continue;
+ }
+ if (QKeyValue.FindBoolAttribute(proc.Attributes, "layer"))
+ {
+ Error(proc, "Pure procedure must not have layers");
+ continue;
+ }
+ if (proc.Modifies.Count > 0)
+ {
+ Error(proc, "Pure procedure must not modify a global variable");
+ continue;
+ }
+ procToAtomicProcedureInfo[proc] = new AtomicProcedureInfo();
+ }
+ foreach (var proc in program.Procedures)
+ {
+ if (QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) continue;
+ var procLayerNums = FindLayers(proc.Attributes);
+ if (procLayerNums.Count == 0) continue;
+ foreach (IdentifierExpr ie in proc.Modifies)
+ {
+ if (!globalVarToSharedVarInfo.ContainsKey(ie.Decl))
+ {
+ Error(proc, "Atomic procedure cannot modify a global variable without layer numbers");
+ continue;
+ }
+ }
+ int lower, upper;
+ if (procLayerNums.Count == 1)
+ {
+ lower = procLayerNums[0];
+ upper = procLayerNums[0];
+ }
+ else if (procLayerNums.Count == 2)
+ {
+ lower = procLayerNums[0];
+ upper = procLayerNums[1];
+ if (lower >= upper)
+ {
+ Error(proc, "Lower layer must be less than upper layer");
+ continue;
+ }
+ }
+ else
+ {
+ Error(proc, "Atomic procedure must specify a layer range");
+ continue;
+ }
+ LayerRange layerRange = new LayerRange(lower, upper);
+ procToAtomicProcedureInfo[proc] = new AtomicProcedureInfo(layerRange);
+ }
+ if (errorCount > 0) return;
+
+ foreach (Implementation impl in program.Implementations)
+ {
+ if (!procToAtomicProcedureInfo.ContainsKey(impl.Proc)) continue;
+ var atomicProcedureInfo = procToAtomicProcedureInfo[impl.Proc];
+ if (atomicProcedureInfo.isPure)
+ {
+ this.enclosingImpl = impl;
+ (new PurityChecker(this)).VisitImplementation(impl);
+ }
+ else
+ {
+ this.enclosingImpl = impl;
+ this.sharedVarsAccessed = new HashSet<Variable>();
+ (new PurityChecker(this)).VisitImplementation(impl);
+ LayerRange upperBound = FindLayerRange();
+ LayerRange lowerBound = atomicProcedureInfo.layerRange;
+ if (!lowerBound.Subset(upperBound))
+ {
+ Error(impl, "Atomic procedure cannot access global variable");
+ }
+ this.sharedVarsAccessed = null;
+ }
+ }
+ if (errorCount > 0) return;
+
+ foreach (var proc in program.Procedures)
+ {
+ if (!QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) continue;
+
+ int createdAtLayerNum; // must be initialized by the following code, otherwise it is an error
+ int availableUptoLayerNum = int.MaxValue;
+ List<int> attrs = FindLayers(proc.Attributes);
+ if (attrs.Count == 1)
+ {
+ createdAtLayerNum = attrs[0];
+ }
+ else if (attrs.Count == 2)
+ {
+ createdAtLayerNum = attrs[0];
+ availableUptoLayerNum = attrs[1];
+ }
+ else
+ {
+ Error(proc, "Incorrect number of layers");
+ continue;
+ }
+ foreach (Ensures e in proc.Ensures)
+ {
+ MoverType moverType = GetMoverType(e);
+ if (moverType == MoverType.Top) continue;
+ CodeExpr codeExpr = e.Condition as CodeExpr;
+ if (codeExpr == null)
+ {
+ Error(e, "An atomic action must be a CodeExpr");
+ continue;
+ }
+ if (procToActionInfo.ContainsKey(proc))
+ {
+ Error(proc, "A procedure can have at most one atomic action");
+ continue;
+ }
+ if (availableUptoLayerNum <= createdAtLayerNum)
+ {
+ Error(proc, "Creation layer number must be less than the available upto layer number");
+ continue;
+ }
+
+ sharedVarsAccessed = new HashSet<Variable>();
+ enclosingProc = proc;
+ enclosingImpl = null;
+ base.VisitEnsures(e);
+ LayerRange upperBound = FindLayerRange();
+ LayerRange lowerBound = new LayerRange(createdAtLayerNum, availableUptoLayerNum);
+ if (lowerBound.Subset(upperBound))
+ {
+ procToActionInfo[proc] = new AtomicActionInfo(proc, e, moverType, createdAtLayerNum, availableUptoLayerNum);
+ }
+ else
+ {
+ Error(e, "A variable being accessed in this action is unavailable");
+ }
+ sharedVarsAccessed = null;
+ }
+ if (errorCount > 0) continue;
+ if (!procToActionInfo.ContainsKey(proc))
+ {
+ if (availableUptoLayerNum < createdAtLayerNum)
+ {
+ Error(proc, "Creation layer number must be no more than the available upto layer number");
+ continue;
+ }
+ else
+ {
+ procToActionInfo[proc] = new ActionInfo(proc, createdAtLayerNum, availableUptoLayerNum);
+ }
+ }
+ }
+ if (errorCount > 0) return;
+
+ foreach (var impl in program.Implementations)
+ {
+ if (!procToActionInfo.ContainsKey(impl.Proc)) continue;
+ ActionInfo actionInfo = procToActionInfo[impl.Proc];
+ procToActionInfo[impl.Proc].hasImplementation = true;
+ if (actionInfo.isExtern)
+ {
+ Error(impl.Proc, "Extern procedure cannot have an implementation");
+ }
+ }
+ if (errorCount > 0) return;
+
+ foreach (Procedure proc in procToActionInfo.Keys)
+ {
+ for (int i = 0; i < proc.InParams.Count; i++)
+ {
+ Variable v = proc.InParams[i];
+ var layer = FindLocalVariableLayer(proc, v, procToActionInfo[proc].createdAtLayerNum);
+ if (layer == int.MinValue) continue;
+ localVarToLocalVariableInfo[v] = new LocalVariableInfo(layer);
+ }
+ for (int i = 0; i < proc.OutParams.Count; i++)
+ {
+ Variable v = proc.OutParams[i];
+ var layer = FindLocalVariableLayer(proc, v, procToActionInfo[proc].createdAtLayerNum);
+ if (layer == int.MinValue) continue;
+ localVarToLocalVariableInfo[v] = new LocalVariableInfo(layer);
+ }
+ }
+ foreach (Implementation node in program.Implementations)
+ {
+ if (!procToActionInfo.ContainsKey(node.Proc)) continue;
+ foreach (Variable v in node.LocVars)
+ {
+ var layer = FindLocalVariableLayer(node, v, procToActionInfo[node.Proc].createdAtLayerNum);
+ if (layer == int.MinValue) continue;
+ localVarToLocalVariableInfo[v] = new LocalVariableInfo(layer);
+ }
+ for (int i = 0; i < node.Proc.InParams.Count; i++)
+ {
+ Variable v = node.Proc.InParams[i];
+ if (!localVarToLocalVariableInfo.ContainsKey(v)) continue;
+ var layer = localVarToLocalVariableInfo[v].layer;
+ localVarToLocalVariableInfo[node.InParams[i]] = new LocalVariableInfo(layer);
+ }
+ for (int i = 0; i < node.Proc.OutParams.Count; i++)
+ {
+ Variable v = node.Proc.OutParams[i];
+ if (!localVarToLocalVariableInfo.ContainsKey(v)) continue;
+ var layer = localVarToLocalVariableInfo[v].layer;
+ localVarToLocalVariableInfo[node.OutParams[i]] = new LocalVariableInfo(layer);
+ }
+ }
+ if (errorCount > 0) return;
+
+ this.VisitProgram(program);
+ if (errorCount > 0) return;
+ YieldTypeChecker.PerformYieldSafeCheck(this);
+ new LayerEraser().VisitProgram(program);
+ }
+
+ public IEnumerable<Variable> SharedVariables
+ {
+ get { return this.globalVarToSharedVarInfo.Keys; }
+ }
+
+ private int FindLocalVariableLayer(Declaration decl, Variable v, int enclosingProcLayerNum)
+ {
+ var layers = FindLayers(v.Attributes);
+ if (layers.Count == 0) return int.MinValue;
+ if (layers.Count > 1)
+ {
+ Error(decl, "Incorrect number of layers");
+ return int.MinValue;
+ }
+ if (layers[0] > enclosingProcLayerNum)
+ {
+ Error(decl, "Layer of local variable cannot be greater than the creation layer of enclosing procedure");
+ return int.MinValue;
+ }
+ return layers[0];
+ }
+
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ if (!procToActionInfo.ContainsKey(node.Proc))
+ {
+ return node;
+ }
+ this.enclosingImpl = node;
+ this.enclosingProc = null;
+ return base.VisitImplementation(node);
+ }
+
+ public override Procedure VisitProcedure(Procedure node)
+ {
+ if (!procToActionInfo.ContainsKey(node))
+ {
+ return node;
+ }
+ this.enclosingProc = node;
+ this.enclosingImpl = null;
+ return base.VisitProcedure(node);
+ }
+
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ int enclosingProcLayerNum = procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
+ if (procToActionInfo.ContainsKey(node.Proc))
+ {
+ ActionInfo actionInfo = procToActionInfo[node.Proc];
+ if (node.IsAsync && actionInfo is AtomicActionInfo)
+ {
+ Error(node, "Target of async call cannot be an atomic action");
+ }
+ int calleeLayerNum = procToActionInfo[node.Proc].createdAtLayerNum;
+ if (enclosingProcLayerNum < calleeLayerNum ||
+ (enclosingProcLayerNum == calleeLayerNum && actionInfo is AtomicActionInfo))
+ {
+ Error(node, "The layer of the caller must be greater than the layer of the callee");
+ }
+ else if (enclosingProcLayerNum == calleeLayerNum && enclosingImpl.OutParams.Count > 0)
+ {
+ HashSet<Variable> outParams = new HashSet<Variable>(enclosingImpl.OutParams);
+ foreach (var x in node.Outs)
+ {
+ if (x.Decl is GlobalVariable)
+ {
+ Error(node, "A global variable cannot be used as output argument for this call");
+ }
+ else if (outParams.Contains(x.Decl))
+ {
+ Error(node, "An output variable of the enclosing implementation cannot be used as output argument for this call");
+ }
+ }
+ }
+ if (actionInfo.availableUptoLayerNum < enclosingProcLayerNum)
+ {
+ Error(node, "The callee is not available in the caller procedure");
+ }
+ for (int i = 0; i < node.Ins.Count; i++)
+ {
+ Visit(node.Ins[i]);
+ if (introducedLocalVarsUpperBound != int.MinValue)
+ {
+ var formal = node.Proc.InParams[i];
+ if (!localVarToLocalVariableInfo.ContainsKey(formal) ||
+ introducedLocalVarsUpperBound > localVarToLocalVariableInfo[formal].layer)
+ {
+ Error(node, "An introduced local variable is accessed but not available");
+ }
+ introducedLocalVarsUpperBound = int.MinValue;
+ }
+ }
+ for (int i = 0; i < node.Outs.Count; i++)
+ {
+ var formal = node.Proc.OutParams[i];
+ if (!localVarToLocalVariableInfo.ContainsKey(formal)) continue;
+ var actual = node.Outs[i].Decl;
+ if (localVarToLocalVariableInfo.ContainsKey(actual) &&
+ localVarToLocalVariableInfo[formal].layer <= localVarToLocalVariableInfo[actual].layer)
+ continue;
+ Error(node, "Formal parameter of call must be introduced no later than the actual parameter");
+ }
+ return node;
+ }
+ else if (procToAtomicProcedureInfo.ContainsKey(node.Proc))
+ {
+ var atomicProcedureInfo = procToAtomicProcedureInfo[node.Proc];
+ if (atomicProcedureInfo.isPure)
+ {
+ if (node.Outs.Count > 0)
+ {
+ int inferredLayer = int.MinValue;
+ foreach (var ie in node.Outs)
+ {
+ if (!localVarToLocalVariableInfo.ContainsKey(ie.Decl)) continue;
+ if (inferredLayer < localVarToLocalVariableInfo[ie.Decl].layer)
+ {
+ inferredLayer = localVarToLocalVariableInfo[ie.Decl].layer;
+ }
+ }
+ pureCallLayer[node] = inferredLayer;
+ if (inferredLayer != int.MinValue)
+ {
+ foreach (var ie in node.Outs)
+ {
+ if (!localVarToLocalVariableInfo.ContainsKey(ie.Decl))
+ {
+ Error(node, "Output variable must be introduced");
+ }
+ else if (inferredLayer != localVarToLocalVariableInfo[ie.Decl].layer)
+ {
+ Error(node, "All output variables must be introduced at the same layer");
+ }
+ }
+ }
+ Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
+ foreach (var e in node.Ins)
+ {
+ Visit(e);
+ if (inferredLayer < introducedLocalVarsUpperBound)
+ {
+ Error(node, "An introduced local variable is not accessible");
+ }
+ introducedLocalVarsUpperBound = int.MinValue;
+ }
+ }
+ else
+ {
+ Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
+ int inferredLayer = int.MinValue;
+ foreach (var e in node.Ins)
+ {
+ Visit(e);
+ if (inferredLayer < introducedLocalVarsUpperBound)
+ {
+ inferredLayer = introducedLocalVarsUpperBound;
+ }
+ introducedLocalVarsUpperBound = int.MinValue;
+ }
+ pureCallLayer[node] = inferredLayer;
+ }
+ }
+ else
+ {
+ if (enclosingProcLayerNum != atomicProcedureInfo.layerRange.upperLayerNum)
+ {
+ Error(node, "Creation layer of caller must be the upper bound of the layer range of callee");
+ }
+ foreach (var ie in node.Proc.Modifies)
+ {
+ if (enclosingProcLayerNum != globalVarToSharedVarInfo[ie.Decl].introLayerNum)
+ {
+ Error(node, "Creation layer of caller must be identical to the introduction layer of modified variable");
+ }
+ }
+ foreach (var ie in node.Outs)
+ {
+ if (localVarToLocalVariableInfo.ContainsKey(ie.Decl) &&
+ enclosingProcLayerNum == localVarToLocalVariableInfo[ie.Decl].layer)
+ continue;
+ Error(node, "Output variable must be introduced at the creation layer of caller");
+ }
+ }
+ return node;
+ }
+ else
+ {
+ Error(node, "A yielding procedure can call only atomic or yielding procedures");
+ return node;
+ }
+ }
+
+ public override Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ int enclosingProcLayerNum = procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
+ bool isLeftMover = true;
+ bool isRightMover = true;
+ int maxCalleeLayerNum = 0;
+ int atomicActionCalleeLayerNum = 0;
+ int numAtomicActions = 0;
+ foreach (CallCmd iter in node.CallCmds)
+ {
+ ActionInfo actionInfo = procToActionInfo[iter.Proc];
+ isLeftMover = isLeftMover && actionInfo.IsLeftMover;
+ isRightMover = isRightMover && actionInfo.IsRightMover;
+ if (actionInfo.createdAtLayerNum > maxCalleeLayerNum)
+ {
+ maxCalleeLayerNum = actionInfo.createdAtLayerNum;
+ }
+ if (actionInfo is AtomicActionInfo)
+ {
+ numAtomicActions++;
+ if (atomicActionCalleeLayerNum == 0)
+ {
+ atomicActionCalleeLayerNum = actionInfo.createdAtLayerNum;
+ }
+ else if (atomicActionCalleeLayerNum != actionInfo.createdAtLayerNum)
+ {
+ Error(node, "All atomic actions must be introduced at the same layer");
+ }
+ }
+ }
+ if (numAtomicActions > 1 && !isLeftMover && !isRightMover)
+ {
+ Error(node, "The atomic actions in the parallel call must be all right movers or all left movers");
+ }
+ if (0 < atomicActionCalleeLayerNum && atomicActionCalleeLayerNum < maxCalleeLayerNum)
+ {
+ Error(node, "Atomic actions must be introduced at the highest layer");
+ }
+ return base.VisitParCallCmd(node);
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ if (node.Decl is GlobalVariable)
+ {
+ if (sharedVarsAccessed == null)
+ {
+ Error(node, "Shared variable can be accessed only in atomic actions or specifications");
+ }
+ else if (this.globalVarToSharedVarInfo.ContainsKey(node.Decl))
+ {
+ sharedVarsAccessed.Add(node.Decl);
+ }
+ else
+ {
+ Error(node, "Accessed shared variable must have layer annotation");
+ }
+ }
+ else if ((node.Decl is Formal || node.Decl is Variable) && localVarToLocalVariableInfo.ContainsKey(node.Decl))
+ {
+ var localVariableInfo = localVarToLocalVariableInfo[node.Decl];
+ if (introducedLocalVarsUpperBound < localVariableInfo.layer)
+ {
+ introducedLocalVarsUpperBound = localVariableInfo.layer;
+ }
+ }
+ return base.VisitIdentifierExpr(node);
+ }
+
+ public override Ensures VisitEnsures(Ensures ensures)
+ {
+ ActionInfo actionInfo = procToActionInfo[enclosingProc];
+ AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
+ if (atomicActionInfo != null && atomicActionInfo.ensures == ensures)
+ {
+ // This case has already been checked
+ }
+ else
+ {
+ sharedVarsAccessed = new HashSet<Variable>();
+ Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
+ base.VisitEnsures(ensures);
+ CheckAndAddLayers(ensures, ensures.Attributes, actionInfo.createdAtLayerNum);
+ if (introducedLocalVarsUpperBound > Least(FindLayers(ensures.Attributes)))
+ {
+ Error(ensures, "An introduced local variable is accessed but not available");
+ }
+ introducedLocalVarsUpperBound = int.MinValue;
+ sharedVarsAccessed = null;
+ }
+ return ensures;
+ }
+
+ public override Requires VisitRequires(Requires requires)
+ {
+ sharedVarsAccessed = new HashSet<Variable>();
+ Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
+ base.VisitRequires(requires);
+ CheckAndAddLayers(requires, requires.Attributes, procToActionInfo[enclosingProc].createdAtLayerNum);
+ if (introducedLocalVarsUpperBound > Least(FindLayers(requires.Attributes)))
+ {
+ Error(requires, "An introduced local variable is accessed but not available");
+ }
+ introducedLocalVarsUpperBound = int.MinValue;
+ sharedVarsAccessed = null;
+ return requires;
+ }
+
+ public override Cmd VisitAssertCmd(AssertCmd node)
+ {
+ if (enclosingImpl == null)
+ {
+ // in this case, we are visiting an assert inside a CodeExpr
+ return base.VisitAssertCmd(node);
+ }
+ sharedVarsAccessed = new HashSet<Variable>();
+ Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
+ base.VisitAssertCmd(node);
+ CheckAndAddLayers(node, node.Attributes, procToActionInfo[enclosingImpl.Proc].createdAtLayerNum);
+ if (introducedLocalVarsUpperBound > Least(FindLayers(node.Attributes)))
+ {
+ Error(node, "An introduced local variable is accessed but not available");
+ }
+ introducedLocalVarsUpperBound = int.MinValue;
+ sharedVarsAccessed = null;
+ return node;
+ }
+
+ private List<int> RemoveDuplicatesAndSort(List<int> attrs)
+ {
+ HashSet<int> layerSet = new HashSet<int>(attrs);
+ List<int> layers = new List<int>(layerSet);
+ layers.Sort();
+ return layers;
+ }
+
+ private void CheckAndAddLayers(Absy node, QKeyValue attributes, int enclosingProcLayerNum)
+ {
+ List<int> attrs = RemoveDuplicatesAndSort(FindLayers(attributes));
+ if (attrs.Count == 0)
+ {
+ Error(node, "layer not present");
+ return;
+ }
+ LayerRange upperBound = FindLayerRange();
+ absyToLayerNums[node] = new HashSet<int>();
+ foreach (int layerNum in attrs)
+ {
+ if (layerNum > enclosingProcLayerNum)
+ {
+ Error(node, "The layer cannot be greater than the layer of enclosing procedure");
+ }
+ else if (upperBound.Contains(layerNum))
+ {
+ absyToLayerNums[node].Add(layerNum);
+ }
+ else
+ {
+ Error(node, string.Format("A variable being accessed in this specification is unavailable at layer {0}", layerNum));
+ }
+ }
+ }
+
+ public void Error(Absy node, string message)
+ {
+ checkingContext.Error(node, message);
+ errorCount++;
+ }
+
+ private class PurityChecker : StandardVisitor
+ {
+ private CivlTypeChecker civlTypeChecker;
+
+ public PurityChecker(CivlTypeChecker civlTypeChecker)
+ {
+ this.civlTypeChecker = civlTypeChecker;
+ }
+
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ Procedure enclosingProc = civlTypeChecker.enclosingImpl.Proc;
+ if (!civlTypeChecker.procToAtomicProcedureInfo.ContainsKey(node.Proc))
+ {
+ civlTypeChecker.Error(node, "Atomic procedure can only call an atomic procedure");
+ return base.VisitCallCmd(node);
+ }
+ var callerInfo = civlTypeChecker.procToAtomicProcedureInfo[enclosingProc];
+ var calleeInfo = civlTypeChecker.procToAtomicProcedureInfo[node.Proc];
+ if (calleeInfo.isPure)
+ {
+ // do nothing
+ }
+ else if (callerInfo.isPure)
+ {
+ civlTypeChecker.Error(node, "Pure procedure can only call pure procedures");
+ }
+ else if (!callerInfo.layerRange.Subset(calleeInfo.layerRange))
+ {
+ civlTypeChecker.Error(node, "Caller layers must be subset of callee layers");
+ }
+ return base.VisitCallCmd(node);
+ }
+
+ public override Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ civlTypeChecker.Error(node, "Atomic procedures cannot make parallel calls");
+ return node;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ Procedure enclosingProc = civlTypeChecker.enclosingImpl.Proc;
+ if (node.Decl is GlobalVariable)
+ {
+ if (civlTypeChecker.procToAtomicProcedureInfo[enclosingProc].isPure)
+ {
+ civlTypeChecker.Error(node, "Pure procedure cannot access global variables");
+ }
+ else if (!civlTypeChecker.globalVarToSharedVarInfo.ContainsKey(node.Decl))
+ {
+ civlTypeChecker.Error(node, "Atomic procedure cannot access a global variable without layer numbers");
+ }
+ else
+ {
+ civlTypeChecker.sharedVarsAccessed.Add(node.Decl);
+ }
+ }
+ return node;
+ }
+ }
+ }
+}
diff --git a/Source/Concurrency/Concurrency.csproj b/Source/Concurrency/Concurrency.csproj
index c245d05a..ac90077c 100644
--- a/Source/Concurrency/Concurrency.csproj
+++ b/Source/Concurrency/Concurrency.csproj
@@ -1,115 +1,115 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{D07B8E38-E172-47F4-AD02-0373014A46D3}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Concurrency</RootNamespace>
- <AssemblyName>Concurrency</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup>
- <StartupObject />
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>TRACE;DEBUG;QED</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <Choose>
- <When Condition="'$(Configuration)' == 'QED'">
- <ItemGroup>
- <Reference Include="Microsoft.Automata">
- <HintPath>..\..\Binaries\Microsoft.Automata.dll</HintPath>
- </Reference>
- </ItemGroup>
- </When>
- <Otherwise>
- </Otherwise>
- </Choose>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="LinearSets.cs" />
- <Compile Include="MoverCheck.cs" />
- <Compile Include="OwickiGries.cs" />
- <Compile Include="Program.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="SimulationRelation.cs" />
- <Compile Include="TypeCheck.cs" />
- <Compile Include="YieldTypeChecker.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="App.config" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{b230a69c-c466-4065-b9c1-84d80e76d802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69a2b0b8-bcac-4101-ae7a-556fcc58c06e}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{fcd3ac7f-9dfd-46c8-ab1e-09f0b0f16dc5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <WCFMetadata Include="Service References\" />
- </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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{D07B8E38-E172-47F4-AD02-0373014A46D3}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Concurrency</RootNamespace>
+ <AssemblyName>BoogieConcurrency</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject />
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;QED</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <Choose>
+ <When Condition="'$(Configuration)' == 'QED'">
+ <ItemGroup>
+ <Reference Include="Microsoft.Automata">
+ <HintPath>..\..\Binaries\Microsoft.Automata.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ </When>
+ <Otherwise>
+ </Otherwise>
+ </Choose>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="LinearSets.cs" />
+ <Compile Include="MoverCheck.cs" />
+ <Compile Include="CivlRefinement.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SimulationRelation.cs" />
+ <Compile Include="CivlTypeChecker.cs" />
+ <Compile Include="YieldTypeChecker.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{b230a69c-c466-4065-b9c1-84d80e76d802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69a2b0b8-bcac-4101-ae7a-556fcc58c06e}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{fcd3ac7f-9dfd-46c8-ab1e-09f0b0f16dc5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <WCFMetadata Include="Service References\" />
+ </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/Concurrency/LinearSets.cs b/Source/Concurrency/LinearSets.cs
index e3891c18..f654b688 100644
--- a/Source/Concurrency/LinearSets.cs
+++ b/Source/Concurrency/LinearSets.cs
@@ -1,1004 +1,1003 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.Boogie;
-using System.Diagnostics;
-
-namespace Microsoft.Boogie
-{
- public class LinearEraser : ReadOnlyVisitor
- {
- private QKeyValue RemoveLinearAttribute(QKeyValue iter)
- {
- if (iter == null) return null;
- iter.Next = RemoveLinearAttribute(iter.Next);
- return (iter.Key == "linear" || iter.Key == "linear_in" || iter.Key == "linear_out") ? iter.Next : iter;
- }
-
- public override Variable VisitVariable(Variable node)
- {
- node.Attributes = RemoveLinearAttribute(node.Attributes);
- return base.VisitVariable(node);
- }
-
- public override Function VisitFunction(Function node)
- {
- node.Attributes = RemoveLinearAttribute(node.Attributes);
- return base.VisitFunction(node);
- }
- }
-
- public enum LinearKind {
- LINEAR,
- LINEAR_IN,
- LINEAR_OUT
- }
-
- public class LinearTypeChecker : ReadOnlyVisitor
- {
- public Program program;
- public int errorCount;
- public CheckingContext checkingContext;
- public Dictionary<string, Dictionary<Type, Function>> domainNameToCollectors;
- private Dictionary<Absy, HashSet<Variable>> availableLinearVars;
- public Dictionary<Variable, LinearQualifier> inParamToLinearQualifier;
- public Dictionary<Variable, string> outParamToDomainName;
- public Dictionary<Variable, string> varToDomainName;
- public Dictionary<Variable, string> globalVarToDomainName;
- public Dictionary<string, LinearDomain> linearDomains;
-
- public LinearTypeChecker(Program program)
- {
- this.program = program;
- this.errorCount = 0;
- this.checkingContext = new CheckingContext(null);
- this.domainNameToCollectors = new Dictionary<string, Dictionary<Type, Function>>();
- this.availableLinearVars = new Dictionary<Absy, HashSet<Variable>>();
- this.inParamToLinearQualifier = new Dictionary<Variable, LinearQualifier>();
- this.outParamToDomainName = new Dictionary<Variable, string>();
- this.varToDomainName = new Dictionary<Variable, string>();
- this.globalVarToDomainName = new Dictionary<Variable, string>();
- this.linearDomains = new Dictionary<string, LinearDomain>();
- }
- public void TypeCheck()
- {
- this.VisitProgram(program);
- foreach (string domainName in domainNameToCollectors.Keys)
- {
- var collectors = domainNameToCollectors[domainName];
- if (collectors.Count == 0) continue;
- this.linearDomains[domainName] = new LinearDomain(program, domainName, collectors);
- }
- Dictionary<Absy, HashSet<Variable>> newAvailableLinearVars = new Dictionary<Absy, HashSet<Variable>>();
- foreach (Absy absy in this.availableLinearVars.Keys)
- {
- HashSet<Variable> vars = new HashSet<Variable>();
- foreach (Variable var in this.availableLinearVars[absy])
- {
- if (var is GlobalVariable) continue;
- string domainName = FindDomainName(var);
- if (this.linearDomains.ContainsKey(domainName))
- {
- vars.Add(var);
- }
- }
- newAvailableLinearVars[absy] = vars;
- }
- this.availableLinearVars = newAvailableLinearVars;
- var temp = new Dictionary<Variable, string>();
- foreach (Variable v in outParamToDomainName.Keys)
- {
- if (linearDomains.ContainsKey(outParamToDomainName[v]))
- temp[v] = outParamToDomainName[v];
- }
- this.outParamToDomainName = temp;
- temp = new Dictionary<Variable, string>();
- foreach (Variable v in varToDomainName.Keys)
- {
- if (linearDomains.ContainsKey(varToDomainName[v]))
- temp[v] = varToDomainName[v];
- }
- this.varToDomainName = temp;
- temp = new Dictionary<Variable, string>();
- foreach (Variable v in globalVarToDomainName.Keys)
- {
- if (linearDomains.ContainsKey(globalVarToDomainName[v]))
- temp[v] = globalVarToDomainName[v];
- }
- this.globalVarToDomainName = temp;
- }
- private void Error(Absy node, string message)
- {
- checkingContext.Error(node, message);
- errorCount++;
- }
- public override Program VisitProgram(Program node)
- {
- foreach (GlobalVariable g in program.GlobalVariables)
- {
- string domainName = FindDomainName(g);
- if (domainName != null)
- {
- globalVarToDomainName[g] = domainName;
- }
- }
- return base.VisitProgram(node);
- }
- public override Function VisitFunction(Function node)
- {
- string domainName = QKeyValue.FindStringAttribute(node.Attributes, "linear");
- if (domainName != null)
- {
- if (!domainNameToCollectors.ContainsKey(domainName))
- {
- domainNameToCollectors[domainName] = new Dictionary<Type, Function>();
- }
- if (node.InParams.Count == 1 && node.OutParams.Count == 1)
- {
- Type inType = node.InParams[0].TypedIdent.Type;
- MapType outType = node.OutParams[0].TypedIdent.Type as MapType;
- if (domainNameToCollectors[domainName].ContainsKey(inType))
- {
- Error(node, string.Format("A collector for domain for input type has already been defined"));
- }
- else if (outType == null || outType.Arguments.Count != 1 || !outType.Result.Equals(Type.Bool))
- {
- Error(node, "Output of a linear domain collector should be of set type");
- }
- else
- {
- domainNameToCollectors[domainName][inType] = node;
- }
- }
- else
- {
- Error(node, "Linear domain collector should have one input and one output parameter");
- }
- }
- return base.VisitFunction(node);
- }
- public override Implementation VisitImplementation(Implementation node)
- {
- node.PruneUnreachableBlocks();
- node.ComputePredecessorsForBlocks();
- GraphUtil.Graph<Block> graph = Program.GraphFromImpl(node);
- graph.ComputeLoops();
-
- HashSet<Variable> start = new HashSet<Variable>(globalVarToDomainName.Keys);
- for (int i = 0; i < node.InParams.Count; i++)
- {
- Variable v = node.Proc.InParams[i];
- string domainName = FindDomainName(v);
- if (domainName != null)
- {
- var kind = FindLinearKind(v);
- inParamToLinearQualifier[node.InParams[i]] = new LinearQualifier(domainName, kind);
- if (kind == LinearKind.LINEAR || kind == LinearKind.LINEAR_IN)
- {
- start.Add(node.InParams[i]);
- }
- }
- }
- for (int i = 0; i < node.OutParams.Count; i++)
- {
- string domainName = FindDomainName(node.Proc.OutParams[i]);
- if (domainName != null)
- {
- outParamToDomainName[node.OutParams[i]] = domainName;
- }
- }
-
- var oldErrorCount = this.errorCount;
- var impl = base.VisitImplementation(node);
- if (oldErrorCount < this.errorCount)
- return impl;
-
- Stack<Block> dfsStack = new Stack<Block>();
- HashSet<Block> dfsStackAsSet = new HashSet<Block>();
- availableLinearVars[node.Blocks[0]] = start;
- dfsStack.Push(node.Blocks[0]);
- dfsStackAsSet.Add(node.Blocks[0]);
- while (dfsStack.Count > 0)
- {
- Block b = dfsStack.Pop();
- dfsStackAsSet.Remove(b);
- HashSet<Variable> end = PropagateAvailableLinearVarsAcrossBlock(b);
- if (b.TransferCmd is ReturnCmd)
- {
- foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(end))
- {
- Error(b.TransferCmd, string.Format("Global variable {0} must be available at a return", g.Name));
- }
- foreach (Variable v in node.InParams)
- {
- if (FindDomainName(v) == null || FindLinearKind(v) == LinearKind.LINEAR_IN || end.Contains(v)) continue;
- Error(b.TransferCmd, string.Format("Input variable {0} must be available at a return", v.Name));
- }
- foreach (Variable v in node.OutParams)
- {
- if (FindDomainName(v) == null || end.Contains(v)) continue;
- Error(b.TransferCmd, string.Format("Output variable {0} must be available at a return", v.Name));
- }
- continue;
- }
- GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
- foreach (Block target in gotoCmd.labelTargets)
- {
- if (!availableLinearVars.ContainsKey(target))
- {
- availableLinearVars[target] = new HashSet<Variable>(end);
- dfsStack.Push(target);
- dfsStackAsSet.Add(target);
- }
- else
- {
- var savedAvailableVars = new HashSet<Variable>(availableLinearVars[target]);
- availableLinearVars[target].IntersectWith(end);
- if (savedAvailableVars.IsProperSupersetOf(availableLinearVars[target]) && !dfsStackAsSet.Contains(target))
- {
- dfsStack.Push(target);
- dfsStackAsSet.Add(target);
- }
- }
- }
- }
-
- if (graph.Reducible)
- {
- foreach (Block header in graph.Headers)
- {
- foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(availableLinearVars[header]))
- {
- Error(header, string.Format("Global variable {0} must be available at a loop head", g.Name));
- }
- }
- }
- return impl;
- }
- public void AddAvailableVars(CallCmd callCmd, HashSet<Variable> start)
- {
- foreach (IdentifierExpr ie in callCmd.Outs)
- {
- if (FindDomainName(ie.Decl) == null) continue;
- start.Add(ie.Decl);
- }
- for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
- {
- IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
- if (ie == null) continue;
- Variable v = callCmd.Proc.InParams[i];
- if (FindDomainName(v) == null) continue;
- if (FindLinearKind(v) == LinearKind.LINEAR_OUT)
- {
- start.Add(ie.Decl);
- }
- }
- }
- public void AddAvailableVars(ParCallCmd parCallCmd, HashSet<Variable> start)
- {
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- AddAvailableVars(callCmd, start);
- }
- }
- private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b) {
- HashSet<Variable> start = new HashSet<Variable>(availableLinearVars[b]);
- foreach (Cmd cmd in b.Cmds)
- {
- if (cmd is AssignCmd)
- {
- AssignCmd assignCmd = (AssignCmd)cmd;
- for (int i = 0; i < assignCmd.Lhss.Count; i++)
- {
- if (FindDomainName(assignCmd.Lhss[i].DeepAssignedVariable) == null) continue;
- IdentifierExpr ie = assignCmd.Rhss[i] as IdentifierExpr;
- if (!start.Contains(ie.Decl))
- {
- Error(ie, "unavailable source for a linear read");
- }
- else
- {
- start.Remove(ie.Decl);
- }
- }
- foreach (AssignLhs assignLhs in assignCmd.Lhss)
- {
- if (FindDomainName(assignLhs.DeepAssignedVariable) == null) continue;
- start.Add(assignLhs.DeepAssignedVariable);
- }
- }
- else if (cmd is CallCmd)
- {
- foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
- {
- Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name));
- }
- CallCmd callCmd = (CallCmd)cmd;
- for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
- {
- Variable param = callCmd.Proc.InParams[i];
- if (FindDomainName(param) == null) continue;
- IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
- LinearKind paramKind = FindLinearKind(param);
- if (start.Contains(ie.Decl))
- {
- if (callCmd.IsAsync || paramKind == LinearKind.LINEAR_IN)
- {
- start.Remove(ie.Decl);
- }
- }
- else
- {
- if (paramKind == LinearKind.LINEAR_OUT)
- {
- start.Add(ie.Decl);
- }
- else
- {
- Error(ie, "unavailable source for a linear read");
- }
- }
- }
- availableLinearVars[callCmd] = new HashSet<Variable>(start);
- AddAvailableVars(callCmd, start);
- }
- else if (cmd is ParCallCmd)
- {
- foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
- {
- Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name));
- }
- ParCallCmd parCallCmd = (ParCallCmd)cmd;
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
- {
- Variable param = callCmd.Proc.InParams[i];
- if (FindDomainName(param) == null) continue;
- IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
- LinearKind paramKind = FindLinearKind(param);
- if (start.Contains(ie.Decl))
- {
- if (paramKind == LinearKind.LINEAR_IN)
- {
- start.Remove(ie.Decl);
- }
- }
- else
- {
- if (paramKind == LinearKind.LINEAR_OUT)
- {
- start.Add(ie.Decl);
- }
- else
- {
- Error(ie, "unavailable source for a linear read");
- }
- }
- }
- }
- availableLinearVars[parCallCmd] = new HashSet<Variable>(start);
- AddAvailableVars(parCallCmd, start);
- }
- else if (cmd is HavocCmd)
- {
- HavocCmd havocCmd = (HavocCmd)cmd;
- foreach (IdentifierExpr ie in havocCmd.Vars)
- {
- if (FindDomainName(ie.Decl) == null) continue;
- start.Remove(ie.Decl);
- }
- }
- else if (cmd is YieldCmd)
- {
- foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
- {
- Error(cmd, string.Format("Global variable {0} must be available at a yield", g.Name));
- }
- availableLinearVars[cmd] = new HashSet<Variable>(start);
- }
- }
- return start;
- }
- public string FindDomainName(Variable v)
- {
- if (globalVarToDomainName.ContainsKey(v))
- return globalVarToDomainName[v];
- if (inParamToLinearQualifier.ContainsKey(v))
- return inParamToLinearQualifier[v].domainName;
- if (outParamToDomainName.ContainsKey(v))
- return outParamToDomainName[v];
- string domainName = QKeyValue.FindStringAttribute(v.Attributes, "linear");
- if (domainName != null)
- return domainName;
- domainName = QKeyValue.FindStringAttribute(v.Attributes, "linear_in");
- if (domainName != null)
- return domainName;
- return QKeyValue.FindStringAttribute(v.Attributes, "linear_out");
- }
- public LinearKind FindLinearKind(Variable v)
- {
- if (globalVarToDomainName.ContainsKey(v))
- return LinearKind.LINEAR;
- if (inParamToLinearQualifier.ContainsKey(v))
- return inParamToLinearQualifier[v].kind;
- if (outParamToDomainName.ContainsKey(v))
- return LinearKind.LINEAR;
-
- if (QKeyValue.FindStringAttribute(v.Attributes, "linear") != null)
- {
- return LinearKind.LINEAR;
- }
- else if (QKeyValue.FindStringAttribute(v.Attributes, "linear_in") != null)
- {
- return LinearKind.LINEAR_IN;
- }
- else if (QKeyValue.FindStringAttribute(v.Attributes, "linear_out") != null)
- {
- return LinearKind.LINEAR_OUT;
- }
- else
- {
- Debug.Assert(false);
- return LinearKind.LINEAR;
- }
- }
- public override Variable VisitVariable(Variable node)
- {
- string domainName = FindDomainName(node);
- if (domainName != null)
- {
- if (!domainNameToCollectors.ContainsKey(domainName))
- {
- domainNameToCollectors[domainName] = new Dictionary<Type,Function>();
- }
- LinearKind kind = FindLinearKind(node);
- if (kind != LinearKind.LINEAR)
- {
- if (node is GlobalVariable || node is LocalVariable || (node is Formal && !(node as Formal).InComing))
- {
- Error(node, "Variable must be declared linear (as opposed to linear_in or linear_out)");
- }
- }
- }
- return base.VisitVariable(node);
- }
- public override Cmd VisitAssignCmd(AssignCmd node)
- {
- HashSet<Variable> rhsVars = new HashSet<Variable>();
- for (int i = 0; i < node.Lhss.Count; i++)
- {
- AssignLhs lhs = node.Lhss[i];
- Variable lhsVar = lhs.DeepAssignedVariable;
- string domainName = FindDomainName(lhsVar);
- if (domainName == null) continue;
- SimpleAssignLhs salhs = lhs as SimpleAssignLhs;
- if (salhs == null)
- {
- Error(node, string.Format("Only simple assignment allowed on linear variable {0}", lhsVar.Name));
- continue;
- }
- IdentifierExpr rhs = node.Rhss[i] as IdentifierExpr;
- if (rhs == null)
- {
- Error(node, string.Format("Only variable can be assigned to linear variable {0}", lhsVar.Name));
- continue;
- }
- string rhsDomainName = FindDomainName(rhs.Decl);
- if (rhsDomainName == null)
- {
- Error(node, string.Format("Only linear variable can be assigned to linear variable {0}", lhsVar.Name));
- continue;
- }
- if (domainName != rhsDomainName)
- {
- Error(node, string.Format("Linear variable of domain {0} cannot be assigned to linear variable of domain {1}", rhsDomainName, domainName));
- continue;
- }
- if (rhsVars.Contains(rhs.Decl))
- {
- Error(node, string.Format("Linear variable {0} can occur only once in the right-hand-side of an assignment", rhs.Decl.Name));
- continue;
- }
- rhsVars.Add(rhs.Decl);
- }
- return base.VisitAssignCmd(node);
- }
- public override Cmd VisitCallCmd(CallCmd node)
- {
- HashSet<Variable> inVars = new HashSet<Variable>();
- for (int i = 0; i < node.Proc.InParams.Count; i++)
- {
- Variable formal = node.Proc.InParams[i];
- string domainName = FindDomainName(formal);
- if (domainName == null) continue;
- IdentifierExpr actual = node.Ins[i] as IdentifierExpr;
- if (actual == null)
- {
- Error(node, string.Format("Only variable can be passed to linear parameter {0}", formal.Name));
- continue;
- }
- string actualDomainName = FindDomainName(actual.Decl);
- if (actualDomainName == null)
- {
- Error(node, string.Format("Only a linear argument can be passed to linear parameter {0}", formal.Name));
- continue;
- }
- if (domainName != actualDomainName)
- {
- Error(node, "The domains of formal and actual parameters must be the same");
- continue;
- }
- if (actual.Decl is GlobalVariable)
- {
- Error(node, "Only local linear variable can be an actual input parameter of a procedure call");
- continue;
- }
- if (inVars.Contains(actual.Decl))
- {
- Error(node, string.Format("Linear variable {0} can occur only once as an input parameter", actual.Decl.Name));
- continue;
- }
- inVars.Add(actual.Decl);
- }
- for (int i = 0; i < node.Proc.OutParams.Count; i++)
- {
- IdentifierExpr actual = node.Outs[i];
- string actualDomainName = FindDomainName(actual.Decl);
- if (actualDomainName == null) continue;
- Variable formal = node.Proc.OutParams[i];
- string domainName = FindDomainName(formal);
- if (domainName == null)
- {
- Error(node, "Only a linear variable can be passed to a linear parameter");
- continue;
- }
- if (domainName != actualDomainName)
- {
- Error(node, "The domains of formal and actual parameters must be the same");
- continue;
- }
- if (actual.Decl is GlobalVariable)
- {
- Error(node, "Only local linear variable can be actual output parameter of a procedure call");
- continue;
- }
- }
- return base.VisitCallCmd(node);
- }
- public override Cmd VisitParCallCmd(ParCallCmd node)
- {
- HashSet<Variable> parallelCallInvars = new HashSet<Variable>();
- foreach (CallCmd callCmd in node.CallCmds)
- {
- for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
- {
- Variable formal = callCmd.Proc.InParams[i];
- string domainName = FindDomainName(formal);
- if (domainName == null) continue;
- IdentifierExpr actual = callCmd.Ins[i] as IdentifierExpr;
- if (parallelCallInvars.Contains(actual.Decl))
- {
- Error(node, string.Format("Linear variable {0} can occur only once as an input parameter of a parallel call", actual.Decl.Name));
- }
- else
- {
- parallelCallInvars.Add(actual.Decl);
- }
- }
- }
- return base.VisitParCallCmd(node);
- }
-
- public override Requires VisitRequires(Requires requires)
- {
- return requires;
- }
-
- public override Ensures VisitEnsures(Ensures ensures)
- {
- return ensures;
- }
-
- public IEnumerable<Variable> AvailableLinearVars(Absy absy)
- {
- if (availableLinearVars.ContainsKey(absy))
- {
- return availableLinearVars[absy];
- }
- else
- {
- return new HashSet<Variable>();
- }
- }
-
- private void AddDisjointnessExpr(List<Cmd> newCmds, Absy absy, Dictionary<string, Variable> domainNameToInputVar)
- {
- Dictionary<string, HashSet<Variable>> domainNameToScope = new Dictionary<string, HashSet<Variable>>();
- foreach (var domainName in linearDomains.Keys)
- {
- domainNameToScope[domainName] = new HashSet<Variable>();
- }
- foreach (Variable v in AvailableLinearVars(absy))
- {
- var domainName = FindDomainName(v);
- domainNameToScope[domainName].Add(v);
- }
- foreach (Variable v in program.GlobalVariables)
- {
- var domainName = FindDomainName(v);
- if (domainName == null) continue;
- domainNameToScope[domainName].Add(v);
- }
- foreach (string domainName in linearDomains.Keys)
- {
- newCmds.Add(new AssumeCmd(Token.NoToken, DisjointnessExpr(domainName, domainNameToInputVar[domainName], domainNameToScope[domainName])));
- }
- }
-
- public void Transform()
- {
- foreach (var impl in program.Implementations)
- {
- Dictionary<string, Variable> domainNameToInputVar = new Dictionary<string, Variable>();
- foreach (string domainName in linearDomains.Keys)
- {
- var domain = linearDomains[domainName];
- Formal f = new Formal(
- Token.NoToken,
- new TypedIdent(Token.NoToken,
- "linear_" + domainName + "_in",
- new MapType(Token.NoToken, new List<TypeVariable>(),
- new List<Type> { domain.elementType }, Type.Bool)), true);
- impl.InParams.Add(f);
- domainNameToInputVar[domainName] = f;
- }
-
- foreach (Block b in impl.Blocks)
- {
- List<Cmd> newCmds = new List<Cmd>();
- for (int i = 0; i < b.Cmds.Count; i++)
- {
- Cmd cmd = b.Cmds[i];
- newCmds.Add(cmd);
- if (cmd is CallCmd)
- {
- CallCmd callCmd = cmd as CallCmd;
- if (callCmd.IsAsync)
- {
- foreach (var domainName in linearDomains.Keys)
- {
- var domain = linearDomains[domainName];
- var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.False });
- expr.Resolve(new ResolutionContext(null));
- expr.Typecheck(new TypecheckingContext(null));
- callCmd.Ins.Add(expr);
- }
- }
- else
- {
- Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
- foreach (var domainName in linearDomains.Keys)
- {
- domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]);
- }
- foreach (Variable v in AvailableLinearVars(callCmd))
- {
- var domainName = FindDomainName(v);
- var domain = linearDomains[domainName];
- if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
- Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
- var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
- expr.Resolve(new ResolutionContext(null));
- expr.Typecheck(new TypecheckingContext(null));
- domainNameToExpr[domainName] = expr;
- }
- foreach (var domainName in linearDomains.Keys)
- {
- callCmd.Ins.Add(domainNameToExpr[domainName]);
- }
- }
- }
- else if (cmd is ParCallCmd)
- {
- ParCallCmd parCallCmd = (ParCallCmd)cmd;
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- foreach (var domainName in linearDomains.Keys)
- {
- var domain = linearDomains[domainName];
- var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.False });
- expr.Resolve(new ResolutionContext(null));
- expr.Typecheck(new TypecheckingContext(null));
- callCmd.Ins.Add(expr);
- }
- }
- }
- else if (cmd is YieldCmd)
- {
- AddDisjointnessExpr(newCmds, cmd, domainNameToInputVar);
- }
- }
- b.Cmds = newCmds;
- }
-
- {
- // Loops
- impl.PruneUnreachableBlocks();
- impl.ComputePredecessorsForBlocks();
- GraphUtil.Graph<Block> g = Program.GraphFromImpl(impl);
- g.ComputeLoops();
- if (g.Reducible)
- {
- foreach (Block header in g.Headers)
- {
- List<Cmd> newCmds = new List<Cmd>();
- AddDisjointnessExpr(newCmds, header, domainNameToInputVar);
- newCmds.AddRange(header.Cmds);
- header.Cmds = newCmds;
- }
- }
- }
- }
-
- foreach (var proc in program.Procedures)
- {
- Dictionary<string, HashSet<Variable>> domainNameToInputScope = new Dictionary<string, HashSet<Variable>>();
- Dictionary<string, HashSet<Variable>> domainNameToOutputScope = new Dictionary<string, HashSet<Variable>>();
- foreach (var domainName in linearDomains.Keys)
- {
- domainNameToInputScope[domainName] = new HashSet<Variable>();
- domainNameToOutputScope[domainName] = new HashSet<Variable>();
-
- }
- foreach (Variable v in globalVarToDomainName.Keys)
- {
- var domainName = globalVarToDomainName[v];
- domainNameToInputScope[domainName].Add(v);
- domainNameToOutputScope[domainName].Add(v);
- }
- foreach (Variable v in proc.InParams)
- {
- var domainName = FindDomainName(v);
- if (domainName == null) continue;
- if (!this.linearDomains.ContainsKey(domainName)) continue;
- domainNameToInputScope[domainName].Add(v);
- }
- foreach (Variable v in proc.OutParams)
- {
- var domainName = FindDomainName(v);
- if (domainName == null) continue;
- if (!this.linearDomains.ContainsKey(domainName)) continue;
- domainNameToOutputScope[domainName].Add(v);
- }
- foreach (var domainName in linearDomains.Keys)
- {
- proc.Requires.Add(new Requires(true, DisjointnessExpr(domainName, domainNameToInputScope[domainName])));
- var domain = linearDomains[domainName];
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
- proc.InParams.Add(f);
- proc.Ensures.Add(new Ensures(true, DisjointnessExpr(domainName, f, domainNameToOutputScope[domainName])));
- }
- }
-
- foreach (LinearDomain domain in linearDomains.Values)
- {
- program.AddTopLevelDeclaration(domain.mapConstBool);
- program.AddTopLevelDeclaration(domain.mapConstInt);
- program.AddTopLevelDeclaration(domain.mapEqInt);
- program.AddTopLevelDeclaration(domain.mapImpBool);
- program.AddTopLevelDeclaration(domain.mapOrBool);
- foreach (Axiom axiom in domain.axioms)
- {
- program.AddTopLevelDeclaration(axiom);
- }
- }
-
- //int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
- //CommandLineOptions.Clo.PrintUnstructured = 1;
- //PrintBplFile("lsd.bpl", program, false, false);
- //CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
- }
-
- private Expr SubsetExpr(LinearDomain domain, Expr ie, Variable partition, int partitionCount)
- {
- Expr e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstInt), new List<Expr> { new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(partitionCount)) });
- e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapEqInt), new List<Expr> { Expr.Ident(partition), e });
- e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapImpBool), new List<Expr> { ie, e });
- e = Expr.Eq(e, new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.True }));
- return e;
- }
-
- private Expr SubsetExprs(LinearDomain domain, HashSet<Variable> scope, Variable partition, int count, Expr expr)
- {
- foreach (Variable v in scope)
- {
- if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
- Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
- expr = Expr.And(SubsetExpr(domain, ie, partition, count), expr);
- count++;
- }
- expr = new ExistsExpr(Token.NoToken, new List<Variable> { partition }, expr);
- expr.Resolve(new ResolutionContext(null));
- expr.Typecheck(new TypecheckingContext(null));
- return expr;
- }
-
- public Expr DisjointnessExpr(string domainName, Variable inputVar, HashSet<Variable> scope)
- {
- LinearDomain domain = linearDomains[domainName];
- BoundVariable partition = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("partition_{0}", domainName), new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Microsoft.Boogie.Type.Int)));
- return SubsetExprs(domain, scope, partition, 1, SubsetExpr(domain, Expr.Ident(inputVar), partition, 0));
- }
-
- public Expr DisjointnessExpr(string domainName, HashSet<Variable> scope)
- {
- LinearDomain domain = linearDomains[domainName];
- BoundVariable partition = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("partition_{0}", domainName), new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Microsoft.Boogie.Type.Int)));
- return SubsetExprs(domain, scope, partition, 0, Expr.True);
- }
- }
-
- public class LinearQualifier
- {
- public string domainName;
- public LinearKind kind;
- public LinearQualifier(string domainName, LinearKind kind)
- {
- this.domainName = domainName;
- this.kind = kind;
- }
- }
-
- public class LinearDomain
- {
- public Function mapEqInt;
- public Function mapConstInt;
- public Function mapOrBool;
- public Function mapImpBool;
- public Function mapConstBool;
- public List<Axiom> axioms;
- public Type elementType;
- public Dictionary<Type, Function> collectors;
-
- public LinearDomain(Program program, string domainName, Dictionary<Type, Function> collectors)
- {
- this.axioms = new List<Axiom>();
- this.collectors = collectors;
- MapType setType = (MapType)collectors.First().Value.OutParams[0].TypedIdent.Type;
- this.elementType = setType.Arguments[0];
- MapType mapTypeBool = new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { this.elementType }, Type.Bool);
- MapType mapTypeInt = new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { this.elementType }, Type.Int);
- this.mapOrBool = new Function(Token.NoToken, "linear_" + domainName + "_MapOr",
- new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) },
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
- if (CommandLineOptions.Clo.UseArrayTheory)
- {
- this.mapOrBool.AddAttribute("builtin", "MapOr");
- }
- else
- {
- BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool));
- IdentifierExpr aie = Expr.Ident(a);
- BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool));
- IdentifierExpr bie = Expr.Ident(b);
- BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
- IdentifierExpr xie = Expr.Ident(x);
- var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapOrBool), new List<Expr> { aie, bie } );
- var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie } );
- var rhsTerm = Expr.Or(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie } ),
- new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie} ));
- var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null,
- new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }),
- new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm)));
- axiomExpr.Typecheck(new TypecheckingContext(null));
- axioms.Add(new Axiom(Token.NoToken, axiomExpr));
- }
-
- this.mapImpBool = new Function(Token.NoToken, "linear_" + domainName + "_MapImp",
- new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) },
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
- if (CommandLineOptions.Clo.UseArrayTheory)
- {
- this.mapImpBool.AddAttribute("builtin", "MapImp");
- }
- else
- {
- BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool));
- IdentifierExpr aie = Expr.Ident(a);
- BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool));
- IdentifierExpr bie = Expr.Ident(b);
- BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
- IdentifierExpr xie = Expr.Ident(x);
- var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapImpBool), new List<Expr> { aie, bie });
- var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie });
- var rhsTerm = Expr.Imp(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie }),
- new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie }));
- var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null,
- new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }),
- new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm)));
- axiomExpr.Typecheck(new TypecheckingContext(null));
- axioms.Add(new Axiom(Token.NoToken, axiomExpr));
- }
-
- this.mapConstBool = new Function(Token.NoToken, "linear_" + domainName + "_MapConstBool",
- new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Bool), true) },
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
- if (CommandLineOptions.Clo.UseArrayTheory)
- {
- this.mapConstBool.AddAttribute("builtin", "MapConst");
- }
- else
- {
- BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
- IdentifierExpr xie = Expr.Ident(x);
- var trueTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
- new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List<Expr> { Expr.True }), xie });
- var trueAxiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { x }, trueTerm);
- trueAxiomExpr.Typecheck(new TypecheckingContext(null));
- axioms.Add(new Axiom(Token.NoToken, trueAxiomExpr));
- var falseTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
- new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List<Expr> { Expr.False }), xie });
- var falseAxiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, falseTerm));
- falseAxiomExpr.Typecheck(new TypecheckingContext(null));
- axioms.Add(new Axiom(Token.NoToken, falseAxiomExpr));
- }
-
- this.mapEqInt = new Function(Token.NoToken, "linear_" + domainName + "_MapEq",
- new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt), true) },
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
- if (CommandLineOptions.Clo.UseArrayTheory)
- {
- this.mapEqInt.AddAttribute("builtin", "MapEq");
- }
- else
- {
- BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt));
- IdentifierExpr aie = Expr.Ident(a);
- BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt));
- IdentifierExpr bie = Expr.Ident(b);
- BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
- IdentifierExpr xie = Expr.Ident(x);
- var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapEqInt), new List<Expr> { aie, bie });
- var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie });
- var rhsTerm = Expr.Eq(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie }),
- new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie }));
- var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null,
- new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }),
- new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm)));
- axiomExpr.Typecheck(new TypecheckingContext(null));
- axioms.Add(new Axiom(Token.NoToken, axiomExpr));
- }
-
- this.mapConstInt = new Function(Token.NoToken, "linear_" + domainName + "_MapConstInt",
- new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Int), true) },
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeInt), false));
- if (CommandLineOptions.Clo.UseArrayTheory)
- {
- this.mapConstInt.AddAttribute("builtin", "MapConst");
- }
- else
- {
- BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", Type.Int));
- IdentifierExpr aie = Expr.Ident(a);
- BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
- IdentifierExpr xie = Expr.Ident(x);
- var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstInt), new List<Expr> { aie }), xie });
- var axiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { a, x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, aie));
- axiomExpr.Typecheck(new TypecheckingContext(null));
- axioms.Add(new Axiom(Token.NoToken, axiomExpr));
- }
-
- foreach (var axiom in axioms)
- {
- axiom.Expr.Resolve(new ResolutionContext(null));
- axiom.Expr.Typecheck(new TypecheckingContext(null));
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Boogie;
+using System.Diagnostics;
+
+namespace Microsoft.Boogie
+{
+ public class LinearEraser : ReadOnlyVisitor
+ {
+ private QKeyValue RemoveLinearAttribute(QKeyValue iter)
+ {
+ if (iter == null) return null;
+ iter.Next = RemoveLinearAttribute(iter.Next);
+ return (iter.Key == "linear" || iter.Key == "linear_in" || iter.Key == "linear_out") ? iter.Next : iter;
+ }
+
+ public override Variable VisitVariable(Variable node)
+ {
+ node.Attributes = RemoveLinearAttribute(node.Attributes);
+ return base.VisitVariable(node);
+ }
+
+ public override Function VisitFunction(Function node)
+ {
+ node.Attributes = RemoveLinearAttribute(node.Attributes);
+ return base.VisitFunction(node);
+ }
+ }
+
+ public enum LinearKind {
+ LINEAR,
+ LINEAR_IN,
+ LINEAR_OUT
+ }
+
+ public class LinearTypeChecker : ReadOnlyVisitor
+ {
+ public Program program;
+ public int errorCount;
+ public CheckingContext checkingContext;
+ public Dictionary<string, Dictionary<Type, Function>> domainNameToCollectors;
+ private Dictionary<Absy, HashSet<Variable>> availableLinearVars;
+ public Dictionary<Variable, LinearQualifier> inParamToLinearQualifier;
+ public Dictionary<Variable, string> outParamToDomainName;
+ public Dictionary<Variable, string> varToDomainName;
+ public Dictionary<Variable, string> globalVarToDomainName;
+ public Dictionary<string, LinearDomain> linearDomains;
+
+ public LinearTypeChecker(Program program)
+ {
+ this.program = program;
+ this.errorCount = 0;
+ this.checkingContext = new CheckingContext(null);
+ this.domainNameToCollectors = new Dictionary<string, Dictionary<Type, Function>>();
+ this.availableLinearVars = new Dictionary<Absy, HashSet<Variable>>();
+ this.inParamToLinearQualifier = new Dictionary<Variable, LinearQualifier>();
+ this.outParamToDomainName = new Dictionary<Variable, string>();
+ this.varToDomainName = new Dictionary<Variable, string>();
+ this.globalVarToDomainName = new Dictionary<Variable, string>();
+ this.linearDomains = new Dictionary<string, LinearDomain>();
+ }
+ public void TypeCheck()
+ {
+ this.VisitProgram(program);
+ foreach (string domainName in domainNameToCollectors.Keys)
+ {
+ var collectors = domainNameToCollectors[domainName];
+ if (collectors.Count == 0) continue;
+ this.linearDomains[domainName] = new LinearDomain(program, domainName, collectors);
+ }
+ Dictionary<Absy, HashSet<Variable>> newAvailableLinearVars = new Dictionary<Absy, HashSet<Variable>>();
+ foreach (Absy absy in this.availableLinearVars.Keys)
+ {
+ HashSet<Variable> vars = new HashSet<Variable>();
+ foreach (Variable var in this.availableLinearVars[absy])
+ {
+ if (var is GlobalVariable) continue;
+ string domainName = FindDomainName(var);
+ if (this.linearDomains.ContainsKey(domainName))
+ {
+ vars.Add(var);
+ }
+ }
+ newAvailableLinearVars[absy] = vars;
+ }
+ this.availableLinearVars = newAvailableLinearVars;
+ var temp = new Dictionary<Variable, string>();
+ foreach (Variable v in outParamToDomainName.Keys)
+ {
+ if (linearDomains.ContainsKey(outParamToDomainName[v]))
+ temp[v] = outParamToDomainName[v];
+ }
+ this.outParamToDomainName = temp;
+ temp = new Dictionary<Variable, string>();
+ foreach (Variable v in varToDomainName.Keys)
+ {
+ if (linearDomains.ContainsKey(varToDomainName[v]))
+ temp[v] = varToDomainName[v];
+ }
+ this.varToDomainName = temp;
+ temp = new Dictionary<Variable, string>();
+ foreach (Variable v in globalVarToDomainName.Keys)
+ {
+ if (linearDomains.ContainsKey(globalVarToDomainName[v]))
+ temp[v] = globalVarToDomainName[v];
+ }
+ this.globalVarToDomainName = temp;
+ }
+ private void Error(Absy node, string message)
+ {
+ checkingContext.Error(node, message);
+ errorCount++;
+ }
+ public override Program VisitProgram(Program node)
+ {
+ foreach (GlobalVariable g in program.GlobalVariables)
+ {
+ string domainName = FindDomainName(g);
+ if (domainName != null)
+ {
+ globalVarToDomainName[g] = domainName;
+ }
+ }
+ return base.VisitProgram(node);
+ }
+ public override Function VisitFunction(Function node)
+ {
+ string domainName = QKeyValue.FindStringAttribute(node.Attributes, "linear");
+ if (domainName != null)
+ {
+ if (!domainNameToCollectors.ContainsKey(domainName))
+ {
+ domainNameToCollectors[domainName] = new Dictionary<Type, Function>();
+ }
+ if (node.InParams.Count == 1 && node.OutParams.Count == 1)
+ {
+ Type inType = node.InParams[0].TypedIdent.Type;
+ MapType outType = node.OutParams[0].TypedIdent.Type as MapType;
+ if (domainNameToCollectors[domainName].ContainsKey(inType))
+ {
+ Error(node, string.Format("A collector for domain for input type has already been defined"));
+ }
+ else if (outType == null || outType.Arguments.Count != 1 || !outType.Result.Equals(Type.Bool))
+ {
+ Error(node, "Output of a linear domain collector should be of set type");
+ }
+ else
+ {
+ domainNameToCollectors[domainName][inType] = node;
+ }
+ }
+ else
+ {
+ Error(node, "Linear domain collector should have one input and one output parameter");
+ }
+ }
+ return base.VisitFunction(node);
+ }
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ node.PruneUnreachableBlocks();
+ node.ComputePredecessorsForBlocks();
+ GraphUtil.Graph<Block> graph = Program.GraphFromImpl(node);
+ graph.ComputeLoops();
+
+ HashSet<Variable> start = new HashSet<Variable>(globalVarToDomainName.Keys);
+ for (int i = 0; i < node.InParams.Count; i++)
+ {
+ Variable v = node.Proc.InParams[i];
+ string domainName = FindDomainName(v);
+ if (domainName != null)
+ {
+ var kind = FindLinearKind(v);
+ inParamToLinearQualifier[node.InParams[i]] = new LinearQualifier(domainName, kind);
+ if (kind == LinearKind.LINEAR || kind == LinearKind.LINEAR_IN)
+ {
+ start.Add(node.InParams[i]);
+ }
+ }
+ }
+ for (int i = 0; i < node.OutParams.Count; i++)
+ {
+ string domainName = FindDomainName(node.Proc.OutParams[i]);
+ if (domainName != null)
+ {
+ outParamToDomainName[node.OutParams[i]] = domainName;
+ }
+ }
+
+ var oldErrorCount = this.errorCount;
+ var impl = base.VisitImplementation(node);
+ if (oldErrorCount < this.errorCount)
+ return impl;
+
+ Stack<Block> dfsStack = new Stack<Block>();
+ HashSet<Block> dfsStackAsSet = new HashSet<Block>();
+ availableLinearVars[node.Blocks[0]] = start;
+ dfsStack.Push(node.Blocks[0]);
+ dfsStackAsSet.Add(node.Blocks[0]);
+ while (dfsStack.Count > 0)
+ {
+ Block b = dfsStack.Pop();
+ dfsStackAsSet.Remove(b);
+ HashSet<Variable> end = PropagateAvailableLinearVarsAcrossBlock(b);
+ if (b.TransferCmd is ReturnCmd)
+ {
+ foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(end))
+ {
+ Error(b.TransferCmd, string.Format("Global variable {0} must be available at a return", g.Name));
+ }
+ foreach (Variable v in node.InParams)
+ {
+ if (FindDomainName(v) == null || FindLinearKind(v) == LinearKind.LINEAR_IN || end.Contains(v)) continue;
+ Error(b.TransferCmd, string.Format("Input variable {0} must be available at a return", v.Name));
+ }
+ foreach (Variable v in node.OutParams)
+ {
+ if (FindDomainName(v) == null || end.Contains(v)) continue;
+ Error(b.TransferCmd, string.Format("Output variable {0} must be available at a return", v.Name));
+ }
+ continue;
+ }
+ GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
+ foreach (Block target in gotoCmd.labelTargets)
+ {
+ if (!availableLinearVars.ContainsKey(target))
+ {
+ availableLinearVars[target] = new HashSet<Variable>(end);
+ dfsStack.Push(target);
+ dfsStackAsSet.Add(target);
+ }
+ else
+ {
+ var savedAvailableVars = new HashSet<Variable>(availableLinearVars[target]);
+ availableLinearVars[target].IntersectWith(end);
+ if (savedAvailableVars.IsProperSupersetOf(availableLinearVars[target]) && !dfsStackAsSet.Contains(target))
+ {
+ dfsStack.Push(target);
+ dfsStackAsSet.Add(target);
+ }
+ }
+ }
+ }
+
+ if (graph.Reducible)
+ {
+ foreach (Block header in graph.Headers)
+ {
+ foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(availableLinearVars[header]))
+ {
+ Error(header, string.Format("Global variable {0} must be available at a loop head", g.Name));
+ }
+ }
+ }
+ return impl;
+ }
+ public void AddAvailableVars(CallCmd callCmd, HashSet<Variable> start)
+ {
+ foreach (IdentifierExpr ie in callCmd.Outs)
+ {
+ if (FindDomainName(ie.Decl) == null) continue;
+ start.Add(ie.Decl);
+ }
+ for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
+ {
+ IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
+ if (ie == null) continue;
+ Variable v = callCmd.Proc.InParams[i];
+ if (FindDomainName(v) == null) continue;
+ if (FindLinearKind(v) == LinearKind.LINEAR_OUT)
+ {
+ start.Add(ie.Decl);
+ }
+ }
+ }
+ public void AddAvailableVars(ParCallCmd parCallCmd, HashSet<Variable> start)
+ {
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ AddAvailableVars(callCmd, start);
+ }
+ }
+ private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b) {
+ HashSet<Variable> start = new HashSet<Variable>(availableLinearVars[b]);
+ foreach (Cmd cmd in b.Cmds)
+ {
+ if (cmd is AssignCmd)
+ {
+ AssignCmd assignCmd = (AssignCmd)cmd;
+ for (int i = 0; i < assignCmd.Lhss.Count; i++)
+ {
+ if (FindDomainName(assignCmd.Lhss[i].DeepAssignedVariable) == null) continue;
+ IdentifierExpr ie = assignCmd.Rhss[i] as IdentifierExpr;
+ if (!start.Contains(ie.Decl))
+ {
+ Error(ie, "unavailable source for a linear read");
+ }
+ else
+ {
+ start.Remove(ie.Decl);
+ }
+ }
+ foreach (AssignLhs assignLhs in assignCmd.Lhss)
+ {
+ if (FindDomainName(assignLhs.DeepAssignedVariable) == null) continue;
+ start.Add(assignLhs.DeepAssignedVariable);
+ }
+ }
+ else if (cmd is CallCmd)
+ {
+ foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
+ {
+ Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name));
+ }
+ CallCmd callCmd = (CallCmd)cmd;
+ for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
+ {
+ Variable param = callCmd.Proc.InParams[i];
+ if (FindDomainName(param) == null) continue;
+ IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
+ LinearKind paramKind = FindLinearKind(param);
+ if (start.Contains(ie.Decl))
+ {
+ if (callCmd.IsAsync || paramKind == LinearKind.LINEAR_IN)
+ {
+ start.Remove(ie.Decl);
+ }
+ }
+ else
+ {
+ if (paramKind == LinearKind.LINEAR_OUT)
+ {
+ start.Add(ie.Decl);
+ }
+ else
+ {
+ Error(ie, "unavailable source for a linear read");
+ }
+ }
+ }
+ availableLinearVars[callCmd] = new HashSet<Variable>(start);
+ AddAvailableVars(callCmd, start);
+ }
+ else if (cmd is ParCallCmd)
+ {
+ foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
+ {
+ Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name));
+ }
+ ParCallCmd parCallCmd = (ParCallCmd)cmd;
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
+ {
+ Variable param = callCmd.Proc.InParams[i];
+ if (FindDomainName(param) == null) continue;
+ IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
+ LinearKind paramKind = FindLinearKind(param);
+ if (start.Contains(ie.Decl))
+ {
+ if (paramKind == LinearKind.LINEAR_IN)
+ {
+ start.Remove(ie.Decl);
+ }
+ }
+ else
+ {
+ if (paramKind == LinearKind.LINEAR_OUT)
+ {
+ start.Add(ie.Decl);
+ }
+ else
+ {
+ Error(ie, "unavailable source for a linear read");
+ }
+ }
+ }
+ }
+ availableLinearVars[parCallCmd] = new HashSet<Variable>(start);
+ AddAvailableVars(parCallCmd, start);
+ }
+ else if (cmd is HavocCmd)
+ {
+ HavocCmd havocCmd = (HavocCmd)cmd;
+ foreach (IdentifierExpr ie in havocCmd.Vars)
+ {
+ if (FindDomainName(ie.Decl) == null) continue;
+ start.Remove(ie.Decl);
+ }
+ }
+ else if (cmd is YieldCmd)
+ {
+ foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
+ {
+ Error(cmd, string.Format("Global variable {0} must be available at a yield", g.Name));
+ }
+ availableLinearVars[cmd] = new HashSet<Variable>(start);
+ }
+ }
+ return start;
+ }
+ public string FindDomainName(Variable v)
+ {
+ if (globalVarToDomainName.ContainsKey(v))
+ return globalVarToDomainName[v];
+ if (inParamToLinearQualifier.ContainsKey(v))
+ return inParamToLinearQualifier[v].domainName;
+ if (outParamToDomainName.ContainsKey(v))
+ return outParamToDomainName[v];
+ string domainName = QKeyValue.FindStringAttribute(v.Attributes, "linear");
+ if (domainName != null)
+ return domainName;
+ domainName = QKeyValue.FindStringAttribute(v.Attributes, "linear_in");
+ if (domainName != null)
+ return domainName;
+ return QKeyValue.FindStringAttribute(v.Attributes, "linear_out");
+ }
+ public LinearKind FindLinearKind(Variable v)
+ {
+ if (globalVarToDomainName.ContainsKey(v))
+ return LinearKind.LINEAR;
+ if (inParamToLinearQualifier.ContainsKey(v))
+ return inParamToLinearQualifier[v].kind;
+ if (outParamToDomainName.ContainsKey(v))
+ return LinearKind.LINEAR;
+
+ if (QKeyValue.FindStringAttribute(v.Attributes, "linear") != null)
+ {
+ return LinearKind.LINEAR;
+ }
+ else if (QKeyValue.FindStringAttribute(v.Attributes, "linear_in") != null)
+ {
+ return LinearKind.LINEAR_IN;
+ }
+ else if (QKeyValue.FindStringAttribute(v.Attributes, "linear_out") != null)
+ {
+ return LinearKind.LINEAR_OUT;
+ }
+ else
+ {
+ Debug.Assert(false);
+ return LinearKind.LINEAR;
+ }
+ }
+ public override Variable VisitVariable(Variable node)
+ {
+ string domainName = FindDomainName(node);
+ if (domainName != null)
+ {
+ if (!domainNameToCollectors.ContainsKey(domainName))
+ {
+ domainNameToCollectors[domainName] = new Dictionary<Type,Function>();
+ }
+ LinearKind kind = FindLinearKind(node);
+ if (kind != LinearKind.LINEAR)
+ {
+ if (node is GlobalVariable || node is LocalVariable || (node is Formal && !(node as Formal).InComing))
+ {
+ Error(node, "Variable must be declared linear (as opposed to linear_in or linear_out)");
+ }
+ }
+ }
+ return base.VisitVariable(node);
+ }
+ public override Cmd VisitAssignCmd(AssignCmd node)
+ {
+ HashSet<Variable> rhsVars = new HashSet<Variable>();
+ for (int i = 0; i < node.Lhss.Count; i++)
+ {
+ AssignLhs lhs = node.Lhss[i];
+ Variable lhsVar = lhs.DeepAssignedVariable;
+ string domainName = FindDomainName(lhsVar);
+ if (domainName == null) continue;
+ SimpleAssignLhs salhs = lhs as SimpleAssignLhs;
+ if (salhs == null)
+ {
+ Error(node, string.Format("Only simple assignment allowed on linear variable {0}", lhsVar.Name));
+ continue;
+ }
+ IdentifierExpr rhs = node.Rhss[i] as IdentifierExpr;
+ if (rhs == null)
+ {
+ Error(node, string.Format("Only variable can be assigned to linear variable {0}", lhsVar.Name));
+ continue;
+ }
+ string rhsDomainName = FindDomainName(rhs.Decl);
+ if (rhsDomainName == null)
+ {
+ Error(node, string.Format("Only linear variable can be assigned to linear variable {0}", lhsVar.Name));
+ continue;
+ }
+ if (domainName != rhsDomainName)
+ {
+ Error(node, string.Format("Linear variable of domain {0} cannot be assigned to linear variable of domain {1}", rhsDomainName, domainName));
+ continue;
+ }
+ if (rhsVars.Contains(rhs.Decl))
+ {
+ Error(node, string.Format("Linear variable {0} can occur only once in the right-hand-side of an assignment", rhs.Decl.Name));
+ continue;
+ }
+ rhsVars.Add(rhs.Decl);
+ }
+ return base.VisitAssignCmd(node);
+ }
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ HashSet<Variable> inVars = new HashSet<Variable>();
+ for (int i = 0; i < node.Proc.InParams.Count; i++)
+ {
+ Variable formal = node.Proc.InParams[i];
+ string domainName = FindDomainName(formal);
+ if (domainName == null) continue;
+ IdentifierExpr actual = node.Ins[i] as IdentifierExpr;
+ if (actual == null)
+ {
+ Error(node, string.Format("Only variable can be passed to linear parameter {0}", formal.Name));
+ continue;
+ }
+ string actualDomainName = FindDomainName(actual.Decl);
+ if (actualDomainName == null)
+ {
+ Error(node, string.Format("Only a linear argument can be passed to linear parameter {0}", formal.Name));
+ continue;
+ }
+ if (domainName != actualDomainName)
+ {
+ Error(node, "The domains of formal and actual parameters must be the same");
+ continue;
+ }
+ if (actual.Decl is GlobalVariable)
+ {
+ Error(node, "Only local linear variable can be an actual input parameter of a procedure call");
+ continue;
+ }
+ if (inVars.Contains(actual.Decl))
+ {
+ Error(node, string.Format("Linear variable {0} can occur only once as an input parameter", actual.Decl.Name));
+ continue;
+ }
+ inVars.Add(actual.Decl);
+ }
+ for (int i = 0; i < node.Proc.OutParams.Count; i++)
+ {
+ IdentifierExpr actual = node.Outs[i];
+ string actualDomainName = FindDomainName(actual.Decl);
+ if (actualDomainName == null) continue;
+ Variable formal = node.Proc.OutParams[i];
+ string domainName = FindDomainName(formal);
+ if (domainName == null)
+ {
+ Error(node, "Only a linear variable can be passed to a linear parameter");
+ continue;
+ }
+ if (domainName != actualDomainName)
+ {
+ Error(node, "The domains of formal and actual parameters must be the same");
+ continue;
+ }
+ if (actual.Decl is GlobalVariable)
+ {
+ Error(node, "Only local linear variable can be actual output parameter of a procedure call");
+ continue;
+ }
+ }
+ return base.VisitCallCmd(node);
+ }
+ public override Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ HashSet<Variable> parallelCallInvars = new HashSet<Variable>();
+ foreach (CallCmd callCmd in node.CallCmds)
+ {
+ for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
+ {
+ Variable formal = callCmd.Proc.InParams[i];
+ string domainName = FindDomainName(formal);
+ if (domainName == null) continue;
+ IdentifierExpr actual = callCmd.Ins[i] as IdentifierExpr;
+ if (parallelCallInvars.Contains(actual.Decl))
+ {
+ Error(node, string.Format("Linear variable {0} can occur only once as an input parameter of a parallel call", actual.Decl.Name));
+ }
+ else
+ {
+ parallelCallInvars.Add(actual.Decl);
+ }
+ }
+ }
+ return base.VisitParCallCmd(node);
+ }
+
+ public override Requires VisitRequires(Requires requires)
+ {
+ return requires;
+ }
+
+ public override Ensures VisitEnsures(Ensures ensures)
+ {
+ return ensures;
+ }
+
+ public IEnumerable<Variable> AvailableLinearVars(Absy absy)
+ {
+ if (availableLinearVars.ContainsKey(absy))
+ {
+ return availableLinearVars[absy];
+ }
+ else
+ {
+ return new HashSet<Variable>();
+ }
+ }
+
+ private void AddDisjointnessExpr(List<Cmd> newCmds, Absy absy, Dictionary<string, Variable> domainNameToInputVar)
+ {
+ Dictionary<string, HashSet<Variable>> domainNameToScope = new Dictionary<string, HashSet<Variable>>();
+ foreach (var domainName in linearDomains.Keys)
+ {
+ domainNameToScope[domainName] = new HashSet<Variable>();
+ }
+ foreach (Variable v in AvailableLinearVars(absy))
+ {
+ var domainName = FindDomainName(v);
+ domainNameToScope[domainName].Add(v);
+ }
+ foreach (Variable v in globalVarToDomainName.Keys)
+ {
+ var domainName = FindDomainName(v);
+ domainNameToScope[domainName].Add(v);
+ }
+ foreach (string domainName in linearDomains.Keys)
+ {
+ newCmds.Add(new AssumeCmd(Token.NoToken, DisjointnessExpr(domainName, domainNameToInputVar[domainName], domainNameToScope[domainName])));
+ }
+ }
+
+ public void Transform()
+ {
+ foreach (var impl in program.Implementations)
+ {
+ Dictionary<string, Variable> domainNameToInputVar = new Dictionary<string, Variable>();
+ foreach (string domainName in linearDomains.Keys)
+ {
+ var domain = linearDomains[domainName];
+ Formal f = new Formal(
+ Token.NoToken,
+ new TypedIdent(Token.NoToken,
+ "linear_" + domainName + "_in",
+ new MapType(Token.NoToken, new List<TypeVariable>(),
+ new List<Type> { domain.elementType }, Type.Bool)), true);
+ impl.InParams.Add(f);
+ domainNameToInputVar[domainName] = f;
+ }
+
+ foreach (Block b in impl.Blocks)
+ {
+ List<Cmd> newCmds = new List<Cmd>();
+ for (int i = 0; i < b.Cmds.Count; i++)
+ {
+ Cmd cmd = b.Cmds[i];
+ newCmds.Add(cmd);
+ if (cmd is CallCmd)
+ {
+ CallCmd callCmd = cmd as CallCmd;
+ if (callCmd.IsAsync)
+ {
+ foreach (var domainName in linearDomains.Keys)
+ {
+ var domain = linearDomains[domainName];
+ var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.False });
+ expr.Resolve(new ResolutionContext(null));
+ expr.Typecheck(new TypecheckingContext(null));
+ callCmd.Ins.Add(expr);
+ }
+ }
+ else
+ {
+ Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
+ foreach (var domainName in linearDomains.Keys)
+ {
+ domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]);
+ }
+ foreach (Variable v in AvailableLinearVars(callCmd))
+ {
+ var domainName = FindDomainName(v);
+ var domain = linearDomains[domainName];
+ if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
+ Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
+ var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
+ expr.Resolve(new ResolutionContext(null));
+ expr.Typecheck(new TypecheckingContext(null));
+ domainNameToExpr[domainName] = expr;
+ }
+ foreach (var domainName in linearDomains.Keys)
+ {
+ callCmd.Ins.Add(domainNameToExpr[domainName]);
+ }
+ }
+ }
+ else if (cmd is ParCallCmd)
+ {
+ ParCallCmd parCallCmd = (ParCallCmd)cmd;
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ foreach (var domainName in linearDomains.Keys)
+ {
+ var domain = linearDomains[domainName];
+ var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.False });
+ expr.Resolve(new ResolutionContext(null));
+ expr.Typecheck(new TypecheckingContext(null));
+ callCmd.Ins.Add(expr);
+ }
+ }
+ }
+ else if (cmd is YieldCmd)
+ {
+ AddDisjointnessExpr(newCmds, cmd, domainNameToInputVar);
+ }
+ }
+ b.Cmds = newCmds;
+ }
+
+ {
+ // Loops
+ impl.PruneUnreachableBlocks();
+ impl.ComputePredecessorsForBlocks();
+ GraphUtil.Graph<Block> g = Program.GraphFromImpl(impl);
+ g.ComputeLoops();
+ if (g.Reducible)
+ {
+ foreach (Block header in g.Headers)
+ {
+ List<Cmd> newCmds = new List<Cmd>();
+ AddDisjointnessExpr(newCmds, header, domainNameToInputVar);
+ newCmds.AddRange(header.Cmds);
+ header.Cmds = newCmds;
+ }
+ }
+ }
+ }
+
+ foreach (var proc in program.Procedures)
+ {
+ Dictionary<string, HashSet<Variable>> domainNameToInputScope = new Dictionary<string, HashSet<Variable>>();
+ Dictionary<string, HashSet<Variable>> domainNameToOutputScope = new Dictionary<string, HashSet<Variable>>();
+ foreach (var domainName in linearDomains.Keys)
+ {
+ domainNameToInputScope[domainName] = new HashSet<Variable>();
+ domainNameToOutputScope[domainName] = new HashSet<Variable>();
+
+ }
+ foreach (Variable v in globalVarToDomainName.Keys)
+ {
+ var domainName = globalVarToDomainName[v];
+ domainNameToInputScope[domainName].Add(v);
+ domainNameToOutputScope[domainName].Add(v);
+ }
+ foreach (Variable v in proc.InParams)
+ {
+ var domainName = FindDomainName(v);
+ if (domainName == null) continue;
+ if (!this.linearDomains.ContainsKey(domainName)) continue;
+ domainNameToInputScope[domainName].Add(v);
+ }
+ foreach (Variable v in proc.OutParams)
+ {
+ var domainName = FindDomainName(v);
+ if (domainName == null) continue;
+ if (!this.linearDomains.ContainsKey(domainName)) continue;
+ domainNameToOutputScope[domainName].Add(v);
+ }
+ foreach (var domainName in linearDomains.Keys)
+ {
+ proc.Requires.Add(new Requires(true, DisjointnessExpr(domainName, domainNameToInputScope[domainName])));
+ var domain = linearDomains[domainName];
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
+ proc.InParams.Add(f);
+ proc.Ensures.Add(new Ensures(true, DisjointnessExpr(domainName, f, domainNameToOutputScope[domainName])));
+ }
+ }
+
+ foreach (LinearDomain domain in linearDomains.Values)
+ {
+ program.AddTopLevelDeclaration(domain.mapConstBool);
+ program.AddTopLevelDeclaration(domain.mapConstInt);
+ program.AddTopLevelDeclaration(domain.mapEqInt);
+ program.AddTopLevelDeclaration(domain.mapImpBool);
+ program.AddTopLevelDeclaration(domain.mapOrBool);
+ foreach (Axiom axiom in domain.axioms)
+ {
+ program.AddTopLevelDeclaration(axiom);
+ }
+ }
+
+ //int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ //CommandLineOptions.Clo.PrintUnstructured = 1;
+ //PrintBplFile("lsd.bpl", program, false, false);
+ //CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+
+ private Expr SubsetExpr(LinearDomain domain, Expr ie, Variable partition, int partitionCount)
+ {
+ Expr e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstInt), new List<Expr> { new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(partitionCount)) });
+ e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapEqInt), new List<Expr> { Expr.Ident(partition), e });
+ e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapImpBool), new List<Expr> { ie, e });
+ e = Expr.Eq(e, new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.True }));
+ return e;
+ }
+
+ private Expr SubsetExprs(LinearDomain domain, HashSet<Variable> scope, Variable partition, int count, Expr expr)
+ {
+ foreach (Variable v in scope)
+ {
+ if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
+ Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
+ expr = Expr.And(SubsetExpr(domain, ie, partition, count), expr);
+ count++;
+ }
+ expr = new ExistsExpr(Token.NoToken, new List<Variable> { partition }, expr);
+ expr.Resolve(new ResolutionContext(null));
+ expr.Typecheck(new TypecheckingContext(null));
+ return expr;
+ }
+
+ public Expr DisjointnessExpr(string domainName, Variable inputVar, HashSet<Variable> scope)
+ {
+ LinearDomain domain = linearDomains[domainName];
+ BoundVariable partition = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("partition_{0}", domainName), new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Microsoft.Boogie.Type.Int)));
+ return SubsetExprs(domain, scope, partition, 1, SubsetExpr(domain, Expr.Ident(inputVar), partition, 0));
+ }
+
+ public Expr DisjointnessExpr(string domainName, HashSet<Variable> scope)
+ {
+ LinearDomain domain = linearDomains[domainName];
+ BoundVariable partition = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("partition_{0}", domainName), new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Microsoft.Boogie.Type.Int)));
+ return SubsetExprs(domain, scope, partition, 0, Expr.True);
+ }
+ }
+
+ public class LinearQualifier
+ {
+ public string domainName;
+ public LinearKind kind;
+ public LinearQualifier(string domainName, LinearKind kind)
+ {
+ this.domainName = domainName;
+ this.kind = kind;
+ }
+ }
+
+ public class LinearDomain
+ {
+ public Function mapEqInt;
+ public Function mapConstInt;
+ public Function mapOrBool;
+ public Function mapImpBool;
+ public Function mapConstBool;
+ public List<Axiom> axioms;
+ public Type elementType;
+ public Dictionary<Type, Function> collectors;
+
+ public LinearDomain(Program program, string domainName, Dictionary<Type, Function> collectors)
+ {
+ this.axioms = new List<Axiom>();
+ this.collectors = collectors;
+ MapType setType = (MapType)collectors.First().Value.OutParams[0].TypedIdent.Type;
+ this.elementType = setType.Arguments[0];
+ MapType mapTypeBool = new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { this.elementType }, Type.Bool);
+ MapType mapTypeInt = new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { this.elementType }, Type.Int);
+ this.mapOrBool = new Function(Token.NoToken, "linear_" + domainName + "_MapOr",
+ new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) },
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ {
+ this.mapOrBool.AddAttribute("builtin", "MapOr");
+ }
+ else
+ {
+ BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool));
+ IdentifierExpr aie = Expr.Ident(a);
+ BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool));
+ IdentifierExpr bie = Expr.Ident(b);
+ BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
+ IdentifierExpr xie = Expr.Ident(x);
+ var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapOrBool), new List<Expr> { aie, bie } );
+ var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie } );
+ var rhsTerm = Expr.Or(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie } ),
+ new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie} ));
+ var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null,
+ new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }),
+ new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm)));
+ axiomExpr.Typecheck(new TypecheckingContext(null));
+ axioms.Add(new Axiom(Token.NoToken, axiomExpr));
+ }
+
+ this.mapImpBool = new Function(Token.NoToken, "linear_" + domainName + "_MapImp",
+ new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) },
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ {
+ this.mapImpBool.AddAttribute("builtin", "MapImp");
+ }
+ else
+ {
+ BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool));
+ IdentifierExpr aie = Expr.Ident(a);
+ BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool));
+ IdentifierExpr bie = Expr.Ident(b);
+ BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
+ IdentifierExpr xie = Expr.Ident(x);
+ var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapImpBool), new List<Expr> { aie, bie });
+ var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie });
+ var rhsTerm = Expr.Imp(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie }),
+ new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie }));
+ var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null,
+ new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }),
+ new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm)));
+ axiomExpr.Typecheck(new TypecheckingContext(null));
+ axioms.Add(new Axiom(Token.NoToken, axiomExpr));
+ }
+
+ this.mapConstBool = new Function(Token.NoToken, "linear_" + domainName + "_MapConstBool",
+ new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Bool), true) },
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ {
+ this.mapConstBool.AddAttribute("builtin", "MapConst");
+ }
+ else
+ {
+ BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
+ IdentifierExpr xie = Expr.Ident(x);
+ var trueTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List<Expr> { Expr.True }), xie });
+ var trueAxiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { x }, trueTerm);
+ trueAxiomExpr.Typecheck(new TypecheckingContext(null));
+ axioms.Add(new Axiom(Token.NoToken, trueAxiomExpr));
+ var falseTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
+ new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List<Expr> { Expr.False }), xie });
+ var falseAxiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, falseTerm));
+ falseAxiomExpr.Typecheck(new TypecheckingContext(null));
+ axioms.Add(new Axiom(Token.NoToken, falseAxiomExpr));
+ }
+
+ this.mapEqInt = new Function(Token.NoToken, "linear_" + domainName + "_MapEq",
+ new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt), true) },
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false));
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ {
+ this.mapEqInt.AddAttribute("builtin", "MapEq");
+ }
+ else
+ {
+ BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt));
+ IdentifierExpr aie = Expr.Ident(a);
+ BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt));
+ IdentifierExpr bie = Expr.Ident(b);
+ BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
+ IdentifierExpr xie = Expr.Ident(x);
+ var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapEqInt), new List<Expr> { aie, bie });
+ var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie });
+ var rhsTerm = Expr.Eq(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie }),
+ new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie }));
+ var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null,
+ new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }),
+ new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm)));
+ axiomExpr.Typecheck(new TypecheckingContext(null));
+ axioms.Add(new Axiom(Token.NoToken, axiomExpr));
+ }
+
+ this.mapConstInt = new Function(Token.NoToken, "linear_" + domainName + "_MapConstInt",
+ new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Int), true) },
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeInt), false));
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ {
+ this.mapConstInt.AddAttribute("builtin", "MapConst");
+ }
+ else
+ {
+ BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", Type.Int));
+ IdentifierExpr aie = Expr.Ident(a);
+ BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType));
+ IdentifierExpr xie = Expr.Ident(x);
+ var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstInt), new List<Expr> { aie }), xie });
+ var axiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { a, x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, aie));
+ axiomExpr.Typecheck(new TypecheckingContext(null));
+ axioms.Add(new Axiom(Token.NoToken, axiomExpr));
+ }
+
+ foreach (var axiom in axioms)
+ {
+ axiom.Expr.Resolve(new ResolutionContext(null));
+ axiom.Expr.Typecheck(new TypecheckingContext(null));
+ }
+ }
+ }
+}
diff --git a/Source/Concurrency/MoverCheck.cs b/Source/Concurrency/MoverCheck.cs
index 971e7271..732bcaa4 100644
--- a/Source/Concurrency/MoverCheck.cs
+++ b/Source/Concurrency/MoverCheck.cs
@@ -1,649 +1,673 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.Diagnostics;
-
-namespace Microsoft.Boogie
-{
- public class MoverCheck
- {
- LinearTypeChecker linearTypeChecker;
- MoverTypeChecker moverTypeChecker;
- List<Declaration> decls;
- HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>> commutativityCheckerCache;
- HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>> gatePreservationCheckerCache;
- HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>> failurePreservationCheckerCache;
- private MoverCheck(LinearTypeChecker linearTypeChecker, MoverTypeChecker moverTypeChecker, List<Declaration> decls)
- {
- this.linearTypeChecker = linearTypeChecker;
- this.moverTypeChecker = moverTypeChecker;
- this.decls = decls;
- this.commutativityCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>();
- this.gatePreservationCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>();
- this.failurePreservationCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>();
- }
-
- public static void AddCheckers(LinearTypeChecker linearTypeChecker, MoverTypeChecker moverTypeChecker, List<Declaration> decls)
- {
- if (moverTypeChecker.procToActionInfo.Count == 0)
- return;
-
- List<ActionInfo> sortedByCreatedLayerNum = new List<ActionInfo>(moverTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo));
- sortedByCreatedLayerNum.Sort((x, y) => { return (x.createdAtLayerNum == y.createdAtLayerNum) ? 0 : (x.createdAtLayerNum < y.createdAtLayerNum) ? -1 : 1; });
- List<ActionInfo> sortedByAvailableUptoLayerNum = new List<ActionInfo>(moverTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo));
- sortedByAvailableUptoLayerNum.Sort((x, y) => { return (x.availableUptoLayerNum == y.availableUptoLayerNum) ? 0 : (x.availableUptoLayerNum < y.availableUptoLayerNum) ? -1 : 1; });
-
- Dictionary<int, HashSet<AtomicActionInfo>> pools = new Dictionary<int, HashSet<AtomicActionInfo>>();
- int indexIntoSortedByCreatedLayerNum = 0;
- int indexIntoSortedByAvailableUptoLayerNum = 0;
- HashSet<AtomicActionInfo> currPool = new HashSet<AtomicActionInfo>();
- while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count)
- {
- var currLayerNum = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum].createdAtLayerNum;
- pools[currLayerNum] = new HashSet<AtomicActionInfo>(currPool);
- while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count)
- {
- var actionInfo = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum] as AtomicActionInfo;
- if (actionInfo.createdAtLayerNum > currLayerNum) break;
- pools[currLayerNum].Add(actionInfo);
- indexIntoSortedByCreatedLayerNum++;
- }
- while (indexIntoSortedByAvailableUptoLayerNum < sortedByAvailableUptoLayerNum.Count)
- {
- var actionInfo = sortedByAvailableUptoLayerNum[indexIntoSortedByAvailableUptoLayerNum] as AtomicActionInfo;
- if (actionInfo.availableUptoLayerNum > currLayerNum) break;
- pools[currLayerNum].Remove(actionInfo);
- indexIntoSortedByAvailableUptoLayerNum++;
- }
- currPool = pools[currLayerNum];
- }
-
- Program program = moverTypeChecker.program;
- MoverCheck moverChecking = new MoverCheck(linearTypeChecker, moverTypeChecker, decls);
- foreach (int layerNum in pools.Keys)
- {
- foreach (AtomicActionInfo first in pools[layerNum])
- {
- Debug.Assert(first.moverType != MoverType.Top);
- if (first.moverType == MoverType.Atomic)
- continue;
- foreach (AtomicActionInfo second in pools[layerNum])
- {
- if (first.IsRightMover)
- {
- moverChecking.CreateCommutativityChecker(program, first, second);
- moverChecking.CreateGatePreservationChecker(program, second, first);
- }
- if (first.IsLeftMover)
- {
- moverChecking.CreateCommutativityChecker(program, second, first);
- moverChecking.CreateGatePreservationChecker(program, first, second);
- moverChecking.CreateFailurePreservationChecker(program, second, first);
- }
- }
- }
- }
- foreach (ActionInfo actionInfo in moverTypeChecker.procToActionInfo.Values)
- {
- AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
- if (atomicActionInfo != null && atomicActionInfo.IsLeftMover && atomicActionInfo.hasAssumeCmd)
- {
- moverChecking.CreateNonBlockingChecker(program, atomicActionInfo);
- }
- }
- }
-
- public sealed class MyDuplicator : Duplicator
- {
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- IdentifierExpr ret = (IdentifierExpr) base.VisitIdentifierExpr(node);
- if (ret.Decl is GlobalVariable)
- {
- return new OldExpr(Token.NoToken, ret);
- }
- else
- {
- return ret;
- }
- }
- }
-
- public class TransitionRelationComputation
- {
- private Program program;
- private AtomicActionInfo first; // corresponds to that*
- private AtomicActionInfo second; // corresponds to this*
- private Stack<Cmd> cmdStack;
- private List<PathInfo> paths;
- private HashSet<Variable> frame;
- private HashSet<Variable> postExistVars;
-
- public TransitionRelationComputation(Program program, AtomicActionInfo second, HashSet<Variable> frame, HashSet<Variable> postExistVars)
- {
- this.postExistVars = postExistVars;
- this.frame = frame;
- TransitionRelationComputationHelper(program, null, second);
- }
-
- public TransitionRelationComputation(Program program, AtomicActionInfo first, AtomicActionInfo second, HashSet<Variable> frame, HashSet<Variable> postExistVars)
- {
- this.postExistVars = postExistVars;
- this.frame = frame;
- TransitionRelationComputationHelper(program, first, second);
- }
-
- private void TransitionRelationComputationHelper(Program program, AtomicActionInfo first, AtomicActionInfo second)
- {
- this.program = program;
- this.first = first;
- this.second = second;
- this.cmdStack = new Stack<Cmd>();
- this.paths = new List<PathInfo>();
- List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
- this.second.thisOutParams.ForEach(v => havocVars.Add(Expr.Ident(v)));
- this.second.thisAction.LocVars.ForEach(v => havocVars.Add(Expr.Ident(v)));
- if (havocVars.Count > 0)
- {
- HavocCmd havocCmd = new HavocCmd(Token.NoToken, havocVars);
- cmdStack.Push(havocCmd);
- }
- Search(this.second.thisAction.Blocks[0], false);
- }
-
- private void Substitute(Dictionary<Variable, Expr> map, ref List<Expr> pathExprs, ref Dictionary<Variable, Expr> varToExpr)
- {
- Substitution subst = Substituter.SubstitutionFromHashtable(map);
- List<Expr> oldPathExprs = pathExprs;
- pathExprs = new List<Expr>();
- foreach (Expr pathExpr in oldPathExprs)
- {
- pathExprs.Add(Substituter.Apply(subst, pathExpr));
- }
- Dictionary<Variable, Expr> oldVarToExpr = varToExpr;
- varToExpr = new Dictionary<Variable, Expr>();
- foreach (Variable v in oldVarToExpr.Keys)
- {
- varToExpr[v] = Substituter.Apply(subst, oldVarToExpr[v]);
- }
- }
-
- struct PathInfo
- {
- public HashSet<Variable> existsVars;
- public Dictionary<Variable, Expr> varToExpr;
- public List<Expr> pathExprs;
-
- public PathInfo(HashSet<Variable> existsVars, Dictionary<Variable, Expr> varToExpr, List<Expr> pathExprs)
- {
- this.existsVars = existsVars;
- this.varToExpr = varToExpr;
- this.pathExprs = pathExprs;
- }
- }
-
- private void FlattenAnd(Expr x, List<Expr> xs)
- {
- NAryExpr naryExpr = x as NAryExpr;
- if (naryExpr != null && naryExpr.Fun.FunctionName == "&&")
- {
- FlattenAnd(naryExpr.Args[0], xs);
- FlattenAnd(naryExpr.Args[1], xs);
- }
- else
- {
- xs.Add(x);
- }
- }
-
- private void AddPath()
- {
- HashSet<Variable> existsVars = new HashSet<Variable>();
- Dictionary<Variable, Expr> varToExpr = new Dictionary<Variable, Expr>();
- foreach (Variable v in frame)
- {
- varToExpr[v] = Expr.Ident(v);
- }
- if (first != null)
- {
- foreach (Variable v in first.thatOutParams)
- {
- varToExpr[v] = Expr.Ident(v);
- }
- }
- foreach (Variable v in second.thisOutParams)
- {
- varToExpr[v] = Expr.Ident(v);
- }
- List<Expr> pathExprs = new List<Expr>();
- int boundVariableCount = 0;
- foreach (Cmd cmd in cmdStack)
- {
- if (cmd is AssumeCmd)
- {
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- FlattenAnd(assumeCmd.Expr, pathExprs);
- }
- else if (cmd is AssignCmd)
- {
- AssignCmd assignCmd = (cmd as AssignCmd).AsSimpleAssignCmd;
- Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
- for (int k = 0; k < assignCmd.Lhss.Count; k++)
- {
- map[assignCmd.Lhss[k].DeepAssignedVariable] = assignCmd.Rhss[k];
- }
- Substitute(map, ref pathExprs, ref varToExpr);
- }
- else if (cmd is HavocCmd)
- {
- HavocCmd havocCmd = cmd as HavocCmd;
- Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
- foreach (IdentifierExpr ie in havocCmd.Vars)
- {
- BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "#tmp_" + boundVariableCount++, ie.Decl.TypedIdent.Type));
- map[ie.Decl] = Expr.Ident(bv);
- existsVars.Add(bv);
- }
- Substitute(map, ref pathExprs, ref varToExpr);
- }
- else
- {
- Debug.Assert(false);
- }
- }
- paths.Add(new PathInfo(existsVars, varToExpr, pathExprs));
- }
-
- private Expr CalculatePathCondition(PathInfo path)
- {
- Expr returnExpr = Expr.True;
-
- HashSet<Variable> existsVars = path.existsVars;
- Dictionary<Variable, Expr> existsMap = new Dictionary<Variable, Expr>();
-
- Dictionary<Variable, Expr> varToExpr = path.varToExpr;
- foreach (Variable v in varToExpr.Keys)
- {
- if (postExistVars.Contains(v)) continue;
- IdentifierExpr ie = varToExpr[v] as IdentifierExpr;
- if (ie != null && !existsMap.ContainsKey(ie.Decl) && existsVars.Contains(ie.Decl))
- {
- existsMap[ie.Decl] = Expr.Ident(v);
- existsVars.Remove(ie.Decl);
- }
- else
- {
- returnExpr = Expr.And(returnExpr, Expr.Eq(Expr.Ident(v), (new MyDuplicator()).VisitExpr(varToExpr[v])));
- returnExpr.Type = Type.Bool;
- }
- }
-
- List<Expr> pathExprs = new List<Expr>();
- path.pathExprs.ForEach(x => pathExprs.Add((new MyDuplicator()).VisitExpr(x)));
- foreach (Expr x in pathExprs)
- {
- Variable boundVar;
- Expr boundVarExpr;
- if (InferSubstitution(x, out boundVar, out boundVarExpr) && existsVars.Contains(boundVar))
- {
- existsMap[boundVar] = boundVarExpr;
- existsVars.Remove(boundVar);
- }
- else
- {
- returnExpr = Expr.And(returnExpr, x);
- returnExpr.Type = Type.Bool;
- }
- }
-
- returnExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(existsMap), returnExpr);
- if (existsVars.Count > 0)
- {
- returnExpr = new ExistsExpr(Token.NoToken, new List<Variable>(existsVars), returnExpr);
- }
- return returnExpr;
- }
-
- bool InferSubstitution(Expr x, out Variable var, out Expr expr)
- {
- var = null;
- expr = null;
- NAryExpr naryExpr = x as NAryExpr;
- if (naryExpr == null || naryExpr.Fun.FunctionName != "==")
- {
- return false;
- }
- IdentifierExpr arg0 = naryExpr.Args[0] as IdentifierExpr;
- if (arg0 != null && arg0.Decl is BoundVariable)
- {
- var = arg0.Decl;
- expr = naryExpr.Args[1];
- return true;
- }
- IdentifierExpr arg1 = naryExpr.Args[1] as IdentifierExpr;
- if (arg1 != null && arg1.Decl is BoundVariable)
- {
- var = arg1.Decl;
- expr = naryExpr.Args[0];
- return true;
- }
- return false;
- }
-
- public Expr TransitionRelationCompute()
- {
- Expr transitionRelation = Expr.False;
- foreach (PathInfo path in paths)
- {
- transitionRelation = Expr.Or(transitionRelation, CalculatePathCondition(path));
- }
- ResolutionContext rc = new ResolutionContext(null);
- rc.StateMode = ResolutionContext.State.Two;
- transitionRelation.Resolve(rc);
- transitionRelation.Typecheck(new TypecheckingContext(null));
- return transitionRelation;
- }
-
- private void Search(Block b, bool inFirst)
- {
- int pathSizeAtEntry = cmdStack.Count;
- foreach (Cmd cmd in b.Cmds)
- {
- cmdStack.Push(cmd);
- }
- if (b.TransferCmd is ReturnCmd)
- {
- if (first == null || inFirst)
- {
- AddPath();
- }
- else
- {
- List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
- first.thatOutParams.ForEach(v => havocVars.Add(Expr.Ident(v)));
- first.thatAction.LocVars.ForEach(v => havocVars.Add(Expr.Ident(v)));
- if (havocVars.Count > 0)
- {
- HavocCmd havocCmd = new HavocCmd(Token.NoToken, havocVars);
- cmdStack.Push(havocCmd);
- }
- Search(first.thatAction.Blocks[0], true);
- }
- }
- else
- {
- GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
- foreach (Block target in gotoCmd.labelTargets)
- {
- Search(target, inFirst);
- }
- }
- Debug.Assert(cmdStack.Count >= pathSizeAtEntry);
- while (cmdStack.Count > pathSizeAtEntry)
- {
- cmdStack.Pop();
- }
- }
- }
-
- private static List<Block> CloneBlocks(List<Block> blocks)
- {
- Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
- List<Block> otherBlocks = new List<Block>();
- foreach (Block block in blocks)
- {
- List<Cmd> otherCmds = new List<Cmd>();
- foreach (Cmd cmd in block.Cmds)
- {
- otherCmds.Add(cmd);
- }
- Block otherBlock = new Block();
- otherBlock.Cmds = otherCmds;
- otherBlock.Label = block.Label;
- otherBlocks.Add(otherBlock);
- blockMap[block] = otherBlock;
- }
- foreach (Block block in blocks)
- {
- if (block.TransferCmd is ReturnCmd) continue;
- List<Block> otherGotoCmdLabelTargets = new List<Block>();
- List<string> otherGotoCmdLabelNames = new List<string>();
- GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
- foreach (Block target in gotoCmd.labelTargets)
- {
- otherGotoCmdLabelTargets.Add(blockMap[target]);
- otherGotoCmdLabelNames.Add(blockMap[target].Label);
- }
- blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets);
- }
- return otherBlocks;
- }
-
- private List<Requires> DisjointnessRequires(Program program, AtomicActionInfo first, AtomicActionInfo second, HashSet<Variable> frame)
- {
- List<Requires> requires = new List<Requires>();
- Dictionary<string, HashSet<Variable>> domainNameToScope = new Dictionary<string, HashSet<Variable>>();
- foreach (var domainName in linearTypeChecker.linearDomains.Keys)
- {
- domainNameToScope[domainName] = new HashSet<Variable>();
- }
- foreach (Variable v in frame)
- {
- var domainName = linearTypeChecker.FindDomainName(v);
- if (domainName == null) continue;
- if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
- domainNameToScope[domainName].Add(v);
- }
- if (first != null)
- {
- foreach (Variable v in first.thatInParams)
- {
- var domainName = linearTypeChecker.FindDomainName(v);
- if (domainName == null) continue;
- if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
- domainNameToScope[domainName].Add(v);
- }
- }
- foreach (Variable v in second.thisInParams)
- {
- var domainName = linearTypeChecker.FindDomainName(v);
- if (domainName == null) continue;
- if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
- domainNameToScope[domainName].Add(v);
- }
- foreach (string domainName in domainNameToScope.Keys)
- {
- requires.Add(new Requires(false, linearTypeChecker.DisjointnessExpr(domainName, domainNameToScope[domainName])));
- }
- return requires;
- }
-
- private void CreateCommutativityChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
- {
- if (first == second && first.thatInParams.Count == 0 && first.thatOutParams.Count == 0)
- return;
- if (first.CommutesWith(second))
- return;
- Tuple<AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple<AtomicActionInfo, AtomicActionInfo>(first, second);
- if (commutativityCheckerCache.Contains(actionPair))
- return;
- commutativityCheckerCache.Add(actionPair);
-
- List<Variable> inputs = new List<Variable>();
- inputs.AddRange(first.thatInParams);
- inputs.AddRange(second.thisInParams);
- List<Variable> outputs = new List<Variable>();
- outputs.AddRange(first.thatOutParams);
- outputs.AddRange(second.thisOutParams);
- List<Variable> locals = new List<Variable>();
- locals.AddRange(first.thatAction.LocVars);
- locals.AddRange(second.thisAction.LocVars);
- List<Block> firstBlocks = CloneBlocks(first.thatAction.Blocks);
- List<Block> secondBlocks = CloneBlocks(second.thisAction.Blocks);
- foreach (Block b in firstBlocks)
- {
- if (b.TransferCmd is ReturnCmd)
- {
- List<Block> bs = new List<Block>();
- bs.Add(secondBlocks[0]);
- List<string> ls = new List<string>();
- ls.Add(secondBlocks[0].Label);
- b.TransferCmd = new GotoCmd(Token.NoToken, ls, bs);
- }
- }
- List<Block> blocks = new List<Block>();
- blocks.AddRange(firstBlocks);
- blocks.AddRange(secondBlocks);
- HashSet<Variable> frame = new HashSet<Variable>();
- frame.UnionWith(first.gateUsedGlobalVars);
- frame.UnionWith(first.actionUsedGlobalVars);
- frame.UnionWith(second.gateUsedGlobalVars);
- frame.UnionWith(second.actionUsedGlobalVars);
- List<Requires> requires = DisjointnessRequires(program, first, second, frame);
- foreach (AssertCmd assertCmd in first.thatGate)
- requires.Add(new Requires(false, assertCmd.Expr));
- foreach (AssertCmd assertCmd in second.thisGate)
- requires.Add(new Requires(false, assertCmd.Expr));
- List<Ensures> ensures = new List<Ensures>();
- Expr transitionRelation = (new TransitionRelationComputation(program, first, second, frame, new HashSet<Variable>())).TransitionRelationCompute();
- Ensures ensureCheck = new Ensures(false, transitionRelation);
- ensureCheck.ErrorData = string.Format("Commutativity check between {0} and {1} failed", first.proc.Name, second.proc.Name);
- ensures.Add(ensureCheck);
- string checkerName = string.Format("CommutativityChecker_{0}_{1}", first.proc.Name, second.proc.Name);
- List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
- moverTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
- Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
- Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, blocks);
- impl.Proc = proc;
- this.decls.Add(impl);
- this.decls.Add(proc);
- }
-
- private void CreateGatePreservationChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
- {
- if (first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Count() == 0)
- return;
- Tuple<AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple<AtomicActionInfo, AtomicActionInfo>(first, second);
- if (gatePreservationCheckerCache.Contains(actionPair))
- return;
- gatePreservationCheckerCache.Add(actionPair);
-
- List<Variable> inputs = new List<Variable>();
- inputs.AddRange(first.thatInParams);
- inputs.AddRange(second.thisInParams);
- List<Variable> outputs = new List<Variable>();
- outputs.AddRange(first.thatOutParams);
- outputs.AddRange(second.thisOutParams);
- List<Variable> locals = new List<Variable>();
- locals.AddRange(second.thisAction.LocVars);
- List<Block> secondBlocks = CloneBlocks(second.thisAction.Blocks);
- HashSet<Variable> frame = new HashSet<Variable>();
- frame.UnionWith(first.gateUsedGlobalVars);
- frame.UnionWith(second.gateUsedGlobalVars);
- frame.UnionWith(second.actionUsedGlobalVars);
- List<Requires> requires = DisjointnessRequires(program, first, second, frame);
- List<Ensures> ensures = new List<Ensures>();
- foreach (AssertCmd assertCmd in first.thatGate)
- {
- requires.Add(new Requires(false, assertCmd.Expr));
- Ensures ensureCheck = new Ensures(assertCmd.tok, false, assertCmd.Expr, null);
- ensureCheck.ErrorData = string.Format("Gate not preserved by {0}", second.proc.Name);
- ensures.Add(ensureCheck);
- }
- foreach (AssertCmd assertCmd in second.thisGate)
- requires.Add(new Requires(false, assertCmd.Expr));
- string checkerName = string.Format("GatePreservationChecker_{0}_{1}", first.proc.Name, second.proc.Name);
- List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
- moverTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
- Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
- Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, secondBlocks);
- impl.Proc = proc;
- this.decls.Add(impl);
- this.decls.Add(proc);
- }
-
- private void CreateFailurePreservationChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
- {
- if (first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Count() == 0)
- return;
- Tuple<AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple<AtomicActionInfo, AtomicActionInfo>(first, second);
- if (failurePreservationCheckerCache.Contains(actionPair))
- return;
- failurePreservationCheckerCache.Add(actionPair);
-
- List<Variable> inputs = new List<Variable>();
- inputs.AddRange(first.thatInParams);
- inputs.AddRange(second.thisInParams);
- List<Variable> outputs = new List<Variable>();
- outputs.AddRange(first.thatOutParams);
- outputs.AddRange(second.thisOutParams);
- List<Variable> locals = new List<Variable>();
- locals.AddRange(second.thisAction.LocVars);
- List<Block> secondBlocks = CloneBlocks(second.thisAction.Blocks);
- HashSet<Variable> frame = new HashSet<Variable>();
- frame.UnionWith(first.gateUsedGlobalVars);
- frame.UnionWith(second.gateUsedGlobalVars);
- frame.UnionWith(second.actionUsedGlobalVars);
- List<Requires> requires = DisjointnessRequires(program, first, second, frame);
- Expr gateExpr = Expr.True;
- foreach (AssertCmd assertCmd in first.thatGate)
- {
- gateExpr = Expr.And(gateExpr, assertCmd.Expr);
- gateExpr.Type = Type.Bool;
- }
- gateExpr = Expr.Not(gateExpr);
- gateExpr.Type = Type.Bool;
- requires.Add(new Requires(false, gateExpr));
- List<Ensures> ensures = new List<Ensures>();
- Ensures ensureCheck = new Ensures(false, gateExpr);
- ensureCheck.ErrorData = string.Format("Gate failure of {0} not preserved by {1}", first.proc.Name, second.proc.Name);
- ensures.Add(ensureCheck);
- foreach (AssertCmd assertCmd in second.thisGate)
- requires.Add(new Requires(false, assertCmd.Expr));
- string checkerName = string.Format("FailurePreservationChecker_{0}_{1}", first.proc.Name, second.proc.Name);
- List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
- moverTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
- Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
- Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, secondBlocks);
- impl.Proc = proc;
- this.decls.Add(impl);
- this.decls.Add(proc);
- }
-
- private void CreateNonBlockingChecker(Program program, AtomicActionInfo second)
- {
- List<Variable> inputs = new List<Variable>();
- inputs.AddRange(second.thisInParams);
-
- HashSet<Variable> frame = new HashSet<Variable>();
- frame.UnionWith(second.gateUsedGlobalVars);
- frame.UnionWith(second.actionUsedGlobalVars);
- List<Requires> requires = DisjointnessRequires(program, null, second, frame);
- foreach (AssertCmd assertCmd in second.thisGate)
- {
- requires.Add(new Requires(false, assertCmd.Expr));
- }
- HashSet<Variable> postExistVars = new HashSet<Variable>();
- postExistVars.UnionWith(frame);
- postExistVars.UnionWith(second.thisOutParams);
- Expr ensuresExpr = (new TransitionRelationComputation(program, second, frame, postExistVars)).TransitionRelationCompute();
- List<Ensures> ensures = new List<Ensures>();
- Ensures ensureCheck = new Ensures(false, ensuresExpr);
- ensureCheck.ErrorData = string.Format("{0} is blocking", second.proc.Name);
- ensures.Add(ensureCheck);
-
- List<Block> blocks = new List<Block>();
- blocks.Add(new Block(Token.NoToken, "L", new List<Cmd>(), new ReturnCmd(Token.NoToken)));
- string checkerName = string.Format("NonBlockingChecker_{0}", second.proc.Name);
- List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
- moverTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
- Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, new List<Variable>(), requires, globalVars, ensures);
- Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks);
- impl.Proc = proc;
- this.decls.Add(impl);
- this.decls.Add(proc);
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics.Contracts;
+using System.Diagnostics;
+
+namespace Microsoft.Boogie
+{
+ public class MoverCheck
+ {
+ LinearTypeChecker linearTypeChecker;
+ CivlTypeChecker civlTypeChecker;
+ List<Declaration> decls;
+ HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>> commutativityCheckerCache;
+ HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>> gatePreservationCheckerCache;
+ HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>> failurePreservationCheckerCache;
+ private MoverCheck(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List<Declaration> decls)
+ {
+ this.linearTypeChecker = linearTypeChecker;
+ this.civlTypeChecker = civlTypeChecker;
+ this.decls = decls;
+ this.commutativityCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>();
+ this.gatePreservationCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>();
+ this.failurePreservationCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>();
+ }
+
+ public static void AddCheckers(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List<Declaration> decls)
+ {
+ if (civlTypeChecker.procToActionInfo.Count == 0)
+ return;
+
+ List<ActionInfo> sortedByCreatedLayerNum = new List<ActionInfo>(civlTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo && !x.isExtern));
+ sortedByCreatedLayerNum.Sort((x, y) => { return (x.createdAtLayerNum == y.createdAtLayerNum) ? 0 : (x.createdAtLayerNum < y.createdAtLayerNum) ? -1 : 1; });
+ List<ActionInfo> sortedByAvailableUptoLayerNum = new List<ActionInfo>(civlTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo && !x.isExtern));
+ sortedByAvailableUptoLayerNum.Sort((x, y) => { return (x.availableUptoLayerNum == y.availableUptoLayerNum) ? 0 : (x.availableUptoLayerNum < y.availableUptoLayerNum) ? -1 : 1; });
+
+ Dictionary<int, HashSet<AtomicActionInfo>> pools = new Dictionary<int, HashSet<AtomicActionInfo>>();
+ int indexIntoSortedByCreatedLayerNum = 0;
+ int indexIntoSortedByAvailableUptoLayerNum = 0;
+ HashSet<AtomicActionInfo> currPool = new HashSet<AtomicActionInfo>();
+ while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count)
+ {
+ var currLayerNum = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum].createdAtLayerNum;
+ pools[currLayerNum] = new HashSet<AtomicActionInfo>(currPool);
+ while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count)
+ {
+ var actionInfo = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum] as AtomicActionInfo;
+ if (actionInfo.createdAtLayerNum > currLayerNum) break;
+ pools[currLayerNum].Add(actionInfo);
+ indexIntoSortedByCreatedLayerNum++;
+ }
+ while (indexIntoSortedByAvailableUptoLayerNum < sortedByAvailableUptoLayerNum.Count)
+ {
+ var actionInfo = sortedByAvailableUptoLayerNum[indexIntoSortedByAvailableUptoLayerNum] as AtomicActionInfo;
+ if (actionInfo.availableUptoLayerNum > currLayerNum) break;
+ pools[currLayerNum].Remove(actionInfo);
+ indexIntoSortedByAvailableUptoLayerNum++;
+ }
+ currPool = pools[currLayerNum];
+ }
+
+ Program program = civlTypeChecker.program;
+ MoverCheck moverChecking = new MoverCheck(linearTypeChecker, civlTypeChecker, decls);
+ foreach (int layerNum in pools.Keys)
+ {
+ foreach (AtomicActionInfo first in pools[layerNum])
+ {
+ Debug.Assert(first.moverType != MoverType.Top);
+ if (first.moverType == MoverType.Atomic)
+ continue;
+ foreach (AtomicActionInfo second in pools[layerNum])
+ {
+ if (first.IsRightMover)
+ {
+ moverChecking.CreateCommutativityChecker(program, first, second);
+ moverChecking.CreateGatePreservationChecker(program, second, first);
+ }
+ if (first.IsLeftMover)
+ {
+ moverChecking.CreateCommutativityChecker(program, second, first);
+ moverChecking.CreateGatePreservationChecker(program, first, second);
+ moverChecking.CreateFailurePreservationChecker(program, second, first);
+ }
+ }
+ }
+ }
+ foreach (AtomicActionInfo atomicActionInfo in sortedByCreatedLayerNum)
+ {
+ if (atomicActionInfo.IsLeftMover && atomicActionInfo.hasAssumeCmd)
+ {
+ moverChecking.CreateNonBlockingChecker(program, atomicActionInfo);
+ }
+ }
+ }
+
+ public sealed class MyDuplicator : Duplicator
+ {
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ IdentifierExpr ret = (IdentifierExpr) base.VisitIdentifierExpr(node);
+ if (ret.Decl is GlobalVariable)
+ {
+ return new OldExpr(Token.NoToken, ret);
+ }
+ else
+ {
+ return ret;
+ }
+ }
+ }
+
+ public class TransitionRelationComputation
+ {
+ private Program program;
+ private AtomicActionInfo first; // corresponds to that*
+ private AtomicActionInfo second; // corresponds to this*
+ private Stack<Cmd> cmdStack;
+ private List<PathInfo> paths;
+ private HashSet<Variable> frame;
+ private HashSet<Variable> postExistVars;
+
+ public TransitionRelationComputation(Program program, AtomicActionInfo second, HashSet<Variable> frame, HashSet<Variable> postExistVars)
+ {
+ this.postExistVars = postExistVars;
+ this.frame = frame;
+ TransitionRelationComputationHelper(program, null, second);
+ }
+
+ public TransitionRelationComputation(Program program, AtomicActionInfo first, AtomicActionInfo second, HashSet<Variable> frame, HashSet<Variable> postExistVars)
+ {
+ this.postExistVars = postExistVars;
+ this.frame = frame;
+ TransitionRelationComputationHelper(program, first, second);
+ }
+
+ private void TransitionRelationComputationHelper(Program program, AtomicActionInfo first, AtomicActionInfo second)
+ {
+ this.program = program;
+ this.first = first;
+ this.second = second;
+ this.cmdStack = new Stack<Cmd>();
+ this.paths = new List<PathInfo>();
+ List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
+ this.second.thisOutParams.ForEach(v => havocVars.Add(Expr.Ident(v)));
+ this.second.thisAction.LocVars.ForEach(v => havocVars.Add(Expr.Ident(v)));
+ if (havocVars.Count > 0)
+ {
+ HavocCmd havocCmd = new HavocCmd(Token.NoToken, havocVars);
+ cmdStack.Push(havocCmd);
+ }
+ Search(this.second.thisAction.Blocks[0], false);
+ }
+
+ private void Substitute(Dictionary<Variable, Expr> map, ref List<Expr> pathExprs, ref Dictionary<Variable, Expr> varToExpr)
+ {
+ Substitution subst = Substituter.SubstitutionFromHashtable(map);
+ List<Expr> oldPathExprs = pathExprs;
+ pathExprs = new List<Expr>();
+ foreach (Expr pathExpr in oldPathExprs)
+ {
+ pathExprs.Add(Substituter.Apply(subst, pathExpr));
+ }
+ Dictionary<Variable, Expr> oldVarToExpr = varToExpr;
+ varToExpr = new Dictionary<Variable, Expr>();
+ foreach (Variable v in oldVarToExpr.Keys)
+ {
+ varToExpr[v] = Substituter.Apply(subst, oldVarToExpr[v]);
+ }
+ }
+
+ struct PathInfo
+ {
+ public HashSet<Variable> existsVars;
+ public Dictionary<Variable, Expr> varToExpr;
+ public List<Expr> pathExprs;
+
+ public PathInfo(HashSet<Variable> existsVars, Dictionary<Variable, Expr> varToExpr, List<Expr> pathExprs)
+ {
+ this.existsVars = existsVars;
+ this.varToExpr = varToExpr;
+ this.pathExprs = pathExprs;
+ }
+ }
+
+ private void FlattenAnd(Expr x, List<Expr> xs)
+ {
+ NAryExpr naryExpr = x as NAryExpr;
+ if (naryExpr != null && naryExpr.Fun.FunctionName == "&&")
+ {
+ FlattenAnd(naryExpr.Args[0], xs);
+ FlattenAnd(naryExpr.Args[1], xs);
+ }
+ else
+ {
+ xs.Add(x);
+ }
+ }
+
+ private void AddPath()
+ {
+ HashSet<Variable> existsVars = new HashSet<Variable>();
+ Dictionary<Variable, Expr> varToExpr = new Dictionary<Variable, Expr>();
+ foreach (Variable v in frame)
+ {
+ varToExpr[v] = Expr.Ident(v);
+ }
+ if (first != null)
+ {
+ foreach (Variable v in first.thatOutParams)
+ {
+ varToExpr[v] = Expr.Ident(v);
+ }
+ }
+ foreach (Variable v in second.thisOutParams)
+ {
+ varToExpr[v] = Expr.Ident(v);
+ }
+ List<Expr> pathExprs = new List<Expr>();
+ int boundVariableCount = 0;
+ foreach (Cmd cmd in cmdStack)
+ {
+ if (cmd is AssumeCmd)
+ {
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ FlattenAnd(assumeCmd.Expr, pathExprs);
+ }
+ else if (cmd is AssignCmd)
+ {
+ AssignCmd assignCmd = (cmd as AssignCmd).AsSimpleAssignCmd;
+ Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
+ for (int k = 0; k < assignCmd.Lhss.Count; k++)
+ {
+ map[assignCmd.Lhss[k].DeepAssignedVariable] = assignCmd.Rhss[k];
+ }
+ Substitute(map, ref pathExprs, ref varToExpr);
+ }
+ else if (cmd is HavocCmd)
+ {
+ HavocCmd havocCmd = cmd as HavocCmd;
+ Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
+ foreach (IdentifierExpr ie in havocCmd.Vars)
+ {
+ BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "#tmp_" + boundVariableCount++, ie.Decl.TypedIdent.Type));
+ map[ie.Decl] = Expr.Ident(bv);
+ existsVars.Add(bv);
+ }
+ Substitute(map, ref pathExprs, ref varToExpr);
+ }
+ else
+ {
+ Debug.Assert(false);
+ }
+ }
+ paths.Add(new PathInfo(existsVars, varToExpr, pathExprs));
+ }
+
+ private Expr CalculatePathCondition(PathInfo path)
+ {
+ Expr returnExpr = Expr.True;
+
+ HashSet<Variable> existsVars = path.existsVars;
+ Dictionary<Variable, Expr> existsMap = new Dictionary<Variable, Expr>();
+
+ Dictionary<Variable, Expr> varToExpr = path.varToExpr;
+ foreach (Variable v in varToExpr.Keys)
+ {
+ if (postExistVars.Contains(v)) continue;
+ IdentifierExpr ie = varToExpr[v] as IdentifierExpr;
+ if (ie != null && !existsMap.ContainsKey(ie.Decl) && existsVars.Contains(ie.Decl))
+ {
+ existsMap[ie.Decl] = Expr.Ident(v);
+ existsVars.Remove(ie.Decl);
+ }
+ else
+ {
+ returnExpr = Expr.And(returnExpr, Expr.Eq(Expr.Ident(v), (new MyDuplicator()).VisitExpr(varToExpr[v])));
+ returnExpr.Type = Type.Bool;
+ }
+ }
+
+ List<Expr> pathExprs = new List<Expr>();
+ path.pathExprs.ForEach(x => pathExprs.Add((new MyDuplicator()).VisitExpr(x)));
+ foreach (Expr x in pathExprs)
+ {
+ Variable boundVar;
+ Expr boundVarExpr;
+ if (InferSubstitution(x, out boundVar, out boundVarExpr) && existsVars.Contains(boundVar))
+ {
+ existsMap[boundVar] = boundVarExpr;
+ existsVars.Remove(boundVar);
+ }
+ else
+ {
+ returnExpr = Expr.And(returnExpr, x);
+ returnExpr.Type = Type.Bool;
+ }
+ }
+
+ returnExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(existsMap), returnExpr);
+ if (existsVars.Count > 0)
+ {
+ returnExpr = new ExistsExpr(Token.NoToken, new List<Variable>(existsVars), returnExpr);
+ }
+ return returnExpr;
+ }
+
+ bool InferSubstitution(Expr x, out Variable var, out Expr expr)
+ {
+ var = null;
+ expr = null;
+ NAryExpr naryExpr = x as NAryExpr;
+ if (naryExpr == null || naryExpr.Fun.FunctionName != "==")
+ {
+ return false;
+ }
+ IdentifierExpr arg0 = naryExpr.Args[0] as IdentifierExpr;
+ if (arg0 != null && arg0.Decl is BoundVariable)
+ {
+ var = arg0.Decl;
+ expr = naryExpr.Args[1];
+ return true;
+ }
+ IdentifierExpr arg1 = naryExpr.Args[1] as IdentifierExpr;
+ if (arg1 != null && arg1.Decl is BoundVariable)
+ {
+ var = arg1.Decl;
+ expr = naryExpr.Args[0];
+ return true;
+ }
+ return false;
+ }
+
+ public Expr TransitionRelationCompute(bool withOriginalInOutVariables = false)
+ {
+ Expr transitionRelation = Expr.False;
+ foreach (PathInfo path in paths)
+ {
+ transitionRelation = Expr.Or(transitionRelation, CalculatePathCondition(path));
+ }
+ ResolutionContext rc = new ResolutionContext(null);
+ rc.StateMode = ResolutionContext.State.Two;
+ transitionRelation.Resolve(rc);
+ transitionRelation.Typecheck(new TypecheckingContext(null));
+
+ if (withOriginalInOutVariables)
+ {
+ Dictionary<Variable, Expr> invertedMap = new Dictionary<Variable, Expr>();
+ if (first != null)
+ {
+ foreach (var x in first.thatMap)
+ {
+ invertedMap[((IdentifierExpr)x.Value).Decl] = Expr.Ident(x.Key);
+ }
+ }
+ if (second != null)
+ {
+ foreach (var x in second.thisMap)
+ {
+ invertedMap[((IdentifierExpr)x.Value).Decl] = Expr.Ident(x.Key);
+ }
+ }
+ Substitution subst = Substituter.SubstitutionFromHashtable(invertedMap);
+ return Substituter.Apply(subst, transitionRelation);
+ }
+ else
+ {
+ return transitionRelation;
+ }
+
+ }
+
+ private void Search(Block b, bool inFirst)
+ {
+ int pathSizeAtEntry = cmdStack.Count;
+ foreach (Cmd cmd in b.Cmds)
+ {
+ cmdStack.Push(cmd);
+ }
+ if (b.TransferCmd is ReturnCmd)
+ {
+ if (first == null || inFirst)
+ {
+ AddPath();
+ }
+ else
+ {
+ List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
+ first.thatOutParams.ForEach(v => havocVars.Add(Expr.Ident(v)));
+ first.thatAction.LocVars.ForEach(v => havocVars.Add(Expr.Ident(v)));
+ if (havocVars.Count > 0)
+ {
+ HavocCmd havocCmd = new HavocCmd(Token.NoToken, havocVars);
+ cmdStack.Push(havocCmd);
+ }
+ Search(first.thatAction.Blocks[0], true);
+ }
+ }
+ else
+ {
+ GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
+ foreach (Block target in gotoCmd.labelTargets)
+ {
+ Search(target, inFirst);
+ }
+ }
+ Debug.Assert(cmdStack.Count >= pathSizeAtEntry);
+ while (cmdStack.Count > pathSizeAtEntry)
+ {
+ cmdStack.Pop();
+ }
+ }
+ }
+
+ private static List<Block> CloneBlocks(List<Block> blocks)
+ {
+ Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
+ List<Block> otherBlocks = new List<Block>();
+ foreach (Block block in blocks)
+ {
+ List<Cmd> otherCmds = new List<Cmd>();
+ foreach (Cmd cmd in block.Cmds)
+ {
+ otherCmds.Add(cmd);
+ }
+ Block otherBlock = new Block();
+ otherBlock.Cmds = otherCmds;
+ otherBlock.Label = block.Label;
+ otherBlocks.Add(otherBlock);
+ blockMap[block] = otherBlock;
+ }
+ foreach (Block block in blocks)
+ {
+ if (block.TransferCmd is ReturnCmd) continue;
+ List<Block> otherGotoCmdLabelTargets = new List<Block>();
+ List<string> otherGotoCmdLabelNames = new List<string>();
+ GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
+ foreach (Block target in gotoCmd.labelTargets)
+ {
+ otherGotoCmdLabelTargets.Add(blockMap[target]);
+ otherGotoCmdLabelNames.Add(blockMap[target].Label);
+ }
+ blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets);
+ }
+ return otherBlocks;
+ }
+
+ private List<Requires> DisjointnessRequires(Program program, AtomicActionInfo first, AtomicActionInfo second, HashSet<Variable> frame)
+ {
+ List<Requires> requires = new List<Requires>();
+ Dictionary<string, HashSet<Variable>> domainNameToScope = new Dictionary<string, HashSet<Variable>>();
+ foreach (var domainName in linearTypeChecker.linearDomains.Keys)
+ {
+ domainNameToScope[domainName] = new HashSet<Variable>();
+ }
+ foreach (Variable v in frame)
+ {
+ var domainName = linearTypeChecker.FindDomainName(v);
+ if (domainName == null) continue;
+ if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
+ domainNameToScope[domainName].Add(v);
+ }
+ if (first != null)
+ {
+ foreach (Variable v in first.thatInParams)
+ {
+ var domainName = linearTypeChecker.FindDomainName(v);
+ if (domainName == null) continue;
+ if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
+ domainNameToScope[domainName].Add(v);
+ }
+ }
+ foreach (Variable v in second.thisInParams)
+ {
+ var domainName = linearTypeChecker.FindDomainName(v);
+ if (domainName == null) continue;
+ if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
+ domainNameToScope[domainName].Add(v);
+ }
+ foreach (string domainName in domainNameToScope.Keys)
+ {
+ requires.Add(new Requires(false, linearTypeChecker.DisjointnessExpr(domainName, domainNameToScope[domainName])));
+ }
+ return requires;
+ }
+
+ private void CreateCommutativityChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
+ {
+ if (first == second && first.thatInParams.Count == 0 && first.thatOutParams.Count == 0)
+ return;
+ if (first.CommutesWith(second))
+ return;
+ Tuple<AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple<AtomicActionInfo, AtomicActionInfo>(first, second);
+ if (commutativityCheckerCache.Contains(actionPair))
+ return;
+ commutativityCheckerCache.Add(actionPair);
+
+ List<Variable> inputs = new List<Variable>();
+ inputs.AddRange(first.thatInParams);
+ inputs.AddRange(second.thisInParams);
+ List<Variable> outputs = new List<Variable>();
+ outputs.AddRange(first.thatOutParams);
+ outputs.AddRange(second.thisOutParams);
+ List<Variable> locals = new List<Variable>();
+ locals.AddRange(first.thatAction.LocVars);
+ locals.AddRange(second.thisAction.LocVars);
+ List<Block> firstBlocks = CloneBlocks(first.thatAction.Blocks);
+ List<Block> secondBlocks = CloneBlocks(second.thisAction.Blocks);
+ foreach (Block b in firstBlocks)
+ {
+ if (b.TransferCmd is ReturnCmd)
+ {
+ List<Block> bs = new List<Block>();
+ bs.Add(secondBlocks[0]);
+ List<string> ls = new List<string>();
+ ls.Add(secondBlocks[0].Label);
+ b.TransferCmd = new GotoCmd(Token.NoToken, ls, bs);
+ }
+ }
+ List<Block> blocks = new List<Block>();
+ blocks.AddRange(firstBlocks);
+ blocks.AddRange(secondBlocks);
+ HashSet<Variable> frame = new HashSet<Variable>();
+ frame.UnionWith(first.gateUsedGlobalVars);
+ frame.UnionWith(first.actionUsedGlobalVars);
+ frame.UnionWith(second.gateUsedGlobalVars);
+ frame.UnionWith(second.actionUsedGlobalVars);
+ List<Requires> requires = DisjointnessRequires(program, first, second, frame);
+ foreach (AssertCmd assertCmd in first.thatGate)
+ requires.Add(new Requires(false, assertCmd.Expr));
+ foreach (AssertCmd assertCmd in second.thisGate)
+ requires.Add(new Requires(false, assertCmd.Expr));
+ List<Ensures> ensures = new List<Ensures>();
+ Expr transitionRelation = (new TransitionRelationComputation(program, first, second, frame, new HashSet<Variable>())).TransitionRelationCompute();
+ Ensures ensureCheck = new Ensures(false, transitionRelation);
+ ensureCheck.ErrorData = string.Format("Commutativity check between {0} and {1} failed", first.proc.Name, second.proc.Name);
+ ensures.Add(ensureCheck);
+ string checkerName = string.Format("CommutativityChecker_{0}_{1}", first.proc.Name, second.proc.Name);
+ List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
+ civlTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
+ Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
+ Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, blocks);
+ impl.Proc = proc;
+ this.decls.Add(impl);
+ this.decls.Add(proc);
+ }
+
+ private void CreateGatePreservationChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
+ {
+ if (first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Count() == 0)
+ return;
+ Tuple<AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple<AtomicActionInfo, AtomicActionInfo>(first, second);
+ if (gatePreservationCheckerCache.Contains(actionPair))
+ return;
+ gatePreservationCheckerCache.Add(actionPair);
+
+ List<Variable> inputs = new List<Variable>();
+ inputs.AddRange(first.thatInParams);
+ inputs.AddRange(second.thisInParams);
+ List<Variable> outputs = new List<Variable>();
+ outputs.AddRange(first.thatOutParams);
+ outputs.AddRange(second.thisOutParams);
+ List<Variable> locals = new List<Variable>();
+ locals.AddRange(second.thisAction.LocVars);
+ List<Block> secondBlocks = CloneBlocks(second.thisAction.Blocks);
+ HashSet<Variable> frame = new HashSet<Variable>();
+ frame.UnionWith(first.gateUsedGlobalVars);
+ frame.UnionWith(second.gateUsedGlobalVars);
+ frame.UnionWith(second.actionUsedGlobalVars);
+ List<Requires> requires = DisjointnessRequires(program, first, second, frame);
+ List<Ensures> ensures = new List<Ensures>();
+ foreach (AssertCmd assertCmd in first.thatGate)
+ {
+ requires.Add(new Requires(false, assertCmd.Expr));
+ Ensures ensureCheck = new Ensures(assertCmd.tok, false, assertCmd.Expr, null);
+ ensureCheck.ErrorData = string.Format("Gate not preserved by {0}", second.proc.Name);
+ ensures.Add(ensureCheck);
+ }
+ foreach (AssertCmd assertCmd in second.thisGate)
+ requires.Add(new Requires(false, assertCmd.Expr));
+ string checkerName = string.Format("GatePreservationChecker_{0}_{1}", first.proc.Name, second.proc.Name);
+ List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
+ civlTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
+ Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
+ Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, secondBlocks);
+ impl.Proc = proc;
+ this.decls.Add(impl);
+ this.decls.Add(proc);
+ }
+
+ private void CreateFailurePreservationChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
+ {
+ if (first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Count() == 0)
+ return;
+ Tuple<AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple<AtomicActionInfo, AtomicActionInfo>(first, second);
+ if (failurePreservationCheckerCache.Contains(actionPair))
+ return;
+ failurePreservationCheckerCache.Add(actionPair);
+
+ List<Variable> inputs = new List<Variable>();
+ inputs.AddRange(first.thatInParams);
+ inputs.AddRange(second.thisInParams);
+ List<Variable> outputs = new List<Variable>();
+ outputs.AddRange(first.thatOutParams);
+ outputs.AddRange(second.thisOutParams);
+ List<Variable> locals = new List<Variable>();
+ locals.AddRange(second.thisAction.LocVars);
+ List<Block> secondBlocks = CloneBlocks(second.thisAction.Blocks);
+ HashSet<Variable> frame = new HashSet<Variable>();
+ frame.UnionWith(first.gateUsedGlobalVars);
+ frame.UnionWith(second.gateUsedGlobalVars);
+ frame.UnionWith(second.actionUsedGlobalVars);
+ List<Requires> requires = DisjointnessRequires(program, first, second, frame);
+ Expr gateExpr = Expr.True;
+ foreach (AssertCmd assertCmd in first.thatGate)
+ {
+ gateExpr = Expr.And(gateExpr, assertCmd.Expr);
+ gateExpr.Type = Type.Bool;
+ }
+ gateExpr = Expr.Not(gateExpr);
+ gateExpr.Type = Type.Bool;
+ requires.Add(new Requires(false, gateExpr));
+ List<Ensures> ensures = new List<Ensures>();
+ Ensures ensureCheck = new Ensures(false, gateExpr);
+ ensureCheck.ErrorData = string.Format("Gate failure of {0} not preserved by {1}", first.proc.Name, second.proc.Name);
+ ensures.Add(ensureCheck);
+ foreach (AssertCmd assertCmd in second.thisGate)
+ requires.Add(new Requires(false, assertCmd.Expr));
+ string checkerName = string.Format("FailurePreservationChecker_{0}_{1}", first.proc.Name, second.proc.Name);
+ List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
+ civlTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
+ Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
+ Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, secondBlocks);
+ impl.Proc = proc;
+ this.decls.Add(impl);
+ this.decls.Add(proc);
+ }
+
+ private void CreateNonBlockingChecker(Program program, AtomicActionInfo second)
+ {
+ List<Variable> inputs = new List<Variable>();
+ inputs.AddRange(second.thisInParams);
+
+ HashSet<Variable> frame = new HashSet<Variable>();
+ frame.UnionWith(second.gateUsedGlobalVars);
+ frame.UnionWith(second.actionUsedGlobalVars);
+ List<Requires> requires = DisjointnessRequires(program, null, second, frame);
+ foreach (AssertCmd assertCmd in second.thisGate)
+ {
+ requires.Add(new Requires(false, assertCmd.Expr));
+ }
+ HashSet<Variable> postExistVars = new HashSet<Variable>();
+ postExistVars.UnionWith(frame);
+ postExistVars.UnionWith(second.thisOutParams);
+ Expr ensuresExpr = (new TransitionRelationComputation(program, second, frame, postExistVars)).TransitionRelationCompute();
+ List<Ensures> ensures = new List<Ensures>();
+ Ensures ensureCheck = new Ensures(false, ensuresExpr);
+ ensureCheck.ErrorData = string.Format("{0} is blocking", second.proc.Name);
+ ensures.Add(ensureCheck);
+
+ List<Block> blocks = new List<Block>();
+ blocks.Add(new Block(Token.NoToken, "L", new List<Cmd>(), new ReturnCmd(Token.NoToken)));
+ string checkerName = string.Format("NonBlockingChecker_{0}", second.proc.Name);
+ List<IdentifierExpr> globalVars = new List<IdentifierExpr>();
+ civlTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
+ Procedure proc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, new List<Variable>(), requires, globalVars, ensures);
+ Implementation impl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks);
+ impl.Proc = proc;
+ this.decls.Add(impl);
+ this.decls.Add(proc);
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Concurrency/Program.cs b/Source/Concurrency/Program.cs
index 8042476e..1be7cc07 100644
--- a/Source/Concurrency/Program.cs
+++ b/Source/Concurrency/Program.cs
@@ -1,44 +1,44 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Microsoft.Boogie
-{
- public class Concurrency
- {
- public static void Transform(LinearTypeChecker linearTypeChecker, MoverTypeChecker moverTypeChecker)
- {
- List<Declaration> originalDecls = new List<Declaration>();
- Program program = linearTypeChecker.program;
- foreach (var decl in program.TopLevelDeclarations)
- {
- Procedure proc = decl as Procedure;
- if (proc != null && moverTypeChecker.procToActionInfo.ContainsKey(proc))
- {
- originalDecls.Add(proc);
- continue;
- }
- Implementation impl = decl as Implementation;
- if (impl != null && moverTypeChecker.procToActionInfo.ContainsKey(impl.Proc))
- {
- originalDecls.Add(impl);
- }
- }
-
- List<Declaration> decls = new List<Declaration>();
- if (!CommandLineOptions.Clo.TrustAtomicityTypes)
- {
- MoverCheck.AddCheckers(linearTypeChecker, moverTypeChecker, decls);
- }
- OwickiGries.AddCheckers(linearTypeChecker, moverTypeChecker, decls);
- foreach (Declaration decl in decls)
- {
- decl.Attributes = OwickiGries.RemoveYieldsAttribute(decl.Attributes);
- }
- program.RemoveTopLevelDeclarations(x => originalDecls.Contains(x));
- program.AddTopLevelDeclarations(decls);
- }
-
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Boogie
+{
+ public class Concurrency
+ {
+ public static void Transform(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker)
+ {
+ List<Declaration> originalDecls = new List<Declaration>();
+ Program program = linearTypeChecker.program;
+ foreach (var decl in program.TopLevelDeclarations)
+ {
+ Procedure proc = decl as Procedure;
+ if (proc != null && civlTypeChecker.procToActionInfo.ContainsKey(proc))
+ {
+ originalDecls.Add(proc);
+ continue;
+ }
+ Implementation impl = decl as Implementation;
+ if (impl != null && civlTypeChecker.procToActionInfo.ContainsKey(impl.Proc))
+ {
+ originalDecls.Add(impl);
+ }
+ }
+
+ List<Declaration> decls = new List<Declaration>();
+ if (!CommandLineOptions.Clo.TrustAtomicityTypes)
+ {
+ MoverCheck.AddCheckers(linearTypeChecker, civlTypeChecker, decls);
+ }
+ CivlRefinement.AddCheckers(linearTypeChecker, civlTypeChecker, decls);
+ foreach (Declaration decl in decls)
+ {
+ decl.Attributes = CivlRefinement.RemoveYieldsAttribute(decl.Attributes);
+ }
+ program.RemoveTopLevelDeclarations(x => originalDecls.Contains(x));
+ program.AddTopLevelDeclarations(decls);
+ }
+
+ }
+}
diff --git a/Source/Concurrency/Properties/AssemblyInfo.cs b/Source/Concurrency/Properties/AssemblyInfo.cs
index 48430488..7e90c12f 100644
--- a/Source/Concurrency/Properties/AssemblyInfo.cs
+++ b/Source/Concurrency/Properties/AssemblyInfo.cs
@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Concurrency")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Concurrency")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("867039c5-87dc-4f76-9f90-4f52afc90116")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Concurrency")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Concurrency")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("867039c5-87dc-4f76-9f90-4f52afc90116")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Concurrency/SimulationRelation.cs b/Source/Concurrency/SimulationRelation.cs
index 7f130f76..c97ebfb7 100644
--- a/Source/Concurrency/SimulationRelation.cs
+++ b/Source/Concurrency/SimulationRelation.cs
@@ -1,197 +1,197 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie
-{
- public class SimulationRelation<A, B, L>
- {
- class Graph<T>
- {
- HashSet<T> nodes;
- Dictionary<T, Dictionary<L, List<T>>> successors;
- Dictionary<T, Dictionary<L, List<T>>> predecessors;
-
- public Graph(List<Tuple<T, L, T>> edges)
- {
- nodes = new HashSet<T>();
- successors = new Dictionary<T, Dictionary<L, List<T>>>();
- predecessors = new Dictionary<T, Dictionary<L, List<T>>>();
- foreach (Tuple<T, L, T> edge in edges)
- {
- T source = edge.Item1;
- L label = edge.Item2;
- T dest = edge.Item3;
- nodes.Add(source);
- nodes.Add(dest);
- if (!successors.ContainsKey(source))
- {
- successors[source] = new Dictionary<L, List<T>>();
- }
- if (!successors[source].ContainsKey(label))
- {
- successors[source][label] = new List<T>();
- }
- if (!predecessors.ContainsKey(dest))
- {
- predecessors[dest] = new Dictionary<L, List<T>>();
- }
- if (!predecessors[dest].ContainsKey(label))
- {
- predecessors[dest][label] = new List<T>();
- }
- successors[source][label].Add(dest);
- predecessors[dest][label].Add(source);
- }
- }
-
- public IEnumerable<T> Nodes { get { return nodes; } }
-
- public IEnumerable<T> Post(T t, L l)
- {
- if (successors.ContainsKey(t) && successors[t].ContainsKey(l))
- {
- return successors[t][l];
- }
- else
- {
- return Enumerable.Empty<T>();
- }
- }
-
- public IEnumerable<T> Post(IEnumerable<T> set, L l)
- {
- return set.Select(x => Post(x, l)).Aggregate(Enumerable.Empty<T>(), (p, q) => p.Concat(q));
- }
-
- public IEnumerable<T> Pre(T t, L l)
- {
- if (predecessors.ContainsKey(t) && predecessors[t].ContainsKey(l))
- {
- return predecessors[t][l];
- }
- else
- {
- return Enumerable.Empty<T>();
- }
- }
-
- public IEnumerable<T> Pre(IEnumerable<T> set, L l)
- {
- return set.Select(x => Pre(x, l)).Aggregate(Enumerable.Empty<T>(), (p, q) => p.Concat(q));
- }
-
- public IEnumerable<L> PostLabels(T t)
- {
- if (successors.ContainsKey(t))
- {
- return successors[t].Keys;
- }
- else
- {
- return Enumerable.Empty<L>();
- }
- }
-
- public IEnumerable<L> PreLabels(T t)
- {
- if (predecessors.ContainsKey(t))
- {
- return predecessors[t].Keys;
- }
- else
- {
- return Enumerable.Empty<L>();
- }
- }
- }
-
- Graph<A> aGraph;
- Graph<B> bGraph;
- Dictionary<A, HashSet<B>> initialConstraints;
-
- public SimulationRelation(List<Tuple<A, L, A>> aEdges, List<Tuple<B, L, B>> bEdges, Dictionary<A, HashSet<B>> initialConstraints)
- {
- this.aGraph = new Graph<A>(aEdges);
- this.bGraph = new Graph<B>(bEdges);
- this.initialConstraints = initialConstraints;
- }
-
- public Dictionary<A, HashSet<B>> ComputeSimulationRelation()
- {
- Dictionary<A, HashSet<B>> prevsim;
- Dictionary<A, HashSet<B>> sim;
- Dictionary<Tuple<A, L>, HashSet<B>> remove;
- Queue<Tuple<A,L>> workQueue;
-
- prevsim = new Dictionary<A, HashSet<B>>();
- sim = new Dictionary<A, HashSet<B>>();
- remove = new Dictionary<Tuple<A, L>, HashSet<B>>();
- workQueue = new Queue<Tuple<A,L>>();
- foreach (var a in aGraph.Nodes)
- {
- prevsim[a] = new HashSet<B>(bGraph.Nodes);
- sim[a] = new HashSet<B>();
- HashSet<L> aOutgoingLabels = new HashSet<L>(aGraph.PostLabels(a));
- foreach (var b in bGraph.Nodes)
- {
- IEnumerable<L> bOutgoingLabels = bGraph.PostLabels(b);
- if (aOutgoingLabels.IsSubsetOf(bOutgoingLabels))
- {
- sim[a].Add(b);
- }
- }
- if (initialConstraints.ContainsKey(a))
- {
- sim[a].IntersectWith(initialConstraints[a]);
- }
-
- foreach (var l in aGraph.PreLabels(a))
- {
- Tuple<A, L> x = new Tuple<A, L>(a, l);
- remove[x] = new HashSet<B>(bGraph.Pre(prevsim[a], l).Except(bGraph.Pre(sim[a], l)));
- if (remove[x].Count > 0)
- {
- workQueue.Enqueue(x);
- }
- }
- }
-
- while (workQueue.Count > 0)
- {
- Tuple<A,L> x = workQueue.Dequeue();
- A v = x.Item1;
- foreach (A u in aGraph.Pre(v, x.Item2))
- {
- foreach (B w in remove[x])
- {
- if (sim[u].Contains(w))
- {
- sim[u].Remove(w);
- foreach (L l in bGraph.PreLabels(w))
- {
- foreach (B b in bGraph.Pre(w, l))
- {
- if (bGraph.Post(b, l).Intersect(sim[u]).Count() == 0)
- {
- Tuple<A, L> z = new Tuple<A, L>(u, l);
- if (!remove.ContainsKey(z))
- remove[z] = new HashSet<B>();
- remove[z].Add(b);
- workQueue.Enqueue(z);
- }
- }
- }
- }
- }
- }
- prevsim[v] = new HashSet<B>(sim[v]);
- remove[x] = new HashSet<B>();
- }
-
- return sim;
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie
+{
+ public class SimulationRelation<A, B, L>
+ {
+ class Graph<T>
+ {
+ HashSet<T> nodes;
+ Dictionary<T, Dictionary<L, List<T>>> successors;
+ Dictionary<T, Dictionary<L, List<T>>> predecessors;
+
+ public Graph(List<Tuple<T, L, T>> edges)
+ {
+ nodes = new HashSet<T>();
+ successors = new Dictionary<T, Dictionary<L, List<T>>>();
+ predecessors = new Dictionary<T, Dictionary<L, List<T>>>();
+ foreach (Tuple<T, L, T> edge in edges)
+ {
+ T source = edge.Item1;
+ L label = edge.Item2;
+ T dest = edge.Item3;
+ nodes.Add(source);
+ nodes.Add(dest);
+ if (!successors.ContainsKey(source))
+ {
+ successors[source] = new Dictionary<L, List<T>>();
+ }
+ if (!successors[source].ContainsKey(label))
+ {
+ successors[source][label] = new List<T>();
+ }
+ if (!predecessors.ContainsKey(dest))
+ {
+ predecessors[dest] = new Dictionary<L, List<T>>();
+ }
+ if (!predecessors[dest].ContainsKey(label))
+ {
+ predecessors[dest][label] = new List<T>();
+ }
+ successors[source][label].Add(dest);
+ predecessors[dest][label].Add(source);
+ }
+ }
+
+ public IEnumerable<T> Nodes { get { return nodes; } }
+
+ public IEnumerable<T> Post(T t, L l)
+ {
+ if (successors.ContainsKey(t) && successors[t].ContainsKey(l))
+ {
+ return successors[t][l];
+ }
+ else
+ {
+ return Enumerable.Empty<T>();
+ }
+ }
+
+ public IEnumerable<T> Post(IEnumerable<T> set, L l)
+ {
+ return set.Select(x => Post(x, l)).Aggregate(Enumerable.Empty<T>(), (p, q) => p.Concat(q));
+ }
+
+ public IEnumerable<T> Pre(T t, L l)
+ {
+ if (predecessors.ContainsKey(t) && predecessors[t].ContainsKey(l))
+ {
+ return predecessors[t][l];
+ }
+ else
+ {
+ return Enumerable.Empty<T>();
+ }
+ }
+
+ public IEnumerable<T> Pre(IEnumerable<T> set, L l)
+ {
+ return set.Select(x => Pre(x, l)).Aggregate(Enumerable.Empty<T>(), (p, q) => p.Concat(q));
+ }
+
+ public IEnumerable<L> PostLabels(T t)
+ {
+ if (successors.ContainsKey(t))
+ {
+ return successors[t].Keys;
+ }
+ else
+ {
+ return Enumerable.Empty<L>();
+ }
+ }
+
+ public IEnumerable<L> PreLabels(T t)
+ {
+ if (predecessors.ContainsKey(t))
+ {
+ return predecessors[t].Keys;
+ }
+ else
+ {
+ return Enumerable.Empty<L>();
+ }
+ }
+ }
+
+ Graph<A> aGraph;
+ Graph<B> bGraph;
+ Dictionary<A, HashSet<B>> initialConstraints;
+
+ public SimulationRelation(List<Tuple<A, L, A>> aEdges, List<Tuple<B, L, B>> bEdges, Dictionary<A, HashSet<B>> initialConstraints)
+ {
+ this.aGraph = new Graph<A>(aEdges);
+ this.bGraph = new Graph<B>(bEdges);
+ this.initialConstraints = initialConstraints;
+ }
+
+ public Dictionary<A, HashSet<B>> ComputeSimulationRelation()
+ {
+ Dictionary<A, HashSet<B>> prevsim;
+ Dictionary<A, HashSet<B>> sim;
+ Dictionary<Tuple<A, L>, HashSet<B>> remove;
+ Queue<Tuple<A,L>> workQueue;
+
+ prevsim = new Dictionary<A, HashSet<B>>();
+ sim = new Dictionary<A, HashSet<B>>();
+ remove = new Dictionary<Tuple<A, L>, HashSet<B>>();
+ workQueue = new Queue<Tuple<A,L>>();
+ foreach (var a in aGraph.Nodes)
+ {
+ prevsim[a] = new HashSet<B>(bGraph.Nodes);
+ sim[a] = new HashSet<B>();
+ HashSet<L> aOutgoingLabels = new HashSet<L>(aGraph.PostLabels(a));
+ foreach (var b in bGraph.Nodes)
+ {
+ IEnumerable<L> bOutgoingLabels = bGraph.PostLabels(b);
+ if (aOutgoingLabels.IsSubsetOf(bOutgoingLabels))
+ {
+ sim[a].Add(b);
+ }
+ }
+ if (initialConstraints.ContainsKey(a))
+ {
+ sim[a].IntersectWith(initialConstraints[a]);
+ }
+
+ foreach (var l in aGraph.PreLabels(a))
+ {
+ Tuple<A, L> x = new Tuple<A, L>(a, l);
+ remove[x] = new HashSet<B>(bGraph.Pre(prevsim[a], l).Except(bGraph.Pre(sim[a], l)));
+ if (remove[x].Count > 0)
+ {
+ workQueue.Enqueue(x);
+ }
+ }
+ }
+
+ while (workQueue.Count > 0)
+ {
+ Tuple<A,L> x = workQueue.Dequeue();
+ A v = x.Item1;
+ foreach (A u in aGraph.Pre(v, x.Item2))
+ {
+ foreach (B w in remove[x])
+ {
+ if (sim[u].Contains(w))
+ {
+ sim[u].Remove(w);
+ foreach (L l in bGraph.PreLabels(w))
+ {
+ foreach (B b in bGraph.Pre(w, l))
+ {
+ if (bGraph.Post(b, l).Intersect(sim[u]).Count() == 0)
+ {
+ Tuple<A, L> z = new Tuple<A, L>(u, l);
+ if (!remove.ContainsKey(z))
+ remove[z] = new HashSet<B>();
+ remove[z].Add(b);
+ workQueue.Enqueue(z);
+ }
+ }
+ }
+ }
+ }
+ }
+ prevsim[v] = new HashSet<B>(sim[v]);
+ remove[x] = new HashSet<B>();
+ }
+
+ return sim;
+ }
+ }
+}
diff --git a/Source/Concurrency/TypeCheck.cs b/Source/Concurrency/TypeCheck.cs
deleted file mode 100644
index f2b2c0ca..00000000
--- a/Source/Concurrency/TypeCheck.cs
+++ /dev/null
@@ -1,724 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using System.Diagnostics.Contracts;
-using System.Diagnostics;
-
-namespace Microsoft.Boogie
-{
- public enum MoverType
- {
- Top,
- Atomic,
- Right,
- Left,
- Both
- }
-
- public class ActionInfo
- {
- public Procedure proc;
- public int createdAtLayerNum;
- public int availableUptoLayerNum;
- public bool hasImplementation;
-
- public ActionInfo(Procedure proc, int createdAtLayerNum, int availableUptoLayerNum)
- {
- this.proc = proc;
- this.createdAtLayerNum = createdAtLayerNum;
- this.availableUptoLayerNum = availableUptoLayerNum;
- this.hasImplementation = false;
- }
-
- public virtual bool IsRightMover
- {
- get { return true; }
- }
-
- public virtual bool IsLeftMover
- {
- get { return true; }
- }
- }
-
- public class AtomicActionInfo : ActionInfo
- {
- public Ensures ensures;
- public MoverType moverType;
- public List<AssertCmd> thisGate;
- public CodeExpr thisAction;
- public List<Variable> thisInParams;
- public List<Variable> thisOutParams;
- public List<AssertCmd> thatGate;
- public CodeExpr thatAction;
- public List<Variable> thatInParams;
- public List<Variable> thatOutParams;
- public HashSet<Variable> actionUsedGlobalVars;
- public HashSet<Variable> modifiedGlobalVars;
- public HashSet<Variable> gateUsedGlobalVars;
- public bool hasAssumeCmd;
-
- public bool CommutesWith(AtomicActionInfo actionInfo)
- {
- if (this.modifiedGlobalVars.Intersect(actionInfo.actionUsedGlobalVars).Count() > 0)
- return false;
- if (this.actionUsedGlobalVars.Intersect(actionInfo.modifiedGlobalVars).Count() > 0)
- return false;
- return true;
- }
-
- public override bool IsRightMover
- {
- get { return moverType == MoverType.Right || moverType == MoverType.Both; }
- }
-
- public override bool IsLeftMover
- {
- get { return moverType == MoverType.Left || moverType == MoverType.Both; }
- }
-
- public AtomicActionInfo(Procedure proc, Ensures ensures, MoverType moverType, int layerNum, int availableUptoLayerNum)
- : base(proc, layerNum, availableUptoLayerNum)
- {
- CodeExpr codeExpr = ensures.Condition as CodeExpr;
- this.ensures = ensures;
- this.moverType = moverType;
- this.thisGate = new List<AssertCmd>();
- this.thisAction = codeExpr;
- this.thisInParams = new List<Variable>();
- this.thisOutParams = new List<Variable>();
- this.thatGate = new List<AssertCmd>();
- this.thatInParams = new List<Variable>();
- this.thatOutParams = new List<Variable>();
- this.hasAssumeCmd = false;
-
- foreach (Block block in codeExpr.Blocks)
- {
- block.Cmds.ForEach(x => this.hasAssumeCmd = this.hasAssumeCmd || x is AssumeCmd);
- }
-
- var cmds = thisAction.Blocks[0].Cmds;
- for (int i = 0; i < cmds.Count; i++)
- {
- AssertCmd assertCmd = cmds[i] as AssertCmd;
- if (assertCmd == null) break;
- thisGate.Add(assertCmd);
- cmds[i] = new AssumeCmd(assertCmd.tok, Expr.True);
- }
-
- Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
- foreach (Variable x in proc.InParams)
- {
- this.thisInParams.Add(x);
- Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true, x.Attributes);
- this.thatInParams.Add(y);
- map[x] = Expr.Ident(y);
- }
- foreach (Variable x in proc.OutParams)
- {
- this.thisOutParams.Add(x);
- Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false, x.Attributes);
- this.thatOutParams.Add(y);
- map[x] = Expr.Ident(y);
- }
- List<Variable> thatLocVars = new List<Variable>();
- foreach (Variable x in thisAction.LocVars)
- {
- Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false);
- map[x] = Expr.Ident(y);
- thatLocVars.Add(y);
- }
- Contract.Assume(proc.TypeParameters.Count == 0);
- Substitution subst = Substituter.SubstitutionFromHashtable(map);
- foreach (AssertCmd assertCmd in thisGate)
- {
- thatGate.Add((AssertCmd)Substituter.Apply(subst, assertCmd));
- }
- Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
- List<Block> thatBlocks = new List<Block>();
- foreach (Block block in thisAction.Blocks)
- {
- List<Cmd> otherCmds = new List<Cmd>();
- foreach (Cmd cmd in block.Cmds)
- {
- otherCmds.Add(Substituter.Apply(subst, cmd));
- }
- Block thatBlock = new Block();
- thatBlock.Cmds = otherCmds;
- thatBlock.Label = "that_" + block.Label;
- block.Label = "this_" + block.Label;
- thatBlocks.Add(thatBlock);
- blockMap[block] = thatBlock;
- if (block.TransferCmd is GotoCmd)
- {
- GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
- for (int i = 0; i < gotoCmd.labelNames.Count; i++)
- {
- gotoCmd.labelNames[i] = "this_" + gotoCmd.labelNames[i];
- }
- }
- }
- foreach (Block block in thisAction.Blocks)
- {
- if (block.TransferCmd is ReturnExprCmd)
- {
- block.TransferCmd = new ReturnCmd(block.TransferCmd.tok);
- blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok);
- continue;
- }
- List<Block> thatGotoCmdLabelTargets = new List<Block>();
- List<string> thatGotoCmdLabelNames = new List<string>();
- GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
- foreach (Block target in gotoCmd.labelTargets)
- {
- thatGotoCmdLabelTargets.Add(blockMap[target]);
- thatGotoCmdLabelNames.Add(blockMap[target].Label);
- }
- blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, thatGotoCmdLabelNames, thatGotoCmdLabelTargets);
- }
- this.thatAction = new CodeExpr(thatLocVars, thatBlocks);
-
- {
- VariableCollector collector = new VariableCollector();
- collector.Visit(codeExpr);
- this.actionUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable));
- }
-
- List<Variable> modifiedVars = new List<Variable>();
- foreach (Block block in codeExpr.Blocks)
- {
- block.Cmds.ForEach(cmd => cmd.AddAssignedVariables(modifiedVars));
- }
- this.modifiedGlobalVars = new HashSet<Variable>(modifiedVars.Where(x => x is GlobalVariable));
-
- {
- VariableCollector collector = new VariableCollector();
- this.thisGate.ForEach(assertCmd => collector.Visit(assertCmd));
- this.gateUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable));
- }
- }
- }
-
- public class SharedVariableInfo
- {
- public int introLayerNum;
- public int hideLayerNum;
-
- public SharedVariableInfo(int introLayerNum, int hideLayerNum)
- {
- this.introLayerNum = introLayerNum;
- this.hideLayerNum = hideLayerNum;
- }
- }
-
- public class LayerEraser : ReadOnlyVisitor
- {
- private QKeyValue RemoveLayerAttribute(QKeyValue iter)
- {
- if (iter == null) return null;
- iter.Next = RemoveLayerAttribute(iter.Next);
- return (iter.Key == "layer") ? iter.Next : iter;
- }
-
- public override Variable VisitVariable(Variable node)
- {
- node.Attributes = RemoveLayerAttribute(node.Attributes);
- return base.VisitVariable(node);
- }
-
- public override Procedure VisitProcedure(Procedure node)
- {
- node.Attributes = RemoveLayerAttribute(node.Attributes);
- return base.VisitProcedure(node);
- }
-
- public override Implementation VisitImplementation(Implementation node)
- {
- node.Attributes = RemoveLayerAttribute(node.Attributes);
- return base.VisitImplementation(node);
- }
-
- public override Requires VisitRequires(Requires node)
- {
- node.Attributes = RemoveLayerAttribute(node.Attributes);
- return base.VisitRequires(node);
- }
-
- public override Ensures VisitEnsures(Ensures node)
- {
- node.Attributes = RemoveLayerAttribute(node.Attributes);
- return base.VisitEnsures(node);
- }
-
- public override Cmd VisitAssertCmd(AssertCmd node)
- {
- node.Attributes = RemoveLayerAttribute(node.Attributes);
- return base.VisitAssertCmd(node);
- }
- }
-
- public class MoverTypeChecker : ReadOnlyVisitor
- {
- CheckingContext checkingContext;
- public int errorCount;
- public Dictionary<Variable, SharedVariableInfo> globalVarToSharedVarInfo;
- Procedure enclosingProc;
- Implementation enclosingImpl;
- public Dictionary<Procedure, ActionInfo> procToActionInfo;
- public Program program;
- bool canAccessSharedVars;
- bool canAccessAuxVars;
- int minLayerNum;
- int maxLayerNum;
- public Dictionary<Absy, HashSet<int>> absyToLayerNums;
- HashSet<Variable> auxVars;
- public int leastUnimplementedLayerNum;
-
- private static List<int> FindLayers(QKeyValue kv)
- {
- HashSet<int> attrs = new HashSet<int>();
- for (; kv != null; kv = kv.Next)
- {
- if (kv.Key != "layer") continue;
- foreach (var o in kv.Params)
- {
- Expr e = o as Expr;
- if (e == null) continue;
- LiteralExpr l = e as LiteralExpr;
- if (l != null && l.isBigNum)
- attrs.Add(l.asBigNum.ToIntSafe);
- }
- }
- List<int> layers = attrs.ToList();
- layers.Sort();
- return layers;
- }
-
- private static MoverType GetMoverType(Ensures e)
- {
- if (QKeyValue.FindBoolAttribute(e.Attributes, "atomic"))
- return MoverType.Atomic;
- if (QKeyValue.FindBoolAttribute(e.Attributes, "right"))
- return MoverType.Right;
- if (QKeyValue.FindBoolAttribute(e.Attributes, "left"))
- return MoverType.Left;
- if (QKeyValue.FindBoolAttribute(e.Attributes, "both"))
- return MoverType.Both;
- return MoverType.Top;
- }
-
- public MoverTypeChecker(Program program)
- {
- this.auxVars = new HashSet<Variable>();
- this.absyToLayerNums = new Dictionary<Absy, HashSet<int>>();
- this.globalVarToSharedVarInfo = new Dictionary<Variable, SharedVariableInfo>();
- this.procToActionInfo = new Dictionary<Procedure, ActionInfo>();
- this.errorCount = 0;
- this.checkingContext = new CheckingContext(null);
- this.program = program;
- this.enclosingProc = null;
- this.enclosingImpl = null;
- this.canAccessSharedVars = false;
- this.canAccessAuxVars = false;
- this.minLayerNum = int.MaxValue;
- this.maxLayerNum = -1;
- this.leastUnimplementedLayerNum = int.MaxValue;
- foreach (var g in program.GlobalVariables)
- {
- List<int> layerNums = FindLayers(g.Attributes);
- if (layerNums.Count == 0)
- {
- // Cannot access atomic actions
- }
- else if (layerNums.Count == 1)
- {
- this.globalVarToSharedVarInfo[g] = new SharedVariableInfo(layerNums[0], int.MaxValue);
- }
- else if (layerNums.Count == 2)
- {
- this.globalVarToSharedVarInfo[g] = new SharedVariableInfo(layerNums[0], layerNums[1]);
- }
- else
- {
- Error(g, "Too many layer numbers");
- }
- }
- }
-
- private HashSet<int> allCreatedLayerNums;
- public IEnumerable<int> AllCreatedLayerNums
- {
- get
- {
- if (allCreatedLayerNums == null)
- {
- allCreatedLayerNums = new HashSet<int>();
- foreach (ActionInfo actionInfo in procToActionInfo.Values)
- {
- allCreatedLayerNums.Add(actionInfo.createdAtLayerNum);
- }
- }
- return allCreatedLayerNums;
- }
- }
-
- public void TypeCheck()
- {
- foreach (var proc in program.Procedures)
- {
- if (!QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) continue;
-
- int createdAtLayerNum; // must be initialized by the following code, otherwise it is an error
- int availableUptoLayerNum = int.MaxValue;
- List<int> attrs = FindLayers(proc.Attributes);
- if (attrs.Count == 1)
- {
- createdAtLayerNum = attrs[0];
- }
- else if (attrs.Count == 2)
- {
- createdAtLayerNum = attrs[0];
- availableUptoLayerNum = attrs[1];
- }
- else
- {
- Error(proc, "Incorrect number of layers");
- continue;
- }
- if (availableUptoLayerNum <= createdAtLayerNum)
- {
- Error(proc, "Creation layer number must be less than the available upto layer number");
- continue;
- }
- foreach (Ensures e in proc.Ensures)
- {
- MoverType moverType = GetMoverType(e);
- if (moverType == MoverType.Top) continue;
- CodeExpr codeExpr = e.Condition as CodeExpr;
- if (codeExpr == null)
- {
- Error(e, "An atomic action must be a CodeExpr");
- continue;
- }
- if (procToActionInfo.ContainsKey(proc))
- {
- Error(proc, "A procedure can have at most one atomic action");
- continue;
- }
-
- minLayerNum = int.MaxValue;
- maxLayerNum = -1;
- canAccessSharedVars = true;
- enclosingProc = proc;
- enclosingImpl = null;
- base.VisitEnsures(e);
- canAccessSharedVars = false;
- if (maxLayerNum > createdAtLayerNum)
- {
- Error(e, "A variable being accessed is introduced after this action is created");
- }
- else if (availableUptoLayerNum > minLayerNum)
- {
- Error(e, "A variable being accessed is hidden before this action becomes unavailable");
- }
- else
- {
- procToActionInfo[proc] = new AtomicActionInfo(proc, e, moverType, createdAtLayerNum, availableUptoLayerNum);
- }
- }
- if (errorCount > 0) continue;
- if (!procToActionInfo.ContainsKey(proc))
- {
- procToActionInfo[proc] = new ActionInfo(proc, createdAtLayerNum, availableUptoLayerNum);
- }
- }
- if (errorCount > 0) return;
- foreach (var impl in program.Implementations)
- {
- if (!procToActionInfo.ContainsKey(impl.Proc)) continue;
- procToActionInfo[impl.Proc].hasImplementation = true;
- }
- foreach (var proc in procToActionInfo.Keys)
- {
- ActionInfo actionInfo = procToActionInfo[proc];
- if (actionInfo.hasImplementation) continue;
- if (leastUnimplementedLayerNum == int.MaxValue)
- {
- leastUnimplementedLayerNum = actionInfo.createdAtLayerNum;
- }
- else if (leastUnimplementedLayerNum == actionInfo.createdAtLayerNum)
- {
- // do nothing
- }
- else
- {
- Error(proc, "All unimplemented atomic actions must be created at the same layer");
- }
- }
- foreach (var g in this.globalVarToSharedVarInfo.Keys)
- {
- var info = globalVarToSharedVarInfo[g];
- if (!this.AllCreatedLayerNums.Contains(info.introLayerNum))
- {
- Error(g, "Variable must be introduced with creation of some atomic action");
- }
- if (info.hideLayerNum != int.MaxValue && !this.AllCreatedLayerNums.Contains(info.hideLayerNum))
- {
- Error(g, "Variable must be hidden with creation of some atomic action");
- }
- }
- if (errorCount > 0) return;
- this.VisitProgram(program);
- if (errorCount > 0) return;
- YieldTypeChecker.PerformYieldSafeCheck(this);
- new LayerEraser().VisitProgram(program);
- }
-
- public IEnumerable<Variable> SharedVariables
- {
- get { return this.globalVarToSharedVarInfo.Keys; }
- }
-
- public override Implementation VisitImplementation(Implementation node)
- {
- if (!procToActionInfo.ContainsKey(node.Proc))
- {
- return node;
- }
- this.enclosingImpl = node;
- this.enclosingProc = null;
- auxVars = new HashSet<Variable>();
- foreach (Variable v in node.LocVars)
- {
- if (QKeyValue.FindBoolAttribute(v.Attributes, "aux"))
- {
- auxVars.Add(v);
- }
- }
- return base.VisitImplementation(node);
- }
-
- public override Procedure VisitProcedure(Procedure node)
- {
- if (!procToActionInfo.ContainsKey(node))
- {
- return node;
- }
- this.enclosingProc = node;
- this.enclosingImpl = null;
- return base.VisitProcedure(node);
- }
-
- public override Cmd VisitCallCmd(CallCmd node)
- {
- int enclosingProcLayerNum = procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
- if (procToActionInfo.ContainsKey(node.Proc))
- {
- ActionInfo actionInfo = procToActionInfo[node.Proc];
- if (node.IsAsync && actionInfo is AtomicActionInfo)
- {
- Error(node, "Target of async call cannot be an atomic action");
- }
- int calleeLayerNum = procToActionInfo[node.Proc].createdAtLayerNum;
- if (enclosingProcLayerNum < calleeLayerNum ||
- (enclosingProcLayerNum == calleeLayerNum && actionInfo is AtomicActionInfo))
- {
- Error(node, "The layer of the caller must be greater than the layer of the callee");
- }
- else if (enclosingProcLayerNum == calleeLayerNum && enclosingImpl.OutParams.Count > 0)
- {
- HashSet<Variable> outParams = new HashSet<Variable>(enclosingImpl.OutParams);
- foreach (var x in node.Outs)
- {
- if (x.Decl is GlobalVariable)
- {
- Error(node, "A global variable cannot be used as output argument for this call");
- }
- else if (outParams.Contains(x.Decl))
- {
- Error(node, "An output variable of the enclosing implementation cannot be used as output argument for this call");
- }
- }
- }
- if (actionInfo.availableUptoLayerNum < enclosingProcLayerNum)
- {
- Error(node, "The callee is not available in the caller procedure");
- }
- }
- else
- {
- Error(node, "Yielding procedure can call only a yielding procedure");
- }
- return base.VisitCallCmd(node);
- }
-
- public override Cmd VisitParCallCmd(ParCallCmd node)
- {
- int enclosingProcLayerNum = procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
- bool isLeftMover = true;
- bool isRightMover = true;
- int maxCalleeLayerNum = 0;
- int numAtomicActions = 0;
- foreach (CallCmd iter in node.CallCmds)
- {
- ActionInfo actionInfo = procToActionInfo[iter.Proc];
- isLeftMover = isLeftMover && actionInfo.IsLeftMover;
- isRightMover = isRightMover && actionInfo.IsRightMover;
- if (actionInfo.createdAtLayerNum > maxCalleeLayerNum)
- {
- maxCalleeLayerNum = actionInfo.createdAtLayerNum;
- }
- if (actionInfo is AtomicActionInfo)
- {
- numAtomicActions++;
- }
- }
- if (maxCalleeLayerNum < enclosingProcLayerNum && !isLeftMover && !isRightMover && node.CallCmds.Count > 1)
- {
- Error(node, "The callees in the parallel call must be all right movers or all left movers");
- }
- if (maxCalleeLayerNum == enclosingProcLayerNum && numAtomicActions > 0)
- {
- Error(node, "If some callee in the parallel call has the same layer as the enclosing procedure, then no callee can be an atomic action");
- }
- return base.VisitParCallCmd(node);
- }
-
- public override Cmd VisitAssignCmd(AssignCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- for (int i = 0; i < node.Lhss.Count; ++i)
- {
- bool savedCanAccessSharedVars = canAccessSharedVars;
- bool savedCanAccessAuxVars = canAccessAuxVars;
- Variable v = node.Lhss[i].DeepAssignedVariable;
- if (v is LocalVariable && auxVars.Contains(v))
- {
- canAccessSharedVars = true;
- canAccessAuxVars = true;
- }
- this.Visit(node.Lhss[i]);
- this.Visit(node.Rhss[i]);
- canAccessSharedVars = savedCanAccessSharedVars;
- canAccessAuxVars = savedCanAccessAuxVars;
- }
- return node;
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- if (node.Decl is GlobalVariable)
- {
- if (!canAccessSharedVars)
- {
- Error(node, "Shared variable can be accessed only in atomic actions or specifications");
- }
- else if (this.globalVarToSharedVarInfo.ContainsKey(node.Decl))
- {
- if (this.globalVarToSharedVarInfo[node.Decl].hideLayerNum < minLayerNum)
- {
- minLayerNum = this.globalVarToSharedVarInfo[node.Decl].hideLayerNum;
- }
- if (this.globalVarToSharedVarInfo[node.Decl].introLayerNum > maxLayerNum)
- {
- maxLayerNum = this.globalVarToSharedVarInfo[node.Decl].introLayerNum;
- }
- }
- else
- {
- Error(node, "Accessed shared variable must have layer annotation");
- }
- }
- else if (node.Decl is LocalVariable && auxVars.Contains(node.Decl) && !canAccessAuxVars)
- {
- Error(node, "Auxiliary variable can be accessed only in assertions");
- }
-
- return base.VisitIdentifierExpr(node);
- }
-
- public override Ensures VisitEnsures(Ensures ensures)
- {
- minLayerNum = int.MaxValue;
- maxLayerNum = -1;
- canAccessSharedVars = true;
- Ensures ret = base.VisitEnsures(ensures);
- canAccessSharedVars = false;
- ActionInfo actionInfo = procToActionInfo[enclosingProc];
- AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
- if (atomicActionInfo != null && atomicActionInfo.ensures == ensures)
- {
- // This case has already been checked
- }
- else
- {
- CheckAndAddLayers(ensures, ensures.Attributes, actionInfo.createdAtLayerNum);
- }
- return ret;
- }
-
- public override Requires VisitRequires(Requires requires)
- {
- minLayerNum = int.MaxValue;
- maxLayerNum = -1;
- canAccessSharedVars = true;
- Requires ret = base.VisitRequires(requires);
- canAccessSharedVars = false;
- CheckAndAddLayers(requires, requires.Attributes, procToActionInfo[enclosingProc].createdAtLayerNum);
- return ret;
- }
-
- public override Cmd VisitAssertCmd(AssertCmd node)
- {
- if (enclosingImpl == null)
- return base.VisitAssertCmd(node);
- minLayerNum = int.MaxValue;
- maxLayerNum = -1;
- canAccessSharedVars = true;
- canAccessAuxVars = true;
- Cmd ret = base.VisitAssertCmd(node);
- canAccessAuxVars = false;
- canAccessSharedVars = false;
- CheckAndAddLayers(node, node.Attributes, procToActionInfo[enclosingImpl.Proc].createdAtLayerNum);
- return ret;
- }
-
- private void CheckAndAddLayers(Absy node, QKeyValue attributes, int enclosingProcLayerNum)
- {
- List<int> attrs = FindLayers(attributes);
- if (attrs.Count == 0)
- {
- Error(node, "layer not present");
- return;
- }
- absyToLayerNums[node] = new HashSet<int>();
- foreach (int layerNum in attrs)
- {
- if (layerNum == leastUnimplementedLayerNum || !AllCreatedLayerNums.Contains(layerNum))
- {
- Error(node, "Illegal layer number");
- }
- else if (layerNum > enclosingProcLayerNum)
- {
- Error(node, "The layer cannot be greater than the layer of enclosing procedure");
- }
- else if (maxLayerNum < layerNum && layerNum <= minLayerNum)
- {
- absyToLayerNums[node].Add(layerNum);
- }
- else
- {
- Error(node, string.Format("A variable being accessed in this specification is unavailable at layer {0}", layerNum));
- }
- }
- }
-
- public void Error(Absy node, string message)
- {
- checkingContext.Error(node, message);
- errorCount++;
- }
- }
-} \ No newline at end of file
diff --git a/Source/Concurrency/YieldTypeChecker.cs b/Source/Concurrency/YieldTypeChecker.cs
index 95884626..ed59d3ad 100644
--- a/Source/Concurrency/YieldTypeChecker.cs
+++ b/Source/Concurrency/YieldTypeChecker.cs
@@ -1,363 +1,368 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics;
-
-namespace Microsoft.Boogie
-{
- class YieldTypeChecker
- {
- static List<Tuple<int, int, int>> ASpec;
- static List<Tuple<int, int, int>> BSpec;
- static List<Tuple<int, int, int>> CSpec;
- static YieldTypeChecker()
- {
- // initial: 0, final: 1
- ASpec = new List<Tuple<int,int,int>>();
- ASpec.Add(new Tuple<int, int, int>(0, 'Y', 1));
- ASpec.Add(new Tuple<int, int, int>(1, 'Y', 1));
- ASpec.Add(new Tuple<int, int, int>(1, 'B', 1));
- ASpec.Add(new Tuple<int, int, int>(1, 'R', 1));
- ASpec.Add(new Tuple<int, int, int>(1, 'L', 1));
- ASpec.Add(new Tuple<int, int, int>(1, 'A', 1));
- ASpec.Add(new Tuple<int, int, int>(0, 'P', 0));
- ASpec.Add(new Tuple<int, int, int>(1, 'P', 1));
-
- // initial: 1, final: 0
- BSpec = new List<Tuple<int, int, int>>();
- BSpec.Add(new Tuple<int, int, int>(1, 'Y', 0));
- BSpec.Add(new Tuple<int, int, int>(1, 'Y', 1));
- BSpec.Add(new Tuple<int, int, int>(1, 'B', 1));
- BSpec.Add(new Tuple<int, int, int>(1, 'R', 1));
- BSpec.Add(new Tuple<int, int, int>(1, 'L', 1));
- BSpec.Add(new Tuple<int, int, int>(1, 'A', 1));
- BSpec.Add(new Tuple<int, int, int>(0, 'P', 0));
- BSpec.Add(new Tuple<int, int, int>(1, 'P', 1));
-
- // initial: {0, 1}, final: {0, 1}
- CSpec = new List<Tuple<int,int,int>>();
- CSpec.Add(new Tuple<int, int, int>(0, 'B', 0));
- CSpec.Add(new Tuple<int, int, int>(0, 'R', 0));
- CSpec.Add(new Tuple<int, int, int>(0, 'Y', 0));
- CSpec.Add(new Tuple<int, int, int>(0, 'B', 1));
- CSpec.Add(new Tuple<int, int, int>(0, 'R', 1));
- CSpec.Add(new Tuple<int, int, int>(0, 'L', 1));
- CSpec.Add(new Tuple<int, int, int>(0, 'A', 1));
- CSpec.Add(new Tuple<int, int, int>(1, 'B', 1));
- CSpec.Add(new Tuple<int, int, int>(1, 'L', 1));
- CSpec.Add(new Tuple<int, int, int>(1, 'Y', 0));
- CSpec.Add(new Tuple<int, int, int>(0, 'P', 0));
- CSpec.Add(new Tuple<int, int, int>(1, 'P', 1));
- }
-
- private void IsYieldTypeSafe()
- {
- List<Tuple<int, int, int>> implEdges = new List<Tuple<int, int, int>>();
- foreach (Tuple<int, int> e in edgeLabels.Keys)
- {
- implEdges.Add(new Tuple<int, int, int>(e.Item1, edgeLabels[e], e.Item2));
- }
- //Console.WriteLine(PrintGraph(impl, implEdges, initialState, finalStates));
- ASpecCheck(implEdges);
- BSpecCheck(implEdges);
- CSpecCheck(implEdges);
- }
-
- private void ASpecCheck(List<Tuple<int, int, int>> implEdges)
- {
- Dictionary<int, HashSet<int>> initialConstraints = new Dictionary<int, HashSet<int>>();
- initialConstraints[initialState] = new HashSet<int>(new int[] { 0 });
- foreach (var finalState in finalStates)
- {
- initialConstraints[finalState] = new HashSet<int>(new int[] { 1 });
- }
- SimulationRelation<int, int, int> x = new SimulationRelation<int, int, int>(implEdges, ASpec, initialConstraints);
- Dictionary<int, HashSet<int>> simulationRelation = x.ComputeSimulationRelation();
- if (simulationRelation[initialState].Count == 0)
- {
- moverTypeChecker.Error(impl, string.Format("Implementation {0} fails simulation check A at layer {1}. An action must be preceded by a yield.\n", impl.Name, currLayerNum));
- }
- }
-
- private void BSpecCheck(List<Tuple<int, int, int>> implEdges)
- {
- Dictionary<int, HashSet<int>> initialConstraints = new Dictionary<int, HashSet<int>>();
- initialConstraints[initialState] = new HashSet<int>(new int[] { 1 });
- foreach (var finalState in finalStates)
- {
- initialConstraints[finalState] = new HashSet<int>(new int[] { 0 });
- }
- SimulationRelation<int, int, int> x = new SimulationRelation<int, int, int>(implEdges, BSpec, initialConstraints);
- Dictionary<int, HashSet<int>> simulationRelation = x.ComputeSimulationRelation();
- if (simulationRelation[initialState].Count == 0)
- {
- moverTypeChecker.Error(impl, string.Format("Implementation {0} fails simulation check B at layer {1}. An action must be succeeded by a yield.\n", impl.Name, currLayerNum));
- }
- }
-
- private void CSpecCheck(List<Tuple<int, int, int>> implEdges)
- {
- Dictionary<int, HashSet<int>> initialConstraints = new Dictionary<int, HashSet<int>>();
- foreach (Block block in loopHeaders)
- {
- if (!IsTerminatingLoopHeader(block))
- {
- initialConstraints[absyToNode[block]] = new HashSet<int>(new int[] { 0 });
- }
- }
- SimulationRelation<int, int, int> x = new SimulationRelation<int, int, int>(implEdges, CSpec, initialConstraints);
- Dictionary<int, HashSet<int>> simulationRelation = x.ComputeSimulationRelation();
- if (simulationRelation[initialState].Count == 0)
- {
- moverTypeChecker.Error(impl, string.Format("Implementation {0} fails simulation check C at layer {1}. Transactions must be separated by a yield.\n", impl.Name, currLayerNum));
- }
- }
-
- private bool IsTerminatingLoopHeader(Block block)
- {
- foreach (Cmd cmd in block.Cmds)
- {
- AssertCmd assertCmd = cmd as AssertCmd;
- if (assertCmd != null && QKeyValue.FindBoolAttribute(assertCmd.Attributes, "terminates") && moverTypeChecker.absyToLayerNums[assertCmd].Contains(currLayerNum))
- {
- return true;
- }
- }
- return false;
- }
-
- public static void PerformYieldSafeCheck(MoverTypeChecker moverTypeChecker)
- {
- foreach (var impl in moverTypeChecker.program.Implementations)
- {
- if (!moverTypeChecker.procToActionInfo.ContainsKey(impl.Proc)) continue;
- impl.PruneUnreachableBlocks();
- Graph<Block> implGraph = Program.GraphFromImpl(impl);
- implGraph.ComputeLoops();
- int specLayerNum = moverTypeChecker.procToActionInfo[impl.Proc].createdAtLayerNum;
- foreach (int layerNum in moverTypeChecker.AllCreatedLayerNums.Except(new int[] { moverTypeChecker.leastUnimplementedLayerNum }))
- {
- if (layerNum > specLayerNum) continue;
- YieldTypeChecker executor = new YieldTypeChecker(moverTypeChecker, impl, layerNum, implGraph.Headers);
- }
- }
- }
-
- int stateCounter;
- MoverTypeChecker moverTypeChecker;
- Implementation impl;
- int currLayerNum;
- Dictionary<Absy, int> absyToNode;
- Dictionary<int, Absy> nodeToAbsy;
- int initialState;
- HashSet<int> finalStates;
- Dictionary<Tuple<int, int>, int> edgeLabels;
- IEnumerable<Block> loopHeaders;
-
- private YieldTypeChecker(MoverTypeChecker moverTypeChecker, Implementation impl, int currLayerNum, IEnumerable<Block> loopHeaders)
- {
- this.moverTypeChecker = moverTypeChecker;
- this.impl = impl;
- this.currLayerNum = currLayerNum;
- this.loopHeaders = loopHeaders;
- this.stateCounter = 0;
- this.absyToNode = new Dictionary<Absy, int>();
- this.initialState = 0;
- this.finalStates = new HashSet<int>();
- this.edgeLabels = new Dictionary<Tuple<int, int>, int>();
-
- foreach (Block block in impl.Blocks)
- {
- absyToNode[block] = stateCounter;
- stateCounter++;
- foreach (Cmd cmd in block.Cmds)
- {
- absyToNode[cmd] = stateCounter;
- stateCounter++;
- }
- absyToNode[block.TransferCmd] = stateCounter;
- stateCounter++;
- if (block.TransferCmd is ReturnCmd)
- {
- finalStates.Add(absyToNode[block.TransferCmd]);
- }
- }
- foreach (Block block in impl.Blocks)
- {
- Absy blockEntry = block.Cmds.Count == 0 ? (Absy)block.TransferCmd : (Absy)block.Cmds[0];
- edgeLabels[new Tuple<int, int>(absyToNode[block], absyToNode[blockEntry])] = 'P';
-
- GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
- if (gotoCmd == null) continue;
- foreach (Block successor in gotoCmd.labelTargets)
- {
- edgeLabels[new Tuple<int, int>(absyToNode[gotoCmd], absyToNode[successor])] = 'P';
- }
- }
-
- this.nodeToAbsy = new Dictionary<int, Absy>();
- foreach (KeyValuePair<Absy, int> state in absyToNode)
- {
- this.nodeToAbsy[state.Value] = state.Key;
- }
-
- ComputeGraph();
- IsYieldTypeSafe();
- }
-
- private void ComputeGraph()
- {
- foreach (Block block in impl.Blocks)
- {
- for (int i = 0; i < block.Cmds.Count; i++)
- {
- Cmd cmd = block.Cmds[i];
- int curr = absyToNode[cmd];
- int next = (i + 1 == block.Cmds.Count) ? absyToNode[block.TransferCmd] : absyToNode[block.Cmds[i + 1]];
- Tuple<int, int> edge = new Tuple<int, int>(curr, next);
- if (cmd is CallCmd)
- {
- CallCmd callCmd = cmd as CallCmd;
- if (callCmd.IsAsync)
- {
- ActionInfo actionInfo = moverTypeChecker.procToActionInfo[callCmd.Proc];
- if (currLayerNum <= actionInfo.createdAtLayerNum)
- edgeLabels[edge] = 'L';
- else
- edgeLabels[edge] = 'B';
- }
- else if (!moverTypeChecker.procToActionInfo.ContainsKey(callCmd.Proc))
- {
- edgeLabels[edge] = 'P';
- }
- else
- {
- MoverType moverType;
- ActionInfo actionInfo = moverTypeChecker.procToActionInfo[callCmd.Proc];
- if (actionInfo.createdAtLayerNum >= currLayerNum)
- {
- moverType = MoverType.Top;
- }
- else
- {
- AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
- if (atomicActionInfo == null)
- moverType = MoverType.Both;
- else
- moverType = atomicActionInfo.moverType;
- }
- switch (moverType)
- {
- case MoverType.Atomic:
- edgeLabels[edge] = 'A';
- break;
- case MoverType.Both:
- edgeLabels[edge] = 'B';
- break;
- case MoverType.Left:
- edgeLabels[edge] = 'L';
- break;
- case MoverType.Right:
- edgeLabels[edge] = 'R';
- break;
- case MoverType.Top:
- edgeLabels[edge] = 'Y';
- break;
- }
- }
- }
- else if (cmd is ParCallCmd)
- {
- ParCallCmd parCallCmd = cmd as ParCallCmd;
- bool isYield = false;
- bool isRightMover = true;
- bool isLeftMover = true;
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- if (moverTypeChecker.procToActionInfo[callCmd.Proc].createdAtLayerNum >= currLayerNum)
- {
- isYield = true;
- }
- }
- if (isYield)
- {
- edgeLabels[edge] = 'Y';
- }
- else
- {
- foreach (CallCmd callCmd in parCallCmd.CallCmds)
- {
- ActionInfo actionInfo = moverTypeChecker.procToActionInfo[callCmd.Proc];
- isRightMover = isRightMover && actionInfo.IsRightMover;
- isLeftMover = isLeftMover && actionInfo.IsLeftMover;
- }
- if (isLeftMover && isRightMover)
- {
- edgeLabels[edge] = 'B';
- }
- else if (isLeftMover)
- {
- edgeLabels[edge] = 'L';
- }
- else if (isRightMover)
- {
- edgeLabels[edge] = 'R';
- }
- else
- {
- Debug.Assert(parCallCmd.CallCmds.Count == 1);
- edgeLabels[edge] = 'A';
- }
- }
- }
- else if (cmd is YieldCmd)
- {
- edgeLabels[edge] = 'Y';
- }
- else
- {
- edgeLabels[edge] = 'P';
- }
- }
- }
- }
-
- private static string PrintGraph(Implementation impl, List<Tuple<int, int, int>> edges, int initialState, HashSet<int> finalStates)
- {
- var s = new StringBuilder();
- s.AppendLine("\nImplementation " + impl.Proc.Name + " digraph G {");
- foreach (var e in edges)
- {
- string label = "P";
- switch (e.Item2)
- {
- case 'P': label = "P"; break;
- case 'Y': label = "Y"; break;
- case 'B': label = "B"; break;
- case 'R': label = "R"; break;
- case 'L': label = "L"; break;
- case 'A': label = "A"; break;
- default: Debug.Assert(false); break;
- }
- s.AppendLine(" \"" + e.Item1.ToString() + "\" -- " + label + " --> " + " \"" + e.Item3.ToString() + "\";");
- }
- s.AppendLine("}");
- s.AppendLine("Initial state: " + initialState);
- s.Append("Final states: ");
- bool first = true;
- foreach (int finalState in finalStates)
- {
- s.Append((first ? "" : ", ") + finalState);
- first = false;
- }
- s.AppendLine();
- return s.ToString();
- }
- }
-}
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics;
+
+namespace Microsoft.Boogie
+{
+ class YieldTypeChecker
+ {
+ static List<Tuple<int, int, int>> ASpec;
+ static List<Tuple<int, int, int>> BSpec;
+ static List<Tuple<int, int, int>> CSpec;
+ static YieldTypeChecker()
+ {
+ // initial: 0, final: 1
+ ASpec = new List<Tuple<int,int,int>>();
+ ASpec.Add(new Tuple<int, int, int>(0, 'Y', 1));
+ ASpec.Add(new Tuple<int, int, int>(1, 'Y', 1));
+ ASpec.Add(new Tuple<int, int, int>(1, 'B', 1));
+ ASpec.Add(new Tuple<int, int, int>(1, 'R', 1));
+ ASpec.Add(new Tuple<int, int, int>(1, 'L', 1));
+ ASpec.Add(new Tuple<int, int, int>(1, 'A', 1));
+ ASpec.Add(new Tuple<int, int, int>(0, 'P', 0));
+ ASpec.Add(new Tuple<int, int, int>(1, 'P', 1));
+
+ // initial: 1, final: 0
+ BSpec = new List<Tuple<int, int, int>>();
+ BSpec.Add(new Tuple<int, int, int>(1, 'Y', 0));
+ BSpec.Add(new Tuple<int, int, int>(1, 'Y', 1));
+ BSpec.Add(new Tuple<int, int, int>(1, 'B', 1));
+ BSpec.Add(new Tuple<int, int, int>(1, 'R', 1));
+ BSpec.Add(new Tuple<int, int, int>(1, 'L', 1));
+ BSpec.Add(new Tuple<int, int, int>(1, 'A', 1));
+ BSpec.Add(new Tuple<int, int, int>(0, 'P', 0));
+ BSpec.Add(new Tuple<int, int, int>(1, 'P', 1));
+
+ // initial: {0, 1}, final: {0, 1}
+ CSpec = new List<Tuple<int,int,int>>();
+ CSpec.Add(new Tuple<int, int, int>(0, 'B', 0));
+ CSpec.Add(new Tuple<int, int, int>(0, 'R', 0));
+ CSpec.Add(new Tuple<int, int, int>(0, 'Y', 0));
+ CSpec.Add(new Tuple<int, int, int>(0, 'B', 1));
+ CSpec.Add(new Tuple<int, int, int>(0, 'R', 1));
+ CSpec.Add(new Tuple<int, int, int>(0, 'L', 1));
+ CSpec.Add(new Tuple<int, int, int>(0, 'A', 1));
+ CSpec.Add(new Tuple<int, int, int>(1, 'B', 1));
+ CSpec.Add(new Tuple<int, int, int>(1, 'L', 1));
+ CSpec.Add(new Tuple<int, int, int>(1, 'Y', 0));
+ CSpec.Add(new Tuple<int, int, int>(0, 'P', 0));
+ CSpec.Add(new Tuple<int, int, int>(1, 'P', 1));
+ }
+
+ private void IsYieldTypeSafe()
+ {
+ List<Tuple<int, int, int>> implEdges = new List<Tuple<int, int, int>>();
+ foreach (Tuple<int, int> e in edgeLabels.Keys)
+ {
+ implEdges.Add(new Tuple<int, int, int>(e.Item1, edgeLabels[e], e.Item2));
+ }
+ //Console.WriteLine(PrintGraph(impl, implEdges, initialState, finalStates));
+ ASpecCheck(implEdges);
+ BSpecCheck(implEdges);
+ CSpecCheck(implEdges);
+ }
+
+ private void ASpecCheck(List<Tuple<int, int, int>> implEdges)
+ {
+ Dictionary<int, HashSet<int>> initialConstraints = new Dictionary<int, HashSet<int>>();
+ initialConstraints[initialState] = new HashSet<int>(new int[] { 0 });
+ foreach (var finalState in finalStates)
+ {
+ initialConstraints[finalState] = new HashSet<int>(new int[] { 1 });
+ }
+ SimulationRelation<int, int, int> x = new SimulationRelation<int, int, int>(implEdges, ASpec, initialConstraints);
+ Dictionary<int, HashSet<int>> simulationRelation = x.ComputeSimulationRelation();
+ if (simulationRelation[initialState].Count == 0)
+ {
+ civlTypeChecker.Error(impl, string.Format("Implementation {0} fails simulation check A at layer {1}. An action must be preceded by a yield.\n", impl.Name, currLayerNum));
+ }
+ }
+
+ private void BSpecCheck(List<Tuple<int, int, int>> implEdges)
+ {
+ Dictionary<int, HashSet<int>> initialConstraints = new Dictionary<int, HashSet<int>>();
+ initialConstraints[initialState] = new HashSet<int>(new int[] { 1 });
+ foreach (var finalState in finalStates)
+ {
+ initialConstraints[finalState] = new HashSet<int>(new int[] { 0 });
+ }
+ SimulationRelation<int, int, int> x = new SimulationRelation<int, int, int>(implEdges, BSpec, initialConstraints);
+ Dictionary<int, HashSet<int>> simulationRelation = x.ComputeSimulationRelation();
+ if (simulationRelation[initialState].Count == 0)
+ {
+ civlTypeChecker.Error(impl, string.Format("Implementation {0} fails simulation check B at layer {1}. An action must be succeeded by a yield.\n", impl.Name, currLayerNum));
+ }
+ }
+
+ private void CSpecCheck(List<Tuple<int, int, int>> implEdges)
+ {
+ Dictionary<int, HashSet<int>> initialConstraints = new Dictionary<int, HashSet<int>>();
+ foreach (Block block in loopHeaders)
+ {
+ if (!IsTerminatingLoopHeader(block))
+ {
+ initialConstraints[absyToNode[block]] = new HashSet<int>(new int[] { 0 });
+ }
+ }
+ SimulationRelation<int, int, int> x = new SimulationRelation<int, int, int>(implEdges, CSpec, initialConstraints);
+ Dictionary<int, HashSet<int>> simulationRelation = x.ComputeSimulationRelation();
+ if (simulationRelation[initialState].Count == 0)
+ {
+ civlTypeChecker.Error(impl, string.Format("Implementation {0} fails simulation check C at layer {1}. Transactions must be separated by a yield.\n", impl.Name, currLayerNum));
+ }
+ }
+
+ private bool IsTerminatingLoopHeader(Block block)
+ {
+ foreach (Cmd cmd in block.Cmds)
+ {
+ AssertCmd assertCmd = cmd as AssertCmd;
+ if (assertCmd != null && QKeyValue.FindBoolAttribute(assertCmd.Attributes, "terminates") && civlTypeChecker.absyToLayerNums[assertCmd].Contains(currLayerNum))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void PerformYieldSafeCheck(CivlTypeChecker civlTypeChecker)
+ {
+ foreach (var impl in civlTypeChecker.program.Implementations)
+ {
+ if (!civlTypeChecker.procToActionInfo.ContainsKey(impl.Proc)) continue;
+ impl.PruneUnreachableBlocks();
+ Graph<Block> implGraph = Program.GraphFromImpl(impl);
+ implGraph.ComputeLoops();
+ int specLayerNum = civlTypeChecker.procToActionInfo[impl.Proc].createdAtLayerNum;
+ foreach (int layerNum in civlTypeChecker.AllLayerNums)
+ {
+ if (layerNum > specLayerNum) continue;
+ YieldTypeChecker executor = new YieldTypeChecker(civlTypeChecker, impl, layerNum, implGraph.Headers);
+ }
+ }
+ }
+
+ int stateCounter;
+ CivlTypeChecker civlTypeChecker;
+ Implementation impl;
+ int currLayerNum;
+ Dictionary<Absy, int> absyToNode;
+ Dictionary<int, Absy> nodeToAbsy;
+ int initialState;
+ HashSet<int> finalStates;
+ Dictionary<Tuple<int, int>, int> edgeLabels;
+ IEnumerable<Block> loopHeaders;
+
+ private YieldTypeChecker(CivlTypeChecker civlTypeChecker, Implementation impl, int currLayerNum, IEnumerable<Block> loopHeaders)
+ {
+ this.civlTypeChecker = civlTypeChecker;
+ this.impl = impl;
+ this.currLayerNum = currLayerNum;
+ this.loopHeaders = loopHeaders;
+ this.stateCounter = 0;
+ this.absyToNode = new Dictionary<Absy, int>();
+ this.initialState = 0;
+ this.finalStates = new HashSet<int>();
+ this.edgeLabels = new Dictionary<Tuple<int, int>, int>();
+
+ foreach (Block block in impl.Blocks)
+ {
+ absyToNode[block] = stateCounter;
+ stateCounter++;
+ foreach (Cmd cmd in block.Cmds)
+ {
+ absyToNode[cmd] = stateCounter;
+ stateCounter++;
+ }
+ absyToNode[block.TransferCmd] = stateCounter;
+ stateCounter++;
+ if (block.TransferCmd is ReturnCmd)
+ {
+ finalStates.Add(absyToNode[block.TransferCmd]);
+ }
+ }
+ foreach (Block block in impl.Blocks)
+ {
+ Absy blockEntry = block.Cmds.Count == 0 ? (Absy)block.TransferCmd : (Absy)block.Cmds[0];
+ edgeLabels[new Tuple<int, int>(absyToNode[block], absyToNode[blockEntry])] = 'P';
+
+ GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
+ if (gotoCmd == null) continue;
+ foreach (Block successor in gotoCmd.labelTargets)
+ {
+ edgeLabels[new Tuple<int, int>(absyToNode[gotoCmd], absyToNode[successor])] = 'P';
+ }
+ }
+
+ this.nodeToAbsy = new Dictionary<int, Absy>();
+ foreach (KeyValuePair<Absy, int> state in absyToNode)
+ {
+ this.nodeToAbsy[state.Value] = state.Key;
+ }
+
+ ComputeGraph();
+ IsYieldTypeSafe();
+ }
+
+ private void ComputeGraph()
+ {
+ foreach (Block block in impl.Blocks)
+ {
+ for (int i = 0; i < block.Cmds.Count; i++)
+ {
+ Cmd cmd = block.Cmds[i];
+ int curr = absyToNode[cmd];
+ int next = (i + 1 == block.Cmds.Count) ? absyToNode[block.TransferCmd] : absyToNode[block.Cmds[i + 1]];
+ Tuple<int, int> edge = new Tuple<int, int>(curr, next);
+ if (cmd is CallCmd)
+ {
+ CallCmd callCmd = cmd as CallCmd;
+ if (callCmd.IsAsync)
+ {
+ ActionInfo actionInfo = civlTypeChecker.procToActionInfo[callCmd.Proc];
+ if (currLayerNum <= actionInfo.createdAtLayerNum)
+ edgeLabels[edge] = 'L';
+ else
+ edgeLabels[edge] = 'B';
+ }
+ else if (!civlTypeChecker.procToActionInfo.ContainsKey(callCmd.Proc))
+ {
+ edgeLabels[edge] = 'P';
+ }
+ else
+ {
+ MoverType moverType;
+ ActionInfo actionInfo = civlTypeChecker.procToActionInfo[callCmd.Proc];
+ if (actionInfo.createdAtLayerNum >= currLayerNum)
+ {
+ moverType = MoverType.Top;
+ }
+ else
+ {
+ AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
+ if (atomicActionInfo == null)
+ moverType = MoverType.Both;
+ else
+ moverType = atomicActionInfo.moverType;
+ }
+ switch (moverType)
+ {
+ case MoverType.Atomic:
+ edgeLabels[edge] = 'A';
+ break;
+ case MoverType.Both:
+ edgeLabels[edge] = 'B';
+ break;
+ case MoverType.Left:
+ edgeLabels[edge] = 'L';
+ break;
+ case MoverType.Right:
+ edgeLabels[edge] = 'R';
+ break;
+ case MoverType.Top:
+ edgeLabels[edge] = 'Y';
+ break;
+ }
+ }
+ }
+ else if (cmd is ParCallCmd)
+ {
+ ParCallCmd parCallCmd = cmd as ParCallCmd;
+ bool isYield = false;
+ bool isRightMover = true;
+ bool isLeftMover = true;
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ if (civlTypeChecker.procToActionInfo[callCmd.Proc].createdAtLayerNum >= currLayerNum)
+ {
+ isYield = true;
+ }
+ }
+ if (isYield)
+ {
+ edgeLabels[edge] = 'Y';
+ }
+ else
+ {
+ int numAtomicActions = 0;
+ foreach (CallCmd callCmd in parCallCmd.CallCmds)
+ {
+ ActionInfo actionInfo = civlTypeChecker.procToActionInfo[callCmd.Proc];
+ isRightMover = isRightMover && actionInfo.IsRightMover;
+ isLeftMover = isLeftMover && actionInfo.IsLeftMover;
+ if (actionInfo is AtomicActionInfo)
+ {
+ numAtomicActions++;
+ }
+ }
+ if (isLeftMover && isRightMover)
+ {
+ edgeLabels[edge] = 'B';
+ }
+ else if (isLeftMover)
+ {
+ edgeLabels[edge] = 'L';
+ }
+ else if (isRightMover)
+ {
+ edgeLabels[edge] = 'R';
+ }
+ else
+ {
+ Debug.Assert(numAtomicActions == 1);
+ edgeLabels[edge] = 'A';
+ }
+ }
+ }
+ else if (cmd is YieldCmd)
+ {
+ edgeLabels[edge] = 'Y';
+ }
+ else
+ {
+ edgeLabels[edge] = 'P';
+ }
+ }
+ }
+ }
+
+ private static string PrintGraph(Implementation impl, List<Tuple<int, int, int>> edges, int initialState, HashSet<int> finalStates)
+ {
+ var s = new StringBuilder();
+ s.AppendLine("\nImplementation " + impl.Proc.Name + " digraph G {");
+ foreach (var e in edges)
+ {
+ string label = "P";
+ switch (e.Item2)
+ {
+ case 'P': label = "P"; break;
+ case 'Y': label = "Y"; break;
+ case 'B': label = "B"; break;
+ case 'R': label = "R"; break;
+ case 'L': label = "L"; break;
+ case 'A': label = "A"; break;
+ default: Debug.Assert(false); break;
+ }
+ s.AppendLine(" \"" + e.Item1.ToString() + "\" -- " + label + " --> " + " \"" + e.Item3.ToString() + "\";");
+ }
+ s.AppendLine("}");
+ s.AppendLine("Initial state: " + initialState);
+ s.Append("Final states: ");
+ bool first = true;
+ foreach (int finalState in finalStates)
+ {
+ s.Append((first ? "" : ", ") + finalState);
+ first = false;
+ }
+ s.AppendLine();
+ return s.ToString();
+ }
+ }
+}
diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs
index a1a54024..8a8558bf 100644
--- a/Source/Core/Absy.cs
+++ b/Source/Core/Absy.cs
@@ -1,4456 +1,4529 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-namespace Microsoft.Boogie.AbstractInterpretation {
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
-
- public class CallSite {
- public readonly Implementation/*!*/ Impl;
- public readonly Block/*!*/ Block;
- public readonly int Statement; // invariant: Block[Statement] is CallCmd
- public readonly ProcedureSummaryEntry/*!*/ SummaryEntry;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Impl != null);
- Contract.Invariant(Block != null);
- Contract.Invariant(SummaryEntry != null);
- }
-
-
- public CallSite(Implementation impl, Block b, int stmt, ProcedureSummaryEntry summaryEntry) {
- Contract.Requires(summaryEntry != null);
- Contract.Requires(b != null);
- Contract.Requires(impl != null);
- this.Impl = impl;
- this.Block = b;
- this.Statement = stmt;
- this.SummaryEntry = summaryEntry;
- }
- }
-
- public class ProcedureSummaryEntry {
-
- private HashSet<CallSite>/*!*/ _returnPoints; // whenever OnExit changes, we start analysis again at all the ReturnPoints
-
- public HashSet<CallSite>/*!*/ ReturnPoints {
- get {
- Contract.Ensures(Contract.Result<HashSet<CallSite>>() != null);
- return this._returnPoints;
- }
- set {
- Contract.Requires(value != null);
- this._returnPoints = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._returnPoints != null);
- }
-
- public ProcedureSummaryEntry() {
- this._returnPoints = new HashSet<CallSite>();
- }
-
- } // class
-
- public class ProcedureSummary : ArrayList/*<ProcedureSummaryEntry>*/
- {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(
- !IsReadOnly && !IsFixedSize);
- }
-
- public new ProcedureSummaryEntry/*!*/ this[int i] {
- get {
- Contract.Requires(0 <= i && i < Count);
- Contract.Ensures(Contract.Result<ProcedureSummaryEntry>() != null);
- return cce.NonNull((ProcedureSummaryEntry/*!*/)base[i]);
- }
- }
-
- } // class
-} // namespace
-
-namespace Microsoft.Boogie {
- using System;
- using System.Linq;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Diagnostics.Contracts;
- using Microsoft.Boogie.AbstractInterpretation;
- using Microsoft.Boogie.GraphUtil;
- using Set = GSet<object>;
-
- [ContractClass(typeof(AbsyContracts))]
- public abstract class Absy {
- private IToken/*!*/ _tok;
- private int uniqueId;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._tok != null);
- }
-
- public IToken tok { //Rename this property and "_tok" if possible
- get {
- Contract.Ensures(Contract.Result<IToken>() != null);
- return this._tok;
- }
- set {
- Contract.Requires(value != null);
- this._tok = value;
- }
- }
-
- public int Line {
- get {
- return tok != null ? tok.line : -1;
- }
- }
- public int Col {
- get {
- return tok != null ? tok.col : -1;
- }
- }
-
- public Absy(IToken tok) {
- Contract.Requires(tok != null);
- this._tok = tok;
- this.uniqueId = System.Threading.Interlocked.Increment(ref CurrentAbsyNodeId);
- }
-
- private static int CurrentAbsyNodeId = -1;
-
- // We uniquely number every AST node to make them
- // suitable for our implementation of functional maps.
- //
- public int UniqueId {
- get {
- return this.uniqueId;
- }
- }
-
- private const int indent_size = 2;
- protected static string Indent(int level) {
- return new string(' ', (indent_size * level));
- }
- [NeedsContracts]
- public abstract void Resolve(ResolutionContext/*!*/ rc);
-
- /// <summary>
- /// Requires the object to have been successfully resolved.
- /// </summary>
- /// <param name="tc"></param>
- [NeedsContracts]
- public abstract void Typecheck(TypecheckingContext/*!*/ tc);
- /// <summary>
- /// Intorduced this so the uniqueId is not the same on a cloned object.
- /// </summary>
- /// <param name="tc"></param>
- public virtual Absy Clone() {
- Contract.Ensures(Contract.Result<Absy>() != null);
- Absy/*!*/ result = cce.NonNull((Absy/*!*/)this.MemberwiseClone());
- result.uniqueId = System.Threading.Interlocked.Increment(ref CurrentAbsyNodeId); // BUGBUG??
-
- if (InternalNumberedMetadata != null) {
- // This should probably use the lock
- result.InternalNumberedMetadata = new List<Object>(this.InternalNumberedMetadata);
- }
-
- return result;
- }
-
- public virtual Absy StdDispatch(StandardVisitor visitor) {
- Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- System.Diagnostics.Debug.Fail("Unknown Absy node type: " + this.GetType());
- throw new System.NotImplementedException();
- }
-
- #region numberedmetadata
- // Implementation of Numbered Metadata
- // This allows any number of arbitrary objects to be
- // associated with an instance of an Absy at run time
- // in a type safe manner using an integer as a key.
-
- // We could use a dictionary but we use a List for look up speed
- // For this to work well the user needs to use small integers as
- // keys. The list is created lazily to minimise memory overhead.
- private volatile List<Object> InternalNumberedMetadata = null;
-
- // The lock exists to ensure that InternalNumberedMetadata is a singleton
- // for every instance of this class.
- // It is static to minimise the memory overhead (we don't want a lock per instance).
- private static readonly Object NumberedMetadataLock = new object();
-
- /// <summary>
- /// Gets the number of meta data objects associated with this instance
- /// </summary>
- /// <value>The numbered meta data count.</value>
- public int NumberedMetaDataCount
- {
- get { return InternalNumberedMetadata == null? 0: InternalNumberedMetadata.Count; }
- }
-
- /// <summary>
- /// Gets an IEnumerable over the numbered metadata associated
- /// with this instance.
- /// </summary>
- /// <value>
- /// The numbered meta data enumerable that looks like the Enumerable
- /// of a dictionary.
- /// </value>
- public IEnumerable<KeyValuePair<int, Object>> NumberedMetadata
- {
- get {
- if (InternalNumberedMetadata == null)
- return Enumerable.Empty<KeyValuePair<int,Object>>();
- else
- return InternalNumberedMetadata.Select((v, index) => new KeyValuePair<int, Object>(index, v));
- }
- }
-
- /// <summary>
- /// Gets the metatdata at specified index.
- /// ArgumentOutOfRange exception is raised if it is not available.
- /// InvalidCastExcpetion is raised if the metadata is available but the wrong type was requested.
- /// </summary>
- /// <returns>The stored metadata of type T</returns>
- /// <param name="index">The index of the metadata</param>
- /// <typeparam name="T">The type of the metadata object required</typeparam>
- public T GetMetadata<T>(int index) {
- // We aren't using NumberedMetadataLock for speed. Perhaps we should be using it?
- if (InternalNumberedMetadata == null)
- throw new ArgumentOutOfRangeException();
-
- if (InternalNumberedMetadata[index] is T)
- return (T) InternalNumberedMetadata[index];
- else if (InternalNumberedMetadata[index] == null) {
- throw new InvalidCastException("Numbered metadata " + index +
- " is null which cannot be casted to " + typeof(T));
- }
- else {
- throw new InvalidCastException("Numbered metadata " + index +
- " is of type " + InternalNumberedMetadata[index].GetType() +
- " rather than requested type " + typeof(T));
- }
- }
-
- private void InitialiseNumberedMetadata() {
- // Ensure InternalNumberedMetadata is a singleton
- if (InternalNumberedMetadata == null) {
- lock (NumberedMetadataLock) {
- if (InternalNumberedMetadata == null)
- InternalNumberedMetadata = new List<Object>();
- }
- }
- }
-
- /// <summary>
- /// Sets the metadata for this instace at a specified index.
- /// </summary>
- /// <param name="index">The index of the metadata</param>
- /// <param name="value">The value to set</param>
- /// <typeparam name="T">The type of value</typeparam>
- public void SetMetadata<T>(int index, T value) {
- InitialiseNumberedMetadata();
-
- if (index < 0)
- throw new IndexOutOfRangeException();
-
- lock (NumberedMetadataLock) {
- if (index < InternalNumberedMetadata.Count)
- InternalNumberedMetadata[index] = value;
- else {
- // Make sure expansion only happens once whilst we pad
- if (InternalNumberedMetadata.Capacity <= index) {
- // Use the next available power of 2
- InternalNumberedMetadata.Capacity = (int) Math.Pow(2, Math.Ceiling(Math.Log(index+1,2)));
- }
-
- // Pad with nulls
- while (InternalNumberedMetadata.Count < index)
- InternalNumberedMetadata.Add (null);
-
- InternalNumberedMetadata.Add(value);
- Debug.Assert(InternalNumberedMetadata.Count == (index + 1));
- }
- }
- }
-
- #endregion
-
- }
-
- [ContractClassFor(typeof(Absy))]
- public abstract class AbsyContracts : Absy {
- public override void Resolve(ResolutionContext rc) {
- Contract.Requires(rc != null);
- throw new NotImplementedException();
- }
- public AbsyContracts() :base(null){
-
- }
- public override void Typecheck(TypecheckingContext tc) {
- Contract.Requires(tc != null);
- throw new NotImplementedException();
- }
- }
-
- public interface IPotentialErrorNode<out TGet>
- {
- TGet ErrorData
- {
- get;
- }
- }
-
- public interface IPotentialErrorNode<out TGet, in TSet> : IPotentialErrorNode<TGet>
- {
- new TSet ErrorData
- {
- set;
- }
- }
-
- public class Program : Absy {
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(this.topLevelDeclarations));
- Contract.Invariant(cce.NonNullElements(this.globalVariablesCache, true));
- }
-
- public Program()
- : base(Token.NoToken) {
- this.topLevelDeclarations = new List<Declaration>();
- }
-
- public void Emit(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- stream.SetToken(this);
- this.topLevelDeclarations.Emit(stream);
- }
-
- public void ProcessDatatypeConstructors() {
- Dictionary<string, DatatypeConstructor> constructors = new Dictionary<string, DatatypeConstructor>();
- List<Declaration> prunedTopLevelDeclarations = new List<Declaration>();
- foreach (Declaration decl in TopLevelDeclarations) {
- Function func = decl as Function;
- if (func == null || !QKeyValue.FindBoolAttribute(decl.Attributes, "constructor")) {
- prunedTopLevelDeclarations.Add(decl);
- continue;
- }
- if (constructors.ContainsKey(func.Name)) continue;
- DatatypeConstructor constructor = new DatatypeConstructor(func);
- constructors.Add(func.Name, constructor);
- prunedTopLevelDeclarations.Add(constructor);
- }
- ClearTopLevelDeclarations();
- AddTopLevelDeclarations(prunedTopLevelDeclarations);
-
- foreach (DatatypeConstructor f in constructors.Values) {
- for (int i = 0; i < f.InParams.Count; i++) {
- DatatypeSelector selector = new DatatypeSelector(f, i);
- f.selectors.Add(selector);
- AddTopLevelDeclaration(selector);
- }
- DatatypeMembership membership = new DatatypeMembership(f);
- f.membership = membership;
- AddTopLevelDeclaration(membership);
- }
- }
-
- /// <summary>
- /// Returns the number of name resolution errors.
- /// </summary>
- /// <returns></returns>
- public int Resolve() {
- return Resolve((IErrorSink)null);
- }
-
- public int Resolve(IErrorSink errorSink) {
- ResolutionContext rc = new ResolutionContext(errorSink);
- Resolve(rc);
- return rc.ErrorCount;
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Helpers.ExtraTraceInformation("Starting resolution");
-
- foreach (var d in TopLevelDeclarations) {
- d.Register(rc);
- }
-
- ResolveTypes(rc);
-
- var prunedTopLevelDecls = new List<Declaration/*!*/>();
- foreach (var d in TopLevelDeclarations) {
- if (QKeyValue.FindBoolAttribute(d.Attributes, "ignore")) {
- continue;
- }
- // resolve all the non-type-declarations
- if (!(d is TypeCtorDecl || d is TypeSynonymDecl)) {
- int e = rc.ErrorCount;
- d.Resolve(rc);
- if (CommandLineOptions.Clo.OverlookBoogieTypeErrors && rc.ErrorCount != e && d is Implementation) {
- // ignore this implementation
- System.Console.WriteLine("Warning: Ignoring implementation {0} because of translation resolution errors", ((Implementation)d).Name);
- rc.ErrorCount = e;
- continue;
- }
- }
- prunedTopLevelDecls.Add(d);
- }
- ClearTopLevelDeclarations();
- AddTopLevelDeclarations(prunedTopLevelDecls);
-
- foreach (var v in Variables) {
- v.ResolveWhere(rc);
- }
- }
-
- private void ResolveTypes(ResolutionContext rc) {
- Contract.Requires(rc != null);
- // first resolve type constructors
- foreach (var d in TopLevelDeclarations.OfType<TypeCtorDecl>()) {
- if (!QKeyValue.FindBoolAttribute(d.Attributes, "ignore"))
- d.Resolve(rc);
- }
-
- // collect type synonym declarations
- List<TypeSynonymDecl/*!*/>/*!*/ synonymDecls = new List<TypeSynonymDecl/*!*/>();
- foreach (var d in TopLevelDeclarations.OfType<TypeSynonymDecl>()) {
- Contract.Assert(d != null);
- if (!QKeyValue.FindBoolAttribute(d.Attributes, "ignore"))
- synonymDecls.Add((TypeSynonymDecl)d);
- }
-
- // then resolve the type synonyms by a simple
- // fixed-point iteration
- TypeSynonymDecl.ResolveTypeSynonyms(synonymDecls, rc);
- }
-
- public int Typecheck() {
- return this.Typecheck((IErrorSink)null);
- }
-
- public int Typecheck(IErrorSink errorSink) {
- TypecheckingContext tc = new TypecheckingContext(errorSink);
- Typecheck(tc);
- return tc.ErrorCount;
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- Helpers.ExtraTraceInformation("Starting typechecking");
-
- int oldErrorCount = tc.ErrorCount;
- foreach (var d in TopLevelDeclarations) {
- d.Typecheck(tc);
- }
-
- if (oldErrorCount == tc.ErrorCount) {
- // check whether any type proxies have remained uninstantiated
- TypeAmbiguitySeeker/*!*/ seeker = new TypeAmbiguitySeeker(tc);
- foreach (var d in TopLevelDeclarations) {
- seeker.Visit(d);
- }
- }
- }
-
- public override Absy Clone()
- {
- var cloned = (Program)base.Clone();
- cloned.topLevelDeclarations = new List<Declaration>();
- cloned.AddTopLevelDeclarations(topLevelDeclarations);
- return cloned;
- }
-
- [Rep]
- private List<Declaration/*!*/>/*!*/ topLevelDeclarations;
-
- public IEnumerable<Declaration> TopLevelDeclarations
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Declaration>>()));
- return topLevelDeclarations.AsReadOnly();
- }
-
- set
- {
- Contract.Requires(value != null);
- // materialize the decls, in case there is any dependency
- // back on topLevelDeclarations
- var v = value.ToList();
- // remove null elements
- v.RemoveAll(d => (d == null));
- // now clear the decls
- ClearTopLevelDeclarations();
- // and add the values
- AddTopLevelDeclarations(v);
- }
- }
-
- public void AddTopLevelDeclaration(Declaration decl)
- {
- Contract.Requires(!TopLevelDeclarationsAreFrozen);
- Contract.Requires(decl != null);
-
- topLevelDeclarations.Add(decl);
- this.globalVariablesCache = null;
- }
-
- public void AddTopLevelDeclarations(IEnumerable<Declaration> decls)
- {
- Contract.Requires(!TopLevelDeclarationsAreFrozen);
- Contract.Requires(cce.NonNullElements(decls));
-
- topLevelDeclarations.AddRange(decls);
- this.globalVariablesCache = null;
- }
-
- public void RemoveTopLevelDeclaration(Declaration decl)
- {
- Contract.Requires(!TopLevelDeclarationsAreFrozen);
-
- topLevelDeclarations.Remove(decl);
- this.globalVariablesCache = null;
- }
-
- public void RemoveTopLevelDeclarations(Predicate<Declaration> match)
- {
- Contract.Requires(!TopLevelDeclarationsAreFrozen);
-
- topLevelDeclarations.RemoveAll(match);
- this.globalVariablesCache = null;
- }
-
- public void ClearTopLevelDeclarations()
- {
- Contract.Requires(!TopLevelDeclarationsAreFrozen);
-
- topLevelDeclarations.Clear();
- this.globalVariablesCache = null;
- }
-
- bool topLevelDeclarationsAreFrozen;
- public bool TopLevelDeclarationsAreFrozen { get { return topLevelDeclarationsAreFrozen; } }
- public void FreezeTopLevelDeclarations()
- {
- topLevelDeclarationsAreFrozen = true;
- }
-
- Dictionary<string, Implementation> implementationsCache;
- public IEnumerable<Implementation> Implementations
- {
- get
- {
- if (implementationsCache != null)
- {
- return implementationsCache.Values;
- }
- var result = TopLevelDeclarations.OfType<Implementation>();
- if (topLevelDeclarationsAreFrozen)
- {
- implementationsCache = result.ToDictionary(p => p.Id);
- }
- return result;
- }
- }
-
- public Implementation FindImplementation(string id)
- {
- Implementation result = null;
- if (implementationsCache != null && implementationsCache.TryGetValue(id, out result))
- {
- return result;
- }
- else
- {
- return Implementations.FirstOrDefault(i => i.Id == id);
- }
- }
-
- List<Axiom> axiomsCache;
- public IEnumerable<Axiom> Axioms
- {
- get
- {
- if (axiomsCache != null)
- {
- return axiomsCache;
- }
- var result = TopLevelDeclarations.OfType<Axiom>();
- if (topLevelDeclarationsAreFrozen)
- {
- axiomsCache = result.ToList();
- }
- return result;
- }
- }
-
- Dictionary<string, Procedure> proceduresCache;
- public IEnumerable<Procedure> Procedures
- {
- get
- {
- if (proceduresCache != null)
- {
- return proceduresCache.Values;
- }
- var result = TopLevelDeclarations.OfType<Procedure>();
- if (topLevelDeclarationsAreFrozen)
- {
- proceduresCache = result.ToDictionary(p => p.Name);
- }
- return result;
- }
- }
-
- public Procedure FindProcedure(string name)
- {
- Procedure result = null;
- if (proceduresCache != null && proceduresCache.TryGetValue(name, out result))
- {
- return result;
- }
- else
- {
- return Procedures.FirstOrDefault(p => p.Name == name);
- }
- }
-
- Dictionary<string, Function> functionsCache;
- public IEnumerable<Function> Functions
- {
- get
- {
- if (functionsCache != null)
- {
- return functionsCache.Values;
- }
- var result = TopLevelDeclarations.OfType<Function>();
- if (topLevelDeclarationsAreFrozen)
- {
- functionsCache = result.ToDictionary(f => f.Name);
- }
- return result;
- }
- }
-
- public Function FindFunction(string name)
- {
- Function result = null;
- if (functionsCache != null && functionsCache.TryGetValue(name, out result))
- {
- return result;
- }
- else
- {
- return Functions.FirstOrDefault(f => f.Name == name);
- }
- }
-
- public IEnumerable<Variable> Variables
- {
- get
- {
- return TopLevelDeclarations.OfType<Variable>();
- }
- }
-
- public IEnumerable<Constant> Constants
- {
- get
- {
- return TopLevelDeclarations.OfType<Constant>();
- }
- }
-
- private IEnumerable<GlobalVariable/*!*/> globalVariablesCache = null;
- public List<GlobalVariable/*!*/>/*!*/ GlobalVariables
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<GlobalVariable>>()));
-
- if (globalVariablesCache == null)
- globalVariablesCache = TopLevelDeclarations.OfType<GlobalVariable>();
-
- return new List<GlobalVariable>(globalVariablesCache);
- }
- }
-
- public IEnumerable<Block> Blocks()
- {
- return Implementations.Select(Item => Item.Blocks).SelectMany(Item => Item);
- }
-
- public void ComputeStronglyConnectedComponents() {
- foreach (var d in this.TopLevelDeclarations) {
- d.ComputeStronglyConnectedComponents();
- }
- }
-
- /// <summary>
- /// Reset the abstract stated computed before
- /// </summary>
- public void ResetAbstractInterpretationState() {
- foreach (var d in this.TopLevelDeclarations) {
- d.ResetAbstractInterpretationState();
- }
- }
-
- public void UnrollLoops(int n, bool uc) {
- Contract.Requires(0 <= n);
- foreach (var impl in Implementations) {
- if (impl.Blocks != null && impl.Blocks.Count > 0) {
- cce.BeginExpose(impl);
- {
- Block start = impl.Blocks[0];
- Contract.Assume(start != null);
- Contract.Assume(cce.IsConsistent(start));
- impl.Blocks = LoopUnroll.UnrollLoops(start, n, uc);
- impl.FreshenCaptureStates();
- }
- cce.EndExpose();
- }
- }
- }
-
- void CreateProceduresForLoops(Implementation impl, Graph<Block/*!*/>/*!*/ g,
- List<Implementation/*!*/>/*!*/ loopImpls,
- Dictionary<string, Dictionary<string, Block>> fullMap) {
- Contract.Requires(impl != null);
- Contract.Requires(cce.NonNullElements(loopImpls));
- // Enumerate the headers
- // for each header h:
- // create implementation p_h with
- // inputs = inputs, outputs, and locals of impl
- // outputs = outputs and locals of impl
- // locals = empty set
- // add call o := p_h(i) at the beginning of the header block
- // break the back edges whose target is h
- // Enumerate the headers again to create the bodies of p_h
- // for each header h:
- // compute the loop corresponding to h
- // make copies of all blocks in the loop for h
- // delete all target edges that do not go to a block in the loop
- // create a new entry block and a new return block
- // add edges from entry block to the loop header and the return block
- // add calls o := p_h(i) at the end of the blocks that are sources of back edges
- foreach (Block block in impl.Blocks)
- {
- AddToFullMap(fullMap, impl.Name, block.Label, block);
- }
-
- bool detLoopExtract = CommandLineOptions.Clo.DeterministicExtractLoops;
-
- Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToInputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>();
- Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToOutputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>();
- Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>/*!*/ loopHeaderToSubstMap = new Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>();
- Dictionary<Block/*!*/, LoopProcedure/*!*/>/*!*/ loopHeaderToLoopProc = new Dictionary<Block/*!*/, LoopProcedure/*!*/>();
- Dictionary<Block/*!*/, CallCmd/*!*/>/*!*/ loopHeaderToCallCmd1 = new Dictionary<Block/*!*/, CallCmd/*!*/>();
- Dictionary<Block, CallCmd> loopHeaderToCallCmd2 = new Dictionary<Block, CallCmd>();
- Dictionary<Block, AssignCmd> loopHeaderToAssignCmd = new Dictionary<Block, AssignCmd>();
-
- foreach (Block/*!*/ header in g.Headers) {
- Contract.Assert(header != null);
- Contract.Assert(header != null);
- List<Variable> inputs = new List<Variable>();
- List<Variable> outputs = new List<Variable>();
- List<Expr> callInputs1 = new List<Expr>();
- List<IdentifierExpr> callOutputs1 = new List<IdentifierExpr>();
- List<Expr> callInputs2 = new List<Expr>();
- List<IdentifierExpr> callOutputs2 = new List<IdentifierExpr>();
- List<AssignLhs> lhss = new List<AssignLhs>();
- List<Expr> rhss = new List<Expr>();
- Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); // Variable -> IdentifierExpr
-
- List<Variable>/*!*/ targets = new List<Variable>();
- HashSet<Variable> footprint = new HashSet<Variable>();
-
- foreach (Block/*!*/ b in g.BackEdgeNodes(header))
- {
- Contract.Assert(b != null);
- foreach (Block/*!*/ block in g.NaturalLoops(header, b))
- {
- Contract.Assert(block != null);
- foreach (Cmd/*!*/ cmd in block.Cmds)
- {
- Contract.Assert(cmd != null);
- cmd.AddAssignedVariables(targets);
-
- VariableCollector c = new VariableCollector();
- c.Visit(cmd);
- footprint.UnionWith(c.usedVars);
- }
- }
- }
-
- List<IdentifierExpr>/*!*/ globalMods = new List<IdentifierExpr>();
- Set targetSet = new Set();
- foreach (Variable/*!*/ v in targets)
- {
- Contract.Assert(v != null);
- if (targetSet.Contains(v))
- continue;
- targetSet.Add(v);
- if (v is GlobalVariable)
- globalMods.Add(new IdentifierExpr(Token.NoToken, v));
- }
-
- foreach (Variable v in impl.InParams) {
- Contract.Assert(v != null);
- if (!footprint.Contains(v)) continue;
- callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
- inputs.Add(f);
- callInputs2.Add(new IdentifierExpr(Token.NoToken, f));
- substMap[v] = new IdentifierExpr(Token.NoToken, f);
- }
- foreach (Variable v in impl.OutParams) {
- Contract.Assert(v != null);
- if (!footprint.Contains(v)) continue;
- callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
- inputs.Add(f1);
- if (targetSet.Contains(v))
- {
- callOutputs1.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
- outputs.Add(f2);
- callInputs2.Add(new IdentifierExpr(Token.NoToken, f2));
- callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2));
- lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2)));
- rhss.Add(new IdentifierExpr(Token.NoToken, f1));
- substMap[v] = new IdentifierExpr(Token.NoToken, f2);
- }
- else
- {
- callInputs2.Add(new IdentifierExpr(Token.NoToken, f1));
- substMap[v] = new IdentifierExpr(Token.NoToken, f1);
- }
- }
- foreach (Variable v in impl.LocVars) {
- Contract.Assert(v != null);
- if (!footprint.Contains(v)) continue;
- callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
- inputs.Add(f1);
- if (targetSet.Contains(v))
- {
- callOutputs1.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
- outputs.Add(f2);
- callInputs2.Add(new IdentifierExpr(Token.NoToken, f2));
- callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2));
- lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2)));
- rhss.Add(new IdentifierExpr(Token.NoToken, f1));
- substMap[v] = new IdentifierExpr(Token.NoToken, f2);
- }
- else
- {
- callInputs2.Add(new IdentifierExpr(Token.NoToken, f1));
- substMap[v] = new IdentifierExpr(Token.NoToken, f1);
- }
- }
-
- loopHeaderToInputs[header] = inputs;
- loopHeaderToOutputs[header] = outputs;
- loopHeaderToSubstMap[header] = substMap;
- LoopProcedure loopProc = new LoopProcedure(impl, header, inputs, outputs, globalMods);
- loopHeaderToLoopProc[header] = loopProc;
-
- CallCmd callCmd1 = new CallCmd(Token.NoToken, loopProc.Name, callInputs1, callOutputs1);
- callCmd1.Proc = loopProc;
- loopHeaderToCallCmd1[header] = callCmd1;
-
- CallCmd callCmd2 = new CallCmd(Token.NoToken, loopProc.Name, callInputs2, callOutputs2);
- callCmd2.Proc = loopProc;
- loopHeaderToCallCmd2[header] = callCmd2;
-
- Debug.Assert(lhss.Count == rhss.Count);
- if (lhss.Count > 0)
- {
- AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss);
- loopHeaderToAssignCmd[header] = assignCmd;
- }
- }
-
- // Keep track of the new blocks created: maps a header node to the
- // header_last block that was created because of splitting header.
- Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>();
-
- bool headRecursion = false; // testing an option to put recursive call before loop body
-
- IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance();
- foreach (Block/*!*/ header in sortedHeaders)
- {
- Contract.Assert(header != null);
- LoopProcedure loopProc = loopHeaderToLoopProc[header];
- Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
- HashSet<string> dummyBlocks = new HashSet<string>();
-
- CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]); // fix me
- List<Variable> inputs = loopHeaderToInputs[header];
- List<Variable> outputs = loopHeaderToOutputs[header];
- int si_unique_loc = 1; // Added by AL: to distinguish the back edges
- foreach (Block/*!*/ source in g.BackEdgeNodes(header)) {
- Contract.Assert(source != null);
- foreach (Block/*!*/ block in g.NaturalLoops(header, source)) {
- Contract.Assert(block != null);
- if (blockMap.ContainsKey(block))
- continue;
- Block newBlock = new Block();
- newBlock.Label = block.Label;
- if (headRecursion && block == header)
- {
- CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
- addUniqueCallAttr(si_unique_loc, callCmd);
- si_unique_loc++;
- newBlock.Cmds.Add(callCmd); // add the recursive call at head of loop
- var rest = codeCopier.CopyCmdSeq(block.Cmds);
- newBlock.Cmds.AddRange(rest);
- }
- else
- newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds);
- blockMap[block] = newBlock;
- if (newBlocksCreated.ContainsKey(block))
- {
- Block newBlock2 = new Block();
- newBlock2.Label = newBlocksCreated[block].Label;
- newBlock2.Cmds = codeCopier.CopyCmdSeq(newBlocksCreated[block].Cmds);
- blockMap[newBlocksCreated[block]] = newBlock2;
- }
- //for detLoopExtract, need the immediate successors even outside the loop
- if (detLoopExtract) {
- GotoCmd auxGotoCmd = block.TransferCmd as GotoCmd;
- Contract.Assert(auxGotoCmd != null && auxGotoCmd.labelNames != null &&
- auxGotoCmd.labelTargets != null && auxGotoCmd.labelTargets.Count >= 1);
- foreach(var bl in auxGotoCmd.labelTargets) {
- bool found = false;
- foreach(var n in g.NaturalLoops(header, source)) { //very expensive, can we do a contains?
- if (bl == n) { //clarify: is this the right comparison?
- found = true;
- break;
- }
- }
- if (!found) {
- Block auxNewBlock = new Block();
- auxNewBlock.Label = ((Block)bl).Label;
- auxNewBlock.Cmds = codeCopier.CopyCmdSeq(((Block)bl).Cmds);
- //add restoration code for such blocks
- if (loopHeaderToAssignCmd.ContainsKey(header))
- {
- AssignCmd assignCmd = loopHeaderToAssignCmd[header];
- auxNewBlock.Cmds.Add(assignCmd);
- }
- List<AssignLhs> lhsg = new List<AssignLhs>();
- List<IdentifierExpr>/*!*/ globalsMods = loopHeaderToLoopProc[header].Modifies;
- foreach (IdentifierExpr gl in globalsMods)
- lhsg.Add(new SimpleAssignLhs(Token.NoToken, gl));
- List<Expr> rhsg = new List<Expr>();
- foreach (IdentifierExpr gl in globalsMods)
- rhsg.Add(new OldExpr(Token.NoToken, gl));
- if (lhsg.Count != 0)
- {
- AssignCmd globalAssignCmd = new AssignCmd(Token.NoToken, lhsg, rhsg);
- auxNewBlock.Cmds.Add(globalAssignCmd);
- }
- blockMap[(Block)bl] = auxNewBlock;
- }
- }
-
- }
- }
-
- List<Cmd> cmdSeq;
- if (headRecursion)
- cmdSeq = new List<Cmd>();
- else
- {
- CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
- addUniqueCallAttr(si_unique_loc, callCmd);
- si_unique_loc++;
- cmdSeq = new List<Cmd> { callCmd };
- }
-
- Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy",
- new List<Cmd>{ new AssumeCmd(Token.NoToken, Expr.False) }, new ReturnCmd(Token.NoToken));
- Block/*!*/ block2 = new Block(Token.NoToken, block1.Label,
- cmdSeq, new ReturnCmd(Token.NoToken));
- impl.Blocks.Add(block1);
- dummyBlocks.Add(block1.Label);
-
- GotoCmd gotoCmd = source.TransferCmd as GotoCmd;
- Contract.Assert(gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Count >= 1);
- List<String>/*!*/ newLabels = new List<String>();
- List<Block>/*!*/ newTargets = new List<Block>();
- for (int i = 0; i < gotoCmd.labelTargets.Count; i++) {
- if (gotoCmd.labelTargets[i] == header)
- continue;
- newTargets.Add(gotoCmd.labelTargets[i]);
- newLabels.Add(gotoCmd.labelNames[i]);
- }
- newTargets.Add(block1);
- newLabels.Add(block1.Label);
- gotoCmd.labelNames = newLabels;
- gotoCmd.labelTargets = newTargets;
- blockMap[block1] = block2;
- }
- List<Block/*!*/>/*!*/ blocks = new List<Block/*!*/>();
- Block exit = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- GotoCmd cmd = new GotoCmd(Token.NoToken,
- new List<String> { cce.NonNull(blockMap[header]).Label, exit.Label },
- new List<Block> { blockMap[header], exit });
-
- if (detLoopExtract) //cutting the non-determinism
- cmd = new GotoCmd(Token.NoToken,
- new List<String> { cce.NonNull(blockMap[header]).Label },
- new List<Block> { blockMap[header] });
-
- Block entry;
- List<Cmd> initCmds = new List<Cmd>();
- if (loopHeaderToAssignCmd.ContainsKey(header)) {
- AssignCmd assignCmd = loopHeaderToAssignCmd[header];
- initCmds.Add(assignCmd);
- }
-
- entry = new Block(Token.NoToken, "entry", initCmds, cmd);
- blocks.Add(entry);
-
- foreach (Block/*!*/ block in blockMap.Keys) {
- Contract.Assert(block != null);
- Block/*!*/ newBlock = cce.NonNull(blockMap[block]);
- GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
- if (gotoCmd == null) {
- newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- } else {
- Contract.Assume(gotoCmd.labelNames != null && gotoCmd.labelTargets != null);
- List<String> newLabels = new List<String>();
- List<Block> newTargets = new List<Block>();
- for (int i = 0; i < gotoCmd.labelTargets.Count; i++) {
- Block target = gotoCmd.labelTargets[i];
- if (blockMap.ContainsKey(target)) {
- newLabels.Add(gotoCmd.labelNames[i]);
- newTargets.Add(blockMap[target]);
- }
- }
- if (newTargets.Count == 0) {
- if (!detLoopExtract)
- newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
- newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- } else {
- newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets);
- }
- }
- blocks.Add(newBlock);
- }
- blocks.Add(exit);
- Implementation loopImpl =
- new Implementation(Token.NoToken, loopProc.Name,
- new List<TypeVariable>(), inputs, outputs, new List<Variable>(), blocks);
- loopImpl.Proc = loopProc;
- loopImpls.Add(loopImpl);
-
- // Make a (shallow) copy of the header before splitting it
- Block origHeader = new Block(header.tok, header.Label, header.Cmds, header.TransferCmd);
-
- // Finally, add call to the loop in the containing procedure
- string lastIterBlockName = header.Label + "_last";
- Block lastIterBlock = new Block(Token.NoToken, lastIterBlockName, header.Cmds, header.TransferCmd);
- newBlocksCreated[header] = lastIterBlock;
- header.Cmds = new List<Cmd> { loopHeaderToCallCmd1[header] };
- header.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { lastIterBlockName }, new List<Block> { lastIterBlock });
- impl.Blocks.Add(lastIterBlock);
- blockMap[origHeader] = blockMap[header];
- blockMap.Remove(header);
-
- Contract.Assert(fullMap[impl.Name][header.Label] == header);
- fullMap[impl.Name][header.Label] = origHeader;
-
- foreach (Block block in blockMap.Keys)
- {
- // Don't add dummy blocks to the map
- if (dummyBlocks.Contains(blockMap[block].Label)) continue;
-
- // Following two statements are for nested loops: compose map
- if (!fullMap[impl.Name].ContainsKey(block.Label)) continue;
- var target = fullMap[impl.Name][block.Label];
-
- AddToFullMap(fullMap, loopProc.Name, blockMap[block].Label, target);
- }
-
- fullMap[impl.Name].Remove(header.Label);
- fullMap[impl.Name][lastIterBlockName] = origHeader;
- }
- }
-
- private void addUniqueCallAttr(int val, CallCmd cmd)
- {
- var a = new List<object>();
- a.Add(new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(val)));
-
- cmd.Attributes = new QKeyValue(Token.NoToken, "si_unique_call", a, cmd.Attributes);
- }
-
- private void AddToFullMap(Dictionary<string, Dictionary<string, Block>> fullMap, string procName, string blockName, Block block)
- {
- if (!fullMap.ContainsKey(procName))
- fullMap[procName] = new Dictionary<string, Block>();
- fullMap[procName][blockName] = block;
- }
-
- public static Graph<Implementation> BuildCallGraph(Program program) {
- Graph<Implementation> callGraph = new Graph<Implementation>();
- Dictionary<Procedure, HashSet<Implementation>> procToImpls = new Dictionary<Procedure, HashSet<Implementation>>();
- foreach (var proc in program.Procedures) {
- procToImpls[proc] = new HashSet<Implementation>();
- }
- foreach (var impl in program.Implementations) {
- if (impl.SkipVerification) continue;
- callGraph.AddSource(impl);
- procToImpls[impl.Proc].Add(impl);
- }
- foreach (var impl in program.Implementations) {
- if (impl.SkipVerification) continue;
- foreach (Block b in impl.Blocks) {
- foreach (Cmd c in b.Cmds) {
- CallCmd cc = c as CallCmd;
- if (cc == null) continue;
- foreach (Implementation callee in procToImpls[cc.Proc]) {
- callGraph.AddEdge(impl, callee);
- }
- }
- }
- }
- return callGraph;
- }
-
- public static Graph<Block/*!*/>/*!*/ GraphFromImpl(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<Graph<Block>>().Nodes));
- Contract.Ensures(Contract.Result<Graph<Block>>() != null);
-
- Graph<Block/*!*/> g = new Graph<Block/*!*/>();
- g.AddSource(impl.Blocks[0]); // there is always at least one node in the graph
-
- foreach (Block b in impl.Blocks) {
- Contract.Assert(b != null);
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- foreach (Block/*!*/ dest in cce.NonNull(gtc.labelTargets)) {
- Contract.Assert(dest != null);
- g.AddEdge(b, dest);
- }
- }
- }
- return g;
- }
-
- public class IrreducibleLoopException : Exception {}
-
- public Graph<Block> ProcessLoops(Implementation impl) {
- while (true) {
- impl.PruneUnreachableBlocks();
- impl.ComputePredecessorsForBlocks();
- Graph<Block/*!*/>/*!*/ g = GraphFromImpl(impl);
- g.ComputeLoops();
- if (g.Reducible) {
- return g;
- }
- throw new IrreducibleLoopException();
-#if USED_CODE
- System.Diagnostics.Debug.Assert(g.SplitCandidates.Count > 0);
- Block splitCandidate = null;
- foreach (Block b in g.SplitCandidates) {
- if (b.Predecessors.Length > 1) {
- splitCandidate = b;
- break;
- }
- }
- System.Diagnostics.Debug.Assert(splitCandidate != null);
- int count = 0;
- foreach (Block b in splitCandidate.Predecessors) {
- GotoCmd gotoCmd = (GotoCmd)b.TransferCmd;
- gotoCmd.labelNames.Remove(splitCandidate.Label);
- gotoCmd.labelTargets.Remove(splitCandidate);
-
- CodeCopier codeCopier = new CodeCopier(new Hashtable(), new Hashtable());
- List<Cmd> newCmdSeq = codeCopier.CopyCmdSeq(splitCandidate.Cmds);
- TransferCmd newTransferCmd;
- GotoCmd splitGotoCmd = splitCandidate.TransferCmd as GotoCmd;
- if (splitGotoCmd == null) {
- newTransferCmd = new ReturnCmd(splitCandidate.tok);
- }
- else {
- List<String> newLabelNames = new List<String>();
- newLabelNames.AddRange(splitGotoCmd.labelNames);
- List<Block> newLabelTargets = new List<Block>();
- newLabelTargets.AddRange(splitGotoCmd.labelTargets);
- newTransferCmd = new GotoCmd(splitCandidate.tok, newLabelNames, newLabelTargets);
- }
- Block copy = new Block(splitCandidate.tok, splitCandidate.Label + count++, newCmdSeq, newTransferCmd);
-
- impl.Blocks.Add(copy);
- gotoCmd.AddTarget(copy);
- }
-#endif
- }
- }
-
- public Dictionary<string, Dictionary<string, Block>> ExtractLoops()
- {
- HashSet<string> procsWithIrreducibleLoops = null;
- return ExtractLoops(out procsWithIrreducibleLoops);
- }
-
- public Dictionary<string, Dictionary<string, Block>> ExtractLoops(out HashSet<string> procsWithIrreducibleLoops)
- {
- procsWithIrreducibleLoops = new HashSet<string>();
- List<Implementation/*!*/>/*!*/ loopImpls = new List<Implementation/*!*/>();
- Dictionary<string, Dictionary<string, Block>> fullMap = new Dictionary<string, Dictionary<string, Block>>();
- foreach (var impl in this.Implementations)
- {
- if (impl.Blocks != null && impl.Blocks.Count > 0)
- {
- try
- {
- Graph<Block> g = ProcessLoops(impl);
- CreateProceduresForLoops(impl, g, loopImpls, fullMap);
- }
- catch (IrreducibleLoopException)
- {
- System.Diagnostics.Debug.Assert(!fullMap.ContainsKey(impl.Name));
- fullMap[impl.Name] = null;
- procsWithIrreducibleLoops.Add(impl.Name);
-
- if (CommandLineOptions.Clo.ExtractLoopsUnrollIrreducible)
- {
- // statically unroll loops in this procedure
-
- // First, build a map of the current blocks
- var origBlocks = new Dictionary<string, Block>();
- foreach (var blk in impl.Blocks) origBlocks.Add(blk.Label, blk);
-
- // unroll
- Block start = impl.Blocks[0];
- impl.Blocks = LoopUnroll.UnrollLoops(start, CommandLineOptions.Clo.RecursionBound, false);
-
- // Now construct the "map back" information
- // Resulting block label -> original block
- var blockMap = new Dictionary<string, Block>();
- foreach (var blk in impl.Blocks)
- {
- var sl = LoopUnroll.sanitizeLabel(blk.Label);
- if (sl == blk.Label) blockMap.Add(blk.Label, blk);
- else
- {
- Contract.Assert(origBlocks.ContainsKey(sl));
- blockMap.Add(blk.Label, origBlocks[sl]);
- }
- }
- fullMap[impl.Name] = blockMap;
- }
- }
- }
- }
- foreach (Implementation/*!*/ loopImpl in loopImpls)
- {
- Contract.Assert(loopImpl != null);
- AddTopLevelDeclaration(loopImpl);
- AddTopLevelDeclaration(loopImpl.Proc);
- }
- return fullMap;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitProgram(this);
- }
-
- int extractedFunctionCount;
- public string FreshExtractedFunctionName()
- {
- var c = System.Threading.Interlocked.Increment(ref extractedFunctionCount);
- return string.Format("##extracted_function##{0}", c);
- }
-
- private int invariantGenerationCounter = 0;
-
- public Constant MakeExistentialBoolean() {
- Constant ExistentialBooleanConstant = new Constant(Token.NoToken, new TypedIdent(tok, "_b" + invariantGenerationCounter, Microsoft.Boogie.Type.Bool), false);
- invariantGenerationCounter++;
- ExistentialBooleanConstant.AddAttribute("existential", new object[] { Expr.True });
- AddTopLevelDeclaration(ExistentialBooleanConstant);
- return ExistentialBooleanConstant;
- }
-
- public PredicateCmd CreateCandidateInvariant(Expr e, string tag = null) {
- Constant ExistentialBooleanConstant = MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Token.NoToken, ExistentialBooleanConstant);
- PredicateCmd invariant = new AssertCmd(Token.NoToken, Expr.Imp(ExistentialBoolean, e));
- if (tag != null)
- invariant.Attributes = new QKeyValue(Token.NoToken, "tag", new List<object>(new object[] { tag }), null);
- return invariant;
- }
- }
-
- //---------------------------------------------------------------------
- // Declarations
-
- [ContractClass(typeof(DeclarationContracts))]
- public abstract class Declaration : Absy {
- public QKeyValue Attributes;
-
- public Declaration(IToken tok)
- : base(tok) {
- Contract.Requires(tok != null);
- }
-
- protected void EmitAttributes(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Emit(stream);
- stream.Write(" ");
- }
- }
-
- protected void ResolveAttributes(ResolutionContext rc) {
- Contract.Requires(rc != null);
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Resolve(rc);
- }
- }
-
- protected void TypecheckAttributes(TypecheckingContext rc) {
- Contract.Requires(rc != null);
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(rc);
- }
- }
-
- /// <summary>
- /// If the declaration has an attribute {:name} or {:name true}, then set "result" to "true" and return "true".
- /// If the declaration has an attribute {:name false}, then set "result" to "false" and return "true".
- /// Otherwise, return "false" and leave "result" unchanged (which gives the caller an easy way to indicate
- /// a default value if the attribute is not mentioned).
- /// If there is more than one attribute called :name, then the last attribute rules.
- /// </summary>
- public bool CheckBooleanAttribute(string name, ref bool result) {
- Contract.Requires(name != null);
- var kv = FindAttribute(name);
- if (kv != null) {
- if (kv.Params.Count == 0) {
- result = true;
- return true;
- } else if (kv.Params.Count == 1) {
- var lit = kv.Params[0] as LiteralExpr;
- if (lit != null && lit.isBool) {
- result = lit.asBool;
- return true;
- }
- }
- }
- return false;
- }
-
- /// <summary>
- /// Find and return the last occurrence of an attribute with the name "name", if any. If none, return null.
- /// </summary>
- public QKeyValue FindAttribute(string name) {
- Contract.Requires(name != null);
- QKeyValue res = null;
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- res = kv;
- }
- }
- return res;
- }
-
- // Look for {:name expr} in list of attributes.
- public Expr FindExprAttribute(string name) {
- Contract.Requires(name != null);
- Expr res = null;
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
- res = (Expr)kv.Params[0];
- }
- }
- }
- return res;
- }
-
- // Look for {:name string} in list of attributes.
- public string FindStringAttribute(string name) {
- Contract.Requires(name != null);
- return QKeyValue.FindStringAttribute(this.Attributes, name);
- }
-
- // Look for {:name N} or {:name N} in list of attributes. Return result in 'result'
- // (which is not touched if there is no attribute specified).
- //
- // Returns false is there was an error processing the flag, true otherwise.
- public bool CheckIntAttribute(string name, ref int result) {
- Contract.Requires(name != null);
- Expr expr = FindExprAttribute(name);
- if (expr != null) {
- if (expr is LiteralExpr && ((LiteralExpr)expr).isBigNum) {
- result = ((LiteralExpr)expr).asBigNum.ToInt;
- } else {
- return false;
- }
- }
- return true;
- }
-
- public void AddAttribute(string name, params object[] vals) {
- Contract.Requires(name != null);
- QKeyValue kv;
- for (kv = this.Attributes; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- kv.AddParams(vals);
- break;
- }
- }
- if (kv == null) {
- Attributes = new QKeyValue(tok, name, new List<object/*!*/>(vals), Attributes);
- }
- }
-
- public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
- public abstract void Register(ResolutionContext/*!*/ rc);
-
- /// <summary>
- /// Compute the strongly connected components of the declaration.
- /// By default, it does nothing
- /// </summary>
- public virtual void ComputeStronglyConnectedComponents() { /* Does nothing */
- }
-
- /// <summary>
- /// Reset the abstract stated computed before
- /// </summary>
- public virtual void ResetAbstractInterpretationState() { /* does nothing */
- }
- }
- [ContractClassFor(typeof(Declaration))]
- public abstract class DeclarationContracts : Declaration {
- public DeclarationContracts() :base(null){
- }
- public override void Register(ResolutionContext rc) {
- Contract.Requires(rc != null);
- throw new NotImplementedException();
- }
- public override void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- throw new NotImplementedException();
- }
- }
-
- public class Axiom : Declaration {
- private Expr/*!*/ expression;
-
- public Expr Expr {
- get {
- Contract.Ensures(Contract.Result<Expr>() != null);
- return this.expression;
- }
- set {
- Contract.Requires(value != null);
- this.expression = value;
- }
- }
-
- [ContractInvariantMethod]
- void ExprInvariant() {
- Contract.Invariant(this.expression != null);
- }
-
- public string Comment;
-
- public Axiom(IToken tok, Expr expr)
- : this(tok, expr, null) {
- Contract.Requires(expr != null);
- Contract.Requires(tok != null);
- }
-
- public Axiom(IToken/*!*/ tok, Expr/*!*/ expr, string comment)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- this.expression = expr;
- Comment = comment;
- }
-
- public Axiom(IToken tok, Expr expr, string comment, QKeyValue kv)
- : this(tok, expr, comment) {
- Contract.Requires(expr != null);
- Contract.Requires(tok != null);
- this.Attributes = kv;
- }
-
- public bool DependenciesCollected { get; set; }
-
- ISet<Function> functionDependencies;
-
- public ISet<Function> FunctionDependencies
- {
- get { return functionDependencies; }
- }
-
- public void AddFunctionDependency(Function function)
- {
- Contract.Requires(function != null);
-
- if (functionDependencies == null)
- {
- functionDependencies = new HashSet<Function>();
- }
- functionDependencies.Add(function);
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "axiom ");
- EmitAttributes(stream);
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddAxiom(this);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- ResolveAttributes(rc);
- rc.StateMode = ResolutionContext.State.StateLess;
- Expr.Resolve(rc);
- rc.StateMode = ResolutionContext.State.Single;
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- TypecheckAttributes(tc);
- Expr.Typecheck(tc);
- Contract.Assert(Expr.Type != null); // follows from postcondition of Expr.Typecheck
- if (!Expr.Type.Unify(Type.Bool)) {
- tc.Error(this, "axioms must be of type bool");
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAxiom(this);
- }
- }
-
- public abstract class NamedDeclaration : Declaration {
- private string/*!*/ name;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(name != null);
- }
-
- public string/*!*/ Name {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return this.name;
- }
- set {
- Contract.Requires(value != null);
- this.name = value;
- }
- }
-
- public int TimeLimit
- {
- get
- {
- int tl = CommandLineOptions.Clo.ProverKillTime;
- CheckIntAttribute("timeLimit", ref tl);
- return tl;
- }
- }
-
- public NamedDeclaration(IToken/*!*/ tok, string/*!*/ name)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- this.name = name;
- }
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return cce.NonNull(Name);
- }
- }
-
- public class TypeCtorDecl : NamedDeclaration {
- public readonly int Arity;
-
- public TypeCtorDecl(IToken/*!*/ tok, string/*!*/ name, int Arity)
- : base(tok, name) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- this.Arity = Arity;
- }
- public TypeCtorDecl(IToken/*!*/ tok, string/*!*/ name, int Arity, QKeyValue kv)
- : base(tok, name) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- this.Arity = Arity;
- this.Attributes = kv;
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "type ");
- EmitAttributes(stream);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
- for (int i = 0; i < Arity; ++i)
- stream.Write(" _");
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddType(this);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- ResolveAttributes(rc);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- TypecheckAttributes(tc);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTypeCtorDecl(this);
- }
- }
-
- public class TypeSynonymDecl : NamedDeclaration {
- private List<TypeVariable>/*!*/ typeParameters;
-
- public List<TypeVariable> TypeParameters {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
- return this.typeParameters;
- }
- set {
- Contract.Requires(value != null);
- this.typeParameters = value;
- }
- }
-
- private Type/*!*/ body;
-
- public Type Body {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.body;
- }
- set {
- Contract.Requires(value != null);
- this.body = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this.body != null);
- Contract.Invariant(this.typeParameters != null);
- }
-
- public TypeSynonymDecl(IToken/*!*/ tok, string/*!*/ name,
- List<TypeVariable>/*!*/ typeParams, Type/*!*/ body)
- : base(tok, name) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(body != null);
- this.typeParameters = typeParams;
- this.body = body;
- }
- public TypeSynonymDecl(IToken/*!*/ tok, string/*!*/ name,
- List<TypeVariable>/*!*/ typeParams, Type/*!*/ body, QKeyValue kv)
- : base(tok, name) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(body != null);
- this.typeParameters = typeParams;
- this.body = body;
- this.Attributes = kv;
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "type ");
- EmitAttributes(stream);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
- if (TypeParameters.Count > 0)
- stream.Write(" ");
- TypeParameters.Emit(stream, " ");
- stream.Write(" = ");
- Body.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddType(this);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- ResolveAttributes(rc);
-
- int previousState = rc.TypeBinderState;
- try {
- foreach (TypeVariable/*!*/ v in TypeParameters) {
- Contract.Assert(v != null);
- rc.AddTypeBinder(v);
- }
- Body = Body.ResolveType(rc);
- } finally {
- rc.TypeBinderState = previousState;
- }
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- TypecheckAttributes(tc);
- }
-
- public static void ResolveTypeSynonyms(List<TypeSynonymDecl/*!*/>/*!*/ synonymDecls, ResolutionContext/*!*/ rc) {
- Contract.Requires(cce.NonNullElements(synonymDecls));
- Contract.Requires(rc != null);
- // then discover all dependencies between type synonyms
- IDictionary<TypeSynonymDecl/*!*/, List<TypeSynonymDecl/*!*/>/*!*/>/*!*/ deps =
- new Dictionary<TypeSynonymDecl/*!*/, List<TypeSynonymDecl/*!*/>/*!*/>();
- foreach (TypeSynonymDecl/*!*/ decl in synonymDecls) {
- Contract.Assert(decl != null);
- List<TypeSynonymDecl/*!*/>/*!*/ declDeps = new List<TypeSynonymDecl/*!*/>();
- FindDependencies(decl.Body, declDeps, rc);
- deps.Add(decl, declDeps);
- }
-
- List<TypeSynonymDecl/*!*/>/*!*/ resolved = new List<TypeSynonymDecl/*!*/>();
-
- int unresolved = synonymDecls.Count - resolved.Count;
- while (unresolved > 0) {
- foreach (TypeSynonymDecl/*!*/ decl in synonymDecls) {
- Contract.Assert(decl != null);
- if (!resolved.Contains(decl) &&
- deps[decl].All(d => resolved.Contains(d))) {
- decl.Resolve(rc);
- resolved.Add(decl);
- }
- }
-
- int newUnresolved = synonymDecls.Count - resolved.Count;
- if (newUnresolved < unresolved) {
- // we are making progress
- unresolved = newUnresolved;
- } else {
- // there have to be cycles in the definitions
- foreach (TypeSynonymDecl/*!*/ decl in synonymDecls) {
- Contract.Assert(decl != null);
- if (!resolved.Contains(decl)) {
- rc.Error(decl,
- "type synonym could not be resolved because of cycles: {0}" +
- " (replacing body with \"bool\" to continue resolving)",
- decl.Name);
-
- // we simply replace the bodies of all remaining type
- // synonyms with "bool" so that resolution can continue
- decl.Body = Type.Bool;
- decl.Resolve(rc);
- }
- }
-
- unresolved = 0;
- }
- }
- }
-
- // determine a list of all type synonyms that occur in "type"
- private static void FindDependencies(Type/*!*/ type, List<TypeSynonymDecl/*!*/>/*!*/ deps, ResolutionContext/*!*/ rc) {
- Contract.Requires(type != null);
- Contract.Requires(cce.NonNullElements(deps));
- Contract.Requires(rc != null);
- if (type.IsVariable || type.IsBasic) {
- // nothing
- } else if (type.IsUnresolved) {
- UnresolvedTypeIdentifier/*!*/ unresType = type.AsUnresolved;
- Contract.Assert(unresType != null);
- TypeSynonymDecl dep = rc.LookUpTypeSynonym(unresType.Name);
- if (dep != null)
- deps.Add(dep);
- foreach (Type/*!*/ subtype in unresType.Arguments) {
- Contract.Assert(subtype != null);
- FindDependencies(subtype, deps, rc);
- }
- } else if (type.IsMap) {
- MapType/*!*/ mapType = type.AsMap;
- Contract.Assert(mapType != null);
- foreach (Type/*!*/ subtype in mapType.Arguments) {
- Contract.Assert(subtype != null);
- FindDependencies(subtype, deps, rc);
- }
- FindDependencies(mapType.Result, deps, rc);
- } else if (type.IsCtor) {
- // this can happen because we allow types to be resolved multiple times
- CtorType/*!*/ ctorType = type.AsCtor;
- Contract.Assert(ctorType != null);
- foreach (Type/*!*/ subtype in ctorType.Arguments) {
- Contract.Assert(subtype != null);
- FindDependencies(subtype, deps, rc);
- }
- } else {
- System.Diagnostics.Debug.Fail("Did not expect this type during resolution: "
- + type);
- }
- }
-
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTypeSynonymDecl(this);
- }
- }
-
- public abstract class Variable : NamedDeclaration {
- private TypedIdent/*!*/ typedIdent;
-
- public TypedIdent TypedIdent {
- get {
- Contract.Ensures(Contract.Result<TypedIdent>() != null);
- return this.typedIdent;
- }
- set {
- Contract.Requires(value != null);
- this.typedIdent = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this.typedIdent != null);
- }
-
- public Variable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent)
- : base(tok, typedIdent.Name) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- this.typedIdent = typedIdent;
- }
-
- public Variable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent, QKeyValue kv)
- : base(tok, typedIdent.Name) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- this.typedIdent = typedIdent;
- this.Attributes = kv;
- }
-
- public abstract bool IsMutable {
- get;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "var ");
- EmitVitals(stream, level, true);
- stream.WriteLine(";");
- }
- public void EmitVitals(TokenTextWriter stream, int level, bool emitAttributes) {
- Contract.Requires(stream != null);
- if (emitAttributes) {
- EmitAttributes(stream);
- }
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds && this.TypedIdent.HasName) {
- stream.Write("h{0}^^", this.GetHashCode()); // the idea is that this will prepend the name printed by TypedIdent.Emit
- }
- this.TypedIdent.Emit(stream);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- this.TypedIdent.Resolve(rc);
- }
- public void ResolveWhere(ResolutionContext rc) {
- Contract.Requires(rc != null);
- if (QKeyValue.FindBoolAttribute(Attributes, "assumption") && this.TypedIdent.WhereExpr != null)
- {
- rc.Error(tok, "assumption variable may not be declared with a where clause");
- }
- if (this.TypedIdent.WhereExpr != null) {
- this.TypedIdent.WhereExpr.Resolve(rc);
- }
- ResolveAttributes(rc);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- TypecheckAttributes(tc);
- this.TypedIdent.Typecheck(tc);
- if (QKeyValue.FindBoolAttribute(Attributes, "assumption") && !this.TypedIdent.Type.IsBool)
- {
- tc.Error(tok, "assumption variable must be of type 'bool'");
- }
- }
- }
-
- public class VariableComparer : IComparer {
- public int Compare(object a, object b) {
- Variable A = a as Variable;
- Variable B = b as Variable;
- if (A == null || B == null) {
- throw new ArgumentException("VariableComparer works only on objects of type Variable");
- }
- return cce.NonNull(A.Name).CompareTo(B.Name);
- }
- }
-
- // class to specify the <:-parents of the values of constants
- public class ConstantParent {
- public readonly IdentifierExpr/*!*/ Parent;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Parent != null);
- }
-
- // if true, the sub-dag underneath this constant-parent edge is
- // disjoint from all other unique sub-dags
- public readonly bool Unique;
-
- public ConstantParent(IdentifierExpr parent, bool unique) {
- Contract.Requires(parent != null);
- Parent = parent;
- Unique = unique;
- }
- }
-
- public class Constant : Variable {
- // when true, the value of this constant is meant to be distinct
- // from all other constants.
- public readonly bool Unique;
-
- // the <:-parents of the value of this constant. If the field is
- // null, no information about the parents is provided, which means
- // that the parental situation is unconstrained.
- public readonly ReadOnlyCollection<ConstantParent/*!*/> Parents;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(Parents, true));
- }
-
- // if true, it is assumed that the immediate <:-children of the
- // value of this constant are completely specified
- public readonly bool ChildrenComplete;
-
- public Constant(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent)
- : base(tok, typedIdent) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- Contract.Requires(typedIdent.Name != null && (!typedIdent.HasName || typedIdent.Name.Length > 0));
- Contract.Requires(typedIdent.WhereExpr == null);
- this.Unique = true;
- this.Parents = null;
- this.ChildrenComplete = false;
- }
- public Constant(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent, bool unique)
- : base(tok, typedIdent) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- Contract.Requires(typedIdent.Name != null && typedIdent.Name.Length > 0);
- Contract.Requires(typedIdent.WhereExpr == null);
- this.Unique = unique;
- this.Parents = null;
- this.ChildrenComplete = false;
- }
- public Constant(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent,
- bool unique,
- IEnumerable<ConstantParent/*!*/> parents, bool childrenComplete,
- QKeyValue kv)
- : base(tok, typedIdent, kv) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- Contract.Requires(cce.NonNullElements(parents, true));
- Contract.Requires(typedIdent.Name != null && typedIdent.Name.Length > 0);
- Contract.Requires(typedIdent.WhereExpr == null);
- this.Unique = unique;
- this.Parents = parents == null ? null : new ReadOnlyCollection<ConstantParent>(parents.ToList());
- this.ChildrenComplete = childrenComplete;
- }
- public override bool IsMutable {
- get {
- return false;
- }
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "const ");
- EmitAttributes(stream);
- if (this.Unique) {
- stream.Write(this, level, "unique ");
- }
- EmitVitals(stream, level, false);
-
- if (Parents != null || ChildrenComplete) {
- stream.Write(this, level, " extends");
- string/*!*/ sep = " ";
- foreach (ConstantParent/*!*/ p in cce.NonNull(Parents)) {
- Contract.Assert(p != null);
- stream.Write(this, level, sep);
- sep = ", ";
- if (p.Unique)
- stream.Write(this, level, "unique ");
- p.Parent.Emit(stream);
- }
- if (ChildrenComplete)
- stream.Write(this, level, " complete");
- }
-
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddVariable(this, true);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- base.Resolve(rc);
- if (Parents != null) {
- foreach (ConstantParent/*!*/ p in Parents) {
- Contract.Assert(p != null);
- p.Parent.Resolve(rc);
- if (p.Parent.Decl != null && !(p.Parent.Decl is Constant))
- rc.Error(p.Parent, "the parent of a constant has to be a constant");
- if (this.Equals(p.Parent.Decl))
- rc.Error(p.Parent, "constant cannot be its own parent");
- }
- }
-
- // check that no parent occurs twice
- // (could be optimised)
- if (Parents != null) {
- for (int i = 0; i < Parents.Count; ++i) {
- if (Parents[i].Parent.Decl != null) {
- for (int j = i + 1; j < Parents.Count; ++j) {
- if (Parents[j].Parent.Decl != null &&
- cce.NonNull(Parents[i].Parent.Decl).Equals(Parents[j].Parent.Decl))
- rc.Error(Parents[j].Parent,
- "{0} occurs more than once as parent",
- Parents[j].Parent.Decl);
- }
- }
- }
- }
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- base.Typecheck(tc);
-
- if (Parents != null) {
- foreach (ConstantParent/*!*/ p in Parents) {
- Contract.Assert(p != null);
- p.Parent.Typecheck(tc);
- if (!cce.NonNull(p.Parent.Decl).TypedIdent.Type.Unify(this.TypedIdent.Type))
- tc.Error(p.Parent,
- "parent of constant has incompatible type ({0} instead of {1})",
- p.Parent.Decl.TypedIdent.Type, this.TypedIdent.Type);
- }
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitConstant(this);
- }
- }
- public class GlobalVariable : Variable {
- public GlobalVariable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent)
- : base(tok, typedIdent) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- }
- public GlobalVariable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent, QKeyValue kv)
- : base(tok, typedIdent, kv) {
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent != null);
- }
- public override bool IsMutable {
- get {
- return true;
- }
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddVariable(this, true);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitGlobalVariable(this);
- }
- }
- public class Formal : Variable {
- public bool InComing;
- public Formal(IToken tok, TypedIdent typedIdent, bool incoming, QKeyValue kv)
- : base(tok, typedIdent, kv) {
- Contract.Requires(typedIdent != null);
- Contract.Requires(tok != null);
- InComing = incoming;
- }
- public Formal(IToken tok, TypedIdent typedIdent, bool incoming)
- : this(tok, typedIdent, incoming, null) {
- Contract.Requires(typedIdent != null);
- Contract.Requires(tok != null);
- }
- public override bool IsMutable {
- get {
- return !InComing;
- }
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddVariable(this, false);
- }
-
- /// <summary>
- /// Given a sequence of Formal declarations, returns sequence of Formals like the given one but without where clauses
- /// and without any attributes.
- /// The Type of each Formal is cloned.
- /// </summary>
- public static List<Variable> StripWhereClauses(List<Variable> w) {
- Contract.Requires(w != null);
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- List<Variable> s = new List<Variable>();
- foreach (Variable/*!*/ v in w) {
- Contract.Assert(v != null);
- Formal f = (Formal)v;
- TypedIdent ti = f.TypedIdent;
- s.Add(new Formal(f.tok, new TypedIdent(ti.tok, ti.Name, ti.Type.CloneUnresolved()), f.InComing, null));
- }
- return s;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitFormal(this);
- }
- }
- public class LocalVariable : Variable {
- public LocalVariable(IToken tok, TypedIdent typedIdent, QKeyValue kv)
- : base(tok, typedIdent, kv) {
- Contract.Requires(typedIdent != null);
- Contract.Requires(tok != null);
- }
- public LocalVariable(IToken tok, TypedIdent typedIdent)
- : base(tok, typedIdent, null) {
- Contract.Requires(typedIdent != null);
- Contract.Requires(tok != null);
- }
- public override bool IsMutable {
- get {
- return true;
- }
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddVariable(this, false);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitLocalVariable(this);
- }
- }
- public class Incarnation : LocalVariable {
- public int incarnationNumber;
- public Incarnation(Variable/*!*/ var, int i) :
- base(
- var.tok,
- new TypedIdent(var.TypedIdent.tok, var.TypedIdent.Name + "@" + i, var.TypedIdent.Type)
- ) {
- Contract.Requires(var != null);
- incarnationNumber = i;
- }
-
- }
- public class BoundVariable : Variable {
- public BoundVariable(IToken tok, TypedIdent typedIdent)
- : base(tok, typedIdent) {
- Contract.Requires(typedIdent != null);
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent.WhereExpr == null);
- }
- public BoundVariable(IToken tok, TypedIdent typedIdent, QKeyValue kv)
- : base(tok, typedIdent, kv) {
- Contract.Requires(typedIdent != null);
- Contract.Requires(tok != null);
- Contract.Requires(typedIdent.WhereExpr == null);
- }
- public override bool IsMutable {
- get {
- return false;
- }
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddVariable(this, false);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBoundVariable(this);
- }
- }
-
- public abstract class DeclWithFormals : NamedDeclaration {
- public List<TypeVariable>/*!*/ TypeParameters;
-
- private /*readonly--except in StandardVisitor*/ List<Variable>/*!*/ inParams, outParams;
-
- public List<Variable>/*!*/ InParams {
- get {
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- return this.inParams;
- }
- set {
- Contract.Requires(value != null);
- this.inParams = value;
- }
- }
-
- public List<Variable>/*!*/ OutParams
- {
- get {
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- return this.outParams;
- }
- set {
- Contract.Requires(value != null);
- this.outParams = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(TypeParameters != null);
- Contract.Invariant(this.inParams != null);
- Contract.Invariant(this.outParams != null);
- }
-
- public DeclWithFormals(IToken tok, string name, List<TypeVariable> typeParams,
- List<Variable> inParams, List<Variable> outParams)
- : base(tok, name) {
- Contract.Requires(inParams != null);
- Contract.Requires(outParams != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- this.TypeParameters = typeParams;
- this.inParams = inParams;
- this.outParams = outParams;
- }
-
- protected DeclWithFormals(DeclWithFormals that)
- : base(that.tok, cce.NonNull(that.Name)) {
- Contract.Requires(that != null);
- this.TypeParameters = that.TypeParameters;
- this.inParams = cce.NonNull(that.InParams);
- this.outParams = cce.NonNull(that.OutParams);
- }
-
- public byte[] MD5Checksum_;
- public byte[] MD5Checksum
- {
- get
- {
- if (MD5Checksum_ == null)
- {
- var c = Checksum;
- if (c != null)
- {
- MD5Checksum_ = System.Security.Cryptography.MD5.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(c));
- }
- }
- return MD5Checksum_;
- }
- }
-
- public byte[] MD5DependencyChecksum_;
- public byte[] MD5DependencyChecksum
- {
- get
- {
- Contract.Requires(DependenciesCollected);
-
- if (MD5DependencyChecksum_ == null && MD5Checksum != null)
- {
- var c = MD5Checksum;
- var transFuncDeps = new HashSet<Function>();
- if (procedureDependencies != null)
- {
- foreach (var p in procedureDependencies)
- {
- if (p.FunctionDependencies != null)
- {
- foreach (var f in p.FunctionDependencies)
- {
- transFuncDeps.Add(f);
- }
- }
- var pc = p.MD5Checksum;
- if (pc == null) { return null; }
- c = ChecksumHelper.CombineChecksums(c, pc, true);
- }
- }
- if (FunctionDependencies != null)
- {
- foreach (var f in FunctionDependencies)
- {
- transFuncDeps.Add(f);
- }
- }
- var q = new Queue<Function>(transFuncDeps);
- while (q.Any())
- {
- var f = q.Dequeue();
- var fc = f.MD5Checksum;
- if (fc == null) { return null; }
- c = ChecksumHelper.CombineChecksums(c, fc, true);
- if (f.FunctionDependencies != null)
- {
- foreach (var d in f.FunctionDependencies)
- {
- if (!transFuncDeps.Contains(d))
- {
- transFuncDeps.Add(d);
- q.Enqueue(d);
- }
- }
- }
- }
- MD5DependencyChecksum_ = c;
- }
- return MD5DependencyChecksum_;
- }
- }
-
- public string Checksum
- {
- get
- {
- return FindStringAttribute("checksum");
- }
- }
-
- string dependencyChecksum;
- public string DependencyChecksum
- {
- get
- {
- if (dependencyChecksum == null && DependenciesCollected && MD5DependencyChecksum != null)
- {
- dependencyChecksum = BitConverter.ToString(MD5DependencyChecksum);
- }
- return dependencyChecksum;
- }
- }
-
- public bool DependenciesCollected { get; set; }
-
- ISet<Procedure> procedureDependencies;
-
- public ISet<Procedure> ProcedureDependencies
- {
- get { return procedureDependencies; }
- }
-
- public void AddProcedureDependency(Procedure procedure)
- {
- Contract.Requires(procedure != null);
-
- if (procedureDependencies == null)
- {
- procedureDependencies = new HashSet<Procedure>();
- }
- procedureDependencies.Add(procedure);
- }
-
- ISet<Function> functionDependencies;
-
- public ISet<Function> FunctionDependencies
- {
- get { return functionDependencies; }
- }
-
- public void AddFunctionDependency(Function function)
- {
- Contract.Requires(function != null);
-
- if (functionDependencies == null)
- {
- functionDependencies = new HashSet<Function>();
- }
- functionDependencies.Add(function);
- }
-
- protected void EmitSignature(TokenTextWriter stream, bool shortRet) {
- Contract.Requires(stream != null);
- Type.EmitOptionalTypeParams(stream, TypeParameters);
- stream.Write("(");
- stream.push();
- InParams.Emit(stream, true);
- stream.Write(")");
- stream.sep();
-
- if (shortRet) {
- Contract.Assert(OutParams.Count == 1);
- stream.Write(" : ");
- cce.NonNull(OutParams[0]).TypedIdent.Type.Emit(stream);
- } else if (OutParams.Count > 0) {
- stream.Write(" returns (");
- OutParams.Emit(stream, true);
- stream.Write(")");
- }
- stream.pop();
- }
-
- // Register all type parameters at the resolution context
- protected void RegisterTypeParameters(ResolutionContext rc) {
- Contract.Requires(rc != null);
- foreach (TypeVariable/*!*/ v in TypeParameters) {
- Contract.Assert(v != null);
- rc.AddTypeBinder(v);
- }
- }
-
- protected void SortTypeParams() {
- List<Type>/*!*/ allTypes = new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray());
- Contract.Assert(allTypes != null);
- allTypes.AddRange(new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()));
- TypeParameters = Type.SortTypeParams(TypeParameters, allTypes, null);
- }
-
- /// <summary>
- /// Adds the given formals to the current variable context, and then resolves
- /// the types of those formals. Does NOT resolve the where clauses of the
- /// formals.
- /// Relies on the caller to first create, and later tear down, that variable
- /// context.
- /// </summary>
- /// <param name="rc"></param>
- protected void RegisterFormals(List<Variable> formals, ResolutionContext rc) {
- Contract.Requires(rc != null);
- Contract.Requires(formals != null);
- foreach (Formal/*!*/ f in formals) {
- Contract.Assert(f != null);
- if (f.Name != TypedIdent.NoName) {
- rc.AddVariable(f, false);
- }
- f.Resolve(rc);
- }
- }
-
- /// <summary>
- /// Resolves the where clauses (and attributes) of the formals.
- /// </summary>
- /// <param name="rc"></param>
- protected void ResolveFormals(List<Variable> formals, ResolutionContext rc) {
- Contract.Requires(rc != null);
- Contract.Requires(formals != null);
- foreach (Formal/*!*/ f in formals) {
- Contract.Assert(f != null);
- f.ResolveWhere(rc);
- }
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- TypecheckAttributes(tc);
- foreach (Formal/*!*/ p in InParams) {
- Contract.Assert(p != null);
- p.Typecheck(tc);
- }
- foreach (Formal/*!*/ p in OutParams) {
- Contract.Assert(p != null);
- p.Typecheck(tc);
- }
- }
- }
-
- public class DatatypeConstructor : Function {
- public List<DatatypeSelector> selectors;
- public DatatypeMembership membership;
-
- public DatatypeConstructor(Function func)
- : base(func.tok, func.Name, func.TypeParameters, func.InParams, func.OutParams[0], func.Comment, func.Attributes)
- {
- selectors = new List<DatatypeSelector>();
- }
-
- public override void Resolve(ResolutionContext rc) {
- HashSet<string> selectorNames = new HashSet<string>();
- foreach (DatatypeSelector selector in selectors) {
- if (selector.Name.StartsWith("#")) {
- rc.Error(selector.tok, "The selector must be a non-empty string");
- }
- else {
- if (selectorNames.Contains(selector.Name))
- rc.Error(this.tok, "The selectors for a constructor must be distinct strings");
- else
- selectorNames.Add(selector.Name);
- }
- }
- base.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- CtorType outputType = this.OutParams[0].TypedIdent.Type as CtorType;
- if (outputType == null || !outputType.IsDatatype()) {
- tc.Error(tok, "The output type of a constructor must be a datatype");
- }
- base.Typecheck(tc);
- }
- }
-
- public class DatatypeSelector : Function {
- public Function constructor;
- public int index;
- public DatatypeSelector(Function constructor, int index)
- : base(constructor.InParams[index].tok,
- constructor.InParams[index].Name + "#" + constructor.Name,
- new List<Variable> { new Formal(constructor.tok, new TypedIdent(constructor.tok, "", constructor.OutParams[0].TypedIdent.Type), true) },
- new Formal(constructor.tok, new TypedIdent(constructor.tok, "", constructor.InParams[index].TypedIdent.Type), false))
- {
- this.constructor = constructor;
- this.index = index;
- }
-
- public override void Emit(TokenTextWriter stream, int level) { }
- }
-
- public class DatatypeMembership : Function {
- public Function constructor;
- public DatatypeMembership(Function constructor)
- : base(constructor.tok,
- "is#" + constructor.Name,
- new List<Variable> { new Formal(constructor.tok, new TypedIdent(constructor.tok, "", constructor.OutParams[0].TypedIdent.Type), true) },
- new Formal(constructor.tok, new TypedIdent(constructor.tok, "", Type.Bool), false))
- {
- this.constructor = constructor;
- }
-
- public override void Emit(TokenTextWriter stream, int level) { }
- }
-
- public class Function : DeclWithFormals {
- public string Comment;
-
- // the body is only set if the function is declared with {:inline}
- public Expr Body;
- public Axiom DefinitionAxiom;
-
- public IList<Axiom> otherDefinitionAxioms;
- public IEnumerable<Axiom> OtherDefinitionAxioms
- {
- get
- {
- return otherDefinitionAxioms;
- }
- }
-
- public void AddOtherDefinitionAxiom(Axiom axiom)
- {
- Contract.Requires(axiom != null);
-
- if (otherDefinitionAxioms == null)
- {
- otherDefinitionAxioms = new List<Axiom>();
- }
- otherDefinitionAxioms.Add(axiom);
- }
-
- public bool doingExpansion;
-
- private bool neverTrigger;
- private bool neverTriggerComputed;
-
- public Function(IToken tok, string name, List<Variable> args, Variable result)
- : this(tok, name, new List<TypeVariable>(), args, result, null) {
- Contract.Requires(result != null);
- Contract.Requires(args != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, new List<TypeVariable>(), args, result, null);
- }
- public Function(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> args, Variable result)
- : this(tok, name, typeParams, args, result, null) {
- Contract.Requires(result != null);
- Contract.Requires(args != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, typeParams, args, result, null);
- }
- public Function(IToken tok, string name, List<Variable> args, Variable result, string comment)
- : this(tok, name, new List<TypeVariable>(), args, result, comment) {
- Contract.Requires(result != null);
- Contract.Requires(args != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, new List<TypeVariable>(), args, result, comment);
- }
- public Function(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> args, Variable/*!*/ result, string comment)
- : base(tok, name, typeParams, args, new List<Variable> { result }) {
- Contract.Requires(result != null);
- Contract.Requires(args != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- Comment = comment;
- }
- public Function(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> args, Variable result,
- string comment, QKeyValue kv)
- : this(tok, name, typeParams, args, result, comment) {
- Contract.Requires(args != null);
- Contract.Requires(result != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, typeParams, args, result, comment);
- this.Attributes = kv;
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "function ");
- EmitAttributes(stream);
- if (Body != null && !QKeyValue.FindBoolAttribute(Attributes, "inline")) {
- // Boogie inlines any function whose .Body field is non-null. The parser populates the .Body field
- // is the :inline attribute is present, but if someone creates the Boogie file directly as an AST, then
- // the :inline attribute may not be there. We'll make sure it's printed, so one can see that this means
- // that the body will be inlined.
- stream.Write("{:inline} ");
- }
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- stream.Write("h{0}^^{1}", this.GetHashCode(), TokenTextWriter.SanitizeIdentifier(this.Name));
- } else {
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- EmitSignature(stream, true);
- if (Body != null) {
- stream.WriteLine();
- stream.WriteLine("{");
- stream.Write(level + 1, "");
- Body.Emit(stream);
- stream.WriteLine();
- stream.WriteLine("}");
- } else {
- stream.WriteLine(";");
- }
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddProcedure(this);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- RegisterTypeParameters(rc);
- rc.PushVarContext();
- RegisterFormals(InParams, rc);
- RegisterFormals(OutParams, rc);
- ResolveAttributes(rc);
- if (Body != null)
- {
- rc.StateMode = ResolutionContext.State.StateLess;
- Body.Resolve(rc);
- rc.StateMode = ResolutionContext.State.Single;
- }
- rc.PopVarContext();
- Type.CheckBoundVariableOccurrences(TypeParameters,
- new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- this.tok, "function arguments",
- rc);
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- SortTypeParams();
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- // PR: why was the base call left out previously?
- base.Typecheck(tc);
- // TypecheckAttributes(tc);
- if (Body != null) {
- Body.Typecheck(tc);
- if (!cce.NonNull(Body.Type).Unify(cce.NonNull(OutParams[0]).TypedIdent.Type))
- tc.Error(Body,
- "function body with invalid type: {0} (expected: {1})",
- Body.Type, cce.NonNull(OutParams[0]).TypedIdent.Type);
- }
- }
-
- public bool NeverTrigger {
- get {
- if (!neverTriggerComputed) {
- this.CheckBooleanAttribute("never_pattern", ref neverTrigger);
- neverTriggerComputed = true;
- }
- return neverTrigger;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitFunction(this);
- }
-
- public Axiom CreateDefinitionAxiom(Expr definition, QKeyValue kv = null) {
- Contract.Requires(definition != null);
-
- List<Variable> dummies = new List<Variable>();
- List<Expr> callArgs = new List<Expr>();
- int i = 0;
- foreach (Formal/*!*/ f in InParams) {
- Contract.Assert(f != null);
- string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
- dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
- callArgs.Add(new IdentifierExpr(f.tok, nm));
- i++;
- }
- List<TypeVariable>/*!*/ quantifiedTypeVars = new List<TypeVariable>();
- foreach (TypeVariable/*!*/ t in TypeParameters) {
- Contract.Assert(t != null);
- quantifiedTypeVars.Add(new TypeVariable(tok, t.Name));
- }
-
- Expr call = new NAryExpr(tok, new FunctionCall(new IdentifierExpr(tok, Name)), callArgs);
- // specify the type of the function, because it might be that
- // type parameters only occur in the output type
- call = Expr.CoerceType(tok, call, (Type)OutParams[0].TypedIdent.Type.Clone());
- Expr def = Expr.Binary(tok, BinaryOperator.Opcode.Eq, call, definition);
- if (quantifiedTypeVars.Count != 0 || dummies.Count != 0) {
- def = new ForallExpr(tok, quantifiedTypeVars, dummies,
- kv,
- new Trigger(tok, true, new List<Expr> { call }, null),
- def);
- }
- DefinitionAxiom = new Axiom(tok, def);
- return DefinitionAxiom;
- }
- }
-
- public class Macro : Function {
- public Macro(IToken tok, string name, List<Variable> args, Variable result)
- : base(tok, name, args, result) { }
- }
-
- public class Requires : Absy, IPotentialErrorNode<string, string> {
- public readonly bool Free;
-
- private Expr/*!*/ _condition;
-
- public Expr/*!*/ Condition {
- get {
- Contract.Ensures(Contract.Result<Expr>() != null);
- return this._condition;
- }
- set {
- Contract.Requires(value != null);
- this._condition = value;
- }
- }
-
- public string Comment;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._condition != null);
- }
-
-
- // TODO: convert to use generics
- private string errorData;
- public string ErrorData {
- get {
- return errorData;
- }
- set {
- errorData = value;
- }
- }
-
-
- private MiningStrategy errorDataEnhanced;
- public MiningStrategy ErrorDataEnhanced {
- get {
- return errorDataEnhanced;
- }
- set {
- errorDataEnhanced = value;
- }
- }
-
- public QKeyValue Attributes;
-
- public String ErrorMessage {
- get {
- return QKeyValue.FindStringAttribute(Attributes, "msg");
- }
- }
-
- public Requires(IToken token, bool free, Expr condition, string comment, QKeyValue kv)
- : base(token) {
- Contract.Requires(condition != null);
- Contract.Requires(token != null);
- this.Free = free;
- this._condition = condition;
- this.Comment = comment;
- this.Attributes = kv;
- }
-
- public Requires(IToken token, bool free, Expr condition, string comment)
- : this(token, free, condition, comment, null) {
- Contract.Requires(condition != null);
- Contract.Requires(token != null);
- //:this(token, free, condition, comment, null);
- }
-
- public Requires(bool free, Expr condition)
- : this(Token.NoToken, free, condition, null) {
- Contract.Requires(condition != null);
- //:this(Token.NoToken, free, condition, null);
- }
-
- public Requires(bool free, Expr condition, string comment)
- : this(Token.NoToken, free, condition, comment) {
- Contract.Requires(condition != null);
- //:this(Token.NoToken, free, condition, comment);
- }
-
- public void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "{0}requires ", Free ? "free " : "");
- Cmd.EmitAttributes(stream, Attributes);
- this.Condition.Emit(stream);
- stream.WriteLine(";");
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- this.Condition.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- this.Condition.Typecheck(tc);
- Contract.Assert(this.Condition.Type != null); // follows from postcondition of Expr.Typecheck
- if (!this.Condition.Type.Unify(Type.Bool)) {
- tc.Error(this, "preconditions must be of type bool");
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- return visitor.VisitRequires(this);
- }
- }
-
- public class Ensures : Absy, IPotentialErrorNode<string, string> {
- public readonly bool Free;
-
- private Expr/*!*/ _condition;
-
- public Expr/*!*/ Condition {
- get {
- Contract.Ensures(Contract.Result<Expr>() != null);
- return this._condition;
- }
- set {
- Contract.Requires(value != null);
- this._condition = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._condition != null);
- }
-
- public string Comment;
-
- // TODO: convert to use generics
- private string errorData;
- public string ErrorData {
- get {
- return errorData;
- }
- set {
- errorData = value;
- }
- }
-
- private MiningStrategy errorDataEnhanced;
- public MiningStrategy ErrorDataEnhanced {
- get {
- return errorDataEnhanced;
- }
- set {
- errorDataEnhanced = value;
- }
- }
-
- public String ErrorMessage {
- get {
- return QKeyValue.FindStringAttribute(Attributes, "msg");
- }
- }
-
- public QKeyValue Attributes;
-
- public Ensures(IToken token, bool free, Expr/*!*/ condition, string comment, QKeyValue kv)
- : base(token) {
- Contract.Requires(condition != null);
- Contract.Requires(token != null);
- this.Free = free;
- this._condition = condition;
- this.Comment = comment;
- this.Attributes = kv;
- }
-
- public Ensures(IToken token, bool free, Expr condition, string comment)
- : this(token, free, condition, comment, null) {
- Contract.Requires(condition != null);
- Contract.Requires(token != null);
- //:this(token, free, condition, comment, null);
- }
-
- public Ensures(bool free, Expr condition)
- : this(Token.NoToken, free, condition, null) {
- Contract.Requires(condition != null);
- //:this(Token.NoToken, free, condition, null);
- }
-
- public Ensures(bool free, Expr condition, string comment)
- : this(Token.NoToken, free, condition, comment) {
- Contract.Requires(condition != null);
- //:this(Token.NoToken, free, condition, comment);
- }
-
- public void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "{0}ensures ", Free ? "free " : "");
- Cmd.EmitAttributes(stream, Attributes);
- this.Condition.Emit(stream);
- stream.WriteLine(";");
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- this.Condition.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- this.Condition.Typecheck(tc);
- Contract.Assert(this.Condition.Type != null); // follows from postcondition of Expr.Typecheck
- if (!this.Condition.Type.Unify(Type.Bool)) {
- tc.Error(this, "postconditions must be of type bool");
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- return visitor.VisitEnsures(this);
- }
- }
-
- public class Procedure : DeclWithFormals {
- public List<Requires>/*!*/ Requires;
- public List<IdentifierExpr>/*!*/ Modifies;
- public List<Ensures>/*!*/ Ensures;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Requires != null);
- Contract.Invariant(Modifies != null);
- Contract.Invariant(Ensures != null);
- Contract.Invariant(Summary != null);
- }
-
-
- // Abstract interpretation: Procedure-specific invariants...
- [Rep]
- public readonly ProcedureSummary/*!*/ Summary;
-
- public Procedure(IToken/*!*/ tok, string/*!*/ name, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ inParams, List<Variable>/*!*/ outParams,
- List<Requires>/*!*/ requires, List<IdentifierExpr>/*!*/ modifies, List<Ensures>/*!*/ ensures)
- : this(tok, name, typeParams, inParams, outParams, requires, modifies, ensures, null) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(outParams != null);
- Contract.Requires(requires != null);
- Contract.Requires(modifies != null);
- Contract.Requires(ensures != null);
- //:this(tok, name, typeParams, inParams, outParams, requires, modifies, ensures, null);
- }
-
- public Procedure(IToken/*!*/ tok, string/*!*/ name, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ inParams, List<Variable>/*!*/ outParams,
- List<Requires>/*!*/ @requires, List<IdentifierExpr>/*!*/ @modifies, List<Ensures>/*!*/ @ensures, QKeyValue kv
- )
- : base(tok, name, typeParams, inParams, outParams) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(outParams != null);
- Contract.Requires(@requires != null);
- Contract.Requires(@modifies != null);
- Contract.Requires(@ensures != null);
- this.Requires = @requires;
- this.Modifies = @modifies;
- this.Ensures = @ensures;
- this.Summary = new ProcedureSummary();
- this.Attributes = kv;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "procedure ");
- EmitAttributes(stream);
- stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- EmitSignature(stream, false);
- stream.WriteLine(";");
-
- level++;
-
- foreach (Requires/*!*/ e in this.Requires) {
- Contract.Assert(e != null);
- e.Emit(stream, level);
- }
-
- if (this.Modifies.Count > 0) {
- stream.Write(level, "modifies ");
- this.Modifies.Emit(stream, false);
- stream.WriteLine(";");
- }
-
- foreach (Ensures/*!*/ e in this.Ensures) {
- Contract.Assert(e != null);
- e.Emit(stream, level);
- }
-
- if (!CommandLineOptions.Clo.IntraproceduralInfer) {
- for (int s = 0; s < this.Summary.Count; s++) {
- ProcedureSummaryEntry/*!*/ entry = cce.NonNull(this.Summary[s]);
- stream.Write(level + 1, "// ");
- stream.WriteLine();
- }
- }
-
- stream.WriteLine();
- stream.WriteLine();
- }
-
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.AddProcedure(this);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.PushVarContext();
-
- foreach (IdentifierExpr/*!*/ ide in Modifies) {
- Contract.Assert(ide != null);
- ide.Resolve(rc);
- }
-
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- RegisterTypeParameters(rc);
-
- RegisterFormals(InParams, rc);
- ResolveFormals(InParams, rc); // "where" clauses of in-parameters are resolved without the out-parameters in scope
- foreach (Requires/*!*/ e in Requires) {
- Contract.Assert(e != null);
- e.Resolve(rc);
- }
- RegisterFormals(OutParams, rc);
- ResolveFormals(OutParams, rc); // "where" clauses of out-parameters are resolved with both in- and out-parametes in scope
-
- rc.StateMode = ResolutionContext.State.Two;
- foreach (Ensures/*!*/ e in Ensures) {
- Contract.Assert(e != null);
- e.Resolve(rc);
- }
- rc.StateMode = ResolutionContext.State.Single;
- ResolveAttributes(rc);
-
- Type.CheckBoundVariableOccurrences(TypeParameters,
- new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- this.tok, "procedure arguments",
- rc);
-
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
-
- rc.PopVarContext();
-
- SortTypeParams();
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- base.Typecheck(tc);
- foreach (IdentifierExpr/*!*/ ide in Modifies) {
- Contract.Assert(ide != null);
- Contract.Assume(ide.Decl != null);
- if (!ide.Decl.IsMutable) {
- tc.Error(this, "modifies list contains constant: {0}", ide.Name);
- }
- ide.Typecheck(tc);
- }
- foreach (Requires/*!*/ e in Requires) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
- bool oldYields = tc.Yields;
- tc.Yields = QKeyValue.FindBoolAttribute(Attributes, "yields");
- foreach (Ensures/*!*/ e in Ensures) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
- tc.Yields = oldYields;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitProcedure(this);
- }
- }
-
- public class LoopProcedure : Procedure
- {
- public Implementation enclosingImpl;
- private Dictionary<Block, Block> blockMap;
- private Dictionary<string, Block> blockLabelMap;
-
- public LoopProcedure(Implementation impl, Block header,
- List<Variable> inputs, List<Variable> outputs, List<IdentifierExpr> globalMods)
- : base(Token.NoToken, impl.Name + "_loop_" + header.ToString(),
- new List<TypeVariable>(), inputs, outputs,
- new List<Requires>(), globalMods, new List<Ensures>())
- {
- enclosingImpl = impl;
- }
-
- public void setBlockMap(Dictionary<Block, Block> bm)
- {
- blockMap = bm;
- blockLabelMap = new Dictionary<string, Block>();
- foreach (var kvp in bm)
- {
- blockLabelMap.Add(kvp.Key.Label, kvp.Value);
- }
- }
-
- public Block getBlock(string label)
- {
- if (blockLabelMap.ContainsKey(label)) return blockLabelMap[label];
- return null;
- }
- }
-
- public class Implementation : DeclWithFormals {
- public List<Variable>/*!*/ LocVars;
- [Rep]
- public StmtList StructuredStmts;
- [Rep]
- public List<Block/*!*/>/*!*/ Blocks;
- public Procedure Proc;
-
- // Blocks before applying passification etc.
- // Both are used only when /inline is set.
- public List<Block/*!*/> OriginalBlocks;
- public List<Variable> OriginalLocVars;
-
- public readonly ISet<byte[]> AssertionChecksums = new HashSet<byte[]>(ChecksumComparer.Default);
-
- public sealed class ChecksumComparer : IEqualityComparer<byte[]>
- {
- static IEqualityComparer<byte[]> defaultComparer;
- public static IEqualityComparer<byte[]> Default
- {
- get
- {
- if (defaultComparer == null)
- {
- defaultComparer = new ChecksumComparer();
- }
- return defaultComparer;
- }
- }
-
- public bool Equals(byte[] x, byte[] y)
- {
- if (x == null || y == null)
- {
- return x == y;
- }
- else
- {
- return x.SequenceEqual(y);
- }
- }
-
- public int GetHashCode(byte[] checksum)
- {
- if (checksum == null)
- {
- throw new ArgumentNullException("checksum");
- }
- else
- {
- var result = 17;
- for (int i = 0; i < checksum.Length; i++)
- {
- result = result * 23 + checksum[i];
- }
- return result;
- }
- }
- }
-
- public void AddAssertionChecksum(byte[] checksum)
- {
- Contract.Requires(checksum != null);
-
- if (AssertionChecksums != null)
- {
- AssertionChecksums.Add(checksum);
- }
- }
-
- public ISet<byte[]> AssertionChecksumsInCachedSnapshot { get; set; }
-
- public bool IsAssertionChecksumInCachedSnapshot(byte[] checksum)
- {
- Contract.Requires(AssertionChecksumsInCachedSnapshot != null);
-
- return AssertionChecksumsInCachedSnapshot.Contains(checksum);
- }
-
- public IList<AssertCmd> RecycledFailingAssertions { get; protected set; }
-
- public void AddRecycledFailingAssertion(AssertCmd assertion)
- {
- if (RecycledFailingAssertions == null)
- {
- RecycledFailingAssertions = new List<AssertCmd>();
- }
- RecycledFailingAssertions.Add(assertion);
- }
-
- // Strongly connected components
- private StronglyConnectedComponents<Block/*!*/> scc;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(LocVars != null);
- Contract.Invariant(cce.NonNullElements(Blocks));
- Contract.Invariant(cce.NonNullElements(OriginalBlocks, true));
- Contract.Invariant(cce.NonNullElements(scc, true));
-
- }
- private bool BlockPredecessorsComputed;
- public bool StronglyConnectedComponentsComputed {
- get {
- return this.scc != null;
- }
- }
-
- public bool SkipVerification {
- get {
- bool verify = true;
- cce.NonNull(this.Proc).CheckBooleanAttribute("verify", ref verify);
- this.CheckBooleanAttribute("verify", ref verify);
- if (!verify) {
- return true;
- }
-
- if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assert ||
- CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assume) {
- Expr inl = this.FindExprAttribute("inline");
- if (inl == null)
- inl = this.Proc.FindExprAttribute("inline");
- if (inl != null && inl is LiteralExpr && ((LiteralExpr)inl).isBigNum && ((LiteralExpr)inl).asBigNum.Signum > 0) {
- return true;
- }
- }
-
- if (CommandLineOptions.Clo.StratifiedInlining > 0) {
- return !QKeyValue.FindBoolAttribute(Attributes, "entrypoint");
- }
-
- return false;
- }
- }
-
- public string Id
- {
- get
- {
- var id = FindStringAttribute("id");
- if (id == null)
- {
- id = Name + GetHashCode().ToString() + ":0";
- }
- return id;
- }
- }
-
- public int Priority
- {
- get
- {
- int priority = 0;
- CheckIntAttribute("priority", ref priority);
- if (priority <= 0)
- {
- priority = 1;
- }
- return priority;
- }
- }
-
- public IDictionary<byte[], object> ErrorChecksumToCachedError { get; private set; }
-
- public bool IsErrorChecksumInCachedSnapshot(byte[] checksum)
- {
- Contract.Requires(ErrorChecksumToCachedError != null);
-
- return ErrorChecksumToCachedError.ContainsKey(checksum);
- }
-
- public void SetErrorChecksumToCachedError(IEnumerable<Tuple<byte[], byte[], object>> errors)
- {
- Contract.Requires(errors != null);
-
- ErrorChecksumToCachedError = new Dictionary<byte[], object>(ChecksumComparer.Default);
- foreach (var kv in errors)
- {
- ErrorChecksumToCachedError[kv.Item1] = kv.Item3;
- if (kv.Item2 != null)
- {
- ErrorChecksumToCachedError[kv.Item2] = null;
- }
- }
- }
-
- public bool HasCachedSnapshot
- {
- get
- {
- return ErrorChecksumToCachedError != null && AssertionChecksumsInCachedSnapshot != null;
- }
- }
-
- public bool AnyErrorsInCachedSnapshot
- {
- get
- {
- Contract.Requires(ErrorChecksumToCachedError != null);
-
- return ErrorChecksumToCachedError.Any();
- }
- }
-
- IList<LocalVariable> injectedAssumptionVariables;
- public IList<LocalVariable> InjectedAssumptionVariables
- {
- get
- {
- return injectedAssumptionVariables != null ? injectedAssumptionVariables : new List<LocalVariable>();
- }
- }
-
- IList<LocalVariable> doomedInjectedAssumptionVariables;
- public IList<LocalVariable> DoomedInjectedAssumptionVariables
- {
- get
- {
- return doomedInjectedAssumptionVariables != null ? doomedInjectedAssumptionVariables : new List<LocalVariable>();
- }
- }
-
- public List<LocalVariable> RelevantInjectedAssumptionVariables(Dictionary<Variable, Expr> incarnationMap)
- {
- return InjectedAssumptionVariables.Where(v => { Expr e; if (incarnationMap.TryGetValue(v, out e)) { var le = e as LiteralExpr; return le == null || !le.IsTrue; } else { return false; } }).ToList();
- }
-
- public List<LocalVariable> RelevantDoomedInjectedAssumptionVariables(Dictionary<Variable, Expr> incarnationMap)
- {
- return DoomedInjectedAssumptionVariables.Where(v => { Expr e; if (incarnationMap.TryGetValue(v, out e)) { var le = e as LiteralExpr; return le == null || !le.IsTrue; } else { return false; } }).ToList();
- }
-
- public Expr ConjunctionOfInjectedAssumptionVariables(Dictionary<Variable, Expr> incarnationMap, out bool isTrue)
- {
- Contract.Requires(incarnationMap != null);
-
- var vars = RelevantInjectedAssumptionVariables(incarnationMap).Select(v => incarnationMap[v]).ToList();
- isTrue = vars.Count == 0;
- return LiteralExpr.BinaryTreeAnd(vars);
- }
-
- public void InjectAssumptionVariable(LocalVariable variable, bool isDoomed = false)
- {
- LocVars.Add(variable);
- if (isDoomed)
- {
- if (doomedInjectedAssumptionVariables == null)
- {
- doomedInjectedAssumptionVariables = new List<LocalVariable>();
- }
- doomedInjectedAssumptionVariables.Add(variable);
- }
- else
- {
- if (injectedAssumptionVariables == null)
- {
- injectedAssumptionVariables = new List<LocalVariable>();
- }
- injectedAssumptionVariables.Add(variable);
- }
- }
-
- public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] StmtList structuredStmts, QKeyValue kv)
- : this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, kv, new Errors()) {
- Contract.Requires(structuredStmts != null);
- Contract.Requires(localVariables != null);
- Contract.Requires(outParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors());
- }
-
- public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] StmtList structuredStmts)
- : this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors()) {
- Contract.Requires(structuredStmts != null);
- Contract.Requires(localVariables != null);
- Contract.Requires(outParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors());
- }
-
- public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] StmtList structuredStmts, Errors errorHandler)
- : this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, errorHandler) {
- Contract.Requires(errorHandler != null);
- Contract.Requires(structuredStmts != null);
- Contract.Requires(localVariables != null);
- Contract.Requires(outParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, errorHandler);
- }
-
- public Implementation(IToken/*!*/ tok,
- string/*!*/ name,
- List<TypeVariable>/*!*/ typeParams,
- List<Variable>/*!*/ inParams,
- List<Variable>/*!*/ outParams,
- List<Variable>/*!*/ localVariables,
- [Captured] StmtList/*!*/ structuredStmts,
- QKeyValue kv,
- Errors/*!*/ errorHandler)
- : base(tok, name, typeParams, inParams, outParams) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(outParams != null);
- Contract.Requires(localVariables != null);
- Contract.Requires(structuredStmts != null);
- Contract.Requires(errorHandler != null);
- LocVars = localVariables;
- StructuredStmts = structuredStmts;
- BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts, errorHandler);
- Blocks = ctx.Blocks;
- BlockPredecessorsComputed = false;
- scc = null;
- Attributes = kv;
- }
-
- public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] List<Block/*!*/> block)
- : this(tok, name, typeParams, inParams, outParams, localVariables, block, null) {
- Contract.Requires(cce.NonNullElements(block));
- Contract.Requires(localVariables != null);
- Contract.Requires(outParams != null);
- Contract.Requires(inParams != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(name != null);
- Contract.Requires(tok != null);
- //:this(tok, name, typeParams, inParams, outParams, localVariables, block, null);
- }
-
- public Implementation(IToken/*!*/ tok,
- string/*!*/ name,
- List<TypeVariable>/*!*/ typeParams,
- List<Variable>/*!*/ inParams,
- List<Variable>/*!*/ outParams,
- List<Variable>/*!*/ localVariables,
- [Captured] List<Block/*!*/>/*!*/ blocks,
- QKeyValue kv)
- : base(tok, name, typeParams, inParams, outParams) {
- Contract.Requires(name != null);
- Contract.Requires(inParams != null);
- Contract.Requires(outParams != null);
- Contract.Requires(localVariables != null);
- Contract.Requires(cce.NonNullElements(blocks));
- LocVars = localVariables;
- Blocks = blocks;
- BlockPredecessorsComputed = false;
- scc = null;
- Attributes = kv;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "implementation ");
- EmitAttributes(stream);
- stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- EmitSignature(stream, false);
- stream.WriteLine();
-
- stream.WriteLine(level, "{0}", '{');
-
- foreach (Variable/*!*/ v in this.LocVars) {
- Contract.Assert(v != null);
- v.Emit(stream, level + 1);
- }
-
- if (this.StructuredStmts != null && !CommandLineOptions.Clo.PrintInstrumented && !CommandLineOptions.Clo.PrintInlined) {
- if (this.LocVars.Count > 0) {
- stream.WriteLine();
- }
- if (CommandLineOptions.Clo.PrintUnstructured < 2) {
- if (CommandLineOptions.Clo.PrintUnstructured == 1) {
- stream.WriteLine(this, level + 1, "/*** structured program:");
- }
- this.StructuredStmts.Emit(stream, level + 1);
- if (CommandLineOptions.Clo.PrintUnstructured == 1) {
- stream.WriteLine(level + 1, "**** end structured program */");
- }
- }
- }
-
- if (this.StructuredStmts == null || 1 <= CommandLineOptions.Clo.PrintUnstructured ||
- CommandLineOptions.Clo.PrintInstrumented || CommandLineOptions.Clo.PrintInlined) {
- foreach (Block b in this.Blocks) {
- b.Emit(stream, level + 1);
- }
- }
-
- stream.WriteLine(level, "{0}", '}');
-
- stream.WriteLine();
- stream.WriteLine();
- }
- public override void Register(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- // nothing to register
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- if (Proc != null) {
- // already resolved
- return;
- }
-
- DeclWithFormals dwf = rc.LookUpProcedure(cce.NonNull(this.Name));
- Proc = dwf as Procedure;
- if (dwf == null) {
- rc.Error(this, "implementation given for undeclared procedure: {0}", this.Name);
- } else if (Proc == null) {
- rc.Error(this, "implementations given for function, not procedure: {0}", this.Name);
- }
-
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- RegisterTypeParameters(rc);
-
- rc.PushVarContext();
- RegisterFormals(InParams, rc);
- RegisterFormals(OutParams, rc);
-
- foreach (Variable/*!*/ v in LocVars) {
- Contract.Assert(v != null);
- v.Register(rc);
- v.Resolve(rc);
- }
- foreach (Variable/*!*/ v in LocVars) {
- Contract.Assert(v != null);
- v.ResolveWhere(rc);
- }
-
- rc.PushProcedureContext();
- foreach (Block b in Blocks) {
- b.Register(rc);
- }
-
- ResolveAttributes(rc);
-
- rc.StateMode = ResolutionContext.State.Two;
- foreach (Block b in Blocks) {
- b.Resolve(rc);
- }
- rc.StateMode = ResolutionContext.State.Single;
-
- rc.PopProcedureContext();
- rc.PopVarContext();
-
- Type.CheckBoundVariableOccurrences(TypeParameters,
- new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- this.tok, "implementation arguments",
- rc);
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- SortTypeParams();
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- base.Typecheck(tc);
-
- Contract.Assume(this.Proc != null);
-
- if (this.TypeParameters.Count != Proc.TypeParameters.Count) {
- tc.Error(this, "mismatched number of type parameters in procedure implementation: {0}",
- this.Name);
- } else {
- // if the numbers of type parameters are different, it is
- // difficult to compare the argument types
- MatchFormals(this.InParams, Proc.InParams, "in", tc);
- MatchFormals(this.OutParams, Proc.OutParams, "out", tc);
- }
-
- foreach (Variable/*!*/ v in LocVars) {
- Contract.Assert(v != null);
- v.Typecheck(tc);
- }
- List<IdentifierExpr> oldFrame = tc.Frame;
- bool oldYields = tc.Yields;
- tc.Frame = Proc.Modifies;
- tc.Yields = QKeyValue.FindBoolAttribute(Proc.Attributes, "yields");
- foreach (Block b in Blocks) {
- b.Typecheck(tc);
- }
- Contract.Assert(tc.Frame == Proc.Modifies);
- tc.Frame = oldFrame;
- tc.Yields = oldYields;
- }
- void MatchFormals(List<Variable>/*!*/ implFormals, List<Variable>/*!*/ procFormals, string/*!*/ inout, TypecheckingContext/*!*/ tc) {
- Contract.Requires(implFormals != null);
- Contract.Requires(procFormals != null);
- Contract.Requires(inout != null);
- Contract.Requires(tc != null);
- if (implFormals.Count != procFormals.Count) {
- tc.Error(this, "mismatched number of {0}-parameters in procedure implementation: {1}",
- inout, this.Name);
- } else {
- // unify the type parameters so that types can be compared
- Contract.Assert(Proc != null);
- Contract.Assert(this.TypeParameters.Count == Proc.TypeParameters.Count);
-
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst1 =
- new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst2 =
- new Dictionary<TypeVariable/*!*/, Type/*!*/>();
-
- for (int i = 0; i < this.TypeParameters.Count; ++i) {
- TypeVariable/*!*/ newVar =
- new TypeVariable(Token.NoToken, Proc.TypeParameters[i].Name);
- Contract.Assert(newVar != null);
- subst1.Add(Proc.TypeParameters[i], newVar);
- subst2.Add(this.TypeParameters[i], newVar);
- }
-
- for (int i = 0; i < implFormals.Count; i++) {
- // the names of the formals are allowed to change from the proc to the impl
-
- // but types must be identical
- Type t = cce.NonNull((Variable)implFormals[i]).TypedIdent.Type.Substitute(subst2);
- Type u = cce.NonNull((Variable)procFormals[i]).TypedIdent.Type.Substitute(subst1);
- if (!t.Equals(u)) {
- string/*!*/ a = cce.NonNull((Variable)implFormals[i]).Name;
- Contract.Assert(a != null);
- string/*!*/ b = cce.NonNull((Variable)procFormals[i]).Name;
- Contract.Assert(b != null);
- string/*!*/ c;
- if (a == b) {
- c = a;
- } else {
- c = String.Format("{0} (named {1} in implementation)", b, a);
- }
- tc.Error(this, "mismatched type of {0}-parameter in implementation {1}: {2}", inout, this.Name, c);
- }
- }
- }
- }
-
- private Dictionary<Variable, Expr>/*?*/ formalMap = null;
- public void ResetImplFormalMap() {
- this.formalMap = null;
- }
- public Dictionary<Variable, Expr>/*!*/ GetImplFormalMap() {
- Contract.Ensures(Contract.Result<Dictionary<Variable, Expr>>() != null);
-
- if (this.formalMap != null)
- return this.formalMap;
- else {
- Dictionary<Variable, Expr>/*!*/ map = new Dictionary<Variable, Expr> (InParams.Count + OutParams.Count);
-
- Contract.Assume(this.Proc != null);
- Contract.Assume(InParams.Count == Proc.InParams.Count);
- for (int i = 0; i < InParams.Count; i++) {
- Variable/*!*/ v = InParams[i];
- Contract.Assert(v != null);
- IdentifierExpr ie = new IdentifierExpr(v.tok, v);
- Variable/*!*/ pv = Proc.InParams[i];
- Contract.Assert(pv != null);
- map.Add(pv, ie);
- }
- System.Diagnostics.Debug.Assert(OutParams.Count == Proc.OutParams.Count);
- for (int i = 0; i < OutParams.Count; i++) {
- Variable/*!*/ v = cce.NonNull(OutParams[i]);
- IdentifierExpr ie = new IdentifierExpr(v.tok, v);
- Variable pv = cce.NonNull(Proc.OutParams[i]);
- map.Add(pv, ie);
- }
- this.formalMap = map;
-
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- Console.WriteLine("Implementation.GetImplFormalMap on {0}:", this.Name);
- using (TokenTextWriter stream = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/false, /*pretty=*/ false)) {
- foreach (var e in map) {
- Console.Write(" ");
- cce.NonNull((Variable/*!*/)e.Key).Emit(stream, 0);
- Console.Write(" --> ");
- cce.NonNull((Expr)e.Value).Emit(stream);
- Console.WriteLine();
- }
- }
- }
-
- return map;
- }
- }
-
- /// <summary>
- /// Return a collection of blocks that are reachable from the block passed as a parameter.
- /// The block must be defined in the current implementation
- /// </summary>
- public ICollection<Block/*!*/> GetConnectedComponents(Block startingBlock) {
- Contract.Requires(startingBlock != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<Block>>(), true));
- Contract.Assert(this.Blocks.Contains(startingBlock));
-
- if (!this.BlockPredecessorsComputed)
- ComputeStronglyConnectedComponents();
-
-#if DEBUG_PRINT
- System.Console.WriteLine("* Strongly connected components * \n{0} \n ** ", scc);
-#endif
-
- foreach (ICollection<Block/*!*/> component in cce.NonNull(this.scc)) {
- foreach (Block/*!*/ b in component) {
- Contract.Assert(b != null);
- if (b == startingBlock) // We found the compontent that owns the startingblock
- {
- return component;
- }
- }
- }
-
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // if we are here, it means that the block is not in one of the components. This is an error.
- }
-
- /// <summary>
- /// Compute the strongly connected compontents of the blocks in the implementation.
- /// As a side effect, it also computes the "predecessor" relation for the block in the implementation
- /// </summary>
- override public void ComputeStronglyConnectedComponents() {
- if (!this.BlockPredecessorsComputed)
- ComputePredecessorsForBlocks();
-
- Adjacency<Block/*!*/> next = new Adjacency<Block/*!*/>(Successors);
- Adjacency<Block/*!*/> prev = new Adjacency<Block/*!*/>(Predecessors);
-
- this.scc = new StronglyConnectedComponents<Block/*!*/>(this.Blocks, next, prev);
- scc.Compute();
-
-
- foreach (Block/*!*/ block in this.Blocks) {
- Contract.Assert(block != null);
- block.Predecessors = new List<Block>();
- }
-
- }
-
- /// <summary>
- /// Reset the abstract stated computed before
- /// </summary>
- override public void ResetAbstractInterpretationState() {
- foreach (Block/*!*/ b in this.Blocks) {
- Contract.Assert(b != null);
- b.ResetAbstractInterpretationState();
- }
- }
-
- /// <summary>
- /// A private method used as delegate for the strongly connected components.
- /// It return, given a node, the set of its successors
- /// </summary>
- private IEnumerable/*<Block!>*//*!*/ Successors(Block node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<IEnumerable>() != null);
-
- GotoCmd gotoCmd = node.TransferCmd as GotoCmd;
-
- if (gotoCmd != null) { // If it is a gotoCmd
- Contract.Assert(gotoCmd.labelTargets != null);
-
- return gotoCmd.labelTargets;
- } else { // otherwise must be a ReturnCmd
- Contract.Assert(node.TransferCmd is ReturnCmd);
-
- return new List<Block/*!*/>();
- }
- }
-
- /// <summary>
- /// A private method used as delegate for the strongly connected components.
- /// It return, given a node, the set of its predecessors
- /// </summary>
- private IEnumerable/*<Block!>*//*!*/ Predecessors(Block node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<IEnumerable>() != null);
-
- Contract.Assert(this.BlockPredecessorsComputed);
-
- return node.Predecessors;
- }
-
- /// <summary>
- /// Compute the predecessor informations for the blocks
- /// </summary>
- public void ComputePredecessorsForBlocks() {
- foreach (Block b in this.Blocks) {
- b.Predecessors = new List<Block>();
- }
- foreach (Block b in this.Blocks) {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- Contract.Assert(gtc.labelTargets != null);
- foreach (Block/*!*/ dest in gtc.labelTargets) {
- Contract.Assert(dest != null);
- dest.Predecessors.Add(b);
- }
- }
- }
- this.BlockPredecessorsComputed = true;
- }
-
- public void PruneUnreachableBlocks() {
- ArrayList /*Block!*/ visitNext = new ArrayList /*Block!*/ ();
- List<Block/*!*/> reachableBlocks = new List<Block/*!*/>();
- HashSet<Block> reachable = new HashSet<Block>(); // the set of elements in "reachableBlocks"
-
- visitNext.Add(this.Blocks[0]);
- while (visitNext.Count != 0) {
- Block b = cce.NonNull((Block)visitNext[visitNext.Count - 1]);
- visitNext.RemoveAt(visitNext.Count - 1);
- if (!reachable.Contains(b)) {
- reachableBlocks.Add(b);
- reachable.Add(b);
- if (b.TransferCmd is GotoCmd) {
- if (CommandLineOptions.Clo.PruneInfeasibleEdges) {
- foreach (Cmd/*!*/ s in b.Cmds) {
- Contract.Assert(s != null);
- if (s is PredicateCmd) {
- LiteralExpr e = ((PredicateCmd)s).Expr as LiteralExpr;
- if (e != null && e.IsFalse) {
- // This statement sequence will never reach the end, because of this "assume false" or "assert false".
- // Hence, it does not reach its successors.
- b.TransferCmd = new ReturnCmd(b.TransferCmd.tok);
- goto NEXT_BLOCK;
- }
- }
- }
- }
- // it seems that the goto statement at the end may be reached
- foreach (Block succ in cce.NonNull((GotoCmd)b.TransferCmd).labelTargets) {
- Contract.Assume(succ != null);
- visitNext.Add(succ);
- }
- }
- }
- NEXT_BLOCK: {
- }
- }
-
- this.Blocks = reachableBlocks;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitImplementation(this);
- }
-
- public void FreshenCaptureStates() {
-
- // Assume commands with the "captureState" attribute allow model states to be
- // captured for error reporting.
- // Some program transformations, such as loop unrolling, duplicate parts of the
- // program, leading to "capture-state-assumes" being duplicated. This leads
- // to ambiguity when getting a state from the model.
- // This method replaces the key of every "captureState" attribute with something
- // unique
-
- int FreshCounter = 0;
- foreach(var b in Blocks) {
- List<Cmd> newCmds = new List<Cmd>();
- for (int i = 0; i < b.Cmds.Count(); i++) {
- var a = b.Cmds[i] as AssumeCmd;
- if (a != null && (QKeyValue.FindStringAttribute(a.Attributes, "captureState") != null)) {
- string StateName = QKeyValue.FindStringAttribute(a.Attributes, "captureState");
- newCmds.Add(new AssumeCmd(Token.NoToken, a.Expr, FreshenCaptureState(a.Attributes, FreshCounter)));
- FreshCounter++;
- }
- else {
- newCmds.Add(b.Cmds[i]);
- }
- }
- b.Cmds = newCmds;
- }
- }
-
- private QKeyValue FreshenCaptureState(QKeyValue Attributes, int FreshCounter) {
- // Returns attributes identical to Attributes, but:
- // - reversed (for ease of implementation; should not matter)
- // - with the value for "captureState" replaced by a fresh value
- Contract.Requires(QKeyValue.FindStringAttribute(Attributes, "captureState") != null);
- string FreshValue = QKeyValue.FindStringAttribute(Attributes, "captureState") + "$renamed$" + Name + "$" + FreshCounter;
-
- QKeyValue result = null;
- while (Attributes != null) {
- if (Attributes.Key.Equals("captureState")) {
- result = new QKeyValue(Token.NoToken, Attributes.Key, new List<object>() { FreshValue }, result);
- } else {
- result = new QKeyValue(Token.NoToken, Attributes.Key, Attributes.Params, result);
- }
- Attributes = Attributes.Next;
- }
- return result;
- }
-
- }
-
-
- public class TypedIdent : Absy {
- public const string NoName = "";
-
- private string/*!*/ _name;
-
- public string/*!*/ Name {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return this._name;
- }
- set {
- Contract.Requires(value != null);
- this._name = value;
- }
- }
-
- private Type/*!*/ _type;
-
- public Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this._type;
- }
- set {
- Contract.Requires(value != null);
- this._type = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._name != null);
- Contract.Invariant(this._type != null);
- }
-
- public Expr WhereExpr;
- // [NotDelayed]
- public TypedIdent(IToken/*!*/ tok, string/*!*/ name, Type/*!*/ type)
- : this(tok, name, type, null) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(type != null);
- Contract.Ensures(this.WhereExpr == null); //PM: needed to verify BoogiePropFactory.FreshBoundVariable
- //:this(tok, name, type, null); // here for aesthetic reasons
- }
- // [NotDelayed]
- public TypedIdent(IToken/*!*/ tok, string/*!*/ name, Type/*!*/ type, Expr whereExpr)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(type != null);
- Contract.Ensures(this.WhereExpr == whereExpr);
- this._name = name;
- this._type = type;
- this.WhereExpr = whereExpr;
- }
- public bool HasName {
- get {
- return this.Name != NoName;
- }
- }
- public void Emit(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- stream.SetToken(this);
- stream.push();
- if (this.Name != NoName) {
- stream.Write("{0}: ", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- this.Type.Emit(stream);
- if (this.WhereExpr != null) {
- stream.sep();
- stream.Write(" where ");
- this.WhereExpr.Emit(stream);
- }
- stream.pop();
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- // NOTE: WhereExpr needs to be resolved by the caller, because the caller must provide a modified ResolutionContext
- this.Type = this.Type.ResolveType(rc);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- // type variables can occur when working with polymorphic functions/procedures
- // if (!this.Type.IsClosed)
- // tc.Error(this, "free variables in type of an identifier: {0}",
- // this.Type.FreeVariables);
- if (this.WhereExpr != null) {
- this.WhereExpr.Typecheck(tc);
- Contract.Assert(this.WhereExpr.Type != null); // follows from postcondition of Expr.Typecheck
- if (!this.WhereExpr.Type.Unify(Type.Bool)) {
- tc.Error(this, "where clauses must be of type bool");
- }
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTypedIdent(this);
- }
- }
-
- #region Helper methods for generic Sequences
-
- public static class TypeVariableSeqAlgorithms {
- public static void AppendWithoutDups(this List<TypeVariable> tvs, List<TypeVariable> s1) {
- Contract.Requires(s1 != null);
- for (int i = 0; i < s1.Count; i++) {
- TypeVariable/*!*/ next = s1[i];
- Contract.Assert(next != null);
- if (!tvs.Contains(next))
- tvs.Add(next);
- }
- }
- }
-
- public static class Emitter {
-
- public static void Emit(this List<Declaration/*!*/>/*!*/ decls, TokenTextWriter stream) {
- Contract.Requires(stream != null);
- Contract.Requires(cce.NonNullElements(decls));
- bool first = true;
- foreach (Declaration d in decls) {
- if (d == null)
- continue;
- if (first) {
- first = false;
- } else {
- stream.WriteLine();
- }
- d.Emit(stream, 0);
- }
- }
-
- public static void Emit(this List<String> ss, TokenTextWriter stream) {
- Contract.Requires(stream != null);
- string sep = "";
- foreach (string/*!*/ s in ss) {
- Contract.Assert(s != null);
- stream.Write(sep);
- sep = ", ";
- stream.Write(s);
- }
- }
-
- public static void Emit(this IList<Expr> ts, TokenTextWriter stream) {
- Contract.Requires(stream != null);
- string sep = "";
- stream.push();
- foreach (Expr/*!*/ e in ts) {
- Contract.Assert(e != null);
- stream.Write(sep);
- sep = ", ";
- stream.sep();
- e.Emit(stream);
- }
- stream.pop();
- }
-
- public static void Emit(this List<IdentifierExpr> ids, TokenTextWriter stream, bool printWhereComments) {
- Contract.Requires(stream != null);
- string sep = "";
- foreach (IdentifierExpr/*!*/ e in ids) {
- Contract.Assert(e != null);
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
-
- if (printWhereComments && e.Decl != null && e.Decl.TypedIdent.WhereExpr != null) {
- stream.Write(" /* where ");
- e.Decl.TypedIdent.WhereExpr.Emit(stream);
- stream.Write(" */");
- }
- }
- }
-
- public static void Emit(this List<Variable> vs, TokenTextWriter stream, bool emitAttributes) {
- Contract.Requires(stream != null);
- string sep = "";
- stream.push();
- foreach (Variable/*!*/ v in vs) {
- Contract.Assert(v != null);
- stream.Write(sep);
- sep = ", ";
- stream.sep();
- v.EmitVitals(stream, 0, emitAttributes);
- }
- stream.pop();
- }
-
- public static void Emit(this List<Type> tys, TokenTextWriter stream, string separator) {
- Contract.Requires(separator != null);
- Contract.Requires(stream != null);
- string sep = "";
- foreach (Type/*!*/ v in tys) {
- Contract.Assert(v != null);
- stream.Write(sep);
- sep = separator;
- v.Emit(stream);
- }
- }
-
- public static void Emit(this List<TypeVariable> tvs, TokenTextWriter stream, string separator) {
- Contract.Requires(separator != null);
- Contract.Requires(stream != null);
- string sep = "";
- foreach (TypeVariable/*!*/ v in tvs) {
- Contract.Assert(v != null);
- stream.Write(sep);
- sep = separator;
- v.Emit(stream);
- }
- }
-
- }
- #endregion
-
-
- #region Regular Expressions
- // a data structure to recover the "program structure" from the flow graph
- public abstract class RE : Cmd {
- public RE()
- : base(Token.NoToken) {
- }
- public override void AddAssignedVariables(List<Variable> vars) {
- //Contract.Requires(vars != null);
- throw new NotImplementedException();
- }
- }
- public class AtomicRE : RE {
- private Block/*!*/ _b;
-
- public Block b
- {
- get
- {
- Contract.Ensures(Contract.Result<Block>() != null);
- return this._b;
- }
- set
- {
- Contract.Requires(value != null);
- this._b = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._b != null);
- }
-
- public AtomicRE(Block block) {
- Contract.Requires(block != null);
- this._b = block;
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- b.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- b.Typecheck(tc);
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- b.Emit(stream, level);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAtomicRE(this);
- }
- }
- public abstract class CompoundRE : RE {
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- return;
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- return;
- }
- }
- public class Sequential : CompoundRE {
- private RE/*!*/ _first;
-
- public RE/*!*/ first {
- get {
- Contract.Ensures(Contract.Result<RE>() != null);
- return this._first;
- }
- set {
- Contract.Requires(value != null);
- this._first = value;
- }
- }
-
- private RE/*!*/ _second;
-
- public RE/*!*/ second {
- get {
- Contract.Ensures(Contract.Result<RE>() != null);
- return this._second;
- }
- set {
- Contract.Requires(value != null);
- this._second = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._first != null);
- Contract.Invariant(this._second != null);
- }
-
- public Sequential(RE first, RE second) {
- Contract.Requires(first != null);
- Contract.Requires(second != null);
- this._first = first;
- this._second = second;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.WriteLine();
- stream.WriteLine("{0};", Indent(stream.UseForComputingChecksums ? 0 : level));
- first.Emit(stream, level + 1);
- second.Emit(stream, level + 1);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitSequential(this);
- }
- }
- public class Choice : CompoundRE {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._rs != null);
- }
-
- private List<RE>/*!*/ _rs;
-
- public List<RE>/*!*/ rs { //Rename this (and _rs) if possible
- get {
- Contract.Ensures(Contract.Result<List<RE>>() != null);
- return this._rs;
- }
- set {
- Contract.Requires(value != null);
- this._rs = value;
- }
- }
-
- public Choice(List<RE> operands) {
- Contract.Requires(operands != null);
- this._rs = operands;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.WriteLine();
- stream.WriteLine("{0}[]", Indent(stream.UseForComputingChecksums ? 0 : level));
- foreach (RE/*!*/ r in rs) {
- Contract.Assert(r != null);
- r.Emit(stream, level + 1);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitChoice(this);
- }
- }
- public class DAG2RE {
- public static RE Transform(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<RE>() != null);
- TransferCmd tc = b.TransferCmd;
- if (tc is ReturnCmd) {
- return new AtomicRE(b);
- } else if (tc is GotoCmd) {
- GotoCmd/*!*/ g = (GotoCmd)tc;
- Contract.Assert(g != null);
- Contract.Assume(g.labelTargets != null);
- if (g.labelTargets.Count == 1) {
- return new Sequential(new AtomicRE(b), Transform(cce.NonNull(g.labelTargets[0])));
- } else {
- List<RE> rs = new List<RE>();
- foreach (Block/*!*/ target in g.labelTargets) {
- Contract.Assert(target != null);
- RE r = Transform(target);
- rs.Add(r);
- }
- RE second = new Choice(rs);
- return new Sequential(new AtomicRE(b), second);
- }
- } else {
- Contract.Assume(false);
- throw new cce.UnreachableException();
- }
- }
- }
-
- #endregion
-
- // NOTE: This class is here for convenience, since this file's
- // classes are used pretty much everywhere.
-
- public class BoogieDebug {
- public static bool DoPrinting = false;
-
- public static void Write(string format, params object[] args) {
- Contract.Requires(args != null);
- Contract.Requires(format != null);
- if (DoPrinting) {
- Console.Error.Write(format, args);
- }
- }
-
- public static void WriteLine(string format, params object[] args) {
- Contract.Requires(args != null);
- Contract.Requires(format != null);
- if (DoPrinting) {
- Console.Error.WriteLine(format, args);
- }
- }
-
- public static void WriteLine() {
- if (DoPrinting) {
- Console.Error.WriteLine();
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+namespace Microsoft.Boogie.AbstractInterpretation {
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ public class CallSite {
+ public readonly Implementation/*!*/ Impl;
+ public readonly Block/*!*/ Block;
+ public readonly int Statement; // invariant: Block[Statement] is CallCmd
+ public readonly ProcedureSummaryEntry/*!*/ SummaryEntry;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Impl != null);
+ Contract.Invariant(Block != null);
+ Contract.Invariant(SummaryEntry != null);
+ }
+
+
+ public CallSite(Implementation impl, Block b, int stmt, ProcedureSummaryEntry summaryEntry) {
+ Contract.Requires(summaryEntry != null);
+ Contract.Requires(b != null);
+ Contract.Requires(impl != null);
+ this.Impl = impl;
+ this.Block = b;
+ this.Statement = stmt;
+ this.SummaryEntry = summaryEntry;
+ }
+ }
+
+ public class ProcedureSummaryEntry {
+
+ private HashSet<CallSite>/*!*/ _returnPoints; // whenever OnExit changes, we start analysis again at all the ReturnPoints
+
+ public HashSet<CallSite>/*!*/ ReturnPoints {
+ get {
+ Contract.Ensures(Contract.Result<HashSet<CallSite>>() != null);
+ return this._returnPoints;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._returnPoints = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._returnPoints != null);
+ }
+
+ public ProcedureSummaryEntry() {
+ this._returnPoints = new HashSet<CallSite>();
+ }
+
+ } // class
+
+ public class ProcedureSummary : ArrayList/*<ProcedureSummaryEntry>*/
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(
+ !IsReadOnly && !IsFixedSize);
+ }
+
+ public new ProcedureSummaryEntry/*!*/ this[int i] {
+ get {
+ Contract.Requires(0 <= i && i < Count);
+ Contract.Ensures(Contract.Result<ProcedureSummaryEntry>() != null);
+ return cce.NonNull((ProcedureSummaryEntry/*!*/)base[i]);
+ }
+ }
+
+ } // class
+} // namespace
+
+namespace Microsoft.Boogie {
+ using System;
+ using System.Linq;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics.Contracts;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using Microsoft.Boogie.GraphUtil;
+ using Set = GSet<object>;
+
+ [ContractClass(typeof(AbsyContracts))]
+ public abstract class Absy {
+ private IToken/*!*/ _tok;
+ private int uniqueId;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._tok != null);
+ }
+
+ public IToken tok { //Rename this property and "_tok" if possible
+ get {
+ Contract.Ensures(Contract.Result<IToken>() != null);
+ return this._tok;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._tok = value;
+ }
+ }
+
+ public int Line {
+ get {
+ return tok != null ? tok.line : -1;
+ }
+ }
+ public int Col {
+ get {
+ return tok != null ? tok.col : -1;
+ }
+ }
+
+ public Absy(IToken tok) {
+ Contract.Requires(tok != null);
+ this._tok = tok;
+ this.uniqueId = System.Threading.Interlocked.Increment(ref CurrentAbsyNodeId);
+ }
+
+ private static int CurrentAbsyNodeId = -1;
+
+ // We uniquely number every AST node to make them
+ // suitable for our implementation of functional maps.
+ //
+ public int UniqueId {
+ get {
+ return this.uniqueId;
+ }
+ }
+
+ private const int indent_size = 2;
+ protected static string Indent(int level) {
+ return new string(' ', (indent_size * level));
+ }
+ [NeedsContracts]
+ public abstract void Resolve(ResolutionContext/*!*/ rc);
+
+ /// <summary>
+ /// Requires the object to have been successfully resolved.
+ /// </summary>
+ /// <param name="tc"></param>
+ [NeedsContracts]
+ public abstract void Typecheck(TypecheckingContext/*!*/ tc);
+ /// <summary>
+ /// Intorduced this so the uniqueId is not the same on a cloned object.
+ /// </summary>
+ /// <param name="tc"></param>
+ public virtual Absy Clone() {
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ Absy/*!*/ result = cce.NonNull((Absy/*!*/)this.MemberwiseClone());
+ result.uniqueId = System.Threading.Interlocked.Increment(ref CurrentAbsyNodeId); // BUGBUG??
+
+ if (InternalNumberedMetadata != null) {
+ // This should probably use the lock
+ result.InternalNumberedMetadata = new List<Object>(this.InternalNumberedMetadata);
+ }
+
+ return result;
+ }
+
+ public virtual Absy StdDispatch(StandardVisitor visitor) {
+ Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ System.Diagnostics.Debug.Fail("Unknown Absy node type: " + this.GetType());
+ throw new System.NotImplementedException();
+ }
+
+ #region numberedmetadata
+ // Implementation of Numbered Metadata
+ // This allows any number of arbitrary objects to be
+ // associated with an instance of an Absy at run time
+ // in a type safe manner using an integer as a key.
+
+ // We could use a dictionary but we use a List for look up speed
+ // For this to work well the user needs to use small integers as
+ // keys. The list is created lazily to minimise memory overhead.
+ private volatile List<Object> InternalNumberedMetadata = null;
+
+ // The lock exists to ensure that InternalNumberedMetadata is a singleton
+ // for every instance of this class.
+ // It is static to minimise the memory overhead (we don't want a lock per instance).
+ private static readonly Object NumberedMetadataLock = new object();
+
+ /// <summary>
+ /// Gets the number of meta data objects associated with this instance
+ /// </summary>
+ /// <value>The numbered meta data count.</value>
+ public int NumberedMetaDataCount
+ {
+ get { return InternalNumberedMetadata == null? 0: InternalNumberedMetadata.Count; }
+ }
+
+ /// <summary>
+ /// Gets an IEnumerable over the numbered metadata associated
+ /// with this instance.
+ /// </summary>
+ /// <value>
+ /// The numbered meta data enumerable that looks like the Enumerable
+ /// of a dictionary.
+ /// </value>
+ public IEnumerable<KeyValuePair<int, Object>> NumberedMetadata
+ {
+ get {
+ if (InternalNumberedMetadata == null)
+ return Enumerable.Empty<KeyValuePair<int,Object>>();
+ else
+ return InternalNumberedMetadata.Select((v, index) => new KeyValuePair<int, Object>(index, v));
+ }
+ }
+
+ /// <summary>
+ /// Gets the metatdata at specified index.
+ /// ArgumentOutOfRange exception is raised if it is not available.
+ /// InvalidCastExcpetion is raised if the metadata is available but the wrong type was requested.
+ /// </summary>
+ /// <returns>The stored metadata of type T</returns>
+ /// <param name="index">The index of the metadata</param>
+ /// <typeparam name="T">The type of the metadata object required</typeparam>
+ public T GetMetadata<T>(int index) {
+ // We aren't using NumberedMetadataLock for speed. Perhaps we should be using it?
+ if (InternalNumberedMetadata == null)
+ throw new ArgumentOutOfRangeException();
+
+ if (InternalNumberedMetadata[index] is T)
+ return (T) InternalNumberedMetadata[index];
+ else if (InternalNumberedMetadata[index] == null) {
+ throw new InvalidCastException("Numbered metadata " + index +
+ " is null which cannot be casted to " + typeof(T));
+ }
+ else {
+ throw new InvalidCastException("Numbered metadata " + index +
+ " is of type " + InternalNumberedMetadata[index].GetType() +
+ " rather than requested type " + typeof(T));
+ }
+ }
+
+ private void InitialiseNumberedMetadata() {
+ // Ensure InternalNumberedMetadata is a singleton
+ if (InternalNumberedMetadata == null) {
+ lock (NumberedMetadataLock) {
+ if (InternalNumberedMetadata == null)
+ InternalNumberedMetadata = new List<Object>();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Sets the metadata for this instace at a specified index.
+ /// </summary>
+ /// <param name="index">The index of the metadata</param>
+ /// <param name="value">The value to set</param>
+ /// <typeparam name="T">The type of value</typeparam>
+ public void SetMetadata<T>(int index, T value) {
+ InitialiseNumberedMetadata();
+
+ if (index < 0)
+ throw new IndexOutOfRangeException();
+
+ lock (NumberedMetadataLock) {
+ if (index < InternalNumberedMetadata.Count)
+ InternalNumberedMetadata[index] = value;
+ else {
+ // Make sure expansion only happens once whilst we pad
+ if (InternalNumberedMetadata.Capacity <= index) {
+ // Use the next available power of 2
+ InternalNumberedMetadata.Capacity = (int) Math.Pow(2, Math.Ceiling(Math.Log(index+1,2)));
+ }
+
+ // Pad with nulls
+ while (InternalNumberedMetadata.Count < index)
+ InternalNumberedMetadata.Add (null);
+
+ InternalNumberedMetadata.Add(value);
+ Debug.Assert(InternalNumberedMetadata.Count == (index + 1));
+ }
+ }
+ }
+
+ #endregion
+
+ }
+
+ [ContractClassFor(typeof(Absy))]
+ public abstract class AbsyContracts : Absy {
+ public override void Resolve(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ throw new NotImplementedException();
+ }
+ public AbsyContracts() :base(null){
+
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ Contract.Requires(tc != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public interface IPotentialErrorNode<out TGet>
+ {
+ TGet ErrorData
+ {
+ get;
+ }
+ }
+
+ public interface IPotentialErrorNode<out TGet, in TSet> : IPotentialErrorNode<TGet>
+ {
+ new TSet ErrorData
+ {
+ set;
+ }
+ }
+
+ public class Program : Absy {
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(this.topLevelDeclarations));
+ Contract.Invariant(cce.NonNullElements(this.globalVariablesCache, true));
+ }
+
+ public Program()
+ : base(Token.NoToken) {
+ this.topLevelDeclarations = new List<Declaration>();
+ }
+
+ public void Emit(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ stream.SetToken(this);
+ this.topLevelDeclarations.Emit(stream);
+ }
+
+ public void ProcessDatatypeConstructors() {
+ Dictionary<string, DatatypeConstructor> constructors = new Dictionary<string, DatatypeConstructor>();
+ List<Declaration> prunedTopLevelDeclarations = new List<Declaration>();
+ foreach (Declaration decl in TopLevelDeclarations) {
+ Function func = decl as Function;
+ if (func == null || !QKeyValue.FindBoolAttribute(decl.Attributes, "constructor")) {
+ prunedTopLevelDeclarations.Add(decl);
+ continue;
+ }
+ if (constructors.ContainsKey(func.Name)) continue;
+ DatatypeConstructor constructor = new DatatypeConstructor(func);
+ constructors.Add(func.Name, constructor);
+ prunedTopLevelDeclarations.Add(constructor);
+ }
+ ClearTopLevelDeclarations();
+ AddTopLevelDeclarations(prunedTopLevelDeclarations);
+
+ foreach (DatatypeConstructor f in constructors.Values) {
+ for (int i = 0; i < f.InParams.Count; i++) {
+ DatatypeSelector selector = new DatatypeSelector(f, i);
+ f.selectors.Add(selector);
+ AddTopLevelDeclaration(selector);
+ }
+ DatatypeMembership membership = new DatatypeMembership(f);
+ f.membership = membership;
+ AddTopLevelDeclaration(membership);
+ }
+ }
+
+ /// <summary>
+ /// Returns the number of name resolution errors.
+ /// </summary>
+ /// <returns></returns>
+ public int Resolve() {
+ return Resolve((IErrorSink)null);
+ }
+
+ public int Resolve(IErrorSink errorSink) {
+ ResolutionContext rc = new ResolutionContext(errorSink);
+ Resolve(rc);
+ return rc.ErrorCount;
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Helpers.ExtraTraceInformation("Starting resolution");
+
+ foreach (var d in TopLevelDeclarations) {
+ d.Register(rc);
+ }
+
+ ResolveTypes(rc);
+
+ var prunedTopLevelDecls = new List<Declaration/*!*/>();
+ foreach (var d in TopLevelDeclarations) {
+ if (QKeyValue.FindBoolAttribute(d.Attributes, "ignore")) {
+ continue;
+ }
+ // resolve all the non-type-declarations
+ if (!(d is TypeCtorDecl || d is TypeSynonymDecl)) {
+ int e = rc.ErrorCount;
+ d.Resolve(rc);
+ if (CommandLineOptions.Clo.OverlookBoogieTypeErrors && rc.ErrorCount != e && d is Implementation) {
+ // ignore this implementation
+ System.Console.WriteLine("Warning: Ignoring implementation {0} because of translation resolution errors", ((Implementation)d).Name);
+ rc.ErrorCount = e;
+ continue;
+ }
+ }
+ prunedTopLevelDecls.Add(d);
+ }
+ ClearTopLevelDeclarations();
+ AddTopLevelDeclarations(prunedTopLevelDecls);
+
+ foreach (var v in Variables) {
+ v.ResolveWhere(rc);
+ }
+ }
+
+ private void ResolveTypes(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ // first resolve type constructors
+ foreach (var d in TopLevelDeclarations.OfType<TypeCtorDecl>()) {
+ if (!QKeyValue.FindBoolAttribute(d.Attributes, "ignore"))
+ d.Resolve(rc);
+ }
+
+ // collect type synonym declarations
+ List<TypeSynonymDecl/*!*/>/*!*/ synonymDecls = new List<TypeSynonymDecl/*!*/>();
+ foreach (var d in TopLevelDeclarations.OfType<TypeSynonymDecl>()) {
+ Contract.Assert(d != null);
+ if (!QKeyValue.FindBoolAttribute(d.Attributes, "ignore"))
+ synonymDecls.Add((TypeSynonymDecl)d);
+ }
+
+ // then resolve the type synonyms by a simple
+ // fixed-point iteration
+ TypeSynonymDecl.ResolveTypeSynonyms(synonymDecls, rc);
+ }
+
+ public int Typecheck() {
+ return this.Typecheck((IErrorSink)null);
+ }
+
+ public int Typecheck(IErrorSink errorSink) {
+ TypecheckingContext tc = new TypecheckingContext(errorSink);
+ Typecheck(tc);
+ return tc.ErrorCount;
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ Helpers.ExtraTraceInformation("Starting typechecking");
+
+ int oldErrorCount = tc.ErrorCount;
+ foreach (var d in TopLevelDeclarations) {
+ d.Typecheck(tc);
+ }
+
+ if (oldErrorCount == tc.ErrorCount) {
+ // check whether any type proxies have remained uninstantiated
+ TypeAmbiguitySeeker/*!*/ seeker = new TypeAmbiguitySeeker(tc);
+ foreach (var d in TopLevelDeclarations) {
+ seeker.Visit(d);
+ }
+ }
+ }
+
+ public override Absy Clone()
+ {
+ var cloned = (Program)base.Clone();
+ cloned.topLevelDeclarations = new List<Declaration>();
+ cloned.AddTopLevelDeclarations(topLevelDeclarations);
+ return cloned;
+ }
+
+ [Rep]
+ private List<Declaration/*!*/>/*!*/ topLevelDeclarations;
+
+ public IEnumerable<Declaration> TopLevelDeclarations
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Declaration>>()));
+ return topLevelDeclarations.AsReadOnly();
+ }
+
+ set
+ {
+ Contract.Requires(value != null);
+ // materialize the decls, in case there is any dependency
+ // back on topLevelDeclarations
+ var v = value.ToList();
+ // remove null elements
+ v.RemoveAll(d => (d == null));
+ // now clear the decls
+ ClearTopLevelDeclarations();
+ // and add the values
+ AddTopLevelDeclarations(v);
+ }
+ }
+
+ public void AddTopLevelDeclaration(Declaration decl)
+ {
+ Contract.Requires(!TopLevelDeclarationsAreFrozen);
+ Contract.Requires(decl != null);
+
+ topLevelDeclarations.Add(decl);
+ this.globalVariablesCache = null;
+ }
+
+ public void AddTopLevelDeclarations(IEnumerable<Declaration> decls)
+ {
+ Contract.Requires(!TopLevelDeclarationsAreFrozen);
+ Contract.Requires(cce.NonNullElements(decls));
+
+ topLevelDeclarations.AddRange(decls);
+ this.globalVariablesCache = null;
+ }
+
+ public void RemoveTopLevelDeclaration(Declaration decl)
+ {
+ Contract.Requires(!TopLevelDeclarationsAreFrozen);
+
+ topLevelDeclarations.Remove(decl);
+ this.globalVariablesCache = null;
+ }
+
+ public void RemoveTopLevelDeclarations(Predicate<Declaration> match)
+ {
+ Contract.Requires(!TopLevelDeclarationsAreFrozen);
+
+ topLevelDeclarations.RemoveAll(match);
+ this.globalVariablesCache = null;
+ }
+
+ public void ClearTopLevelDeclarations()
+ {
+ Contract.Requires(!TopLevelDeclarationsAreFrozen);
+
+ topLevelDeclarations.Clear();
+ this.globalVariablesCache = null;
+ }
+
+ bool topLevelDeclarationsAreFrozen;
+ public bool TopLevelDeclarationsAreFrozen { get { return topLevelDeclarationsAreFrozen; } }
+ public void FreezeTopLevelDeclarations()
+ {
+ topLevelDeclarationsAreFrozen = true;
+ }
+
+ Dictionary<string, Implementation> implementationsCache;
+ public IEnumerable<Implementation> Implementations
+ {
+ get
+ {
+ if (implementationsCache != null)
+ {
+ return implementationsCache.Values;
+ }
+ var result = TopLevelDeclarations.OfType<Implementation>();
+ if (topLevelDeclarationsAreFrozen)
+ {
+ implementationsCache = result.ToDictionary(p => p.Id);
+ }
+ return result;
+ }
+ }
+
+ public Implementation FindImplementation(string id)
+ {
+ Implementation result = null;
+ if (implementationsCache != null && implementationsCache.TryGetValue(id, out result))
+ {
+ return result;
+ }
+ else
+ {
+ return Implementations.FirstOrDefault(i => i.Id == id);
+ }
+ }
+
+ List<Axiom> axiomsCache;
+ public IEnumerable<Axiom> Axioms
+ {
+ get
+ {
+ if (axiomsCache != null)
+ {
+ return axiomsCache;
+ }
+ var result = TopLevelDeclarations.OfType<Axiom>();
+ if (topLevelDeclarationsAreFrozen)
+ {
+ axiomsCache = result.ToList();
+ }
+ return result;
+ }
+ }
+
+ Dictionary<string, Procedure> proceduresCache;
+ public IEnumerable<Procedure> Procedures
+ {
+ get
+ {
+ if (proceduresCache != null)
+ {
+ return proceduresCache.Values;
+ }
+ var result = TopLevelDeclarations.OfType<Procedure>();
+ if (topLevelDeclarationsAreFrozen)
+ {
+ proceduresCache = result.ToDictionary(p => p.Name);
+ }
+ return result;
+ }
+ }
+
+ public Procedure FindProcedure(string name)
+ {
+ Procedure result = null;
+ if (proceduresCache != null && proceduresCache.TryGetValue(name, out result))
+ {
+ return result;
+ }
+ else
+ {
+ return Procedures.FirstOrDefault(p => p.Name == name);
+ }
+ }
+
+ Dictionary<string, Function> functionsCache;
+ public IEnumerable<Function> Functions
+ {
+ get
+ {
+ if (functionsCache != null)
+ {
+ return functionsCache.Values;
+ }
+ var result = TopLevelDeclarations.OfType<Function>();
+ if (topLevelDeclarationsAreFrozen)
+ {
+ functionsCache = result.ToDictionary(f => f.Name);
+ }
+ return result;
+ }
+ }
+
+ public Function FindFunction(string name)
+ {
+ Function result = null;
+ if (functionsCache != null && functionsCache.TryGetValue(name, out result))
+ {
+ return result;
+ }
+ else
+ {
+ return Functions.FirstOrDefault(f => f.Name == name);
+ }
+ }
+
+ public IEnumerable<Variable> Variables
+ {
+ get
+ {
+ return TopLevelDeclarations.OfType<Variable>();
+ }
+ }
+
+ public IEnumerable<Constant> Constants
+ {
+ get
+ {
+ return TopLevelDeclarations.OfType<Constant>();
+ }
+ }
+
+ private IEnumerable<GlobalVariable/*!*/> globalVariablesCache = null;
+ public List<GlobalVariable/*!*/>/*!*/ GlobalVariables
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<GlobalVariable>>()));
+
+ if (globalVariablesCache == null)
+ globalVariablesCache = TopLevelDeclarations.OfType<GlobalVariable>();
+
+ return new List<GlobalVariable>(globalVariablesCache);
+ }
+ }
+
+ public readonly ISet<string> NecessaryAssumes = new HashSet<string>();
+
+ public IEnumerable<Block> Blocks()
+ {
+ return Implementations.Select(Item => Item.Blocks).SelectMany(Item => Item);
+ }
+
+ public void ComputeStronglyConnectedComponents() {
+ foreach (var d in this.TopLevelDeclarations) {
+ d.ComputeStronglyConnectedComponents();
+ }
+ }
+
+ /// <summary>
+ /// Reset the abstract stated computed before
+ /// </summary>
+ public void ResetAbstractInterpretationState() {
+ foreach (var d in this.TopLevelDeclarations) {
+ d.ResetAbstractInterpretationState();
+ }
+ }
+
+ public void UnrollLoops(int n, bool uc) {
+ Contract.Requires(0 <= n);
+ foreach (var impl in Implementations) {
+ if (impl.Blocks != null && impl.Blocks.Count > 0) {
+ cce.BeginExpose(impl);
+ {
+ Block start = impl.Blocks[0];
+ Contract.Assume(start != null);
+ Contract.Assume(cce.IsConsistent(start));
+ impl.Blocks = LoopUnroll.UnrollLoops(start, n, uc);
+ impl.FreshenCaptureStates();
+ }
+ cce.EndExpose();
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Finds blocks that break out of a loop in NaturalLoops(header, backEdgeNode)
+ /// </summary>
+ /// <param name="header"></param>
+ /// <param name="backEdgeNode"></param>
+ /// <returns></returns>
+ private HashSet<Block> GetBreakBlocksOfLoop(Block header, Block backEdgeNode, Graph<Block/*!*/>/*!*/ g)
+ {
+ Contract.Assert(CommandLineOptions.Clo.DeterministicExtractLoops, "Can only be called with /deterministicExtractLoops option");
+ var immSuccBlks = new HashSet<Block>();
+ var loopBlocks = g.NaturalLoops(header, backEdgeNode);
+ foreach (Block/*!*/ block in loopBlocks)
+ {
+ Contract.Assert(block != null);
+ var auxCmd = block.TransferCmd as GotoCmd;
+ if (auxCmd == null) continue;
+ foreach (var bl in auxCmd.labelTargets)
+ {
+ if (loopBlocks.Contains(bl)) continue;
+ immSuccBlks.Add(bl);
+ }
+ }
+ return immSuccBlks;
+ }
+
+ private HashSet<Block> GetBlocksInAllNaturalLoops(Block header, Graph<Block/*!*/>/*!*/ g)
+ {
+ Contract.Assert(CommandLineOptions.Clo.DeterministicExtractLoops, "Can only be called with /deterministicExtractLoops option");
+ var allBlocksInNaturalLoops = new HashSet<Block>();
+ foreach (Block/*!*/ source in g.BackEdgeNodes(header))
+ {
+ Contract.Assert(source != null);
+ g.NaturalLoops(header, source).Iter(b => allBlocksInNaturalLoops.Add(b));
+ }
+ return allBlocksInNaturalLoops;
+ }
+
+
+ void CreateProceduresForLoops(Implementation impl, Graph<Block/*!*/>/*!*/ g,
+ List<Implementation/*!*/>/*!*/ loopImpls,
+ Dictionary<string, Dictionary<string, Block>> fullMap) {
+ Contract.Requires(impl != null);
+ Contract.Requires(cce.NonNullElements(loopImpls));
+ // Enumerate the headers
+ // for each header h:
+ // create implementation p_h with
+ // inputs = inputs, outputs, and locals of impl
+ // outputs = outputs and locals of impl
+ // locals = empty set
+ // add call o := p_h(i) at the beginning of the header block
+ // break the back edges whose target is h
+ // Enumerate the headers again to create the bodies of p_h
+ // for each header h:
+ // compute the loop corresponding to h
+ // make copies of all blocks in the loop for h
+ // delete all target edges that do not go to a block in the loop
+ // create a new entry block and a new return block
+ // add edges from entry block to the loop header and the return block
+ // add calls o := p_h(i) at the end of the blocks that are sources of back edges
+ foreach (Block block in impl.Blocks)
+ {
+ AddToFullMap(fullMap, impl.Name, block.Label, block);
+ }
+
+ bool detLoopExtract = CommandLineOptions.Clo.DeterministicExtractLoops;
+
+ Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToInputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>();
+ Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToOutputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>();
+ Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>/*!*/ loopHeaderToSubstMap = new Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>();
+ Dictionary<Block/*!*/, LoopProcedure/*!*/>/*!*/ loopHeaderToLoopProc = new Dictionary<Block/*!*/, LoopProcedure/*!*/>();
+ Dictionary<Block/*!*/, CallCmd/*!*/>/*!*/ loopHeaderToCallCmd1 = new Dictionary<Block/*!*/, CallCmd/*!*/>();
+ Dictionary<Block, CallCmd> loopHeaderToCallCmd2 = new Dictionary<Block, CallCmd>();
+ Dictionary<Block, AssignCmd> loopHeaderToAssignCmd = new Dictionary<Block, AssignCmd>();
+
+ foreach (Block/*!*/ header in g.Headers) {
+ Contract.Assert(header != null);
+ Contract.Assert(header != null);
+ List<Variable> inputs = new List<Variable>();
+ List<Variable> outputs = new List<Variable>();
+ List<Expr> callInputs1 = new List<Expr>();
+ List<IdentifierExpr> callOutputs1 = new List<IdentifierExpr>();
+ List<Expr> callInputs2 = new List<Expr>();
+ List<IdentifierExpr> callOutputs2 = new List<IdentifierExpr>();
+ List<AssignLhs> lhss = new List<AssignLhs>();
+ List<Expr> rhss = new List<Expr>();
+ Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); // Variable -> IdentifierExpr
+
+ List<Variable>/*!*/ targets = new List<Variable>();
+ HashSet<Variable> footprint = new HashSet<Variable>();
+
+ foreach (Block/*!*/ b in g.BackEdgeNodes(header))
+ {
+ Contract.Assert(b != null);
+ HashSet<Block> immSuccBlks = new HashSet<Block>();
+ if (detLoopExtract)
+ {
+ //Need to get the blocks that exit the loop, as we need to add them to targets and footprint
+ immSuccBlks = GetBreakBlocksOfLoop(header, b, g);
+ }
+ foreach (Block/*!*/ block in g.NaturalLoops(header, b).Union(immSuccBlks))
+ {
+ Contract.Assert(block != null);
+ foreach (Cmd/*!*/ cmd in block.Cmds)
+ {
+ Contract.Assert(cmd != null);
+ cmd.AddAssignedVariables(targets);
+
+ VariableCollector c = new VariableCollector();
+ c.Visit(cmd);
+ footprint.UnionWith(c.usedVars);
+ }
+ }
+ }
+
+ List<IdentifierExpr>/*!*/ globalMods = new List<IdentifierExpr>();
+ Set targetSet = new Set();
+ foreach (Variable/*!*/ v in targets)
+ {
+ Contract.Assert(v != null);
+ if (targetSet.Contains(v))
+ continue;
+ targetSet.Add(v);
+ if (v is GlobalVariable)
+ globalMods.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+
+ foreach (Variable v in impl.InParams) {
+ Contract.Assert(v != null);
+ if (!footprint.Contains(v)) continue;
+ callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
+ Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
+ inputs.Add(f);
+ callInputs2.Add(new IdentifierExpr(Token.NoToken, f));
+ substMap[v] = new IdentifierExpr(Token.NoToken, f);
+ }
+ foreach (Variable v in impl.OutParams) {
+ Contract.Assert(v != null);
+ if (!footprint.Contains(v)) continue;
+ callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
+ Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
+ inputs.Add(f1);
+ if (targetSet.Contains(v))
+ {
+ callOutputs1.Add(new IdentifierExpr(Token.NoToken, v));
+ Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
+ outputs.Add(f2);
+ callInputs2.Add(new IdentifierExpr(Token.NoToken, f2));
+ callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2));
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2)));
+ rhss.Add(new IdentifierExpr(Token.NoToken, f1));
+ substMap[v] = new IdentifierExpr(Token.NoToken, f2);
+ }
+ else
+ {
+ callInputs2.Add(new IdentifierExpr(Token.NoToken, f1));
+ substMap[v] = new IdentifierExpr(Token.NoToken, f1);
+ }
+ }
+ foreach (Variable v in impl.LocVars) {
+ Contract.Assert(v != null);
+ if (!footprint.Contains(v)) continue;
+ callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
+ Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
+ inputs.Add(f1);
+ if (targetSet.Contains(v))
+ {
+ callOutputs1.Add(new IdentifierExpr(Token.NoToken, v));
+ Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
+ outputs.Add(f2);
+ callInputs2.Add(new IdentifierExpr(Token.NoToken, f2));
+ callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2));
+ lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2)));
+ rhss.Add(new IdentifierExpr(Token.NoToken, f1));
+ substMap[v] = new IdentifierExpr(Token.NoToken, f2);
+ }
+ else
+ {
+ callInputs2.Add(new IdentifierExpr(Token.NoToken, f1));
+ substMap[v] = new IdentifierExpr(Token.NoToken, f1);
+ }
+ }
+
+ loopHeaderToInputs[header] = inputs;
+ loopHeaderToOutputs[header] = outputs;
+ loopHeaderToSubstMap[header] = substMap;
+ LoopProcedure loopProc = new LoopProcedure(impl, header, inputs, outputs, globalMods);
+ loopHeaderToLoopProc[header] = loopProc;
+
+ CallCmd callCmd1 = new CallCmd(Token.NoToken, loopProc.Name, callInputs1, callOutputs1);
+ callCmd1.Proc = loopProc;
+ loopHeaderToCallCmd1[header] = callCmd1;
+
+ CallCmd callCmd2 = new CallCmd(Token.NoToken, loopProc.Name, callInputs2, callOutputs2);
+ callCmd2.Proc = loopProc;
+ loopHeaderToCallCmd2[header] = callCmd2;
+
+ Debug.Assert(lhss.Count == rhss.Count);
+ if (lhss.Count > 0)
+ {
+ AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss);
+ loopHeaderToAssignCmd[header] = assignCmd;
+ }
+ }
+
+ // Keep track of the new blocks created: maps a header node to the
+ // header_last block that was created because of splitting header.
+ Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>();
+
+ bool headRecursion = false; // testing an option to put recursive call before loop body
+
+ IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance();
+ foreach (Block/*!*/ header in sortedHeaders)
+ {
+ Contract.Assert(header != null);
+ LoopProcedure loopProc = loopHeaderToLoopProc[header];
+ Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
+ HashSet<string> dummyBlocks = new HashSet<string>();
+
+ CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]); // fix me
+ List<Variable> inputs = loopHeaderToInputs[header];
+ List<Variable> outputs = loopHeaderToOutputs[header];
+ int si_unique_loc = 1; // Added by AL: to distinguish the back edges
+ foreach (Block/*!*/ source in g.BackEdgeNodes(header)) {
+ Contract.Assert(source != null);
+ foreach (Block/*!*/ block in g.NaturalLoops(header, source)) {
+ Contract.Assert(block != null);
+ if (blockMap.ContainsKey(block))
+ continue;
+ Block newBlock = new Block();
+ newBlock.Label = block.Label;
+ if (headRecursion && block == header)
+ {
+ CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
+ addUniqueCallAttr(si_unique_loc, callCmd);
+ si_unique_loc++;
+ newBlock.Cmds.Add(callCmd); // add the recursive call at head of loop
+ var rest = codeCopier.CopyCmdSeq(block.Cmds);
+ newBlock.Cmds.AddRange(rest);
+ }
+ else
+ newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds);
+ blockMap[block] = newBlock;
+ if (newBlocksCreated.ContainsKey(block))
+ {
+ Block newBlock2 = new Block();
+ newBlock2.Label = newBlocksCreated[block].Label;
+ newBlock2.Cmds = codeCopier.CopyCmdSeq(newBlocksCreated[block].Cmds);
+ blockMap[newBlocksCreated[block]] = newBlock2;
+ }
+ //for detLoopExtract, need the immediate successors even outside the loop
+ if (detLoopExtract) {
+ GotoCmd auxGotoCmd = block.TransferCmd as GotoCmd;
+ Contract.Assert(auxGotoCmd != null && auxGotoCmd.labelNames != null &&
+ auxGotoCmd.labelTargets != null && auxGotoCmd.labelTargets.Count >= 1);
+ //BUGFIX on 10/26/15: this contains nodes present in NaturalLoops for a different backedgenode
+ var loopNodes = GetBlocksInAllNaturalLoops(header, g); //var loopNodes = g.NaturalLoops(header, source);
+ foreach(var bl in auxGotoCmd.labelTargets) {
+ if (g.Nodes.Contains(bl) && //newly created blocks are not present in NaturalLoop(header, xx, g)
+ !loopNodes.Contains(bl)) {
+ Block auxNewBlock = new Block();
+ auxNewBlock.Label = ((Block)bl).Label;
+ //these blocks may have read/write locals that are not present in naturalLoops
+ //we need to capture these variables
+ auxNewBlock.Cmds = codeCopier.CopyCmdSeq(((Block)bl).Cmds);
+ //add restoration code for such blocks
+ if (loopHeaderToAssignCmd.ContainsKey(header))
+ {
+ AssignCmd assignCmd = loopHeaderToAssignCmd[header];
+ auxNewBlock.Cmds.Add(assignCmd);
+ }
+ List<AssignLhs> lhsg = new List<AssignLhs>();
+ List<IdentifierExpr>/*!*/ globalsMods = loopHeaderToLoopProc[header].Modifies;
+ foreach (IdentifierExpr gl in globalsMods)
+ lhsg.Add(new SimpleAssignLhs(Token.NoToken, gl));
+ List<Expr> rhsg = new List<Expr>();
+ foreach (IdentifierExpr gl in globalsMods)
+ rhsg.Add(new OldExpr(Token.NoToken, gl));
+ if (lhsg.Count != 0)
+ {
+ AssignCmd globalAssignCmd = new AssignCmd(Token.NoToken, lhsg, rhsg);
+ auxNewBlock.Cmds.Add(globalAssignCmd);
+ }
+ blockMap[(Block)bl] = auxNewBlock;
+ }
+ }
+
+ }
+ }
+
+ List<Cmd> cmdSeq;
+ if (headRecursion)
+ cmdSeq = new List<Cmd>();
+ else
+ {
+ CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
+ addUniqueCallAttr(si_unique_loc, callCmd);
+ si_unique_loc++;
+ cmdSeq = new List<Cmd> { callCmd };
+ }
+
+ Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy",
+ new List<Cmd>{ new AssumeCmd(Token.NoToken, Expr.False) }, new ReturnCmd(Token.NoToken));
+ Block/*!*/ block2 = new Block(Token.NoToken, block1.Label,
+ cmdSeq, new ReturnCmd(Token.NoToken));
+ impl.Blocks.Add(block1);
+ dummyBlocks.Add(block1.Label);
+
+ GotoCmd gotoCmd = source.TransferCmd as GotoCmd;
+ Contract.Assert(gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Count >= 1);
+ List<String>/*!*/ newLabels = new List<String>();
+ List<Block>/*!*/ newTargets = new List<Block>();
+ for (int i = 0; i < gotoCmd.labelTargets.Count; i++) {
+ if (gotoCmd.labelTargets[i] == header)
+ continue;
+ newTargets.Add(gotoCmd.labelTargets[i]);
+ newLabels.Add(gotoCmd.labelNames[i]);
+ }
+ newTargets.Add(block1);
+ newLabels.Add(block1.Label);
+ gotoCmd.labelNames = newLabels;
+ gotoCmd.labelTargets = newTargets;
+ blockMap[block1] = block2;
+ }
+ List<Block/*!*/>/*!*/ blocks = new List<Block/*!*/>();
+ Block exit = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ GotoCmd cmd = new GotoCmd(Token.NoToken,
+ new List<String> { cce.NonNull(blockMap[header]).Label, exit.Label },
+ new List<Block> { blockMap[header], exit });
+
+ if (detLoopExtract) //cutting the non-determinism
+ cmd = new GotoCmd(Token.NoToken,
+ new List<String> { cce.NonNull(blockMap[header]).Label },
+ new List<Block> { blockMap[header] });
+
+ Block entry;
+ List<Cmd> initCmds = new List<Cmd>();
+ if (loopHeaderToAssignCmd.ContainsKey(header)) {
+ AssignCmd assignCmd = loopHeaderToAssignCmd[header];
+ initCmds.Add(assignCmd);
+ }
+
+ entry = new Block(Token.NoToken, "entry", initCmds, cmd);
+ blocks.Add(entry);
+
+ foreach (Block/*!*/ block in blockMap.Keys) {
+ Contract.Assert(block != null);
+ Block/*!*/ newBlock = cce.NonNull(blockMap[block]);
+ GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
+ if (gotoCmd == null) {
+ newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
+ } else {
+ Contract.Assume(gotoCmd.labelNames != null && gotoCmd.labelTargets != null);
+ List<String> newLabels = new List<String>();
+ List<Block> newTargets = new List<Block>();
+ for (int i = 0; i < gotoCmd.labelTargets.Count; i++) {
+ Block target = gotoCmd.labelTargets[i];
+ if (blockMap.ContainsKey(target)) {
+ newLabels.Add(gotoCmd.labelNames[i]);
+ newTargets.Add(blockMap[target]);
+ }
+ }
+ if (newTargets.Count == 0) {
+ if (!detLoopExtract)
+ newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
+ newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
+ } else {
+ newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets);
+ }
+ }
+ blocks.Add(newBlock);
+ }
+ blocks.Add(exit);
+ Implementation loopImpl =
+ new Implementation(Token.NoToken, loopProc.Name,
+ new List<TypeVariable>(), inputs, outputs, new List<Variable>(), blocks);
+ loopImpl.Proc = loopProc;
+ loopImpls.Add(loopImpl);
+
+ // Make a (shallow) copy of the header before splitting it
+ Block origHeader = new Block(header.tok, header.Label, header.Cmds, header.TransferCmd);
+
+ // Finally, add call to the loop in the containing procedure
+ string lastIterBlockName = header.Label + "_last";
+ Block lastIterBlock = new Block(Token.NoToken, lastIterBlockName, header.Cmds, header.TransferCmd);
+ newBlocksCreated[header] = lastIterBlock;
+ header.Cmds = new List<Cmd> { loopHeaderToCallCmd1[header] };
+ header.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { lastIterBlockName }, new List<Block> { lastIterBlock });
+ impl.Blocks.Add(lastIterBlock);
+ blockMap[origHeader] = blockMap[header];
+ blockMap.Remove(header);
+
+ Contract.Assert(fullMap[impl.Name][header.Label] == header);
+ fullMap[impl.Name][header.Label] = origHeader;
+
+ foreach (Block block in blockMap.Keys)
+ {
+ // Don't add dummy blocks to the map
+ if (dummyBlocks.Contains(blockMap[block].Label)) continue;
+
+ // Following two statements are for nested loops: compose map
+ if (!fullMap[impl.Name].ContainsKey(block.Label)) continue;
+ var target = fullMap[impl.Name][block.Label];
+
+ AddToFullMap(fullMap, loopProc.Name, blockMap[block].Label, target);
+ }
+
+ fullMap[impl.Name].Remove(header.Label);
+ fullMap[impl.Name][lastIterBlockName] = origHeader;
+ }
+ }
+
+ private void addUniqueCallAttr(int val, CallCmd cmd)
+ {
+ var a = new List<object>();
+ a.Add(new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(val)));
+
+ cmd.Attributes = new QKeyValue(Token.NoToken, "si_unique_call", a, cmd.Attributes);
+ }
+
+ private void AddToFullMap(Dictionary<string, Dictionary<string, Block>> fullMap, string procName, string blockName, Block block)
+ {
+ if (!fullMap.ContainsKey(procName))
+ fullMap[procName] = new Dictionary<string, Block>();
+ fullMap[procName][blockName] = block;
+ }
+
+ public static Graph<Implementation> BuildCallGraph(Program program) {
+ Graph<Implementation> callGraph = new Graph<Implementation>();
+ Dictionary<Procedure, HashSet<Implementation>> procToImpls = new Dictionary<Procedure, HashSet<Implementation>>();
+ foreach (var proc in program.Procedures) {
+ procToImpls[proc] = new HashSet<Implementation>();
+ }
+ foreach (var impl in program.Implementations) {
+ if (impl.SkipVerification) continue;
+ callGraph.AddSource(impl);
+ procToImpls[impl.Proc].Add(impl);
+ }
+ foreach (var impl in program.Implementations) {
+ if (impl.SkipVerification) continue;
+ foreach (Block b in impl.Blocks) {
+ foreach (Cmd c in b.Cmds) {
+ CallCmd cc = c as CallCmd;
+ if (cc == null) continue;
+ foreach (Implementation callee in procToImpls[cc.Proc]) {
+ callGraph.AddEdge(impl, callee);
+ }
+ }
+ }
+ }
+ return callGraph;
+ }
+
+ public static Graph<Block/*!*/>/*!*/ GraphFromImpl(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<Graph<Block>>().Nodes));
+ Contract.Ensures(Contract.Result<Graph<Block>>() != null);
+
+ Graph<Block/*!*/> g = new Graph<Block/*!*/>();
+ g.AddSource(impl.Blocks[0]); // there is always at least one node in the graph
+
+ foreach (Block b in impl.Blocks) {
+ Contract.Assert(b != null);
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null) {
+ foreach (Block/*!*/ dest in cce.NonNull(gtc.labelTargets)) {
+ Contract.Assert(dest != null);
+ g.AddEdge(b, dest);
+ }
+ }
+ }
+ return g;
+ }
+
+ public class IrreducibleLoopException : Exception {}
+
+ public Graph<Block> ProcessLoops(Implementation impl) {
+ while (true) {
+ impl.PruneUnreachableBlocks();
+ impl.ComputePredecessorsForBlocks();
+ Graph<Block/*!*/>/*!*/ g = GraphFromImpl(impl);
+ g.ComputeLoops();
+ if (g.Reducible) {
+ return g;
+ }
+ throw new IrreducibleLoopException();
+#if USED_CODE
+ System.Diagnostics.Debug.Assert(g.SplitCandidates.Count > 0);
+ Block splitCandidate = null;
+ foreach (Block b in g.SplitCandidates) {
+ if (b.Predecessors.Length > 1) {
+ splitCandidate = b;
+ break;
+ }
+ }
+ System.Diagnostics.Debug.Assert(splitCandidate != null);
+ int count = 0;
+ foreach (Block b in splitCandidate.Predecessors) {
+ GotoCmd gotoCmd = (GotoCmd)b.TransferCmd;
+ gotoCmd.labelNames.Remove(splitCandidate.Label);
+ gotoCmd.labelTargets.Remove(splitCandidate);
+
+ CodeCopier codeCopier = new CodeCopier(new Hashtable(), new Hashtable());
+ List<Cmd> newCmdSeq = codeCopier.CopyCmdSeq(splitCandidate.Cmds);
+ TransferCmd newTransferCmd;
+ GotoCmd splitGotoCmd = splitCandidate.TransferCmd as GotoCmd;
+ if (splitGotoCmd == null) {
+ newTransferCmd = new ReturnCmd(splitCandidate.tok);
+ }
+ else {
+ List<String> newLabelNames = new List<String>();
+ newLabelNames.AddRange(splitGotoCmd.labelNames);
+ List<Block> newLabelTargets = new List<Block>();
+ newLabelTargets.AddRange(splitGotoCmd.labelTargets);
+ newTransferCmd = new GotoCmd(splitCandidate.tok, newLabelNames, newLabelTargets);
+ }
+ Block copy = new Block(splitCandidate.tok, splitCandidate.Label + count++, newCmdSeq, newTransferCmd);
+
+ impl.Blocks.Add(copy);
+ gotoCmd.AddTarget(copy);
+ }
+#endif
+ }
+ }
+
+ public Dictionary<string, Dictionary<string, Block>> ExtractLoops()
+ {
+ HashSet<string> procsWithIrreducibleLoops = null;
+ return ExtractLoops(out procsWithIrreducibleLoops);
+ }
+
+ public Dictionary<string, Dictionary<string, Block>> ExtractLoops(out HashSet<string> procsWithIrreducibleLoops)
+ {
+ procsWithIrreducibleLoops = new HashSet<string>();
+ List<Implementation/*!*/>/*!*/ loopImpls = new List<Implementation/*!*/>();
+ Dictionary<string, Dictionary<string, Block>> fullMap = new Dictionary<string, Dictionary<string, Block>>();
+ foreach (var impl in this.Implementations)
+ {
+ if (impl.Blocks != null && impl.Blocks.Count > 0)
+ {
+ try
+ {
+ Graph<Block> g = ProcessLoops(impl);
+ CreateProceduresForLoops(impl, g, loopImpls, fullMap);
+ }
+ catch (IrreducibleLoopException)
+ {
+ System.Diagnostics.Debug.Assert(!fullMap.ContainsKey(impl.Name));
+ fullMap[impl.Name] = null;
+ procsWithIrreducibleLoops.Add(impl.Name);
+
+ if (CommandLineOptions.Clo.ExtractLoopsUnrollIrreducible)
+ {
+ // statically unroll loops in this procedure
+
+ // First, build a map of the current blocks
+ var origBlocks = new Dictionary<string, Block>();
+ foreach (var blk in impl.Blocks) origBlocks.Add(blk.Label, blk);
+
+ // unroll
+ Block start = impl.Blocks[0];
+ impl.Blocks = LoopUnroll.UnrollLoops(start, CommandLineOptions.Clo.RecursionBound, false);
+
+ // Now construct the "map back" information
+ // Resulting block label -> original block
+ var blockMap = new Dictionary<string, Block>();
+ foreach (var blk in impl.Blocks)
+ {
+ var sl = LoopUnroll.sanitizeLabel(blk.Label);
+ if (sl == blk.Label) blockMap.Add(blk.Label, blk);
+ else
+ {
+ Contract.Assert(origBlocks.ContainsKey(sl));
+ blockMap.Add(blk.Label, origBlocks[sl]);
+ }
+ }
+ fullMap[impl.Name] = blockMap;
+ }
+ }
+ }
+ }
+ foreach (Implementation/*!*/ loopImpl in loopImpls)
+ {
+ Contract.Assert(loopImpl != null);
+ AddTopLevelDeclaration(loopImpl);
+ AddTopLevelDeclaration(loopImpl.Proc);
+ }
+ return fullMap;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitProgram(this);
+ }
+
+ int extractedFunctionCount;
+ public string FreshExtractedFunctionName()
+ {
+ var c = System.Threading.Interlocked.Increment(ref extractedFunctionCount);
+ return string.Format("##extracted_function##{0}", c);
+ }
+
+ private int invariantGenerationCounter = 0;
+
+ public Constant MakeExistentialBoolean() {
+ Constant ExistentialBooleanConstant = new Constant(Token.NoToken, new TypedIdent(tok, "_b" + invariantGenerationCounter, Microsoft.Boogie.Type.Bool), false);
+ invariantGenerationCounter++;
+ ExistentialBooleanConstant.AddAttribute("existential", new object[] { Expr.True });
+ AddTopLevelDeclaration(ExistentialBooleanConstant);
+ return ExistentialBooleanConstant;
+ }
+
+ public PredicateCmd CreateCandidateInvariant(Expr e, string tag = null) {
+ Constant ExistentialBooleanConstant = MakeExistentialBoolean();
+ IdentifierExpr ExistentialBoolean = new IdentifierExpr(Token.NoToken, ExistentialBooleanConstant);
+ PredicateCmd invariant = new AssertCmd(Token.NoToken, Expr.Imp(ExistentialBoolean, e));
+ if (tag != null)
+ invariant.Attributes = new QKeyValue(Token.NoToken, "tag", new List<object>(new object[] { tag }), null);
+ return invariant;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Declarations
+
+ [ContractClass(typeof(DeclarationContracts))]
+ public abstract class Declaration : Absy {
+ public QKeyValue Attributes;
+
+ public Declaration(IToken tok)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ }
+
+ protected void EmitAttributes(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Emit(stream);
+ stream.Write(" ");
+ }
+ }
+
+ protected void ResolveAttributes(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Resolve(rc);
+ }
+ }
+
+ protected void TypecheckAttributes(TypecheckingContext rc) {
+ Contract.Requires(rc != null);
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Typecheck(rc);
+ }
+ }
+
+ /// <summary>
+ /// If the declaration has an attribute {:name} or {:name true}, then set "result" to "true" and return "true".
+ /// If the declaration has an attribute {:name false}, then set "result" to "false" and return "true".
+ /// Otherwise, return "false" and leave "result" unchanged (which gives the caller an easy way to indicate
+ /// a default value if the attribute is not mentioned).
+ /// If there is more than one attribute called :name, then the last attribute rules.
+ /// </summary>
+ public bool CheckBooleanAttribute(string name, ref bool result) {
+ Contract.Requires(name != null);
+ var kv = FindAttribute(name);
+ if (kv != null) {
+ if (kv.Params.Count == 0) {
+ result = true;
+ return true;
+ } else if (kv.Params.Count == 1) {
+ var lit = kv.Params[0] as LiteralExpr;
+ if (lit != null && lit.isBool) {
+ result = lit.asBool;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Find and return the last occurrence of an attribute with the name "name", if any. If none, return null.
+ /// </summary>
+ public QKeyValue FindAttribute(string name) {
+ Contract.Requires(name != null);
+ QKeyValue res = null;
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ res = kv;
+ }
+ }
+ return res;
+ }
+
+ // Look for {:name expr} in list of attributes.
+ public Expr FindExprAttribute(string name) {
+ Contract.Requires(name != null);
+ Expr res = null;
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
+ res = (Expr)kv.Params[0];
+ }
+ }
+ }
+ return res;
+ }
+
+ // Look for {:name string} in list of attributes.
+ public string FindStringAttribute(string name) {
+ Contract.Requires(name != null);
+ return QKeyValue.FindStringAttribute(this.Attributes, name);
+ }
+
+ // Look for {:name N} or {:name N} in list of attributes. Return result in 'result'
+ // (which is not touched if there is no attribute specified).
+ //
+ // Returns false is there was an error processing the flag, true otherwise.
+ public bool CheckIntAttribute(string name, ref int result) {
+ Contract.Requires(name != null);
+ Expr expr = FindExprAttribute(name);
+ if (expr != null) {
+ if (expr is LiteralExpr && ((LiteralExpr)expr).isBigNum) {
+ result = ((LiteralExpr)expr).asBigNum.ToInt;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void AddAttribute(string name, params object[] vals) {
+ Contract.Requires(name != null);
+ QKeyValue kv;
+ for (kv = this.Attributes; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ kv.AddParams(vals);
+ break;
+ }
+ }
+ if (kv == null) {
+ Attributes = new QKeyValue(tok, name, new List<object/*!*/>(vals), Attributes);
+ }
+ }
+
+ public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
+ public abstract void Register(ResolutionContext/*!*/ rc);
+
+ /// <summary>
+ /// Compute the strongly connected components of the declaration.
+ /// By default, it does nothing
+ /// </summary>
+ public virtual void ComputeStronglyConnectedComponents() { /* Does nothing */
+ }
+
+ /// <summary>
+ /// Reset the abstract stated computed before
+ /// </summary>
+ public virtual void ResetAbstractInterpretationState() { /* does nothing */
+ }
+ }
+ [ContractClassFor(typeof(Declaration))]
+ public abstract class DeclarationContracts : Declaration {
+ public DeclarationContracts() :base(null){
+ }
+ public override void Register(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ throw new NotImplementedException();
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public class Axiom : Declaration {
+ private Expr/*!*/ expression;
+
+ public Expr Expr {
+ get {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return this.expression;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.expression = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ExprInvariant() {
+ Contract.Invariant(this.expression != null);
+ }
+
+ public string Comment;
+
+ public Axiom(IToken tok, Expr expr)
+ : this(tok, expr, null) {
+ Contract.Requires(expr != null);
+ Contract.Requires(tok != null);
+ }
+
+ public Axiom(IToken/*!*/ tok, Expr/*!*/ expr, string comment)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ this.expression = expr;
+ Comment = comment;
+ }
+
+ public Axiom(IToken tok, Expr expr, string comment, QKeyValue kv)
+ : this(tok, expr, comment) {
+ Contract.Requires(expr != null);
+ Contract.Requires(tok != null);
+ this.Attributes = kv;
+ }
+
+ public bool DependenciesCollected { get; set; }
+
+ ISet<Function> functionDependencies;
+
+ public ISet<Function> FunctionDependencies
+ {
+ get { return functionDependencies; }
+ }
+
+ public void AddFunctionDependency(Function function)
+ {
+ Contract.Requires(function != null);
+
+ if (functionDependencies == null)
+ {
+ functionDependencies = new HashSet<Function>();
+ }
+ functionDependencies.Add(function);
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "axiom ");
+ EmitAttributes(stream);
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddAxiom(this);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ ResolveAttributes(rc);
+ rc.StateMode = ResolutionContext.State.StateLess;
+ Expr.Resolve(rc);
+ rc.StateMode = ResolutionContext.State.Single;
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(tc);
+ Expr.Typecheck(tc);
+ Contract.Assert(Expr.Type != null); // follows from postcondition of Expr.Typecheck
+ if (!Expr.Type.Unify(Type.Bool)) {
+ tc.Error(this, "axioms must be of type bool");
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitAxiom(this);
+ }
+ }
+
+ public abstract class NamedDeclaration : Declaration {
+ private string/*!*/ name;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(name != null);
+ }
+
+ public string/*!*/ Name {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return this.name;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.name = value;
+ }
+ }
+
+ public int TimeLimit
+ {
+ get
+ {
+ int tl = CommandLineOptions.Clo.ProverKillTime;
+ CheckIntAttribute("timeLimit", ref tl);
+ return tl;
+ }
+ }
+
+ public NamedDeclaration(IToken/*!*/ tok, string/*!*/ name)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ this.name = name;
+ }
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return cce.NonNull(Name);
+ }
+ }
+
+ public class TypeCtorDecl : NamedDeclaration {
+ public readonly int Arity;
+
+ public TypeCtorDecl(IToken/*!*/ tok, string/*!*/ name, int Arity)
+ : base(tok, name) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ this.Arity = Arity;
+ }
+ public TypeCtorDecl(IToken/*!*/ tok, string/*!*/ name, int Arity, QKeyValue kv)
+ : base(tok, name) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ this.Arity = Arity;
+ this.Attributes = kv;
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "type ");
+ EmitAttributes(stream);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
+ for (int i = 0; i < Arity; ++i)
+ stream.Write(" _");
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddType(this);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ ResolveAttributes(rc);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(tc);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTypeCtorDecl(this);
+ }
+ }
+
+ public class TypeSynonymDecl : NamedDeclaration {
+ private List<TypeVariable>/*!*/ typeParameters;
+
+ public List<TypeVariable> TypeParameters {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+ return this.typeParameters;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.typeParameters = value;
+ }
+ }
+
+ private Type/*!*/ body;
+
+ public Type Body {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.body;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.body = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this.body != null);
+ Contract.Invariant(this.typeParameters != null);
+ }
+
+ public TypeSynonymDecl(IToken/*!*/ tok, string/*!*/ name,
+ List<TypeVariable>/*!*/ typeParams, Type/*!*/ body)
+ : base(tok, name) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(body != null);
+ this.typeParameters = typeParams;
+ this.body = body;
+ }
+ public TypeSynonymDecl(IToken/*!*/ tok, string/*!*/ name,
+ List<TypeVariable>/*!*/ typeParams, Type/*!*/ body, QKeyValue kv)
+ : base(tok, name) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(body != null);
+ this.typeParameters = typeParams;
+ this.body = body;
+ this.Attributes = kv;
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "type ");
+ EmitAttributes(stream);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
+ if (TypeParameters.Count > 0)
+ stream.Write(" ");
+ TypeParameters.Emit(stream, " ");
+ stream.Write(" = ");
+ Body.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddType(this);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ ResolveAttributes(rc);
+
+ int previousState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable/*!*/ v in TypeParameters) {
+ Contract.Assert(v != null);
+ rc.AddTypeBinder(v);
+ }
+ Body = Body.ResolveType(rc);
+ } finally {
+ rc.TypeBinderState = previousState;
+ }
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(tc);
+ }
+
+ public static void ResolveTypeSynonyms(List<TypeSynonymDecl/*!*/>/*!*/ synonymDecls, ResolutionContext/*!*/ rc) {
+ Contract.Requires(cce.NonNullElements(synonymDecls));
+ Contract.Requires(rc != null);
+ // then discover all dependencies between type synonyms
+ IDictionary<TypeSynonymDecl/*!*/, List<TypeSynonymDecl/*!*/>/*!*/>/*!*/ deps =
+ new Dictionary<TypeSynonymDecl/*!*/, List<TypeSynonymDecl/*!*/>/*!*/>();
+ foreach (TypeSynonymDecl/*!*/ decl in synonymDecls) {
+ Contract.Assert(decl != null);
+ List<TypeSynonymDecl/*!*/>/*!*/ declDeps = new List<TypeSynonymDecl/*!*/>();
+ FindDependencies(decl.Body, declDeps, rc);
+ deps.Add(decl, declDeps);
+ }
+
+ List<TypeSynonymDecl/*!*/>/*!*/ resolved = new List<TypeSynonymDecl/*!*/>();
+
+ int unresolved = synonymDecls.Count - resolved.Count;
+ while (unresolved > 0) {
+ foreach (TypeSynonymDecl/*!*/ decl in synonymDecls) {
+ Contract.Assert(decl != null);
+ if (!resolved.Contains(decl) &&
+ deps[decl].All(d => resolved.Contains(d))) {
+ decl.Resolve(rc);
+ resolved.Add(decl);
+ }
+ }
+
+ int newUnresolved = synonymDecls.Count - resolved.Count;
+ if (newUnresolved < unresolved) {
+ // we are making progress
+ unresolved = newUnresolved;
+ } else {
+ // there have to be cycles in the definitions
+ foreach (TypeSynonymDecl/*!*/ decl in synonymDecls) {
+ Contract.Assert(decl != null);
+ if (!resolved.Contains(decl)) {
+ rc.Error(decl,
+ "type synonym could not be resolved because of cycles: {0}" +
+ " (replacing body with \"bool\" to continue resolving)",
+ decl.Name);
+
+ // we simply replace the bodies of all remaining type
+ // synonyms with "bool" so that resolution can continue
+ decl.Body = Type.Bool;
+ decl.Resolve(rc);
+ }
+ }
+
+ unresolved = 0;
+ }
+ }
+ }
+
+ // determine a list of all type synonyms that occur in "type"
+ private static void FindDependencies(Type/*!*/ type, List<TypeSynonymDecl/*!*/>/*!*/ deps, ResolutionContext/*!*/ rc) {
+ Contract.Requires(type != null);
+ Contract.Requires(cce.NonNullElements(deps));
+ Contract.Requires(rc != null);
+ if (type.IsVariable || type.IsBasic) {
+ // nothing
+ } else if (type.IsUnresolved) {
+ UnresolvedTypeIdentifier/*!*/ unresType = type.AsUnresolved;
+ Contract.Assert(unresType != null);
+ TypeSynonymDecl dep = rc.LookUpTypeSynonym(unresType.Name);
+ if (dep != null)
+ deps.Add(dep);
+ foreach (Type/*!*/ subtype in unresType.Arguments) {
+ Contract.Assert(subtype != null);
+ FindDependencies(subtype, deps, rc);
+ }
+ } else if (type.IsMap) {
+ MapType/*!*/ mapType = type.AsMap;
+ Contract.Assert(mapType != null);
+ foreach (Type/*!*/ subtype in mapType.Arguments) {
+ Contract.Assert(subtype != null);
+ FindDependencies(subtype, deps, rc);
+ }
+ FindDependencies(mapType.Result, deps, rc);
+ } else if (type.IsCtor) {
+ // this can happen because we allow types to be resolved multiple times
+ CtorType/*!*/ ctorType = type.AsCtor;
+ Contract.Assert(ctorType != null);
+ foreach (Type/*!*/ subtype in ctorType.Arguments) {
+ Contract.Assert(subtype != null);
+ FindDependencies(subtype, deps, rc);
+ }
+ } else {
+ System.Diagnostics.Debug.Fail("Did not expect this type during resolution: "
+ + type);
+ }
+ }
+
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTypeSynonymDecl(this);
+ }
+ }
+
+ public abstract class Variable : NamedDeclaration {
+ private TypedIdent/*!*/ typedIdent;
+
+ public TypedIdent TypedIdent {
+ get {
+ Contract.Ensures(Contract.Result<TypedIdent>() != null);
+ return this.typedIdent;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.typedIdent = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this.typedIdent != null);
+ }
+
+ public Variable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent)
+ : base(tok, typedIdent.Name) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ this.typedIdent = typedIdent;
+ }
+
+ public Variable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent, QKeyValue kv)
+ : base(tok, typedIdent.Name) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ this.typedIdent = typedIdent;
+ this.Attributes = kv;
+ }
+
+ public abstract bool IsMutable {
+ get;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "var ");
+ EmitVitals(stream, level, true);
+ stream.WriteLine(";");
+ }
+ public void EmitVitals(TokenTextWriter stream, int level, bool emitAttributes) {
+ Contract.Requires(stream != null);
+ if (emitAttributes) {
+ EmitAttributes(stream);
+ }
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds && this.TypedIdent.HasName) {
+ stream.Write("h{0}^^", this.GetHashCode()); // the idea is that this will prepend the name printed by TypedIdent.Emit
+ }
+ this.TypedIdent.Emit(stream);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ this.TypedIdent.Resolve(rc);
+ }
+ public void ResolveWhere(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ if (QKeyValue.FindBoolAttribute(Attributes, "assumption") && this.TypedIdent.WhereExpr != null)
+ {
+ rc.Error(tok, "assumption variable may not be declared with a where clause");
+ }
+ if (this.TypedIdent.WhereExpr != null) {
+ this.TypedIdent.WhereExpr.Resolve(rc);
+ }
+ ResolveAttributes(rc);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(tc);
+ this.TypedIdent.Typecheck(tc);
+ if (QKeyValue.FindBoolAttribute(Attributes, "assumption") && !this.TypedIdent.Type.IsBool)
+ {
+ tc.Error(tok, "assumption variable must be of type 'bool'");
+ }
+ }
+ }
+
+ public class VariableComparer : IComparer {
+ public int Compare(object a, object b) {
+ Variable A = a as Variable;
+ Variable B = b as Variable;
+ if (A == null || B == null) {
+ throw new ArgumentException("VariableComparer works only on objects of type Variable");
+ }
+ return cce.NonNull(A.Name).CompareTo(B.Name);
+ }
+ }
+
+ // class to specify the <:-parents of the values of constants
+ public class ConstantParent {
+ public readonly IdentifierExpr/*!*/ Parent;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Parent != null);
+ }
+
+ // if true, the sub-dag underneath this constant-parent edge is
+ // disjoint from all other unique sub-dags
+ public readonly bool Unique;
+
+ public ConstantParent(IdentifierExpr parent, bool unique) {
+ Contract.Requires(parent != null);
+ Parent = parent;
+ Unique = unique;
+ }
+ }
+
+ public class Constant : Variable {
+ // when true, the value of this constant is meant to be distinct
+ // from all other constants.
+ public readonly bool Unique;
+
+ // the <:-parents of the value of this constant. If the field is
+ // null, no information about the parents is provided, which means
+ // that the parental situation is unconstrained.
+ public readonly ReadOnlyCollection<ConstantParent/*!*/> Parents;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(Parents, true));
+ }
+
+ // if true, it is assumed that the immediate <:-children of the
+ // value of this constant are completely specified
+ public readonly bool ChildrenComplete;
+
+ public Constant(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent)
+ : base(tok, typedIdent) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(typedIdent.Name != null && (!typedIdent.HasName || typedIdent.Name.Length > 0));
+ Contract.Requires(typedIdent.WhereExpr == null);
+ this.Unique = true;
+ this.Parents = null;
+ this.ChildrenComplete = false;
+ }
+ public Constant(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent, bool unique)
+ : base(tok, typedIdent) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(typedIdent.Name != null && typedIdent.Name.Length > 0);
+ Contract.Requires(typedIdent.WhereExpr == null);
+ this.Unique = unique;
+ this.Parents = null;
+ this.ChildrenComplete = false;
+ }
+ public Constant(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent,
+ bool unique,
+ IEnumerable<ConstantParent/*!*/> parents, bool childrenComplete,
+ QKeyValue kv)
+ : base(tok, typedIdent, kv) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(cce.NonNullElements(parents, true));
+ Contract.Requires(typedIdent.Name != null && typedIdent.Name.Length > 0);
+ Contract.Requires(typedIdent.WhereExpr == null);
+ this.Unique = unique;
+ this.Parents = parents == null ? null : new ReadOnlyCollection<ConstantParent>(parents.ToList());
+ this.ChildrenComplete = childrenComplete;
+ }
+ public override bool IsMutable {
+ get {
+ return false;
+ }
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "const ");
+ EmitAttributes(stream);
+ if (this.Unique) {
+ stream.Write(this, level, "unique ");
+ }
+ EmitVitals(stream, level, false);
+
+ if (Parents != null || ChildrenComplete) {
+ stream.Write(this, level, " extends");
+ string/*!*/ sep = " ";
+ foreach (ConstantParent/*!*/ p in cce.NonNull(Parents)) {
+ Contract.Assert(p != null);
+ stream.Write(this, level, sep);
+ sep = ", ";
+ if (p.Unique)
+ stream.Write(this, level, "unique ");
+ p.Parent.Emit(stream);
+ }
+ if (ChildrenComplete)
+ stream.Write(this, level, " complete");
+ }
+
+ stream.WriteLine(";");
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddVariable(this, true);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ base.Resolve(rc);
+ if (Parents != null) {
+ foreach (ConstantParent/*!*/ p in Parents) {
+ Contract.Assert(p != null);
+ p.Parent.Resolve(rc);
+ if (p.Parent.Decl != null && !(p.Parent.Decl is Constant))
+ rc.Error(p.Parent, "the parent of a constant has to be a constant");
+ if (this.Equals(p.Parent.Decl))
+ rc.Error(p.Parent, "constant cannot be its own parent");
+ }
+ }
+
+ // check that no parent occurs twice
+ // (could be optimised)
+ if (Parents != null) {
+ for (int i = 0; i < Parents.Count; ++i) {
+ if (Parents[i].Parent.Decl != null) {
+ for (int j = i + 1; j < Parents.Count; ++j) {
+ if (Parents[j].Parent.Decl != null &&
+ cce.NonNull(Parents[i].Parent.Decl).Equals(Parents[j].Parent.Decl))
+ rc.Error(Parents[j].Parent,
+ "{0} occurs more than once as parent",
+ Parents[j].Parent.Decl);
+ }
+ }
+ }
+ }
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ base.Typecheck(tc);
+
+ if (Parents != null) {
+ foreach (ConstantParent/*!*/ p in Parents) {
+ Contract.Assert(p != null);
+ p.Parent.Typecheck(tc);
+ if (!cce.NonNull(p.Parent.Decl).TypedIdent.Type.Unify(this.TypedIdent.Type))
+ tc.Error(p.Parent,
+ "parent of constant has incompatible type ({0} instead of {1})",
+ p.Parent.Decl.TypedIdent.Type, this.TypedIdent.Type);
+ }
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitConstant(this);
+ }
+ }
+ public class GlobalVariable : Variable {
+ public GlobalVariable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent)
+ : base(tok, typedIdent) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ }
+ public GlobalVariable(IToken/*!*/ tok, TypedIdent/*!*/ typedIdent, QKeyValue kv)
+ : base(tok, typedIdent, kv) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent != null);
+ }
+ public override bool IsMutable {
+ get {
+ return true;
+ }
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddVariable(this, true);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitGlobalVariable(this);
+ }
+ }
+ public class Formal : Variable {
+ public bool InComing;
+ public Formal(IToken tok, TypedIdent typedIdent, bool incoming, QKeyValue kv)
+ : base(tok, typedIdent, kv) {
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(tok != null);
+ InComing = incoming;
+ }
+ public Formal(IToken tok, TypedIdent typedIdent, bool incoming)
+ : this(tok, typedIdent, incoming, null) {
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(tok != null);
+ }
+ public override bool IsMutable {
+ get {
+ return !InComing;
+ }
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddVariable(this, false);
+ }
+
+ /// <summary>
+ /// Given a sequence of Formal declarations, returns sequence of Formals like the given one but without where clauses
+ /// and without any attributes.
+ /// The Type of each Formal is cloned.
+ /// </summary>
+ public static List<Variable> StripWhereClauses(List<Variable> w) {
+ Contract.Requires(w != null);
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ List<Variable> s = new List<Variable>();
+ foreach (Variable/*!*/ v in w) {
+ Contract.Assert(v != null);
+ Formal f = (Formal)v;
+ TypedIdent ti = f.TypedIdent;
+ s.Add(new Formal(f.tok, new TypedIdent(ti.tok, ti.Name, ti.Type.CloneUnresolved()), f.InComing, null));
+ }
+ return s;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitFormal(this);
+ }
+ }
+ public class LocalVariable : Variable {
+ public LocalVariable(IToken tok, TypedIdent typedIdent, QKeyValue kv)
+ : base(tok, typedIdent, kv) {
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(tok != null);
+ }
+ public LocalVariable(IToken tok, TypedIdent typedIdent)
+ : base(tok, typedIdent, null) {
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(tok != null);
+ }
+ public override bool IsMutable {
+ get {
+ return true;
+ }
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddVariable(this, false);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitLocalVariable(this);
+ }
+ }
+ public class Incarnation : LocalVariable {
+ public int incarnationNumber;
+ public readonly Variable OriginalVariable;
+ public Incarnation(Variable/*!*/ var, int i) :
+ base(
+ var.tok,
+ new TypedIdent(var.TypedIdent.tok, var.TypedIdent.Name + "@" + i, var.TypedIdent.Type)
+ ) {
+ Contract.Requires(var != null);
+ incarnationNumber = i;
+ OriginalVariable = var;
+ }
+
+ }
+ public class BoundVariable : Variable {
+ public BoundVariable(IToken tok, TypedIdent typedIdent)
+ : base(tok, typedIdent) {
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent.WhereExpr == null);
+ }
+ public BoundVariable(IToken tok, TypedIdent typedIdent, QKeyValue kv)
+ : base(tok, typedIdent, kv) {
+ Contract.Requires(typedIdent != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(typedIdent.WhereExpr == null);
+ }
+ public override bool IsMutable {
+ get {
+ return false;
+ }
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddVariable(this, false);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBoundVariable(this);
+ }
+ }
+
+ public abstract class DeclWithFormals : NamedDeclaration {
+ public List<TypeVariable>/*!*/ TypeParameters;
+
+ private /*readonly--except in StandardVisitor*/ List<Variable>/*!*/ inParams, outParams;
+
+ public List<Variable>/*!*/ InParams {
+ get {
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ return this.inParams;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.inParams = value;
+ }
+ }
+
+ public List<Variable>/*!*/ OutParams
+ {
+ get {
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ return this.outParams;
+ }
+ set {
+ Contract.Requires(value != null);
+ this.outParams = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(TypeParameters != null);
+ Contract.Invariant(this.inParams != null);
+ Contract.Invariant(this.outParams != null);
+ }
+
+ public DeclWithFormals(IToken tok, string name, List<TypeVariable> typeParams,
+ List<Variable> inParams, List<Variable> outParams)
+ : base(tok, name) {
+ Contract.Requires(inParams != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ this.TypeParameters = typeParams;
+ this.inParams = inParams;
+ this.outParams = outParams;
+ }
+
+ protected DeclWithFormals(DeclWithFormals that)
+ : base(that.tok, cce.NonNull(that.Name)) {
+ Contract.Requires(that != null);
+ this.TypeParameters = that.TypeParameters;
+ this.inParams = cce.NonNull(that.InParams);
+ this.outParams = cce.NonNull(that.OutParams);
+ }
+
+ public byte[] MD5Checksum_;
+ public byte[] MD5Checksum
+ {
+ get
+ {
+ if (MD5Checksum_ == null)
+ {
+ var c = Checksum;
+ if (c != null)
+ {
+ MD5Checksum_ = System.Security.Cryptography.MD5.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(c));
+ }
+ }
+ return MD5Checksum_;
+ }
+ }
+
+ public byte[] MD5DependencyChecksum_;
+ public byte[] MD5DependencyChecksum
+ {
+ get
+ {
+ Contract.Requires(DependenciesCollected);
+
+ if (MD5DependencyChecksum_ == null && MD5Checksum != null)
+ {
+ var c = MD5Checksum;
+ var transFuncDeps = new HashSet<Function>();
+ if (procedureDependencies != null)
+ {
+ foreach (var p in procedureDependencies)
+ {
+ if (p.FunctionDependencies != null)
+ {
+ foreach (var f in p.FunctionDependencies)
+ {
+ transFuncDeps.Add(f);
+ }
+ }
+ var pc = p.MD5Checksum;
+ if (pc == null) { return null; }
+ c = ChecksumHelper.CombineChecksums(c, pc, true);
+ }
+ }
+ if (FunctionDependencies != null)
+ {
+ foreach (var f in FunctionDependencies)
+ {
+ transFuncDeps.Add(f);
+ }
+ }
+ var q = new Queue<Function>(transFuncDeps);
+ while (q.Any())
+ {
+ var f = q.Dequeue();
+ var fc = f.MD5Checksum;
+ if (fc == null) { return null; }
+ c = ChecksumHelper.CombineChecksums(c, fc, true);
+ if (f.FunctionDependencies != null)
+ {
+ foreach (var d in f.FunctionDependencies)
+ {
+ if (!transFuncDeps.Contains(d))
+ {
+ transFuncDeps.Add(d);
+ q.Enqueue(d);
+ }
+ }
+ }
+ }
+ MD5DependencyChecksum_ = c;
+ }
+ return MD5DependencyChecksum_;
+ }
+ }
+
+ public string Checksum
+ {
+ get
+ {
+ return FindStringAttribute("checksum");
+ }
+ }
+
+ string dependencyChecksum;
+ public string DependencyChecksum
+ {
+ get
+ {
+ if (dependencyChecksum == null && DependenciesCollected && MD5DependencyChecksum != null)
+ {
+ dependencyChecksum = BitConverter.ToString(MD5DependencyChecksum);
+ }
+ return dependencyChecksum;
+ }
+ }
+
+ public bool DependenciesCollected { get; set; }
+
+ ISet<Procedure> procedureDependencies;
+
+ public ISet<Procedure> ProcedureDependencies
+ {
+ get { return procedureDependencies; }
+ }
+
+ public void AddProcedureDependency(Procedure procedure)
+ {
+ Contract.Requires(procedure != null);
+
+ if (procedureDependencies == null)
+ {
+ procedureDependencies = new HashSet<Procedure>();
+ }
+ procedureDependencies.Add(procedure);
+ }
+
+ ISet<Function> functionDependencies;
+
+ public ISet<Function> FunctionDependencies
+ {
+ get { return functionDependencies; }
+ }
+
+ public void AddFunctionDependency(Function function)
+ {
+ Contract.Requires(function != null);
+
+ if (functionDependencies == null)
+ {
+ functionDependencies = new HashSet<Function>();
+ }
+ functionDependencies.Add(function);
+ }
+
+ public bool SignatureEquals(DeclWithFormals other)
+ {
+ Contract.Requires(other != null);
+
+ string sig = null;
+ string otherSig = null;
+ using (var strWr = new System.IO.StringWriter())
+ using (var tokTxtWr = new TokenTextWriter("<no file>", strWr, false, false))
+ {
+ EmitSignature(tokTxtWr, this is Function);
+ sig = strWr.ToString();
+ }
+
+ using (var otherStrWr = new System.IO.StringWriter())
+ using (var otherTokTxtWr = new TokenTextWriter("<no file>", otherStrWr, false, false))
+ {
+ EmitSignature(otherTokTxtWr, other is Function);
+ otherSig = otherStrWr.ToString();
+ }
+ return sig == otherSig;
+ }
+
+ protected void EmitSignature(TokenTextWriter stream, bool shortRet) {
+ Contract.Requires(stream != null);
+ Type.EmitOptionalTypeParams(stream, TypeParameters);
+ stream.Write("(");
+ stream.push();
+ InParams.Emit(stream, true);
+ stream.Write(")");
+ stream.sep();
+
+ if (shortRet) {
+ Contract.Assert(OutParams.Count == 1);
+ stream.Write(" : ");
+ cce.NonNull(OutParams[0]).TypedIdent.Type.Emit(stream);
+ } else if (OutParams.Count > 0) {
+ stream.Write(" returns (");
+ OutParams.Emit(stream, true);
+ stream.Write(")");
+ }
+ stream.pop();
+ }
+
+ // Register all type parameters at the resolution context
+ protected void RegisterTypeParameters(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ foreach (TypeVariable/*!*/ v in TypeParameters) {
+ Contract.Assert(v != null);
+ rc.AddTypeBinder(v);
+ }
+ }
+
+ protected void SortTypeParams() {
+ List<Type>/*!*/ allTypes = new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray());
+ Contract.Assert(allTypes != null);
+ allTypes.AddRange(new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()));
+ TypeParameters = Type.SortTypeParams(TypeParameters, allTypes, null);
+ }
+
+ /// <summary>
+ /// Adds the given formals to the current variable context, and then resolves
+ /// the types of those formals. Does NOT resolve the where clauses of the
+ /// formals.
+ /// Relies on the caller to first create, and later tear down, that variable
+ /// context.
+ /// </summary>
+ /// <param name="rc"></param>
+ protected void RegisterFormals(List<Variable> formals, ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ Contract.Requires(formals != null);
+ foreach (Formal/*!*/ f in formals) {
+ Contract.Assert(f != null);
+ if (f.Name != TypedIdent.NoName) {
+ rc.AddVariable(f, false);
+ }
+ f.Resolve(rc);
+ }
+ }
+
+ /// <summary>
+ /// Resolves the where clauses (and attributes) of the formals.
+ /// </summary>
+ /// <param name="rc"></param>
+ protected void ResolveFormals(List<Variable> formals, ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ Contract.Requires(formals != null);
+ foreach (Formal/*!*/ f in formals) {
+ Contract.Assert(f != null);
+ f.ResolveWhere(rc);
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(tc);
+ foreach (Formal/*!*/ p in InParams) {
+ Contract.Assert(p != null);
+ p.Typecheck(tc);
+ }
+ foreach (Formal/*!*/ p in OutParams) {
+ Contract.Assert(p != null);
+ p.Typecheck(tc);
+ }
+ }
+ }
+
+ public class DatatypeConstructor : Function {
+ public List<DatatypeSelector> selectors;
+ public DatatypeMembership membership;
+
+ public DatatypeConstructor(Function func)
+ : base(func.tok, func.Name, func.TypeParameters, func.InParams, func.OutParams[0], func.Comment, func.Attributes)
+ {
+ selectors = new List<DatatypeSelector>();
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ HashSet<string> selectorNames = new HashSet<string>();
+ foreach (DatatypeSelector selector in selectors) {
+ if (selector.Name.StartsWith("#")) {
+ rc.Error(selector.tok, "The selector must be a non-empty string");
+ }
+ else {
+ if (selectorNames.Contains(selector.Name))
+ rc.Error(this.tok, "The selectors for a constructor must be distinct strings");
+ else
+ selectorNames.Add(selector.Name);
+ }
+ }
+ base.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ CtorType outputType = this.OutParams[0].TypedIdent.Type as CtorType;
+ if (outputType == null || !outputType.IsDatatype()) {
+ tc.Error(tok, "The output type of a constructor must be a datatype");
+ }
+ base.Typecheck(tc);
+ }
+ }
+
+ public class DatatypeSelector : Function {
+ public Function constructor;
+ public int index;
+ public DatatypeSelector(Function constructor, int index)
+ : base(constructor.InParams[index].tok,
+ constructor.InParams[index].Name + "#" + constructor.Name,
+ new List<Variable> { new Formal(constructor.tok, new TypedIdent(constructor.tok, "", constructor.OutParams[0].TypedIdent.Type), true) },
+ new Formal(constructor.tok, new TypedIdent(constructor.tok, "", constructor.InParams[index].TypedIdent.Type), false))
+ {
+ this.constructor = constructor;
+ this.index = index;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) { }
+ }
+
+ public class DatatypeMembership : Function {
+ public Function constructor;
+ public DatatypeMembership(Function constructor)
+ : base(constructor.tok,
+ "is#" + constructor.Name,
+ new List<Variable> { new Formal(constructor.tok, new TypedIdent(constructor.tok, "", constructor.OutParams[0].TypedIdent.Type), true) },
+ new Formal(constructor.tok, new TypedIdent(constructor.tok, "", Type.Bool), false))
+ {
+ this.constructor = constructor;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) { }
+ }
+
+ public class Function : DeclWithFormals {
+ public string Comment;
+
+ // the body is only set if the function is declared with {:inline}
+ public Expr Body;
+ public Axiom DefinitionAxiom;
+
+ public IList<Axiom> otherDefinitionAxioms;
+ public IEnumerable<Axiom> OtherDefinitionAxioms
+ {
+ get
+ {
+ return otherDefinitionAxioms;
+ }
+ }
+
+ public void AddOtherDefinitionAxiom(Axiom axiom)
+ {
+ Contract.Requires(axiom != null);
+
+ if (otherDefinitionAxioms == null)
+ {
+ otherDefinitionAxioms = new List<Axiom>();
+ }
+ otherDefinitionAxioms.Add(axiom);
+ }
+
+ public bool doingExpansion;
+
+ private bool neverTrigger;
+ private bool neverTriggerComputed;
+
+ public string OriginalLambdaExprAsString;
+
+ public Function(IToken tok, string name, List<Variable> args, Variable result)
+ : this(tok, name, new List<TypeVariable>(), args, result, null) {
+ Contract.Requires(result != null);
+ Contract.Requires(args != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, new List<TypeVariable>(), args, result, null);
+ }
+ public Function(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> args, Variable result)
+ : this(tok, name, typeParams, args, result, null) {
+ Contract.Requires(result != null);
+ Contract.Requires(args != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, typeParams, args, result, null);
+ }
+ public Function(IToken tok, string name, List<Variable> args, Variable result, string comment)
+ : this(tok, name, new List<TypeVariable>(), args, result, comment) {
+ Contract.Requires(result != null);
+ Contract.Requires(args != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, new List<TypeVariable>(), args, result, comment);
+ }
+ public Function(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> args, Variable/*!*/ result, string comment)
+ : base(tok, name, typeParams, args, new List<Variable> { result }) {
+ Contract.Requires(result != null);
+ Contract.Requires(args != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ Comment = comment;
+ }
+ public Function(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> args, Variable result,
+ string comment, QKeyValue kv)
+ : this(tok, name, typeParams, args, result, comment) {
+ Contract.Requires(args != null);
+ Contract.Requires(result != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, typeParams, args, result, comment);
+ this.Attributes = kv;
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "function ");
+ EmitAttributes(stream);
+ if (Body != null && !QKeyValue.FindBoolAttribute(Attributes, "inline")) {
+ // Boogie inlines any function whose .Body field is non-null. The parser populates the .Body field
+ // is the :inline attribute is present, but if someone creates the Boogie file directly as an AST, then
+ // the :inline attribute may not be there. We'll make sure it's printed, so one can see that this means
+ // that the body will be inlined.
+ stream.Write("{:inline} ");
+ }
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ stream.Write("h{0}^^{1}", this.GetHashCode(), TokenTextWriter.SanitizeIdentifier(this.Name));
+ } else {
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ EmitSignature(stream, true);
+ if (Body != null) {
+ stream.WriteLine();
+ stream.WriteLine("{");
+ stream.Write(level + 1, "");
+ Body.Emit(stream);
+ stream.WriteLine();
+ stream.WriteLine("}");
+ } else {
+ stream.WriteLine(";");
+ }
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddProcedure(this);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ RegisterTypeParameters(rc);
+ rc.PushVarContext();
+ RegisterFormals(InParams, rc);
+ RegisterFormals(OutParams, rc);
+ ResolveAttributes(rc);
+ if (Body != null)
+ {
+ rc.StateMode = ResolutionContext.State.StateLess;
+ Body.Resolve(rc);
+ rc.StateMode = ResolutionContext.State.Single;
+ }
+ rc.PopVarContext();
+ Type.CheckBoundVariableOccurrences(TypeParameters,
+ new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ this.tok, "function arguments",
+ rc);
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+ SortTypeParams();
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ // PR: why was the base call left out previously?
+ base.Typecheck(tc);
+ // TypecheckAttributes(tc);
+ if (Body != null) {
+ Body.Typecheck(tc);
+ if (!cce.NonNull(Body.Type).Unify(cce.NonNull(OutParams[0]).TypedIdent.Type))
+ tc.Error(Body,
+ "function body with invalid type: {0} (expected: {1})",
+ Body.Type, cce.NonNull(OutParams[0]).TypedIdent.Type);
+ }
+ }
+
+ public bool NeverTrigger {
+ get {
+ if (!neverTriggerComputed) {
+ this.CheckBooleanAttribute("never_pattern", ref neverTrigger);
+ neverTriggerComputed = true;
+ }
+ return neverTrigger;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitFunction(this);
+ }
+
+ public Axiom CreateDefinitionAxiom(Expr definition, QKeyValue kv = null) {
+ Contract.Requires(definition != null);
+
+ List<Variable> dummies = new List<Variable>();
+ List<Expr> callArgs = new List<Expr>();
+ int i = 0;
+ foreach (Formal/*!*/ f in InParams) {
+ Contract.Assert(f != null);
+ string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
+ dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
+ callArgs.Add(new IdentifierExpr(f.tok, nm));
+ i++;
+ }
+ List<TypeVariable>/*!*/ quantifiedTypeVars = new List<TypeVariable>();
+ foreach (TypeVariable/*!*/ t in TypeParameters) {
+ Contract.Assert(t != null);
+ quantifiedTypeVars.Add(new TypeVariable(tok, t.Name));
+ }
+
+ Expr call = new NAryExpr(tok, new FunctionCall(new IdentifierExpr(tok, Name)), callArgs);
+ // specify the type of the function, because it might be that
+ // type parameters only occur in the output type
+ call = Expr.CoerceType(tok, call, (Type)OutParams[0].TypedIdent.Type.Clone());
+ Expr def = Expr.Binary(tok, BinaryOperator.Opcode.Eq, call, definition);
+ if (quantifiedTypeVars.Count != 0 || dummies.Count != 0) {
+ def = new ForallExpr(tok, quantifiedTypeVars, dummies,
+ kv,
+ new Trigger(tok, true, new List<Expr> { call }, null),
+ def);
+ }
+ DefinitionAxiom = new Axiom(tok, def);
+ return DefinitionAxiom;
+ }
+ }
+
+ public class Macro : Function {
+ public Macro(IToken tok, string name, List<Variable> args, Variable result)
+ : base(tok, name, args, result) { }
+ }
+
+ public class Requires : Absy, IPotentialErrorNode<string, string> {
+ public readonly bool Free;
+
+ private Expr/*!*/ _condition;
+
+ public Expr/*!*/ Condition {
+ get {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return this._condition;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._condition = value;
+ }
+ }
+
+ public string Comment;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._condition != null);
+ }
+
+
+ // TODO: convert to use generics
+ private string errorData;
+ public string ErrorData {
+ get {
+ return errorData;
+ }
+ set {
+ errorData = value;
+ }
+ }
+
+
+ private MiningStrategy errorDataEnhanced;
+ public MiningStrategy ErrorDataEnhanced {
+ get {
+ return errorDataEnhanced;
+ }
+ set {
+ errorDataEnhanced = value;
+ }
+ }
+
+ public QKeyValue Attributes;
+
+ public String ErrorMessage {
+ get {
+ return QKeyValue.FindStringAttribute(Attributes, "msg");
+ }
+ }
+
+ public Requires(IToken token, bool free, Expr condition, string comment, QKeyValue kv)
+ : base(token) {
+ Contract.Requires(condition != null);
+ Contract.Requires(token != null);
+ this.Free = free;
+ this._condition = condition;
+ this.Comment = comment;
+ this.Attributes = kv;
+ }
+
+ public Requires(IToken token, bool free, Expr condition, string comment)
+ : this(token, free, condition, comment, null) {
+ Contract.Requires(condition != null);
+ Contract.Requires(token != null);
+ //:this(token, free, condition, comment, null);
+ }
+
+ public Requires(bool free, Expr condition)
+ : this(Token.NoToken, free, condition, null) {
+ Contract.Requires(condition != null);
+ //:this(Token.NoToken, free, condition, null);
+ }
+
+ public Requires(bool free, Expr condition, string comment)
+ : this(Token.NoToken, free, condition, comment) {
+ Contract.Requires(condition != null);
+ //:this(Token.NoToken, free, condition, comment);
+ }
+
+ public void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "{0}requires ", Free ? "free " : "");
+ Cmd.EmitAttributes(stream, Attributes);
+ this.Condition.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ this.Condition.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ this.Condition.Typecheck(tc);
+ Contract.Assert(this.Condition.Type != null); // follows from postcondition of Expr.Typecheck
+ if (!this.Condition.Type.Unify(Type.Bool)) {
+ tc.Error(this, "preconditions must be of type bool");
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ return visitor.VisitRequires(this);
+ }
+ }
+
+ public class Ensures : Absy, IPotentialErrorNode<string, string> {
+ public readonly bool Free;
+
+ private Expr/*!*/ _condition;
+
+ public Expr/*!*/ Condition {
+ get {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return this._condition;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._condition = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._condition != null);
+ }
+
+ public string Comment;
+
+ // TODO: convert to use generics
+ private string errorData;
+ public string ErrorData {
+ get {
+ return errorData;
+ }
+ set {
+ errorData = value;
+ }
+ }
+
+ private MiningStrategy errorDataEnhanced;
+ public MiningStrategy ErrorDataEnhanced {
+ get {
+ return errorDataEnhanced;
+ }
+ set {
+ errorDataEnhanced = value;
+ }
+ }
+
+ public String ErrorMessage {
+ get {
+ return QKeyValue.FindStringAttribute(Attributes, "msg");
+ }
+ }
+
+ public QKeyValue Attributes;
+
+ public Ensures(IToken token, bool free, Expr/*!*/ condition, string comment, QKeyValue kv)
+ : base(token) {
+ Contract.Requires(condition != null);
+ Contract.Requires(token != null);
+ this.Free = free;
+ this._condition = condition;
+ this.Comment = comment;
+ this.Attributes = kv;
+ }
+
+ public Ensures(IToken token, bool free, Expr condition, string comment)
+ : this(token, free, condition, comment, null) {
+ Contract.Requires(condition != null);
+ Contract.Requires(token != null);
+ //:this(token, free, condition, comment, null);
+ }
+
+ public Ensures(bool free, Expr condition)
+ : this(Token.NoToken, free, condition, null) {
+ Contract.Requires(condition != null);
+ //:this(Token.NoToken, free, condition, null);
+ }
+
+ public Ensures(bool free, Expr condition, string comment)
+ : this(Token.NoToken, free, condition, comment) {
+ Contract.Requires(condition != null);
+ //:this(Token.NoToken, free, condition, comment);
+ }
+
+ public void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ if (Comment != null) {
+ stream.WriteLine(this, level, "// " + Comment);
+ }
+ stream.Write(this, level, "{0}ensures ", Free ? "free " : "");
+ Cmd.EmitAttributes(stream, Attributes);
+ this.Condition.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ this.Condition.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ this.Condition.Typecheck(tc);
+ Contract.Assert(this.Condition.Type != null); // follows from postcondition of Expr.Typecheck
+ if (!this.Condition.Type.Unify(Type.Bool)) {
+ tc.Error(this, "postconditions must be of type bool");
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ return visitor.VisitEnsures(this);
+ }
+ }
+
+ public class Procedure : DeclWithFormals {
+ public List<Requires>/*!*/ Requires;
+ public List<IdentifierExpr>/*!*/ Modifies;
+ public List<Ensures>/*!*/ Ensures;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Requires != null);
+ Contract.Invariant(Modifies != null);
+ Contract.Invariant(Ensures != null);
+ Contract.Invariant(Summary != null);
+ }
+
+
+ // Abstract interpretation: Procedure-specific invariants...
+ [Rep]
+ public readonly ProcedureSummary/*!*/ Summary;
+
+ public Procedure(IToken/*!*/ tok, string/*!*/ name, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ inParams, List<Variable>/*!*/ outParams,
+ List<Requires>/*!*/ requires, List<IdentifierExpr>/*!*/ modifies, List<Ensures>/*!*/ ensures)
+ : this(tok, name, typeParams, inParams, outParams, requires, modifies, ensures, null) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(requires != null);
+ Contract.Requires(modifies != null);
+ Contract.Requires(ensures != null);
+ //:this(tok, name, typeParams, inParams, outParams, requires, modifies, ensures, null);
+ }
+
+ public Procedure(IToken/*!*/ tok, string/*!*/ name, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ inParams, List<Variable>/*!*/ outParams,
+ List<Requires>/*!*/ @requires, List<IdentifierExpr>/*!*/ @modifies, List<Ensures>/*!*/ @ensures, QKeyValue kv
+ )
+ : base(tok, name, typeParams, inParams, outParams) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(@requires != null);
+ Contract.Requires(@modifies != null);
+ Contract.Requires(@ensures != null);
+ this.Requires = @requires;
+ this.Modifies = @modifies;
+ this.Ensures = @ensures;
+ this.Summary = new ProcedureSummary();
+ this.Attributes = kv;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "procedure ");
+ EmitAttributes(stream);
+ stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ EmitSignature(stream, false);
+ stream.WriteLine(";");
+
+ level++;
+
+ foreach (Requires/*!*/ e in this.Requires) {
+ Contract.Assert(e != null);
+ e.Emit(stream, level);
+ }
+
+ if (this.Modifies.Count > 0) {
+ stream.Write(level, "modifies ");
+ this.Modifies.Emit(stream, false);
+ stream.WriteLine(";");
+ }
+
+ foreach (Ensures/*!*/ e in this.Ensures) {
+ Contract.Assert(e != null);
+ e.Emit(stream, level);
+ }
+
+ if (!CommandLineOptions.Clo.IntraproceduralInfer) {
+ for (int s = 0; s < this.Summary.Count; s++) {
+ ProcedureSummaryEntry/*!*/ entry = cce.NonNull(this.Summary[s]);
+ stream.Write(level + 1, "// ");
+ stream.WriteLine();
+ }
+ }
+
+ stream.WriteLine();
+ stream.WriteLine();
+ }
+
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.AddProcedure(this);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.PushVarContext();
+
+ foreach (IdentifierExpr/*!*/ ide in Modifies) {
+ Contract.Assert(ide != null);
+ ide.Resolve(rc);
+ }
+
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ RegisterTypeParameters(rc);
+
+ RegisterFormals(InParams, rc);
+ ResolveFormals(InParams, rc); // "where" clauses of in-parameters are resolved without the out-parameters in scope
+ foreach (Requires/*!*/ e in Requires) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+ }
+ RegisterFormals(OutParams, rc);
+ ResolveFormals(OutParams, rc); // "where" clauses of out-parameters are resolved with both in- and out-parametes in scope
+
+ rc.StateMode = ResolutionContext.State.Two;
+ foreach (Ensures/*!*/ e in Ensures) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+ }
+ rc.StateMode = ResolutionContext.State.Single;
+ ResolveAttributes(rc);
+
+ Type.CheckBoundVariableOccurrences(TypeParameters,
+ new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ this.tok, "procedure arguments",
+ rc);
+
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+
+ rc.PopVarContext();
+
+ SortTypeParams();
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ base.Typecheck(tc);
+ foreach (IdentifierExpr/*!*/ ide in Modifies) {
+ Contract.Assert(ide != null);
+ Contract.Assume(ide.Decl != null);
+ if (!ide.Decl.IsMutable) {
+ tc.Error(this, "modifies list contains constant: {0}", ide.Name);
+ }
+ ide.Typecheck(tc);
+ }
+ foreach (Requires/*!*/ e in Requires) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+ bool oldYields = tc.Yields;
+ tc.Yields = QKeyValue.FindBoolAttribute(Attributes, "yields");
+ foreach (Ensures/*!*/ e in Ensures) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+ tc.Yields = oldYields;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitProcedure(this);
+ }
+ }
+
+ public class LoopProcedure : Procedure
+ {
+ public Implementation enclosingImpl;
+ private Dictionary<Block, Block> blockMap;
+ private Dictionary<string, Block> blockLabelMap;
+
+ public LoopProcedure(Implementation impl, Block header,
+ List<Variable> inputs, List<Variable> outputs, List<IdentifierExpr> globalMods)
+ : base(Token.NoToken, impl.Name + "_loop_" + header.ToString(),
+ new List<TypeVariable>(), inputs, outputs,
+ new List<Requires>(), globalMods, new List<Ensures>())
+ {
+ enclosingImpl = impl;
+ }
+
+ public void setBlockMap(Dictionary<Block, Block> bm)
+ {
+ blockMap = bm;
+ blockLabelMap = new Dictionary<string, Block>();
+ foreach (var kvp in bm)
+ {
+ blockLabelMap.Add(kvp.Key.Label, kvp.Value);
+ }
+ }
+
+ public Block getBlock(string label)
+ {
+ if (blockLabelMap.ContainsKey(label)) return blockLabelMap[label];
+ return null;
+ }
+ }
+
+ public class Implementation : DeclWithFormals {
+ public List<Variable>/*!*/ LocVars;
+ [Rep]
+ public StmtList StructuredStmts;
+ [Rep]
+ public List<Block/*!*/>/*!*/ Blocks;
+ public Procedure Proc;
+
+ // Blocks before applying passification etc.
+ // Both are used only when /inline is set.
+ public List<Block/*!*/> OriginalBlocks;
+ public List<Variable> OriginalLocVars;
+
+ public readonly ISet<byte[]> AssertionChecksums = new HashSet<byte[]>(ChecksumComparer.Default);
+
+ public sealed class ChecksumComparer : IEqualityComparer<byte[]>
+ {
+ static IEqualityComparer<byte[]> defaultComparer;
+ public static IEqualityComparer<byte[]> Default
+ {
+ get
+ {
+ if (defaultComparer == null)
+ {
+ defaultComparer = new ChecksumComparer();
+ }
+ return defaultComparer;
+ }
+ }
+
+ public bool Equals(byte[] x, byte[] y)
+ {
+ if (x == null || y == null)
+ {
+ return x == y;
+ }
+ else
+ {
+ return x.SequenceEqual(y);
+ }
+ }
+
+ public int GetHashCode(byte[] checksum)
+ {
+ if (checksum == null)
+ {
+ throw new ArgumentNullException("checksum");
+ }
+ else
+ {
+ var result = 17;
+ for (int i = 0; i < checksum.Length; i++)
+ {
+ result = result * 23 + checksum[i];
+ }
+ return result;
+ }
+ }
+ }
+
+ public void AddAssertionChecksum(byte[] checksum)
+ {
+ Contract.Requires(checksum != null);
+
+ if (AssertionChecksums != null)
+ {
+ AssertionChecksums.Add(checksum);
+ }
+ }
+
+ public ISet<byte[]> AssertionChecksumsInCachedSnapshot { get; set; }
+
+ public bool IsAssertionChecksumInCachedSnapshot(byte[] checksum)
+ {
+ Contract.Requires(AssertionChecksumsInCachedSnapshot != null);
+
+ return AssertionChecksumsInCachedSnapshot.Contains(checksum);
+ }
+
+ public IList<AssertCmd> RecycledFailingAssertions { get; protected set; }
+
+ public void AddRecycledFailingAssertion(AssertCmd assertion)
+ {
+ if (RecycledFailingAssertions == null)
+ {
+ RecycledFailingAssertions = new List<AssertCmd>();
+ }
+ RecycledFailingAssertions.Add(assertion);
+ }
+
+ public Cmd ExplicitAssumptionAboutCachedPrecondition { get; set; }
+
+ // Strongly connected components
+ private StronglyConnectedComponents<Block/*!*/> scc;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(LocVars != null);
+ Contract.Invariant(cce.NonNullElements(Blocks));
+ Contract.Invariant(cce.NonNullElements(OriginalBlocks, true));
+ Contract.Invariant(cce.NonNullElements(scc, true));
+
+ }
+ private bool BlockPredecessorsComputed;
+ public bool StronglyConnectedComponentsComputed {
+ get {
+ return this.scc != null;
+ }
+ }
+
+ public bool SkipVerification {
+ get {
+ bool verify = true;
+ cce.NonNull(this.Proc).CheckBooleanAttribute("verify", ref verify);
+ this.CheckBooleanAttribute("verify", ref verify);
+ if (!verify) {
+ return true;
+ }
+
+ if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assert ||
+ CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assume) {
+ Expr inl = this.FindExprAttribute("inline");
+ if (inl == null)
+ inl = this.Proc.FindExprAttribute("inline");
+ if (inl != null && inl is LiteralExpr && ((LiteralExpr)inl).isBigNum && ((LiteralExpr)inl).asBigNum.Signum > 0) {
+ return true;
+ }
+ }
+
+ if (CommandLineOptions.Clo.StratifiedInlining > 0) {
+ return !QKeyValue.FindBoolAttribute(Attributes, "entrypoint");
+ }
+
+ return false;
+ }
+ }
+
+ public string Id
+ {
+ get
+ {
+ var id = FindStringAttribute("id");
+ if (id == null)
+ {
+ id = Name + GetHashCode().ToString() + ":0";
+ }
+ return id;
+ }
+ }
+
+ public int Priority
+ {
+ get
+ {
+ int priority = 0;
+ CheckIntAttribute("priority", ref priority);
+ if (priority <= 0)
+ {
+ priority = 1;
+ }
+ return priority;
+ }
+ }
+
+ public IDictionary<byte[], object> ErrorChecksumToCachedError { get; private set; }
+
+ public bool IsErrorChecksumInCachedSnapshot(byte[] checksum)
+ {
+ Contract.Requires(ErrorChecksumToCachedError != null);
+
+ return ErrorChecksumToCachedError.ContainsKey(checksum);
+ }
+
+ public void SetErrorChecksumToCachedError(IEnumerable<Tuple<byte[], byte[], object>> errors)
+ {
+ Contract.Requires(errors != null);
+
+ ErrorChecksumToCachedError = new Dictionary<byte[], object>(ChecksumComparer.Default);
+ foreach (var kv in errors)
+ {
+ ErrorChecksumToCachedError[kv.Item1] = kv.Item3;
+ if (kv.Item2 != null)
+ {
+ ErrorChecksumToCachedError[kv.Item2] = null;
+ }
+ }
+ }
+
+ public bool HasCachedSnapshot
+ {
+ get
+ {
+ return ErrorChecksumToCachedError != null && AssertionChecksumsInCachedSnapshot != null;
+ }
+ }
+
+ public bool AnyErrorsInCachedSnapshot
+ {
+ get
+ {
+ Contract.Requires(ErrorChecksumToCachedError != null);
+
+ return ErrorChecksumToCachedError.Any();
+ }
+ }
+
+ IList<LocalVariable> injectedAssumptionVariables;
+ public IList<LocalVariable> InjectedAssumptionVariables
+ {
+ get
+ {
+ return injectedAssumptionVariables != null ? injectedAssumptionVariables : new List<LocalVariable>();
+ }
+ }
+
+ IList<LocalVariable> doomedInjectedAssumptionVariables;
+ public IList<LocalVariable> DoomedInjectedAssumptionVariables
+ {
+ get
+ {
+ return doomedInjectedAssumptionVariables != null ? doomedInjectedAssumptionVariables : new List<LocalVariable>();
+ }
+ }
+
+ public List<LocalVariable> RelevantInjectedAssumptionVariables(Dictionary<Variable, Expr> incarnationMap)
+ {
+ return InjectedAssumptionVariables.Where(v => { Expr e; if (incarnationMap.TryGetValue(v, out e)) { var le = e as LiteralExpr; return le == null || !le.IsTrue; } else { return false; } }).ToList();
+ }
+
+ public List<LocalVariable> RelevantDoomedInjectedAssumptionVariables(Dictionary<Variable, Expr> incarnationMap)
+ {
+ return DoomedInjectedAssumptionVariables.Where(v => { Expr e; if (incarnationMap.TryGetValue(v, out e)) { var le = e as LiteralExpr; return le == null || !le.IsTrue; } else { return false; } }).ToList();
+ }
+
+ public Expr ConjunctionOfInjectedAssumptionVariables(Dictionary<Variable, Expr> incarnationMap, out bool isTrue)
+ {
+ Contract.Requires(incarnationMap != null);
+
+ var vars = RelevantInjectedAssumptionVariables(incarnationMap).Select(v => incarnationMap[v]).ToList();
+ isTrue = vars.Count == 0;
+ return LiteralExpr.BinaryTreeAnd(vars);
+ }
+
+ public void InjectAssumptionVariable(LocalVariable variable, bool isDoomed = false)
+ {
+ LocVars.Add(variable);
+ if (isDoomed)
+ {
+ if (doomedInjectedAssumptionVariables == null)
+ {
+ doomedInjectedAssumptionVariables = new List<LocalVariable>();
+ }
+ doomedInjectedAssumptionVariables.Add(variable);
+ }
+ else
+ {
+ if (injectedAssumptionVariables == null)
+ {
+ injectedAssumptionVariables = new List<LocalVariable>();
+ }
+ injectedAssumptionVariables.Add(variable);
+ }
+ }
+
+ public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] StmtList structuredStmts, QKeyValue kv)
+ : this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, kv, new Errors()) {
+ Contract.Requires(structuredStmts != null);
+ Contract.Requires(localVariables != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors());
+ }
+
+ public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] StmtList structuredStmts)
+ : this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors()) {
+ Contract.Requires(structuredStmts != null);
+ Contract.Requires(localVariables != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors());
+ }
+
+ public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] StmtList structuredStmts, Errors errorHandler)
+ : this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, errorHandler) {
+ Contract.Requires(errorHandler != null);
+ Contract.Requires(structuredStmts != null);
+ Contract.Requires(localVariables != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, errorHandler);
+ }
+
+ public Implementation(IToken/*!*/ tok,
+ string/*!*/ name,
+ List<TypeVariable>/*!*/ typeParams,
+ List<Variable>/*!*/ inParams,
+ List<Variable>/*!*/ outParams,
+ List<Variable>/*!*/ localVariables,
+ [Captured] StmtList/*!*/ structuredStmts,
+ QKeyValue kv,
+ Errors/*!*/ errorHandler)
+ : base(tok, name, typeParams, inParams, outParams) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(localVariables != null);
+ Contract.Requires(structuredStmts != null);
+ Contract.Requires(errorHandler != null);
+ LocVars = localVariables;
+ StructuredStmts = structuredStmts;
+ BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts, errorHandler);
+ Blocks = ctx.Blocks;
+ BlockPredecessorsComputed = false;
+ scc = null;
+ Attributes = kv;
+ }
+
+ public Implementation(IToken tok, string name, List<TypeVariable> typeParams, List<Variable> inParams, List<Variable> outParams, List<Variable> localVariables, [Captured] List<Block/*!*/> block)
+ : this(tok, name, typeParams, inParams, outParams, localVariables, block, null) {
+ Contract.Requires(cce.NonNullElements(block));
+ Contract.Requires(localVariables != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(name != null);
+ Contract.Requires(tok != null);
+ //:this(tok, name, typeParams, inParams, outParams, localVariables, block, null);
+ }
+
+ public Implementation(IToken/*!*/ tok,
+ string/*!*/ name,
+ List<TypeVariable>/*!*/ typeParams,
+ List<Variable>/*!*/ inParams,
+ List<Variable>/*!*/ outParams,
+ List<Variable>/*!*/ localVariables,
+ [Captured] List<Block/*!*/>/*!*/ blocks,
+ QKeyValue kv)
+ : base(tok, name, typeParams, inParams, outParams) {
+ Contract.Requires(name != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(localVariables != null);
+ Contract.Requires(cce.NonNullElements(blocks));
+ LocVars = localVariables;
+ Blocks = blocks;
+ BlockPredecessorsComputed = false;
+ scc = null;
+ Attributes = kv;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "implementation ");
+ EmitAttributes(stream);
+ stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ EmitSignature(stream, false);
+ stream.WriteLine();
+
+ stream.WriteLine(level, "{0}", '{');
+
+ foreach (Variable/*!*/ v in this.LocVars) {
+ Contract.Assert(v != null);
+ v.Emit(stream, level + 1);
+ }
+
+ if (this.StructuredStmts != null && !CommandLineOptions.Clo.PrintInstrumented && !CommandLineOptions.Clo.PrintInlined) {
+ if (this.LocVars.Count > 0) {
+ stream.WriteLine();
+ }
+ if (CommandLineOptions.Clo.PrintUnstructured < 2) {
+ if (CommandLineOptions.Clo.PrintUnstructured == 1) {
+ stream.WriteLine(this, level + 1, "/*** structured program:");
+ }
+ this.StructuredStmts.Emit(stream, level + 1);
+ if (CommandLineOptions.Clo.PrintUnstructured == 1) {
+ stream.WriteLine(level + 1, "**** end structured program */");
+ }
+ }
+ }
+
+ if (this.StructuredStmts == null || 1 <= CommandLineOptions.Clo.PrintUnstructured ||
+ CommandLineOptions.Clo.PrintInstrumented || CommandLineOptions.Clo.PrintInlined) {
+ foreach (Block b in this.Blocks) {
+ b.Emit(stream, level + 1);
+ }
+ }
+
+ stream.WriteLine(level, "{0}", '}');
+
+ stream.WriteLine();
+ stream.WriteLine();
+ }
+ public override void Register(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ // nothing to register
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ if (Proc != null) {
+ // already resolved
+ return;
+ }
+
+ DeclWithFormals dwf = rc.LookUpProcedure(cce.NonNull(this.Name));
+ Proc = dwf as Procedure;
+ if (dwf == null) {
+ rc.Error(this, "implementation given for undeclared procedure: {0}", this.Name);
+ } else if (Proc == null) {
+ rc.Error(this, "implementations given for function, not procedure: {0}", this.Name);
+ }
+
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ RegisterTypeParameters(rc);
+
+ rc.PushVarContext();
+ RegisterFormals(InParams, rc);
+ RegisterFormals(OutParams, rc);
+
+ foreach (Variable/*!*/ v in LocVars) {
+ Contract.Assert(v != null);
+ v.Register(rc);
+ v.Resolve(rc);
+ }
+ foreach (Variable/*!*/ v in LocVars) {
+ Contract.Assert(v != null);
+ v.ResolveWhere(rc);
+ }
+
+ rc.PushProcedureContext();
+ foreach (Block b in Blocks) {
+ b.Register(rc);
+ }
+
+ ResolveAttributes(rc);
+
+ rc.StateMode = ResolutionContext.State.Two;
+ foreach (Block b in Blocks) {
+ b.Resolve(rc);
+ }
+ rc.StateMode = ResolutionContext.State.Single;
+
+ rc.PopProcedureContext();
+ rc.PopVarContext();
+
+ Type.CheckBoundVariableOccurrences(TypeParameters,
+ new List<Type>(InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ new List<Type>(OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ this.tok, "implementation arguments",
+ rc);
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+ SortTypeParams();
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ base.Typecheck(tc);
+
+ Contract.Assume(this.Proc != null);
+
+ if (this.TypeParameters.Count != Proc.TypeParameters.Count) {
+ tc.Error(this, "mismatched number of type parameters in procedure implementation: {0}",
+ this.Name);
+ } else {
+ // if the numbers of type parameters are different, it is
+ // difficult to compare the argument types
+ MatchFormals(this.InParams, Proc.InParams, "in", tc);
+ MatchFormals(this.OutParams, Proc.OutParams, "out", tc);
+ }
+
+ foreach (Variable/*!*/ v in LocVars) {
+ Contract.Assert(v != null);
+ v.Typecheck(tc);
+ }
+ List<IdentifierExpr> oldFrame = tc.Frame;
+ bool oldYields = tc.Yields;
+ tc.Frame = Proc.Modifies;
+ tc.Yields = QKeyValue.FindBoolAttribute(Proc.Attributes, "yields");
+ foreach (Block b in Blocks) {
+ b.Typecheck(tc);
+ }
+ Contract.Assert(tc.Frame == Proc.Modifies);
+ tc.Frame = oldFrame;
+ tc.Yields = oldYields;
+ }
+ void MatchFormals(List<Variable>/*!*/ implFormals, List<Variable>/*!*/ procFormals, string/*!*/ inout, TypecheckingContext/*!*/ tc) {
+ Contract.Requires(implFormals != null);
+ Contract.Requires(procFormals != null);
+ Contract.Requires(inout != null);
+ Contract.Requires(tc != null);
+ if (implFormals.Count != procFormals.Count) {
+ tc.Error(this, "mismatched number of {0}-parameters in procedure implementation: {1}",
+ inout, this.Name);
+ } else {
+ // unify the type parameters so that types can be compared
+ Contract.Assert(Proc != null);
+ Contract.Assert(this.TypeParameters.Count == Proc.TypeParameters.Count);
+
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst1 =
+ new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst2 =
+ new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+
+ for (int i = 0; i < this.TypeParameters.Count; ++i) {
+ TypeVariable/*!*/ newVar =
+ new TypeVariable(Token.NoToken, Proc.TypeParameters[i].Name);
+ Contract.Assert(newVar != null);
+ subst1.Add(Proc.TypeParameters[i], newVar);
+ subst2.Add(this.TypeParameters[i], newVar);
+ }
+
+ for (int i = 0; i < implFormals.Count; i++) {
+ // the names of the formals are allowed to change from the proc to the impl
+
+ // but types must be identical
+ Type t = cce.NonNull((Variable)implFormals[i]).TypedIdent.Type.Substitute(subst2);
+ Type u = cce.NonNull((Variable)procFormals[i]).TypedIdent.Type.Substitute(subst1);
+ if (!t.Equals(u)) {
+ string/*!*/ a = cce.NonNull((Variable)implFormals[i]).Name;
+ Contract.Assert(a != null);
+ string/*!*/ b = cce.NonNull((Variable)procFormals[i]).Name;
+ Contract.Assert(b != null);
+ string/*!*/ c;
+ if (a == b) {
+ c = a;
+ } else {
+ c = String.Format("{0} (named {1} in implementation)", b, a);
+ }
+ tc.Error(this, "mismatched type of {0}-parameter in implementation {1}: {2}", inout, this.Name, c);
+ }
+ }
+ }
+ }
+
+ private Dictionary<Variable, Expr>/*?*/ formalMap = null;
+ public void ResetImplFormalMap() {
+ this.formalMap = null;
+ }
+ public Dictionary<Variable, Expr>/*!*/ GetImplFormalMap() {
+ Contract.Ensures(Contract.Result<Dictionary<Variable, Expr>>() != null);
+
+ if (this.formalMap != null)
+ return this.formalMap;
+ else {
+ Dictionary<Variable, Expr>/*!*/ map = new Dictionary<Variable, Expr> (InParams.Count + OutParams.Count);
+
+ Contract.Assume(this.Proc != null);
+ Contract.Assume(InParams.Count == Proc.InParams.Count);
+ for (int i = 0; i < InParams.Count; i++) {
+ Variable/*!*/ v = InParams[i];
+ Contract.Assert(v != null);
+ IdentifierExpr ie = new IdentifierExpr(v.tok, v);
+ Variable/*!*/ pv = Proc.InParams[i];
+ Contract.Assert(pv != null);
+ map.Add(pv, ie);
+ }
+ System.Diagnostics.Debug.Assert(OutParams.Count == Proc.OutParams.Count);
+ for (int i = 0; i < OutParams.Count; i++) {
+ Variable/*!*/ v = cce.NonNull(OutParams[i]);
+ IdentifierExpr ie = new IdentifierExpr(v.tok, v);
+ Variable pv = cce.NonNull(Proc.OutParams[i]);
+ map.Add(pv, ie);
+ }
+ this.formalMap = map;
+
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ Console.WriteLine("Implementation.GetImplFormalMap on {0}:", this.Name);
+ using (TokenTextWriter stream = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/false, /*pretty=*/ false)) {
+ foreach (var e in map) {
+ Console.Write(" ");
+ cce.NonNull((Variable/*!*/)e.Key).Emit(stream, 0);
+ Console.Write(" --> ");
+ cce.NonNull((Expr)e.Value).Emit(stream);
+ Console.WriteLine();
+ }
+ }
+ }
+
+ return map;
+ }
+ }
+
+ /// <summary>
+ /// Return a collection of blocks that are reachable from the block passed as a parameter.
+ /// The block must be defined in the current implementation
+ /// </summary>
+ public ICollection<Block/*!*/> GetConnectedComponents(Block startingBlock) {
+ Contract.Requires(startingBlock != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<Block>>(), true));
+ Contract.Assert(this.Blocks.Contains(startingBlock));
+
+ if (!this.BlockPredecessorsComputed)
+ ComputeStronglyConnectedComponents();
+
+#if DEBUG_PRINT
+ System.Console.WriteLine("* Strongly connected components * \n{0} \n ** ", scc);
+#endif
+
+ foreach (ICollection<Block/*!*/> component in cce.NonNull(this.scc)) {
+ foreach (Block/*!*/ b in component) {
+ Contract.Assert(b != null);
+ if (b == startingBlock) // We found the compontent that owns the startingblock
+ {
+ return component;
+ }
+ }
+ }
+
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // if we are here, it means that the block is not in one of the components. This is an error.
+ }
+
+ /// <summary>
+ /// Compute the strongly connected compontents of the blocks in the implementation.
+ /// As a side effect, it also computes the "predecessor" relation for the block in the implementation
+ /// </summary>
+ override public void ComputeStronglyConnectedComponents() {
+ if (!this.BlockPredecessorsComputed)
+ ComputePredecessorsForBlocks();
+
+ Adjacency<Block/*!*/> next = new Adjacency<Block/*!*/>(Successors);
+ Adjacency<Block/*!*/> prev = new Adjacency<Block/*!*/>(Predecessors);
+
+ this.scc = new StronglyConnectedComponents<Block/*!*/>(this.Blocks, next, prev);
+ scc.Compute();
+
+
+ foreach (Block/*!*/ block in this.Blocks) {
+ Contract.Assert(block != null);
+ block.Predecessors = new List<Block>();
+ }
+
+ }
+
+ /// <summary>
+ /// Reset the abstract stated computed before
+ /// </summary>
+ override public void ResetAbstractInterpretationState() {
+ foreach (Block/*!*/ b in this.Blocks) {
+ Contract.Assert(b != null);
+ b.ResetAbstractInterpretationState();
+ }
+ }
+
+ /// <summary>
+ /// A private method used as delegate for the strongly connected components.
+ /// It return, given a node, the set of its successors
+ /// </summary>
+ private IEnumerable/*<Block!>*//*!*/ Successors(Block node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+
+ GotoCmd gotoCmd = node.TransferCmd as GotoCmd;
+
+ if (gotoCmd != null) { // If it is a gotoCmd
+ Contract.Assert(gotoCmd.labelTargets != null);
+
+ return gotoCmd.labelTargets;
+ } else { // otherwise must be a ReturnCmd
+ Contract.Assert(node.TransferCmd is ReturnCmd);
+
+ return new List<Block/*!*/>();
+ }
+ }
+
+ /// <summary>
+ /// A private method used as delegate for the strongly connected components.
+ /// It return, given a node, the set of its predecessors
+ /// </summary>
+ private IEnumerable/*<Block!>*//*!*/ Predecessors(Block node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+
+ Contract.Assert(this.BlockPredecessorsComputed);
+
+ return node.Predecessors;
+ }
+
+ /// <summary>
+ /// Compute the predecessor informations for the blocks
+ /// </summary>
+ public void ComputePredecessorsForBlocks() {
+ foreach (Block b in this.Blocks) {
+ b.Predecessors = new List<Block>();
+ }
+ foreach (Block b in this.Blocks) {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null) {
+ Contract.Assert(gtc.labelTargets != null);
+ foreach (Block/*!*/ dest in gtc.labelTargets) {
+ Contract.Assert(dest != null);
+ dest.Predecessors.Add(b);
+ }
+ }
+ }
+ this.BlockPredecessorsComputed = true;
+ }
+
+ public void PruneUnreachableBlocks() {
+ ArrayList /*Block!*/ visitNext = new ArrayList /*Block!*/ ();
+ List<Block/*!*/> reachableBlocks = new List<Block/*!*/>();
+ HashSet<Block> reachable = new HashSet<Block>(); // the set of elements in "reachableBlocks"
+
+ visitNext.Add(this.Blocks[0]);
+ while (visitNext.Count != 0) {
+ Block b = cce.NonNull((Block)visitNext[visitNext.Count - 1]);
+ visitNext.RemoveAt(visitNext.Count - 1);
+ if (!reachable.Contains(b)) {
+ reachableBlocks.Add(b);
+ reachable.Add(b);
+ if (b.TransferCmd is GotoCmd) {
+ if (CommandLineOptions.Clo.PruneInfeasibleEdges) {
+ foreach (Cmd/*!*/ s in b.Cmds) {
+ Contract.Assert(s != null);
+ if (s is PredicateCmd) {
+ LiteralExpr e = ((PredicateCmd)s).Expr as LiteralExpr;
+ if (e != null && e.IsFalse) {
+ // This statement sequence will never reach the end, because of this "assume false" or "assert false".
+ // Hence, it does not reach its successors.
+ b.TransferCmd = new ReturnCmd(b.TransferCmd.tok);
+ goto NEXT_BLOCK;
+ }
+ }
+ }
+ }
+ // it seems that the goto statement at the end may be reached
+ foreach (Block succ in cce.NonNull((GotoCmd)b.TransferCmd).labelTargets) {
+ Contract.Assume(succ != null);
+ visitNext.Add(succ);
+ }
+ }
+ }
+ NEXT_BLOCK: {
+ }
+ }
+
+ this.Blocks = reachableBlocks;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitImplementation(this);
+ }
+
+ public void FreshenCaptureStates() {
+
+ // Assume commands with the "captureState" attribute allow model states to be
+ // captured for error reporting.
+ // Some program transformations, such as loop unrolling, duplicate parts of the
+ // program, leading to "capture-state-assumes" being duplicated. This leads
+ // to ambiguity when getting a state from the model.
+ // This method replaces the key of every "captureState" attribute with something
+ // unique
+
+ int FreshCounter = 0;
+ foreach(var b in Blocks) {
+ List<Cmd> newCmds = new List<Cmd>();
+ for (int i = 0; i < b.Cmds.Count(); i++) {
+ var a = b.Cmds[i] as AssumeCmd;
+ if (a != null && (QKeyValue.FindStringAttribute(a.Attributes, "captureState") != null)) {
+ string StateName = QKeyValue.FindStringAttribute(a.Attributes, "captureState");
+ newCmds.Add(new AssumeCmd(Token.NoToken, a.Expr, FreshenCaptureState(a.Attributes, FreshCounter)));
+ FreshCounter++;
+ }
+ else {
+ newCmds.Add(b.Cmds[i]);
+ }
+ }
+ b.Cmds = newCmds;
+ }
+ }
+
+ private QKeyValue FreshenCaptureState(QKeyValue Attributes, int FreshCounter) {
+ // Returns attributes identical to Attributes, but:
+ // - reversed (for ease of implementation; should not matter)
+ // - with the value for "captureState" replaced by a fresh value
+ Contract.Requires(QKeyValue.FindStringAttribute(Attributes, "captureState") != null);
+ string FreshValue = QKeyValue.FindStringAttribute(Attributes, "captureState") + "$renamed$" + Name + "$" + FreshCounter;
+
+ QKeyValue result = null;
+ while (Attributes != null) {
+ if (Attributes.Key.Equals("captureState")) {
+ result = new QKeyValue(Token.NoToken, Attributes.Key, new List<object>() { FreshValue }, result);
+ } else {
+ result = new QKeyValue(Token.NoToken, Attributes.Key, Attributes.Params, result);
+ }
+ Attributes = Attributes.Next;
+ }
+ return result;
+ }
+
+ }
+
+
+ public class TypedIdent : Absy {
+ public const string NoName = "";
+
+ private string/*!*/ _name;
+
+ public string/*!*/ Name {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this._name;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._name = value;
+ }
+ }
+
+ private Type/*!*/ _type;
+
+ public Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this._type;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._type = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._name != null);
+ Contract.Invariant(this._type != null);
+ }
+
+ public Expr WhereExpr;
+ // [NotDelayed]
+ public TypedIdent(IToken/*!*/ tok, string/*!*/ name, Type/*!*/ type)
+ : this(tok, name, type, null) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(type != null);
+ Contract.Ensures(this.WhereExpr == null); //PM: needed to verify BoogiePropFactory.FreshBoundVariable
+ //:this(tok, name, type, null); // here for aesthetic reasons
+ }
+ // [NotDelayed]
+ public TypedIdent(IToken/*!*/ tok, string/*!*/ name, Type/*!*/ type, Expr whereExpr)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(type != null);
+ Contract.Ensures(this.WhereExpr == whereExpr);
+ this._name = name;
+ this._type = type;
+ this.WhereExpr = whereExpr;
+ }
+ public bool HasName {
+ get {
+ return this.Name != NoName;
+ }
+ }
+ public void Emit(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ stream.SetToken(this);
+ stream.push();
+ if (this.Name != NoName) {
+ stream.Write("{0}: ", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ this.Type.Emit(stream);
+ if (this.WhereExpr != null) {
+ stream.sep();
+ stream.Write(" where ");
+ this.WhereExpr.Emit(stream);
+ }
+ stream.pop();
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ // NOTE: WhereExpr needs to be resolved by the caller, because the caller must provide a modified ResolutionContext
+ this.Type = this.Type.ResolveType(rc);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ // type variables can occur when working with polymorphic functions/procedures
+ // if (!this.Type.IsClosed)
+ // tc.Error(this, "free variables in type of an identifier: {0}",
+ // this.Type.FreeVariables);
+ if (this.WhereExpr != null) {
+ this.WhereExpr.Typecheck(tc);
+ Contract.Assert(this.WhereExpr.Type != null); // follows from postcondition of Expr.Typecheck
+ if (!this.WhereExpr.Type.Unify(Type.Bool)) {
+ tc.Error(this, "where clauses must be of type bool");
+ }
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTypedIdent(this);
+ }
+ }
+
+ #region Helper methods for generic Sequences
+
+ public static class TypeVariableSeqAlgorithms {
+ public static void AppendWithoutDups(this List<TypeVariable> tvs, List<TypeVariable> s1) {
+ Contract.Requires(s1 != null);
+ for (int i = 0; i < s1.Count; i++) {
+ TypeVariable/*!*/ next = s1[i];
+ Contract.Assert(next != null);
+ if (!tvs.Contains(next))
+ tvs.Add(next);
+ }
+ }
+ }
+
+ public static class Emitter {
+
+ public static void Emit(this List<Declaration/*!*/>/*!*/ decls, TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ Contract.Requires(cce.NonNullElements(decls));
+ bool first = true;
+ foreach (Declaration d in decls) {
+ if (d == null)
+ continue;
+ if (first) {
+ first = false;
+ } else {
+ stream.WriteLine();
+ }
+ d.Emit(stream, 0);
+ }
+ }
+
+ public static void Emit(this List<String> ss, TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ string sep = "";
+ foreach (string/*!*/ s in ss) {
+ Contract.Assert(s != null);
+ stream.Write(sep);
+ sep = ", ";
+ stream.Write(s);
+ }
+ }
+
+ public static void Emit(this IList<Expr> ts, TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ string sep = "";
+ stream.push();
+ foreach (Expr/*!*/ e in ts) {
+ Contract.Assert(e != null);
+ stream.Write(sep);
+ sep = ", ";
+ stream.sep();
+ e.Emit(stream);
+ }
+ stream.pop();
+ }
+
+ public static void Emit(this List<IdentifierExpr> ids, TokenTextWriter stream, bool printWhereComments) {
+ Contract.Requires(stream != null);
+ string sep = "";
+ foreach (IdentifierExpr/*!*/ e in ids) {
+ Contract.Assert(e != null);
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+
+ if (printWhereComments && e.Decl != null && e.Decl.TypedIdent.WhereExpr != null) {
+ stream.Write(" /* where ");
+ e.Decl.TypedIdent.WhereExpr.Emit(stream);
+ stream.Write(" */");
+ }
+ }
+ }
+
+ public static void Emit(this List<Variable> vs, TokenTextWriter stream, bool emitAttributes) {
+ Contract.Requires(stream != null);
+ string sep = "";
+ stream.push();
+ foreach (Variable/*!*/ v in vs) {
+ Contract.Assert(v != null);
+ stream.Write(sep);
+ sep = ", ";
+ stream.sep();
+ v.EmitVitals(stream, 0, emitAttributes);
+ }
+ stream.pop();
+ }
+
+ public static void Emit(this List<Type> tys, TokenTextWriter stream, string separator) {
+ Contract.Requires(separator != null);
+ Contract.Requires(stream != null);
+ string sep = "";
+ foreach (Type/*!*/ v in tys) {
+ Contract.Assert(v != null);
+ stream.Write(sep);
+ sep = separator;
+ v.Emit(stream);
+ }
+ }
+
+ public static void Emit(this List<TypeVariable> tvs, TokenTextWriter stream, string separator) {
+ Contract.Requires(separator != null);
+ Contract.Requires(stream != null);
+ string sep = "";
+ foreach (TypeVariable/*!*/ v in tvs) {
+ Contract.Assert(v != null);
+ stream.Write(sep);
+ sep = separator;
+ v.Emit(stream);
+ }
+ }
+
+ }
+ #endregion
+
+
+ #region Regular Expressions
+ // a data structure to recover the "program structure" from the flow graph
+ public abstract class RE : Cmd {
+ public RE()
+ : base(Token.NoToken) {
+ }
+ public override void AddAssignedVariables(List<Variable> vars) {
+ //Contract.Requires(vars != null);
+ throw new NotImplementedException();
+ }
+ }
+ public class AtomicRE : RE {
+ private Block/*!*/ _b;
+
+ public Block b
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<Block>() != null);
+ return this._b;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._b = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._b != null);
+ }
+
+ public AtomicRE(Block block) {
+ Contract.Requires(block != null);
+ this._b = block;
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ b.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ b.Typecheck(tc);
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ b.Emit(stream, level);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitAtomicRE(this);
+ }
+ }
+ public abstract class CompoundRE : RE {
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ return;
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ return;
+ }
+ }
+ public class Sequential : CompoundRE {
+ private RE/*!*/ _first;
+
+ public RE/*!*/ first {
+ get {
+ Contract.Ensures(Contract.Result<RE>() != null);
+ return this._first;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._first = value;
+ }
+ }
+
+ private RE/*!*/ _second;
+
+ public RE/*!*/ second {
+ get {
+ Contract.Ensures(Contract.Result<RE>() != null);
+ return this._second;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._second = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._first != null);
+ Contract.Invariant(this._second != null);
+ }
+
+ public Sequential(RE first, RE second) {
+ Contract.Requires(first != null);
+ Contract.Requires(second != null);
+ this._first = first;
+ this._second = second;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.WriteLine();
+ stream.WriteLine("{0};", Indent(stream.UseForComputingChecksums ? 0 : level));
+ first.Emit(stream, level + 1);
+ second.Emit(stream, level + 1);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitSequential(this);
+ }
+ }
+ public class Choice : CompoundRE {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._rs != null);
+ }
+
+ private List<RE>/*!*/ _rs;
+
+ public List<RE>/*!*/ rs { //Rename this (and _rs) if possible
+ get {
+ Contract.Ensures(Contract.Result<List<RE>>() != null);
+ return this._rs;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._rs = value;
+ }
+ }
+
+ public Choice(List<RE> operands) {
+ Contract.Requires(operands != null);
+ this._rs = operands;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.WriteLine();
+ stream.WriteLine("{0}[]", Indent(stream.UseForComputingChecksums ? 0 : level));
+ foreach (RE/*!*/ r in rs) {
+ Contract.Assert(r != null);
+ r.Emit(stream, level + 1);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitChoice(this);
+ }
+ }
+ public class DAG2RE {
+ public static RE Transform(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<RE>() != null);
+ TransferCmd tc = b.TransferCmd;
+ if (tc is ReturnCmd) {
+ return new AtomicRE(b);
+ } else if (tc is GotoCmd) {
+ GotoCmd/*!*/ g = (GotoCmd)tc;
+ Contract.Assert(g != null);
+ Contract.Assume(g.labelTargets != null);
+ if (g.labelTargets.Count == 1) {
+ return new Sequential(new AtomicRE(b), Transform(cce.NonNull(g.labelTargets[0])));
+ } else {
+ List<RE> rs = new List<RE>();
+ foreach (Block/*!*/ target in g.labelTargets) {
+ Contract.Assert(target != null);
+ RE r = Transform(target);
+ rs.Add(r);
+ }
+ RE second = new Choice(rs);
+ return new Sequential(new AtomicRE(b), second);
+ }
+ } else {
+ Contract.Assume(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+
+ #endregion
+
+ // NOTE: This class is here for convenience, since this file's
+ // classes are used pretty much everywhere.
+
+ public class BoogieDebug {
+ public static bool DoPrinting = false;
+
+ public static void Write(string format, params object[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(format != null);
+ if (DoPrinting) {
+ Console.Error.Write(format, args);
+ }
+ }
+
+ public static void WriteLine(string format, params object[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(format != null);
+ if (DoPrinting) {
+ Console.Error.WriteLine(format, args);
+ }
+ }
+
+ public static void WriteLine() {
+ if (DoPrinting) {
+ Console.Error.WriteLine();
+ }
+ }
+ }
+}
diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs
index b5581ea6..2e33e1dd 100644
--- a/Source/Core/AbsyCmd.cs
+++ b/Source/Core/AbsyCmd.cs
@@ -1,3496 +1,3500 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie {
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using System.Linq;
- using Microsoft.Boogie.AbstractInterpretation;
- using System.Diagnostics.Contracts;
- using Set = GSet<object>;
-
-
- //---------------------------------------------------------------------
- // BigBlock
- public class BigBlock {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(tok != null);
- Contract.Invariant(Anonymous || this.labelName != null);
- Contract.Invariant(this._ec == null || this._tc == null);
- Contract.Invariant(this._simpleCmds != null);
- }
-
- public readonly IToken/*!*/ tok;
-
- public readonly bool Anonymous;
-
- private string labelName;
-
- public string LabelName
- {
- get
- {
- Contract.Ensures(Anonymous || Contract.Result<string>() != null);
- return this.labelName;
- }
- set
- {
- Contract.Requires(Anonymous || value != null);
- this.labelName = value;
- }
- }
-
- [Rep]
- private List<Cmd>/*!*/ _simpleCmds;
-
- public List<Cmd>/*!*/ simpleCmds
- {
- get
- {
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- return this._simpleCmds;
- }
- set
- {
- Contract.Requires(value != null);
- this._simpleCmds = value;
- }
- }
-
- private StructuredCmd _ec;
-
- public StructuredCmd ec
- {
- get
- {
- return this._ec;
- }
- set
- {
- Contract.Requires(value == null || this.tc == null);
- this._ec = value;
- }
- }
-
- private TransferCmd _tc;
-
- public TransferCmd tc
- {
- get
- {
- return this._tc;
- }
- set
- {
- Contract.Requires(value == null || this.ec == null);
- this._tc = value;
- }
- }
-
- public BigBlock successorBigBlock; // semantic successor (may be a back-edge, pointing back to enclosing while statement); null if successor is end of procedure body (or if field has not yet been initialized)
-
- public BigBlock(IToken tok, string labelName, [Captured] List<Cmd> simpleCmds, StructuredCmd ec, TransferCmd tc) {
- Contract.Requires(simpleCmds != null);
- Contract.Requires(tok != null);
- Contract.Requires(ec == null || tc == null);
- this.tok = tok;
- this.Anonymous = labelName == null;
- this.labelName = labelName;
- this._simpleCmds = simpleCmds;
- this._ec = ec;
- this._tc = tc;
- }
-
- public void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- if (!Anonymous) {
- stream.WriteLine(level, "{0}:",
- CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.LabelName) : this.LabelName);
- }
-
- foreach (Cmd/*!*/ c in this.simpleCmds) {
- Contract.Assert(c != null);
- c.Emit(stream, level + 1);
- }
-
- if (this.ec != null) {
- this.ec.Emit(stream, level + 1);
- } else if (this.tc != null) {
- this.tc.Emit(stream, level + 1);
- }
- }
- }
-
- public class StmtList {
- [Rep]
- private readonly List<BigBlock/*!*/>/*!*/ bigBlocks;
-
- public IList<BigBlock/*!*/>/*!*/ BigBlocks
- {
- get
- {
- Contract.Ensures(Contract.Result<IList<BigBlock>>() != null);
- Contract.Ensures(Contract.Result<IList<BigBlock>>().IsReadOnly);
- return this.bigBlocks.AsReadOnly();
- }
- }
-
- public List<Cmd> PrefixCommands;
- public readonly IToken/*!*/ EndCurly;
- public StmtList ParentContext;
- public BigBlock ParentBigBlock;
-
- private readonly HashSet<string/*!*/>/*!*/ labels = new HashSet<string/*!*/>();
-
- public void AddLabel(string label)
- {
- labels.Add(label);
- }
-
- public IEnumerable<string/*!*/>/*!*/ Labels
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string/*!*/>/*!*/>()));
- return this.labels.AsEnumerable<string>();
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(EndCurly != null);
- Contract.Invariant(cce.NonNullElements(this.bigBlocks));
- Contract.Invariant(cce.NonNullElements(this.labels));
- }
-
- public StmtList(IList<BigBlock/*!*/>/*!*/ bigblocks, IToken endCurly) {
- Contract.Requires(endCurly != null);
- Contract.Requires(cce.NonNullElements(bigblocks));
- Contract.Requires(bigblocks.Count > 0);
- this.bigBlocks = new List<BigBlock>(bigblocks);
- this.EndCurly = endCurly;
- }
-
- // prints the list of statements, not the surrounding curly braces
- public void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- bool needSeperator = false;
- foreach (BigBlock b in BigBlocks) {
- Contract.Assert(b != null);
- Contract.Assume(cce.IsPeerConsistent(b));
- if (needSeperator) {
- stream.WriteLine();
- }
- b.Emit(stream, level);
- needSeperator = true;
- }
- }
-
- /// <summary>
- /// Tries to insert the commands "prefixCmds" at the beginning of the first block
- /// of the StmtList, and returns "true" iff it succeeded.
- /// In the event of success, the "suggestedLabel" returns as the name of the
- /// block inside StmtList where "prefixCmds" were inserted. This name may be the
- /// same as the one passed in, in case this StmtList has no preference as to what
- /// to call its first block. In the event of failure, "suggestedLabel" is returned
- /// as its input value.
- /// Note, to be conservative (that is, ignoring the possible optimization that this
- /// method enables), this method can do nothing and return false.
- /// </summary>
- public bool PrefixFirstBlock([Captured] List<Cmd> prefixCmds, ref string suggestedLabel) {
- Contract.Requires(suggestedLabel != null);
- Contract.Requires(prefixCmds != null);
- Contract.Ensures(Contract.Result<bool>() || cce.Owner.None(prefixCmds)); // "prefixCmds" is captured only on success
- Contract.Assume(PrefixCommands == null); // prefix has not been used
-
- BigBlock bb0 = BigBlocks[0];
- if (prefixCmds.Count == 0) {
- // This is always a success, since there is nothing to insert. Now, decide
- // which name to use for the first block.
- if (bb0.Anonymous) {
- bb0.LabelName = suggestedLabel;
- } else {
- Contract.Assert(bb0.LabelName != null);
- suggestedLabel = bb0.LabelName;
- }
- return true;
-
- } else {
- // There really is something to insert. We can do this inline only if the first
- // block is anonymous (which implies there is no branch to it from within the block).
- if (bb0.Anonymous) {
- PrefixCommands = prefixCmds;
- bb0.LabelName = suggestedLabel;
- return true;
- } else {
- return false;
- }
- }
- }
- }
-
- /// <summary>
- /// The AST for Boogie structured commands was designed to support backward compatibility with
- /// the Boogie unstructured commands. This has made the structured commands hard to construct.
- /// The StmtListBuilder class makes it easier to build structured commands.
- /// </summary>
- public class StmtListBuilder {
- List<BigBlock/*!*/>/*!*/ bigBlocks = new List<BigBlock/*!*/>();
- string label;
- List<Cmd> simpleCmds;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(bigBlocks));
- }
-
- void Dump(StructuredCmd scmd, TransferCmd tcmd) {
- Contract.Requires(scmd == null || tcmd == null);
- Contract.Ensures(label == null && simpleCmds == null);
- if (label == null && simpleCmds == null && scmd == null && tcmd == null) {
- // nothing to do
- } else {
- if (simpleCmds == null) {
- simpleCmds = new List<Cmd>();
- }
- bigBlocks.Add(new BigBlock(Token.NoToken, label, simpleCmds, scmd, tcmd));
- label = null;
- simpleCmds = null;
- }
- }
-
- /// <summary>
- /// Collects the StmtList built so far and returns it. The StmtListBuilder should no longer
- /// be used once this method has been invoked.
- /// </summary>
- public StmtList Collect(IToken endCurlyBrace) {
- Contract.Requires(endCurlyBrace != null);
- Contract.Ensures(Contract.Result<StmtList>() != null);
- Dump(null, null);
- if (bigBlocks.Count == 0) {
- simpleCmds = new List<Cmd>(); // the StmtList constructor doesn't like an empty list of BigBlock's
- Dump(null, null);
- }
- return new StmtList(bigBlocks, endCurlyBrace);
- }
-
- public void Add(Cmd cmd) {
- Contract.Requires(cmd != null);
- if (simpleCmds == null) {
- simpleCmds = new List<Cmd>();
- }
- simpleCmds.Add(cmd);
- }
-
- public void Add(StructuredCmd scmd) {
- Contract.Requires(scmd != null);
- Dump(scmd, null);
- }
-
- public void Add(TransferCmd tcmd) {
- Contract.Requires(tcmd != null);
- Dump(null, tcmd);
- }
-
- public void AddLabelCmd(string label) {
- Contract.Requires(label != null);
- Dump(null, null);
- this.label = label;
- }
-
- public void AddLocalVariable(string name) {
- Contract.Requires(name != null);
- // TODO
- }
- }
-
- class BigBlocksResolutionContext {
- StmtList/*!*/ stmtList;
- [Peer]
- List<Block/*!*/> blocks;
- string/*!*/ prefix = "anon";
- int anon = 0;
- int FreshAnon()
- {
- return anon++;
- }
- HashSet<string/*!*/> allLabels = new HashSet<string/*!*/>();
- Errors/*!*/ errorHandler;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(stmtList != null);
- Contract.Invariant(cce.NonNullElements(blocks, true));
- Contract.Invariant(prefix != null);
- Contract.Invariant(cce.NonNullElements(allLabels, true));
- Contract.Invariant(errorHandler != null);
- }
-
- private void ComputeAllLabels(StmtList stmts) {
- if (stmts == null) return;
- foreach (BigBlock bb in stmts.BigBlocks) {
- if (bb.LabelName != null) {
- allLabels.Add(bb.LabelName);
- }
- ComputeAllLabels(bb.ec);
- }
- }
-
- private void ComputeAllLabels(StructuredCmd cmd) {
- if (cmd == null) return;
- if (cmd is IfCmd) {
- IfCmd ifCmd = (IfCmd)cmd;
- ComputeAllLabels(ifCmd.thn);
- ComputeAllLabels(ifCmd.elseIf);
- ComputeAllLabels(ifCmd.elseBlock);
- }
- else if (cmd is WhileCmd) {
- WhileCmd whileCmd = (WhileCmd)cmd;
- ComputeAllLabels(whileCmd.Body);
- }
- }
-
- public BigBlocksResolutionContext(StmtList stmtList, Errors errorHandler) {
- Contract.Requires(errorHandler != null);
- Contract.Requires(stmtList != null);
- this.stmtList = stmtList;
- this.errorHandler = errorHandler;
- ComputeAllLabels(stmtList);
- }
-
- public List<Block/*!*/>/*!*/ Blocks {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- if (blocks == null) {
- blocks = new List<Block/*!*/>();
-
- int startErrorCount = this.errorHandler.count;
- // Check that all goto statements go to a label in allLabels, and no break statement to a non-enclosing loop.
- // Also, determine a good value for "prefix".
- CheckLegalLabels(stmtList, null, null);
-
- // fill in names of anonymous blocks
- NameAnonymousBlocks(stmtList);
-
- // determine successor blocks
- RecordSuccessors(stmtList, null);
-
- if (this.errorHandler.count == startErrorCount) {
- // generate blocks from the big blocks
- CreateBlocks(stmtList, null);
- }
- }
- return blocks;
- }
- }
-
- void CheckLegalLabels(StmtList stmtList, StmtList parentContext, BigBlock parentBigBlock) {
- Contract.Requires(stmtList != null);
- Contract.Requires((parentContext == null) == (parentBigBlock == null));
- Contract.Requires(stmtList.ParentContext == null); // it hasn't been set yet
- //modifies stmtList.*;
- Contract.Ensures(stmtList.ParentContext == parentContext);
- stmtList.ParentContext = parentContext;
- stmtList.ParentBigBlock = parentBigBlock;
-
- // record the labels declared in this StmtList
- foreach (BigBlock b in stmtList.BigBlocks) {
- if (b.LabelName != null) {
- string n = b.LabelName;
- if (n.StartsWith(prefix)) {
- if (prefix.Length < n.Length && n[prefix.Length] == '0') {
- prefix += "1";
- } else {
- prefix += "0";
- }
- }
- stmtList.AddLabel(b.LabelName);
- }
- }
-
- // check that labels in this and nested StmtList's are legal
- foreach (BigBlock b in stmtList.BigBlocks) {
- // goto's must reference blocks in enclosing blocks
- if (b.tc is GotoCmd) {
- GotoCmd g = (GotoCmd)b.tc;
- foreach (string/*!*/ lbl in cce.NonNull(g.labelNames)) {
- Contract.Assert(lbl != null);
- /*
- bool found = false;
- for (StmtList sl = stmtList; sl != null; sl = sl.ParentContext) {
- if (sl.Labels.Contains(lbl)) {
- found = true;
- break;
- }
- }
- if (!found) {
- this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined or out of reach");
- }
- */
- if (!allLabels.Contains(lbl)) {
- this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined");
- }
- }
- }
-
- // break labels must refer to an enclosing while statement
- else if (b.ec is BreakCmd) {
- BreakCmd bcmd = (BreakCmd)b.ec;
- Contract.Assert(bcmd.BreakEnclosure == null); // it hasn't been initialized yet
- bool found = false;
- for (StmtList sl = stmtList; sl.ParentBigBlock != null; sl = sl.ParentContext) {
- cce.LoopInvariant(sl != null);
- BigBlock bb = sl.ParentBigBlock;
-
- if (bcmd.Label == null) {
- // a label-less break statement breaks out of the innermost enclosing while statement
- if (bb.ec is WhileCmd) {
- bcmd.BreakEnclosure = bb;
- found = true;
- break;
- }
- } else if (bcmd.Label == bb.LabelName) {
- // a break statement with a label can break out of both if statements and while statements
- if (bb.simpleCmds.Count == 0) {
- // this is a good target: the label refers to the if/while statement
- bcmd.BreakEnclosure = bb;
- } else {
- // the label of bb refers to the first statement of bb, which in which case is a simple statement, not an if/while statement
- this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
- }
- found = true; // don't look any further, since we've found a matching label
- break;
- }
- }
- if (!found) {
- if (bcmd.Label == null) {
- this.errorHandler.SemErr(bcmd.tok, "Error: break statement is not inside a loop");
- } else {
- this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
- }
- }
- }
-
- // recurse
- else if (b.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)b.ec;
- CheckLegalLabels(wcmd.Body, stmtList, b);
- } else {
- for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
- CheckLegalLabels(ifcmd.thn, stmtList, b);
- if (ifcmd.elseBlock != null) {
- CheckLegalLabels(ifcmd.elseBlock, stmtList, b);
- }
- }
- }
- }
- }
-
- void NameAnonymousBlocks(StmtList stmtList) {
- Contract.Requires(stmtList != null);
- foreach (BigBlock b in stmtList.BigBlocks) {
- if (b.LabelName == null) {
- b.LabelName = prefix + FreshAnon();
- }
- if (b.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)b.ec;
- NameAnonymousBlocks(wcmd.Body);
- } else {
- for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
- NameAnonymousBlocks(ifcmd.thn);
- if (ifcmd.elseBlock != null) {
- NameAnonymousBlocks(ifcmd.elseBlock);
- }
- }
- }
- }
- }
-
- void RecordSuccessors(StmtList stmtList, BigBlock successor) {
- Contract.Requires(stmtList != null);
- for (int i = stmtList.BigBlocks.Count; 0 <= --i; ) {
- BigBlock big = stmtList.BigBlocks[i];
- big.successorBigBlock = successor;
-
- if (big.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)big.ec;
- RecordSuccessors(wcmd.Body, big);
- } else {
- for (IfCmd ifcmd = big.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
- RecordSuccessors(ifcmd.thn, successor);
- if (ifcmd.elseBlock != null) {
- RecordSuccessors(ifcmd.elseBlock, successor);
- }
- }
- }
-
- successor = big;
- }
- }
-
- // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label;
- // otherwise, it is null.
- void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) {
- Contract.Requires(stmtList != null);
- Contract.Requires(blocks != null);
- List<Cmd> cmdPrefixToApply = stmtList.PrefixCommands;
-
- int n = stmtList.BigBlocks.Count;
- foreach (BigBlock b in stmtList.BigBlocks) {
- n--;
- Contract.Assert(b.LabelName != null);
- List<Cmd> theSimpleCmds;
- if (cmdPrefixToApply == null) {
- theSimpleCmds = b.simpleCmds;
- } else {
- theSimpleCmds = new List<Cmd>();
- theSimpleCmds.AddRange(cmdPrefixToApply);
- theSimpleCmds.AddRange(b.simpleCmds);
- cmdPrefixToApply = null; // now, we've used 'em up
- }
-
- if (b.tc != null) {
- // this BigBlock has the very same components as a Block
- Contract.Assert(b.ec == null);
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc);
- blocks.Add(block);
-
- } else if (b.ec == null) {
- TransferCmd trCmd;
- if (n == 0 && runOffTheEndLabel != null) {
- // goto the given label instead of the textual successor block
- trCmd = new GotoCmd(stmtList.EndCurly, new List<String> { runOffTheEndLabel });
- } else {
- trCmd = GotoSuccessor(stmtList.EndCurly, b);
- }
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd);
- blocks.Add(block);
-
- } else if (b.ec is BreakCmd) {
- BreakCmd bcmd = (BreakCmd)b.ec;
- Contract.Assert(bcmd.BreakEnclosure != null);
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure));
- blocks.Add(block);
-
- } else if (b.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)b.ec;
- var a = FreshAnon();
- string loopHeadLabel = prefix + a + "_LoopHead";
- string/*!*/ loopBodyLabel = prefix + a + "_LoopBody";
- string loopDoneLabel = prefix + a + "_LoopDone";
-
- List<Cmd> ssBody = new List<Cmd>();
- List<Cmd> ssDone = new List<Cmd>();
- if (wcmd.Guard != null) {
- var ac = new AssumeCmd(wcmd.tok, wcmd.Guard);
- ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null);
- ssBody.Add(ac);
-
- ac = new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard));
- ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null);
- ssDone.Add(ac);
- }
-
- // Try to squeeze in ssBody into the first block of wcmd.Body
- bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel);
-
- // ... goto LoopHead;
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new List<String> { loopHeadLabel }));
- blocks.Add(block);
-
- // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody;
- List<Cmd> ssHead = new List<Cmd>();
- foreach (PredicateCmd inv in wcmd.Invariants) {
- ssHead.Add(inv);
- }
- block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new List<String> { loopDoneLabel, loopBodyLabel }));
- blocks.Add(block);
-
- if (!bodyGuardTakenCareOf) {
- // LoopBody: assume guard; goto firstLoopBlock;
- block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new List<String> { wcmd.Body.BigBlocks[0].LabelName }));
- blocks.Add(block);
- }
-
- // recurse to create the blocks for the loop body
- CreateBlocks(wcmd.Body, loopHeadLabel);
-
- // LoopDone: assume !guard; goto loopSuccessor;
- TransferCmd trCmd;
- if (n == 0 && runOffTheEndLabel != null) {
- // goto the given label instead of the textual successor block
- trCmd = new GotoCmd(wcmd.tok, new List<String> { runOffTheEndLabel });
- } else {
- trCmd = GotoSuccessor(wcmd.tok, b);
- }
- block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd);
- blocks.Add(block);
-
- } else {
- IfCmd ifcmd = (IfCmd)b.ec;
- string predLabel = b.LabelName;
- List<Cmd> predCmds = theSimpleCmds;
-
- for (; ifcmd != null; ifcmd = ifcmd.elseIf) {
- var a = FreshAnon();
- string thenLabel = prefix + a + "_Then";
- Contract.Assert(thenLabel != null);
- string elseLabel = prefix + a + "_Else";
- Contract.Assert(elseLabel != null);
-
- List<Cmd> ssThen = new List<Cmd>();
- List<Cmd> ssElse = new List<Cmd>();
- if (ifcmd.Guard != null) {
- var ac = new AssumeCmd(ifcmd.tok, ifcmd.Guard);
- ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
- ssThen.Add(ac);
-
- ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard));
- ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
- ssElse.Add(ac);
- }
-
- // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock
- bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel);
- bool elseGuardTakenCareOf = false;
- if (ifcmd.elseBlock != null) {
- elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel);
- }
-
- // ... goto Then, Else;
- Block block = new Block(b.tok, predLabel, predCmds,
- new GotoCmd(ifcmd.tok, new List<String> { thenLabel, elseLabel }));
- blocks.Add(block);
-
- if (!thenGuardTakenCareOf) {
- // Then: assume guard; goto firstThenBlock;
- block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.thn.BigBlocks[0].LabelName }));
- blocks.Add(block);
- }
-
- // recurse to create the blocks for the then branch
- CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null);
-
- if (ifcmd.elseBlock != null) {
- Contract.Assert(ifcmd.elseIf == null);
- if (!elseGuardTakenCareOf) {
- // Else: assume !guard; goto firstElseBlock;
- block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.elseBlock.BigBlocks[0].LabelName }));
- blocks.Add(block);
- }
-
- // recurse to create the blocks for the else branch
- CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null);
-
- } else if (ifcmd.elseIf != null) {
- // this is an "else if"
- predLabel = elseLabel;
- predCmds = new List<Cmd>();
- if (ifcmd.Guard != null) {
- var ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard));
- ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
- predCmds.Add(ac);
- }
-
- } else {
- // no else alternative is specified, so else branch is just "skip"
- // Else: assume !guard; goto ifSuccessor;
- TransferCmd trCmd;
- if (n == 0 && runOffTheEndLabel != null) {
- // goto the given label instead of the textual successor block
- trCmd = new GotoCmd(ifcmd.tok, new List<String> { runOffTheEndLabel });
- } else {
- trCmd = GotoSuccessor(ifcmd.tok, b);
- }
- block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd);
- blocks.Add(block);
- }
- }
- }
- }
- }
-
- TransferCmd GotoSuccessor(IToken tok, BigBlock b) {
- Contract.Requires(b != null);
- Contract.Requires(tok != null);
- Contract.Ensures(Contract.Result<TransferCmd>() != null);
- if (b.successorBigBlock != null) {
- return new GotoCmd(tok, new List<String> { b.successorBigBlock.LabelName });
- } else {
- return new ReturnCmd(tok);
- }
- }
- }
-
- [ContractClass(typeof(StructuredCmdContracts))]
- public abstract class StructuredCmd {
- private IToken/*!*/ _tok;
-
- public IToken/*!*/ tok
- {
- get
- {
- Contract.Ensures(Contract.Result<IToken>() != null);
- return this._tok;
- }
- set
- {
- Contract.Requires(value != null);
- this._tok = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._tok != null);
- }
-
- public StructuredCmd(IToken tok) {
- Contract.Requires(tok != null);
- this._tok = tok;
- }
-
- public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
- }
- [ContractClassFor(typeof(StructuredCmd))]
- public abstract class StructuredCmdContracts : StructuredCmd {
- public override void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- throw new NotImplementedException();
- }
- public StructuredCmdContracts() :base(null){
-
- }
- }
-
- public class IfCmd : StructuredCmd {
- public Expr Guard;
-
- private StmtList/*!*/ _thn;
-
- public StmtList/*!*/ thn
- {
- get
- {
- Contract.Ensures(Contract.Result<StmtList>() != null);
- return this._thn;
- }
- set
- {
- Contract.Requires(value != null);
- this._thn = value;
- }
- }
-
- private IfCmd _elseIf;
-
- public IfCmd elseIf
- {
- get
- {
- return this._elseIf;
- }
- set
- {
- Contract.Requires(value == null || this.elseBlock == null);
- this._elseIf = value;
- }
- }
-
- private StmtList _elseBlock;
-
- public StmtList elseBlock
- {
- get
- {
- return this._elseBlock;
- }
- set
- {
- Contract.Requires(value == null || this.elseIf == null);
- this._elseBlock = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._thn != null);
- Contract.Invariant(this._elseIf == null || this._elseBlock == null);
- }
-
- public IfCmd(IToken/*!*/ tok, Expr guard, StmtList/*!*/ thn, IfCmd elseIf, StmtList elseBlock)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(thn != null);
- Contract.Requires(elseIf == null || elseBlock == null);
- this.Guard = guard;
- this._thn = thn;
- this._elseIf = elseIf;
- this._elseBlock = elseBlock;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- stream.Write(level, "if (");
- IfCmd/*!*/ ifcmd = this;
- while (true) {
- if (ifcmd.Guard == null) {
- stream.Write("*");
- } else {
- ifcmd.Guard.Emit(stream);
- }
- stream.WriteLine(")");
-
- stream.WriteLine(level, "{");
- ifcmd.thn.Emit(stream, level + 1);
- stream.WriteLine(level, "}");
-
- if (ifcmd.elseIf != null) {
- stream.Write(level, "else if (");
- ifcmd = ifcmd.elseIf;
- continue;
- } else if (ifcmd.elseBlock != null) {
- stream.WriteLine(level, "else");
- stream.WriteLine(level, "{");
- ifcmd.elseBlock.Emit(stream, level + 1);
- stream.WriteLine(level, "}");
- }
- break;
- }
- }
- }
-
- public class WhileCmd : StructuredCmd {
- [Peer]
- public Expr Guard;
- public List<PredicateCmd/*!*/>/*!*/ Invariants;
- public StmtList/*!*/ Body;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Body != null);
- Contract.Invariant(cce.NonNullElements(Invariants));
- }
-
-
- public WhileCmd(IToken tok, [Captured] Expr guard, List<PredicateCmd/*!*/>/*!*/ invariants, StmtList/*!*/ body)
- : base(tok) {
- Contract.Requires(cce.NonNullElements(invariants));
- Contract.Requires(body != null);
- Contract.Requires(tok != null);
- this.Guard = guard;
- this.Invariants = invariants;
- this.Body = body;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- stream.Write(level, "while (");
- if (Guard == null) {
- stream.Write("*");
- } else {
- Guard.Emit(stream);
- }
- stream.WriteLine(")");
-
- foreach (PredicateCmd inv in Invariants) {
- if (inv is AssumeCmd) {
- stream.Write(level + 1, "free invariant ");
- } else {
- stream.Write(level + 1, "invariant ");
- }
- Cmd.EmitAttributes(stream, inv.Attributes);
- inv.Expr.Emit(stream);
- stream.WriteLine(";");
- }
-
- stream.WriteLine(level, "{");
- Body.Emit(stream, level + 1);
- stream.WriteLine(level, "}");
- }
- }
-
- public class BreakCmd : StructuredCmd {
- public string Label;
- public BigBlock BreakEnclosure;
-
- public BreakCmd(IToken tok, string label)
- : base(tok) {
- Contract.Requires(tok != null);
- this.Label = label;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
-
- if (Label == null) {
- stream.WriteLine(level, "break;");
- } else {
- stream.WriteLine(level, "break {0};", Label);
- }
- }
- }
-
- //---------------------------------------------------------------------
- // Block
- public sealed class Block : Absy {
- private string/*!*/ label; // Note, Label is mostly readonly, but it can change to the name of a nearby block during block coalescing and empty-block removal
-
- public string/*!*/ Label
- {
- get
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return this.label;
- }
- set
- {
- Contract.Requires(value != null);
- this.label = value;
- }
- }
-
- [Rep]
- [ElementsPeer]
- public List<Cmd>/*!*/ cmds;
-
- public List<Cmd>/*!*/ Cmds
- {
- get
- {
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- return this.cmds;
- }
- set
- {
- Contract.Requires(value != null);
- this.cmds = value;
- }
- }
-
- [Rep] //PM: needed to verify Traverse.Visit
- public TransferCmd TransferCmd; // maybe null only because we allow deferred initialization (necessary for cyclic structures)
-
- public byte[] Checksum;
-
- // Abstract interpretation
-
- // public bool currentlyTraversed;
-
- public enum VisitState {
- ToVisit,
- BeingVisited,
- AlreadyVisited
- }; // used by WidenPoints.Compute
- public VisitState TraversingStatus;
-
- public int aiId; // block ID used by the abstract interpreter, which may change these numbers with each AI run
- public bool widenBlock;
- public int iterations; // Count the number of time we visited the block during fixpoint computation. Used to decide if we widen or not
-
- // VC generation and SCC computation
- public List<Block>/*!*/ Predecessors;
-
- // This field is used during passification to null-out entries in block2Incartion hashtable early
- public int succCount;
-
- private HashSet<Variable/*!*/> _liveVarsBefore;
-
- public IEnumerable<Variable/*!*/> liveVarsBefore
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Variable/*!*/>>(), true));
- if (this._liveVarsBefore == null)
- return null;
- else
- return this._liveVarsBefore.AsEnumerable<Variable>();
- }
- set
- {
- Contract.Requires(cce.NonNullElements(value, true));
- if (value == null)
- this._liveVarsBefore = null;
- else
- this._liveVarsBefore = new HashSet<Variable>(value);
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this.label != null);
- Contract.Invariant(this.cmds != null);
- Contract.Invariant(cce.NonNullElements(this._liveVarsBefore, true));
- }
-
- public bool IsLive(Variable v) {
- Contract.Requires(v != null);
- if (liveVarsBefore == null)
- return true;
- return liveVarsBefore.Contains(v);
- }
-
- public Block()
- : this(Token.NoToken, "", new List<Cmd>(), new ReturnCmd(Token.NoToken)) {
-
- }
-
- public Block(IToken tok, string/*!*/ label, List<Cmd>/*!*/ cmds, TransferCmd transferCmd)
- : base(tok) {
- Contract.Requires(label != null);
- Contract.Requires(cmds != null);
- Contract.Requires(tok != null);
- this.label = label;
- this.cmds = cmds;
- this.TransferCmd = transferCmd;
- this.Predecessors = new List<Block>();
- this._liveVarsBefore = null;
- this.TraversingStatus = VisitState.ToVisit;
- this.iterations = 0;
- }
-
- public void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- stream.WriteLine();
- stream.WriteLine(
- this,
- level,
- "{0}:{1}",
- CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.Label) : this.Label,
- this.widenBlock ? " // cut point" : "");
-
- foreach (Cmd/*!*/ c in this.Cmds) {
- Contract.Assert(c != null);
- c.Emit(stream, level + 1);
- }
- Contract.Assume(this.TransferCmd != null);
- this.TransferCmd.Emit(stream, level + 1);
- }
-
- public void Register(ResolutionContext rc) {
- Contract.Requires(rc != null);
- rc.AddBlock(this);
- }
-
- public override void Resolve(ResolutionContext rc) {
-
-
- foreach (Cmd/*!*/ c in Cmds) {
- Contract.Assert(c != null);
- c.Resolve(rc);
- }
- Contract.Assume(this.TransferCmd != null);
- TransferCmd.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
-
- foreach (Cmd/*!*/ c in Cmds) {
- Contract.Assert(c != null);
- c.Typecheck(tc);
- }
- Contract.Assume(this.TransferCmd != null);
- TransferCmd.Typecheck(tc);
- }
-
- /// <summary>
- /// Reset the abstract intepretation state of this block. It does this by putting the iterations to 0 and the pre and post states to null
- /// </summary>
- public void ResetAbstractInterpretationState() {
- // this.currentlyTraversed = false;
- this.TraversingStatus = VisitState.ToVisit;
- this.iterations = 0;
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return this.Label + (this.widenBlock ? "[w]" : "");
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
-
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBlock(this);
- }
- }
-
- //---------------------------------------------------------------------
- // Commands
- [ContractClassFor(typeof(Cmd))]
- public abstract class CmdContracts : Cmd {
- public CmdContracts() :base(null){
-
- }
- public override void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- throw new NotImplementedException();
- }
- public override void AddAssignedVariables(List<Variable> vars) {
- Contract.Requires(vars != null);
- throw new NotImplementedException();
- }
- }
-
- public static class ChecksumHelper
- {
- public static void ComputeChecksums(Cmd cmd, Implementation impl, ISet<Variable> usedVariables, byte[] currentChecksum = null)
- {
- if (CommandLineOptions.Clo.VerifySnapshots < 2)
- {
- return;
- }
-
- var assumeCmd = cmd as AssumeCmd;
- if (assumeCmd != null
- && QKeyValue.FindBoolAttribute(assumeCmd.Attributes, "assumption_variable_initialization"))
- {
- // Ignore assumption variable initializations.
- assumeCmd.Checksum = currentChecksum;
- return;
- }
-
- using (var strWr = new System.IO.StringWriter())
- using (var tokTxtWr = new TokenTextWriter("<no file>", strWr, false, false))
- {
- tokTxtWr.UseForComputingChecksums = true;
- var havocCmd = cmd as HavocCmd;
- if (havocCmd != null)
- {
- tokTxtWr.Write("havoc ");
- var relevantVars = havocCmd.Vars.Where(e => usedVariables.Contains(e.Decl) && !e.Decl.Name.StartsWith("a##post##")).OrderBy(e => e.Name).ToList();
- relevantVars.Emit(tokTxtWr, true);
- tokTxtWr.WriteLine(";");
- }
- else
- {
- cmd.Emit(tokTxtWr, 0);
- }
- var md5 = System.Security.Cryptography.MD5.Create();
- var str = strWr.ToString();
- if (str.Any())
- {
- var data = System.Text.Encoding.UTF8.GetBytes(str);
- var checksum = md5.ComputeHash(data);
- currentChecksum = currentChecksum != null ? CombineChecksums(currentChecksum, checksum) : checksum;
- }
- cmd.Checksum = currentChecksum;
- }
-
- var assertCmd = cmd as AssertCmd;
- if (assertCmd != null && assertCmd.Checksum != null)
- {
- var assertRequiresCmd = assertCmd as AssertRequiresCmd;
- if (assertRequiresCmd != null)
- {
- impl.AddAssertionChecksum(assertRequiresCmd.Checksum);
- impl.AddAssertionChecksum(assertRequiresCmd.Call.Checksum);
- assertRequiresCmd.SugaredCmdChecksum = assertRequiresCmd.Call.Checksum;
- }
- else
- {
- impl.AddAssertionChecksum(assertCmd.Checksum);
- }
- }
-
- var sugaredCmd = cmd as SugaredCmd;
- if (sugaredCmd != null)
- {
- // The checksum of a sugared command should not depend on the desugaring itself.
- var stateCmd = sugaredCmd.Desugaring as StateCmd;
- if (stateCmd != null)
- {
- foreach (var c in stateCmd.Cmds)
- {
- ComputeChecksums(c, impl, usedVariables, currentChecksum);
- currentChecksum = c.Checksum;
- if (c.SugaredCmdChecksum == null)
- {
- c.SugaredCmdChecksum = cmd.Checksum;
- }
- }
- }
- else
- {
- ComputeChecksums(sugaredCmd.Desugaring, impl, usedVariables, currentChecksum);
- }
- }
- }
-
- public static byte[] CombineChecksums(byte[] first, byte[] second, bool unordered = false)
- {
- Contract.Requires(first != null && (second == null || first.Length == second.Length));
-
- var result = (byte[])(first.Clone());
- for (int i = 0; second != null && i < second.Length; i++)
- {
- if (unordered)
- {
- result[i] += second[i];
- }
- else
- {
- result[i] = (byte)(result[i] * 31 ^ second[i]);
- }
- }
- return result;
- }
- }
-
- [ContractClass(typeof(CmdContracts))]
- public abstract class Cmd : Absy {
- public byte[] Checksum { get; internal set; }
- public byte[] SugaredCmdChecksum { get; internal set; }
-
- public Cmd(IToken/*!*/ tok)
- : base(tok) {
- Contract.Assert(tok != null);
- }
- public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
- public abstract void AddAssignedVariables(List<Variable>/*!*/ vars);
- public void CheckAssignments(TypecheckingContext tc)
- {
- Contract.Requires(tc != null);
- List<Variable>/*!*/ vars = new List<Variable>();
- this.AddAssignedVariables(vars);
- foreach (Variable/*!*/ v in vars)
- {
- Contract.Assert(v != null);
- if (!v.IsMutable)
- {
- tc.Error(this, "command assigns to an immutable variable: {0}", v.Name);
- }
- else if (!CommandLineOptions.Clo.DoModSetAnalysis && v is GlobalVariable)
- {
- if (tc.Yields) {
- // a yielding procedure is allowed to modify any global variable
- }
- else if (tc.Frame == null)
- {
- tc.Error(this, "update to a global variable allowed only inside an atomic action of a yielding procedure");
- }
- else if (!tc.InFrame(v))
- {
- tc.Error(this, "command assigns to a global variable that is not in the enclosing procedure's modifies clause: {0}", v.Name);
- }
- }
- }
- }
-
- // Methods to simulate the old SimpleAssignCmd and MapAssignCmd
- public static AssignCmd SimpleAssign(IToken tok, IdentifierExpr lhs, Expr rhs) {
- Contract.Requires(rhs != null);
- Contract.Requires(lhs != null);
- Contract.Requires(tok != null);
- Contract.Ensures(Contract.Result<AssignCmd>() != null);
- List<AssignLhs/*!*/>/*!*/ lhss = new List<AssignLhs/*!*/>();
- List<Expr/*!*/>/*!*/ rhss = new List<Expr/*!*/>();
-
- lhss.Add(new SimpleAssignLhs(lhs.tok, lhs));
- rhss.Add(rhs);
-
- return new AssignCmd(tok, lhss, rhss);
- }
-
- public static AssignCmd/*!*/ MapAssign(IToken tok,
- IdentifierExpr/*!*/ map,
- List<Expr>/*!*/ indexes, Expr/*!*/ rhs) {
-
- Contract.Requires(tok != null);
- Contract.Requires(map != null);
- Contract.Requires(indexes != null);
- Contract.Requires(rhs != null);
- Contract.Ensures(Contract.Result<AssignCmd>() != null);
- List<AssignLhs/*!*/>/*!*/ lhss = new List<AssignLhs/*!*/>();
- List<Expr/*!*/>/*!*/ rhss = new List<Expr/*!*/>();
- List<Expr/*!*/>/*!*/ indexesList = new List<Expr/*!*/>();
-
-
-
- foreach (Expr e in indexes)
- indexesList.Add(cce.NonNull(e));
-
- lhss.Add(new MapAssignLhs(map.tok,
- new SimpleAssignLhs(map.tok, map),
- indexesList));
- rhss.Add(rhs);
-
- return new AssignCmd(tok, lhss, rhss);
- }
-
- public static AssignCmd/*!*/ MapAssign(IToken tok,
- IdentifierExpr/*!*/ map,
- params Expr[]/*!*/ args) {
- Contract.Requires(tok != null);
- Contract.Requires(map != null);
- Contract.Requires(args != null);
- Contract.Requires(args.Length > 0); // at least the rhs
- Contract.Requires(Contract.ForAll(args, i => i != null));
- Contract.Ensures(Contract.Result<AssignCmd>() != null);
-
- List<AssignLhs/*!*/>/*!*/ lhss = new List<AssignLhs/*!*/>();
- List<Expr/*!*/>/*!*/ rhss = new List<Expr/*!*/>();
- List<Expr/*!*/>/*!*/ indexesList = new List<Expr/*!*/>();
-
- for (int i = 0; i < args.Length - 1; ++i)
- indexesList.Add(cce.NonNull(args[i]));
-
- lhss.Add(new MapAssignLhs(map.tok,
- new SimpleAssignLhs(map.tok, map),
- indexesList));
- rhss.Add(cce.NonNull(args[args.Length - 1]));
-
- return new AssignCmd(tok, lhss, rhss);
- }
-
- /// <summary>
- /// This is a helper routine for printing a linked list of attributes. Each attribute
- /// is terminated by a space.
- /// </summary>
- public static void EmitAttributes(TokenTextWriter stream, QKeyValue attributes) {
- Contract.Requires(stream != null);
-
- if (stream.UseForComputingChecksums) { return; }
-
- for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
- kv.Emit(stream);
- stream.Write(" ");
- }
- }
- public static void ResolveAttributes(QKeyValue attributes, ResolutionContext rc) {
- Contract.Requires(rc != null);
- for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
- kv.Resolve(rc);
- }
- }
- public static void TypecheckAttributes(QKeyValue attributes, TypecheckingContext tc) {
- Contract.Requires(tc != null);
- for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(tc);
- }
- }
-
- [Pure]
- public override string ToString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false , /*pretty=*/ false)) {
- this.Emit(stream, 0);
- }
- return buffer.ToString();
- }
- }
-
- public class YieldCmd : Cmd
- {
- public YieldCmd(IToken/*!*/ tok)
- : base(tok)
- {
- Contract.Requires(tok != null);
- }
- public override void Emit(TokenTextWriter stream, int level)
- {
- //Contract.Requires(stream != null);
- stream.WriteLine(this, level, "yield;");
- }
- public override void Resolve(ResolutionContext rc)
- {
- // nothing to resolve
- }
- public override void Typecheck(TypecheckingContext tc)
- {
- if (!CommandLineOptions.Clo.DoModSetAnalysis && !tc.Yields)
- {
- tc.Error(this, "enclosing procedure of a yield command must yield");
- }
- }
- public override void AddAssignedVariables(List<Variable> vars)
- {
- // nothing to add
- }
- public override Absy StdDispatch(StandardVisitor visitor)
- {
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitYieldCmd(this);
- }
- }
-
- public class CommentCmd : Cmd // just a convenience for debugging
- {
- public readonly string/*!*/ Comment;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Comment != null);
- }
-
- public CommentCmd(string c)
- : base(Token.NoToken) {
- Contract.Requires(c != null);
- Comment = c;
- }
- public override void Emit(TokenTextWriter stream, int level) {
- if (stream.UseForComputingChecksums) { return; }
-
- if (this.Comment.Contains("\n")) {
- stream.WriteLine(this, level, "/* {0} */", this.Comment);
- } else {
- stream.WriteLine(this, level, "// {0}", this.Comment);
- }
- }
- public override void Resolve(ResolutionContext rc) {
-
- }
- public override void AddAssignedVariables(List<Variable> vars) {
-
- }
- public override void Typecheck(TypecheckingContext tc) {
-
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
-
-
- return visitor.VisitCommentCmd(this);
- }
- }
-
- // class for parallel assignments, which subsumes both the old
- // SimpleAssignCmd and the old MapAssignCmd
- public class AssignCmd : Cmd {
- private List<AssignLhs/*!*/>/*!*/ _lhss;
-
- public IList<AssignLhs/*!*/>/*!*/ Lhss {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IList<AssignLhs>>()));
- Contract.Ensures(Contract.Result<IList<AssignLhs>>().IsReadOnly);
- return this._lhss.AsReadOnly();
- }
- set {
- Contract.Requires(cce.NonNullElements(value));
- this._lhss = new List<AssignLhs>(value);
- }
- }
-
- internal void SetLhs(int index, AssignLhs lhs)
- {
- Contract.Requires(0 <= index && index < this.Lhss.Count);
- Contract.Requires(lhs != null);
- Contract.Ensures(this.Lhss[index] == lhs);
- this._lhss[index] = lhs;
- }
-
- private List<Expr/*!*/>/*!*/ _rhss;
-
- public IList<Expr/*!*/>/*!*/ Rhss {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IList<Expr>>()));
- Contract.Ensures(Contract.Result<IList<Expr>>().IsReadOnly);
- return this._rhss.AsReadOnly();
- }
- set {
- Contract.Requires(cce.NonNullElements(value));
- this._rhss = new List<Expr>(value);
- }
- }
-
- internal void SetRhs(int index, Expr rhs)
- {
- Contract.Requires(0 <= index && index < this.Rhss.Count);
- Contract.Requires(rhs != null);
- Contract.Ensures(this.Rhss[index] == rhs);
- this._rhss[index] = rhs;
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(this._lhss));
- Contract.Invariant(cce.NonNullElements(this._rhss));
- }
-
-
- public AssignCmd(IToken tok, IList<AssignLhs/*!*/>/*!*/ lhss, IList<Expr/*!*/>/*!*/ rhss)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(cce.NonNullElements(rhss));
- Contract.Requires(cce.NonNullElements(lhss));
- this._lhss = new List<AssignLhs>(lhss);
- this._rhss = new List<Expr>(rhss);
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- if (stream.UseForComputingChecksums)
- {
- var lhs = Lhss.FirstOrDefault() as SimpleAssignLhs;
- if (lhs != null
- && lhs.AssignedVariable.Decl != null
- && (QKeyValue.FindBoolAttribute(lhs.AssignedVariable.Decl.Attributes, "assumption")
- || lhs.AssignedVariable.Decl.Name.Contains("##old##")))
- {
- return;
- }
- }
-
- stream.Write(this, level, "");
-
- string/*!*/ sep = "";
- foreach (AssignLhs/*!*/ l in Lhss) {
- Contract.Assert(l != null);
- stream.Write(sep);
- sep = ", ";
- l.Emit(stream);
- }
-
- stream.Write(" := ");
-
- sep = "";
- foreach (Expr/*!*/ e in Rhss) {
- Contract.Assert(e != null);
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
-
- stream.WriteLine(";");
- }
-
- public override void Resolve(ResolutionContext rc) {
-
- if (Lhss.Count != Rhss.Count)
- rc.Error(this,
- "number of left-hand sides does not match number of right-hand sides");
-
- foreach (AssignLhs/*!*/ e in Lhss) {
- Contract.Assert(e != null);
- e.Resolve(rc);
- }
- foreach (Expr/*!*/ e in Rhss) {
- Contract.Assert(e != null);
- e.Resolve(rc);
- }
-
- // check for double occurrences of assigned variables
- // (could be optimised)
- for (int i = 0; i < Lhss.Count; ++i) {
- for (int j = i + 1; j < Lhss.Count; ++j) {
- if (cce.NonNull(Lhss[i].DeepAssignedVariable).Equals(
- Lhss[j].DeepAssignedVariable))
- rc.Error(Lhss[j],
- "variable {0} is assigned more than once in parallel assignment",
- Lhss[j].DeepAssignedVariable);
- }
- }
-
- for (int i = 0; i < Lhss.Count; i++)
- {
- var lhs = Lhss[i].AsExpr as IdentifierExpr;
- if (lhs != null && lhs.Decl != null && QKeyValue.FindBoolAttribute(lhs.Decl.Attributes, "assumption"))
- {
- var rhs = Rhss[i] as NAryExpr;
- if (rhs == null
- || !(rhs.Fun is BinaryOperator)
- || ((BinaryOperator)(rhs.Fun)).Op != BinaryOperator.Opcode.And
- || !(rhs.Args[0] is IdentifierExpr)
- || ((IdentifierExpr)(rhs.Args[0])).Name != lhs.Name)
- {
- rc.Error(tok, string.Format("RHS of assignment to assumption variable {0} must match expression \"{0} && <boolean expression>\"", lhs.Name));
- }
- else if (rc.HasVariableBeenAssigned(lhs.Decl.Name))
- {
- rc.Error(tok, "assumption variable may not be assigned to more than once");
- }
- else
- {
- rc.MarkVariableAsAssigned(lhs.Decl.Name);
- }
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext tc) {
-
- foreach (AssignLhs/*!*/ e in Lhss) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
- foreach (Expr/*!*/ e in Rhss) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
-
- this.CheckAssignments(tc);
-
- for (int i = 0; i < Lhss.Count; ++i) {
- Type ltype = Lhss[i].Type;
- Type rtype = Rhss[i].Type;
- if (ltype != null && rtype != null) {
- // otherwise, there has already been an error when
- // typechecking the lhs or rhs
- if (!ltype.Unify(rtype))
- tc.Error(Lhss[i],
- "mismatched types in assignment command (cannot assign {0} to {1})",
- rtype, ltype);
- }
- }
- }
-
- public override void AddAssignedVariables(List<Variable> vars) {
-
- foreach (AssignLhs/*!*/ l in Lhss) {
- Contract.Assert(l != null);
- vars.Add(l.DeepAssignedVariable);
- }
- }
-
- // transform away the syntactic sugar of map assignments and
- // determine an equivalent assignment in which all rhs are simple
- // variables
- public AssignCmd/*!*/ AsSimpleAssignCmd {
- get {
- Contract.Ensures(Contract.Result<AssignCmd>() != null);
-
- List<AssignLhs/*!*/>/*!*/ newLhss = new List<AssignLhs/*!*/>();
- List<Expr/*!*/>/*!*/ newRhss = new List<Expr/*!*/>();
-
- for (int i = 0; i < Lhss.Count; ++i) {
- IdentifierExpr/*!*/ newLhs;
- Expr/*!*/ newRhs;
- Lhss[i].AsSimpleAssignment(Rhss[i], out newLhs, out newRhs);
- newLhss.Add(new SimpleAssignLhs(Token.NoToken, newLhs));
- newRhss.Add(newRhs);
- }
-
- return new AssignCmd(Token.NoToken, newLhss, newRhss);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
-
-
- return visitor.VisitAssignCmd(this);
- }
- }
-
- // There are two different kinds of left-hand sides in assignments:
- // simple variables (identifiers), or locations of a map
- [ContractClass(typeof(AssignLhsContracts))]
- public abstract class AssignLhs : Absy {
- // The type of the lhs is determined during typechecking
- public abstract Type Type {
- get;
- }
- // Determine the variable that is actually assigned in this lhs
- public abstract IdentifierExpr/*!*/ DeepAssignedIdentifier {
- get;
- }
- public abstract Variable DeepAssignedVariable {
- get;
- }
-
- public AssignLhs(IToken/*!*/ tok)
- : base(tok) {
- Contract.Requires(tok != null);
- }
- public abstract void Emit(TokenTextWriter/*!*/ stream);
-
- public abstract Expr/*!*/ AsExpr {
- get;
- }
-
- // transform away the syntactic sugar of map assignments and
- // determine an equivalent simple assignment
- internal abstract void AsSimpleAssignment(Expr/*!*/ rhs,
- out IdentifierExpr/*!*/ simpleLhs,
- out Expr/*!*/ simpleRhs);
- }
- [ContractClassFor(typeof(AssignLhs))]
- public abstract class AssignLhsContracts : AssignLhs {
- public AssignLhsContracts():base(null)
- {
-
- }public override IdentifierExpr DeepAssignedIdentifier {
-
- get {
- Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
- throw new NotImplementedException();
- }
- }
- public override Expr AsExpr {
- get {
- Contract.Ensures(Contract.Result<Expr>() != null);
- throw new NotImplementedException();
- }
-
- }
- internal override void AsSimpleAssignment(Expr rhs, out IdentifierExpr simpleLhs, out Expr simpleRhs) {
- Contract.Requires(rhs != null);
- Contract.Ensures(Contract.ValueAtReturn(out simpleLhs) != null);
- Contract.Ensures(Contract.ValueAtReturn(out simpleRhs) != null);
-
- throw new NotImplementedException();
- }
- }
-
- public class SimpleAssignLhs : AssignLhs {
- public IdentifierExpr/*!*/ AssignedVariable;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AssignedVariable != null);
- }
-
-
- public override Type Type {
- get {
- return AssignedVariable.Type;
- }
- }
-
- public override IdentifierExpr/*!*/ DeepAssignedIdentifier {
- get {
- Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
- return AssignedVariable;
- }
- }
-
- public override Variable DeepAssignedVariable {
- get {
- return AssignedVariable.Decl;
- }
- }
-
- public SimpleAssignLhs(IToken tok, IdentifierExpr assignedVariable)
- : base(tok) {
- Contract.Requires(assignedVariable != null);
- Contract.Requires(tok != null);
- AssignedVariable = assignedVariable;
- }
- public override void Resolve(ResolutionContext rc) {
-
- AssignedVariable.Resolve(rc);
- }
- public override void Typecheck(TypecheckingContext tc) {
-
- AssignedVariable.Typecheck(tc);
- }
- public override void Emit(TokenTextWriter stream) {
-
- AssignedVariable.Emit(stream);
- }
- public override Expr/*!*/ AsExpr {
- get {
- Contract.Ensures(Contract.Result<Expr>() != null);
-
- return AssignedVariable;
- }
- }
- internal override void AsSimpleAssignment(Expr rhs,
- out IdentifierExpr/*!*/ simpleLhs,
- out Expr/*!*/ simpleRhs) {
-
-
-
- simpleLhs = AssignedVariable;
- simpleRhs = rhs;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
-
-
- return visitor.VisitSimpleAssignLhs(this);
- }
- }
-
- // A map-assignment-lhs (m[t1, t2, ...] := ...) is quite similar to
- // a map select expression, but it is cleaner to keep those two
- // things separate
- public class MapAssignLhs : AssignLhs {
- public AssignLhs/*!*/ Map;
-
- public List<Expr/*!*/>/*!*/ Indexes;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Map != null);
- Contract.Invariant(cce.NonNullElements(Indexes));
- }
-
-
- // The instantiation of type parameters of the map that is
- // determined during type checking.
- public TypeParamInstantiation TypeParameters = null;
-
- private Type TypeAttr = null;
-
- public override Type Type {
- get {
- return TypeAttr;
- }
- }
-
- public override IdentifierExpr/*!*/ DeepAssignedIdentifier {
- get {
- Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
-
- return Map.DeepAssignedIdentifier;
- }
- }
-
- public override Variable DeepAssignedVariable {
- get {
- return Map.DeepAssignedVariable;
- }
- }
-
- public MapAssignLhs(IToken tok, AssignLhs map, List<Expr/*!*/>/*!*/ indexes)
- : base(tok) {
- Contract.Requires(map != null);
- Contract.Requires(tok != null);
- Contract.Requires(cce.NonNullElements(indexes));
-
- Map = map;
- Indexes = indexes;
- }
- public override void Resolve(ResolutionContext rc) {
-
- Map.Resolve(rc);
- foreach (Expr/*!*/ e in Indexes) {
- Contract.Assert(e != null);
- e.Resolve(rc);
- }
- }
- public override void Typecheck(TypecheckingContext tc) {
-
- Map.Typecheck(tc);
- foreach (Expr/*!*/ e in Indexes) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
-
- // we use the same typechecking code as in MapSelect
- List<Expr>/*!*/ selectArgs = new List<Expr>();
- foreach (Expr/*!*/ e in Indexes) {
- Contract.Assert(e != null);
- selectArgs.Add(e);
- }
- TypeParamInstantiation/*!*/ tpInsts;
- TypeAttr =
- MapSelect.Typecheck(cce.NonNull(Map.Type), Map,
- selectArgs, out tpInsts, tc, tok, "map assignment");
- TypeParameters = tpInsts;
- }
- public override void Emit(TokenTextWriter stream) {
-
- Map.Emit(stream);
- stream.Write("[");
- string/*!*/ sep = "";
- foreach (Expr/*!*/ e in Indexes) {
- Contract.Assert(e != null);
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
- stream.Write("]");
- }
- public override Expr/*!*/ AsExpr {
- get {
- Contract.Ensures(Contract.Result<Expr>() != null);
-
- NAryExpr/*!*/ res = Expr.Select(Map.AsExpr, Indexes);
- Contract.Assert(res != null);
- res.TypeParameters = this.TypeParameters;
- res.Type = this.Type;
- return res;
- }
- }
- internal override void AsSimpleAssignment(Expr rhs,
- out IdentifierExpr/*!*/ simpleLhs,
- out Expr/*!*/ simpleRhs) { //Contract.Requires(rhs != null);
- Contract.Ensures(Contract.ValueAtReturn(out simpleLhs) != null);
- Contract.Ensures(Contract.ValueAtReturn(out simpleRhs) != null);
-
- NAryExpr/*!*/ newRhs = Expr.Store(Map.AsExpr, Indexes, rhs);
- Contract.Assert(newRhs != null);
- newRhs.TypeParameters = this.TypeParameters;
- newRhs.Type = Map.Type;
- Map.AsSimpleAssignment(newRhs, out simpleLhs, out simpleRhs);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitMapAssignLhs(this);
- }
- }
-
- /// <summary>
- /// A StateCmd is like an imperative-let binding around a sequence of commands.
- /// There is no user syntax for a StateCmd. Instead, a StateCmd is only used
- /// temporarily during the desugaring phase inside the VC generator.
- /// </summary>
- public class StateCmd : Cmd {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._locals != null);
- Contract.Invariant(this._cmds != null);
- }
-
- private List<Variable> _locals;
-
- public /*readonly, except for the StandardVisitor*/ List<Variable>/*!*/ Locals {
- get {
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- return this._locals;
- }
- internal set {
- Contract.Requires(value != null);
- this._locals = value;
- }
- }
-
- private List<Cmd> _cmds;
-
- public /*readonly, except for the StandardVisitor*/ List<Cmd>/*!*/ Cmds {
- get {
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- return this._cmds;
- }
- set {
- Contract.Requires(value != null);
- this._cmds = value;
- }
- }
-
- public StateCmd(IToken tok, List<Variable>/*!*/ locals, List<Cmd>/*!*/ cmds)
- : base(tok) {
- Contract.Requires(locals != null);
- Contract.Requires(cmds != null);
- Contract.Requires(tok != null);
- this._locals = locals;
- this._cmds = cmds;
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.PushVarContext();
- foreach (Variable/*!*/ v in Locals) {
- Contract.Assert(v != null);
- rc.AddVariable(v, false);
- }
- foreach (Cmd/*!*/ cmd in Cmds) {
- Contract.Assert(cmd != null);
- cmd.Resolve(rc);
- }
- rc.PopVarContext();
- }
-
- public override void AddAssignedVariables(List<Variable> vars) {
- //Contract.Requires(vars != null);
- List<Variable>/*!*/ vs = new List<Variable>();
- foreach (Cmd/*!*/ cmd in this.Cmds) {
- Contract.Assert(cmd != null);
- cmd.AddAssignedVariables(vs);
- }
- System.Collections.Hashtable/*!*/ localsSet = new System.Collections.Hashtable();
- foreach (Variable/*!*/ local in this.Locals) {
- Contract.Assert(local != null);
- localsSet[local] = bool.TrueString;
- }
- foreach (Variable/*!*/ v in vs) {
- Contract.Assert(v != null);
- if (!localsSet.ContainsKey(v)) {
- vars.Add(v);
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- foreach (Cmd/*!*/ cmd in Cmds) {
- Contract.Assert(cmd != null);
- cmd.Typecheck(tc);
- }
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.WriteLine(this, level, "{");
- foreach (Variable/*!*/ v in Locals) {
- Contract.Assert(v != null);
- v.Emit(stream, level + 1);
- }
- foreach (Cmd/*!*/ c in Cmds) {
- Contract.Assert(c != null);
- c.Emit(stream, level + 1);
- }
- stream.WriteLine(level, "}");
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitStateCmd(this);
- }
- }
- [ContractClass(typeof(SugaredCmdContracts))]
- abstract public class SugaredCmd : Cmd {
- private Cmd desugaring; // null until desugared
-
- public SugaredCmd(IToken/*!*/ tok)
- : base(tok) {
- Contract.Requires(tok != null);
- }
-
- public Cmd/*!*/ Desugaring {
- get {
- Contract.Ensures(Contract.Result<Cmd>() != null);
-
- if (desugaring == null) {
- desugaring = ComputeDesugaring();
- }
- return desugaring;
- }
- }
- /// <summary>
- /// This method invokes "visitor.Visit" on the desugaring, and then updates the
- /// desugaring to the result thereof. The method's intended use is for subclasses
- /// of StandardVisitor that need to also visit the desugaring. Note, since the
- /// "desugaring" field is updated, this is not an appropriate method to be called
- /// be a ReadOnlyVisitor; such visitors should instead just call
- /// visitor.Visit(sugaredCmd.Desugaring).
- /// </summary>
- public void VisitDesugaring(StandardVisitor visitor) {
- Contract.Requires(visitor != null && !(visitor is ReadOnlyVisitor));
- if (desugaring != null) {
- desugaring = (Cmd)visitor.Visit(desugaring);
- }
- }
- protected abstract Cmd/*!*/ ComputeDesugaring();
-
- public void ExtendDesugaring(IEnumerable<Cmd> before, IEnumerable<Cmd> beforePreconditionCheck, IEnumerable<Cmd> after)
- {
- var desug = Desugaring;
- var stCmd = desug as StateCmd;
- if (stCmd != null)
- {
- stCmd.Cmds.InsertRange(0, before);
- var idx = stCmd.Cmds.FindIndex(c => c is AssertCmd || c is HavocCmd || c is AssumeCmd);
- if (idx < 0)
- {
- idx = 0;
- }
- stCmd.Cmds.InsertRange(idx, beforePreconditionCheck);
- stCmd.Cmds.AddRange(after);
- }
- else if (desug != null)
- {
- var cmds = new List<Cmd>(before);
- cmds.Add(desug);
- cmds.AddRange(after);
- desugaring = new StateCmd(Token.NoToken, new List<Variable>(), cmds);
- }
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- if (CommandLineOptions.Clo.PrintDesugarings && !stream.UseForComputingChecksums) {
- stream.WriteLine(this, level, "/*** desugaring:");
- Desugaring.Emit(stream, level);
- stream.WriteLine(level, "**** end desugaring */");
- }
- }
- }
- [ContractClassFor(typeof(SugaredCmd))]
- public abstract class SugaredCmdContracts : SugaredCmd {
- public SugaredCmdContracts() :base(null){
-
- }
- protected override Cmd ComputeDesugaring() {
- Contract.Ensures(Contract.Result<Cmd>() != null);
-
- throw new NotImplementedException();
- }
- }
-
- public abstract class CallCommonality : SugaredCmd {
- public QKeyValue Attributes;
-
- private bool isFree = false;
- public bool IsFree {
- get {
- return isFree;
- }
- set {
- isFree = value;
- }
- }
-
- private bool isAsync = false;
- public bool IsAsync
- {
- get
- {
- return isAsync;
- }
- set
- {
- isAsync = value;
- }
- }
-
- protected CallCommonality(IToken tok, QKeyValue kv)
- : base(tok) {
- Contract.Requires(tok != null);
- Attributes = kv;
- }
-
- protected enum TempVarKind {
- Formal,
- Old,
- Bound
- }
-
- // We have to give the type explicitly, because the type of the formal "likeThisOne" can contain type variables
- protected Variable CreateTemporaryVariable(List<Variable> tempVars, Variable likeThisOne, Type ty, TempVarKind kind, ref int uniqueId) {
- Contract.Requires(ty != null);
- Contract.Requires(likeThisOne != null);
- Contract.Requires(tempVars != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
- string/*!*/ tempNamePrefix;
- switch (kind) {
- case TempVarKind.Formal:
- tempNamePrefix = "formal@";
- break;
- case TempVarKind.Old:
- tempNamePrefix = "old@";
- break;
- case TempVarKind.Bound:
- tempNamePrefix = "forall@";
- break;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // unexpected kind
- }
- TypedIdent ti = likeThisOne.TypedIdent;
- // KLM: uniqueId was messing up FixedPointVC for unknown reason.
- // I reverted this change for FixedPointVC only.
- int id = CommandLineOptions.Clo.FixedPointEngine != null ? UniqueId : (uniqueId++);
- TypedIdent newTi = new TypedIdent(ti.tok, "call" + id + tempNamePrefix + ti.Name, ty);
- Variable/*!*/ v;
- if (kind == TempVarKind.Bound) {
- v = new BoundVariable(likeThisOne.tok, newTi);
- } else {
- v = new LocalVariable(likeThisOne.tok, newTi);
- tempVars.Add(v);
- }
- return v;
- }
- }
-
- public class ParCallCmd : CallCommonality, IPotentialErrorNode<object, object>
- {
- public List<CallCmd> CallCmds;
- public ParCallCmd(IToken tok, List<CallCmd> callCmds)
- : base(tok, null)
- {
- this.CallCmds = callCmds;
- }
- public ParCallCmd(IToken tok, List<CallCmd> callCmds, QKeyValue kv)
- : base(tok, kv)
- {
- this.CallCmds = callCmds;
- }
- protected override Cmd ComputeDesugaring()
- {
- throw new NotImplementedException();
- }
- private object errorData;
- public object ErrorData
- {
- get
- {
- return errorData;
- }
- set
- {
- errorData = value;
- }
- }
- public override void Resolve(ResolutionContext rc)
- {
- ResolveAttributes(Attributes, rc);
- foreach (CallCmd callCmd in CallCmds)
- {
- callCmd.Resolve(rc);
- }
- HashSet<Variable> parallelCallLhss = new HashSet<Variable>();
- foreach (CallCmd callCmd in CallCmds)
- {
- foreach (IdentifierExpr ie in callCmd.Outs)
- {
- if (parallelCallLhss.Contains(ie.Decl))
- {
- rc.Error(this, "left-hand side of parallel call command contains variable twice: {0}", ie.Name);
- }
- else
- {
- parallelCallLhss.Add(ie.Decl);
- }
- }
- }
- }
- public override void Typecheck(TypecheckingContext tc)
- {
- TypecheckAttributes(Attributes, tc);
- if (!CommandLineOptions.Clo.DoModSetAnalysis)
- {
- if (!tc.Yields)
- {
- tc.Error(this, "enclosing procedure of a parallel call must yield");
- }
- foreach (CallCmd callCmd in CallCmds)
- {
- if (!QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "yields"))
- {
- tc.Error(callCmd, "target procedure of a parallel call must yield");
- }
- }
- }
- foreach (CallCmd callCmd in CallCmds)
- {
- callCmd.Typecheck(tc);
- }
- }
- public override void AddAssignedVariables(List<Variable> vars)
- {
- foreach (CallCmd callCmd in CallCmds)
- {
- callCmd.AddAssignedVariables(vars);
- }
- }
- public override Absy StdDispatch(StandardVisitor visitor)
- {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitParCallCmd(this);
- }
- }
-
- public class CallCmd : CallCommonality, IPotentialErrorNode<object, object>
- {
- public string/*!*/ callee { get; set; }
- public Procedure Proc;
- public LocalVariable AssignedAssumptionVariable;
-
- // Element of the following lists can be null, which means that
- // the call happens with * as these parameters
- public List<Expr>/*!*/ Ins;
- public List<IdentifierExpr>/*!*/ Outs;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(callee != null);
- Contract.Invariant(Ins != null);
- Contract.Invariant(Outs != null);
- }
-
- //public Lattice.Element StateAfterCall;
-
- // The instantiation of type parameters that is determined during
- // type checking
- public TypeParamInstantiation TypeParameters = null;
-
- // TODO: convert to use generics
- private object errorData;
- public object ErrorData {
- get {
- return errorData;
- }
- set {
- errorData = value;
- }
- }
- public CallCmd(IToken tok, string callee, List<Expr> ins, List<IdentifierExpr> outs)
- : base(tok, null) {
- Contract.Requires(outs != null);
- Contract.Requires(ins != null);
- Contract.Requires(callee != null);
- Contract.Requires(tok != null);
- this.callee = callee;
- this.Ins = ins;
- this.Outs = outs;
- }
- public CallCmd(IToken tok, string callee, List<Expr> ins, List<IdentifierExpr> outs, QKeyValue kv)
- : base(tok, kv) {
- Contract.Requires(outs != null);
- Contract.Requires(ins != null);
- Contract.Requires(callee != null);
- Contract.Requires(tok != null);
- this.callee = callee;
- this.Ins = ins;
- this.Outs = outs;
- }
-
- public CallCmd(IToken tok, string callee, List<Expr> ins, List<IdentifierExpr> outs, QKeyValue kv, bool IsAsync)
- : base(tok, kv)
- {
- Contract.Requires(outs != null);
- Contract.Requires(ins != null);
- Contract.Requires(callee != null);
- Contract.Requires(tok != null);
- this.callee = callee;
- this.Ins = ins;
- this.Outs = outs;
- this.IsAsync = IsAsync;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "");
- if (IsFree) {
- stream.Write("free ");
- }
- if (IsAsync) {
- stream.Write("async ");
- }
- stream.Write("call ");
- EmitAttributes(stream, Attributes);
- string sep = "";
- if (Outs.Count > 0) {
- foreach (Expr arg in Outs) {
- stream.Write(sep);
- sep = ", ";
- if (arg == null) {
- stream.Write("*");
- } else {
- arg.Emit(stream);
- }
- }
- stream.Write(" := ");
- }
- stream.Write(TokenTextWriter.SanitizeIdentifier(callee));
- stream.Write("(");
- sep = "";
- foreach (Expr arg in Ins) {
- stream.Write(sep);
- sep = ", ";
- if (arg == null) {
- stream.Write("*");
- } else {
- arg.Emit(stream);
- }
- }
- stream.WriteLine(");");
- base.Emit(stream, level);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- if (Proc != null) {
- // already resolved
- return;
- }
- ResolveAttributes(Attributes, rc);
- Proc = rc.LookUpProcedure(callee) as Procedure;
- if (Proc == null) {
- rc.Error(this, "call to undeclared procedure: {0}", callee);
- }
- foreach (Expr e in Ins) {
- if (e != null) {
- e.Resolve(rc);
- }
- }
- HashSet<Variable> actualOuts = new HashSet<Variable>();
- foreach (IdentifierExpr ide in Outs) {
- if (ide != null) {
- ide.Resolve(rc);
- if (ide.Decl != null) {
- if (actualOuts.Contains(ide.Decl)) {
- rc.Error(this, "left-hand side of call command contains variable twice: {0}", ide.Name);
- } else {
- actualOuts.Add(ide.Decl);
- }
- }
- }
- }
-
- if (Proc == null)
- return;
-
- // first make sure that the right number of parameters is given
- // (a similar check is in CheckArgumentTypes, but we are not
- // able to call this method because it cannot cope with Ins/Outs
- // that are null)
- if (Ins.Count != Proc.InParams.Count) {
- rc.Error(this.tok,
- "wrong number of arguments in call to {0}: {1}",
- callee, Ins.Count);
- return;
- }
- if (Outs.Count != Proc.OutParams.Count) {
- rc.Error(this.tok,
- "wrong number of result variables in call to {0}: {1}",
- callee, Outs.Count);
- return;
- }
- if (IsAsync) {
- if (Proc.OutParams.Count > 0) {
- rc.Error(this.tok, "a procedure called asynchronously can have no output parameters");
- return;
- }
- }
-
- // Check that type parameters can be determined using the given
- // actual i/o arguments. This is done already during resolution
- // because CheckBoundVariableOccurrences needs a resolution
- // context
- List<Type>/*!*/ formalInTypes = new List<Type>();
- List<Type>/*!*/ formalOutTypes = new List<Type>();
- for (int i = 0; i < Ins.Count; ++i)
- if (Ins[i] != null)
- formalInTypes.Add(cce.NonNull(Proc.InParams[i]).TypedIdent.Type);
- for (int i = 0; i < Outs.Count; ++i)
- if (Outs[i] != null)
- formalOutTypes.Add(cce.NonNull(Proc.OutParams[i]).TypedIdent.Type);
-
- // we need to bind the type parameters for this
- // (this is expected by CheckBoundVariableOccurrences)
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- foreach (TypeVariable/*!*/ v in Proc.TypeParameters) {
- Contract.Assert(v != null);
- rc.AddTypeBinder(v);
- }
- Type.CheckBoundVariableOccurrences(Proc.TypeParameters,
- formalInTypes, formalOutTypes,
- this.tok, "types of given arguments",
- rc);
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- }
-
- public override void AddAssignedVariables(List<Variable> vars) {
- if (this.IsAsync)
- return;
- foreach (IdentifierExpr e in Outs) {
- if (e != null) {
- vars.Add(e.Decl);
- }
- }
- Contract.Assume(this.Proc != null);
- foreach (IdentifierExpr/*!*/ e in this.Proc.Modifies) {
- Contract.Assert(e != null);
- vars.Add(e.Decl);
- }
- if (AssignedAssumptionVariable != null)
- {
- vars.Add(AssignedAssumptionVariable);
- }
- }
-
- public override void Typecheck(TypecheckingContext tc)
- {
- //Contract.Requires(tc != null);
- Contract.Assume(this.Proc != null); // we assume the CallCmd has been successfully resolved before calling this Typecheck method
-
- TypecheckAttributes(Attributes, tc);
-
- // typecheck in-parameters
- foreach (Expr e in Ins)
- if (e != null)
- e.Typecheck(tc);
- foreach (Expr e in Outs)
- if (e != null)
- e.Typecheck(tc);
- this.CheckAssignments(tc);
-
- List<Type>/*!*/ formalInTypes = new List<Type>();
- List<Type>/*!*/ formalOutTypes = new List<Type>();
- List<Expr>/*!*/ actualIns = new List<Expr>();
- List<IdentifierExpr>/*!*/ actualOuts = new List<IdentifierExpr>();
- for (int i = 0; i < Ins.Count; ++i)
- {
- if (Ins[i] != null)
- {
- formalInTypes.Add(cce.NonNull(Proc.InParams[i]).TypedIdent.Type);
- actualIns.Add(Ins[i]);
- }
- }
- for (int i = 0; i < Outs.Count; ++i)
- {
- if (Outs[i] != null)
- {
- formalOutTypes.Add(cce.NonNull(Proc.OutParams[i]).TypedIdent.Type);
- actualOuts.Add(Outs[i]);
- }
- }
-
- // match actuals with formals
- List<Type/*!*/>/*!*/ actualTypeParams;
- Type.CheckArgumentTypes(Proc.TypeParameters,
- out actualTypeParams,
- formalInTypes, actualIns,
- formalOutTypes, actualOuts,
- this.tok,
- "call to " + callee,
- tc);
- Contract.Assert(cce.NonNullElements(actualTypeParams));
- TypeParameters = SimpleTypeParamInstantiation.From(Proc.TypeParameters,
- actualTypeParams);
-
- if (!CommandLineOptions.Clo.DoModSetAnalysis && IsAsync)
- {
- if (!tc.Yields)
- {
- tc.Error(this, "enclosing procedure of an async call must yield");
- }
- if (!QKeyValue.FindBoolAttribute(Proc.Attributes, "yields"))
- {
- tc.Error(this, "target procedure of an async call must yield");
- }
- }
- }
-
- private IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ TypeParamSubstitution() {
- Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
- Contract.Assume(TypeParameters != null);
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ res = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- foreach (TypeVariable/*!*/ v in TypeParameters.FormalTypeParams) {
- Contract.Assert(v != null);
- res.Add(v, TypeParameters[v]);
- }
- return res;
- }
-
- protected override Cmd ComputeDesugaring() {
- Contract.Ensures(Contract.Result<Cmd>() != null);
-
- int uniqueId = 0;
- List<Cmd> newBlockBody = new List<Cmd>();
- Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>();
- Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>();
- Dictionary<Variable, Expr> substMapBound = new Dictionary<Variable, Expr>();
- List<Variable>/*!*/ tempVars = new List<Variable>();
-
- // proc P(ins) returns (outs)
- // requires Pre
- // //modifies frame
- // ensures Post
- //
- // call aouts := P(ains)
-
- // ins : formal in parameters of procedure
- // frame : a list of global variables from the modifies clause
- // outs : formal out parameters of procedure
- // ains : actual in arguments passed to call
- // aouts : actual variables assigned to from call
- // cins : new variables created just for this call, one per ains
- // cframe : new variables created just for this call, to keep track of OLD values
- // couts : new variables created just for this call, one per aouts
- // WildcardVars : new variables created just for this call, one per null in ains
-
- #region Create cins; each one is an incarnation of the corresponding in parameter
- List<Variable>/*!*/ cins = new List<Variable>();
- List<Variable> wildcardVars = new List<Variable>();
- Contract.Assume(this.Proc != null);
- for (int i = 0; i < this.Proc.InParams.Count; ++i) {
- Variable/*!*/ param = cce.NonNull(this.Proc.InParams[i]);
- bool isWildcard = this.Ins[i] == null;
-
- Type/*!*/ actualType;
- if (isWildcard)
- actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
- else
- // during type checking, we have ensured that the type of the actual
- // parameter Ins[i] is correct, so we can use it here
- actualType = cce.NonNull(cce.NonNull(Ins[i]).Type);
-
- Variable cin = CreateTemporaryVariable(tempVars, param, actualType,
- TempVarKind.Formal, ref uniqueId);
- cins.Add(cin);
- IdentifierExpr ie = new IdentifierExpr(cin.tok, cin);
- substMap.Add(param, ie);
- if (isWildcard) {
- cin = CreateTemporaryVariable(tempVars, param,
- actualType, TempVarKind.Bound, ref uniqueId);
- wildcardVars.Add(cin);
- ie = new IdentifierExpr(cin.tok, cin);
- }
- substMapBound.Add(param, ie);
- }
- #endregion
- #region call aouts := P(ains) becomes: (open outlining one level to see)
- #region cins := ains (or havoc cin when ain is null)
- for (int i = 0, n = this.Ins.Count; i < n; i++) {
- IdentifierExpr/*!*/ cin_exp = new IdentifierExpr(cce.NonNull(cins[i]).tok, cce.NonNull(cins[i]));
- Contract.Assert(cin_exp != null);
- if (this.Ins[i] != null) {
- AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, cce.NonNull(this.Ins[i]));
- newBlockBody.Add(assign);
- } else {
- List<IdentifierExpr>/*!*/ ies = new List<IdentifierExpr>();
- ies.Add(cin_exp);
- HavocCmd havoc = new HavocCmd(Token.NoToken, ies);
- newBlockBody.Add(havoc);
- }
- }
- #endregion
-
- #region assert (exists wildcardVars :: Pre[ins := cins])
- Substitution s = Substituter.SubstitutionFromHashtable(substMapBound);
- bool hasWildcard = (wildcardVars.Count != 0);
- Expr preConjunction = null;
- for (int i = 0; i < this.Proc.Requires.Count; i++) {
- Requires/*!*/ req = cce.NonNull(this.Proc.Requires[i]);
- if (!req.Free && !IsFree) {
- if (hasWildcard) {
- Expr pre = Substituter.Apply(s, req.Condition);
- if (preConjunction == null) {
- preConjunction = pre;
- } else {
- preConjunction = Expr.And(preConjunction, pre);
- }
- } else {
- Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
- reqCopy.Condition = Substituter.Apply(s, req.Condition);
- AssertCmd/*!*/ a = new AssertRequiresCmd(this, reqCopy);
- Contract.Assert(a != null);
- a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
- newBlockBody.Add(a);
- }
- }
- else if (CommandLineOptions.Clo.StratifiedInlining > 0)
- {
- // inject free requires as assume statements at the call site
- AssumeCmd/*!*/ a = new AssumeCmd(req.tok, Substituter.Apply(s, req.Condition));
- Contract.Assert(a != null);
- newBlockBody.Add(a);
- }
- }
- if (hasWildcard) {
- if (preConjunction == null) {
- preConjunction = Expr.True;
- }
- Expr/*!*/ expr = new ExistsExpr(tok, wildcardVars, preConjunction);
- Contract.Assert(expr != null);
- AssertCmd/*!*/ a = new AssertCmd(tok, expr);
- Contract.Assert(a != null);
- a.ErrorDataEnhanced = AssertCmd.GenerateBoundVarMiningStrategy(expr);
- newBlockBody.Add(a);
- }
- #endregion
-
- #region assume Pre[ins := cins] with formal paramters
- if (hasWildcard) {
- s = Substituter.SubstitutionFromHashtable(substMap);
- for (int i = 0; i < this.Proc.Requires.Count; i++) {
- Requires/*!*/ req = cce.NonNull(this.Proc.Requires[i]);
- if (!req.Free) {
- Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
- reqCopy.Condition = Substituter.Apply(s, req.Condition);
- AssumeCmd/*!*/ a = new AssumeCmd(tok, reqCopy.Condition);
- Contract.Assert(a != null);
- newBlockBody.Add(a);
- }
- }
- }
- #endregion
-
- #region cframe := frame (to hold onto frame values in case they are referred to in the postcondition)
- List<IdentifierExpr> havocVarExprs = new List<IdentifierExpr>();
-
- foreach (IdentifierExpr/*!*/ f in this.Proc.Modifies) {
- Contract.Assert(f != null);
- Contract.Assume(f.Decl != null);
- Contract.Assert(f.Type != null);
- Variable v = CreateTemporaryVariable(tempVars, f.Decl, f.Type, TempVarKind.Old, ref uniqueId);
- IdentifierExpr v_exp = new IdentifierExpr(v.tok, v);
- substMapOld.Add(f.Decl, v_exp); // this assumes no duplicates in this.Proc.Modifies
- AssignCmd assign = Cmd.SimpleAssign(f.tok, v_exp, f);
- newBlockBody.Add(assign);
-
- // fra
- if (!havocVarExprs.Contains(f))
- havocVarExprs.Add(f);
- }
- #endregion
- #region Create couts
- List<Variable>/*!*/ couts = new List<Variable>();
- for (int i = 0; i < this.Proc.OutParams.Count; ++i) {
- Variable/*!*/ param = cce.NonNull(this.Proc.OutParams[i]);
- bool isWildcard = this.Outs[i] == null;
-
- Type/*!*/ actualType;
- if (isWildcard)
- actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
- else
- // during type checking, we have ensured that the type of the actual
- // out parameter Outs[i] is correct, so we can use it here
- actualType = cce.NonNull(cce.NonNull(Outs[i]).Type);
-
- Variable cout = CreateTemporaryVariable(tempVars, param, actualType,
- TempVarKind.Formal, ref uniqueId);
- couts.Add(cout);
- IdentifierExpr ie = new IdentifierExpr(cout.tok, cout);
- substMap.Add(param, ie);
-
- if (!havocVarExprs.Contains(ie))
- havocVarExprs.Add(ie);
- }
- // add the where clauses, now that we have the entire substitution map
- foreach (Variable/*!*/ param in this.Proc.OutParams) {
- Contract.Assert(param != null);
- Expr w = param.TypedIdent.WhereExpr;
- if (w != null) {
- IdentifierExpr ie = (IdentifierExpr/*!*/)cce.NonNull(substMap[param]);
- Contract.Assert(ie.Decl != null);
- ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w);
- }
- }
- #endregion
-
- #region havoc frame, couts
- // pass on this's token
- HavocCmd hc = new HavocCmd(this.tok, havocVarExprs);
- newBlockBody.Add(hc);
- #endregion
-
- #region assume Post[ins, outs, old(frame) := cins, couts, cframe]
- calleeSubstitution = Substituter.SubstitutionFromHashtable(substMap, true, Proc);
- calleeSubstitutionOld = Substituter.SubstitutionFromHashtable(substMapOld, true, Proc);
- foreach (Ensures/*!*/ e in this.Proc.Ensures) {
- Contract.Assert(e != null);
- Expr copy = Substituter.ApplyReplacingOldExprs(calleeSubstitution, calleeSubstitutionOld, e.Condition);
- AssumeCmd assume = new AssumeCmd(this.tok, copy);
- #region stratified inlining support
- if (QKeyValue.FindBoolAttribute(e.Attributes, "si_fcall"))
- {
- assume.Attributes = Attributes;
- }
- if (QKeyValue.FindBoolAttribute(e.Attributes, "candidate"))
- {
- assume.Attributes = new QKeyValue(Token.NoToken, "candidate", new List<object>(), assume.Attributes);
- assume.Attributes.AddParam(this.callee);
- }
- #endregion
- newBlockBody.Add(assume);
- }
- #endregion
-
- #region aouts := couts
- for (int i = 0, n = this.Outs.Count; i < n; i++) {
- if (this.Outs[i] != null) {
- Variable/*!*/ param_i = cce.NonNull(this.Proc.OutParams[i]);
- Expr/*!*/ cout_exp = new IdentifierExpr(cce.NonNull(couts[i]).tok, cce.NonNull(couts[i]));
- Contract.Assert(cout_exp != null);
- AssignCmd assign = Cmd.SimpleAssign(param_i.tok, cce.NonNull(this.Outs[i]), cout_exp);
- newBlockBody.Add(assign);
- }
- }
- #endregion
- #endregion
-
- return new StateCmd(this.tok, tempVars, newBlockBody);
- }
-
- class NameEqualityComparer : EqualityComparer<IdentifierExpr>
- {
- public override bool Equals(IdentifierExpr x, IdentifierExpr y)
- {
- return x.Name.Equals(y.Name);
- }
-
- public override int GetHashCode(IdentifierExpr obj)
- {
- return obj.Name.GetHashCode();
- }
- }
-
- NameEqualityComparer comparer = new NameEqualityComparer();
-
- public Substitution calleeSubstitution;
- public Substitution calleeSubstitutionOld;
-
- public IEnumerable<IdentifierExpr> UnmodifiedBefore(Procedure oldProcedure)
- {
- Contract.Requires(oldProcedure != null);
-
- return Proc.Modifies.Except(oldProcedure.Modifies, comparer).Select(e => new IdentifierExpr(Token.NoToken, e.Decl));
- }
-
- public IEnumerable<IdentifierExpr> ModifiedBefore(Procedure oldProcedure)
- {
- Contract.Requires(oldProcedure != null);
-
- return oldProcedure.Modifies.Except(Proc.Modifies, comparer).Select(e => new IdentifierExpr(Token.NoToken, e.Decl));
- }
-
- public Expr Postcondition(Procedure procedure, List<Expr> modifies, Dictionary<Variable, Expr> oldSubst, Program program, Func<Expr, Expr> extract)
- {
- Contract.Requires(calleeSubstitution != null && calleeSubstitutionOld != null && modifies != null && oldSubst != null && program != null && extract != null);
-
- Substitution substOldCombined = v => { Expr s; if (oldSubst.TryGetValue(v, out s)) { return s; } return calleeSubstitutionOld(v); };
-
- var clauses = procedure.Ensures.Select(e => Substituter.FunctionCallReresolvingApplyReplacingOldExprs(calleeSubstitution, substOldCombined, e.Condition, program)).Concat(modifies);
- // TODO(wuestholz): Try extracting a function for each clause:
- // return Conjunction(clauses.Select(c => extract(c)));
- var conj = Conjunction(clauses);
- return conj != null ? extract(conj) : conj;
- }
-
- public Expr CheckedPrecondition(Procedure procedure, Program program, Func<Expr, Expr> extract)
- {
- Contract.Requires(calleeSubstitution != null && calleeSubstitutionOld != null && program != null && extract != null);
-
- var clauses = procedure.Requires.Where(r => !r.Free).Select(r => Substituter.FunctionCallReresolvingApplyReplacingOldExprs(calleeSubstitution, calleeSubstitutionOld, r.Condition, program));
- // TODO(wuestholz): Try extracting a function for each clause:
- // return Conjunction(clauses.Select(c => extract(c)));
- var conj = Conjunction(clauses);
- return conj != null ? extract(conj) : conj;
- }
-
- private static Expr Conjunction(IEnumerable<Expr> conjuncts)
- {
- // TODO(wuestholz): Maybe we should use 'LiteralExpr.BinaryTreeAnd' instead.
- Expr result = null;
- foreach (var c in conjuncts)
- {
- if (result != null)
- {
- result = LiteralExpr.And(result, c);
- result.Type = Type.Bool;
- }
- else
- {
- result = c;
- result.Type = Type.Bool;
- }
- }
- return result;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitCallCmd(this);
- }
- }
-
- public abstract class PredicateCmd : Cmd {
- public QKeyValue Attributes;
- public /*readonly--except in StandardVisitor*/ Expr/*!*/ Expr;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Expr != null);
- }
-
- public PredicateCmd(IToken/*!*/ tok, Expr/*!*/ expr)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- Expr = expr;
- }
- public PredicateCmd(IToken/*!*/ tok, Expr/*!*/ expr, QKeyValue kv)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- Expr = expr;
- Attributes = kv;
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Expr.Resolve(rc);
- }
- public override void AddAssignedVariables(List<Variable> vars) {
- //Contract.Requires(vars != null);
- }
- }
-
- public abstract class MiningStrategy {
- // abstract class to bind all MiningStrategys, i.e., all types of enhanced error data
- // types together
- }
-
- public class ListOfMiningStrategies : MiningStrategy {
-
- private List<MiningStrategy>/*!*/ _msList;
-
- public List<MiningStrategy>/*!*/ msList
- {
- get
- {
- Contract.Ensures(Contract.Result<List<MiningStrategy>>() != null);
- return this._msList;
- }
- set
- {
- Contract.Requires(value != null);
- this._msList = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._msList != null);
- }
-
- public ListOfMiningStrategies(List<MiningStrategy> l) {
- Contract.Requires(l != null);
- this._msList = l;
- }
- }
-
- public class EEDTemplate : MiningStrategy {
- private string/*!*/ _reason;
- public string/*!*/ reason
- {
- get
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return this._reason;
- }
- set
- {
- Contract.Requires(value != null);
- this._reason = value;
- }
- }
-
- private List<Expr/*!*/>/*!*/ exprList;
- public IEnumerable<Expr> Expressions
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Expr>>()));
- return this.exprList.AsReadOnly();
- }
- set
- {
- Contract.Requires(cce.NonNullElements(value));
- this.exprList = new List<Expr>(value);
- }
- }
-
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._reason != null);
- Contract.Invariant(cce.NonNullElements(this.exprList));
- }
-
- public EEDTemplate(string reason, List<Expr/*!*/>/*!*/ exprList) {
- Contract.Requires(reason != null);
- Contract.Requires(cce.NonNullElements(exprList));
- this._reason = reason;
- this.exprList = exprList;
- }
- }
-
- public class AssertCmd : PredicateCmd, IPotentialErrorNode<object, object>
- {
- public Expr OrigExpr;
- public Dictionary<Variable, Expr> IncarnationMap;
-
- Expr verifiedUnder;
- public Expr VerifiedUnder
- {
- get
- {
- if (verifiedUnder != null)
- {
- return verifiedUnder;
- }
- verifiedUnder = QKeyValue.FindExprAttribute(Attributes, "verified_under");
- return verifiedUnder;
- }
- }
-
- public void MarkAsVerifiedUnder(Expr expr)
- {
- Attributes = new QKeyValue(tok, "verified_under", new List<object> { expr }, Attributes);
- verifiedUnder = expr;
- }
-
- // TODO: convert to use generics
- private object errorData;
- public object ErrorData {
- get {
- return errorData;
- }
- set {
- errorData = value;
- }
- }
-
- public string ErrorMessage {
- get {
- return QKeyValue.FindStringAttribute(Attributes, "msg");
- }
- }
-
- private MiningStrategy errorDataEnhanced;
- public MiningStrategy ErrorDataEnhanced {
- get {
- return errorDataEnhanced;
- }
- set {
- errorDataEnhanced = value;
- }
- }
-
- public AssertCmd(IToken/*!*/ tok, Expr/*!*/ expr)
- : base(tok, expr) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
- }
-
- public AssertCmd(IToken/*!*/ tok, Expr/*!*/ expr, QKeyValue kv)
- : base(tok, expr, kv) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "assert ");
- EmitAttributes(stream, Attributes);
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- ResolveAttributes(Attributes, rc);
- base.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- TypecheckAttributes(Attributes, tc);
- Expr.Typecheck(tc);
- Contract.Assert(Expr.Type != null); // follows from Expr.Typecheck postcondition
- if (!Expr.Type.Unify(Type.Bool)) {
- tc.Error(this, "an asserted expression must be of type bool (got: {0})", Expr.Type);
- }
- }
-
- public static MiningStrategy GenerateBoundVarMiningStrategy(Expr expr) {
- Contract.Requires(expr != null);
- List<MiningStrategy> l = new List<MiningStrategy>();
- if (expr != null) {
- l = GenerateBoundVarListForMining(expr, l);
- }
- return new ListOfMiningStrategies(l);
- }
-
- public static List<MiningStrategy>/*!*/ GenerateBoundVarListForMining(Expr expr, List<MiningStrategy> l) {
- Contract.Requires(l != null);
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<List<MiningStrategy>>() != null);
-
- // go through the origExpr and identify all bound variables in the AST.
- if (expr is LiteralExpr || expr is IdentifierExpr) {
- //end recursion
- } else if (expr is NAryExpr) {
- NAryExpr e = (NAryExpr)expr;
- foreach (Expr/*!*/ arg in e.Args) {
- Contract.Assert(arg != null);
- l = GenerateBoundVarListForMining(arg, l);
- }
- } else if (expr is OldExpr) {
- OldExpr e = (OldExpr)expr;
- l = GenerateBoundVarListForMining(e.Expr, l);
- } else if (expr is QuantifierExpr) {
- QuantifierExpr qe = (QuantifierExpr)expr;
- List<Variable> vs = qe.Dummies;
- foreach (Variable/*!*/ x in vs) {
- Contract.Assert(x != null);
- string name = x.Name;
- if (name.StartsWith("^")) {
- name = name.Substring(1);
- List<Expr> exprList = new List<Expr>();
- exprList.Add(new IdentifierExpr(Token.NoToken, x.ToString(), x.TypedIdent.Type));
- MiningStrategy eed = new EEDTemplate("The bound variable " + name + " has the value {0}.", exprList);
- l.Add(eed);
- }
- }
- l = GenerateBoundVarListForMining(qe.Body, l);
- }
- return l;
- }
-
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAssertCmd(this);
- }
- }
-
- // An AssertCmd that is a loop invariant check before the loop iteration starts
- public class LoopInitAssertCmd : AssertCmd {
- public LoopInitAssertCmd(IToken/*!*/ tok, Expr/*!*/ expr)
- : base(tok, expr) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- }
- }
-
- // An AssertCmd that is a loop invariant check to maintain the invariant after iteration
- public class LoopInvMaintainedAssertCmd : AssertCmd {
- public LoopInvMaintainedAssertCmd(IToken/*!*/ tok, Expr/*!*/ expr)
- : base(tok, expr) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- }
- }
-
- /// <summary>
- /// An AssertCmd that is introduced in translation from the requires on a call.
- /// </summary>
- public class AssertRequiresCmd : AssertCmd {
- public CallCmd/*!*/ Call;
- public Requires/*!*/ Requires;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Call != null);
- Contract.Invariant(Requires != null);
- }
-
-
- public AssertRequiresCmd(CallCmd/*!*/ call, Requires/*!*/ requires)
- : base(call.tok, requires.Condition) {
- Contract.Requires(call != null);
- Contract.Requires(requires != null);
- this.Call = call;
- this.Requires = requires;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAssertRequiresCmd(this);
- }
- }
-
- /// <summary>
- /// An AssertCmd that is introduced in translation from an ensures
- /// declaration.
- /// </summary>
- public class AssertEnsuresCmd : AssertCmd {
- public Ensures/*!*/ Ensures;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Ensures != null);
- }
-
- public AssertEnsuresCmd(Ensures/*!*/ ens)
- : base(ens.tok, ens.Condition) {
- Contract.Requires(ens != null);
- this.Ensures = ens;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAssertEnsuresCmd(this);
- }
- }
-
- public class AssumeCmd : PredicateCmd {
- public AssumeCmd(IToken/*!*/ tok, Expr/*!*/ expr)
- : base(tok, expr) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- }
- public AssumeCmd(IToken/*!*/ tok, Expr/*!*/ expr, QKeyValue kv)
- : base(tok, expr, kv) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
-
- if (stream.UseForComputingChecksums && QKeyValue.FindBoolAttribute(Attributes, "precondition_previous_snapshot")) { return; }
-
- stream.Write(this, level, "assume ");
- EmitAttributes(stream, Attributes);
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- Expr.Typecheck(tc);
- Contract.Assert(Expr.Type != null); // follows from Expr.Typecheck postcondition
- if (!Expr.Type.Unify(Type.Bool)) {
- tc.Error(this, "an assumed expression must be of type bool (got: {0})", Expr.Type);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitAssumeCmd(this);
- }
- }
-
- public class ReturnExprCmd : ReturnCmd {
- public Expr/*!*/ Expr;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Expr != null);
- }
-
- public ReturnExprCmd(IToken/*!*/ tok, Expr/*!*/ expr)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- Expr = expr;
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "return ");
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- Expr.Typecheck(tc);
- Contract.Assert(Expr.Type != null); // follows from Expr.Typecheck postcondition
- if (!Expr.Type.Unify(Type.Bool)) {
- tc.Error(this, "a return expression must be of type bool (got: {0})", Expr.Type);
- }
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Expr.Resolve(rc);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitReturnExprCmd(this);
- }
- }
-
- public class HavocCmd : Cmd {
- private List<IdentifierExpr>/*!*/ _vars;
-
- public List<IdentifierExpr>/*!*/ Vars {
- get {
- Contract.Ensures(Contract.Result<List<IdentifierExpr>>() != null);
- return this._vars;
- }
- set {
- Contract.Requires(value != null);
- this._vars = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._vars != null);
- }
-
- public HavocCmd(IToken/*!*/ tok, List<IdentifierExpr>/*!*/ vars)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(vars != null);
- this._vars = vars;
- }
-
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.Write(this, level, "havoc ");
- Vars.Emit(stream, true);
- stream.WriteLine(";");
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- foreach (IdentifierExpr/*!*/ ide in Vars) {
- Contract.Assert(ide != null);
- ide.Resolve(rc);
- }
- }
- public override void AddAssignedVariables(List<Variable> vars) {
- //Contract.Requires(vars != null);
- foreach (IdentifierExpr/*!*/ e in this.Vars) {
- Contract.Assert(e != null);
- vars.Add(e.Decl);
- }
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- foreach (IdentifierExpr ie in Vars)
- {
- ie.Typecheck(tc);
- }
- this.CheckAssignments(tc);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitHavocCmd(this);
- }
- }
-
- //---------------------------------------------------------------------
- // Transfer commands
- [ContractClass(typeof(TransferCmdContracts))]
- public abstract class TransferCmd : Absy {
- internal TransferCmd(IToken/*!*/ tok)
- : base(tok) {
- Contract.Requires(tok != null);
- }
- public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- // nothing to typecheck
- }
-
- public override string ToString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false , /*pretty=*/ false)) {
- this.Emit(stream, 0);
- }
- return buffer.ToString();
- }
- }
- [ContractClassFor(typeof(TransferCmd))]
- public abstract class TransferCmdContracts : TransferCmd {
- public TransferCmdContracts() :base(null){
-
- }
- public override void Emit(TokenTextWriter stream, int level) {
- Contract.Requires(stream != null);
- throw new NotImplementedException();
- }
- }
-
- public class ReturnCmd : TransferCmd {
- public ReturnCmd(IToken/*!*/ tok)
- : base(tok) {
- Contract.Requires(tok != null);
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- stream.WriteLine(this, level, "return;");
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- // nothing to resolve
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitReturnCmd(this);
- }
- }
-
- public class GotoCmd : TransferCmd {
- [Rep]
- public List<String> labelNames;
- [Rep]
- public List<Block> labelTargets;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(labelNames == null || labelTargets == null || labelNames.Count == labelTargets.Count);
- }
-
- [NotDelayed]
- public GotoCmd(IToken/*!*/ tok, List<String>/*!*/ labelSeq)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(labelSeq != null);
- this.labelNames = labelSeq;
- }
- public GotoCmd(IToken/*!*/ tok, List<String>/*!*/ labelSeq, List<Block>/*!*/ blockSeq)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(labelSeq != null);
- Contract.Requires(blockSeq != null);
- Debug.Assert(labelSeq.Count == blockSeq.Count);
- for (int i = 0; i < labelSeq.Count; i++) {
- Debug.Assert(Equals(labelSeq[i], cce.NonNull(blockSeq[i]).Label));
- }
-
- this.labelNames = labelSeq;
- this.labelTargets = blockSeq;
- }
- public GotoCmd(IToken/*!*/ tok, List<Block>/*!*/ blockSeq)
- : base(tok) { //requires (blockSeq[i] != null ==> blockSeq[i].Label != null);
- Contract.Requires(tok != null);
- Contract.Requires(blockSeq != null);
- List<String> labelSeq = new List<String>();
- for (int i = 0; i < blockSeq.Count; i++)
- labelSeq.Add(cce.NonNull(blockSeq[i]).Label);
- this.labelNames = labelSeq;
- this.labelTargets = blockSeq;
- }
- public void AddTarget(Block b) {
- Contract.Requires(b != null);
- Contract.Requires(b.Label != null);
- Contract.Requires(this.labelTargets != null);
- Contract.Requires(this.labelNames != null);
- this.labelTargets.Add(b);
- this.labelNames.Add(b.Label);
- }
- public override void Emit(TokenTextWriter stream, int level) {
- //Contract.Requires(stream != null);
- Contract.Assume(this.labelNames != null);
- stream.Write(this, level, "goto ");
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- if (labelTargets == null) {
- string sep = "";
- foreach (string name in labelNames) {
- stream.Write("{0}{1}^^{2}", sep, "NoDecl", name);
- sep = ", ";
- }
- } else {
- string sep = "";
- foreach (Block/*!*/ b in labelTargets) {
- Contract.Assert(b != null);
- stream.Write("{0}h{1}^^{2}", sep, b.GetHashCode(), b.Label);
- sep = ", ";
- }
- }
- } else {
- labelNames.Emit(stream);
- }
- stream.WriteLine(";");
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(labelTargets != null);
- if (labelTargets != null) {
- // already resolved
- return;
- }
- Contract.Assume(this.labelNames != null);
- labelTargets = new List<Block>();
- foreach (string/*!*/ lbl in labelNames) {
- Contract.Assert(lbl != null);
- Block b = rc.LookUpBlock(lbl);
- if (b == null) {
- rc.Error(this, "goto to unknown block: {0}", lbl);
- } else {
- labelTargets.Add(b);
- }
- }
- Debug.Assert(rc.ErrorCount > 0 || labelTargets.Count == labelNames.Count);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitGotoCmd(this);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie {
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using System.Diagnostics.Contracts;
+ using Set = GSet<object>;
+
+
+ //---------------------------------------------------------------------
+ // BigBlock
+ public class BigBlock {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(tok != null);
+ Contract.Invariant(Anonymous || this.labelName != null);
+ Contract.Invariant(this._ec == null || this._tc == null);
+ Contract.Invariant(this._simpleCmds != null);
+ }
+
+ public readonly IToken/*!*/ tok;
+
+ public readonly bool Anonymous;
+
+ private string labelName;
+
+ public string LabelName
+ {
+ get
+ {
+ Contract.Ensures(Anonymous || Contract.Result<string>() != null);
+ return this.labelName;
+ }
+ set
+ {
+ Contract.Requires(Anonymous || value != null);
+ this.labelName = value;
+ }
+ }
+
+ [Rep]
+ private List<Cmd>/*!*/ _simpleCmds;
+
+ public List<Cmd>/*!*/ simpleCmds
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ return this._simpleCmds;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._simpleCmds = value;
+ }
+ }
+
+ private StructuredCmd _ec;
+
+ public StructuredCmd ec
+ {
+ get
+ {
+ return this._ec;
+ }
+ set
+ {
+ Contract.Requires(value == null || this.tc == null);
+ this._ec = value;
+ }
+ }
+
+ private TransferCmd _tc;
+
+ public TransferCmd tc
+ {
+ get
+ {
+ return this._tc;
+ }
+ set
+ {
+ Contract.Requires(value == null || this.ec == null);
+ this._tc = value;
+ }
+ }
+
+ public BigBlock successorBigBlock; // semantic successor (may be a back-edge, pointing back to enclosing while statement); null if successor is end of procedure body (or if field has not yet been initialized)
+
+ public BigBlock(IToken tok, string labelName, [Captured] List<Cmd> simpleCmds, StructuredCmd ec, TransferCmd tc) {
+ Contract.Requires(simpleCmds != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(ec == null || tc == null);
+ this.tok = tok;
+ this.Anonymous = labelName == null;
+ this.labelName = labelName;
+ this._simpleCmds = simpleCmds;
+ this._ec = ec;
+ this._tc = tc;
+ }
+
+ public void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ if (!Anonymous) {
+ stream.WriteLine(level, "{0}:",
+ CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.LabelName) : this.LabelName);
+ }
+
+ foreach (Cmd/*!*/ c in this.simpleCmds) {
+ Contract.Assert(c != null);
+ c.Emit(stream, level + 1);
+ }
+
+ if (this.ec != null) {
+ this.ec.Emit(stream, level + 1);
+ } else if (this.tc != null) {
+ this.tc.Emit(stream, level + 1);
+ }
+ }
+ }
+
+ public class StmtList {
+ [Rep]
+ private readonly List<BigBlock/*!*/>/*!*/ bigBlocks;
+
+ public IList<BigBlock/*!*/>/*!*/ BigBlocks
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IList<BigBlock>>() != null);
+ Contract.Ensures(Contract.Result<IList<BigBlock>>().IsReadOnly);
+ return this.bigBlocks.AsReadOnly();
+ }
+ }
+
+ public List<Cmd> PrefixCommands;
+ public readonly IToken/*!*/ EndCurly;
+ public StmtList ParentContext;
+ public BigBlock ParentBigBlock;
+
+ private readonly HashSet<string/*!*/>/*!*/ labels = new HashSet<string/*!*/>();
+
+ public void AddLabel(string label)
+ {
+ labels.Add(label);
+ }
+
+ public IEnumerable<string/*!*/>/*!*/ Labels
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string/*!*/>/*!*/>()));
+ return this.labels.AsEnumerable<string>();
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(EndCurly != null);
+ Contract.Invariant(cce.NonNullElements(this.bigBlocks));
+ Contract.Invariant(cce.NonNullElements(this.labels));
+ }
+
+ public StmtList(IList<BigBlock/*!*/>/*!*/ bigblocks, IToken endCurly) {
+ Contract.Requires(endCurly != null);
+ Contract.Requires(cce.NonNullElements(bigblocks));
+ Contract.Requires(bigblocks.Count > 0);
+ this.bigBlocks = new List<BigBlock>(bigblocks);
+ this.EndCurly = endCurly;
+ }
+
+ // prints the list of statements, not the surrounding curly braces
+ public void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ bool needSeperator = false;
+ foreach (BigBlock b in BigBlocks) {
+ Contract.Assert(b != null);
+ Contract.Assume(cce.IsPeerConsistent(b));
+ if (needSeperator) {
+ stream.WriteLine();
+ }
+ b.Emit(stream, level);
+ needSeperator = true;
+ }
+ }
+
+ /// <summary>
+ /// Tries to insert the commands "prefixCmds" at the beginning of the first block
+ /// of the StmtList, and returns "true" iff it succeeded.
+ /// In the event of success, the "suggestedLabel" returns as the name of the
+ /// block inside StmtList where "prefixCmds" were inserted. This name may be the
+ /// same as the one passed in, in case this StmtList has no preference as to what
+ /// to call its first block. In the event of failure, "suggestedLabel" is returned
+ /// as its input value.
+ /// Note, to be conservative (that is, ignoring the possible optimization that this
+ /// method enables), this method can do nothing and return false.
+ /// </summary>
+ public bool PrefixFirstBlock([Captured] List<Cmd> prefixCmds, ref string suggestedLabel) {
+ Contract.Requires(suggestedLabel != null);
+ Contract.Requires(prefixCmds != null);
+ Contract.Ensures(Contract.Result<bool>() || cce.Owner.None(prefixCmds)); // "prefixCmds" is captured only on success
+ Contract.Assume(PrefixCommands == null); // prefix has not been used
+
+ BigBlock bb0 = BigBlocks[0];
+ if (prefixCmds.Count == 0) {
+ // This is always a success, since there is nothing to insert. Now, decide
+ // which name to use for the first block.
+ if (bb0.Anonymous) {
+ bb0.LabelName = suggestedLabel;
+ } else {
+ Contract.Assert(bb0.LabelName != null);
+ suggestedLabel = bb0.LabelName;
+ }
+ return true;
+
+ } else {
+ // There really is something to insert. We can do this inline only if the first
+ // block is anonymous (which implies there is no branch to it from within the block).
+ if (bb0.Anonymous) {
+ PrefixCommands = prefixCmds;
+ bb0.LabelName = suggestedLabel;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// The AST for Boogie structured commands was designed to support backward compatibility with
+ /// the Boogie unstructured commands. This has made the structured commands hard to construct.
+ /// The StmtListBuilder class makes it easier to build structured commands.
+ /// </summary>
+ public class StmtListBuilder {
+ List<BigBlock/*!*/>/*!*/ bigBlocks = new List<BigBlock/*!*/>();
+ string label;
+ List<Cmd> simpleCmds;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(bigBlocks));
+ }
+
+ void Dump(StructuredCmd scmd, TransferCmd tcmd) {
+ Contract.Requires(scmd == null || tcmd == null);
+ Contract.Ensures(label == null && simpleCmds == null);
+ if (label == null && simpleCmds == null && scmd == null && tcmd == null) {
+ // nothing to do
+ } else {
+ if (simpleCmds == null) {
+ simpleCmds = new List<Cmd>();
+ }
+ bigBlocks.Add(new BigBlock(Token.NoToken, label, simpleCmds, scmd, tcmd));
+ label = null;
+ simpleCmds = null;
+ }
+ }
+
+ /// <summary>
+ /// Collects the StmtList built so far and returns it. The StmtListBuilder should no longer
+ /// be used once this method has been invoked.
+ /// </summary>
+ public StmtList Collect(IToken endCurlyBrace) {
+ Contract.Requires(endCurlyBrace != null);
+ Contract.Ensures(Contract.Result<StmtList>() != null);
+ Dump(null, null);
+ if (bigBlocks.Count == 0) {
+ simpleCmds = new List<Cmd>(); // the StmtList constructor doesn't like an empty list of BigBlock's
+ Dump(null, null);
+ }
+ return new StmtList(bigBlocks, endCurlyBrace);
+ }
+
+ public void Add(Cmd cmd) {
+ Contract.Requires(cmd != null);
+ if (simpleCmds == null) {
+ simpleCmds = new List<Cmd>();
+ }
+ simpleCmds.Add(cmd);
+ }
+
+ public void Add(StructuredCmd scmd) {
+ Contract.Requires(scmd != null);
+ Dump(scmd, null);
+ }
+
+ public void Add(TransferCmd tcmd) {
+ Contract.Requires(tcmd != null);
+ Dump(null, tcmd);
+ }
+
+ public void AddLabelCmd(string label) {
+ Contract.Requires(label != null);
+ Dump(null, null);
+ this.label = label;
+ }
+
+ public void AddLocalVariable(string name) {
+ Contract.Requires(name != null);
+ // TODO
+ }
+ }
+
+ class BigBlocksResolutionContext {
+ StmtList/*!*/ stmtList;
+ [Peer]
+ List<Block/*!*/> blocks;
+ string/*!*/ prefix = "anon";
+ int anon = 0;
+ int FreshAnon()
+ {
+ return anon++;
+ }
+ HashSet<string/*!*/> allLabels = new HashSet<string/*!*/>();
+ Errors/*!*/ errorHandler;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(stmtList != null);
+ Contract.Invariant(cce.NonNullElements(blocks, true));
+ Contract.Invariant(prefix != null);
+ Contract.Invariant(cce.NonNullElements(allLabels, true));
+ Contract.Invariant(errorHandler != null);
+ }
+
+ private void ComputeAllLabels(StmtList stmts) {
+ if (stmts == null) return;
+ foreach (BigBlock bb in stmts.BigBlocks) {
+ if (bb.LabelName != null) {
+ allLabels.Add(bb.LabelName);
+ }
+ ComputeAllLabels(bb.ec);
+ }
+ }
+
+ private void ComputeAllLabels(StructuredCmd cmd) {
+ if (cmd == null) return;
+ if (cmd is IfCmd) {
+ IfCmd ifCmd = (IfCmd)cmd;
+ ComputeAllLabels(ifCmd.thn);
+ ComputeAllLabels(ifCmd.elseIf);
+ ComputeAllLabels(ifCmd.elseBlock);
+ }
+ else if (cmd is WhileCmd) {
+ WhileCmd whileCmd = (WhileCmd)cmd;
+ ComputeAllLabels(whileCmd.Body);
+ }
+ }
+
+ public BigBlocksResolutionContext(StmtList stmtList, Errors errorHandler) {
+ Contract.Requires(errorHandler != null);
+ Contract.Requires(stmtList != null);
+ this.stmtList = stmtList;
+ this.errorHandler = errorHandler;
+ ComputeAllLabels(stmtList);
+ }
+
+ public List<Block/*!*/>/*!*/ Blocks {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+ if (blocks == null) {
+ blocks = new List<Block/*!*/>();
+
+ int startErrorCount = this.errorHandler.count;
+ // Check that all goto statements go to a label in allLabels, and no break statement to a non-enclosing loop.
+ // Also, determine a good value for "prefix".
+ CheckLegalLabels(stmtList, null, null);
+
+ // fill in names of anonymous blocks
+ NameAnonymousBlocks(stmtList);
+
+ // determine successor blocks
+ RecordSuccessors(stmtList, null);
+
+ if (this.errorHandler.count == startErrorCount) {
+ // generate blocks from the big blocks
+ CreateBlocks(stmtList, null);
+ }
+ }
+ return blocks;
+ }
+ }
+
+ void CheckLegalLabels(StmtList stmtList, StmtList parentContext, BigBlock parentBigBlock) {
+ Contract.Requires(stmtList != null);
+ Contract.Requires((parentContext == null) == (parentBigBlock == null));
+ Contract.Requires(stmtList.ParentContext == null); // it hasn't been set yet
+ //modifies stmtList.*;
+ Contract.Ensures(stmtList.ParentContext == parentContext);
+ stmtList.ParentContext = parentContext;
+ stmtList.ParentBigBlock = parentBigBlock;
+
+ // record the labels declared in this StmtList
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ if (b.LabelName != null) {
+ string n = b.LabelName;
+ if (n.StartsWith(prefix)) {
+ if (prefix.Length < n.Length && n[prefix.Length] == '0') {
+ prefix += "1";
+ } else {
+ prefix += "0";
+ }
+ }
+ stmtList.AddLabel(b.LabelName);
+ }
+ }
+
+ // check that labels in this and nested StmtList's are legal
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ // goto's must reference blocks in enclosing blocks
+ if (b.tc is GotoCmd) {
+ GotoCmd g = (GotoCmd)b.tc;
+ foreach (string/*!*/ lbl in cce.NonNull(g.labelNames)) {
+ Contract.Assert(lbl != null);
+ /*
+ bool found = false;
+ for (StmtList sl = stmtList; sl != null; sl = sl.ParentContext) {
+ if (sl.Labels.Contains(lbl)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined or out of reach");
+ }
+ */
+ if (!allLabels.Contains(lbl)) {
+ this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined");
+ }
+ }
+ }
+
+ // break labels must refer to an enclosing while statement
+ else if (b.ec is BreakCmd) {
+ BreakCmd bcmd = (BreakCmd)b.ec;
+ Contract.Assert(bcmd.BreakEnclosure == null); // it hasn't been initialized yet
+ bool found = false;
+ for (StmtList sl = stmtList; sl.ParentBigBlock != null; sl = sl.ParentContext) {
+ cce.LoopInvariant(sl != null);
+ BigBlock bb = sl.ParentBigBlock;
+
+ if (bcmd.Label == null) {
+ // a label-less break statement breaks out of the innermost enclosing while statement
+ if (bb.ec is WhileCmd) {
+ bcmd.BreakEnclosure = bb;
+ found = true;
+ break;
+ }
+ } else if (bcmd.Label == bb.LabelName) {
+ // a break statement with a label can break out of both if statements and while statements
+ if (bb.simpleCmds.Count == 0) {
+ // this is a good target: the label refers to the if/while statement
+ bcmd.BreakEnclosure = bb;
+ } else {
+ // the label of bb refers to the first statement of bb, which in which case is a simple statement, not an if/while statement
+ this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
+ }
+ found = true; // don't look any further, since we've found a matching label
+ break;
+ }
+ }
+ if (!found) {
+ if (bcmd.Label == null) {
+ this.errorHandler.SemErr(bcmd.tok, "Error: break statement is not inside a loop");
+ } else {
+ this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
+ }
+ }
+ }
+
+ // recurse
+ else if (b.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)b.ec;
+ CheckLegalLabels(wcmd.Body, stmtList, b);
+ } else {
+ for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ CheckLegalLabels(ifcmd.thn, stmtList, b);
+ if (ifcmd.elseBlock != null) {
+ CheckLegalLabels(ifcmd.elseBlock, stmtList, b);
+ }
+ }
+ }
+ }
+ }
+
+ void NameAnonymousBlocks(StmtList stmtList) {
+ Contract.Requires(stmtList != null);
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ if (b.LabelName == null) {
+ b.LabelName = prefix + FreshAnon();
+ }
+ if (b.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)b.ec;
+ NameAnonymousBlocks(wcmd.Body);
+ } else {
+ for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ NameAnonymousBlocks(ifcmd.thn);
+ if (ifcmd.elseBlock != null) {
+ NameAnonymousBlocks(ifcmd.elseBlock);
+ }
+ }
+ }
+ }
+ }
+
+ void RecordSuccessors(StmtList stmtList, BigBlock successor) {
+ Contract.Requires(stmtList != null);
+ for (int i = stmtList.BigBlocks.Count; 0 <= --i; ) {
+ BigBlock big = stmtList.BigBlocks[i];
+ big.successorBigBlock = successor;
+
+ if (big.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)big.ec;
+ RecordSuccessors(wcmd.Body, big);
+ } else {
+ for (IfCmd ifcmd = big.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ RecordSuccessors(ifcmd.thn, successor);
+ if (ifcmd.elseBlock != null) {
+ RecordSuccessors(ifcmd.elseBlock, successor);
+ }
+ }
+ }
+
+ successor = big;
+ }
+ }
+
+ // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label;
+ // otherwise, it is null.
+ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) {
+ Contract.Requires(stmtList != null);
+ Contract.Requires(blocks != null);
+ List<Cmd> cmdPrefixToApply = stmtList.PrefixCommands;
+
+ int n = stmtList.BigBlocks.Count;
+ foreach (BigBlock b in stmtList.BigBlocks) {
+ n--;
+ Contract.Assert(b.LabelName != null);
+ List<Cmd> theSimpleCmds;
+ if (cmdPrefixToApply == null) {
+ theSimpleCmds = b.simpleCmds;
+ } else {
+ theSimpleCmds = new List<Cmd>();
+ theSimpleCmds.AddRange(cmdPrefixToApply);
+ theSimpleCmds.AddRange(b.simpleCmds);
+ cmdPrefixToApply = null; // now, we've used 'em up
+ }
+
+ if (b.tc != null) {
+ // this BigBlock has the very same components as a Block
+ Contract.Assert(b.ec == null);
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc);
+ blocks.Add(block);
+
+ } else if (b.ec == null) {
+ TransferCmd trCmd;
+ if (n == 0 && runOffTheEndLabel != null) {
+ // goto the given label instead of the textual successor block
+ trCmd = new GotoCmd(stmtList.EndCurly, new List<String> { runOffTheEndLabel });
+ } else {
+ trCmd = GotoSuccessor(stmtList.EndCurly, b);
+ }
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd);
+ blocks.Add(block);
+
+ } else if (b.ec is BreakCmd) {
+ BreakCmd bcmd = (BreakCmd)b.ec;
+ Contract.Assert(bcmd.BreakEnclosure != null);
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure));
+ blocks.Add(block);
+
+ } else if (b.ec is WhileCmd) {
+ WhileCmd wcmd = (WhileCmd)b.ec;
+ var a = FreshAnon();
+ string loopHeadLabel = prefix + a + "_LoopHead";
+ string/*!*/ loopBodyLabel = prefix + a + "_LoopBody";
+ string loopDoneLabel = prefix + a + "_LoopDone";
+
+ List<Cmd> ssBody = new List<Cmd>();
+ List<Cmd> ssDone = new List<Cmd>();
+ if (wcmd.Guard != null) {
+ var ac = new AssumeCmd(wcmd.tok, wcmd.Guard);
+ ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null);
+ ssBody.Add(ac);
+
+ ac = new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard));
+ ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null);
+ ssDone.Add(ac);
+ }
+
+ // Try to squeeze in ssBody into the first block of wcmd.Body
+ bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel);
+
+ // ... goto LoopHead;
+ Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new List<String> { loopHeadLabel }));
+ blocks.Add(block);
+
+ // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody;
+ List<Cmd> ssHead = new List<Cmd>();
+ foreach (PredicateCmd inv in wcmd.Invariants) {
+ ssHead.Add(inv);
+ }
+ block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new List<String> { loopDoneLabel, loopBodyLabel }));
+ blocks.Add(block);
+
+ if (!bodyGuardTakenCareOf) {
+ // LoopBody: assume guard; goto firstLoopBlock;
+ block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new List<String> { wcmd.Body.BigBlocks[0].LabelName }));
+ blocks.Add(block);
+ }
+
+ // recurse to create the blocks for the loop body
+ CreateBlocks(wcmd.Body, loopHeadLabel);
+
+ // LoopDone: assume !guard; goto loopSuccessor;
+ TransferCmd trCmd;
+ if (n == 0 && runOffTheEndLabel != null) {
+ // goto the given label instead of the textual successor block
+ trCmd = new GotoCmd(wcmd.tok, new List<String> { runOffTheEndLabel });
+ } else {
+ trCmd = GotoSuccessor(wcmd.tok, b);
+ }
+ block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd);
+ blocks.Add(block);
+
+ } else {
+ IfCmd ifcmd = (IfCmd)b.ec;
+ string predLabel = b.LabelName;
+ List<Cmd> predCmds = theSimpleCmds;
+
+ for (; ifcmd != null; ifcmd = ifcmd.elseIf) {
+ var a = FreshAnon();
+ string thenLabel = prefix + a + "_Then";
+ Contract.Assert(thenLabel != null);
+ string elseLabel = prefix + a + "_Else";
+ Contract.Assert(elseLabel != null);
+
+ List<Cmd> ssThen = new List<Cmd>();
+ List<Cmd> ssElse = new List<Cmd>();
+ if (ifcmd.Guard != null) {
+ var ac = new AssumeCmd(ifcmd.tok, ifcmd.Guard);
+ ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
+ ssThen.Add(ac);
+
+ ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard));
+ ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
+ ssElse.Add(ac);
+ }
+
+ // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock
+ bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel);
+ bool elseGuardTakenCareOf = false;
+ if (ifcmd.elseBlock != null) {
+ elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel);
+ }
+
+ // ... goto Then, Else;
+ Block block = new Block(b.tok, predLabel, predCmds,
+ new GotoCmd(ifcmd.tok, new List<String> { thenLabel, elseLabel }));
+ blocks.Add(block);
+
+ if (!thenGuardTakenCareOf) {
+ // Then: assume guard; goto firstThenBlock;
+ block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.thn.BigBlocks[0].LabelName }));
+ blocks.Add(block);
+ }
+
+ // recurse to create the blocks for the then branch
+ CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null);
+
+ if (ifcmd.elseBlock != null) {
+ Contract.Assert(ifcmd.elseIf == null);
+ if (!elseGuardTakenCareOf) {
+ // Else: assume !guard; goto firstElseBlock;
+ block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.elseBlock.BigBlocks[0].LabelName }));
+ blocks.Add(block);
+ }
+
+ // recurse to create the blocks for the else branch
+ CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null);
+
+ } else if (ifcmd.elseIf != null) {
+ // this is an "else if"
+ predLabel = elseLabel;
+ predCmds = new List<Cmd>();
+ if (ifcmd.Guard != null) {
+ var ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard));
+ ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
+ predCmds.Add(ac);
+ }
+
+ } else {
+ // no else alternative is specified, so else branch is just "skip"
+ // Else: assume !guard; goto ifSuccessor;
+ TransferCmd trCmd;
+ if (n == 0 && runOffTheEndLabel != null) {
+ // goto the given label instead of the textual successor block
+ trCmd = new GotoCmd(ifcmd.tok, new List<String> { runOffTheEndLabel });
+ } else {
+ trCmd = GotoSuccessor(ifcmd.tok, b);
+ }
+ block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd);
+ blocks.Add(block);
+ }
+ }
+ }
+ }
+ }
+
+ TransferCmd GotoSuccessor(IToken tok, BigBlock b) {
+ Contract.Requires(b != null);
+ Contract.Requires(tok != null);
+ Contract.Ensures(Contract.Result<TransferCmd>() != null);
+ if (b.successorBigBlock != null) {
+ return new GotoCmd(tok, new List<String> { b.successorBigBlock.LabelName });
+ } else {
+ return new ReturnCmd(tok);
+ }
+ }
+ }
+
+ [ContractClass(typeof(StructuredCmdContracts))]
+ public abstract class StructuredCmd {
+ private IToken/*!*/ _tok;
+
+ public IToken/*!*/ tok
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IToken>() != null);
+ return this._tok;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._tok = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._tok != null);
+ }
+
+ public StructuredCmd(IToken tok) {
+ Contract.Requires(tok != null);
+ this._tok = tok;
+ }
+
+ public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
+ }
+ [ContractClassFor(typeof(StructuredCmd))]
+ public abstract class StructuredCmdContracts : StructuredCmd {
+ public override void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ throw new NotImplementedException();
+ }
+ public StructuredCmdContracts() :base(null){
+
+ }
+ }
+
+ public class IfCmd : StructuredCmd {
+ public Expr Guard;
+
+ private StmtList/*!*/ _thn;
+
+ public StmtList/*!*/ thn
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<StmtList>() != null);
+ return this._thn;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._thn = value;
+ }
+ }
+
+ private IfCmd _elseIf;
+
+ public IfCmd elseIf
+ {
+ get
+ {
+ return this._elseIf;
+ }
+ set
+ {
+ Contract.Requires(value == null || this.elseBlock == null);
+ this._elseIf = value;
+ }
+ }
+
+ private StmtList _elseBlock;
+
+ public StmtList elseBlock
+ {
+ get
+ {
+ return this._elseBlock;
+ }
+ set
+ {
+ Contract.Requires(value == null || this.elseIf == null);
+ this._elseBlock = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._thn != null);
+ Contract.Invariant(this._elseIf == null || this._elseBlock == null);
+ }
+
+ public IfCmd(IToken/*!*/ tok, Expr guard, StmtList/*!*/ thn, IfCmd elseIf, StmtList elseBlock)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(thn != null);
+ Contract.Requires(elseIf == null || elseBlock == null);
+ this.Guard = guard;
+ this._thn = thn;
+ this._elseIf = elseIf;
+ this._elseBlock = elseBlock;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ stream.Write(level, "if (");
+ IfCmd/*!*/ ifcmd = this;
+ while (true) {
+ if (ifcmd.Guard == null) {
+ stream.Write("*");
+ } else {
+ ifcmd.Guard.Emit(stream);
+ }
+ stream.WriteLine(")");
+
+ stream.WriteLine(level, "{");
+ ifcmd.thn.Emit(stream, level + 1);
+ stream.WriteLine(level, "}");
+
+ if (ifcmd.elseIf != null) {
+ stream.Write(level, "else if (");
+ ifcmd = ifcmd.elseIf;
+ continue;
+ } else if (ifcmd.elseBlock != null) {
+ stream.WriteLine(level, "else");
+ stream.WriteLine(level, "{");
+ ifcmd.elseBlock.Emit(stream, level + 1);
+ stream.WriteLine(level, "}");
+ }
+ break;
+ }
+ }
+ }
+
+ public class WhileCmd : StructuredCmd {
+ [Peer]
+ public Expr Guard;
+ public List<PredicateCmd/*!*/>/*!*/ Invariants;
+ public StmtList/*!*/ Body;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Body != null);
+ Contract.Invariant(cce.NonNullElements(Invariants));
+ }
+
+
+ public WhileCmd(IToken tok, [Captured] Expr guard, List<PredicateCmd/*!*/>/*!*/ invariants, StmtList/*!*/ body)
+ : base(tok) {
+ Contract.Requires(cce.NonNullElements(invariants));
+ Contract.Requires(body != null);
+ Contract.Requires(tok != null);
+ this.Guard = guard;
+ this.Invariants = invariants;
+ this.Body = body;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ stream.Write(level, "while (");
+ if (Guard == null) {
+ stream.Write("*");
+ } else {
+ Guard.Emit(stream);
+ }
+ stream.WriteLine(")");
+
+ foreach (PredicateCmd inv in Invariants) {
+ if (inv is AssumeCmd) {
+ stream.Write(level + 1, "free invariant ");
+ } else {
+ stream.Write(level + 1, "invariant ");
+ }
+ Cmd.EmitAttributes(stream, inv.Attributes);
+ inv.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+
+ stream.WriteLine(level, "{");
+ Body.Emit(stream, level + 1);
+ stream.WriteLine(level, "}");
+ }
+ }
+
+ public class BreakCmd : StructuredCmd {
+ public string Label;
+ public BigBlock BreakEnclosure;
+
+ public BreakCmd(IToken tok, string label)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ this.Label = label;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+
+ if (Label == null) {
+ stream.WriteLine(level, "break;");
+ } else {
+ stream.WriteLine(level, "break {0};", Label);
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Block
+ public sealed class Block : Absy {
+ private string/*!*/ label; // Note, Label is mostly readonly, but it can change to the name of a nearby block during block coalescing and empty-block removal
+
+ public string/*!*/ Label
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this.label;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this.label = value;
+ }
+ }
+
+ [Rep]
+ [ElementsPeer]
+ public List<Cmd>/*!*/ cmds;
+
+ public List<Cmd>/*!*/ Cmds
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ return this.cmds;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this.cmds = value;
+ }
+ }
+
+ [Rep] //PM: needed to verify Traverse.Visit
+ public TransferCmd TransferCmd; // maybe null only because we allow deferred initialization (necessary for cyclic structures)
+
+ public byte[] Checksum;
+
+ // Abstract interpretation
+
+ // public bool currentlyTraversed;
+
+ public enum VisitState {
+ ToVisit,
+ BeingVisited,
+ AlreadyVisited
+ }; // used by WidenPoints.Compute
+ public VisitState TraversingStatus;
+
+ public int aiId; // block ID used by the abstract interpreter, which may change these numbers with each AI run
+ public bool widenBlock;
+ public int iterations; // Count the number of time we visited the block during fixpoint computation. Used to decide if we widen or not
+
+ // VC generation and SCC computation
+ public List<Block>/*!*/ Predecessors;
+
+ // This field is used during passification to null-out entries in block2Incartion hashtable early
+ public int succCount;
+
+ private HashSet<Variable/*!*/> _liveVarsBefore;
+
+ public IEnumerable<Variable/*!*/> liveVarsBefore
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Variable/*!*/>>(), true));
+ if (this._liveVarsBefore == null)
+ return null;
+ else
+ return this._liveVarsBefore.AsEnumerable<Variable>();
+ }
+ set
+ {
+ Contract.Requires(cce.NonNullElements(value, true));
+ if (value == null)
+ this._liveVarsBefore = null;
+ else
+ this._liveVarsBefore = new HashSet<Variable>(value);
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this.label != null);
+ Contract.Invariant(this.cmds != null);
+ Contract.Invariant(cce.NonNullElements(this._liveVarsBefore, true));
+ }
+
+ public bool IsLive(Variable v) {
+ Contract.Requires(v != null);
+ if (liveVarsBefore == null)
+ return true;
+ return liveVarsBefore.Contains(v);
+ }
+
+ public Block()
+ : this(Token.NoToken, "", new List<Cmd>(), new ReturnCmd(Token.NoToken)) {
+
+ }
+
+ public Block(IToken tok, string/*!*/ label, List<Cmd>/*!*/ cmds, TransferCmd transferCmd)
+ : base(tok) {
+ Contract.Requires(label != null);
+ Contract.Requires(cmds != null);
+ Contract.Requires(tok != null);
+ this.label = label;
+ this.cmds = cmds;
+ this.TransferCmd = transferCmd;
+ this.Predecessors = new List<Block>();
+ this._liveVarsBefore = null;
+ this.TraversingStatus = VisitState.ToVisit;
+ this.iterations = 0;
+ }
+
+ public void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ stream.WriteLine();
+ stream.WriteLine(
+ this,
+ level,
+ "{0}:{1}",
+ CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.Label) : this.Label,
+ this.widenBlock ? " // cut point" : "");
+
+ foreach (Cmd/*!*/ c in this.Cmds) {
+ Contract.Assert(c != null);
+ c.Emit(stream, level + 1);
+ }
+ Contract.Assume(this.TransferCmd != null);
+ this.TransferCmd.Emit(stream, level + 1);
+ }
+
+ public void Register(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ rc.AddBlock(this);
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+
+
+ foreach (Cmd/*!*/ c in Cmds) {
+ Contract.Assert(c != null);
+ c.Resolve(rc);
+ }
+ Contract.Assume(this.TransferCmd != null);
+ TransferCmd.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+
+ foreach (Cmd/*!*/ c in Cmds) {
+ Contract.Assert(c != null);
+ c.Typecheck(tc);
+ }
+ Contract.Assume(this.TransferCmd != null);
+ TransferCmd.Typecheck(tc);
+ }
+
+ /// <summary>
+ /// Reset the abstract intepretation state of this block. It does this by putting the iterations to 0 and the pre and post states to null
+ /// </summary>
+ public void ResetAbstractInterpretationState() {
+ // this.currentlyTraversed = false;
+ this.TraversingStatus = VisitState.ToVisit;
+ this.iterations = 0;
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this.Label + (this.widenBlock ? "[w]" : "");
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBlock(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Commands
+ [ContractClassFor(typeof(Cmd))]
+ public abstract class CmdContracts : Cmd {
+ public CmdContracts() :base(null){
+
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ throw new NotImplementedException();
+ }
+ public override void AddAssignedVariables(List<Variable> vars) {
+ Contract.Requires(vars != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public static class ChecksumHelper
+ {
+ public static void ComputeChecksums(Cmd cmd, Implementation impl, ISet<Variable> usedVariables, byte[] currentChecksum = null)
+ {
+ if (CommandLineOptions.Clo.VerifySnapshots < 2)
+ {
+ return;
+ }
+
+ if (cmd.IrrelevantForChecksumComputation)
+ {
+ cmd.Checksum = currentChecksum;
+ return;
+ }
+
+ var assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd != null
+ && QKeyValue.FindBoolAttribute(assumeCmd.Attributes, "assumption_variable_initialization"))
+ {
+ // Ignore assumption variable initializations.
+ assumeCmd.Checksum = currentChecksum;
+ return;
+ }
+
+ using (var strWr = new System.IO.StringWriter())
+ using (var tokTxtWr = new TokenTextWriter("<no file>", strWr, false, false))
+ {
+ tokTxtWr.UseForComputingChecksums = true;
+ var havocCmd = cmd as HavocCmd;
+ if (havocCmd != null)
+ {
+ tokTxtWr.Write("havoc ");
+ var relevantVars = havocCmd.Vars.Where(e => usedVariables.Contains(e.Decl) && !e.Decl.Name.StartsWith("a##cached##")).OrderBy(e => e.Name).ToList();
+ relevantVars.Emit(tokTxtWr, true);
+ tokTxtWr.WriteLine(";");
+ }
+ else
+ {
+ cmd.Emit(tokTxtWr, 0);
+ }
+ var md5 = System.Security.Cryptography.MD5.Create();
+ var str = strWr.ToString();
+ if (str.Any())
+ {
+ var data = System.Text.Encoding.UTF8.GetBytes(str);
+ var checksum = md5.ComputeHash(data);
+ currentChecksum = currentChecksum != null ? CombineChecksums(currentChecksum, checksum) : checksum;
+ }
+ cmd.Checksum = currentChecksum;
+ }
+
+ var assertCmd = cmd as AssertCmd;
+ if (assertCmd != null && assertCmd.Checksum != null)
+ {
+ var assertRequiresCmd = assertCmd as AssertRequiresCmd;
+ if (assertRequiresCmd != null)
+ {
+ impl.AddAssertionChecksum(assertRequiresCmd.Checksum);
+ impl.AddAssertionChecksum(assertRequiresCmd.Call.Checksum);
+ assertRequiresCmd.SugaredCmdChecksum = assertRequiresCmd.Call.Checksum;
+ }
+ else
+ {
+ impl.AddAssertionChecksum(assertCmd.Checksum);
+ }
+ }
+
+ var sugaredCmd = cmd as SugaredCmd;
+ if (sugaredCmd != null)
+ {
+ // The checksum of a sugared command should not depend on the desugaring itself.
+ var stateCmd = sugaredCmd.Desugaring as StateCmd;
+ if (stateCmd != null)
+ {
+ foreach (var c in stateCmd.Cmds)
+ {
+ ComputeChecksums(c, impl, usedVariables, currentChecksum);
+ currentChecksum = c.Checksum;
+ if (c.SugaredCmdChecksum == null)
+ {
+ c.SugaredCmdChecksum = cmd.Checksum;
+ }
+ }
+ }
+ else
+ {
+ ComputeChecksums(sugaredCmd.Desugaring, impl, usedVariables, currentChecksum);
+ }
+ }
+ }
+
+ public static byte[] CombineChecksums(byte[] first, byte[] second, bool unordered = false)
+ {
+ Contract.Requires(first != null && (second == null || first.Length == second.Length));
+
+ var result = (byte[])(first.Clone());
+ for (int i = 0; second != null && i < second.Length; i++)
+ {
+ if (unordered)
+ {
+ result[i] += second[i];
+ }
+ else
+ {
+ result[i] = (byte)(result[i] * 31 ^ second[i]);
+ }
+ }
+ return result;
+ }
+ }
+
+ [ContractClass(typeof(CmdContracts))]
+ public abstract class Cmd : Absy {
+ public byte[] Checksum { get; internal set; }
+ public byte[] SugaredCmdChecksum { get; internal set; }
+ public bool IrrelevantForChecksumComputation { get; set; }
+
+ public Cmd(IToken/*!*/ tok)
+ : base(tok) {
+ Contract.Assert(tok != null);
+ }
+ public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
+ public abstract void AddAssignedVariables(List<Variable>/*!*/ vars);
+ public void CheckAssignments(TypecheckingContext tc)
+ {
+ Contract.Requires(tc != null);
+ List<Variable>/*!*/ vars = new List<Variable>();
+ this.AddAssignedVariables(vars);
+ foreach (Variable/*!*/ v in vars)
+ {
+ Contract.Assert(v != null);
+ if (!v.IsMutable)
+ {
+ tc.Error(this, "command assigns to an immutable variable: {0}", v.Name);
+ }
+ else if (!CommandLineOptions.Clo.DoModSetAnalysis && v is GlobalVariable)
+ {
+ if (tc.Yields) {
+ // a yielding procedure is allowed to modify any global variable
+ }
+ else if (tc.Frame == null)
+ {
+ tc.Error(this, "update to a global variable allowed only inside an atomic action of a yielding procedure");
+ }
+ else if (!tc.InFrame(v))
+ {
+ tc.Error(this, "command assigns to a global variable that is not in the enclosing procedure's modifies clause: {0}", v.Name);
+ }
+ }
+ }
+ }
+
+ // Methods to simulate the old SimpleAssignCmd and MapAssignCmd
+ public static AssignCmd SimpleAssign(IToken tok, IdentifierExpr lhs, Expr rhs) {
+ Contract.Requires(rhs != null);
+ Contract.Requires(lhs != null);
+ Contract.Requires(tok != null);
+ Contract.Ensures(Contract.Result<AssignCmd>() != null);
+ List<AssignLhs/*!*/>/*!*/ lhss = new List<AssignLhs/*!*/>();
+ List<Expr/*!*/>/*!*/ rhss = new List<Expr/*!*/>();
+
+ lhss.Add(new SimpleAssignLhs(lhs.tok, lhs));
+ rhss.Add(rhs);
+
+ return new AssignCmd(tok, lhss, rhss);
+ }
+
+ public static AssignCmd/*!*/ MapAssign(IToken tok,
+ IdentifierExpr/*!*/ map,
+ List<Expr>/*!*/ indexes, Expr/*!*/ rhs) {
+
+ Contract.Requires(tok != null);
+ Contract.Requires(map != null);
+ Contract.Requires(indexes != null);
+ Contract.Requires(rhs != null);
+ Contract.Ensures(Contract.Result<AssignCmd>() != null);
+ List<AssignLhs/*!*/>/*!*/ lhss = new List<AssignLhs/*!*/>();
+ List<Expr/*!*/>/*!*/ rhss = new List<Expr/*!*/>();
+ List<Expr/*!*/>/*!*/ indexesList = new List<Expr/*!*/>();
+
+
+
+ foreach (Expr e in indexes)
+ indexesList.Add(cce.NonNull(e));
+
+ lhss.Add(new MapAssignLhs(map.tok,
+ new SimpleAssignLhs(map.tok, map),
+ indexesList));
+ rhss.Add(rhs);
+
+ return new AssignCmd(tok, lhss, rhss);
+ }
+
+ public static AssignCmd/*!*/ MapAssign(IToken tok,
+ IdentifierExpr/*!*/ map,
+ params Expr[]/*!*/ args) {
+ Contract.Requires(tok != null);
+ Contract.Requires(map != null);
+ Contract.Requires(args != null);
+ Contract.Requires(args.Length > 0); // at least the rhs
+ Contract.Requires(Contract.ForAll(args, i => i != null));
+ Contract.Ensures(Contract.Result<AssignCmd>() != null);
+
+ List<AssignLhs/*!*/>/*!*/ lhss = new List<AssignLhs/*!*/>();
+ List<Expr/*!*/>/*!*/ rhss = new List<Expr/*!*/>();
+ List<Expr/*!*/>/*!*/ indexesList = new List<Expr/*!*/>();
+
+ for (int i = 0; i < args.Length - 1; ++i)
+ indexesList.Add(cce.NonNull(args[i]));
+
+ lhss.Add(new MapAssignLhs(map.tok,
+ new SimpleAssignLhs(map.tok, map),
+ indexesList));
+ rhss.Add(cce.NonNull(args[args.Length - 1]));
+
+ return new AssignCmd(tok, lhss, rhss);
+ }
+
+ /// <summary>
+ /// This is a helper routine for printing a linked list of attributes. Each attribute
+ /// is terminated by a space.
+ /// </summary>
+ public static void EmitAttributes(TokenTextWriter stream, QKeyValue attributes) {
+ Contract.Requires(stream != null);
+
+ if (stream.UseForComputingChecksums) { return; }
+
+ for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
+ kv.Emit(stream);
+ stream.Write(" ");
+ }
+ }
+ public static void ResolveAttributes(QKeyValue attributes, ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
+ kv.Resolve(rc);
+ }
+ }
+ public static void TypecheckAttributes(QKeyValue attributes, TypecheckingContext tc) {
+ Contract.Requires(tc != null);
+ for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
+ kv.Typecheck(tc);
+ }
+ }
+
+ [Pure]
+ public override string ToString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false , /*pretty=*/ false)) {
+ this.Emit(stream, 0);
+ }
+ return buffer.ToString();
+ }
+ }
+
+ public class YieldCmd : Cmd
+ {
+ public YieldCmd(IToken/*!*/ tok)
+ : base(tok)
+ {
+ Contract.Requires(tok != null);
+ }
+ public override void Emit(TokenTextWriter stream, int level)
+ {
+ //Contract.Requires(stream != null);
+ stream.WriteLine(this, level, "yield;");
+ }
+ public override void Resolve(ResolutionContext rc)
+ {
+ // nothing to resolve
+ }
+ public override void Typecheck(TypecheckingContext tc)
+ {
+ if (!CommandLineOptions.Clo.DoModSetAnalysis && !tc.Yields)
+ {
+ tc.Error(this, "enclosing procedure of a yield command must yield");
+ }
+ }
+ public override void AddAssignedVariables(List<Variable> vars)
+ {
+ // nothing to add
+ }
+ public override Absy StdDispatch(StandardVisitor visitor)
+ {
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitYieldCmd(this);
+ }
+ }
+
+ public class CommentCmd : Cmd // just a convenience for debugging
+ {
+ public readonly string/*!*/ Comment;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Comment != null);
+ }
+
+ public CommentCmd(string c)
+ : base(Token.NoToken) {
+ Contract.Requires(c != null);
+ Comment = c;
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ if (stream.UseForComputingChecksums) { return; }
+
+ if (this.Comment.Contains("\n")) {
+ stream.WriteLine(this, level, "/* {0} */", this.Comment);
+ } else {
+ stream.WriteLine(this, level, "// {0}", this.Comment);
+ }
+ }
+ public override void Resolve(ResolutionContext rc) {
+
+ }
+ public override void AddAssignedVariables(List<Variable> vars) {
+
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+
+
+ return visitor.VisitCommentCmd(this);
+ }
+ }
+
+ // class for parallel assignments, which subsumes both the old
+ // SimpleAssignCmd and the old MapAssignCmd
+ public class AssignCmd : Cmd {
+ private List<AssignLhs/*!*/>/*!*/ _lhss;
+
+ public IList<AssignLhs/*!*/>/*!*/ Lhss {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IList<AssignLhs>>()));
+ Contract.Ensures(Contract.Result<IList<AssignLhs>>().IsReadOnly);
+ return this._lhss.AsReadOnly();
+ }
+ set {
+ Contract.Requires(cce.NonNullElements(value));
+ this._lhss = new List<AssignLhs>(value);
+ }
+ }
+
+ internal void SetLhs(int index, AssignLhs lhs)
+ {
+ Contract.Requires(0 <= index && index < this.Lhss.Count);
+ Contract.Requires(lhs != null);
+ Contract.Ensures(this.Lhss[index] == lhs);
+ this._lhss[index] = lhs;
+ }
+
+ private List<Expr/*!*/>/*!*/ _rhss;
+
+ public IList<Expr/*!*/>/*!*/ Rhss {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IList<Expr>>()));
+ Contract.Ensures(Contract.Result<IList<Expr>>().IsReadOnly);
+ return this._rhss.AsReadOnly();
+ }
+ set {
+ Contract.Requires(cce.NonNullElements(value));
+ this._rhss = new List<Expr>(value);
+ }
+ }
+
+ internal void SetRhs(int index, Expr rhs)
+ {
+ Contract.Requires(0 <= index && index < this.Rhss.Count);
+ Contract.Requires(rhs != null);
+ Contract.Ensures(this.Rhss[index] == rhs);
+ this._rhss[index] = rhs;
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(this._lhss));
+ Contract.Invariant(cce.NonNullElements(this._rhss));
+ }
+
+
+ public AssignCmd(IToken tok, IList<AssignLhs/*!*/>/*!*/ lhss, IList<Expr/*!*/>/*!*/ rhss)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(cce.NonNullElements(rhss));
+ Contract.Requires(cce.NonNullElements(lhss));
+ this._lhss = new List<AssignLhs>(lhss);
+ this._rhss = new List<Expr>(rhss);
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ stream.Write(this, level, "");
+
+ string/*!*/ sep = "";
+ foreach (AssignLhs/*!*/ l in Lhss) {
+ Contract.Assert(l != null);
+ stream.Write(sep);
+ sep = ", ";
+ l.Emit(stream);
+ }
+
+ stream.Write(" := ");
+
+ sep = "";
+ foreach (Expr/*!*/ e in Rhss) {
+ Contract.Assert(e != null);
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+
+ stream.WriteLine(";");
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+
+ if (Lhss.Count != Rhss.Count)
+ rc.Error(this,
+ "number of left-hand sides does not match number of right-hand sides");
+
+ foreach (AssignLhs/*!*/ e in Lhss) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+ }
+ foreach (Expr/*!*/ e in Rhss) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+ }
+
+ // check for double occurrences of assigned variables
+ // (could be optimised)
+ for (int i = 0; i < Lhss.Count; ++i) {
+ for (int j = i + 1; j < Lhss.Count; ++j) {
+ if (cce.NonNull(Lhss[i].DeepAssignedVariable).Equals(
+ Lhss[j].DeepAssignedVariable))
+ rc.Error(Lhss[j],
+ "variable {0} is assigned more than once in parallel assignment",
+ Lhss[j].DeepAssignedVariable);
+ }
+ }
+
+ for (int i = 0; i < Lhss.Count; i++)
+ {
+ var lhs = Lhss[i].AsExpr as IdentifierExpr;
+ if (lhs != null && lhs.Decl != null && QKeyValue.FindBoolAttribute(lhs.Decl.Attributes, "assumption"))
+ {
+ var rhs = Rhss[i] as NAryExpr;
+ if (rhs == null
+ || !(rhs.Fun is BinaryOperator)
+ || ((BinaryOperator)(rhs.Fun)).Op != BinaryOperator.Opcode.And
+ || !(rhs.Args[0] is IdentifierExpr)
+ || ((IdentifierExpr)(rhs.Args[0])).Name != lhs.Name)
+ {
+ rc.Error(tok, string.Format("RHS of assignment to assumption variable {0} must match expression \"{0} && <boolean expression>\"", lhs.Name));
+ }
+ else if (rc.HasVariableBeenAssigned(lhs.Decl.Name))
+ {
+ rc.Error(tok, "assumption variable may not be assigned to more than once");
+ }
+ else
+ {
+ rc.MarkVariableAsAssigned(lhs.Decl.Name);
+ }
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+
+ foreach (AssignLhs/*!*/ e in Lhss) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+ foreach (Expr/*!*/ e in Rhss) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+
+ this.CheckAssignments(tc);
+
+ for (int i = 0; i < Lhss.Count; ++i) {
+ Type ltype = Lhss[i].Type;
+ Type rtype = Rhss[i].Type;
+ if (ltype != null && rtype != null) {
+ // otherwise, there has already been an error when
+ // typechecking the lhs or rhs
+ if (!ltype.Unify(rtype))
+ tc.Error(Lhss[i],
+ "mismatched types in assignment command (cannot assign {0} to {1})",
+ rtype, ltype);
+ }
+ }
+ }
+
+ public override void AddAssignedVariables(List<Variable> vars) {
+
+ foreach (AssignLhs/*!*/ l in Lhss) {
+ Contract.Assert(l != null);
+ vars.Add(l.DeepAssignedVariable);
+ }
+ }
+
+ // transform away the syntactic sugar of map assignments and
+ // determine an equivalent assignment in which all rhs are simple
+ // variables
+ public AssignCmd/*!*/ AsSimpleAssignCmd {
+ get {
+ Contract.Ensures(Contract.Result<AssignCmd>() != null);
+
+ List<AssignLhs/*!*/>/*!*/ newLhss = new List<AssignLhs/*!*/>();
+ List<Expr/*!*/>/*!*/ newRhss = new List<Expr/*!*/>();
+
+ for (int i = 0; i < Lhss.Count; ++i) {
+ IdentifierExpr/*!*/ newLhs;
+ Expr/*!*/ newRhs;
+ Lhss[i].AsSimpleAssignment(Rhss[i], out newLhs, out newRhs);
+ newLhss.Add(new SimpleAssignLhs(Token.NoToken, newLhs));
+ newRhss.Add(newRhs);
+ }
+
+ return new AssignCmd(Token.NoToken, newLhss, newRhss);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+
+
+ return visitor.VisitAssignCmd(this);
+ }
+ }
+
+ // There are two different kinds of left-hand sides in assignments:
+ // simple variables (identifiers), or locations of a map
+ [ContractClass(typeof(AssignLhsContracts))]
+ public abstract class AssignLhs : Absy {
+ // The type of the lhs is determined during typechecking
+ public abstract Type Type {
+ get;
+ }
+ // Determine the variable that is actually assigned in this lhs
+ public abstract IdentifierExpr/*!*/ DeepAssignedIdentifier {
+ get;
+ }
+ public abstract Variable DeepAssignedVariable {
+ get;
+ }
+
+ public AssignLhs(IToken/*!*/ tok)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ }
+ public abstract void Emit(TokenTextWriter/*!*/ stream);
+
+ public abstract Expr/*!*/ AsExpr {
+ get;
+ }
+
+ // transform away the syntactic sugar of map assignments and
+ // determine an equivalent simple assignment
+ internal abstract void AsSimpleAssignment(Expr/*!*/ rhs,
+ out IdentifierExpr/*!*/ simpleLhs,
+ out Expr/*!*/ simpleRhs);
+ }
+ [ContractClassFor(typeof(AssignLhs))]
+ public abstract class AssignLhsContracts : AssignLhs {
+ public AssignLhsContracts():base(null)
+ {
+
+ }public override IdentifierExpr DeepAssignedIdentifier {
+
+ get {
+ Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
+ throw new NotImplementedException();
+ }
+ }
+ public override Expr AsExpr {
+ get {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ throw new NotImplementedException();
+ }
+
+ }
+ internal override void AsSimpleAssignment(Expr rhs, out IdentifierExpr simpleLhs, out Expr simpleRhs) {
+ Contract.Requires(rhs != null);
+ Contract.Ensures(Contract.ValueAtReturn(out simpleLhs) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out simpleRhs) != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public class SimpleAssignLhs : AssignLhs {
+ public IdentifierExpr/*!*/ AssignedVariable;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AssignedVariable != null);
+ }
+
+
+ public override Type Type {
+ get {
+ return AssignedVariable.Type;
+ }
+ }
+
+ public override IdentifierExpr/*!*/ DeepAssignedIdentifier {
+ get {
+ Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
+ return AssignedVariable;
+ }
+ }
+
+ public override Variable DeepAssignedVariable {
+ get {
+ return AssignedVariable.Decl;
+ }
+ }
+
+ public SimpleAssignLhs(IToken tok, IdentifierExpr assignedVariable)
+ : base(tok) {
+ Contract.Requires(assignedVariable != null);
+ Contract.Requires(tok != null);
+ AssignedVariable = assignedVariable;
+ }
+ public override void Resolve(ResolutionContext rc) {
+
+ AssignedVariable.Resolve(rc);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+
+ AssignedVariable.Typecheck(tc);
+ }
+ public override void Emit(TokenTextWriter stream) {
+
+ AssignedVariable.Emit(stream);
+ }
+ public override Expr/*!*/ AsExpr {
+ get {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+
+ return AssignedVariable;
+ }
+ }
+ internal override void AsSimpleAssignment(Expr rhs,
+ out IdentifierExpr/*!*/ simpleLhs,
+ out Expr/*!*/ simpleRhs) {
+
+
+
+ simpleLhs = AssignedVariable;
+ simpleRhs = rhs;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+
+
+ return visitor.VisitSimpleAssignLhs(this);
+ }
+ }
+
+ // A map-assignment-lhs (m[t1, t2, ...] := ...) is quite similar to
+ // a map select expression, but it is cleaner to keep those two
+ // things separate
+ public class MapAssignLhs : AssignLhs {
+ public AssignLhs/*!*/ Map;
+
+ public List<Expr/*!*/>/*!*/ Indexes;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Map != null);
+ Contract.Invariant(cce.NonNullElements(Indexes));
+ }
+
+
+ // The instantiation of type parameters of the map that is
+ // determined during type checking.
+ public TypeParamInstantiation TypeParameters = null;
+
+ private Type TypeAttr = null;
+
+ public override Type Type {
+ get {
+ return TypeAttr;
+ }
+ }
+
+ public override IdentifierExpr/*!*/ DeepAssignedIdentifier {
+ get {
+ Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
+
+ return Map.DeepAssignedIdentifier;
+ }
+ }
+
+ public override Variable DeepAssignedVariable {
+ get {
+ return Map.DeepAssignedVariable;
+ }
+ }
+
+ public MapAssignLhs(IToken tok, AssignLhs map, List<Expr/*!*/>/*!*/ indexes)
+ : base(tok) {
+ Contract.Requires(map != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+
+ Map = map;
+ Indexes = indexes;
+ }
+ public override void Resolve(ResolutionContext rc) {
+
+ Map.Resolve(rc);
+ foreach (Expr/*!*/ e in Indexes) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+ }
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+
+ Map.Typecheck(tc);
+ foreach (Expr/*!*/ e in Indexes) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+
+ // we use the same typechecking code as in MapSelect
+ List<Expr>/*!*/ selectArgs = new List<Expr>();
+ foreach (Expr/*!*/ e in Indexes) {
+ Contract.Assert(e != null);
+ selectArgs.Add(e);
+ }
+ TypeParamInstantiation/*!*/ tpInsts;
+ TypeAttr =
+ MapSelect.Typecheck(cce.NonNull(Map.Type), Map,
+ selectArgs, out tpInsts, tc, tok, "map assignment");
+ TypeParameters = tpInsts;
+ }
+ public override void Emit(TokenTextWriter stream) {
+
+ Map.Emit(stream);
+ stream.Write("[");
+ string/*!*/ sep = "";
+ foreach (Expr/*!*/ e in Indexes) {
+ Contract.Assert(e != null);
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+ stream.Write("]");
+ }
+ public override Expr/*!*/ AsExpr {
+ get {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+
+ NAryExpr/*!*/ res = Expr.Select(Map.AsExpr, Indexes);
+ Contract.Assert(res != null);
+ res.TypeParameters = this.TypeParameters;
+ res.Type = this.Type;
+ return res;
+ }
+ }
+ internal override void AsSimpleAssignment(Expr rhs,
+ out IdentifierExpr/*!*/ simpleLhs,
+ out Expr/*!*/ simpleRhs) { //Contract.Requires(rhs != null);
+ Contract.Ensures(Contract.ValueAtReturn(out simpleLhs) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out simpleRhs) != null);
+
+ NAryExpr/*!*/ newRhs = Expr.Store(Map.AsExpr, Indexes, rhs);
+ Contract.Assert(newRhs != null);
+ newRhs.TypeParameters = this.TypeParameters;
+ newRhs.Type = Map.Type;
+ Map.AsSimpleAssignment(newRhs, out simpleLhs, out simpleRhs);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitMapAssignLhs(this);
+ }
+ }
+
+ /// <summary>
+ /// A StateCmd is like an imperative-let binding around a sequence of commands.
+ /// There is no user syntax for a StateCmd. Instead, a StateCmd is only used
+ /// temporarily during the desugaring phase inside the VC generator.
+ /// </summary>
+ public class StateCmd : Cmd {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._locals != null);
+ Contract.Invariant(this._cmds != null);
+ }
+
+ private List<Variable> _locals;
+
+ public /*readonly, except for the StandardVisitor*/ List<Variable>/*!*/ Locals {
+ get {
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ return this._locals;
+ }
+ internal set {
+ Contract.Requires(value != null);
+ this._locals = value;
+ }
+ }
+
+ private List<Cmd> _cmds;
+
+ public /*readonly, except for the StandardVisitor*/ List<Cmd>/*!*/ Cmds {
+ get {
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ return this._cmds;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._cmds = value;
+ }
+ }
+
+ public StateCmd(IToken tok, List<Variable>/*!*/ locals, List<Cmd>/*!*/ cmds)
+ : base(tok) {
+ Contract.Requires(locals != null);
+ Contract.Requires(cmds != null);
+ Contract.Requires(tok != null);
+ this._locals = locals;
+ this._cmds = cmds;
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.PushVarContext();
+ foreach (Variable/*!*/ v in Locals) {
+ Contract.Assert(v != null);
+ rc.AddVariable(v, false);
+ }
+ foreach (Cmd/*!*/ cmd in Cmds) {
+ Contract.Assert(cmd != null);
+ cmd.Resolve(rc);
+ }
+ rc.PopVarContext();
+ }
+
+ public override void AddAssignedVariables(List<Variable> vars) {
+ //Contract.Requires(vars != null);
+ List<Variable>/*!*/ vs = new List<Variable>();
+ foreach (Cmd/*!*/ cmd in this.Cmds) {
+ Contract.Assert(cmd != null);
+ cmd.AddAssignedVariables(vs);
+ }
+ System.Collections.Hashtable/*!*/ localsSet = new System.Collections.Hashtable();
+ foreach (Variable/*!*/ local in this.Locals) {
+ Contract.Assert(local != null);
+ localsSet[local] = bool.TrueString;
+ }
+ foreach (Variable/*!*/ v in vs) {
+ Contract.Assert(v != null);
+ if (!localsSet.ContainsKey(v)) {
+ vars.Add(v);
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ foreach (Cmd/*!*/ cmd in Cmds) {
+ Contract.Assert(cmd != null);
+ cmd.Typecheck(tc);
+ }
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.WriteLine(this, level, "{");
+ foreach (Variable/*!*/ v in Locals) {
+ Contract.Assert(v != null);
+ v.Emit(stream, level + 1);
+ }
+ foreach (Cmd/*!*/ c in Cmds) {
+ Contract.Assert(c != null);
+ c.Emit(stream, level + 1);
+ }
+ stream.WriteLine(level, "}");
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitStateCmd(this);
+ }
+ }
+ [ContractClass(typeof(SugaredCmdContracts))]
+ abstract public class SugaredCmd : Cmd {
+ private Cmd desugaring; // null until desugared
+
+ public SugaredCmd(IToken/*!*/ tok)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ }
+
+ public Cmd/*!*/ Desugaring {
+ get {
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+
+ if (desugaring == null) {
+ desugaring = ComputeDesugaring();
+ }
+ return desugaring;
+ }
+ }
+ /// <summary>
+ /// This method invokes "visitor.Visit" on the desugaring, and then updates the
+ /// desugaring to the result thereof. The method's intended use is for subclasses
+ /// of StandardVisitor that need to also visit the desugaring. Note, since the
+ /// "desugaring" field is updated, this is not an appropriate method to be called
+ /// be a ReadOnlyVisitor; such visitors should instead just call
+ /// visitor.Visit(sugaredCmd.Desugaring).
+ /// </summary>
+ public void VisitDesugaring(StandardVisitor visitor) {
+ Contract.Requires(visitor != null && !(visitor is ReadOnlyVisitor));
+ if (desugaring != null) {
+ desugaring = (Cmd)visitor.Visit(desugaring);
+ }
+ }
+ protected abstract Cmd/*!*/ ComputeDesugaring();
+
+ public void ExtendDesugaring(IEnumerable<Cmd> before, IEnumerable<Cmd> beforePreconditionCheck, IEnumerable<Cmd> after)
+ {
+ var desug = Desugaring;
+ var stCmd = desug as StateCmd;
+ if (stCmd != null)
+ {
+ stCmd.Cmds.InsertRange(0, before);
+ var idx = stCmd.Cmds.FindIndex(c => c is AssertCmd || c is HavocCmd || c is AssumeCmd);
+ if (idx < 0)
+ {
+ idx = 0;
+ }
+ stCmd.Cmds.InsertRange(idx, beforePreconditionCheck);
+ stCmd.Cmds.AddRange(after);
+ }
+ else if (desug != null)
+ {
+ var cmds = new List<Cmd>(before);
+ cmds.Add(desug);
+ cmds.AddRange(after);
+ desugaring = new StateCmd(Token.NoToken, new List<Variable>(), cmds);
+ }
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ if (CommandLineOptions.Clo.PrintDesugarings && !stream.UseForComputingChecksums) {
+ stream.WriteLine(this, level, "/*** desugaring:");
+ Desugaring.Emit(stream, level);
+ stream.WriteLine(level, "**** end desugaring */");
+ }
+ }
+ }
+ [ContractClassFor(typeof(SugaredCmd))]
+ public abstract class SugaredCmdContracts : SugaredCmd {
+ public SugaredCmdContracts() :base(null){
+
+ }
+ protected override Cmd ComputeDesugaring() {
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public abstract class CallCommonality : SugaredCmd {
+ public QKeyValue Attributes;
+
+ private bool isFree = false;
+ public bool IsFree {
+ get {
+ return isFree;
+ }
+ set {
+ isFree = value;
+ }
+ }
+
+ private bool isAsync = false;
+ public bool IsAsync
+ {
+ get
+ {
+ return isAsync;
+ }
+ set
+ {
+ isAsync = value;
+ }
+ }
+
+ protected CallCommonality(IToken tok, QKeyValue kv)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Attributes = kv;
+ }
+
+ protected enum TempVarKind {
+ Formal,
+ Old,
+ Bound
+ }
+
+ // We have to give the type explicitly, because the type of the formal "likeThisOne" can contain type variables
+ protected Variable CreateTemporaryVariable(List<Variable> tempVars, Variable likeThisOne, Type ty, TempVarKind kind, ref int uniqueId) {
+ Contract.Requires(ty != null);
+ Contract.Requires(likeThisOne != null);
+ Contract.Requires(tempVars != null);
+ Contract.Ensures(Contract.Result<Variable>() != null);
+ string/*!*/ tempNamePrefix;
+ switch (kind) {
+ case TempVarKind.Formal:
+ tempNamePrefix = "formal@";
+ break;
+ case TempVarKind.Old:
+ tempNamePrefix = "old@";
+ break;
+ case TempVarKind.Bound:
+ tempNamePrefix = "forall@";
+ break;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // unexpected kind
+ }
+ TypedIdent ti = likeThisOne.TypedIdent;
+ // KLM: uniqueId was messing up FixedPointVC for unknown reason.
+ // I reverted this change for FixedPointVC only.
+ int id = CommandLineOptions.Clo.FixedPointEngine != null ? UniqueId : (uniqueId++);
+ TypedIdent newTi = new TypedIdent(ti.tok, "call" + id + tempNamePrefix + ti.Name, ty);
+ Variable/*!*/ v;
+ if (kind == TempVarKind.Bound) {
+ v = new BoundVariable(likeThisOne.tok, newTi);
+ } else {
+ v = new LocalVariable(likeThisOne.tok, newTi);
+ tempVars.Add(v);
+ }
+ return v;
+ }
+ }
+
+ public class ParCallCmd : CallCommonality, IPotentialErrorNode<object, object>
+ {
+ public List<CallCmd> CallCmds;
+ public ParCallCmd(IToken tok, List<CallCmd> callCmds)
+ : base(tok, null)
+ {
+ this.CallCmds = callCmds;
+ }
+ public ParCallCmd(IToken tok, List<CallCmd> callCmds, QKeyValue kv)
+ : base(tok, kv)
+ {
+ this.CallCmds = callCmds;
+ }
+ protected override Cmd ComputeDesugaring()
+ {
+ throw new NotImplementedException();
+ }
+ private object errorData;
+ public object ErrorData
+ {
+ get
+ {
+ return errorData;
+ }
+ set
+ {
+ errorData = value;
+ }
+ }
+ public override void Resolve(ResolutionContext rc)
+ {
+ ResolveAttributes(Attributes, rc);
+ foreach (CallCmd callCmd in CallCmds)
+ {
+ callCmd.Resolve(rc);
+ }
+ HashSet<Variable> parallelCallLhss = new HashSet<Variable>();
+ foreach (CallCmd callCmd in CallCmds)
+ {
+ foreach (IdentifierExpr ie in callCmd.Outs)
+ {
+ if (parallelCallLhss.Contains(ie.Decl))
+ {
+ rc.Error(this, "left-hand side of parallel call command contains variable twice: {0}", ie.Name);
+ }
+ else
+ {
+ parallelCallLhss.Add(ie.Decl);
+ }
+ }
+ }
+ }
+ public override void Typecheck(TypecheckingContext tc)
+ {
+ TypecheckAttributes(Attributes, tc);
+ if (!CommandLineOptions.Clo.DoModSetAnalysis)
+ {
+ if (!tc.Yields)
+ {
+ tc.Error(this, "enclosing procedure of a parallel call must yield");
+ }
+ foreach (CallCmd callCmd in CallCmds)
+ {
+ if (!QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "yields"))
+ {
+ tc.Error(callCmd, "target procedure of a parallel call must yield");
+ }
+ }
+ }
+ foreach (CallCmd callCmd in CallCmds)
+ {
+ callCmd.Typecheck(tc);
+ }
+ }
+ public override void AddAssignedVariables(List<Variable> vars)
+ {
+ foreach (CallCmd callCmd in CallCmds)
+ {
+ callCmd.AddAssignedVariables(vars);
+ }
+ }
+ public override Absy StdDispatch(StandardVisitor visitor)
+ {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitParCallCmd(this);
+ }
+ }
+
+ public class CallCmd : CallCommonality, IPotentialErrorNode<object, object>
+ {
+ public string/*!*/ callee { get; set; }
+ public Procedure Proc;
+ public LocalVariable AssignedAssumptionVariable;
+
+ // Element of the following lists can be null, which means that
+ // the call happens with * as these parameters
+ public List<Expr>/*!*/ Ins;
+ public List<IdentifierExpr>/*!*/ Outs;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(callee != null);
+ Contract.Invariant(Ins != null);
+ Contract.Invariant(Outs != null);
+ }
+
+ //public Lattice.Element StateAfterCall;
+
+ // The instantiation of type parameters that is determined during
+ // type checking
+ public TypeParamInstantiation TypeParameters = null;
+
+ // TODO: convert to use generics
+ private object errorData;
+ public object ErrorData {
+ get {
+ return errorData;
+ }
+ set {
+ errorData = value;
+ }
+ }
+ public CallCmd(IToken tok, string callee, List<Expr> ins, List<IdentifierExpr> outs)
+ : base(tok, null) {
+ Contract.Requires(outs != null);
+ Contract.Requires(ins != null);
+ Contract.Requires(callee != null);
+ Contract.Requires(tok != null);
+ this.callee = callee;
+ this.Ins = ins;
+ this.Outs = outs;
+ }
+ public CallCmd(IToken tok, string callee, List<Expr> ins, List<IdentifierExpr> outs, QKeyValue kv)
+ : base(tok, kv) {
+ Contract.Requires(outs != null);
+ Contract.Requires(ins != null);
+ Contract.Requires(callee != null);
+ Contract.Requires(tok != null);
+ this.callee = callee;
+ this.Ins = ins;
+ this.Outs = outs;
+ }
+
+ public CallCmd(IToken tok, string callee, List<Expr> ins, List<IdentifierExpr> outs, QKeyValue kv, bool IsAsync)
+ : base(tok, kv)
+ {
+ Contract.Requires(outs != null);
+ Contract.Requires(ins != null);
+ Contract.Requires(callee != null);
+ Contract.Requires(tok != null);
+ this.callee = callee;
+ this.Ins = ins;
+ this.Outs = outs;
+ this.IsAsync = IsAsync;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "");
+ if (IsFree) {
+ stream.Write("free ");
+ }
+ if (IsAsync) {
+ stream.Write("async ");
+ }
+ stream.Write("call ");
+ EmitAttributes(stream, Attributes);
+ string sep = "";
+ if (Outs.Count > 0) {
+ foreach (Expr arg in Outs) {
+ stream.Write(sep);
+ sep = ", ";
+ if (arg == null) {
+ stream.Write("*");
+ } else {
+ arg.Emit(stream);
+ }
+ }
+ stream.Write(" := ");
+ }
+ stream.Write(TokenTextWriter.SanitizeIdentifier(callee));
+ stream.Write("(");
+ sep = "";
+ foreach (Expr arg in Ins) {
+ stream.Write(sep);
+ sep = ", ";
+ if (arg == null) {
+ stream.Write("*");
+ } else {
+ arg.Emit(stream);
+ }
+ }
+ stream.WriteLine(");");
+ base.Emit(stream, level);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ if (Proc != null) {
+ // already resolved
+ return;
+ }
+ ResolveAttributes(Attributes, rc);
+ Proc = rc.LookUpProcedure(callee) as Procedure;
+ if (Proc == null) {
+ rc.Error(this, "call to undeclared procedure: {0}", callee);
+ }
+ foreach (Expr e in Ins) {
+ if (e != null) {
+ e.Resolve(rc);
+ }
+ }
+ HashSet<Variable> actualOuts = new HashSet<Variable>();
+ foreach (IdentifierExpr ide in Outs) {
+ if (ide != null) {
+ ide.Resolve(rc);
+ if (ide.Decl != null) {
+ if (actualOuts.Contains(ide.Decl)) {
+ rc.Error(this, "left-hand side of call command contains variable twice: {0}", ide.Name);
+ } else {
+ actualOuts.Add(ide.Decl);
+ }
+ }
+ }
+ }
+
+ if (Proc == null)
+ return;
+
+ // first make sure that the right number of parameters is given
+ // (a similar check is in CheckArgumentTypes, but we are not
+ // able to call this method because it cannot cope with Ins/Outs
+ // that are null)
+ if (Ins.Count != Proc.InParams.Count) {
+ rc.Error(this.tok,
+ "wrong number of arguments in call to {0}: {1}",
+ callee, Ins.Count);
+ return;
+ }
+ if (Outs.Count != Proc.OutParams.Count) {
+ rc.Error(this.tok,
+ "wrong number of result variables in call to {0}: {1}",
+ callee, Outs.Count);
+ return;
+ }
+ if (IsAsync) {
+ if (Proc.OutParams.Count > 0) {
+ rc.Error(this.tok, "a procedure called asynchronously can have no output parameters");
+ return;
+ }
+ }
+
+ // Check that type parameters can be determined using the given
+ // actual i/o arguments. This is done already during resolution
+ // because CheckBoundVariableOccurrences needs a resolution
+ // context
+ List<Type>/*!*/ formalInTypes = new List<Type>();
+ List<Type>/*!*/ formalOutTypes = new List<Type>();
+ for (int i = 0; i < Ins.Count; ++i)
+ if (Ins[i] != null)
+ formalInTypes.Add(cce.NonNull(Proc.InParams[i]).TypedIdent.Type);
+ for (int i = 0; i < Outs.Count; ++i)
+ if (Outs[i] != null)
+ formalOutTypes.Add(cce.NonNull(Proc.OutParams[i]).TypedIdent.Type);
+
+ // we need to bind the type parameters for this
+ // (this is expected by CheckBoundVariableOccurrences)
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable/*!*/ v in Proc.TypeParameters) {
+ Contract.Assert(v != null);
+ rc.AddTypeBinder(v);
+ }
+ Type.CheckBoundVariableOccurrences(Proc.TypeParameters,
+ formalInTypes, formalOutTypes,
+ this.tok, "types of given arguments",
+ rc);
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+
+ var id = QKeyValue.FindStringAttribute(Attributes, "id");
+ if (id != null)
+ {
+ rc.AddStatementId(tok, id);
+ }
+ }
+
+ public override void AddAssignedVariables(List<Variable> vars) {
+ if (this.IsAsync)
+ return;
+ foreach (IdentifierExpr e in Outs) {
+ if (e != null) {
+ vars.Add(e.Decl);
+ }
+ }
+ Contract.Assume(this.Proc != null);
+ foreach (IdentifierExpr/*!*/ e in this.Proc.Modifies) {
+ Contract.Assert(e != null);
+ vars.Add(e.Decl);
+ }
+ if (AssignedAssumptionVariable != null)
+ {
+ vars.Add(AssignedAssumptionVariable);
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc)
+ {
+ //Contract.Requires(tc != null);
+ Contract.Assume(this.Proc != null); // we assume the CallCmd has been successfully resolved before calling this Typecheck method
+
+ TypecheckAttributes(Attributes, tc);
+
+ // typecheck in-parameters
+ foreach (Expr e in Ins)
+ if (e != null)
+ e.Typecheck(tc);
+ foreach (Expr e in Outs)
+ if (e != null)
+ e.Typecheck(tc);
+ this.CheckAssignments(tc);
+
+ List<Type>/*!*/ formalInTypes = new List<Type>();
+ List<Type>/*!*/ formalOutTypes = new List<Type>();
+ List<Expr>/*!*/ actualIns = new List<Expr>();
+ List<IdentifierExpr>/*!*/ actualOuts = new List<IdentifierExpr>();
+ for (int i = 0; i < Ins.Count; ++i)
+ {
+ if (Ins[i] != null)
+ {
+ formalInTypes.Add(cce.NonNull(Proc.InParams[i]).TypedIdent.Type);
+ actualIns.Add(Ins[i]);
+ }
+ }
+ for (int i = 0; i < Outs.Count; ++i)
+ {
+ if (Outs[i] != null)
+ {
+ formalOutTypes.Add(cce.NonNull(Proc.OutParams[i]).TypedIdent.Type);
+ actualOuts.Add(Outs[i]);
+ }
+ }
+
+ // match actuals with formals
+ List<Type/*!*/>/*!*/ actualTypeParams;
+ Type.CheckArgumentTypes(Proc.TypeParameters,
+ out actualTypeParams,
+ formalInTypes, actualIns,
+ formalOutTypes, actualOuts,
+ this.tok,
+ "call to " + callee,
+ tc);
+ Contract.Assert(cce.NonNullElements(actualTypeParams));
+ TypeParameters = SimpleTypeParamInstantiation.From(Proc.TypeParameters,
+ actualTypeParams);
+
+ if (!CommandLineOptions.Clo.DoModSetAnalysis && IsAsync)
+ {
+ if (!tc.Yields)
+ {
+ tc.Error(this, "enclosing procedure of an async call must yield");
+ }
+ if (!QKeyValue.FindBoolAttribute(Proc.Attributes, "yields"))
+ {
+ tc.Error(this, "target procedure of an async call must yield");
+ }
+ }
+ }
+
+ private IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ TypeParamSubstitution() {
+ Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
+ Contract.Assume(TypeParameters != null);
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ res = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ foreach (TypeVariable/*!*/ v in TypeParameters.FormalTypeParams) {
+ Contract.Assert(v != null);
+ res.Add(v, TypeParameters[v]);
+ }
+ return res;
+ }
+
+ protected override Cmd ComputeDesugaring() {
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+
+ int uniqueId = 0;
+ List<Cmd> newBlockBody = new List<Cmd>();
+ Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>();
+ Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>();
+ Dictionary<Variable, Expr> substMapBound = new Dictionary<Variable, Expr>();
+ List<Variable>/*!*/ tempVars = new List<Variable>();
+
+ // proc P(ins) returns (outs)
+ // requires Pre
+ // //modifies frame
+ // ensures Post
+ //
+ // call aouts := P(ains)
+
+ // ins : formal in parameters of procedure
+ // frame : a list of global variables from the modifies clause
+ // outs : formal out parameters of procedure
+ // ains : actual in arguments passed to call
+ // aouts : actual variables assigned to from call
+ // cins : new variables created just for this call, one per ains
+ // cframe : new variables created just for this call, to keep track of OLD values
+ // couts : new variables created just for this call, one per aouts
+ // WildcardVars : new variables created just for this call, one per null in ains
+
+ #region Create cins; each one is an incarnation of the corresponding in parameter
+ List<Variable>/*!*/ cins = new List<Variable>();
+ List<Variable> wildcardVars = new List<Variable>();
+ Contract.Assume(this.Proc != null);
+ for (int i = 0; i < this.Proc.InParams.Count; ++i) {
+ Variable/*!*/ param = cce.NonNull(this.Proc.InParams[i]);
+ bool isWildcard = this.Ins[i] == null;
+
+ Type/*!*/ actualType;
+ if (isWildcard)
+ actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
+ else
+ // during type checking, we have ensured that the type of the actual
+ // parameter Ins[i] is correct, so we can use it here
+ actualType = cce.NonNull(cce.NonNull(Ins[i]).Type);
+
+ Variable cin = CreateTemporaryVariable(tempVars, param, actualType,
+ TempVarKind.Formal, ref uniqueId);
+ cins.Add(cin);
+ IdentifierExpr ie = new IdentifierExpr(cin.tok, cin);
+ substMap.Add(param, ie);
+ if (isWildcard) {
+ cin = CreateTemporaryVariable(tempVars, param,
+ actualType, TempVarKind.Bound, ref uniqueId);
+ wildcardVars.Add(cin);
+ ie = new IdentifierExpr(cin.tok, cin);
+ }
+ substMapBound.Add(param, ie);
+ }
+ #endregion
+ #region call aouts := P(ains) becomes: (open outlining one level to see)
+ #region cins := ains (or havoc cin when ain is null)
+ for (int i = 0, n = this.Ins.Count; i < n; i++) {
+ IdentifierExpr/*!*/ cin_exp = new IdentifierExpr(cce.NonNull(cins[i]).tok, cce.NonNull(cins[i]));
+ Contract.Assert(cin_exp != null);
+ if (this.Ins[i] != null) {
+ AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, cce.NonNull(this.Ins[i]));
+ newBlockBody.Add(assign);
+ } else {
+ List<IdentifierExpr>/*!*/ ies = new List<IdentifierExpr>();
+ ies.Add(cin_exp);
+ HavocCmd havoc = new HavocCmd(Token.NoToken, ies);
+ newBlockBody.Add(havoc);
+ }
+ }
+ #endregion
+
+ #region assert (exists wildcardVars :: Pre[ins := cins])
+ Substitution s = Substituter.SubstitutionFromHashtable(substMapBound);
+ bool hasWildcard = (wildcardVars.Count != 0);
+ Expr preConjunction = null;
+ for (int i = 0; i < this.Proc.Requires.Count; i++) {
+ Requires/*!*/ req = cce.NonNull(this.Proc.Requires[i]);
+ if (!req.Free && !IsFree) {
+ if (hasWildcard) {
+ Expr pre = Substituter.Apply(s, req.Condition);
+ if (preConjunction == null) {
+ preConjunction = pre;
+ } else {
+ preConjunction = Expr.And(preConjunction, pre);
+ }
+ } else {
+ Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
+ reqCopy.Condition = Substituter.Apply(s, req.Condition);
+ AssertCmd/*!*/ a = new AssertRequiresCmd(this, reqCopy);
+ Contract.Assert(a != null);
+ if (Attributes != null)
+ {
+ // Inherit attributes of call.
+ var attrCopy = (QKeyValue)cce.NonNull(Attributes.Clone());
+ attrCopy = Substituter.Apply(s, attrCopy);
+ a.Attributes = attrCopy;
+ }
+ a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
+ newBlockBody.Add(a);
+ }
+ }
+ else if (CommandLineOptions.Clo.StratifiedInlining > 0)
+ {
+ // inject free requires as assume statements at the call site
+ AssumeCmd/*!*/ a = new AssumeCmd(req.tok, Substituter.Apply(s, req.Condition));
+ Contract.Assert(a != null);
+ newBlockBody.Add(a);
+ }
+ }
+ if (hasWildcard) {
+ if (preConjunction == null) {
+ preConjunction = Expr.True;
+ }
+ Expr/*!*/ expr = new ExistsExpr(tok, wildcardVars, preConjunction);
+ Contract.Assert(expr != null);
+ AssertCmd/*!*/ a = new AssertCmd(tok, expr);
+ Contract.Assert(a != null);
+ if (Attributes != null)
+ {
+ // Inherit attributes of call.
+ var attrCopy = (QKeyValue)cce.NonNull(Attributes.Clone());
+ attrCopy = Substituter.Apply(s, attrCopy);
+ a.Attributes = attrCopy;
+ }
+ a.ErrorDataEnhanced = AssertCmd.GenerateBoundVarMiningStrategy(expr);
+ newBlockBody.Add(a);
+ }
+ #endregion
+
+ #region assume Pre[ins := cins] with formal paramters
+ if (hasWildcard) {
+ s = Substituter.SubstitutionFromHashtable(substMap);
+ for (int i = 0; i < this.Proc.Requires.Count; i++) {
+ Requires/*!*/ req = cce.NonNull(this.Proc.Requires[i]);
+ if (!req.Free) {
+ Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
+ reqCopy.Condition = Substituter.Apply(s, req.Condition);
+ AssumeCmd/*!*/ a = new AssumeCmd(tok, reqCopy.Condition);
+ Contract.Assert(a != null);
+ newBlockBody.Add(a);
+ }
+ }
+ }
+ #endregion
+
+ #region cframe := frame (to hold onto frame values in case they are referred to in the postcondition)
+ List<IdentifierExpr> havocVarExprs = new List<IdentifierExpr>();
+
+ foreach (IdentifierExpr/*!*/ f in this.Proc.Modifies) {
+ Contract.Assert(f != null);
+ Contract.Assume(f.Decl != null);
+ Contract.Assert(f.Type != null);
+ Variable v = CreateTemporaryVariable(tempVars, f.Decl, f.Type, TempVarKind.Old, ref uniqueId);
+ IdentifierExpr v_exp = new IdentifierExpr(v.tok, v);
+ substMapOld.Add(f.Decl, v_exp); // this assumes no duplicates in this.Proc.Modifies
+ AssignCmd assign = Cmd.SimpleAssign(f.tok, v_exp, f);
+ newBlockBody.Add(assign);
+
+ // fra
+ if (!havocVarExprs.Contains(f))
+ havocVarExprs.Add(f);
+ }
+ #endregion
+ #region Create couts
+ List<Variable>/*!*/ couts = new List<Variable>();
+ for (int i = 0; i < this.Proc.OutParams.Count; ++i) {
+ Variable/*!*/ param = cce.NonNull(this.Proc.OutParams[i]);
+ bool isWildcard = this.Outs[i] == null;
+
+ Type/*!*/ actualType;
+ if (isWildcard)
+ actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
+ else
+ // during type checking, we have ensured that the type of the actual
+ // out parameter Outs[i] is correct, so we can use it here
+ actualType = cce.NonNull(cce.NonNull(Outs[i]).Type);
+
+ Variable cout = CreateTemporaryVariable(tempVars, param, actualType,
+ TempVarKind.Formal, ref uniqueId);
+ couts.Add(cout);
+ IdentifierExpr ie = new IdentifierExpr(cout.tok, cout);
+ substMap.Add(param, ie);
+
+ if (!havocVarExprs.Contains(ie))
+ havocVarExprs.Add(ie);
+ }
+ // add the where clauses, now that we have the entire substitution map
+ foreach (Variable/*!*/ param in this.Proc.OutParams) {
+ Contract.Assert(param != null);
+ Expr w = param.TypedIdent.WhereExpr;
+ if (w != null) {
+ IdentifierExpr ie = (IdentifierExpr/*!*/)cce.NonNull(substMap[param]);
+ Contract.Assert(ie.Decl != null);
+ ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w);
+ }
+ }
+ #endregion
+
+ #region havoc frame, couts
+ // pass on this's token
+ HavocCmd hc = new HavocCmd(this.tok, havocVarExprs);
+ newBlockBody.Add(hc);
+ #endregion
+
+ #region assume Post[ins, outs, old(frame) := cins, couts, cframe]
+ calleeSubstitution = Substituter.SubstitutionFromHashtable(substMap, true, Proc);
+ calleeSubstitutionOld = Substituter.SubstitutionFromHashtable(substMapOld, true, Proc);
+ foreach (Ensures/*!*/ e in this.Proc.Ensures) {
+ Contract.Assert(e != null);
+ Expr copy = Substituter.ApplyReplacingOldExprs(calleeSubstitution, calleeSubstitutionOld, e.Condition);
+ AssumeCmd assume = new AssumeCmd(this.tok, copy);
+ #region stratified inlining support
+ if (QKeyValue.FindBoolAttribute(e.Attributes, "si_fcall"))
+ {
+ assume.Attributes = Attributes;
+ }
+ if (QKeyValue.FindBoolAttribute(e.Attributes, "candidate"))
+ {
+ assume.Attributes = new QKeyValue(Token.NoToken, "candidate", new List<object>(), assume.Attributes);
+ assume.Attributes.AddParam(this.callee);
+ }
+ #endregion
+ newBlockBody.Add(assume);
+ }
+ #endregion
+
+ #region aouts := couts
+ for (int i = 0, n = this.Outs.Count; i < n; i++) {
+ if (this.Outs[i] != null) {
+ Variable/*!*/ param_i = cce.NonNull(this.Proc.OutParams[i]);
+ Expr/*!*/ cout_exp = new IdentifierExpr(cce.NonNull(couts[i]).tok, cce.NonNull(couts[i]));
+ Contract.Assert(cout_exp != null);
+ AssignCmd assign = Cmd.SimpleAssign(param_i.tok, cce.NonNull(this.Outs[i]), cout_exp);
+ newBlockBody.Add(assign);
+ }
+ }
+ #endregion
+ #endregion
+
+ return new StateCmd(this.tok, tempVars, newBlockBody);
+ }
+
+ class NameEqualityComparer : EqualityComparer<IdentifierExpr>
+ {
+ public override bool Equals(IdentifierExpr x, IdentifierExpr y)
+ {
+ return x.Name.Equals(y.Name);
+ }
+
+ public override int GetHashCode(IdentifierExpr obj)
+ {
+ return obj.Name.GetHashCode();
+ }
+ }
+
+ NameEqualityComparer comparer = new NameEqualityComparer();
+
+ public Substitution calleeSubstitution;
+ public Substitution calleeSubstitutionOld;
+
+ public IEnumerable<IdentifierExpr> UnmodifiedBefore(Procedure oldProcedure)
+ {
+ Contract.Requires(oldProcedure != null);
+
+ return Proc.Modifies.Except(oldProcedure.Modifies, comparer).Select(e => new IdentifierExpr(Token.NoToken, e.Decl));
+ }
+
+ public IEnumerable<IdentifierExpr> ModifiedBefore(Procedure oldProcedure)
+ {
+ Contract.Requires(oldProcedure != null);
+
+ return oldProcedure.Modifies.Except(Proc.Modifies, comparer).Select(e => new IdentifierExpr(Token.NoToken, e.Decl));
+ }
+
+ public Expr Postcondition(Procedure procedure, List<Expr> modifies, Dictionary<Variable, Expr> oldSubst, Program program, Func<Expr, Expr> extract)
+ {
+ Contract.Requires(calleeSubstitution != null && calleeSubstitutionOld != null && modifies != null && oldSubst != null && program != null && extract != null);
+
+ Substitution substOldCombined = v => { Expr s; if (oldSubst.TryGetValue(v, out s)) { return s; } return calleeSubstitutionOld(v); };
+
+ var clauses = procedure.Ensures.Select(e => Substituter.FunctionCallReresolvingApplyReplacingOldExprs(calleeSubstitution, substOldCombined, e.Condition, program)).Concat(modifies);
+ // TODO(wuestholz): Try extracting a function for each clause:
+ // return Conjunction(clauses.Select(c => extract(c)));
+ var conj = Expr.And(clauses, true);
+ return conj != null ? extract(conj) : conj;
+ }
+
+ public Expr CheckedPrecondition(Procedure procedure, Program program, Func<Expr, Expr> extract)
+ {
+ Contract.Requires(calleeSubstitution != null && calleeSubstitutionOld != null && program != null && extract != null);
+
+ var clauses = procedure.Requires.Where(r => !r.Free).Select(r => Substituter.FunctionCallReresolvingApplyReplacingOldExprs(calleeSubstitution, calleeSubstitutionOld, r.Condition, program));
+ // TODO(wuestholz): Try extracting a function for each clause:
+ // return Conjunction(clauses.Select(c => extract(c)));
+ var conj = Expr.And(clauses, true);
+ return conj != null ? extract(conj) : conj;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitCallCmd(this);
+ }
+ }
+
+ public abstract class PredicateCmd : Cmd {
+ public QKeyValue Attributes;
+ public /*readonly--except in StandardVisitor*/ Expr/*!*/ Expr;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Expr != null);
+ }
+
+ public PredicateCmd(IToken/*!*/ tok, Expr/*!*/ expr)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ Expr = expr;
+ }
+ public PredicateCmd(IToken/*!*/ tok, Expr/*!*/ expr, QKeyValue kv)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ Expr = expr;
+ Attributes = kv;
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Expr.Resolve(rc);
+
+ var id = QKeyValue.FindStringAttribute(Attributes, "id");
+ if (id != null)
+ {
+ rc.AddStatementId(tok, id);
+ }
+ }
+ public override void AddAssignedVariables(List<Variable> vars) {
+ //Contract.Requires(vars != null);
+ }
+ }
+
+ public abstract class MiningStrategy {
+ // abstract class to bind all MiningStrategys, i.e., all types of enhanced error data
+ // types together
+ }
+
+ public class ListOfMiningStrategies : MiningStrategy {
+
+ private List<MiningStrategy>/*!*/ _msList;
+
+ public List<MiningStrategy>/*!*/ msList
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<List<MiningStrategy>>() != null);
+ return this._msList;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._msList = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._msList != null);
+ }
+
+ public ListOfMiningStrategies(List<MiningStrategy> l) {
+ Contract.Requires(l != null);
+ this._msList = l;
+ }
+ }
+
+ public class EEDTemplate : MiningStrategy {
+ private string/*!*/ _reason;
+ public string/*!*/ reason
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this._reason;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._reason = value;
+ }
+ }
+
+ private List<Expr/*!*/>/*!*/ exprList;
+ public IEnumerable<Expr> Expressions
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Expr>>()));
+ return this.exprList.AsReadOnly();
+ }
+ set
+ {
+ Contract.Requires(cce.NonNullElements(value));
+ this.exprList = new List<Expr>(value);
+ }
+ }
+
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._reason != null);
+ Contract.Invariant(cce.NonNullElements(this.exprList));
+ }
+
+ public EEDTemplate(string reason, List<Expr/*!*/>/*!*/ exprList) {
+ Contract.Requires(reason != null);
+ Contract.Requires(cce.NonNullElements(exprList));
+ this._reason = reason;
+ this.exprList = exprList;
+ }
+ }
+
+ public class AssertCmd : PredicateCmd, IPotentialErrorNode<object, object>
+ {
+ public Expr OrigExpr;
+ public Dictionary<Variable, Expr> IncarnationMap;
+
+ Expr verifiedUnder;
+ public Expr VerifiedUnder
+ {
+ get
+ {
+ if (verifiedUnder != null)
+ {
+ return verifiedUnder;
+ }
+ verifiedUnder = QKeyValue.FindExprAttribute(Attributes, "verified_under");
+ return verifiedUnder;
+ }
+ }
+
+ public void MarkAsVerifiedUnder(Expr expr)
+ {
+ Attributes = new QKeyValue(tok, "verified_under", new List<object> { expr }, Attributes);
+ verifiedUnder = expr;
+ }
+
+ // TODO: convert to use generics
+ private object errorData;
+ public object ErrorData {
+ get {
+ return errorData;
+ }
+ set {
+ errorData = value;
+ }
+ }
+
+ public string ErrorMessage {
+ get {
+ return QKeyValue.FindStringAttribute(Attributes, "msg");
+ }
+ }
+
+ private MiningStrategy errorDataEnhanced;
+ public MiningStrategy ErrorDataEnhanced {
+ get {
+ return errorDataEnhanced;
+ }
+ set {
+ errorDataEnhanced = value;
+ }
+ }
+
+ public AssertCmd(IToken/*!*/ tok, Expr/*!*/ expr)
+ : base(tok, expr) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
+ }
+
+ public AssertCmd(IToken/*!*/ tok, Expr/*!*/ expr, QKeyValue kv)
+ : base(tok, expr, kv) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "assert ");
+ EmitAttributes(stream, Attributes);
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ ResolveAttributes(Attributes, rc);
+ base.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(Attributes, tc);
+ Expr.Typecheck(tc);
+ Contract.Assert(Expr.Type != null); // follows from Expr.Typecheck postcondition
+ if (!Expr.Type.Unify(Type.Bool)) {
+ tc.Error(this, "an asserted expression must be of type bool (got: {0})", Expr.Type);
+ }
+ }
+
+ public static MiningStrategy GenerateBoundVarMiningStrategy(Expr expr) {
+ Contract.Requires(expr != null);
+ List<MiningStrategy> l = new List<MiningStrategy>();
+ if (expr != null) {
+ l = GenerateBoundVarListForMining(expr, l);
+ }
+ return new ListOfMiningStrategies(l);
+ }
+
+ public static List<MiningStrategy>/*!*/ GenerateBoundVarListForMining(Expr expr, List<MiningStrategy> l) {
+ Contract.Requires(l != null);
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<List<MiningStrategy>>() != null);
+
+ // go through the origExpr and identify all bound variables in the AST.
+ if (expr is LiteralExpr || expr is IdentifierExpr) {
+ //end recursion
+ } else if (expr is NAryExpr) {
+ NAryExpr e = (NAryExpr)expr;
+ foreach (Expr/*!*/ arg in e.Args) {
+ Contract.Assert(arg != null);
+ l = GenerateBoundVarListForMining(arg, l);
+ }
+ } else if (expr is OldExpr) {
+ OldExpr e = (OldExpr)expr;
+ l = GenerateBoundVarListForMining(e.Expr, l);
+ } else if (expr is QuantifierExpr) {
+ QuantifierExpr qe = (QuantifierExpr)expr;
+ List<Variable> vs = qe.Dummies;
+ foreach (Variable/*!*/ x in vs) {
+ Contract.Assert(x != null);
+ string name = x.Name;
+ if (name.StartsWith("^")) {
+ name = name.Substring(1);
+ List<Expr> exprList = new List<Expr>();
+ exprList.Add(new IdentifierExpr(Token.NoToken, x.ToString(), x.TypedIdent.Type));
+ MiningStrategy eed = new EEDTemplate("The bound variable " + name + " has the value {0}.", exprList);
+ l.Add(eed);
+ }
+ }
+ l = GenerateBoundVarListForMining(qe.Body, l);
+ }
+ return l;
+ }
+
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitAssertCmd(this);
+ }
+ }
+
+ // An AssertCmd that is a loop invariant check before the loop iteration starts
+ public class LoopInitAssertCmd : AssertCmd {
+ public LoopInitAssertCmd(IToken/*!*/ tok, Expr/*!*/ expr)
+ : base(tok, expr) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ }
+ }
+
+ // An AssertCmd that is a loop invariant check to maintain the invariant after iteration
+ public class LoopInvMaintainedAssertCmd : AssertCmd {
+ public LoopInvMaintainedAssertCmd(IToken/*!*/ tok, Expr/*!*/ expr)
+ : base(tok, expr) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ }
+ }
+
+ /// <summary>
+ /// An AssertCmd that is introduced in translation from the requires on a call.
+ /// </summary>
+ public class AssertRequiresCmd : AssertCmd {
+ public CallCmd/*!*/ Call;
+ public Requires/*!*/ Requires;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Call != null);
+ Contract.Invariant(Requires != null);
+ }
+
+
+ public AssertRequiresCmd(CallCmd/*!*/ call, Requires/*!*/ requires)
+ : base(call.tok, requires.Condition) {
+ Contract.Requires(call != null);
+ Contract.Requires(requires != null);
+ this.Call = call;
+ this.Requires = requires;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitAssertRequiresCmd(this);
+ }
+ }
+
+ /// <summary>
+ /// An AssertCmd that is introduced in translation from an ensures
+ /// declaration.
+ /// </summary>
+ public class AssertEnsuresCmd : AssertCmd {
+ public Ensures/*!*/ Ensures;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Ensures != null);
+ }
+
+ public AssertEnsuresCmd(Ensures/*!*/ ens)
+ : base(ens.tok, ens.Condition) {
+ Contract.Requires(ens != null);
+ this.Ensures = ens;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitAssertEnsuresCmd(this);
+ }
+ }
+
+ public class AssumeCmd : PredicateCmd {
+ public AssumeCmd(IToken/*!*/ tok, Expr/*!*/ expr)
+ : base(tok, expr) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ }
+ public AssumeCmd(IToken/*!*/ tok, Expr/*!*/ expr, QKeyValue kv)
+ : base(tok, expr, kv) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "assume ");
+ EmitAttributes(stream, Attributes);
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ ResolveAttributes(Attributes, rc);
+ base.Resolve(rc);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ TypecheckAttributes(Attributes, tc);
+ Expr.Typecheck(tc);
+ Contract.Assert(Expr.Type != null); // follows from Expr.Typecheck postcondition
+ if (!Expr.Type.Unify(Type.Bool)) {
+ tc.Error(this, "an assumed expression must be of type bool (got: {0})", Expr.Type);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitAssumeCmd(this);
+ }
+ }
+
+ public class ReturnExprCmd : ReturnCmd {
+ public Expr/*!*/ Expr;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Expr != null);
+ }
+
+ public ReturnExprCmd(IToken/*!*/ tok, Expr/*!*/ expr)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ Expr = expr;
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "return ");
+ this.Expr.Emit(stream);
+ stream.WriteLine(";");
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ Expr.Typecheck(tc);
+ Contract.Assert(Expr.Type != null); // follows from Expr.Typecheck postcondition
+ if (!Expr.Type.Unify(Type.Bool)) {
+ tc.Error(this, "a return expression must be of type bool (got: {0})", Expr.Type);
+ }
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Expr.Resolve(rc);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitReturnExprCmd(this);
+ }
+ }
+
+ public class HavocCmd : Cmd {
+ private List<IdentifierExpr>/*!*/ _vars;
+
+ public List<IdentifierExpr>/*!*/ Vars {
+ get {
+ Contract.Ensures(Contract.Result<List<IdentifierExpr>>() != null);
+ return this._vars;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._vars = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._vars != null);
+ }
+
+ public HavocCmd(IToken/*!*/ tok, List<IdentifierExpr>/*!*/ vars)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(vars != null);
+ this._vars = vars;
+ }
+
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, level, "havoc ");
+ Vars.Emit(stream, true);
+ stream.WriteLine(";");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ foreach (IdentifierExpr/*!*/ ide in Vars) {
+ Contract.Assert(ide != null);
+ ide.Resolve(rc);
+ }
+ }
+ public override void AddAssignedVariables(List<Variable> vars) {
+ //Contract.Requires(vars != null);
+ foreach (IdentifierExpr/*!*/ e in this.Vars) {
+ Contract.Assert(e != null);
+ vars.Add(e.Decl);
+ }
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ foreach (IdentifierExpr ie in Vars)
+ {
+ ie.Typecheck(tc);
+ }
+ this.CheckAssignments(tc);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitHavocCmd(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Transfer commands
+ [ContractClass(typeof(TransferCmdContracts))]
+ public abstract class TransferCmd : Absy {
+ internal TransferCmd(IToken/*!*/ tok)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ }
+ public abstract void Emit(TokenTextWriter/*!*/ stream, int level);
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ // nothing to typecheck
+ }
+
+ public override string ToString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false , /*pretty=*/ false)) {
+ this.Emit(stream, 0);
+ }
+ return buffer.ToString();
+ }
+ }
+ [ContractClassFor(typeof(TransferCmd))]
+ public abstract class TransferCmdContracts : TransferCmd {
+ public TransferCmdContracts() :base(null){
+
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ Contract.Requires(stream != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public class ReturnCmd : TransferCmd {
+ public ReturnCmd(IToken/*!*/ tok)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ stream.WriteLine(this, level, "return;");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ // nothing to resolve
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitReturnCmd(this);
+ }
+ }
+
+ public class GotoCmd : TransferCmd {
+ [Rep]
+ public List<String> labelNames;
+ [Rep]
+ public List<Block> labelTargets;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(labelNames == null || labelTargets == null || labelNames.Count == labelTargets.Count);
+ }
+
+ [NotDelayed]
+ public GotoCmd(IToken/*!*/ tok, List<String>/*!*/ labelSeq)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(labelSeq != null);
+ this.labelNames = labelSeq;
+ }
+ public GotoCmd(IToken/*!*/ tok, List<String>/*!*/ labelSeq, List<Block>/*!*/ blockSeq)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(labelSeq != null);
+ Contract.Requires(blockSeq != null);
+ Debug.Assert(labelSeq.Count == blockSeq.Count);
+ for (int i = 0; i < labelSeq.Count; i++) {
+ Debug.Assert(Equals(labelSeq[i], cce.NonNull(blockSeq[i]).Label));
+ }
+
+ this.labelNames = labelSeq;
+ this.labelTargets = blockSeq;
+ }
+ public GotoCmd(IToken/*!*/ tok, List<Block>/*!*/ blockSeq)
+ : base(tok) { //requires (blockSeq[i] != null ==> blockSeq[i].Label != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(blockSeq != null);
+ List<String> labelSeq = new List<String>();
+ for (int i = 0; i < blockSeq.Count; i++)
+ labelSeq.Add(cce.NonNull(blockSeq[i]).Label);
+ this.labelNames = labelSeq;
+ this.labelTargets = blockSeq;
+ }
+ public void AddTarget(Block b) {
+ Contract.Requires(b != null);
+ Contract.Requires(b.Label != null);
+ Contract.Requires(this.labelTargets != null);
+ Contract.Requires(this.labelNames != null);
+ this.labelTargets.Add(b);
+ this.labelNames.Add(b.Label);
+ }
+ public override void Emit(TokenTextWriter stream, int level) {
+ //Contract.Requires(stream != null);
+ Contract.Assume(this.labelNames != null);
+ stream.Write(this, level, "goto ");
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ if (labelTargets == null) {
+ string sep = "";
+ foreach (string name in labelNames) {
+ stream.Write("{0}{1}^^{2}", sep, "NoDecl", name);
+ sep = ", ";
+ }
+ } else {
+ string sep = "";
+ foreach (Block/*!*/ b in labelTargets) {
+ Contract.Assert(b != null);
+ stream.Write("{0}h{1}^^{2}", sep, b.GetHashCode(), b.Label);
+ sep = ", ";
+ }
+ }
+ } else {
+ labelNames.Emit(stream);
+ }
+ stream.WriteLine(";");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(labelTargets != null);
+ if (labelTargets != null) {
+ // already resolved
+ return;
+ }
+ Contract.Assume(this.labelNames != null);
+ labelTargets = new List<Block>();
+ foreach (string/*!*/ lbl in labelNames) {
+ Contract.Assert(lbl != null);
+ Block b = rc.LookUpBlock(lbl);
+ if (b == null) {
+ rc.Error(this, "goto to unknown block: {0}", lbl);
+ } else {
+ labelTargets.Add(b);
+ }
+ }
+ Debug.Assert(rc.ErrorCount > 0 || labelTargets.Count == labelNames.Count);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitGotoCmd(this);
+ }
+ }
+}
diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs
index 6b2e1201..b980a22b 100644
--- a/Source/Core/AbsyExpr.cs
+++ b/Source/Core/AbsyExpr.cs
@@ -1,3320 +1,3351 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie {
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using System.Diagnostics.Contracts;
- using System.Linq;
- using Microsoft.Basetypes;
-
- using Set = GSet<object>; // not that the set used is not a set of Variable only, as it also contains TypeVariables
-
-
- //---------------------------------------------------------------------
- // Expressions
- //
- // For expressions, we override the Equals and GetHashCode method to
- // implement structural equality. Note this is not logical equivalence
- // and is not modulo alpha-renaming.
- //---------------------------------------------------------------------
-
-
- [ContractClass(typeof(ExprContracts))]
- public abstract class Expr : Absy {
- public Expr(IToken/*!*/ tok, bool immutable)
- : base(tok) {
- Contract.Requires(tok != null);
- this.Immutable = immutable;
- }
-
- public void Emit(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- Emit(stream, 0, false);
- }
-
- /// <summary>
- /// If true the client is making a promise that this Expr will be
- /// treated immutably (i.e. once constructed it is never changed).
- /// This is currently not enforced but it should be!
- ///
- /// This allows the Expr's hash code to be cached making calls to
- /// GetHashCode() very cheap.
- /// </summary>
- /// <value><c>true</c> if immutable; otherwise, <c>false</c>.</value>
- public bool Immutable {
- get;
- private set;
- }
-
- /// <summary>
- /// Computes the hash code of this Expr skipping any cache.
- ///
- /// Sub classes should place their implementation of computing their hashcode
- /// here (making sure to call GetHashCode() not ComputeHashCode() on Expr for performance reasons)
- /// and have GetHashCode() use a cached result from ComputeHashCode() if the
- /// Expr was constructed to be immutable.
- /// </summary>
- /// <returns>The hash code.</returns>
- public abstract int ComputeHashCode();
- protected int CachedHashCode = 0;
-
- public abstract void Emit(TokenTextWriter/*!*/ wr, int contextBindingStrength, bool fragileContext);
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
- this.Emit(stream, 0, false);
- }
- return buffer.ToString();
- }
-
- /// <summary>
- /// Add to "freeVars" the free variables in the expression.
- /// </summary>
- public abstract void ComputeFreeVariables(Set /*Variable*//*!*/ freeVars);
-
- /// <summary>
- /// Filled in by the Typecheck method. A value of "null" means a succeeding
- /// call to Typecheck has not taken place (that is, either Typecheck hasn't
- /// been called or Typecheck encountered an error in the expression to be
- /// typechecked).
- /// </summary>
- private Type _Type = null;
- public Type Type {
- get {
- return _Type;
- }
- set {
- if (_Type == null) {
- // Expr has never been type checked so always allow this
- _Type = value;
- } else {
- if (Immutable && !_Type.Equals(value))
- throw new InvalidOperationException("Cannot change the Type of an Immutable Expr");
-
- // Once the Type has been set (i.e. no longer null) we never change the reference
- // if this Expr is immutable, even if the Type is equivalent (i.e. _Type.Equals(newType))
- if (!Immutable)
- _Type = value;
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- Contract.Ensures(Type != null);
- // This body is added only because C# insists on it. It should really be left out, as if TypeCheck still were abstract.
- // The reason for mentioning the method here at all is to give TypeCheck a postcondition for all expressions.
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- /// <summary>
- /// Returns the type of the expression, supposing that all its subexpressions are well typed.
- /// </summary>
- public abstract Type/*!*/ ShallowType {
- get;
- }
-
- // Handy syntactic sugar follows:
-
- public static NAryExpr Unary(IToken x, UnaryOperator.Opcode op, Expr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(x != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return new NAryExpr(x, new UnaryOperator(x, op), new List<Expr> { e1 });
- }
-
- public static NAryExpr Binary(IToken x, BinaryOperator.Opcode op, Expr e0, Expr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Requires(x != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return new NAryExpr(x, new BinaryOperator(x, op), new List<Expr> { e0, e1 });
- }
-
- public static NAryExpr Binary(BinaryOperator.Opcode op, Expr e0, Expr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(Token.NoToken, op, e0, e1);
- }
-
- public static NAryExpr Eq(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Eq, e1, e2);
- }
- public static NAryExpr Neq(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Neq, e1, e2);
- }
- public static NAryExpr Le(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Le, e1, e2);
- }
- public static NAryExpr Ge(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Ge, e1, e2);
- }
- public static NAryExpr Lt(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Lt, e1, e2);
- }
- public static NAryExpr Gt(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Gt, e1, e2);
- }
- public static Expr And(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- if (e1 == true_) {
- return e2;
- } else if (e2 == true_) {
- return e1;
- } else if (e1 == false_ || e2 == false_) {
- return false_;
- } else {
- var res = Binary(BinaryOperator.Opcode.And, e1, e2);
- res.Type = Microsoft.Boogie.Type.Bool;
- res.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- return res;
- }
- }
- public static Expr Or(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- if (e1 == false_) {
- return e2;
- } else if (e2 == false_) {
- return e1;
- } else if (e1 == true_ || e2 == true_) {
- return true_;
- } else {
- return Binary(BinaryOperator.Opcode.Or, e1, e2);
- }
- }
- public static Expr Not(Expr e1) {
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- NAryExpr nary = e1 as NAryExpr;
-
- if (e1 == true_) {
- return false_;
- } else if (e1 == false_) {
- return true_;
- } else if (nary != null) {
- if (nary.Fun is UnaryOperator) {
- UnaryOperator op = (UnaryOperator)nary.Fun;
- if (op.Op == UnaryOperator.Opcode.Not) {
- return cce.NonNull(nary.Args[0]);
- }
- } else if (nary.Fun is BinaryOperator) {
- BinaryOperator op = (BinaryOperator)nary.Fun;
- Expr arg0 = cce.NonNull(nary.Args[0]);
- Expr arg1 = cce.NonNull(nary.Args[1]);
- if (op.Op == BinaryOperator.Opcode.Eq) {
- return Neq(arg0, arg1);
- } else if (op.Op == BinaryOperator.Opcode.Neq) {
- return Eq(arg0, arg1);
- } else if (op.Op == BinaryOperator.Opcode.Lt) {
- return Le(arg1, arg0);
- } else if (op.Op == BinaryOperator.Opcode.Le) {
- return Lt(arg1, arg0);
- } else if (op.Op == BinaryOperator.Opcode.Ge) {
- return Gt(arg1, arg0);
- } else if (op.Op == BinaryOperator.Opcode.Gt) {
- return Ge(arg1, arg0);
- }
- }
- }
-
- return Unary(Token.NoToken, UnaryOperator.Opcode.Not, e1);
- }
-
- public static Expr Neg(Expr e1) {
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return Unary(Token.NoToken, UnaryOperator.Opcode.Neg, e1);
- }
-
- public static NAryExpr Imp(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Imp, e1, e2);
- }
- public static NAryExpr Iff(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Iff, e1, e2);
- }
- public static NAryExpr Add(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Add, e1, e2);
- }
- public static NAryExpr Sub(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Sub, e1, e2);
- }
- public static NAryExpr Mul(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Mul, e1, e2);
- }
- public static NAryExpr Div(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Div, e1, e2);
- }
- public static NAryExpr Mod(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Mod, e1, e2);
- }
- public static NAryExpr RealDiv(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.RealDiv, e1, e2);
- }
- public static NAryExpr FloatDiv(Expr e1, Expr e2)
- {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.FloatDiv, e1, e2);
- }
- public static NAryExpr Pow(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Pow, e1, e2);
- }
- public static NAryExpr Subtype(Expr e1, Expr e2) {
- Contract.Requires(e2 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Binary(BinaryOperator.Opcode.Subtype, e1, e2);
- }
-
- public static IdentifierExpr Ident(string name, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
- return new IdentifierExpr(Token.NoToken, name, type);
- }
-
- public static IdentifierExpr Ident(Variable decl) {
- Contract.Requires(decl != null);
- Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
- IdentifierExpr result = new IdentifierExpr(Token.NoToken, decl);
- return result;
- }
-
- public static LiteralExpr Literal(bool value) {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return new LiteralExpr(Token.NoToken, value);
- }
- public static LiteralExpr Literal(int value) {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(value));
- }
- public static LiteralExpr Literal(BigNum value) {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return new LiteralExpr(Token.NoToken, value);
- }
- public static LiteralExpr Literal(BigDec value) {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return new LiteralExpr(Token.NoToken, value);
- }
- public static LiteralExpr Literal(BigFloat value)
- {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return new LiteralExpr(Token.NoToken, value);
- }
-
- private static LiteralExpr/*!*/ true_ = Literal(true);
- public static LiteralExpr/*!*/ True {
- get {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return true_;
- }
- }
-
- private static LiteralExpr/*!*/ false_ = Literal(false);
- public static LiteralExpr/*!*/ False {
- get {
- Contract.Ensures(Contract.Result<LiteralExpr>() != null);
- return false_;
- }
- }
-
-
- public static NAryExpr Select(Expr map, params Expr[] args) {
- Contract.Requires(args != null);
- Contract.Requires(map != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return SelectTok(Token.NoToken, map, args);
- }
-
- public static NAryExpr Select(Expr map, List<Expr/*!*/>/*!*/ args) {
- Contract.Requires(map != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return Select(map, args.ToArray());
- }
-
- // use a different name for this variant of the method
- // (-> some bug prevents overloading in this case)
- public static NAryExpr SelectTok(IToken x, Expr map, params Expr[] args) {
- Contract.Requires(args != null);
- Contract.Requires(map != null);
- Contract.Requires(x != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- List<Expr>/*!*/ allArgs = new List<Expr>();
- allArgs.Add(map);
- foreach (Expr/*!*/ a in args) {
- Contract.Assert(a != null);
- allArgs.Add(a);
- }
- return new NAryExpr(x, new MapSelect(Token.NoToken, args.Length), allArgs);
- }
-
- public static NAryExpr Store(Expr map, params Expr[] args) {
- Contract.Requires(args != null);
- Contract.Requires(map != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- return StoreTok(Token.NoToken, map, args);
- }
-
- public static NAryExpr Store(Expr map, List<Expr/*!*/>/*!*/ indexes, Expr rhs) {
- Contract.Requires(rhs != null);
- Contract.Requires(map != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- Expr[]/*!*/ allArgs = new Expr[indexes.Count + 1];
- for (int i = 0; i < indexes.Count; ++i)
- allArgs[i] = indexes[i];
- allArgs[indexes.Count] = rhs;
- return Store(map, allArgs);
- }
-
- // use a different name for this variant of the method
- // (-> some bug prevents overloading in this case)
- public static NAryExpr/*!*/ StoreTok(IToken x, Expr map, params Expr[] args) {
- Contract.Requires(args != null);
- Contract.Requires(map != null);
- Contract.Requires(x != null);
- Contract.Requires(args.Length > 0); // zero or more indices, plus the value
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
-
- List<Expr>/*!*/ allArgs = new List<Expr>();
- allArgs.Add(map);
- foreach (Expr/*!*/ a in args) {
- Contract.Assert(a != null);
- allArgs.Add(a);
- }
- return new NAryExpr(x, new MapStore(Token.NoToken, args.Length - 1), allArgs);
- }
-
- public static NAryExpr CoerceType(IToken x, Expr subexpr, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(subexpr != null);
- Contract.Requires(x != null);
- Contract.Ensures(Contract.Result<NAryExpr>() != null);
- List<Expr>/*!*/ args = new List<Expr>();
- args.Add(subexpr);
- return new NAryExpr(x, new TypeCoercion(x, type), args);
- }
-
- public static Expr BinaryTreeAnd(List<Expr> terms)
- {
- return BinaryTreeAnd(terms, 0, terms.Count - 1);
- }
-
- private static Expr BinaryTreeAnd(List<Expr> terms, int start, int end)
- {
- if (start > end)
- return Expr.True;
- if (start == end)
- return terms[start];
- if (start + 1 == end)
- return Expr.And(terms[start], terms[start + 1]);
- var mid = (start + end) / 2;
- return Expr.And(BinaryTreeAnd(terms, start, mid), BinaryTreeAnd(terms, mid + 1, end));
- }
- }
- [ContractClassFor(typeof(Expr))]
- public abstract class ExprContracts : Expr {
- public ExprContracts() :base(null, /*immutable=*/ false){
-
- }
- public override void Emit(TokenTextWriter wr, int contextBindingStrength, bool fragileContext) {
- Contract.Requires(wr != null);
- throw new NotImplementedException();
- }
- public override void ComputeFreeVariables(Set freeVars) {
- Contract.Requires(freeVars != null);
- throw new NotImplementedException();
- }
- public override Type ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- }
- }
-
- public class LiteralExpr : Expr {
- public readonly object/*!*/ Val; // false, true, a BigNum, a BigDec, a BigFloat, or a BvConst
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Val != null);
- }
-
- /// <summary>
- /// Creates a literal expression for the boolean value "b".
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="b"></param>
- public LiteralExpr(IToken/*!*/ tok, bool b, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Val = b;
- Type = Type.Bool;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- /// <summary>
- /// Creates a literal expression for the integer value "v".
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="v"></param>
- public LiteralExpr(IToken/*!*/ tok, BigNum v, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Val = v;
- Type = Type.Int;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- /// <summary>
- /// Creates a literal expression for the real value "v".
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="v"></param>
- public LiteralExpr(IToken/*!*/ tok, BigDec v, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Val = v;
- Type = Type.Real;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- /// <summary>
- /// Creates a literal expression for the floating point value "v".
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="v"></param>
- public LiteralExpr(IToken/*!*/ tok, BigFloat v, bool immutable = false)
- : base(tok, immutable)
- {
- Contract.Requires(tok != null);
- Val = v;
- Type = Type.GetFloatType(v.ExponentSize, v.SignificandSize);
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- /// <summary>
- /// Creates a literal expression for the bitvector value "v".
- /// </summary>
- public LiteralExpr(IToken/*!*/ tok, BigNum v, int b, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(0 <= b);
- Val = new BvConst(v, b);
- Type = Type.GetBvType(b);
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is LiteralExpr))
- return false;
-
- LiteralExpr other = (LiteralExpr)obj;
- return object.Equals(this.Val, other.Val);
- }
-
- [Pure]
- public override int GetHashCode() {
- if (Immutable)
- return this.CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- return this.Val.GetHashCode();
- }
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- if (this.Val is bool) {
- stream.Write((bool)this.Val ? "true" : "false"); // correct capitalization
- } else {
- stream.Write(cce.NonNull(this.Val.ToString()));
- }
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- // nothing to resolve
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- // no free variables to add
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- this.Type = ShallowType;
- }
-
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- if (Val is bool) {
- return Type.Bool;
- } else if (Val is BigNum) {
- return Type.Int;
- } else if (Val is BigDec) {
- return Type.Real;
- } else if (Val is BigFloat) {
- BigFloat temp = (BigFloat)Val;
- return Type.GetFloatType(temp.ExponentSize, temp.SignificandSize);
- } else if (Val is BvConst) {
- return Type.GetBvType(((BvConst)Val).Bits);
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // like, where did this value come from?!
- }
- }
- }
-
- public bool IsFalse {
- get {
- return Val is bool && ((bool)Val) == false;
- }
- }
- public bool IsTrue {
- get {
- return Val is bool && ((bool)Val) == true;
- }
- }
-
- // should be eliminated after converting everything to BigNums
- private int asInt {
- get {
- return asBigNum.ToIntSafe;
- }
- }
-
- public bool isBigNum {
- get {
- return Val is BigNum;
- }
- }
-
- public BigNum asBigNum {
- get {
- Contract.Assert(isBigNum);
- return (BigNum)cce.NonNull(Val);
- }
- }
-
- public bool isBigDec {
- get {
- return Val is BigDec;
- }
- }
-
- public bool isBigFloat
- {
- get
- {
- return Val is BigFloat;
- }
- }
-
- public BigDec asBigDec {
- get {
- Contract.Assert(isBigDec);
- return (BigDec)cce.NonNull(Val);
- }
- }
-
- public BigFloat asBigFloat {
- get {
- Contract.Assert(isBigFloat);
- return (BigFloat)cce.NonNull(Val);
- }
- }
-
- public bool isBool {
- get {
- return Val is bool;
- }
- }
-
- public bool asBool {
- get {
- Contract.Assert(isBool);
- return (bool)cce.NonNull(Val);
- }
- }
-
- public bool isBvConst {
- get {
- return Val is BvConst;
- }
- }
-
- public BvConst asBvConst {
- get {
- Contract.Assert(isBvConst);
- return (BvConst)cce.NonNull(Val);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitLiteralExpr(this);
- }
- }
-
- public class BvConst {
- public readonly BigNum Value;
- public readonly int Bits;
-
- public BvConst(BigNum v, int b) {
- Contract.Assert(v.Signum >= 0);
- Value = v;
- Bits = b;
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return Value + "bv" + Bits;
- }
-
- [Pure]
- public string ToReadableString() {
- Contract.Ensures(Contract.Result<string>() != null);
- if (Value > BigNum.FromInt(10000)) {
- string val = cce.NonNull(Value.ToString("x"));
- int pos = val.Length % 4;
- string res = "0x" + val.Substring(0, pos);
- Contract.Assert(res != null);
- while (pos < val.Length) {
- res += "." + val.Substring(pos, 4);
- pos += 4;
- }
- return res + ".bv" + Bits;
- } else
- return ToString();
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- BvConst other = obj as BvConst;
- if (other == null)
- return false;
-
- return Bits == other.Bits && Value == other.Value;
- }
-
- [Pure]
- public override int GetHashCode() {
- unchecked {
- return Value.GetHashCode() ^ Bits;
- }
- }
- }
-
- public class IdentifierExpr : Expr {
- private string _Name;
- public string Name { // identifier symbol
- get {
- return _Name;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Cannot change Name on Immutable Expr");
-
- _Name = value;
- }
- }
- private Variable _Decl;
- public Variable Decl { // identifier declaration
- get {
- return _Decl;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Cannot change Decl on Immutable Expr");
-
- _Decl = value;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- }
-
-
- /// <summary>
- /// Creates an unresolved identifier expression. This constructor is intended to be called
- /// only from within the parser; for use inside the translation, use another constructor, which
- /// specifies the type of the expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="name"></param>
- internal IdentifierExpr(IToken/*!*/ tok, string/*!*/ name, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- _Name = name;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
- /// <summary>
- /// Creates an unresolved identifier expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="name"></param>
- /// <param name="type"></param>
- public IdentifierExpr(IToken/*!*/ tok, string/*!*/ name, Type/*!*/ type, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(name != null);
- Contract.Requires(type != null);
- _Name = name;
- Type = type;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- /// <summary>
- /// Creates a resolved identifier expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="d"></param>
- public IdentifierExpr(IToken/*!*/ tok, Variable/*!*/ d, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(d != null);
- _Name = cce.NonNull(d.Name);
- _Decl = d;
- Type = d.TypedIdent.Type;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is IdentifierExpr))
- return false;
-
- IdentifierExpr other = (IdentifierExpr)obj;
- return object.Equals(this.Name, other.Name) && object.Equals(this.Decl, other.Decl);
- }
-
- [Pure]
- public override int GetHashCode() {
- if (Immutable)
- return this.CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- int h = this.Name == null ? 0 : this.Name.GetHashCode();
- h ^= this.Decl == null ? 0 : this.Decl.GetHashCode();
- return h;
- }
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds && !stream.UseForComputingChecksums) {
- stream.Write("{0}^^", this.Decl == null ? "NoDecl" : "h" + this.Decl.GetHashCode());
- }
- stream.Write(this, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- if (Decl != null) {
- // already resolved, but re-resolve type just in case it came from an unresolved type
- if (Type != null) {
- Type = Type.ResolveType(rc);
- }
- return;
- }
- Decl = rc.LookUpVariable(Name);
- if (Decl == null) {
- rc.Error(this, "undeclared identifier: {0}", Name);
- } else if (rc.StateMode == ResolutionContext.State.StateLess && Decl is GlobalVariable) {
- rc.Error(this, "cannot refer to a global variable in this context: {0}", Name);
- }
- if (Type != null) {
- Type = Type.ResolveType(rc);
- }
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- Contract.Assume(this.Decl != null);
- freeVars.Add(Decl);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- if (this.Decl != null) {
- // sanity check
- if (Type != null && !Type.Equals(Decl.TypedIdent.Type)) {
- tc.Error(this, "internal error, shallow-type assignment was done incorrectly, {0}:{1} != {2}",
- Name, Type, Decl.TypedIdent.Type);
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- Type = Decl.TypedIdent.Type;
- }
- }
-
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- Contract.Assert(Type != null);
- return Type;
- }
- }
-
- public sealed class ConstantFunApp {
- private IdentifierExpr/*!*/ identifierExpr;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(identifierExpr != null);
- Contract.Invariant(emptyArgs != null);
- }
-
- public IdentifierExpr/*!*/ IdentifierExpr {
- get {
- Contract.Requires(IdentifierExpr != null);
- return identifierExpr;
- }
- }
-
- private static IList/*!*/ emptyArgs = ArrayList.ReadOnly(cce.NonNull((IList/*!*/)new ArrayList()));
- public IList/*!*/ Arguments {
- get {
- Contract.Ensures(Contract.Result<IList>() != null);
- return emptyArgs;
- }
- }
-
- public ConstantFunApp(IdentifierExpr ie, Constant c) {
- Contract.Requires(c != null);
- Contract.Requires(ie != null);
- this.identifierExpr = ie;
- }
-
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitIdentifierExpr(this);
- }
- }
-
- public class OldExpr : Expr
- {
- private Expr _Expr;
- public Expr/*!*/ Expr {
- get {
- return _Expr;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Cannot change Expr of an Immutable OldExpr");
-
- _Expr = value;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Expr != null);
- }
-
- public OldExpr(IToken/*!*/ tok, Expr/*!*/ expr, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(expr != null);
- _Expr = expr;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is OldExpr))
- return false;
-
- OldExpr other = (OldExpr)obj;
- return object.Equals(this.Expr, other.Expr);
- }
- [Pure]
- public override int GetHashCode() {
- if (Immutable)
- return this.CachedHashCode;
- else
- return ComputeHashCode ();
- }
- public override int ComputeHashCode() {
- // FIXME: This is wrong, it's as if the OldExpr node isn't there at all
- return this.Expr == null ? 0 : this.Expr.GetHashCode();
- }
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- stream.Write(this, "old(");
- this.Expr.Emit(stream);
- stream.Write(")");
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- if (rc.StateMode != ResolutionContext.State.Two) {
- rc.Error(this, "old expressions allowed only in two-state contexts");
- }
- Expr.Resolve(rc);
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- Expr.ComputeFreeVariables(freeVars);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- Expr.Typecheck(tc);
- Type = Expr.Type;
- }
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Expr.ShallowType;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitOldExpr(this);
- }
- }
- [ContractClass(typeof(IAppliableVisitorContracts<>))]
- public interface IAppliableVisitor<T> {
- T Visit(UnaryOperator/*!*/ unaryOperator);
- T Visit(BinaryOperator/*!*/ binaryOperator);
- T Visit(FunctionCall/*!*/ functionCall);
- T Visit(MapSelect/*!*/ mapSelect);
- T Visit(MapStore/*!*/ mapStore);
- T Visit(TypeCoercion/*!*/ typeCoercion);
- T Visit(ArithmeticCoercion/*!*/ arithCoercion);
- T Visit(IfThenElse/*!*/ ifThenElse);
- }
- [ContractClassFor(typeof(IAppliableVisitor<>))]
- public abstract class IAppliableVisitorContracts<T> : IAppliableVisitor<T> {
-
- #region IAppliableVisitor<T> Members
-
- public T Visit(UnaryOperator unaryOperator) {
- Contract.Requires(unaryOperator != null);
- throw new NotImplementedException();
- }
-
- public T Visit(BinaryOperator binaryOperator) {
- Contract.Requires(binaryOperator != null);
- throw new NotImplementedException();
- }
-
- public T Visit(FunctionCall functionCall) {
- Contract.Requires(functionCall != null);
- throw new NotImplementedException();
- }
-
- public T Visit(MapSelect mapSelect) {
- Contract.Requires(mapSelect != null);
- throw new NotImplementedException();
- }
-
- public T Visit(MapStore mapStore) {
- Contract.Requires(mapStore != null);
- throw new NotImplementedException();
- }
-
- public T Visit(TypeCoercion typeCoercion) {
- Contract.Requires(typeCoercion != null);
- throw new NotImplementedException();
- }
-
- public T Visit(ArithmeticCoercion arithCoercion) {
- Contract.Requires(arithCoercion != null);
- throw new NotImplementedException();
- }
-
- public T Visit(IfThenElse ifThenElse) {
- Contract.Requires(ifThenElse != null);
- throw new NotImplementedException();
- }
-
- #endregion
- }
-
- [ContractClass(typeof(IAppliableContracts))]
- public interface IAppliable {
- string/*!*/ FunctionName {
- get;
- }
-
- /// <summary>
- /// Emits to "stream" the operator applied to the given arguments.
- /// The length of "args" can be anything that the parser allows for this appliable operator
- /// (but can be nothing else).
- /// </summary>
- /// <param name="args"></param>
- /// <param name="stream"></param>
- /// <param name="contextBindingStrength"></param>
- /// <param name="fragileContext"></param>
- void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream, int contextBindingStrength, bool fragileContext);
-
- void Resolve(ResolutionContext/*!*/ rc, Expr/*!*/ subjectForErrorReporting);
-
- /// <summary>
- /// Requires the object to have been properly resolved.
- /// </summary>
- int ArgumentCount {
- get;
- }
-
- /// <summary>
- /// Typechecks the arguments "args" for the Appliable. If the arguments are
- /// appropriate, returns the result type; otherwise returns null.
- /// As result of the type checking, the values of type parameters of the
- /// appliable can be returned (which are then stored in the NAryExpr and later
- /// also used in the VCExprAST).
- /// Requires the object to have been successfully resolved.
- /// Requires args.Length == ArgumentCount.
- /// Requires all elements of "args" to have a non-null Type field.
- /// </summary>
- /// <param name="args"></param>
- /// <param name="tc"></param>
- Type Typecheck(IList<Expr>/*!*/ args, out TypeParamInstantiation/*!*/ tpInstantiation, TypecheckingContext/*!*/ tc);
-
- // Contract.Requires( Microsoft.SpecSharp.Collections.Reductions.Forall{Expr! arg in args; arg.Type != null});
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- Type/*!*/ ShallowType(IList<Expr>/*!*/ args);
-
- T Dispatch<T>(IAppliableVisitor<T>/*!*/ visitor);
- }
- [ContractClassFor(typeof(IAppliable))]
- abstract class IAppliableContracts : IAppliable {
-
- #region IAppliable Members
-
- public string FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
- }
- }
-
- public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- Contract.Requires(args != null);
- Contract.Requires(stream != null);
- throw new NotImplementedException();
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- Contract.Requires(rc != null);
- Contract.Requires(subjectForErrorReporting != null);
- throw new NotImplementedException();
- }
-
- public int ArgumentCount {
- get {
- throw new NotImplementedException();
- }
- }
-
- public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- Contract.Requires(args != null);
- Contract.Requires(tc != null);
- Contract.Ensures(Contract.ValueAtReturn(out args) != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Ensures(args.Count == Contract.OldValue(args.Count));
- throw new NotImplementedException();
- }
-
- public Type ShallowType(IList<Expr> args) {
- Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- Contract.Requires(visitor != null);
- throw new NotImplementedException();
- }
-
- #endregion
- }
-
-
- [ContractClass(typeof(IOverloadedAppliableContracts))]
- public interface IOverloadedAppliable {
- void ResolveOverloading(NAryExpr/*!*/ expr);
- bool DoNotResolveOverloading { get; set; }
- }
- [ContractClassFor(typeof(IOverloadedAppliable))]
- public abstract class IOverloadedAppliableContracts : IOverloadedAppliable {
-
- #region IOverloadedAppliable Members
-
- void IOverloadedAppliable.ResolveOverloading(NAryExpr expr) {
- Contract.Requires(expr != null);
- throw new NotImplementedException();
- }
-
- public bool DoNotResolveOverloading
- {
- get
- {
- throw new NotImplementedException();
- }
- set
- {
- throw new NotImplementedException();
- }
- }
-
- #endregion
- }
-
- public class UnaryOperator : IAppliable {
- private IToken/*!*/ tok;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(tok != null);
- }
-
- public enum Opcode {
- Neg,
- Not
- };
- private Opcode op;
- public Opcode Op {
- get {
- return op;
- }
- }
- public UnaryOperator(IToken tok, Opcode op) {
- Contract.Requires(tok != null);
- this.tok = tok;
- this.op = op;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is UnaryOperator))
- return false;
-
- UnaryOperator other = (UnaryOperator)obj;
- return object.Equals(this.op, other.op);
- }
- [Pure]
- public override int GetHashCode() {
- return (int)this.op;
- }
-
- public string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- switch (this.op) {
- case Opcode.Neg:
- return "-";
- case Opcode.Not:
- return "!";
- }
- System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
- public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- //Contract.Requires(args != null);
- stream.SetToken(ref this.tok);
- Contract.Assert(args.Count == 1);
- // determine if parens are needed
- int opBindingStrength = 0x70;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded) {
- stream.Write("(");
- }
- stream.Write(FunctionName);
- cce.NonNull(args[0]).Emit(stream, opBindingStrength, false);
- if (parensNeeded) {
- stream.Write(")");
- }
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- if (rc.TriggerMode && this.op == Opcode.Not) {
- rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
- }
- }
-
- public int ArgumentCount {
- get {
- return 1;
- }
- }
-
- public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Ensures(Contract.ValueAtReturn(out args) != null);
-
- Contract.Assume(args.Count == 1);
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- Type arg0type = cce.NonNull(cce.NonNull(args[0]).Type);
- switch (this.op) {
- case Opcode.Neg:
- if (arg0type.Unify(Type.Int)) {
- return Type.Int;
- }
- if (arg0type.Unify(Type.Real)) {
- return Type.Real;
- }
- //if (arg0type.Unify(Type.Float)) {
- //return Type.Float;
- //}
- goto BAD_TYPE;
- case Opcode.Not:
- if (arg0type.Unify(Type.Bool)) {
- return Type.Bool;
- }
- goto BAD_TYPE;
- }
- System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- BAD_TYPE:
- tc.Error(this.tok, "invalid argument type ({1}) to unary operator {0}",
- this.FunctionName, arg0type);
- return null;
- }
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- switch (this.op) {
- case Opcode.Neg:
- return cce.NonNull(cce.NonNull(args[0]).Type);
- case Opcode.Not:
- return Type.Bool;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // unexpected unary operator
- }
- }
-
- public object Evaluate(object argument) {
- if (argument == null) {
- return null;
- }
- switch (this.op) {
- case Opcode.Neg:
- if (argument is BigNum) {
- return -((BigNum)argument);
- }
- if (argument is BigDec) {
- return -((BigDec)argument);
- }
- if (argument is BigFloat) {
- return -((BigFloat)argument);
- }
- break;
- case Opcode.Not:
- if (argument is bool) {
- return !((bool)argument);
- }
- throw new System.InvalidOperationException("unary Not only applies to bool");
- }
- return null; // unreachable
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
- }
-
- public class BinaryOperator : IAppliable, IOverloadedAppliable {
- private IToken/*!*/ tok;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(tok != null);
- }
-
- public bool DoNotResolveOverloading { get; set; }
-
- public enum Opcode {
- Add,
- Sub,
- Mul,
- Div,
- Mod,
- RealDiv,
- FloatDiv,
- Pow,
- Eq,
- Neq,
- Gt,
- Ge,
- Lt,
- Le,
- And,
- Or,
- Imp,
- Iff,
- Subtype
- };
- private Opcode op;
- public Opcode Op {
- get {
- return op;
- }
- }
- public BinaryOperator(IToken tok, Opcode op) {
- Contract.Requires(tok != null);
- this.tok = tok;
- this.op = op;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is BinaryOperator))
- return false;
-
- BinaryOperator other = (BinaryOperator)obj;
- return object.Equals(this.op, other.op);
- }
-
- [Pure]
- public override int GetHashCode() {
- return (int)this.op << 1;
- }
-
- public string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- switch (this.op) {
- case Opcode.Add:
- return "+";
- case Opcode.Sub:
- return "-";
- case Opcode.Mul:
- return "*";
- case Opcode.Div:
- return "div";
- case Opcode.Mod:
- return "mod";
- case Opcode.RealDiv:
- return "/";
- case Opcode.Pow:
- return "**";
- case Opcode.Eq:
- return "==";
- case Opcode.Neq:
- return "!=";
- case Opcode.Gt:
- return ">";
- case Opcode.Ge:
- return ">=";
- case Opcode.Lt:
- return "<";
- case Opcode.Le:
- return "<=";
- case Opcode.And:
- return "&&";
- case Opcode.Or:
- return "||";
- case Opcode.Imp:
- return "==>";
- case Opcode.Iff:
- return "<==>";
- case Opcode.Subtype:
- return "<:";
- }
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
- public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- //Contract.Requires(args != null);
- stream.SetToken(ref this.tok);
- Contract.Assert(args.Count == 2);
- // determine if parens are needed
- int opBindingStrength;
- bool fragileLeftContext = false; // false means "allow same binding power on left without parens"
- bool fragileRightContext = false; // false means "allow same binding power on right without parens"
- switch (this.op) {
- case Opcode.Add:
- opBindingStrength = 0x40;
- break;
- case Opcode.Sub:
- opBindingStrength = 0x40;
- fragileRightContext = true;
- break;
- case Opcode.Mul:
- opBindingStrength = 0x50;
- break;
- case Opcode.Div:
- opBindingStrength = 0x50;
- fragileRightContext = true;
- break;
- case Opcode.Mod:
- opBindingStrength = 0x50;
- fragileRightContext = true;
- break;
- case Opcode.RealDiv:
- opBindingStrength = 0x50;
- fragileRightContext = true;
- break;
- case Opcode.Pow:
- opBindingStrength = 0x60;
- fragileRightContext = true;
- break;
- case Opcode.Eq:
- case Opcode.Neq:
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- case Opcode.Subtype:
- opBindingStrength = 0x30;
- fragileLeftContext = fragileRightContext = true;
- break;
- case Opcode.And:
- opBindingStrength = 0x20;
- break;
- case Opcode.Or:
- opBindingStrength = 0x21;
- break;
- case Opcode.Imp:
- opBindingStrength = 0x10;
- fragileLeftContext = true;
- break;
- case Opcode.Iff:
- opBindingStrength = 0x00;
- break;
- default:
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- opBindingStrength = -1; // to please compiler, which refuses to consider whether or not all enumeration cases have been considered!
- break;
- }
- int opBS = opBindingStrength & 0xF0;
- int ctxtBS = contextBindingStrength & 0xF0;
- bool parensNeeded = opBS < ctxtBS ||
- (opBS == ctxtBS && (opBindingStrength != contextBindingStrength || fragileContext));
-
- var pop = stream.push(FunctionName);
- if (parensNeeded) {
- stream.Write("(");
- }
- cce.NonNull(args[0]).Emit(stream, opBindingStrength, fragileLeftContext);
- stream.sep();
- stream.Write(" {0} ", FunctionName);
- cce.NonNull(args[1]).Emit(stream, opBindingStrength, fragileRightContext);
- if (parensNeeded) {
- stream.Write(")");
- }
- stream.pop(pop);
- }
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- if (rc.TriggerMode) {
- switch (this.op) {
- case Opcode.Add:
- case Opcode.Sub:
- case Opcode.Mul:
- case Opcode.Div:
- case Opcode.Mod:
- case Opcode.RealDiv:
- case Opcode.Pow:
- case Opcode.Neq: // Neq is allowed, but not Eq
- case Opcode.Subtype:
- // These are fine
- break;
-
- case Opcode.Eq:
- rc.Error(subjectForErrorReporting, "equality is not allowed in triggers");
- break;
-
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- rc.Error(subjectForErrorReporting, "arithmetic comparisons are not allowed in triggers");
- break;
-
- case Opcode.And:
- case Opcode.Or:
- case Opcode.Imp:
- case Opcode.Iff:
- rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
- break;
-
- default:
- System.Diagnostics.Debug.Fail("unknown binary operator: " + this.op.ToString());
- break;
- }
- }
- }
- public int ArgumentCount {
- get {
- return 2;
- }
- }
- public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Ensures(args != null);
- Contract.Assert(args.Count == 2);
- // the default; the only binary operator with a type parameter is equality, but right
- // we don't store this parameter because it does not appear necessary
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- Expr arg0 = cce.NonNull(args[0]);
- Expr arg1 = cce.NonNull(args[1]);
- Type arg0type = cce.NonNull(arg0.Type);
- Type arg1type = cce.NonNull(arg1.Type);
- switch (this.op) {
- case Opcode.Add:
- case Opcode.Sub:
- case Opcode.Mul:
- if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
- return Type.Int;
- }
- if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
- return Type.Real;
- }
- if (arg0type.IsFloat && arg0type.Unify(arg1type)) {
- return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa);
- }
- if (arg1type.IsFloat && arg1type.Unify(arg0type)) {
- return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa);
- }
- goto BAD_TYPE;
- case Opcode.Div:
- case Opcode.Mod:
- if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
- return Type.Int;
- }
- goto BAD_TYPE;
- case Opcode.RealDiv:
- if ((arg0type.Unify(Type.Int) || arg0type.Unify(Type.Real)) &&
- (arg1type.Unify(Type.Int) || arg1type.Unify(Type.Real))) {
- return Type.Real;
- }
- if (arg0type.IsFloat && arg0type.Unify(arg1type)) {
- return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa);
- }
- if (arg1type.IsFloat && arg1type.Unify(arg0type)) {
- return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa);
- }
- goto BAD_TYPE;
- case Opcode.Pow:
- if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
- return Type.Real;
- }
- goto BAD_TYPE;
- case Opcode.Eq:
- case Opcode.Neq:
- // Comparison is allowed if the argument types are unifiable
- // (i.e., if there is any chance that the values of the arguments are
- // in the same domain)
- if (arg0type.Equals(arg1type)) {
- // quick path
- return Type.Bool;
- }
- List<TypeVariable>/*!*/ unifiable = new List<TypeVariable>();
- unifiable.AddRange(arg0type.FreeVariables);
- unifiable.AddRange(arg1type.FreeVariables);
-
- if (arg0type.Unify(arg1type, unifiable, new Dictionary<TypeVariable/*!*/, Type/*!*/>()))
- return Type.Bool;
- goto BAD_TYPE;
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
- return Type.Bool;
- }
- if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
- return Type.Bool;
- }
- if ((arg0type.IsFloat && arg0type.Unify(arg1type)) || (arg1type.IsFloat && arg1type.Unify(arg0type))) {
- return Type.Bool;
- }
- goto BAD_TYPE;
- case Opcode.And:
- case Opcode.Or:
- case Opcode.Imp:
- case Opcode.Iff:
- if (arg0type.Unify(Type.Bool) && arg1type.Unify(Type.Bool)) {
- return Type.Bool;
- }
- goto BAD_TYPE;
- case Opcode.Subtype:
- // Subtype is polymorphically typed and can compare things of
- // arbitrary types (but both arguments must have the same type)
- if (arg0type.Unify(arg1type)) {
- return Type.Bool;
- }
- goto BAD_TYPE;
- }
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- BAD_TYPE:
- tc.Error(this.tok, "invalid argument types ({1} and {2}) to binary operator {0}", this.FunctionName, arg0type, arg1type);
- return null;
- }
-
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- switch (this.op) {
- case Opcode.Add:
- case Opcode.Sub:
- case Opcode.Mul:
- return cce.NonNull(args[0]).ShallowType;
-
- case Opcode.Div:
- case Opcode.Mod:
- return Type.Int;
-
- case Opcode.RealDiv:
- case Opcode.Pow:
- return Type.Real;
-
- case Opcode.Eq:
- case Opcode.Neq:
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- case Opcode.And:
- case Opcode.Or:
- case Opcode.Imp:
- case Opcode.Iff:
- case Opcode.Subtype:
- return Type.Bool;
-
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // unexpected binary operator
- }
- }
-
- public void ResolveOverloading(NAryExpr expr) {
- //Contract.Requires(expr != null);
-
- // immutable Expr must not be modified
- if (DoNotResolveOverloading || expr.Immutable)
- {
- return;
- }
-
- Expr arg0 = cce.NonNull(expr.Args[0]);
- Expr arg1 = cce.NonNull(expr.Args[1]);
- switch (op) {
- case Opcode.Eq:
- if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool) {
- expr.Fun = new BinaryOperator(tok, Opcode.Iff);
- }
- break;
- case Opcode.Neq:
- if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool) {
- expr.Fun = new BinaryOperator(tok, Opcode.Iff);
- var arg1New = new NAryExpr(expr.tok, new UnaryOperator(tok, UnaryOperator.Opcode.Not), new List<Expr> { arg1 });
-
- // ugly ... there should be some more general approach,
- // e.g., to typecheck the whole expression again
- arg1New.Type = Type.Bool;
- arg1New.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
-
- expr.Args[1] = arg1New;
- }
- break;
- }
- }
-
- public object Evaluate(object e1, object e2) {
- if (e1 == null || e2 == null) {
- return null;
- }
-
- switch (this.op) {
- case Opcode.Add:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) + ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) + ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) + ((BigFloat)e2);
- }
- break;
- case Opcode.Sub:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) - ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) - ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) - ((BigFloat)e2);
- }
- break;
- case Opcode.Mul:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) * ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) * ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) * ((BigFloat)e2);
- }
- break;
- case Opcode.Div:
- if (e1 is BigNum && e2 is BigNum) {
- return /* TODO: right semantics? */ ((BigNum)e1) / ((BigNum)e2);
- }
- break;
- case Opcode.Mod:
- if (e1 is BigNum && e2 is BigNum) {
- return /* TODO: right semantics? */ ((BigNum)e1) % ((BigNum)e2);
- }
- break;
- case Opcode.RealDiv:
- // TODO: add partial evaluation fro real division
- break;
- case Opcode.FloatDiv:
- //TODO: add float division
- break;
- case Opcode.Pow:
- // TODO: add partial evaluation fro real exponentiation
- break;
- case Opcode.Lt:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) < ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) < ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) < ((BigFloat)e2);
- }
- break;
- case Opcode.Le:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) <= ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) <= ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) <= ((BigFloat)e2);
- }
- break;
- case Opcode.Gt:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) > ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) > ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) > ((BigFloat)e2);
- }
- break;
- case Opcode.Ge:
- if (e1 is BigNum && e2 is BigNum) {
- return ((BigNum)e1) >= ((BigNum)e2);
- }
- if (e1 is BigDec && e2 is BigDec) {
- return ((BigDec)e1) >= ((BigDec)e2);
- }
- if (e1 is BigFloat && e2 is BigFloat) {
- return ((BigFloat)e1) >= ((BigFloat)e2);
- }
- break;
-
- case Opcode.And:
- if (e1 is bool && e2 is bool) {
- return (bool)e1 && (bool)e2;
- }
- break;
- case Opcode.Or:
- if (e1 is bool && e2 is bool) {
- return (bool)e1 || (bool)e2;
- }
- break;
- case Opcode.Imp:
- if (e1 is bool && e2 is bool) {
- return !(bool)e1 || (bool)e2;
- }
- break;
- case Opcode.Iff:
- if (e1 is bool && e2 is bool) {
- return e1 == e2;
- }
- break;
-
- case Opcode.Eq:
- return Equals(e1, e2);
- case Opcode.Neq:
- return !Equals(e1, e2);
-
- case Opcode.Subtype:
- throw new System.NotImplementedException();
- }
- throw new System.InvalidOperationException("bad types to binary operator " + this.op);
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
-
- }
-
- public class FunctionCall : IAppliable {
- private IdentifierExpr/*!*/ name;
- public Function Func;
- public FunctionCall(IdentifierExpr name) {
- Contract.Requires(name != null);
- this.name = name;
- }
- public FunctionCall(Function f) {
- Contract.Requires(f != null);
- this.Func = f;
- this.name = new IdentifierExpr(Token.NoToken, f.Name);
-
- // We need set the type of this IdentifierExpr so ShallowType() works
- Debug.Assert(f.OutParams.Count > 0);
- this.name.Type = f.OutParams[0].TypedIdent.Type;
- }
- public string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return this.name.Name;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(name != null);
- }
-
- public FunctionCall createUnresolvedCopy()
- {
- return new FunctionCall(new IdentifierExpr(name.tok, name.Name, name.Type));
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return name.Name;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- FunctionCall fc = other as FunctionCall;
- return fc != null && this.Func == fc.Func;
- }
- [Pure]
- public override int GetHashCode() {
- Contract.Assume(this.Func != null);
- return Func.GetHashCode();
- }
-
- virtual public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- //Contract.Requires(args != null);
- this.name.Emit(stream, 0xF0, false);
- if (stream.UseForComputingChecksums)
- {
- var c = Func.DependencyChecksum;
- if (c != null)
- {
- stream.Write(string.Format("[dependency_checksum:{0}]", c));
- }
- }
- stream.Write("(");
- args.Emit(stream);
- stream.Write(")");
- }
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- if (Func != null) {
- // already resolved
- return;
- }
- Func = rc.LookUpProcedure(name.Name) as Function;
- if (Func == null) {
- rc.Error(this.name, "use of undeclared function: {0}", name.Name);
- }
- else if (name.Type == null) {
- // We need set the type of this IdentifierExpr so ShallowType() works
- Debug.Assert(name.Type == null);
- Debug.Assert(Func.OutParams.Count > 0);
- name.Type = Func.OutParams[0].TypedIdent.Type;
- }
- }
- public virtual int ArgumentCount {
- get {
- Contract.Assume(Func != null); // ArgumentCount requires object to be properly resolved.
- return Func.InParams.Count;
- }
- }
- public virtual Type Typecheck(IList<Expr> actuals, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- //Contract.Requires(actuals != null);
- Contract.Ensures(Contract.ValueAtReturn(out actuals) != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Assume(this.Func != null);
- Contract.Assume(actuals.Count == Func.InParams.Count);
- Contract.Assume(Func.OutParams.Count == 1);
-
- List<Type/*!*/>/*!*/ resultingTypeArgs;
- List<Type> actualResultType =
- Type.CheckArgumentTypes(Func.TypeParameters,
- out resultingTypeArgs,
- new List<Type>(Func.InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- actuals,
- new List<Type>(Func.OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
- null,
- // we need some token to report a possibly wrong number of
- // arguments
- actuals.Count > 0 ? cce.NonNull(actuals[0]).tok : Token.NoToken,
- "application of " + name.Name,
- tc);
-
- if (actualResultType == null) {
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- } else {
- Contract.Assert(actualResultType.Count == 1);
- tpInstantiation =
- SimpleTypeParamInstantiation.From(Func.TypeParameters, resultingTypeArgs);
- return actualResultType[0];
- }
- }
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assume(name.Type != null);
- return name.Type;
- }
-
- public virtual T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
- }
-
- public class TypeCoercion : IAppliable {
- private IToken/*!*/ tok;
- public Type/*!*/ Type;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(tok != null);
- }
-
- public TypeCoercion(IToken tok, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(tok != null);
- this.tok = tok;
- this.Type = type;
- }
-
- public override bool Equals(object obj) {
- TypeCoercion other = obj as TypeCoercion;
- if (other == null) {
- return false;
- } else {
- return object.Equals(Type, other.Type);
- }
- }
-
-
-
- public
- string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return ":";
- }
- }
-
- public void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
- int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(args != null);
- //Contract.Requires(stream != null);
- stream.SetToken(ref this.tok);
- Contract.Assert(args.Count == 1);
- // determine if parens are needed
- int opBindingStrength = 0x80;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded)
- stream.Write("(");
-
- cce.NonNull(args[0]).Emit(stream, opBindingStrength, false);
- stream.Write("{0} ", FunctionName);
- Type.Emit(stream, 0);
-
- if (parensNeeded)
- stream.Write(")");
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- this.Type = this.Type.ResolveType(rc);
- }
-
- public int ArgumentCount {
- get {
- return 1;
- }
- }
-
- public Type Typecheck(IList<Expr>/*!*/ args,
- out TypeParamInstantiation/*!*/ tpInstantiation,
- TypecheckingContext/*!*/ tc) {
- //Contract.Requires(args != null);
- //Contract.Requires(tc != null);
- Contract.Ensures(args != null);
-
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
-
- Contract.Assume(args.Count == 1);
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
-
- if (!this.Type.Unify(cce.NonNull(cce.NonNull(args[0]).Type)))
- tc.Error(this.tok, "{0} cannot be coerced to {1}",
- cce.NonNull(args[0]).Type, this.Type);
- return this.Type;
- }
-
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.Type;
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
-
- }
-
- public class ArithmeticCoercion : IAppliable {
- public enum CoercionType {
- ToInt,
- ToReal,
- ToFloat
- }
-
- private IToken/*!*/ tok;
- public readonly CoercionType Coercion;
- private readonly string name;
- private readonly Type type;
- private readonly Type argType;
- private readonly Type argType2;
- private readonly int hashCode;
-
- public ArithmeticCoercion(IToken tok, CoercionType coercion) {
- this.tok = tok;
- this.Coercion = coercion;
-
- switch (coercion) {
- case CoercionType.ToInt:
- this.name = "int";
- this.type = Type.Int;
- this.argType = Type.Real;
- this.hashCode = 1;
- break;
- case CoercionType.ToReal:
- this.name = "real";
- this.type = Type.Real;
- this.argType = Type.Int;
- this.hashCode = 2;
- break;
- default:
- Contract.Assert(false);
- break;
- }
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return this.name;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- ArithmeticCoercion ac = other as ArithmeticCoercion;
- return ac != null && this.Coercion == ac.Coercion;
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.hashCode;
- }
-
- public string/*!*/ FunctionName {
- get {
- return this.name;
- }
- }
-
- public int ArgumentCount {
- get {
- return 1;
- }
- }
-
- virtual public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- //Contract.Requires(args != null);
- stream.Write(this.name);
- stream.Write("(");
- args.Emit(stream);
- stream.Write(")");
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- }
-
- public virtual Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- //Contract.Requires(args != null);
- Contract.Ensures(args != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
-
- Contract.Assert(args.Count == 1);
-
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
-
- if (!(cce.NonNull(cce.NonNull(args[0]).Type).Unify(argType) || cce.NonNull(cce.NonNull(args[0]).Type).Unify(argType2)))
- {
- tc.Error(this.tok, "argument type {0} does not match expected type {1} or type {2}", cce.NonNull(args[0]).Type, this.argType, this.argType2);
- }
-
- return this.type;
- }
-
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.type;
- }
-
- public virtual T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
- }
-
- public class NAryExpr : Expr {
- [Additive]
- [Peer]
- private IAppliable _Fun;
- public IAppliable/*!*/ Fun {
- get {
- return _Fun;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Cannot change Function used by Immutable NAryExpr");
-
- _Fun = value;
- }
- }
- private List<Expr> _Args;
- public IList<Expr> Args {
- get {
- if (Immutable)
- return _Args.AsReadOnly();
- else
- return _Args;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Cannot change Args of Immutable NAryExpr");
-
- _Args = value as List<Expr>;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Fun != null);
- Contract.Invariant(Args != null);
- }
-
-
- // The instantiation of type parameters that is determined during type checking.
- // Which type parameters are available depends on the IAppliable
- public TypeParamInstantiation TypeParameters = null;
-
- [Captured]
- public NAryExpr(IToken/*!*/ tok, IAppliable/*!*/ fun, IList<Expr>/*!*/ args, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(fun != null);
- Contract.Requires(args != null);
- _Fun = fun;
- Contract.Assert(Contract.ForAll(0, args.Count, index => args[index] != null));
- if (immutable) {
- // We need to make a new list because the client might be holding
- // references to the list that they gave us which could be used to
- // circumvent the immutability enforcement
- _Args = new List<Expr>(args);
- CachedHashCode = ComputeHashCode();
- } else {
- if (args is List<Expr>) {
- // Preserve NAryExpr's old behaviour, we take ownership of the List<Expr>.
- // We can only do this if the type matches
- _Args = args as List<Expr>;
- }
- else {
- // Otherwise we must make a copy
- _Args = new List<Expr> (args);
- }
- }
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is NAryExpr))
- return false;
-
- NAryExpr other = (NAryExpr)obj;
- return object.Equals(this.Fun, other.Fun) && this.Args.SequenceEqual(other.Args);
- }
-
- [Pure]
- public override int GetHashCode() {
- if (Immutable)
- return this.CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- int h = this.Fun.GetHashCode();
- // DO NOT USE Args.GetHashCode() because that uses Object.GetHashCode() which uses references
- // We want structural equality
- foreach (var arg in Args) {
- h = (97*h) + arg.GetHashCode();
- }
- return h;
- }
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- Fun.Emit(Args, stream, contextBindingStrength, fragileContext);
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Fun.Resolve(rc, this);
- foreach (Expr/*!*/ e in Args) {
- Contract.Assert(e != null);
- e.Resolve(rc);
- }
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- foreach (Expr/*!*/ e in Args) {
- Contract.Assert(e != null);
- e.ComputeFreeVariables(freeVars);
- }
- // also add the free type variables
- if (TypeParameters != null) {
- foreach (TypeVariable/*!*/ var in TypeParameters.FormalTypeParams) {
- Contract.Assert(var != null);
- foreach (TypeVariable/*!*/ w in TypeParameters[var].FreeVariables) {
- Contract.Assert(w != null);
- freeVars.Add(w);
- }
- }
- }
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- int prevErrorCount = tc.ErrorCount;
- foreach (Expr/*!*/ e in Args) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
- if (Fun.ArgumentCount != Args.Count) {
- tc.Error(this, "wrong number of arguments to function: {0} ({1} instead of {2})",
- Fun.FunctionName, Args.Count, Fun.ArgumentCount);
- } else if (tc.ErrorCount == prevErrorCount &&
- // if the type parameters are set, this node has already been
- // typechecked and does not need to be checked again
- TypeParameters == null) {
- TypeParamInstantiation tpInsts;
- Type = Fun.Typecheck(Args, out tpInsts, tc); // Make sure we pass Args so if this Expr is immutable it is protected
- TypeParameters = tpInsts;
- }
- IOverloadedAppliable oa = Fun as IOverloadedAppliable;
- if (oa != null) {
- oa.ResolveOverloading(this);
- }
- if (Type == null) {
- // set Type to some non-null value
- Type = new TypeProxy(this.tok, "type_checking_error");
- }
- }
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Fun.ShallowType(Args);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitNAryExpr(this);
- }
- }
-
- public class MapSelect : IAppliable {
-
- public readonly int Arity;
- private readonly IToken/*!*/ tok;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(tok != null);
- }
-
-
- public MapSelect(IToken tok, int arity) {
- Contract.Requires(tok != null);
- this.tok = tok;
- this.Arity = arity;
- }
-
- public string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return "MapSelect";
- }
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (!(obj is MapSelect))
- return false;
-
- MapSelect other = (MapSelect)obj;
- return this.Arity == other.Arity;
- }
-
- [Pure]
- public override int GetHashCode() {
- return Arity.GetHashCode() * 2823;
- }
-
- public void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
- int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(args != null);
- //Contract.Requires(stream != null);
- Contract.Assume(args.Count == Arity + 1);
- Emit(args, stream, contextBindingStrength, fragileContext, false);
- }
-
- public static void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
- int contextBindingStrength, bool fragileContext,
- bool withRhs) {
- Contract.Requires(args != null);
- Contract.Requires(stream != null);
- const int opBindingStrength = 0x90;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded) {
- stream.Write("(");
- }
- cce.NonNull(args[0]).Emit(stream, opBindingStrength, false);
- stream.Write("[");
-
- string sep = "";
- int lastIndex = withRhs ? args.Count - 1 : args.Count;
- for (int i = 1; i < lastIndex; ++i) {
- stream.Write(sep);
- sep = ", ";
- cce.NonNull(args[i]).Emit(stream);
- }
-
- if (withRhs) {
- stream.Write(" := ");
- cce.NonNull(args.Last()).Emit(stream);
- }
-
- stream.Write("]");
- if (parensNeeded) {
- stream.Write(")");
- }
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- // PR: nothing?
- }
-
- public int ArgumentCount {
- get {
- return Arity + 1;
- }
- }
-
- // it is assumed that each of the arguments has already been typechecked
- public static Type Typecheck(Type/*!*/ mapType,
- // we just pass an Absy, because in
- // the AssignCmd maps can also be
- // represented by non-expressions
- Absy/*!*/ map,
- List<Expr>/*!*/ indexes,
- // the type parameters, in this context, are the parameters of the
- // potentially polymorphic map type. Because it might happen that
- // the whole map type is unknown and represented using a MapTypeProxy,
- // the instantiations given in the following out-parameter are subject
- // to change if further unifications are done.
- out TypeParamInstantiation/*!*/ tpInstantiation,
- TypecheckingContext/*!*/ tc,
- IToken/*!*/ typeCheckingSubject,
- string/*!*/ opName) {
- Contract.Requires(mapType != null);
- Contract.Requires(map != null);
- Contract.Requires(indexes != null);
- Contract.Requires(tc != null);
- Contract.Requires(typeCheckingSubject != null);
- Contract.Requires(opName != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
-
- mapType = mapType.Expanded;
- if (mapType.IsMap && mapType.MapArity != indexes.Count) {
- tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1} instead of {2}",
- opName, indexes.Count, mapType.MapArity);
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- } else if (!mapType.Unify(new MapTypeProxy(map.tok, "select", indexes.Count))) {
- tc.Error(map.tok, "{0} applied to a non-map: {1}", opName, map);
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- }
- mapType = TypeProxy.FollowProxy(mapType);
-
- if (mapType is MapType) {
- MapType mt = (MapType)mapType;
- return mt.CheckArgumentTypes(indexes, out tpInstantiation,
- typeCheckingSubject, opName, tc);
- } else {
- MapTypeProxy mt = (MapTypeProxy)mapType;
- return mt.CheckArgumentTypes(indexes, out tpInstantiation,
- typeCheckingSubject, opName, tc);
- }
- }
-
- public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Assume(args.Count == Arity + 1);
-
- // FIXME: Wny are we passing a copy?
- List<Expr> actualArgs = new List<Expr>();
- for (int i = 1; i < args.Count; ++i)
- actualArgs.Add(args[i]);
-
- return Typecheck(cce.NonNull(cce.NonNull(args[0]).Type), cce.NonNull(args[0]),
- actualArgs, out tpInstantiation, tc, this.tok, "map select");
- }
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Expr a0 = cce.NonNull(args[0]);
- Type a0Type = a0.ShallowType;
- if (a0Type == null || !a0Type.IsMap) {
- // we are unable to determine the type of the select, so just return an arbitrary type
- return Type.Int;
- }
- MapType mapType = a0Type.AsMap;
- List<Type> actualArgTypes = new List<Type>();
- for (int i = 1; i < args.Count; ++i) {
- actualArgTypes.Add(cce.NonNull(args[i]).ShallowType);
- }
- return Type.InferValueType(mapType.TypeParameters, mapType.Arguments, mapType.Result, actualArgTypes);
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
- }
-
- public class MapStore : IAppliable {
-
- public readonly int Arity;
- public readonly IToken/*!*/ tok;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(tok != null);
- }
-
-
- public MapStore(IToken tok, int arity) {
- Contract.Requires(tok != null);
- this.tok = tok;
- this.Arity = arity;
- }
-
- public string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return "MapStore";
- }
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (!(obj is MapStore))
- return false;
-
- MapStore other = (MapStore)obj;
- return this.Arity == other.Arity;
- }
-
- [Pure]
- public override int GetHashCode() {
- return Arity.GetHashCode() * 28231;
- }
-
- public void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
- int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(args != null);
- //Contract.Requires(stream != null);
- Contract.Assert(args.Count == Arity + 2);
- MapSelect.Emit(args, stream, contextBindingStrength, fragileContext, true);
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- // PR: nothing?
- }
-
- public int ArgumentCount {
- get {
- return Arity + 2;
- }
- }
-
- // it is assumed that each of the arguments has already been typechecked
- public static Type Typecheck(IList<Expr>/*!*/ args, out TypeParamInstantiation/*!*/ tpInstantiation,
- TypecheckingContext/*!*/ tc,
- IToken/*!*/ typeCheckingSubject,
- string/*!*/ opName) {
- Contract.Requires(args != null);
- Contract.Requires(tc != null);
- Contract.Requires(typeCheckingSubject != null);
- Contract.Requires(opName != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
-
- // part of the type checking works exactly as for MapSelect
- List<Expr> selectArgs = new List<Expr>();
- for (int i = 1; i < args.Count - 1; ++i)
- selectArgs.Add(args[i]);
- Type resultType =
- MapSelect.Typecheck(cce.NonNull(cce.NonNull(args[0]).Type), cce.NonNull(args[0]),
- selectArgs, out tpInstantiation, tc, typeCheckingSubject, opName);
-
- // check the the rhs has the right type
- if (resultType == null) {
- // error messages have already been created by MapSelect.Typecheck
- return null;
- }
- Type rhsType = cce.NonNull(cce.NonNull(args.Last()).Type);
- if (!resultType.Unify(rhsType)) {
- tc.Error(cce.NonNull(args.Last()).tok,
- "right-hand side in {0} with wrong type: {1} (expected: {2})",
- opName, rhsType, resultType);
- return null;
- }
-
- return cce.NonNull(args[0]).Type;
- }
-
- public Type Typecheck(IList<Expr>/*!*/ args,
- out TypeParamInstantiation/*!*/ tpInstantiation,
- TypecheckingContext/*!*/ tc) {
- //Contract.Requires(args != null);
- //Contract.Requires(tc != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Ensures(Contract.ValueAtReturn(out args) != null);
- Contract.Assert(args.Count == Arity + 2);
- return Typecheck(args, out tpInstantiation, tc, this.tok, "map store");
- }
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return cce.NonNull(args[0]).ShallowType;
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
- }
-
-
- public class IfThenElse : IAppliable {
-
- private IToken/*!*/ _tok;
-
- public IToken/*!*/ tok
- {
- get
- {
- Contract.Ensures(Contract.Result<IToken>() != null);
- return this._tok;
- }
- set
- {
- Contract.Requires(value != null);
- this._tok = value;
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this._tok != null);
- }
-
- public IfThenElse(IToken tok) {
- Contract.Requires(tok != null);
- this._tok = tok;
- }
-
- public string/*!*/ FunctionName {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
-
- return "if-then-else";
- }
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (!(obj is IfThenElse))
- return false;
- return true;
- }
-
- [Pure]
- public override int GetHashCode() {
- return 1;
- }
-
- public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- //Contract.Requires(args != null);
- stream.SetToken(this);
- Contract.Assert(args.Count == 3);
- stream.push();
- stream.Write("(if ");
- cce.NonNull(args[0]).Emit(stream, 0x00, false);
- stream.sep();
- stream.Write(" then ");
- cce.NonNull(args[1]).Emit(stream, 0x00, false);
- stream.sep();
- stream.Write(" else ");
- cce.NonNull(args[2]).Emit(stream, 0x00, false);
- stream.Write(")");
- stream.pop();
- }
-
- public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
- //Contract.Requires(subjectForErrorReporting != null);
- //Contract.Requires(rc != null);
- // PR: nothing?
- }
-
- public int ArgumentCount {
- get {
- return 3;
- }
- }
-
- public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- //Contract.Requires(args != null);
- Contract.Ensures(args != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- Contract.Assert(args.Count == 3);
- // the default; the only binary operator with a type parameter is equality, but right
- // we don't store this parameter because it does not appear necessary
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- Expr arg0 = cce.NonNull(args[0]);
- Expr arg1 = cce.NonNull(args[1]);
- Expr arg2 = cce.NonNull(args[2]);
-
- if (!cce.NonNull(arg0.Type).Unify(Type.Bool)) {
- tc.Error(this.tok, "the first argument to if-then-else should be bool, not {0}", arg0.Type);
- } else if (!cce.NonNull(arg1.Type).Unify(cce.NonNull(arg2.Type))) {
- tc.Error(this.tok, "branches of if-then-else have incompatible types {0} and {1}", arg1.Type, arg2.Type);
- } else {
- return arg1.Type;
- }
-
- return null;
- }
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- public Type ShallowType(IList<Expr> args) {
- //Contract.Requires(args != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return cce.NonNull(args[1]).ShallowType;
- }
-
- public T Dispatch<T>(IAppliableVisitor<T> visitor) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this);
- }
- }
-
-
-
- public class CodeExpr : Expr {
- public List<Variable>/*!*/ LocVars;
- [Rep]
- public List<Block/*!*/>/*!*/ Blocks;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(LocVars != null);
- Contract.Invariant(cce.NonNullElements(Blocks));
- }
-
- public CodeExpr(List<Variable>/*!*/ localVariables, List<Block/*!*/>/*!*/ blocks, bool immutable=false)
- : base(Token.NoToken, immutable) {
- Contract.Requires(localVariables != null);
- Contract.Requires(cce.NonNullElements(blocks));
- Contract.Requires(0 < blocks.Count);
- LocVars = localVariables;
- Blocks = blocks;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- // FIXME: This seems wrong we don't want reference equality, we want structural equality
- [Pure]
- public override bool Equals(object obj)
- {
- return base.Equals(obj);
- }
-
- [Pure]
- public override int GetHashCode()
- {
- if (Immutable)
- return CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- return base.GetHashCode();
- }
-
-
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- // Treat a BlockEexpr as if it has no free variables at all
- }
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- //level++;
- int level = 0;
- stream.WriteLine(level, "|{");
-
- if (this.LocVars.Count > 0) {
- stream.Write(level + 1, "var ");
- this.LocVars.Emit(stream, true);
- stream.WriteLine(";");
- }
-
- foreach (Block/*!*/ b in this.Blocks) {
- Contract.Assert(b != null);
- b.Emit(stream, level + 1);
- }
-
- stream.WriteLine();
- stream.WriteLine(level, "}|");
-
- stream.WriteLine();
- stream.WriteLine();
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
-
- rc.PushVarContext();
- foreach (Variable/*!*/ v in LocVars) {
- Contract.Assert(v != null);
- v.Register(rc);
- v.Resolve(rc);
- }
-
- rc.PushProcedureContext();
- foreach (Block/*!*/ b in Blocks) {
- Contract.Assert(b != null);
- b.Register(rc);
- }
-
- foreach (Block/*!*/ b in Blocks) {
- Contract.Assert(b != null);
- b.Resolve(rc);
- }
-
- rc.PopProcedureContext();
- rc.PopVarContext();
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- foreach (Variable/*!*/ v in LocVars) {
- Contract.Assert(v != null);
- v.Typecheck(tc);
- }
- foreach (Block/*!*/ b in Blocks) {
- Contract.Assert(b != null);
- b.Typecheck(tc);
- }
- this.Type = Type.Bool;
- }
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Type.Bool;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitCodeExpr(this);
- }
- }
-
- public class BvExtractExpr : Expr {
- private /*readonly--except in StandardVisitor*/ Expr/*!*/ _Bitvector;
- public Expr Bitvector {
- get {
- return _Bitvector;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Cannot change BitVector field of an immutable BvExtractExpr");
-
- _Bitvector = value;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(_Bitvector != null);
- }
-
- public readonly int Start, End;
-
- public BvExtractExpr(IToken/*!*/ tok, Expr/*!*/ bv, int end, int start, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(bv != null);
- _Bitvector = bv;
- Start = start;
- End = end;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is BvExtractExpr))
- return false;
-
- BvExtractExpr other = (BvExtractExpr)obj;
- return object.Equals(this.Bitvector, other.Bitvector) &&
- this.Start.Equals(other.Start) && this.End.Equals(other.End);
- }
-
- [Pure]
- public override int GetHashCode() {
- if (Immutable)
- return CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- int h = this.Bitvector.GetHashCode();
- h ^= Start * 17 ^ End * 13;
- return h;
- }
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- int opBindingStrength = 0x90;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded) {
- stream.Write("(");
- }
- Bitvector.Emit(stream, opBindingStrength, false);
- stream.Write("[" + End + ":" + Start + "]");
- if (parensNeeded) {
- stream.Write(")");
- }
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Bitvector.Resolve(rc);
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- Bitvector.ComputeFreeVariables(freeVars);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- Bitvector.Typecheck(tc);
- Contract.Assert(Bitvector.Type != null); // follows from postcondition of Expr.Typecheck
-
- if (Start < 0) {
- tc.Error(this, "start index in extract must not be negative");
- } else if (End < 0) {
- tc.Error(this, "end index in extract must not be negative");
- } else if (End < Start) {
- tc.Error(this, "start index in extract must be no bigger than the end index");
- } else {
- Type typeConstraint = new BvTypeProxy(this.tok, "extract", End - Start);
- if (typeConstraint.Unify(Bitvector.Type)) {
- Type = Type.GetBvType(End - Start);
- } else {
- tc.Error(this, "extract operand must be a bitvector of at least {0} bits (got {1})", End - Start, Bitvector.Type);
- }
- }
- if (Type == null) {
- Type = new TypeProxy(this.tok, "type_checking_error");
- }
- }
-
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Type.GetBvType(End - Start);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBvExtractExpr(this);
- }
- }
-
- public class BvConcatExpr : Expr {
- private /*readonly--except in StandardVisitor*/ Expr/*!*/ _E0, _E1;
- public Expr E0 {
- get {
- return _E0;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Can't change E0 reference on immutable Expr");
-
- _E0 = value;
- }
- }
- public Expr E1 {
- get {
- return _E1;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException("Can't change E1 reference on immutable Expr");
-
- _E1 = value;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(E0 != null);
- Contract.Invariant(E1 != null);
- }
-
-
- public BvConcatExpr(IToken/*!*/ tok, Expr/*!*/ e0, Expr/*!*/ e1, bool immutable=false)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- _E0 = e0;
- _E1 = e1;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is BvConcatExpr))
- return false;
-
- BvConcatExpr other = (BvConcatExpr)obj;
- return object.Equals(this.E0, other.E0) && object.Equals(this.E1, other.E1);
- }
-
- [Pure]
- public override int GetHashCode()
- {
- if (Immutable)
- return CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- int h = this.E0.GetHashCode() ^ this.E1.GetHashCode() * 17;
- return h;
- }
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- int opBindingStrength = 0x32;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded) {
- stream.Write("(");
- }
- E0.Emit(stream, opBindingStrength, false);
- stream.Write(" ++ ");
- // while this operator is associative, our incomplete axioms in int translation don't
- // make much use of it, so better stick to the actual tree shape
- E1.Emit(stream, opBindingStrength, true);
- if (parensNeeded) {
- stream.Write(")");
- }
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- E0.Resolve(rc);
- E1.Resolve(rc);
- }
- public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- //Contract.Requires(freeVars != null);
- E0.ComputeFreeVariables(freeVars);
- E1.ComputeFreeVariables(freeVars);
- }
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- E0.Typecheck(tc);
- Contract.Assert(E0.Type != null); // follows from postcondition of Expr.Typecheck
- E1.Typecheck(tc);
- Contract.Assert(E1.Type != null); // follows from postcondition of Expr.Typecheck
-
- if (E0.Type.Unify(new BvTypeProxy(this.tok, "concat0", 0)) && E1.Type.Unify(new BvTypeProxy(this.tok, "concat1", 0))) {
- Type = new BvTypeProxy(this.tok, "concat", E0.Type, E1.Type);
- } else {
- tc.Error(this, "++ operands need to be bitvectors (got {0}, {1})", E0.Type, E1.Type);
- }
- if (Type == null) {
- Type = new TypeProxy(this.tok, "type_checking_error");
- }
- }
-
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- Type t0 = E0.ShallowType;
- Type t1 = E1.ShallowType;
- int len0 = t0.IsBv ? t0.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
- int len1 = t1.IsBv ? t1.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
- return Type.GetBvType(len0 + len1);
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBvConcatExpr(this);
- }
- }
-}
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie {
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using Microsoft.Basetypes;
+
+ using Set = GSet<object>; // not that the set used is not a set of Variable only, as it also contains TypeVariables
+
+
+ //---------------------------------------------------------------------
+ // Expressions
+ //
+ // For expressions, we override the Equals and GetHashCode method to
+ // implement structural equality. Note this is not logical equivalence
+ // and is not modulo alpha-renaming.
+ //---------------------------------------------------------------------
+
+
+ [ContractClass(typeof(ExprContracts))]
+ public abstract class Expr : Absy {
+ public Expr(IToken/*!*/ tok, bool immutable)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ this.Immutable = immutable;
+ }
+
+ public void Emit(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ Emit(stream, 0, false);
+ }
+
+ /// <summary>
+ /// If true the client is making a promise that this Expr will be
+ /// treated immutably (i.e. once constructed it is never changed).
+ /// This is currently not enforced but it should be!
+ ///
+ /// This allows the Expr's hash code to be cached making calls to
+ /// GetHashCode() very cheap.
+ /// </summary>
+ /// <value><c>true</c> if immutable; otherwise, <c>false</c>.</value>
+ public bool Immutable {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// Computes the hash code of this Expr skipping any cache.
+ ///
+ /// Sub classes should place their implementation of computing their hashcode
+ /// here (making sure to call GetHashCode() not ComputeHashCode() on Expr for performance reasons)
+ /// and have GetHashCode() use a cached result from ComputeHashCode() if the
+ /// Expr was constructed to be immutable.
+ /// </summary>
+ /// <returns>The hash code.</returns>
+ public abstract int ComputeHashCode();
+ protected int CachedHashCode = 0;
+
+ public abstract void Emit(TokenTextWriter/*!*/ wr, int contextBindingStrength, bool fragileContext);
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
+ this.Emit(stream, 0, false);
+ }
+ return buffer.ToString();
+ }
+
+ /// <summary>
+ /// Add to "freeVars" the free variables in the expression.
+ /// </summary>
+ public abstract void ComputeFreeVariables(Set /*Variable*//*!*/ freeVars);
+
+ /// <summary>
+ /// Filled in by the Typecheck method. A value of "null" means a succeeding
+ /// call to Typecheck has not taken place (that is, either Typecheck hasn't
+ /// been called or Typecheck encountered an error in the expression to be
+ /// typechecked).
+ /// </summary>
+ private Type _Type = null;
+ public Type Type {
+ get {
+ return _Type;
+ }
+ set {
+ if (_Type == null) {
+ // Expr has never been type checked so always allow this
+ _Type = value;
+ } else {
+ if (Immutable && !_Type.Equals(value))
+ throw new InvalidOperationException("Cannot change the Type of an Immutable Expr");
+
+ // Once the Type has been set (i.e. no longer null) we never change the reference
+ // if this Expr is immutable, even if the Type is equivalent (i.e. _Type.Equals(newType))
+ if (!Immutable)
+ _Type = value;
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ Contract.Ensures(Type != null);
+ // This body is added only because C# insists on it. It should really be left out, as if TypeCheck still were abstract.
+ // The reason for mentioning the method here at all is to give TypeCheck a postcondition for all expressions.
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ /// <summary>
+ /// Returns the type of the expression, supposing that all its subexpressions are well typed.
+ /// </summary>
+ public abstract Type/*!*/ ShallowType {
+ get;
+ }
+
+ // Handy syntactic sugar follows:
+
+ public static NAryExpr Unary(IToken x, UnaryOperator.Opcode op, Expr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return new NAryExpr(x, new UnaryOperator(x, op), new List<Expr> { e1 });
+ }
+
+ public static NAryExpr Binary(IToken x, BinaryOperator.Opcode op, Expr e0, Expr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return new NAryExpr(x, new BinaryOperator(x, op), new List<Expr> { e0, e1 });
+ }
+
+ public static NAryExpr Binary(BinaryOperator.Opcode op, Expr e0, Expr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(Token.NoToken, op, e0, e1);
+ }
+
+ public static NAryExpr Eq(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Eq, e1, e2);
+ }
+ public static NAryExpr Neq(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Neq, e1, e2);
+ }
+ public static NAryExpr Le(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Le, e1, e2);
+ }
+ public static NAryExpr Ge(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Ge, e1, e2);
+ }
+ public static NAryExpr Lt(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Lt, e1, e2);
+ }
+ public static NAryExpr Gt(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Gt, e1, e2);
+ }
+ public static Expr And(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ if (e1 == true_) {
+ return e2;
+ } else if (e2 == true_) {
+ return e1;
+ } else if (e1 == false_ || e2 == false_) {
+ return false_;
+ } else {
+ var res = Binary(BinaryOperator.Opcode.And, e1, e2);
+ res.Type = Microsoft.Boogie.Type.Bool;
+ res.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ return res;
+ }
+ }
+ public static Expr Or(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ if (e1 == false_) {
+ return e2;
+ } else if (e2 == false_) {
+ return e1;
+ } else if (e1 == true_ || e2 == true_) {
+ return true_;
+ } else {
+ return Binary(BinaryOperator.Opcode.Or, e1, e2);
+ }
+ }
+ public static Expr Not(Expr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ NAryExpr nary = e1 as NAryExpr;
+
+ if (e1 == true_) {
+ return false_;
+ } else if (e1 == false_) {
+ return true_;
+ } else if (nary != null) {
+ if (nary.Fun is UnaryOperator) {
+ UnaryOperator op = (UnaryOperator)nary.Fun;
+ if (op.Op == UnaryOperator.Opcode.Not) {
+ return cce.NonNull(nary.Args[0]);
+ }
+ } else if (nary.Fun is BinaryOperator) {
+ BinaryOperator op = (BinaryOperator)nary.Fun;
+ Expr arg0 = cce.NonNull(nary.Args[0]);
+ Expr arg1 = cce.NonNull(nary.Args[1]);
+ if (op.Op == BinaryOperator.Opcode.Eq) {
+ return Neq(arg0, arg1);
+ } else if (op.Op == BinaryOperator.Opcode.Neq) {
+ return Eq(arg0, arg1);
+ } else if (op.Op == BinaryOperator.Opcode.Lt) {
+ return Le(arg1, arg0);
+ } else if (op.Op == BinaryOperator.Opcode.Le) {
+ return Lt(arg1, arg0);
+ } else if (op.Op == BinaryOperator.Opcode.Ge) {
+ return Gt(arg1, arg0);
+ } else if (op.Op == BinaryOperator.Opcode.Gt) {
+ return Ge(arg1, arg0);
+ }
+ }
+ }
+
+ return Unary(Token.NoToken, UnaryOperator.Opcode.Not, e1);
+ }
+
+ public static Expr Neg(Expr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return Unary(Token.NoToken, UnaryOperator.Opcode.Neg, e1);
+ }
+
+ public static NAryExpr Imp(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Imp, e1, e2);
+ }
+ public static NAryExpr Iff(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Iff, e1, e2);
+ }
+ public static NAryExpr Add(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Add, e1, e2);
+ }
+ public static NAryExpr Sub(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Sub, e1, e2);
+ }
+ public static NAryExpr Mul(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Mul, e1, e2);
+ }
+ public static NAryExpr Div(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Div, e1, e2);
+ }
+ public static NAryExpr Mod(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Mod, e1, e2);
+ }
+ public static NAryExpr RealDiv(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.RealDiv, e1, e2);
+ }
+ public static NAryExpr FloatDiv(Expr e1, Expr e2)
+ {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.FloatDiv, e1, e2);
+ }
+ public static NAryExpr Pow(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Pow, e1, e2);
+ }
+ public static NAryExpr Subtype(Expr e1, Expr e2) {
+ Contract.Requires(e2 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Binary(BinaryOperator.Opcode.Subtype, e1, e2);
+ }
+
+ public static IdentifierExpr Ident(string name, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
+ return new IdentifierExpr(Token.NoToken, name, type);
+ }
+
+ public static IdentifierExpr Ident(Variable decl) {
+ Contract.Requires(decl != null);
+ Contract.Ensures(Contract.Result<IdentifierExpr>() != null);
+ IdentifierExpr result = new IdentifierExpr(Token.NoToken, decl);
+ return result;
+ }
+
+ public static LiteralExpr Literal(bool value) {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return new LiteralExpr(Token.NoToken, value);
+ }
+ public static LiteralExpr Literal(int value) {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return new LiteralExpr(Token.NoToken, BigNum.FromInt(value));
+ }
+ public static LiteralExpr Literal(BigNum value) {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return new LiteralExpr(Token.NoToken, value);
+ }
+ public static LiteralExpr Literal(BigDec value) {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return new LiteralExpr(Token.NoToken, value);
+ }
+ public static LiteralExpr Literal(BigFloat value)
+ {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return new LiteralExpr(Token.NoToken, value);
+ }
+
+ private static LiteralExpr/*!*/ true_ = Literal(true);
+ public static LiteralExpr/*!*/ True {
+ get {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return true_;
+ }
+ }
+
+ private static LiteralExpr/*!*/ false_ = Literal(false);
+ public static LiteralExpr/*!*/ False {
+ get {
+ Contract.Ensures(Contract.Result<LiteralExpr>() != null);
+ return false_;
+ }
+ }
+
+
+ public static NAryExpr Select(Expr map, params Expr[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(map != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return SelectTok(Token.NoToken, map, args);
+ }
+
+ public static NAryExpr Select(Expr map, List<Expr/*!*/>/*!*/ args) {
+ Contract.Requires(map != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return Select(map, args.ToArray());
+ }
+
+ // use a different name for this variant of the method
+ // (-> some bug prevents overloading in this case)
+ public static NAryExpr SelectTok(IToken x, Expr map, params Expr[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(map != null);
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ List<Expr>/*!*/ allArgs = new List<Expr>();
+ allArgs.Add(map);
+ foreach (Expr/*!*/ a in args) {
+ Contract.Assert(a != null);
+ allArgs.Add(a);
+ }
+ return new NAryExpr(x, new MapSelect(Token.NoToken, args.Length), allArgs);
+ }
+
+ public static NAryExpr Store(Expr map, params Expr[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(map != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ return StoreTok(Token.NoToken, map, args);
+ }
+
+ public static NAryExpr Store(Expr map, List<Expr/*!*/>/*!*/ indexes, Expr rhs) {
+ Contract.Requires(rhs != null);
+ Contract.Requires(map != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ Expr[]/*!*/ allArgs = new Expr[indexes.Count + 1];
+ for (int i = 0; i < indexes.Count; ++i)
+ allArgs[i] = indexes[i];
+ allArgs[indexes.Count] = rhs;
+ return Store(map, allArgs);
+ }
+
+ // use a different name for this variant of the method
+ // (-> some bug prevents overloading in this case)
+ public static NAryExpr/*!*/ StoreTok(IToken x, Expr map, params Expr[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(map != null);
+ Contract.Requires(x != null);
+ Contract.Requires(args.Length > 0); // zero or more indices, plus the value
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+
+ List<Expr>/*!*/ allArgs = new List<Expr>();
+ allArgs.Add(map);
+ foreach (Expr/*!*/ a in args) {
+ Contract.Assert(a != null);
+ allArgs.Add(a);
+ }
+ return new NAryExpr(x, new MapStore(Token.NoToken, args.Length - 1), allArgs);
+ }
+
+ public static NAryExpr CoerceType(IToken x, Expr subexpr, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(subexpr != null);
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.Result<NAryExpr>() != null);
+ List<Expr>/*!*/ args = new List<Expr>();
+ args.Add(subexpr);
+ return new NAryExpr(x, new TypeCoercion(x, type), args);
+ }
+
+ public static Expr BinaryTreeAnd(List<Expr> terms)
+ {
+ return BinaryTreeAnd(terms, 0, terms.Count - 1);
+ }
+
+ private static Expr BinaryTreeAnd(List<Expr> terms, int start, int end)
+ {
+ if (start > end)
+ return Expr.True;
+ if (start == end)
+ return terms[start];
+ if (start + 1 == end)
+ return Expr.And(terms[start], terms[start + 1]);
+ var mid = (start + end) / 2;
+ return Expr.And(BinaryTreeAnd(terms, start, mid), BinaryTreeAnd(terms, mid + 1, end));
+ }
+
+ public static Expr And(IEnumerable<Expr> conjuncts, bool returnNullIfEmpty = false)
+ {
+ Expr result = null;
+ foreach (var c in conjuncts)
+ {
+ if (result != null)
+ {
+ result = LiteralExpr.And(result, c);
+ result.Type = Type.Bool;
+ }
+ else
+ {
+ result = c;
+ result.Type = Type.Bool;
+ }
+ }
+ if (result == null && !returnNullIfEmpty)
+ {
+ result = Expr.True;
+ }
+ return result;
+ }
+ }
+ [ContractClassFor(typeof(Expr))]
+ public abstract class ExprContracts : Expr {
+ public ExprContracts() :base(null, /*immutable=*/ false){
+
+ }
+ public override void Emit(TokenTextWriter wr, int contextBindingStrength, bool fragileContext) {
+ Contract.Requires(wr != null);
+ throw new NotImplementedException();
+ }
+ public override void ComputeFreeVariables(Set freeVars) {
+ Contract.Requires(freeVars != null);
+ throw new NotImplementedException();
+ }
+ public override Type ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+ }
+
+ public class LiteralExpr : Expr {
+ public readonly object/*!*/ Val; // false, true, a BigNum, a BigDec, a BigFloat, or a BvConst
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Val != null);
+ }
+
+ /// <summary>
+ /// Creates a literal expression for the boolean value "b".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="b"></param>
+ public LiteralExpr(IToken/*!*/ tok, bool b, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Val = b;
+ Type = Type.Bool;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ /// <summary>
+ /// Creates a literal expression for the integer value "v".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="v"></param>
+ public LiteralExpr(IToken/*!*/ tok, BigNum v, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Val = v;
+ Type = Type.Int;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ /// <summary>
+ /// Creates a literal expression for the real value "v".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="v"></param>
+ public LiteralExpr(IToken/*!*/ tok, BigDec v, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Val = v;
+ Type = Type.Real;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ /// <summary>
+ /// Creates a literal expression for the floating point value "v".
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="v"></param>
+ public LiteralExpr(IToken/*!*/ tok, BigFloat v, bool immutable = false)
+ : base(tok, immutable)
+ {
+ Contract.Requires(tok != null);
+ Val = v;
+ Type = Type.GetFloatType(v.ExponentSize, v.SignificandSize);
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ /// <summary>
+ /// Creates a literal expression for the bitvector value "v".
+ /// </summary>
+ public LiteralExpr(IToken/*!*/ tok, BigNum v, int b, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(0 <= b);
+ Val = new BvConst(v, b);
+ Type = Type.GetBvType(b);
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is LiteralExpr))
+ return false;
+
+ LiteralExpr other = (LiteralExpr)obj;
+ return object.Equals(this.Val, other.Val);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ if (Immutable)
+ return this.CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ return this.Val.GetHashCode();
+ }
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ if (this.Val is bool) {
+ stream.Write((bool)this.Val ? "true" : "false"); // correct capitalization
+ } else {
+ stream.Write(cce.NonNull(this.Val.ToString()));
+ }
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ // nothing to resolve
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ // no free variables to add
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ this.Type = ShallowType;
+ }
+
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ if (Val is bool) {
+ return Type.Bool;
+ } else if (Val is BigNum) {
+ return Type.Int;
+ } else if (Val is BigDec) {
+ return Type.Real;
+ } else if (Val is BigFloat) {
+ BigFloat temp = (BigFloat)Val;
+ return Type.GetFloatType(temp.ExponentSize, temp.SignificandSize);
+ } else if (Val is BvConst) {
+ return Type.GetBvType(((BvConst)Val).Bits);
+ } else {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // like, where did this value come from?!
+ }
+ }
+ }
+
+ public bool IsFalse {
+ get {
+ return Val is bool && ((bool)Val) == false;
+ }
+ }
+ public bool IsTrue {
+ get {
+ return Val is bool && ((bool)Val) == true;
+ }
+ }
+
+ // should be eliminated after converting everything to BigNums
+ private int asInt {
+ get {
+ return asBigNum.ToIntSafe;
+ }
+ }
+
+ public bool isBigNum {
+ get {
+ return Val is BigNum;
+ }
+ }
+
+ public BigNum asBigNum {
+ get {
+ Contract.Assert(isBigNum);
+ return (BigNum)cce.NonNull(Val);
+ }
+ }
+
+ public bool isBigDec {
+ get {
+ return Val is BigDec;
+ }
+ }
+
+ public bool isBigFloat
+ {
+ get
+ {
+ return Val is BigFloat;
+ }
+ }
+
+ public BigDec asBigDec {
+ get {
+ Contract.Assert(isBigDec);
+ return (BigDec)cce.NonNull(Val);
+ }
+ }
+
+ public BigFloat asBigFloat {
+ get {
+ Contract.Assert(isBigFloat);
+ return (BigFloat)cce.NonNull(Val);
+ }
+ }
+
+ public bool isBool {
+ get {
+ return Val is bool;
+ }
+ }
+
+ public bool asBool {
+ get {
+ Contract.Assert(isBool);
+ return (bool)cce.NonNull(Val);
+ }
+ }
+
+ public bool isBvConst {
+ get {
+ return Val is BvConst;
+ }
+ }
+
+ public BvConst asBvConst {
+ get {
+ Contract.Assert(isBvConst);
+ return (BvConst)cce.NonNull(Val);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitLiteralExpr(this);
+ }
+ }
+
+ public class BvConst {
+ public readonly BigNum Value;
+ public readonly int Bits;
+
+ public BvConst(BigNum v, int b) {
+ Contract.Assert(v.Signum >= 0);
+ Value = v;
+ Bits = b;
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return Value + "bv" + Bits;
+ }
+
+ [Pure]
+ public string ToReadableString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ if (Value > BigNum.FromInt(10000)) {
+ string val = cce.NonNull(Value.ToString("x"));
+ int pos = val.Length % 4;
+ string res = "0x" + val.Substring(0, pos);
+ Contract.Assert(res != null);
+ while (pos < val.Length) {
+ res += "." + val.Substring(pos, 4);
+ pos += 4;
+ }
+ return res + ".bv" + Bits;
+ } else
+ return ToString();
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ BvConst other = obj as BvConst;
+ if (other == null)
+ return false;
+
+ return Bits == other.Bits && Value == other.Value;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ unchecked {
+ return Value.GetHashCode() ^ Bits;
+ }
+ }
+ }
+
+ public class IdentifierExpr : Expr {
+ private string _Name;
+ public string Name { // identifier symbol
+ get {
+ return _Name;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Cannot change Name on Immutable Expr");
+
+ _Name = value;
+ }
+ }
+ private Variable _Decl;
+ public Variable Decl { // identifier declaration
+ get {
+ return _Decl;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Cannot change Decl on Immutable Expr");
+
+ _Decl = value;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ }
+
+
+ /// <summary>
+ /// Creates an unresolved identifier expression. This constructor is intended to be called
+ /// only from within the parser; for use inside the translation, use another constructor, which
+ /// specifies the type of the expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="name"></param>
+ internal IdentifierExpr(IToken/*!*/ tok, string/*!*/ name, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ _Name = name;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+ /// <summary>
+ /// Creates an unresolved identifier expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="name"></param>
+ /// <param name="type"></param>
+ public IdentifierExpr(IToken/*!*/ tok, string/*!*/ name, Type/*!*/ type, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(type != null);
+ _Name = name;
+ Type = type;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ /// <summary>
+ /// Creates a resolved identifier expression.
+ /// </summary>
+ /// <param name="tok"></param>
+ /// <param name="d"></param>
+ public IdentifierExpr(IToken/*!*/ tok, Variable/*!*/ d, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(d != null);
+ _Name = cce.NonNull(d.Name);
+ _Decl = d;
+ Type = d.TypedIdent.Type;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is IdentifierExpr))
+ return false;
+
+ IdentifierExpr other = (IdentifierExpr)obj;
+ return object.Equals(this.Name, other.Name) && object.Equals(this.Decl, other.Decl);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ if (Immutable)
+ return this.CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ int h = this.Name == null ? 0 : this.Name.GetHashCode();
+ h ^= this.Decl == null ? 0 : this.Decl.GetHashCode();
+ return h;
+ }
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds && !stream.UseForComputingChecksums) {
+ stream.Write("{0}^^", this.Decl == null ? "NoDecl" : "h" + this.Decl.GetHashCode());
+ }
+ stream.Write(this, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ if (Decl != null) {
+ // already resolved, but re-resolve type just in case it came from an unresolved type
+ if (Type != null) {
+ Type = Type.ResolveType(rc);
+ }
+ return;
+ }
+ Decl = rc.LookUpVariable(Name);
+ if (Decl == null) {
+ rc.Error(this, "undeclared identifier: {0}", Name);
+ } else if (rc.StateMode == ResolutionContext.State.StateLess && Decl is GlobalVariable) {
+ rc.Error(this, "cannot refer to a global variable in this context: {0}", Name);
+ }
+ if (Type != null) {
+ Type = Type.ResolveType(rc);
+ }
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ Contract.Assume(this.Decl != null);
+ freeVars.Add(Decl);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ if (this.Decl != null) {
+ // sanity check
+ if (Type != null && !Type.Equals(Decl.TypedIdent.Type)) {
+ tc.Error(this, "internal error, shallow-type assignment was done incorrectly, {0}:{1} != {2}",
+ Name, Type, Decl.TypedIdent.Type);
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ Type = Decl.TypedIdent.Type;
+ }
+ }
+
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ Contract.Assert(Type != null);
+ return Type;
+ }
+ }
+
+ public sealed class ConstantFunApp {
+ private IdentifierExpr/*!*/ identifierExpr;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(identifierExpr != null);
+ Contract.Invariant(emptyArgs != null);
+ }
+
+ public IdentifierExpr/*!*/ IdentifierExpr {
+ get {
+ Contract.Requires(IdentifierExpr != null);
+ return identifierExpr;
+ }
+ }
+
+ private static IList/*!*/ emptyArgs = ArrayList.ReadOnly(cce.NonNull((IList/*!*/)new ArrayList()));
+ public IList/*!*/ Arguments {
+ get {
+ Contract.Ensures(Contract.Result<IList>() != null);
+ return emptyArgs;
+ }
+ }
+
+ public ConstantFunApp(IdentifierExpr ie, Constant c) {
+ Contract.Requires(c != null);
+ Contract.Requires(ie != null);
+ this.identifierExpr = ie;
+ }
+
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitIdentifierExpr(this);
+ }
+ }
+
+ public class OldExpr : Expr
+ {
+ private Expr _Expr;
+ public Expr/*!*/ Expr {
+ get {
+ return _Expr;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Cannot change Expr of an Immutable OldExpr");
+
+ _Expr = value;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Expr != null);
+ }
+
+ public OldExpr(IToken/*!*/ tok, Expr/*!*/ expr, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(expr != null);
+ _Expr = expr;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is OldExpr))
+ return false;
+
+ OldExpr other = (OldExpr)obj;
+ return object.Equals(this.Expr, other.Expr);
+ }
+ [Pure]
+ public override int GetHashCode() {
+ if (Immutable)
+ return this.CachedHashCode;
+ else
+ return ComputeHashCode ();
+ }
+ public override int ComputeHashCode() {
+ // FIXME: This is wrong, it's as if the OldExpr node isn't there at all
+ return this.Expr == null ? 0 : this.Expr.GetHashCode();
+ }
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ stream.Write(this, "old(");
+ this.Expr.Emit(stream);
+ stream.Write(")");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ if (rc.StateMode != ResolutionContext.State.Two) {
+ rc.Error(this, "old expressions allowed only in two-state contexts");
+ }
+ Expr.Resolve(rc);
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ Expr.ComputeFreeVariables(freeVars);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ Expr.Typecheck(tc);
+ Type = Expr.Type;
+ }
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Expr.ShallowType;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitOldExpr(this);
+ }
+ }
+ [ContractClass(typeof(IAppliableVisitorContracts<>))]
+ public interface IAppliableVisitor<T> {
+ T Visit(UnaryOperator/*!*/ unaryOperator);
+ T Visit(BinaryOperator/*!*/ binaryOperator);
+ T Visit(FunctionCall/*!*/ functionCall);
+ T Visit(MapSelect/*!*/ mapSelect);
+ T Visit(MapStore/*!*/ mapStore);
+ T Visit(TypeCoercion/*!*/ typeCoercion);
+ T Visit(ArithmeticCoercion/*!*/ arithCoercion);
+ T Visit(IfThenElse/*!*/ ifThenElse);
+ }
+ [ContractClassFor(typeof(IAppliableVisitor<>))]
+ public abstract class IAppliableVisitorContracts<T> : IAppliableVisitor<T> {
+
+ #region IAppliableVisitor<T> Members
+
+ public T Visit(UnaryOperator unaryOperator) {
+ Contract.Requires(unaryOperator != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(BinaryOperator binaryOperator) {
+ Contract.Requires(binaryOperator != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(FunctionCall functionCall) {
+ Contract.Requires(functionCall != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(MapSelect mapSelect) {
+ Contract.Requires(mapSelect != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(MapStore mapStore) {
+ Contract.Requires(mapStore != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(TypeCoercion typeCoercion) {
+ Contract.Requires(typeCoercion != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(ArithmeticCoercion arithCoercion) {
+ Contract.Requires(arithCoercion != null);
+ throw new NotImplementedException();
+ }
+
+ public T Visit(IfThenElse ifThenElse) {
+ Contract.Requires(ifThenElse != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
+ [ContractClass(typeof(IAppliableContracts))]
+ public interface IAppliable {
+ string/*!*/ FunctionName {
+ get;
+ }
+
+ /// <summary>
+ /// Emits to "stream" the operator applied to the given arguments.
+ /// The length of "args" can be anything that the parser allows for this appliable operator
+ /// (but can be nothing else).
+ /// </summary>
+ /// <param name="args"></param>
+ /// <param name="stream"></param>
+ /// <param name="contextBindingStrength"></param>
+ /// <param name="fragileContext"></param>
+ void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream, int contextBindingStrength, bool fragileContext);
+
+ void Resolve(ResolutionContext/*!*/ rc, Expr/*!*/ subjectForErrorReporting);
+
+ /// <summary>
+ /// Requires the object to have been properly resolved.
+ /// </summary>
+ int ArgumentCount {
+ get;
+ }
+
+ /// <summary>
+ /// Typechecks the arguments "args" for the Appliable. If the arguments are
+ /// appropriate, returns the result type; otherwise returns null.
+ /// As result of the type checking, the values of type parameters of the
+ /// appliable can be returned (which are then stored in the NAryExpr and later
+ /// also used in the VCExprAST).
+ /// Requires the object to have been successfully resolved.
+ /// Requires args.Length == ArgumentCount.
+ /// Requires all elements of "args" to have a non-null Type field.
+ /// </summary>
+ /// <param name="args"></param>
+ /// <param name="tc"></param>
+ Type Typecheck(IList<Expr>/*!*/ args, out TypeParamInstantiation/*!*/ tpInstantiation, TypecheckingContext/*!*/ tc);
+
+ // Contract.Requires( Microsoft.SpecSharp.Collections.Reductions.Forall{Expr! arg in args; arg.Type != null});
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ Type/*!*/ ShallowType(IList<Expr>/*!*/ args);
+
+ T Dispatch<T>(IAppliableVisitor<T>/*!*/ visitor);
+ }
+ [ContractClassFor(typeof(IAppliable))]
+ abstract class IAppliableContracts : IAppliable {
+
+ #region IAppliable Members
+
+ public string FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ Contract.Requires(args != null);
+ Contract.Requires(stream != null);
+ throw new NotImplementedException();
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ Contract.Requires(rc != null);
+ Contract.Requires(subjectForErrorReporting != null);
+ throw new NotImplementedException();
+ }
+
+ public int ArgumentCount {
+ get {
+ throw new NotImplementedException();
+ }
+ }
+
+ public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ Contract.Requires(args != null);
+ Contract.Requires(tc != null);
+ Contract.Ensures(Contract.ValueAtReturn(out args) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Ensures(args.Count == Contract.OldValue(args.Count));
+ throw new NotImplementedException();
+ }
+
+ public Type ShallowType(IList<Expr> args) {
+ Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ Contract.Requires(visitor != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
+
+ [ContractClass(typeof(IOverloadedAppliableContracts))]
+ public interface IOverloadedAppliable {
+ void ResolveOverloading(NAryExpr/*!*/ expr);
+ bool DoNotResolveOverloading { get; set; }
+ }
+ [ContractClassFor(typeof(IOverloadedAppliable))]
+ public abstract class IOverloadedAppliableContracts : IOverloadedAppliable {
+
+ #region IOverloadedAppliable Members
+
+ void IOverloadedAppliable.ResolveOverloading(NAryExpr expr) {
+ Contract.Requires(expr != null);
+ throw new NotImplementedException();
+ }
+
+ public bool DoNotResolveOverloading
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ #endregion
+ }
+
+ public class UnaryOperator : IAppliable {
+ private IToken/*!*/ tok;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(tok != null);
+ }
+
+ public enum Opcode {
+ Neg,
+ Not
+ };
+ private Opcode op;
+ public Opcode Op {
+ get {
+ return op;
+ }
+ }
+ public UnaryOperator(IToken tok, Opcode op) {
+ Contract.Requires(tok != null);
+ this.tok = tok;
+ this.op = op;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is UnaryOperator))
+ return false;
+
+ UnaryOperator other = (UnaryOperator)obj;
+ return object.Equals(this.op, other.op);
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (int)this.op;
+ }
+
+ public string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ switch (this.op) {
+ case Opcode.Neg:
+ return "-";
+ case Opcode.Not:
+ return "!";
+ }
+ System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
+ throw new Exception();
+ }
+ }
+
+ public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //Contract.Requires(args != null);
+ stream.SetToken(ref this.tok);
+ Contract.Assert(args.Count == 1);
+ // determine if parens are needed
+ int opBindingStrength = 0x70;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) {
+ stream.Write("(");
+ }
+ stream.Write(FunctionName);
+ cce.NonNull(args[0]).Emit(stream, opBindingStrength, false);
+ if (parensNeeded) {
+ stream.Write(")");
+ }
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ if (rc.TriggerMode && this.op == Opcode.Not) {
+ rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
+ }
+ }
+
+ public int ArgumentCount {
+ get {
+ return 1;
+ }
+ }
+
+ public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out args) != null);
+
+ Contract.Assume(args.Count == 1);
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ Type arg0type = cce.NonNull(cce.NonNull(args[0]).Type);
+ switch (this.op) {
+ case Opcode.Neg:
+ if (arg0type.Unify(Type.Int)) {
+ return Type.Int;
+ }
+ if (arg0type.Unify(Type.Real)) {
+ return Type.Real;
+ }
+ //if (arg0type.Unify(Type.Float)) {
+ //return Type.Float;
+ //}
+ goto BAD_TYPE;
+ case Opcode.Not:
+ if (arg0type.Unify(Type.Bool)) {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ }
+ System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ BAD_TYPE:
+ tc.Error(this.tok, "invalid argument type ({1}) to unary operator {0}",
+ this.FunctionName, arg0type);
+ return null;
+ }
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ switch (this.op) {
+ case Opcode.Neg:
+ return cce.NonNull(cce.NonNull(args[0]).Type);
+ case Opcode.Not:
+ return Type.Bool;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // unexpected unary operator
+ }
+ }
+
+ public object Evaluate(object argument) {
+ if (argument == null) {
+ return null;
+ }
+ switch (this.op) {
+ case Opcode.Neg:
+ if (argument is BigNum) {
+ return -((BigNum)argument);
+ }
+ if (argument is BigDec) {
+ return -((BigDec)argument);
+ }
+ if (argument is BigFloat) {
+ return -((BigFloat)argument);
+ }
+ break;
+ case Opcode.Not:
+ if (argument is bool) {
+ return !((bool)argument);
+ }
+ throw new System.InvalidOperationException("unary Not only applies to bool");
+ }
+ return null; // unreachable
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+ }
+
+ public class BinaryOperator : IAppliable, IOverloadedAppliable {
+ private IToken/*!*/ tok;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(tok != null);
+ }
+
+ public bool DoNotResolveOverloading { get; set; }
+
+ public enum Opcode {
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Mod,
+ RealDiv,
+ FloatDiv,
+ Pow,
+ Eq,
+ Neq,
+ Gt,
+ Ge,
+ Lt,
+ Le,
+ And,
+ Or,
+ Imp,
+ Iff,
+ Subtype
+ };
+ private Opcode op;
+ public Opcode Op {
+ get {
+ return op;
+ }
+ }
+ public BinaryOperator(IToken tok, Opcode op) {
+ Contract.Requires(tok != null);
+ this.tok = tok;
+ this.op = op;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is BinaryOperator))
+ return false;
+
+ BinaryOperator other = (BinaryOperator)obj;
+ return object.Equals(this.op, other.op);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return (int)this.op << 1;
+ }
+
+ public string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ switch (this.op) {
+ case Opcode.Add:
+ return "+";
+ case Opcode.Sub:
+ return "-";
+ case Opcode.Mul:
+ return "*";
+ case Opcode.Div:
+ return "div";
+ case Opcode.Mod:
+ return "mod";
+ case Opcode.RealDiv:
+ return "/";
+ case Opcode.Pow:
+ return "**";
+ case Opcode.Eq:
+ return "==";
+ case Opcode.Neq:
+ return "!=";
+ case Opcode.Gt:
+ return ">";
+ case Opcode.Ge:
+ return ">=";
+ case Opcode.Lt:
+ return "<";
+ case Opcode.Le:
+ return "<=";
+ case Opcode.And:
+ return "&&";
+ case Opcode.Or:
+ return "||";
+ case Opcode.Imp:
+ return "==>";
+ case Opcode.Iff:
+ return "<==>";
+ case Opcode.Subtype:
+ return "<:";
+ }
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
+ throw new Exception();
+ }
+ }
+
+ public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //Contract.Requires(args != null);
+ stream.SetToken(ref this.tok);
+ Contract.Assert(args.Count == 2);
+ // determine if parens are needed
+ int opBindingStrength;
+ bool fragileLeftContext = false; // false means "allow same binding power on left without parens"
+ bool fragileRightContext = false; // false means "allow same binding power on right without parens"
+ switch (this.op) {
+ case Opcode.Add:
+ opBindingStrength = 0x40;
+ break;
+ case Opcode.Sub:
+ opBindingStrength = 0x40;
+ fragileRightContext = true;
+ break;
+ case Opcode.Mul:
+ opBindingStrength = 0x50;
+ break;
+ case Opcode.Div:
+ opBindingStrength = 0x50;
+ fragileRightContext = true;
+ break;
+ case Opcode.Mod:
+ opBindingStrength = 0x50;
+ fragileRightContext = true;
+ break;
+ case Opcode.RealDiv:
+ opBindingStrength = 0x50;
+ fragileRightContext = true;
+ break;
+ case Opcode.Pow:
+ opBindingStrength = 0x60;
+ fragileRightContext = true;
+ break;
+ case Opcode.Eq:
+ case Opcode.Neq:
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ case Opcode.Subtype:
+ opBindingStrength = 0x30;
+ fragileLeftContext = fragileRightContext = true;
+ break;
+ case Opcode.And:
+ opBindingStrength = 0x20;
+ break;
+ case Opcode.Or:
+ opBindingStrength = 0x21;
+ break;
+ case Opcode.Imp:
+ opBindingStrength = 0x10;
+ fragileLeftContext = true;
+ break;
+ case Opcode.Iff:
+ opBindingStrength = 0x00;
+ break;
+ default:
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
+ opBindingStrength = -1; // to please compiler, which refuses to consider whether or not all enumeration cases have been considered!
+ break;
+ }
+ int opBS = opBindingStrength & 0xF0;
+ int ctxtBS = contextBindingStrength & 0xF0;
+ bool parensNeeded = opBS < ctxtBS ||
+ (opBS == ctxtBS && (opBindingStrength != contextBindingStrength || fragileContext));
+
+ var pop = stream.push(FunctionName);
+ if (parensNeeded) {
+ stream.Write("(");
+ }
+ cce.NonNull(args[0]).Emit(stream, opBindingStrength, fragileLeftContext);
+ stream.sep();
+ stream.Write(" {0} ", FunctionName);
+ cce.NonNull(args[1]).Emit(stream, opBindingStrength, fragileRightContext);
+ if (parensNeeded) {
+ stream.Write(")");
+ }
+ stream.pop(pop);
+ }
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ if (rc.TriggerMode) {
+ switch (this.op) {
+ case Opcode.Add:
+ case Opcode.Sub:
+ case Opcode.Mul:
+ case Opcode.Div:
+ case Opcode.Mod:
+ case Opcode.RealDiv:
+ case Opcode.Pow:
+ case Opcode.Neq: // Neq is allowed, but not Eq
+ case Opcode.Subtype:
+ // These are fine
+ break;
+
+ case Opcode.Eq:
+ rc.Error(subjectForErrorReporting, "equality is not allowed in triggers");
+ break;
+
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ rc.Error(subjectForErrorReporting, "arithmetic comparisons are not allowed in triggers");
+ break;
+
+ case Opcode.And:
+ case Opcode.Or:
+ case Opcode.Imp:
+ case Opcode.Iff:
+ rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
+ break;
+
+ default:
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + this.op.ToString());
+ break;
+ }
+ }
+ }
+ public int ArgumentCount {
+ get {
+ return 2;
+ }
+ }
+ public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Ensures(args != null);
+ Contract.Assert(args.Count == 2);
+ // the default; the only binary operator with a type parameter is equality, but right
+ // we don't store this parameter because it does not appear necessary
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ Expr arg0 = cce.NonNull(args[0]);
+ Expr arg1 = cce.NonNull(args[1]);
+ Type arg0type = cce.NonNull(arg0.Type);
+ Type arg1type = cce.NonNull(arg1.Type);
+ switch (this.op) {
+ case Opcode.Add:
+ case Opcode.Sub:
+ case Opcode.Mul:
+ if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
+ return Type.Int;
+ }
+ if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
+ return Type.Real;
+ }
+ if (arg0type.IsFloat && arg0type.Unify(arg1type)) {
+ return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa);
+ }
+ if (arg1type.IsFloat && arg1type.Unify(arg0type)) {
+ return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa);
+ }
+ goto BAD_TYPE;
+ case Opcode.Div:
+ case Opcode.Mod:
+ if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
+ return Type.Int;
+ }
+ goto BAD_TYPE;
+ case Opcode.RealDiv:
+ if ((arg0type.Unify(Type.Int) || arg0type.Unify(Type.Real)) &&
+ (arg1type.Unify(Type.Int) || arg1type.Unify(Type.Real))) {
+ return Type.Real;
+ }
+ if (arg0type.IsFloat && arg0type.Unify(arg1type)) {
+ return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa);
+ }
+ if (arg1type.IsFloat && arg1type.Unify(arg0type)) {
+ return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa);
+ }
+ goto BAD_TYPE;
+ case Opcode.Pow:
+ if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
+ return Type.Real;
+ }
+ goto BAD_TYPE;
+ case Opcode.Eq:
+ case Opcode.Neq:
+ // Comparison is allowed if the argument types are unifiable
+ // (i.e., if there is any chance that the values of the arguments are
+ // in the same domain)
+ if (arg0type.Equals(arg1type)) {
+ // quick path
+ return Type.Bool;
+ }
+ List<TypeVariable>/*!*/ unifiable = new List<TypeVariable>();
+ unifiable.AddRange(arg0type.FreeVariables);
+ unifiable.AddRange(arg1type.FreeVariables);
+
+ if (arg0type.Unify(arg1type, unifiable, new Dictionary<TypeVariable/*!*/, Type/*!*/>()))
+ return Type.Bool;
+ goto BAD_TYPE;
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
+ return Type.Bool;
+ }
+ if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) {
+ return Type.Bool;
+ }
+ if ((arg0type.IsFloat && arg0type.Unify(arg1type)) || (arg1type.IsFloat && arg1type.Unify(arg0type))) {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ case Opcode.And:
+ case Opcode.Or:
+ case Opcode.Imp:
+ case Opcode.Iff:
+ if (arg0type.Unify(Type.Bool) && arg1type.Unify(Type.Bool)) {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ case Opcode.Subtype:
+ // Subtype is polymorphically typed and can compare things of
+ // arbitrary types (but both arguments must have the same type)
+ if (arg0type.Unify(arg1type)) {
+ return Type.Bool;
+ }
+ goto BAD_TYPE;
+ }
+ System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ BAD_TYPE:
+ tc.Error(this.tok, "invalid argument types ({1} and {2}) to binary operator {0}", this.FunctionName, arg0type, arg1type);
+ return null;
+ }
+
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ switch (this.op) {
+ case Opcode.Add:
+ case Opcode.Sub:
+ case Opcode.Mul:
+ return cce.NonNull(args[0]).ShallowType;
+
+ case Opcode.Div:
+ case Opcode.Mod:
+ return Type.Int;
+
+ case Opcode.RealDiv:
+ case Opcode.Pow:
+ return Type.Real;
+
+ case Opcode.Eq:
+ case Opcode.Neq:
+ case Opcode.Gt:
+ case Opcode.Ge:
+ case Opcode.Lt:
+ case Opcode.Le:
+ case Opcode.And:
+ case Opcode.Or:
+ case Opcode.Imp:
+ case Opcode.Iff:
+ case Opcode.Subtype:
+ return Type.Bool;
+
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // unexpected binary operator
+ }
+ }
+
+ public void ResolveOverloading(NAryExpr expr) {
+ //Contract.Requires(expr != null);
+
+ // immutable Expr must not be modified
+ if (DoNotResolveOverloading || expr.Immutable)
+ {
+ return;
+ }
+
+ Expr arg0 = cce.NonNull(expr.Args[0]);
+ Expr arg1 = cce.NonNull(expr.Args[1]);
+ switch (op) {
+ case Opcode.Eq:
+ if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool) {
+ expr.Fun = new BinaryOperator(tok, Opcode.Iff);
+ }
+ break;
+ case Opcode.Neq:
+ if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool) {
+ expr.Fun = new BinaryOperator(tok, Opcode.Iff);
+ var arg1New = new NAryExpr(expr.tok, new UnaryOperator(tok, UnaryOperator.Opcode.Not), new List<Expr> { arg1 });
+
+ // ugly ... there should be some more general approach,
+ // e.g., to typecheck the whole expression again
+ arg1New.Type = Type.Bool;
+ arg1New.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+
+ expr.Args[1] = arg1New;
+ }
+ break;
+ }
+ }
+
+ public object Evaluate(object e1, object e2) {
+ if (e1 == null || e2 == null) {
+ return null;
+ }
+
+ switch (this.op) {
+ case Opcode.Add:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) + ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) + ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) + ((BigFloat)e2);
+ }
+ break;
+ case Opcode.Sub:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) - ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) - ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) - ((BigFloat)e2);
+ }
+ break;
+ case Opcode.Mul:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) * ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) * ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) * ((BigFloat)e2);
+ }
+ break;
+ case Opcode.Div:
+ if (e1 is BigNum && e2 is BigNum) {
+ return /* TODO: right semantics? */ ((BigNum)e1) / ((BigNum)e2);
+ }
+ break;
+ case Opcode.Mod:
+ if (e1 is BigNum && e2 is BigNum) {
+ return /* TODO: right semantics? */ ((BigNum)e1) % ((BigNum)e2);
+ }
+ break;
+ case Opcode.RealDiv:
+ // TODO: add partial evaluation fro real division
+ break;
+ case Opcode.FloatDiv:
+ //TODO: add float division
+ break;
+ case Opcode.Pow:
+ // TODO: add partial evaluation fro real exponentiation
+ break;
+ case Opcode.Lt:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) < ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) < ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) < ((BigFloat)e2);
+ }
+ break;
+ case Opcode.Le:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) <= ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) <= ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) <= ((BigFloat)e2);
+ }
+ break;
+ case Opcode.Gt:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) > ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) > ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) > ((BigFloat)e2);
+ }
+ break;
+ case Opcode.Ge:
+ if (e1 is BigNum && e2 is BigNum) {
+ return ((BigNum)e1) >= ((BigNum)e2);
+ }
+ if (e1 is BigDec && e2 is BigDec) {
+ return ((BigDec)e1) >= ((BigDec)e2);
+ }
+ if (e1 is BigFloat && e2 is BigFloat) {
+ return ((BigFloat)e1) >= ((BigFloat)e2);
+ }
+ break;
+
+ case Opcode.And:
+ if (e1 is bool && e2 is bool) {
+ return (bool)e1 && (bool)e2;
+ }
+ break;
+ case Opcode.Or:
+ if (e1 is bool && e2 is bool) {
+ return (bool)e1 || (bool)e2;
+ }
+ break;
+ case Opcode.Imp:
+ if (e1 is bool && e2 is bool) {
+ return !(bool)e1 || (bool)e2;
+ }
+ break;
+ case Opcode.Iff:
+ if (e1 is bool && e2 is bool) {
+ return e1 == e2;
+ }
+ break;
+
+ case Opcode.Eq:
+ return Equals(e1, e2);
+ case Opcode.Neq:
+ return !Equals(e1, e2);
+
+ case Opcode.Subtype:
+ throw new System.NotImplementedException();
+ }
+ throw new System.InvalidOperationException("bad types to binary operator " + this.op);
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+
+ }
+
+ public class FunctionCall : IAppliable {
+ private IdentifierExpr/*!*/ name;
+ public Function Func;
+ public FunctionCall(IdentifierExpr name) {
+ Contract.Requires(name != null);
+ this.name = name;
+ }
+ public FunctionCall(Function f) {
+ Contract.Requires(f != null);
+ this.Func = f;
+ this.name = new IdentifierExpr(Token.NoToken, f.Name);
+
+ // We need set the type of this IdentifierExpr so ShallowType() works
+ Debug.Assert(f.OutParams.Count > 0);
+ this.name.Type = f.OutParams[0].TypedIdent.Type;
+ }
+ public string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this.name.Name;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(name != null);
+ }
+
+ public FunctionCall createUnresolvedCopy()
+ {
+ return new FunctionCall(new IdentifierExpr(name.tok, name.Name, name.Type));
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return name.Name;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ FunctionCall fc = other as FunctionCall;
+ return fc != null && this.Func == fc.Func;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ Contract.Assume(this.Func != null);
+ return Func.GetHashCode();
+ }
+
+ virtual public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //Contract.Requires(args != null);
+
+ if (stream.UseForComputingChecksums && Func.OriginalLambdaExprAsString != null)
+ {
+ stream.Write(Func.OriginalLambdaExprAsString);
+ }
+ else
+ {
+ this.name.Emit(stream, 0xF0, false);
+ }
+ if (stream.UseForComputingChecksums)
+ {
+ var c = Func.DependencyChecksum;
+ if (c != null)
+ {
+ stream.Write(string.Format("[dependency_checksum:{0}]", c));
+ }
+ }
+ stream.Write("(");
+ args.Emit(stream);
+ stream.Write(")");
+ }
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ if (Func != null) {
+ // already resolved
+ return;
+ }
+ Func = rc.LookUpProcedure(name.Name) as Function;
+ if (Func == null) {
+ rc.Error(this.name, "use of undeclared function: {0}", name.Name);
+ }
+ else if (name.Type == null) {
+ // We need set the type of this IdentifierExpr so ShallowType() works
+ Debug.Assert(name.Type == null);
+ Debug.Assert(Func.OutParams.Count > 0);
+ name.Type = Func.OutParams[0].TypedIdent.Type;
+ }
+ }
+ public virtual int ArgumentCount {
+ get {
+ Contract.Assume(Func != null); // ArgumentCount requires object to be properly resolved.
+ return Func.InParams.Count;
+ }
+ }
+ public virtual Type Typecheck(IList<Expr> actuals, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(actuals != null);
+ Contract.Ensures(Contract.ValueAtReturn(out actuals) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Assume(this.Func != null);
+ Contract.Assume(actuals.Count == Func.InParams.Count);
+ Contract.Assume(Func.OutParams.Count == 1);
+
+ List<Type/*!*/>/*!*/ resultingTypeArgs;
+ List<Type> actualResultType =
+ Type.CheckArgumentTypes(Func.TypeParameters,
+ out resultingTypeArgs,
+ new List<Type>(Func.InParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ actuals,
+ new List<Type>(Func.OutParams.Select(Item => Item.TypedIdent.Type).ToArray()),
+ null,
+ // we need some token to report a possibly wrong number of
+ // arguments
+ actuals.Count > 0 ? cce.NonNull(actuals[0]).tok : Token.NoToken,
+ "application of " + name.Name,
+ tc);
+
+ if (actualResultType == null) {
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ } else {
+ Contract.Assert(actualResultType.Count == 1);
+ tpInstantiation =
+ SimpleTypeParamInstantiation.From(Func.TypeParameters, resultingTypeArgs);
+ return actualResultType[0];
+ }
+ }
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assume(name.Type != null);
+ return name.Type;
+ }
+
+ public virtual T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+ }
+
+ public class TypeCoercion : IAppliable {
+ private IToken/*!*/ tok;
+ public Type/*!*/ Type;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(tok != null);
+ }
+
+ public TypeCoercion(IToken tok, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(tok != null);
+ this.tok = tok;
+ this.Type = type;
+ }
+
+ public override bool Equals(object obj) {
+ TypeCoercion other = obj as TypeCoercion;
+ if (other == null) {
+ return false;
+ } else {
+ return object.Equals(Type, other.Type);
+ }
+ }
+
+
+
+ public
+ string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return ":";
+ }
+ }
+
+ public void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
+ int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(stream != null);
+ stream.SetToken(ref this.tok);
+ Contract.Assert(args.Count == 1);
+ // determine if parens are needed
+ int opBindingStrength = 0x80;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded)
+ stream.Write("(");
+
+ cce.NonNull(args[0]).Emit(stream, opBindingStrength, false);
+ stream.Write("{0} ", FunctionName);
+ Type.Emit(stream, 0);
+
+ if (parensNeeded)
+ stream.Write(")");
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ this.Type = this.Type.ResolveType(rc);
+ }
+
+ public int ArgumentCount {
+ get {
+ return 1;
+ }
+ }
+
+ public Type Typecheck(IList<Expr>/*!*/ args,
+ out TypeParamInstantiation/*!*/ tpInstantiation,
+ TypecheckingContext/*!*/ tc) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(tc != null);
+ Contract.Ensures(args != null);
+
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+
+ Contract.Assume(args.Count == 1);
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+
+ if (!this.Type.Unify(cce.NonNull(cce.NonNull(args[0]).Type)))
+ tc.Error(this.tok, "{0} cannot be coerced to {1}",
+ cce.NonNull(args[0]).Type, this.Type);
+ return this.Type;
+ }
+
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.Type;
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+
+ }
+
+ public class ArithmeticCoercion : IAppliable {
+ public enum CoercionType {
+ ToInt,
+ ToReal,
+ ToFloat
+ }
+
+ private IToken/*!*/ tok;
+ public readonly CoercionType Coercion;
+ private readonly string name;
+ private readonly Type type;
+ private readonly Type argType;
+ private readonly Type argType2;
+ private readonly int hashCode;
+
+ public ArithmeticCoercion(IToken tok, CoercionType coercion) {
+ this.tok = tok;
+ this.Coercion = coercion;
+
+ switch (coercion) {
+ case CoercionType.ToInt:
+ this.name = "int";
+ this.type = Type.Int;
+ this.argType = Type.Real;
+ this.hashCode = 1;
+ break;
+ case CoercionType.ToReal:
+ this.name = "real";
+ this.type = Type.Real;
+ this.argType = Type.Int;
+ this.hashCode = 2;
+ break;
+ default:
+ Contract.Assert(false);
+ break;
+ }
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this.name;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ ArithmeticCoercion ac = other as ArithmeticCoercion;
+ return ac != null && this.Coercion == ac.Coercion;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.hashCode;
+ }
+
+ public string/*!*/ FunctionName {
+ get {
+ return this.name;
+ }
+ }
+
+ public int ArgumentCount {
+ get {
+ return 1;
+ }
+ }
+
+ virtual public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //Contract.Requires(args != null);
+ stream.Write(this.name);
+ stream.Write("(");
+ args.Emit(stream);
+ stream.Write(")");
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ }
+
+ public virtual Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(args != null);
+ Contract.Ensures(args != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+
+ Contract.Assert(args.Count == 1);
+
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+
+ if (!(cce.NonNull(cce.NonNull(args[0]).Type).Unify(argType) || cce.NonNull(cce.NonNull(args[0]).Type).Unify(argType2)))
+ {
+ tc.Error(this.tok, "argument type {0} does not match expected type {1} or type {2}", cce.NonNull(args[0]).Type, this.argType, this.argType2);
+ }
+
+ return this.type;
+ }
+
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.type;
+ }
+
+ public virtual T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+ }
+
+ public class NAryExpr : Expr {
+ [Additive]
+ [Peer]
+ private IAppliable _Fun;
+ public IAppliable/*!*/ Fun {
+ get {
+ return _Fun;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Cannot change Function used by Immutable NAryExpr");
+
+ _Fun = value;
+ }
+ }
+ private List<Expr> _Args;
+ public IList<Expr> Args {
+ get {
+ if (Immutable)
+ return _Args.AsReadOnly();
+ else
+ return _Args;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Cannot change Args of Immutable NAryExpr");
+
+ _Args = value as List<Expr>;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Fun != null);
+ Contract.Invariant(Args != null);
+ }
+
+
+ // The instantiation of type parameters that is determined during type checking.
+ // Which type parameters are available depends on the IAppliable
+ public TypeParamInstantiation TypeParameters = null;
+
+ [Captured]
+ public NAryExpr(IToken/*!*/ tok, IAppliable/*!*/ fun, IList<Expr>/*!*/ args, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(fun != null);
+ Contract.Requires(args != null);
+ _Fun = fun;
+ Contract.Assert(Contract.ForAll(0, args.Count, index => args[index] != null));
+ if (immutable) {
+ // We need to make a new list because the client might be holding
+ // references to the list that they gave us which could be used to
+ // circumvent the immutability enforcement
+ _Args = new List<Expr>(args);
+ CachedHashCode = ComputeHashCode();
+ } else {
+ if (args is List<Expr>) {
+ // Preserve NAryExpr's old behaviour, we take ownership of the List<Expr>.
+ // We can only do this if the type matches
+ _Args = args as List<Expr>;
+ }
+ else {
+ // Otherwise we must make a copy
+ _Args = new List<Expr> (args);
+ }
+ }
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is NAryExpr))
+ return false;
+
+ NAryExpr other = (NAryExpr)obj;
+ return object.Equals(this.Fun, other.Fun) && this.Args.SequenceEqual(other.Args);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ if (Immutable)
+ return this.CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ int h = this.Fun.GetHashCode();
+ // DO NOT USE Args.GetHashCode() because that uses Object.GetHashCode() which uses references
+ // We want structural equality
+ foreach (var arg in Args) {
+ h = (97*h) + arg.GetHashCode();
+ }
+ return h;
+ }
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ Fun.Emit(Args, stream, contextBindingStrength, fragileContext);
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Fun.Resolve(rc, this);
+ foreach (Expr/*!*/ e in Args) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+ }
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ foreach (Expr/*!*/ e in Args) {
+ Contract.Assert(e != null);
+ e.ComputeFreeVariables(freeVars);
+ }
+ // also add the free type variables
+ if (TypeParameters != null) {
+ foreach (TypeVariable/*!*/ var in TypeParameters.FormalTypeParams) {
+ Contract.Assert(var != null);
+ foreach (TypeVariable/*!*/ w in TypeParameters[var].FreeVariables) {
+ Contract.Assert(w != null);
+ freeVars.Add(w);
+ }
+ }
+ }
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ int prevErrorCount = tc.ErrorCount;
+ foreach (Expr/*!*/ e in Args) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+ if (Fun.ArgumentCount != Args.Count) {
+ tc.Error(this, "wrong number of arguments to function: {0} ({1} instead of {2})",
+ Fun.FunctionName, Args.Count, Fun.ArgumentCount);
+ } else if (tc.ErrorCount == prevErrorCount &&
+ // if the type parameters are set, this node has already been
+ // typechecked and does not need to be checked again
+ TypeParameters == null) {
+ TypeParamInstantiation tpInsts;
+ Type = Fun.Typecheck(Args, out tpInsts, tc); // Make sure we pass Args so if this Expr is immutable it is protected
+ TypeParameters = tpInsts;
+ }
+ IOverloadedAppliable oa = Fun as IOverloadedAppliable;
+ if (oa != null) {
+ oa.ResolveOverloading(this);
+ }
+ if (Type == null) {
+ // set Type to some non-null value
+ Type = new TypeProxy(this.tok, "type_checking_error");
+ }
+ }
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Fun.ShallowType(Args);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitNAryExpr(this);
+ }
+ }
+
+ public class MapSelect : IAppliable {
+
+ public readonly int Arity;
+ private readonly IToken/*!*/ tok;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(tok != null);
+ }
+
+
+ public MapSelect(IToken tok, int arity) {
+ Contract.Requires(tok != null);
+ this.tok = tok;
+ this.Arity = arity;
+ }
+
+ public string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return "MapSelect";
+ }
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (!(obj is MapSelect))
+ return false;
+
+ MapSelect other = (MapSelect)obj;
+ return this.Arity == other.Arity;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return Arity.GetHashCode() * 2823;
+ }
+
+ public void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
+ int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(stream != null);
+ Contract.Assume(args.Count == Arity + 1);
+ Emit(args, stream, contextBindingStrength, fragileContext, false);
+ }
+
+ public static void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
+ int contextBindingStrength, bool fragileContext,
+ bool withRhs) {
+ Contract.Requires(args != null);
+ Contract.Requires(stream != null);
+ const int opBindingStrength = 0x90;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) {
+ stream.Write("(");
+ }
+ cce.NonNull(args[0]).Emit(stream, opBindingStrength, false);
+ stream.Write("[");
+
+ string sep = "";
+ int lastIndex = withRhs ? args.Count - 1 : args.Count;
+ for (int i = 1; i < lastIndex; ++i) {
+ stream.Write(sep);
+ sep = ", ";
+ cce.NonNull(args[i]).Emit(stream);
+ }
+
+ if (withRhs) {
+ stream.Write(" := ");
+ cce.NonNull(args.Last()).Emit(stream);
+ }
+
+ stream.Write("]");
+ if (parensNeeded) {
+ stream.Write(")");
+ }
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ // PR: nothing?
+ }
+
+ public int ArgumentCount {
+ get {
+ return Arity + 1;
+ }
+ }
+
+ // it is assumed that each of the arguments has already been typechecked
+ public static Type Typecheck(Type/*!*/ mapType,
+ // we just pass an Absy, because in
+ // the AssignCmd maps can also be
+ // represented by non-expressions
+ Absy/*!*/ map,
+ List<Expr>/*!*/ indexes,
+ // the type parameters, in this context, are the parameters of the
+ // potentially polymorphic map type. Because it might happen that
+ // the whole map type is unknown and represented using a MapTypeProxy,
+ // the instantiations given in the following out-parameter are subject
+ // to change if further unifications are done.
+ out TypeParamInstantiation/*!*/ tpInstantiation,
+ TypecheckingContext/*!*/ tc,
+ IToken/*!*/ typeCheckingSubject,
+ string/*!*/ opName) {
+ Contract.Requires(mapType != null);
+ Contract.Requires(map != null);
+ Contract.Requires(indexes != null);
+ Contract.Requires(tc != null);
+ Contract.Requires(typeCheckingSubject != null);
+ Contract.Requires(opName != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+
+ mapType = mapType.Expanded;
+ if (mapType.IsMap && mapType.MapArity != indexes.Count) {
+ tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1} instead of {2}",
+ opName, indexes.Count, mapType.MapArity);
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ } else if (!mapType.Unify(new MapTypeProxy(map.tok, "select", indexes.Count))) {
+ tc.Error(map.tok, "{0} applied to a non-map: {1}", opName, map);
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ }
+ mapType = TypeProxy.FollowProxy(mapType);
+
+ if (mapType is MapType) {
+ MapType mt = (MapType)mapType;
+ return mt.CheckArgumentTypes(indexes, out tpInstantiation,
+ typeCheckingSubject, opName, tc);
+ } else {
+ MapTypeProxy mt = (MapTypeProxy)mapType;
+ return mt.CheckArgumentTypes(indexes, out tpInstantiation,
+ typeCheckingSubject, opName, tc);
+ }
+ }
+
+ public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Assume(args.Count == Arity + 1);
+
+ // FIXME: Wny are we passing a copy?
+ List<Expr> actualArgs = new List<Expr>();
+ for (int i = 1; i < args.Count; ++i)
+ actualArgs.Add(args[i]);
+
+ return Typecheck(cce.NonNull(cce.NonNull(args[0]).Type), cce.NonNull(args[0]),
+ actualArgs, out tpInstantiation, tc, this.tok, "map select");
+ }
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Expr a0 = cce.NonNull(args[0]);
+ Type a0Type = a0.ShallowType;
+ if (a0Type == null || !a0Type.IsMap) {
+ // we are unable to determine the type of the select, so just return an arbitrary type
+ return Type.Int;
+ }
+ MapType mapType = a0Type.AsMap;
+ List<Type> actualArgTypes = new List<Type>();
+ for (int i = 1; i < args.Count; ++i) {
+ actualArgTypes.Add(cce.NonNull(args[i]).ShallowType);
+ }
+ return Type.InferValueType(mapType.TypeParameters, mapType.Arguments, mapType.Result, actualArgTypes);
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+ }
+
+ public class MapStore : IAppliable {
+
+ public readonly int Arity;
+ public readonly IToken/*!*/ tok;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(tok != null);
+ }
+
+
+ public MapStore(IToken tok, int arity) {
+ Contract.Requires(tok != null);
+ this.tok = tok;
+ this.Arity = arity;
+ }
+
+ public string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return "MapStore";
+ }
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (!(obj is MapStore))
+ return false;
+
+ MapStore other = (MapStore)obj;
+ return this.Arity == other.Arity;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return Arity.GetHashCode() * 28231;
+ }
+
+ public void Emit(IList<Expr>/*!*/ args, TokenTextWriter/*!*/ stream,
+ int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(stream != null);
+ Contract.Assert(args.Count == Arity + 2);
+ MapSelect.Emit(args, stream, contextBindingStrength, fragileContext, true);
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ // PR: nothing?
+ }
+
+ public int ArgumentCount {
+ get {
+ return Arity + 2;
+ }
+ }
+
+ // it is assumed that each of the arguments has already been typechecked
+ public static Type Typecheck(IList<Expr>/*!*/ args, out TypeParamInstantiation/*!*/ tpInstantiation,
+ TypecheckingContext/*!*/ tc,
+ IToken/*!*/ typeCheckingSubject,
+ string/*!*/ opName) {
+ Contract.Requires(args != null);
+ Contract.Requires(tc != null);
+ Contract.Requires(typeCheckingSubject != null);
+ Contract.Requires(opName != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+
+ // part of the type checking works exactly as for MapSelect
+ List<Expr> selectArgs = new List<Expr>();
+ for (int i = 1; i < args.Count - 1; ++i)
+ selectArgs.Add(args[i]);
+ Type resultType =
+ MapSelect.Typecheck(cce.NonNull(cce.NonNull(args[0]).Type), cce.NonNull(args[0]),
+ selectArgs, out tpInstantiation, tc, typeCheckingSubject, opName);
+
+ // check the the rhs has the right type
+ if (resultType == null) {
+ // error messages have already been created by MapSelect.Typecheck
+ return null;
+ }
+ Type rhsType = cce.NonNull(cce.NonNull(args.Last()).Type);
+ if (!resultType.Unify(rhsType)) {
+ tc.Error(cce.NonNull(args.Last()).tok,
+ "right-hand side in {0} with wrong type: {1} (expected: {2})",
+ opName, rhsType, resultType);
+ return null;
+ }
+
+ return cce.NonNull(args[0]).Type;
+ }
+
+ public Type Typecheck(IList<Expr>/*!*/ args,
+ out TypeParamInstantiation/*!*/ tpInstantiation,
+ TypecheckingContext/*!*/ tc) {
+ //Contract.Requires(args != null);
+ //Contract.Requires(tc != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out args) != null);
+ Contract.Assert(args.Count == Arity + 2);
+ return Typecheck(args, out tpInstantiation, tc, this.tok, "map store");
+ }
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return cce.NonNull(args[0]).ShallowType;
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+ }
+
+
+ public class IfThenElse : IAppliable {
+
+ private IToken/*!*/ _tok;
+
+ public IToken/*!*/ tok
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IToken>() != null);
+ return this._tok;
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ this._tok = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this._tok != null);
+ }
+
+ public IfThenElse(IToken tok) {
+ Contract.Requires(tok != null);
+ this._tok = tok;
+ }
+
+ public string/*!*/ FunctionName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return "if-then-else";
+ }
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (!(obj is IfThenElse))
+ return false;
+ return true;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return 1;
+ }
+
+ public void Emit(IList<Expr> args, TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //Contract.Requires(args != null);
+ stream.SetToken(this);
+ Contract.Assert(args.Count == 3);
+ stream.push();
+ stream.Write("(if ");
+ cce.NonNull(args[0]).Emit(stream, 0x00, false);
+ stream.sep();
+ stream.Write(" then ");
+ cce.NonNull(args[1]).Emit(stream, 0x00, false);
+ stream.sep();
+ stream.Write(" else ");
+ cce.NonNull(args[2]).Emit(stream, 0x00, false);
+ stream.Write(")");
+ stream.pop();
+ }
+
+ public void Resolve(ResolutionContext rc, Expr subjectForErrorReporting) {
+ //Contract.Requires(subjectForErrorReporting != null);
+ //Contract.Requires(rc != null);
+ // PR: nothing?
+ }
+
+ public int ArgumentCount {
+ get {
+ return 3;
+ }
+ }
+
+ public Type Typecheck(IList<Expr> args, out TypeParamInstantiation tpInstantiation, TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ //Contract.Requires(args != null);
+ Contract.Ensures(args != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ Contract.Assert(args.Count == 3);
+ // the default; the only binary operator with a type parameter is equality, but right
+ // we don't store this parameter because it does not appear necessary
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ Expr arg0 = cce.NonNull(args[0]);
+ Expr arg1 = cce.NonNull(args[1]);
+ Expr arg2 = cce.NonNull(args[2]);
+
+ if (!cce.NonNull(arg0.Type).Unify(Type.Bool)) {
+ tc.Error(this.tok, "the first argument to if-then-else should be bool, not {0}", arg0.Type);
+ } else if (!cce.NonNull(arg1.Type).Unify(cce.NonNull(arg2.Type))) {
+ tc.Error(this.tok, "branches of if-then-else have incompatible types {0} and {1}", arg1.Type, arg2.Type);
+ } else {
+ return arg1.Type;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
+ /// </summary>
+ public Type ShallowType(IList<Expr> args) {
+ //Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return cce.NonNull(args[1]).ShallowType;
+ }
+
+ public T Dispatch<T>(IAppliableVisitor<T> visitor) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this);
+ }
+ }
+
+
+
+ public class CodeExpr : Expr {
+ public List<Variable>/*!*/ LocVars;
+ [Rep]
+ public List<Block/*!*/>/*!*/ Blocks;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(LocVars != null);
+ Contract.Invariant(cce.NonNullElements(Blocks));
+ }
+
+ public CodeExpr(List<Variable>/*!*/ localVariables, List<Block/*!*/>/*!*/ blocks, bool immutable=false)
+ : base(Token.NoToken, immutable) {
+ Contract.Requires(localVariables != null);
+ Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Requires(0 < blocks.Count);
+ LocVars = localVariables;
+ Blocks = blocks;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ // FIXME: This seems wrong we don't want reference equality, we want structural equality
+ [Pure]
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ if (Immutable)
+ return CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ return base.GetHashCode();
+ }
+
+
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ // Treat a BlockEexpr as if it has no free variables at all
+ }
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ //level++;
+ int level = 0;
+ stream.WriteLine(level, "|{");
+
+ if (this.LocVars.Count > 0) {
+ stream.Write(level + 1, "var ");
+ this.LocVars.Emit(stream, true);
+ stream.WriteLine(";");
+ }
+
+ foreach (Block/*!*/ b in this.Blocks) {
+ Contract.Assert(b != null);
+ b.Emit(stream, level + 1);
+ }
+
+ stream.WriteLine();
+ stream.WriteLine(level, "}|");
+
+ stream.WriteLine();
+ stream.WriteLine();
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+
+ rc.PushVarContext();
+ foreach (Variable/*!*/ v in LocVars) {
+ Contract.Assert(v != null);
+ v.Register(rc);
+ v.Resolve(rc);
+ }
+
+ rc.PushProcedureContext();
+ foreach (Block/*!*/ b in Blocks) {
+ Contract.Assert(b != null);
+ b.Register(rc);
+ }
+
+ foreach (Block/*!*/ b in Blocks) {
+ Contract.Assert(b != null);
+ b.Resolve(rc);
+ }
+
+ rc.PopProcedureContext();
+ rc.PopVarContext();
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ foreach (Variable/*!*/ v in LocVars) {
+ Contract.Assert(v != null);
+ v.Typecheck(tc);
+ }
+ foreach (Block/*!*/ b in Blocks) {
+ Contract.Assert(b != null);
+ b.Typecheck(tc);
+ }
+ this.Type = Type.Bool;
+ }
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Type.Bool;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitCodeExpr(this);
+ }
+ }
+
+ public class BvExtractExpr : Expr {
+ private /*readonly--except in StandardVisitor*/ Expr/*!*/ _Bitvector;
+ public Expr Bitvector {
+ get {
+ return _Bitvector;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Cannot change BitVector field of an immutable BvExtractExpr");
+
+ _Bitvector = value;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(_Bitvector != null);
+ }
+
+ public readonly int Start, End;
+
+ public BvExtractExpr(IToken/*!*/ tok, Expr/*!*/ bv, int end, int start, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(bv != null);
+ _Bitvector = bv;
+ Start = start;
+ End = end;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is BvExtractExpr))
+ return false;
+
+ BvExtractExpr other = (BvExtractExpr)obj;
+ return object.Equals(this.Bitvector, other.Bitvector) &&
+ this.Start.Equals(other.Start) && this.End.Equals(other.End);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ if (Immutable)
+ return CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ int h = this.Bitvector.GetHashCode();
+ h ^= Start * 17 ^ End * 13;
+ return h;
+ }
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ int opBindingStrength = 0x90;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) {
+ stream.Write("(");
+ }
+ Bitvector.Emit(stream, opBindingStrength, false);
+ stream.Write("[" + End + ":" + Start + "]");
+ if (parensNeeded) {
+ stream.Write(")");
+ }
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Bitvector.Resolve(rc);
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ Bitvector.ComputeFreeVariables(freeVars);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ Bitvector.Typecheck(tc);
+ Contract.Assert(Bitvector.Type != null); // follows from postcondition of Expr.Typecheck
+
+ if (Start < 0) {
+ tc.Error(this, "start index in extract must not be negative");
+ } else if (End < 0) {
+ tc.Error(this, "end index in extract must not be negative");
+ } else if (End < Start) {
+ tc.Error(this, "start index in extract must be no bigger than the end index");
+ } else {
+ Type typeConstraint = new BvTypeProxy(this.tok, "extract", End - Start);
+ if (typeConstraint.Unify(Bitvector.Type)) {
+ Type = Type.GetBvType(End - Start);
+ } else {
+ tc.Error(this, "extract operand must be a bitvector of at least {0} bits (got {1})", End - Start, Bitvector.Type);
+ }
+ }
+ if (Type == null) {
+ Type = new TypeProxy(this.tok, "type_checking_error");
+ }
+ }
+
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Type.GetBvType(End - Start);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBvExtractExpr(this);
+ }
+ }
+
+ public class BvConcatExpr : Expr {
+ private /*readonly--except in StandardVisitor*/ Expr/*!*/ _E0, _E1;
+ public Expr E0 {
+ get {
+ return _E0;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Can't change E0 reference on immutable Expr");
+
+ _E0 = value;
+ }
+ }
+ public Expr E1 {
+ get {
+ return _E1;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException("Can't change E1 reference on immutable Expr");
+
+ _E1 = value;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(E0 != null);
+ Contract.Invariant(E1 != null);
+ }
+
+
+ public BvConcatExpr(IToken/*!*/ tok, Expr/*!*/ e0, Expr/*!*/ e1, bool immutable=false)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ _E0 = e0;
+ _E1 = e1;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj is BvConcatExpr))
+ return false;
+
+ BvConcatExpr other = (BvConcatExpr)obj;
+ return object.Equals(this.E0, other.E0) && object.Equals(this.E1, other.E1);
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ if (Immutable)
+ return CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ int h = this.E0.GetHashCode() ^ this.E1.GetHashCode() * 17;
+ return h;
+ }
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ int opBindingStrength = 0x32;
+ bool parensNeeded = opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) {
+ stream.Write("(");
+ }
+ E0.Emit(stream, opBindingStrength, false);
+ stream.Write(" ++ ");
+ // while this operator is associative, our incomplete axioms in int translation don't
+ // make much use of it, so better stick to the actual tree shape
+ E1.Emit(stream, opBindingStrength, true);
+ if (parensNeeded) {
+ stream.Write(")");
+ }
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ E0.Resolve(rc);
+ E1.Resolve(rc);
+ }
+ public override void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ //Contract.Requires(freeVars != null);
+ E0.ComputeFreeVariables(freeVars);
+ E1.ComputeFreeVariables(freeVars);
+ }
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ E0.Typecheck(tc);
+ Contract.Assert(E0.Type != null); // follows from postcondition of Expr.Typecheck
+ E1.Typecheck(tc);
+ Contract.Assert(E1.Type != null); // follows from postcondition of Expr.Typecheck
+
+ if (E0.Type.Unify(new BvTypeProxy(this.tok, "concat0", 0)) && E1.Type.Unify(new BvTypeProxy(this.tok, "concat1", 0))) {
+ Type = new BvTypeProxy(this.tok, "concat", E0.Type, E1.Type);
+ } else {
+ tc.Error(this, "++ operands need to be bitvectors (got {0}, {1})", E0.Type, E1.Type);
+ }
+ if (Type == null) {
+ Type = new TypeProxy(this.tok, "type_checking_error");
+ }
+ }
+
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ Type t0 = E0.ShallowType;
+ Type t1 = E1.ShallowType;
+ int len0 = t0.IsBv ? t0.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
+ int len1 = t1.IsBv ? t1.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
+ return Type.GetBvType(len0 + len1);
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBvConcatExpr(this);
+ }
+ }
+}
+
diff --git a/Source/Core/AbsyQuant.cs b/Source/Core/AbsyQuant.cs
index 2258e553..3a27eddf 100644
--- a/Source/Core/AbsyQuant.cs
+++ b/Source/Core/AbsyQuant.cs
@@ -1,930 +1,953 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - AbsyQuant.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie {
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using System.Linq;
- using Microsoft.Boogie.AbstractInterpretation;
- using System.Diagnostics.Contracts;
- using Microsoft.Basetypes;
-
- using Set = GSet<object>;
-
- //---------------------------------------------------------------------
- // Quantifiers and general binders
- //---------------------------------------------------------------------
-
- public enum BinderKind {
- Forall,
- Exists,
- Lambda
- }
- [ContractClassFor(typeof(BinderExpr))]
- abstract class BinderExprContracts : BinderExpr {
- public override BinderKind Kind {
- get {
- throw new NotImplementedException();
- }
- }
- public BinderExprContracts():base(null,null,null,null,null,false){
- }
-
- public override Type ShallowType {
- get {
- throw new NotImplementedException();
- }
- }
- }
- [ContractClass(typeof(BinderExprContracts))]
- public abstract class BinderExpr : Expr {
- public List<TypeVariable>/*!*/ TypeParameters;
- public List<Variable>/*!*/ Dummies;
- public QKeyValue Attributes;
- // FIXME: Protect the above Fields
- public Expr _Body;
- public Expr/*!*/ Body {
- get {
- return _Body;
- }
- set {
- if (Immutable)
- throw new InvalidOperationException ("Cannot change the Body of an immutable BinderExpr");
-
- _Body = value;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(TypeParameters != null);
- Contract.Invariant(Dummies != null);
- Contract.Invariant(Body != null);
- }
-
- public BinderExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters,
- List<Variable>/*!*/ dummies, QKeyValue kv, Expr/*!*/ body, bool immutable)
- : base(tok, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(typeParameters != null);
- Contract.Requires(dummies != null);
- Contract.Requires(body != null);
- Contract.Requires(dummies.Count + typeParameters.Count > 0);
- TypeParameters = typeParameters;
- Dummies = dummies;
- Attributes = kv;
- _Body = body;
- if (immutable)
- CachedHashCode = ComputeHashCode();
- }
-
- abstract public BinderKind Kind {
- get;
- }
-
- protected static bool CompareAttributesAndTriggers = false;
-
- public static bool EqualWithAttributesAndTriggers(object a, object b) {
- CompareAttributesAndTriggers = true;
- var res = object.Equals(a, b);
- Contract.Assert(CompareAttributesAndTriggers);
- CompareAttributesAndTriggers = false;
- return res;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- return BinderEquals(obj);
- }
-
- public bool BinderEquals(object obj) {
- if (obj == null) {
- return false;
- }
- if (!(obj is BinderExpr) ||
- this.Kind != ((BinderExpr) obj).Kind) {
- return false;
- }
-
- var other = (BinderExpr) obj;
-
- return this.TypeParameters.SequenceEqual(other.TypeParameters)
- && this.Dummies.SequenceEqual(other.Dummies)
- && (!CompareAttributesAndTriggers || object.Equals(this.Attributes, other.Attributes))
- && object.Equals(this.Body, other.Body);
- }
-
- [Pure]
- public override int GetHashCode()
- {
- if (Immutable)
- return CachedHashCode;
- else
- return ComputeHashCode();
- }
-
- [Pure]
- public override int ComputeHashCode() {
- // Note, we don't hash triggers and attributes
-
- // DO NOT USE Dummies.GetHashCode() because we want structurally
- // identical Expr to have the same hash code **not** identical references
- // to have the same hash code.
- int h = 0;
- foreach (var dummyVar in this.Dummies) {
- h = ( 53 * h ) + dummyVar.GetHashCode();
- }
-
- h ^= this.Body.GetHashCode();
-
- // DO NOT USE TypeParameters.GetHashCode() because we want structural
- // identical Expr to have the same hash code **not** identical references
- // to have the same hash code.
- int h2 = 0;
- foreach (var typeParam in this.TypeParameters) {
- h2 = ( 97 * h2 ) + typeParam.GetHashCode();
- }
-
- h = h * 5 + h2;
- h *= ((int)Kind + 1);
- return h;
- }
-
- protected virtual void EmitTypeHint(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- }
-
- protected virtual void EmitTriggers(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- }
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
- //Contract.Requires(stream != null);
- stream.push();
- stream.Write(this, "({0}", Kind.ToString().ToLower());
- this.EmitTypeHint(stream);
- Type.EmitOptionalTypeParams(stream, TypeParameters);
- stream.Write(this, " ");
- this.Dummies.Emit(stream, true);
- stream.Write(" :: ");
- stream.sep();
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Emit(stream);
- stream.Write(" ");
- }
- this.EmitTriggers(stream);
- stream.sep();
-
- this.Body.Emit(stream);
- stream.Write(")");
- stream.pop();
- }
-
- protected virtual void ResolveTriggers(ResolutionContext rc) {
- Contract.Requires(rc != null);
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- if (rc.TriggerMode) {
- rc.Error(this, "quantifiers are not allowed in triggers");
- }
-
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- foreach (TypeVariable/*!*/ v in TypeParameters) {
- Contract.Assert(v != null);
- rc.AddTypeBinder(v);
- }
-
- rc.PushVarContext();
- foreach (Variable/*!*/ v in Dummies) {
- Contract.Assert(v != null);
- v.Register(rc);
- v.Resolve(rc);
- }
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Resolve(rc);
- }
- this.ResolveTriggers(rc);
- Body.Resolve(rc);
- rc.PopVarContext();
-
- // establish a canonical order of the type parameters
- this.TypeParameters = Type.SortTypeParams(TypeParameters, new List<Type>(Dummies.Select(Item => Item.TypedIdent.Type).ToArray()), null);
-
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- }
-
- public override void ComputeFreeVariables(Set freeVars) {
- //Contract.Requires(freeVars != null);
- ComputeBinderFreeVariables(TypeParameters, Dummies, Body, Attributes, freeVars);
- }
-
- public static void ComputeBinderFreeVariables(List<TypeVariable> typeParameters, List<Variable> dummies, Expr body, QKeyValue attributes, Set freeVars) {
- Contract.Requires(dummies != null);
- Contract.Requires(body != null);
-
- foreach (var v in dummies) {
- Contract.Assert(v != null);
- Contract.Assert(!freeVars[v]);
- }
- body.ComputeFreeVariables(freeVars);
- for (var a = attributes; a != null; a = a.Next) {
- foreach (var o in a.Params) {
- var e = o as Expr;
- if (e != null) {
- e.ComputeFreeVariables(freeVars);
- }
- }
- }
- foreach (var v in dummies) {
- freeVars.AddRange(v.TypedIdent.Type.FreeVariables);
- }
- freeVars.RemoveRange(dummies);
- freeVars.RemoveRange(typeParameters);
- }
-
- protected List<TypeVariable> GetUnmentionedTypeParameters() {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
- List<TypeVariable>/*!*/ dummyParameters = Type.FreeVariablesIn(new List<Type>(Dummies.Select(Item => Item.TypedIdent.Type).ToArray()));
- Contract.Assert(dummyParameters != null);
- List<TypeVariable>/*!*/ unmentionedParameters = new List<TypeVariable>();
- foreach (TypeVariable/*!*/ var in TypeParameters) {
- Contract.Assert(var != null);
- if (!dummyParameters.Contains(var))
- unmentionedParameters.Add(var);
- }
- return unmentionedParameters;
- }
- }
-
- public class QKeyValue : Absy {
- public readonly string/*!*/ Key;
- private readonly List<object/*!*/>/*!*/ _params; // each element is either a string or an Expr
-
- public void AddParam(object p)
- {
- Contract.Requires(p != null);
- this._params.Add(p);
- }
-
- public void AddParams(IEnumerable<object> ps)
- {
- Contract.Requires(cce.NonNullElements(ps));
- this._params.AddRange(ps);
- }
-
- public void ClearParams()
- {
- this._params.Clear();
- }
-
- public IList<object> Params
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IList<object>>()));
- Contract.Ensures(Contract.Result<IList<object>>().IsReadOnly);
- return this._params.AsReadOnly();
- }
- }
-
- public QKeyValue Next;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Key != null);
- Contract.Invariant(cce.NonNullElements(this._params));
- }
-
- public QKeyValue(IToken tok, string key, IList<object/*!*/>/*!*/ parameters, QKeyValue next)
- : base(tok) {
- Contract.Requires(key != null);
- Contract.Requires(tok != null);
- Contract.Requires(cce.NonNullElements(parameters));
- Key = key;
- this._params = new List<object>(parameters);
- Next = next;
- }
-
- public void Emit(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- stream.Write("{:");
- stream.Write(Key);
- string sep = " ";
- foreach (object p in Params) {
- stream.Write(sep);
- sep = ", ";
- if (p is string) {
- stream.Write("\"");
- stream.Write((string)p);
- stream.Write("\"");
- } else {
- ((Expr)p).Emit(stream);
- }
- }
- stream.Write("}");
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- foreach (object p in Params) {
- if (p is Expr) {
- ((Expr)p).Resolve(rc);
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- foreach (object p in Params) {
- if (p is Expr) {
- ((Expr)p).Typecheck(tc);
- }
- }
- }
- public void AddLast(QKeyValue other) {
- Contract.Requires(other != null);
- QKeyValue current = this;
- while (current.Next != null) {
- current = current.Next;
- }
- current.Next = other;
- }
- // Look for {:name string} in list of attributes.
- [Pure]
- public static string FindStringAttribute(QKeyValue kv, string name) {
- Contract.Requires(name != null);
- for (; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- if (kv.Params.Count == 1 && kv.Params[0] is string) {
- return (string)kv.Params[0];
- }
- }
- }
- return null;
- }
- // Look for {:name expr} in list of attributes.
- public static Expr FindExprAttribute(QKeyValue kv, string name) {
- Contract.Requires(name != null);
- for (; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
- return (Expr)kv.Params[0];
- }
- }
- }
- return null;
- }
- // Return 'true' if {:name true} or {:name} is an attribute in 'kv'
- public static bool FindBoolAttribute(QKeyValue kv, string name) {
- Contract.Requires(name != null);
- for (; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- return kv.Params.Count == 0 ||
- (kv.Params.Count == 1 && kv.Params[0] is LiteralExpr && ((LiteralExpr)kv.Params[0]).IsTrue);
- }
- }
- return false;
- }
-
- public static int FindIntAttribute(QKeyValue kv, string name, int defl) {
- Contract.Requires(name != null);
- Expr e = FindExprAttribute(kv, name);
- LiteralExpr l = e as LiteralExpr;
- if (l != null && l.isBigNum)
- return l.asBigNum.ToIntSafe;
- return defl;
- }
-
- public override Absy Clone() {
- List<object> newParams = new List<object>();
- foreach (object o in Params)
- newParams.Add(o);
- return new QKeyValue(tok, Key, newParams, (Next == null) ? null : (QKeyValue)Next.Clone());
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- return visitor.VisitQKeyValue(this);
- }
-
- public override bool Equals(object obj) {
- var other = obj as QKeyValue;
- if (other == null) {
- return false;
- } else {
- return Key == other.Key && object.Equals(Params, other.Params) &&
- (Next == null
- ? other.Next == null
- : object.Equals(Next, other.Next));
- }
- }
-
- public override int GetHashCode() {
- throw new NotImplementedException();
- }
- }
-
- public class Trigger : Absy {
- public readonly bool Pos;
- [Rep]
- private List<Expr>/*!*/ tr;
-
- public IList<Expr>/*!*/ Tr
- {
- get
- {
- Contract.Ensures(Contract.Result<IList<Expr>>() != null);
- Contract.Ensures(Contract.Result<IList<Expr>>().Count >= 1);
- Contract.Ensures(this.Pos || Contract.Result<IList<Expr>>().Count == 1);
- return this.tr.AsReadOnly();
- }
- set
- {
- Contract.Requires(value != null);
- Contract.Requires(value.Count >= 1);
- Contract.Requires(this.Pos || value.Count == 1);
- this.tr = new List<Expr>(value);
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(this.tr != null);
- Contract.Invariant(this.tr.Count >= 1);
- Contract.Invariant(Pos || this.tr.Count == 1);
- }
-
- public Trigger Next;
-
- public Trigger(IToken/*!*/ tok, bool pos, IEnumerable<Expr>/*!*/ tr, Trigger next = null)
- : base(tok) {
- Contract.Requires(tok != null);
- Contract.Requires(tr != null);
- Contract.Requires(tr.Count() >= 1);
- Contract.Requires(pos || tr.Count() == 1);
- this.Pos = pos;
- this.Tr = new List<Expr>(tr);
- this.Next = next;
- }
-
- public void Emit(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- stream.SetToken(this);
- Contract.Assert(this.Tr.Count >= 1);
- string/*!*/ sep = Pos ? "{ " : "{:nopats ";
- foreach (Expr/*!*/ e in this.Tr) {
- Contract.Assert(e != null);
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
- stream.Write(" }");
- }
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- rc.TriggerMode = true;
- foreach (Expr/*!*/ e in this.Tr) {
- Contract.Assert(e != null);
- e.Resolve(rc);
-
- // just a variable by itself is not allowed
- if (e is IdentifierExpr) {
- rc.Error(e, "a matching pattern must be more than just a variable by itself: {0}", e);
- }
-
- // the free-variable check is performed in the surrounding quantifier expression (because that's
- // where the bound variables are known)
- }
- rc.TriggerMode = false;
- }
-
- /// <summary>
- /// Add to "freeVars" the free variables in the triggering expressions.
- /// </summary>
- public void ComputeFreeVariables(Set /*Variable*/ freeVars) {
- Contract.Requires(freeVars != null);
- foreach (Expr/*!*/ e in this.Tr) {
- Contract.Assert(e != null);
- e.ComputeFreeVariables(freeVars);
- }
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- foreach (Expr/*!*/ e in this.Tr) {
- Contract.Assert(e != null);
- e.Typecheck(tc);
- }
- }
-
- public void AddLast(Trigger other) {
- Trigger current = this;
- while (current.Next != null) {
- current = current.Next;
- }
- current.Next = other;
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTrigger(this);
- }
-
- public override bool Equals(object obj) {
- var other = obj as Trigger;
- if (other == null) {
- return false;
- } else {
- return this.Tr.SequenceEqual(other.Tr) &&
- (Next == null ? other.Next == null : object.Equals(Next, other.Next));
- }
- }
-
- public override int GetHashCode() {
- throw new NotImplementedException();
- }
- }
-
- public class ForallExpr : QuantifierExpr {
- public ForallExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParams,
- List<Variable>/*!*/ dummies, QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable=false)
- : base(tok, typeParams, dummies, kv, triggers, body, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(dummies != null);
- Contract.Requires(body != null);
- Contract.Requires(dummies.Count + typeParams.Count > 0);
- }
- public ForallExpr(IToken tok, List<Variable> dummies, Trigger triggers, Expr body, bool immutable=false)
- : base(tok, new List<TypeVariable>(), dummies, null, triggers, body, immutable) {
- Contract.Requires(body != null);
- Contract.Requires(dummies != null);
- Contract.Requires(tok != null);
- Contract.Requires(dummies.Count > 0);
- }
- public ForallExpr(IToken tok, List<Variable> dummies, Expr body, bool immutable=false)
- : base(tok, new List<TypeVariable>(), dummies, null, null, body, immutable) {
- Contract.Requires(body != null);
- Contract.Requires(dummies != null);
- Contract.Requires(tok != null);
- Contract.Requires(dummies.Count > 0);
- }
- public ForallExpr(IToken tok, List<TypeVariable> typeParams, List<Variable> dummies, Expr body, bool immutable=false)
- : base(tok, typeParams, dummies, null, null, body, immutable) {
- Contract.Requires(body != null);
- Contract.Requires(dummies != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(tok != null);
- Contract.Requires(dummies.Count + typeParams.Count > 0);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitForallExpr(this);
- }
-
- public override BinderKind Kind {
- get {
- return BinderKind.Forall;
- }
- }
- }
-
- public class ExistsExpr : QuantifierExpr {
- public ExistsExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ dummies,
- QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable=false)
- : base(tok, typeParams, dummies, kv, triggers, body, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(typeParams != null);
- Contract.Requires(dummies != null);
- Contract.Requires(body != null);
- Contract.Requires(dummies.Count + typeParams.Count > 0);
- }
- public ExistsExpr(IToken tok, List<Variable> dummies, Trigger triggers, Expr body, bool immutable=false)
- : base(tok, new List<TypeVariable>(), dummies, null, triggers, body, immutable) {
- Contract.Requires(body != null);
- Contract.Requires(dummies != null);
- Contract.Requires(tok != null);
- Contract.Requires(dummies.Count > 0);
- }
- public ExistsExpr(IToken tok, List<Variable> dummies, Expr body, bool immutable=false)
- : base(tok, new List<TypeVariable>(), dummies, null, null, body, immutable) {
- Contract.Requires(body != null);
- Contract.Requires(dummies != null);
- Contract.Requires(tok != null);
- Contract.Requires(dummies.Count > 0);
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitExistsExpr(this);
- }
-
- public override BinderKind Kind {
- get {
- return BinderKind.Exists;
- }
- }
- }
-
- public abstract class QuantifierExpr : BinderExpr {
- public Trigger Triggers;
-
- static int SkolemIds = -1;
- public static int GetNextSkolemId() {
- return System.Threading.Interlocked.Increment(ref SkolemIds);
- }
-
- public readonly int SkolemId;
-
- public QuantifierExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters,
- List<Variable>/*!*/ dummies, QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable)
- : base(tok, typeParameters, dummies, kv, body, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(typeParameters != null);
- Contract.Requires(dummies != null);
- Contract.Requires(body != null);
- Contract.Requires(dummies.Count + typeParameters.Count > 0);
-
- Contract.Assert((this is ForallExpr) || (this is ExistsExpr));
-
- Triggers = triggers;
- SkolemId = GetNextSkolemId();
- }
-
- protected override void EmitTriggers(TokenTextWriter stream) {
- //Contract.Requires(stream != null);
- stream.push();
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- tr.Emit(stream);
- stream.Write(" ");
- stream.sep();
- }
- stream.pop();
- }
-
- // if the user says ( forall x :: forall y :: ... ) and specifies *no* triggers, we transform it to
- // (forall x, y :: ... ) which may help the prover to pick trigger terms
- //
- // (Note: there used to be a different criterion here, which allowed merging when triggers were specified, which could cause prover errors due to resulting unbound variables in the triggers)
- private void MergeAdjecentQuantifier() {
- QuantifierExpr qbody = Body as QuantifierExpr;
- if (!(qbody != null && (qbody is ForallExpr) == (this is ForallExpr) && Triggers == null)) {
- return;
- }
- qbody.MergeAdjecentQuantifier();
- if (this.Triggers != null || qbody.Triggers != null) {
- return;
- }
- Body = qbody.Body;
- TypeParameters.AddRange(qbody.TypeParameters);
- Dummies.AddRange(qbody.Dummies);
- Triggers = qbody.Triggers;
- if (qbody.Attributes != null) {
- if (Attributes == null) {
- Attributes = qbody.Attributes;
- } else {
- QKeyValue p = Attributes;
- while (p.Next != null) {
- p = p.Next;
- }
- p.Next = qbody.Attributes;
- }
- }
- }
-
- #region never triggers
- private class NeverTriggerCollector : ReadOnlyVisitor {
- QuantifierExpr/*!*/ parent;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(parent != null);
- }
-
- public NeverTriggerCollector(QuantifierExpr p) {
- Contract.Requires(p != null);
- parent = p;
- }
-
- public override Expr VisitNAryExpr(NAryExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- FunctionCall fn = node.Fun as FunctionCall;
- if (fn != null && cce.NonNull(fn.Func).NeverTrigger) {
- parent.Triggers = new Trigger(fn.Func.tok, false, new List<Expr> { node} , parent.Triggers);
- }
- return base.VisitNAryExpr(node);
- }
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
- // don't go into quantifier expression or its triggers, since the terms in there may have more bound variables
- // (note, with only the VisitBinderExpr override below, we'd still be visiting triggers, which we don't want to do)
- return node;
- }
- public override BinderExpr VisitBinderExpr(BinderExpr node) {
- // don't go into binder expression, since the terms in there may have more bound variables
- return node;
- }
- }
-
- private bool neverTriggerApplied;
- private void ApplyNeverTriggers() {
- if (neverTriggerApplied) {
- return;
- }
- neverTriggerApplied = true;
-
- for (Trigger t = Triggers; t != null; t = t.Next) {
- if (t.Pos) {
- return;
- }
- }
-
- NeverTriggerCollector visitor = new NeverTriggerCollector(this);
- visitor.VisitExpr(Body);
- }
- #endregion
-
- protected override void ResolveTriggers(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- int prevErrorCount = rc.ErrorCount;
- tr.Resolve(rc);
- if (prevErrorCount == rc.ErrorCount) {
- // for positive triggers, make sure all bound variables are mentioned
- if (tr.Pos) {
- Set /*Variable*/ freeVars = new Set /*Variable*/ ();
- tr.ComputeFreeVariables(freeVars);
- foreach (Variable/*!*/ v in Dummies) {
- Contract.Assert(v != null);
- if (!freeVars[v]) {
- rc.Error(tr, "trigger must mention all quantified variables, but does not mention: {0}", v);
- }
- }
- }
- }
- }
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- int oldErrorCount = rc.ErrorCount;
-
- this.MergeAdjecentQuantifier();
-
- base.Resolve(rc);
-
- if (oldErrorCount == rc.ErrorCount) {
- this.ApplyNeverTriggers();
- }
- }
-
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(tc);
- }
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- tr.Typecheck(tc);
- }
- Body.Typecheck(tc);
- Contract.Assert(Body.Type != null); // follows from postcondition of Expr.Typecheck
- if (!Body.Type.Unify(Type.Bool)) {
- tc.Error(this, "quantifier body must be of type bool");
- }
- this.Type = Type.Bool;
-
- // Check that type parameters occur in the types of the
- // dummies, or otherwise in the triggers. This can only be
- // done after typechecking
- List<TypeVariable>/*!*/ unmentionedParameters = GetUnmentionedTypeParameters();
- Contract.Assert(unmentionedParameters != null);
-
- if (unmentionedParameters.Count > 0) {
- // all the type parameters that do not occur in dummy types
- // have to occur in triggers
-
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- // for positive triggers, make sure all bound variables are mentioned
- if (tr.Pos) {
- Set /*Variable*/ freeVars = new Set /*Variable*/ ();
- tr.ComputeFreeVariables(freeVars);
- foreach (TypeVariable/*!*/ v in unmentionedParameters) {
- Contract.Assert(v != null);
- if (!freeVars[v])
- tc.Error(tr,
- "trigger does not mention {0}, which does not occur in variables types either",
- v);
- }
- }
- }
- }
- }
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Type.Bool;
- }
- }
-
- public override bool Equals(object obj) {
- var other = obj as QuantifierExpr;
- if (other == null) {
- return false;
- } else {
- return this.BinderEquals(obj) &&
- (!CompareAttributesAndTriggers || object.Equals(Triggers, other.Triggers));
- }
- }
- }
-
-
- public class LambdaExpr : BinderExpr {
- public LambdaExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters,
- List<Variable>/*!*/ dummies, QKeyValue kv, Expr/*!*/ body, bool immutable=false)
- : base(tok, typeParameters, dummies, kv, body, immutable) {
- Contract.Requires(tok != null);
- Contract.Requires(typeParameters != null);
- Contract.Requires(dummies != null);
- Contract.Requires(body != null);
- Contract.Requires(dummies.Count + typeParameters.Count > 0);
- }
-
- public override BinderKind Kind {
- get {
- return BinderKind.Lambda;
- }
- }
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- base.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(tc);
- }
- Body.Typecheck(tc);
- Contract.Assert(Body.Type != null); // follows from postcondition of Expr.Typecheck
-
- List<Type>/*!*/ argTypes = new List<Type>();
- foreach (Variable/*!*/ v in Dummies) {
- Contract.Assert(v != null);
- argTypes.Add(v.TypedIdent.Type);
- }
- this.Type = new MapType(this.tok, this.TypeParameters, argTypes, Body.Type);
-
- // Check that type parameters occur in the types of the
- // dummies, or otherwise in the triggers. This can only be
- // done after typechecking
- List<TypeVariable>/*!*/ unmentionedParameters = GetUnmentionedTypeParameters();
- Contract.Assert(unmentionedParameters != null);
-
- if (unmentionedParameters.Count > 0) {
- tc.Error(this, "the type variable {0} does not occur in types of the lambda parameters", unmentionedParameters[0]);
- }
- }
-
- private Type mapType;
- public override Type/*!*/ ShallowType {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- if (mapType == null) {
- List<Type>/*!*/ argTypes = new List<Type>();
- foreach (Variable/*!*/ v in Dummies) {
- Contract.Assert(v != null);
- argTypes.Add(v.TypedIdent.Type);
- }
- mapType = new MapType(this.tok, this.TypeParameters, argTypes, Body.ShallowType);
- }
-
- return mapType;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitLambdaExpr(this);
- }
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - AbsyQuant.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie {
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using System.Diagnostics.Contracts;
+ using Microsoft.Basetypes;
+
+ using Set = GSet<object>;
+
+ //---------------------------------------------------------------------
+ // Quantifiers and general binders
+ //---------------------------------------------------------------------
+
+ public enum BinderKind {
+ Forall,
+ Exists,
+ Lambda
+ }
+ [ContractClassFor(typeof(BinderExpr))]
+ abstract class BinderExprContracts : BinderExpr {
+ public override BinderKind Kind {
+ get {
+ throw new NotImplementedException();
+ }
+ }
+ public BinderExprContracts():base(null,null,null,null,null,false){
+ }
+
+ public override Type ShallowType {
+ get {
+ throw new NotImplementedException();
+ }
+ }
+ }
+ [ContractClass(typeof(BinderExprContracts))]
+ public abstract class BinderExpr : Expr {
+ public List<TypeVariable>/*!*/ TypeParameters;
+ public List<Variable>/*!*/ Dummies;
+ public QKeyValue Attributes;
+ // FIXME: Protect the above Fields
+ public Expr _Body;
+ public Expr/*!*/ Body {
+ get {
+ return _Body;
+ }
+ set {
+ if (Immutable)
+ throw new InvalidOperationException ("Cannot change the Body of an immutable BinderExpr");
+
+ _Body = value;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(TypeParameters != null);
+ Contract.Invariant(Dummies != null);
+ Contract.Invariant(Body != null);
+ }
+
+ public BinderExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters,
+ List<Variable>/*!*/ dummies, QKeyValue kv, Expr/*!*/ body, bool immutable)
+ : base(tok, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typeParameters != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(body != null);
+ Contract.Requires(dummies.Count + typeParameters.Count > 0);
+ TypeParameters = typeParameters;
+ Dummies = dummies;
+ Attributes = kv;
+ _Body = body;
+ if (immutable)
+ CachedHashCode = ComputeHashCode();
+ }
+
+ abstract public BinderKind Kind {
+ get;
+ }
+
+ protected static bool CompareAttributesAndTriggers = false;
+
+ public static bool EqualWithAttributesAndTriggers(object a, object b) {
+ CompareAttributesAndTriggers = true;
+ var res = object.Equals(a, b);
+ Contract.Assert(CompareAttributesAndTriggers);
+ CompareAttributesAndTriggers = false;
+ return res;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object obj) {
+ return BinderEquals(obj);
+ }
+
+ public bool BinderEquals(object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj is BinderExpr) ||
+ this.Kind != ((BinderExpr) obj).Kind) {
+ return false;
+ }
+
+ var other = (BinderExpr) obj;
+
+ return this.TypeParameters.SequenceEqual(other.TypeParameters)
+ && this.Dummies.SequenceEqual(other.Dummies)
+ && (!CompareAttributesAndTriggers || object.Equals(this.Attributes, other.Attributes))
+ && object.Equals(this.Body, other.Body);
+ }
+
+ [Pure]
+ public override int GetHashCode()
+ {
+ if (Immutable)
+ return CachedHashCode;
+ else
+ return ComputeHashCode();
+ }
+
+ [Pure]
+ public override int ComputeHashCode() {
+ // Note, we don't hash triggers and attributes
+
+ // DO NOT USE Dummies.GetHashCode() because we want structurally
+ // identical Expr to have the same hash code **not** identical references
+ // to have the same hash code.
+ int h = 0;
+ foreach (var dummyVar in this.Dummies) {
+ h = ( 53 * h ) + dummyVar.GetHashCode();
+ }
+
+ h ^= this.Body.GetHashCode();
+
+ // DO NOT USE TypeParameters.GetHashCode() because we want structural
+ // identical Expr to have the same hash code **not** identical references
+ // to have the same hash code.
+ int h2 = 0;
+ foreach (var typeParam in this.TypeParameters) {
+ h2 = ( 97 * h2 ) + typeParam.GetHashCode();
+ }
+
+ h = h * 5 + h2;
+ h *= ((int)Kind + 1);
+ return h;
+ }
+
+ protected virtual void EmitTypeHint(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ }
+
+ protected virtual void EmitTriggers(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ }
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength, bool fragileContext) {
+ //Contract.Requires(stream != null);
+ stream.push();
+ stream.Write(this, "({0}", Kind.ToString().ToLower());
+ this.EmitTypeHint(stream);
+ Type.EmitOptionalTypeParams(stream, TypeParameters);
+ stream.Write(this, " ");
+ this.Dummies.Emit(stream, true);
+ stream.Write(" :: ");
+ stream.sep();
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Emit(stream);
+ stream.Write(" ");
+ }
+ this.EmitTriggers(stream);
+ stream.sep();
+
+ this.Body.Emit(stream);
+ stream.Write(")");
+ stream.pop();
+ }
+
+ protected virtual void ResolveTriggers(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ if (rc.TriggerMode) {
+ rc.Error(this, "quantifiers are not allowed in triggers");
+ }
+
+ int previousTypeBinderState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable/*!*/ v in TypeParameters) {
+ Contract.Assert(v != null);
+ rc.AddTypeBinder(v);
+ }
+
+ rc.PushVarContext();
+ foreach (Variable/*!*/ v in Dummies) {
+ Contract.Assert(v != null);
+ v.Register(rc);
+ v.Resolve(rc);
+ }
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Resolve(rc);
+ }
+ this.ResolveTriggers(rc);
+ Body.Resolve(rc);
+ rc.PopVarContext();
+
+ // establish a canonical order of the type parameters
+ this.TypeParameters = Type.SortTypeParams(TypeParameters, new List<Type>(Dummies.Select(Item => Item.TypedIdent.Type).ToArray()), null);
+
+ } finally {
+ rc.TypeBinderState = previousTypeBinderState;
+ }
+ }
+
+ public override void ComputeFreeVariables(Set freeVars) {
+ //Contract.Requires(freeVars != null);
+ ComputeBinderFreeVariables(TypeParameters, Dummies, Body, Attributes, freeVars);
+ }
+
+ public static void ComputeBinderFreeVariables(List<TypeVariable> typeParameters, List<Variable> dummies, Expr body, QKeyValue attributes, Set freeVars) {
+ Contract.Requires(dummies != null);
+ Contract.Requires(body != null);
+
+ foreach (var v in dummies) {
+ Contract.Assert(v != null);
+ Contract.Assert(!freeVars[v]);
+ }
+ body.ComputeFreeVariables(freeVars);
+ for (var a = attributes; a != null; a = a.Next) {
+ foreach (var o in a.Params) {
+ var e = o as Expr;
+ if (e != null) {
+ e.ComputeFreeVariables(freeVars);
+ }
+ }
+ }
+ foreach (var v in dummies) {
+ freeVars.AddRange(v.TypedIdent.Type.FreeVariables);
+ }
+ freeVars.RemoveRange(dummies);
+ freeVars.RemoveRange(typeParameters);
+ }
+
+ protected List<TypeVariable> GetUnmentionedTypeParameters() {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+ List<TypeVariable>/*!*/ dummyParameters = Type.FreeVariablesIn(new List<Type>(Dummies.Select(Item => Item.TypedIdent.Type).ToArray()));
+ Contract.Assert(dummyParameters != null);
+ List<TypeVariable>/*!*/ unmentionedParameters = new List<TypeVariable>();
+ foreach (TypeVariable/*!*/ var in TypeParameters) {
+ Contract.Assert(var != null);
+ if (!dummyParameters.Contains(var))
+ unmentionedParameters.Add(var);
+ }
+ return unmentionedParameters;
+ }
+ }
+
+ public class QKeyValue : Absy {
+ public readonly string/*!*/ Key;
+ private readonly List<object/*!*/>/*!*/ _params; // each element is either a string or an Expr
+
+ public void AddParam(object p)
+ {
+ Contract.Requires(p != null);
+ this._params.Add(p);
+ }
+
+ public void AddParams(IEnumerable<object> ps)
+ {
+ Contract.Requires(cce.NonNullElements(ps));
+ this._params.AddRange(ps);
+ }
+
+ public void ClearParams()
+ {
+ this._params.Clear();
+ }
+
+ public IList<object> Params
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IList<object>>()));
+ Contract.Ensures(Contract.Result<IList<object>>().IsReadOnly);
+ return this._params.AsReadOnly();
+ }
+ }
+
+ public QKeyValue Next;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Key != null);
+ Contract.Invariant(cce.NonNullElements(this._params));
+ }
+
+ public QKeyValue(IToken tok, string key, IList<object/*!*/>/*!*/ parameters, QKeyValue next)
+ : base(tok) {
+ Contract.Requires(key != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(cce.NonNullElements(parameters));
+ Key = key;
+ this._params = new List<object>(parameters);
+ Next = next;
+ }
+
+ public void Emit(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ stream.Write("{:");
+ stream.Write(Key);
+ string sep = " ";
+ foreach (object p in Params) {
+ stream.Write(sep);
+ sep = ", ";
+ if (p is string) {
+ stream.Write("\"");
+ stream.Write((string)p);
+ stream.Write("\"");
+ } else {
+ ((Expr)p).Emit(stream);
+ }
+ }
+ stream.Write("}");
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+
+ if ((Key == "minimize" || Key == "maximize") && Params.Count != 1)
+ {
+ rc.Error(this, "attributes :minimize and :maximize accept only one argument");
+ }
+
+ if (Key == "verified_under" && Params.Count != 1)
+ {
+ rc.Error(this, "attribute :verified_under accepts only one argument");
+ }
+
+ foreach (object p in Params) {
+ if (p is Expr) {
+ ((Expr)p).Resolve(rc);
+ }
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ foreach (object p in Params) {
+ var expr = p as Expr;
+ if (expr != null) {
+ expr.Typecheck(tc);
+ }
+ if ((Key == "minimize" || Key == "maximize")
+ && (expr == null || !(expr.Type.IsInt || expr.Type.IsReal || expr.Type.IsBv)))
+ {
+ tc.Error(this, "attributes :minimize and :maximize accept only one argument of type int, real or bv");
+ break;
+ }
+ if (Key == "verified_under" && (expr == null || !expr.Type.IsBool))
+ {
+ tc.Error(this, "attribute :verified_under accepts only one argument of type bool");
+ break;
+ }
+ }
+ }
+ public void AddLast(QKeyValue other) {
+ Contract.Requires(other != null);
+ QKeyValue current = this;
+ while (current.Next != null) {
+ current = current.Next;
+ }
+ current.Next = other;
+ }
+ // Look for {:name string} in list of attributes.
+ [Pure]
+ public static string FindStringAttribute(QKeyValue kv, string name) {
+ Contract.Requires(name != null);
+ for (; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ if (kv.Params.Count == 1 && kv.Params[0] is string) {
+ return (string)kv.Params[0];
+ }
+ }
+ }
+ return null;
+ }
+ // Look for {:name expr} in list of attributes.
+ public static Expr FindExprAttribute(QKeyValue kv, string name) {
+ Contract.Requires(name != null);
+ for (; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
+ return (Expr)kv.Params[0];
+ }
+ }
+ }
+ return null;
+ }
+ // Return 'true' if {:name true} or {:name} is an attribute in 'kv'
+ public static bool FindBoolAttribute(QKeyValue kv, string name) {
+ Contract.Requires(name != null);
+ for (; kv != null; kv = kv.Next) {
+ if (kv.Key == name) {
+ return kv.Params.Count == 0 ||
+ (kv.Params.Count == 1 && kv.Params[0] is LiteralExpr && ((LiteralExpr)kv.Params[0]).IsTrue);
+ }
+ }
+ return false;
+ }
+
+ public static int FindIntAttribute(QKeyValue kv, string name, int defl) {
+ Contract.Requires(name != null);
+ Expr e = FindExprAttribute(kv, name);
+ LiteralExpr l = e as LiteralExpr;
+ if (l != null && l.isBigNum)
+ return l.asBigNum.ToIntSafe;
+ return defl;
+ }
+
+ public override Absy Clone() {
+ List<object> newParams = new List<object>();
+ foreach (object o in Params)
+ newParams.Add(o);
+ return new QKeyValue(tok, Key, newParams, (Next == null) ? null : (QKeyValue)Next.Clone());
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ return visitor.VisitQKeyValue(this);
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as QKeyValue;
+ if (other == null) {
+ return false;
+ } else {
+ return Key == other.Key && object.Equals(Params, other.Params) &&
+ (Next == null
+ ? other.Next == null
+ : object.Equals(Next, other.Next));
+ }
+ }
+
+ public override int GetHashCode() {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class Trigger : Absy {
+ public readonly bool Pos;
+ [Rep]
+ private List<Expr>/*!*/ tr;
+
+ public IList<Expr>/*!*/ Tr
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IList<Expr>>() != null);
+ Contract.Ensures(Contract.Result<IList<Expr>>().Count >= 1);
+ Contract.Ensures(this.Pos || Contract.Result<IList<Expr>>().Count == 1);
+ return this.tr.AsReadOnly();
+ }
+ set
+ {
+ Contract.Requires(value != null);
+ Contract.Requires(value.Count >= 1);
+ Contract.Requires(this.Pos || value.Count == 1);
+ this.tr = new List<Expr>(value);
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(this.tr != null);
+ Contract.Invariant(this.tr.Count >= 1);
+ Contract.Invariant(Pos || this.tr.Count == 1);
+ }
+
+ public Trigger Next;
+
+ public Trigger(IToken/*!*/ tok, bool pos, IEnumerable<Expr>/*!*/ tr, Trigger next = null)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(tr != null);
+ Contract.Requires(tr.Count() >= 1);
+ Contract.Requires(pos || tr.Count() == 1);
+ this.Pos = pos;
+ this.Tr = new List<Expr>(tr);
+ this.Next = next;
+ }
+
+ public void Emit(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ stream.SetToken(this);
+ Contract.Assert(this.Tr.Count >= 1);
+ string/*!*/ sep = Pos ? "{ " : "{:nopats ";
+ foreach (Expr/*!*/ e in this.Tr) {
+ Contract.Assert(e != null);
+ stream.Write(sep);
+ sep = ", ";
+ e.Emit(stream);
+ }
+ stream.Write(" }");
+ }
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ rc.TriggerMode = true;
+ foreach (Expr/*!*/ e in this.Tr) {
+ Contract.Assert(e != null);
+ e.Resolve(rc);
+
+ // just a variable by itself is not allowed
+ if (e is IdentifierExpr) {
+ rc.Error(e, "a matching pattern must be more than just a variable by itself: {0}", e);
+ }
+
+ // the free-variable check is performed in the surrounding quantifier expression (because that's
+ // where the bound variables are known)
+ }
+ rc.TriggerMode = false;
+ }
+
+ /// <summary>
+ /// Add to "freeVars" the free variables in the triggering expressions.
+ /// </summary>
+ public void ComputeFreeVariables(Set /*Variable*/ freeVars) {
+ Contract.Requires(freeVars != null);
+ foreach (Expr/*!*/ e in this.Tr) {
+ Contract.Assert(e != null);
+ e.ComputeFreeVariables(freeVars);
+ }
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ foreach (Expr/*!*/ e in this.Tr) {
+ Contract.Assert(e != null);
+ e.Typecheck(tc);
+ }
+ }
+
+ public void AddLast(Trigger other) {
+ Trigger current = this;
+ while (current.Next != null) {
+ current = current.Next;
+ }
+ current.Next = other;
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTrigger(this);
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as Trigger;
+ if (other == null) {
+ return false;
+ } else {
+ return this.Tr.SequenceEqual(other.Tr) &&
+ (Next == null ? other.Next == null : object.Equals(Next, other.Next));
+ }
+ }
+
+ public override int GetHashCode() {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class ForallExpr : QuantifierExpr {
+ public ForallExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParams,
+ List<Variable>/*!*/ dummies, QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable=false)
+ : base(tok, typeParams, dummies, kv, triggers, body, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(body != null);
+ Contract.Requires(dummies.Count + typeParams.Count > 0);
+ }
+ public ForallExpr(IToken tok, List<Variable> dummies, Trigger triggers, Expr body, bool immutable=false)
+ : base(tok, new List<TypeVariable>(), dummies, null, triggers, body, immutable) {
+ Contract.Requires(body != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(dummies.Count > 0);
+ }
+ public ForallExpr(IToken tok, List<Variable> dummies, Expr body, bool immutable=false)
+ : base(tok, new List<TypeVariable>(), dummies, null, null, body, immutable) {
+ Contract.Requires(body != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(dummies.Count > 0);
+ }
+ public ForallExpr(IToken tok, List<TypeVariable> typeParams, List<Variable> dummies, Expr body, bool immutable=false)
+ : base(tok, typeParams, dummies, null, null, body, immutable) {
+ Contract.Requires(body != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(dummies.Count + typeParams.Count > 0);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitForallExpr(this);
+ }
+
+ public override BinderKind Kind {
+ get {
+ return BinderKind.Forall;
+ }
+ }
+ }
+
+ public class ExistsExpr : QuantifierExpr {
+ public ExistsExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ dummies,
+ QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable=false)
+ : base(tok, typeParams, dummies, kv, triggers, body, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typeParams != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(body != null);
+ Contract.Requires(dummies.Count + typeParams.Count > 0);
+ }
+ public ExistsExpr(IToken tok, List<Variable> dummies, Trigger triggers, Expr body, bool immutable=false)
+ : base(tok, new List<TypeVariable>(), dummies, null, triggers, body, immutable) {
+ Contract.Requires(body != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(dummies.Count > 0);
+ }
+ public ExistsExpr(IToken tok, List<Variable> dummies, Expr body, bool immutable=false)
+ : base(tok, new List<TypeVariable>(), dummies, null, null, body, immutable) {
+ Contract.Requires(body != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(tok != null);
+ Contract.Requires(dummies.Count > 0);
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitExistsExpr(this);
+ }
+
+ public override BinderKind Kind {
+ get {
+ return BinderKind.Exists;
+ }
+ }
+ }
+
+ public abstract class QuantifierExpr : BinderExpr {
+ public Trigger Triggers;
+
+ static int SkolemIds = -1;
+ public static int GetNextSkolemId() {
+ return System.Threading.Interlocked.Increment(ref SkolemIds);
+ }
+
+ public readonly int SkolemId;
+
+ public QuantifierExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters,
+ List<Variable>/*!*/ dummies, QKeyValue kv, Trigger triggers, Expr/*!*/ body, bool immutable)
+ : base(tok, typeParameters, dummies, kv, body, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typeParameters != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(body != null);
+ Contract.Requires(dummies.Count + typeParameters.Count > 0);
+
+ Contract.Assert((this is ForallExpr) || (this is ExistsExpr));
+
+ Triggers = triggers;
+ SkolemId = GetNextSkolemId();
+ }
+
+ protected override void EmitTriggers(TokenTextWriter stream) {
+ //Contract.Requires(stream != null);
+ stream.push();
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ tr.Emit(stream);
+ stream.Write(" ");
+ stream.sep();
+ }
+ stream.pop();
+ }
+
+ // if the user says ( forall x :: forall y :: ... ) and specifies *no* triggers, we transform it to
+ // (forall x, y :: ... ) which may help the prover to pick trigger terms
+ //
+ // (Note: there used to be a different criterion here, which allowed merging when triggers were specified, which could cause prover errors due to resulting unbound variables in the triggers)
+ private void MergeAdjecentQuantifier() {
+ QuantifierExpr qbody = Body as QuantifierExpr;
+ if (!(qbody != null && (qbody is ForallExpr) == (this is ForallExpr) && Triggers == null)) {
+ return;
+ }
+ qbody.MergeAdjecentQuantifier();
+ if (this.Triggers != null || qbody.Triggers != null) {
+ return;
+ }
+ Body = qbody.Body;
+ TypeParameters.AddRange(qbody.TypeParameters);
+ Dummies.AddRange(qbody.Dummies);
+ Triggers = qbody.Triggers;
+ if (qbody.Attributes != null) {
+ if (Attributes == null) {
+ Attributes = qbody.Attributes;
+ } else {
+ QKeyValue p = Attributes;
+ while (p.Next != null) {
+ p = p.Next;
+ }
+ p.Next = qbody.Attributes;
+ }
+ }
+ }
+
+ #region never triggers
+ private class NeverTriggerCollector : ReadOnlyVisitor {
+ QuantifierExpr/*!*/ parent;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(parent != null);
+ }
+
+ public NeverTriggerCollector(QuantifierExpr p) {
+ Contract.Requires(p != null);
+ parent = p;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ FunctionCall fn = node.Fun as FunctionCall;
+ if (fn != null && cce.NonNull(fn.Func).NeverTrigger) {
+ parent.Triggers = new Trigger(fn.Func.tok, false, new List<Expr> { node} , parent.Triggers);
+ }
+ return base.VisitNAryExpr(node);
+ }
+ public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
+ // don't go into quantifier expression or its triggers, since the terms in there may have more bound variables
+ // (note, with only the VisitBinderExpr override below, we'd still be visiting triggers, which we don't want to do)
+ return node;
+ }
+ public override BinderExpr VisitBinderExpr(BinderExpr node) {
+ // don't go into binder expression, since the terms in there may have more bound variables
+ return node;
+ }
+ }
+
+ private bool neverTriggerApplied;
+ private void ApplyNeverTriggers() {
+ if (neverTriggerApplied) {
+ return;
+ }
+ neverTriggerApplied = true;
+
+ for (Trigger t = Triggers; t != null; t = t.Next) {
+ if (t.Pos) {
+ return;
+ }
+ }
+
+ NeverTriggerCollector visitor = new NeverTriggerCollector(this);
+ visitor.VisitExpr(Body);
+ }
+ #endregion
+
+ protected override void ResolveTriggers(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ int prevErrorCount = rc.ErrorCount;
+ tr.Resolve(rc);
+ if (prevErrorCount == rc.ErrorCount) {
+ // for positive triggers, make sure all bound variables are mentioned
+ if (tr.Pos) {
+ Set /*Variable*/ freeVars = new Set /*Variable*/ ();
+ tr.ComputeFreeVariables(freeVars);
+ foreach (Variable/*!*/ v in Dummies) {
+ Contract.Assert(v != null);
+ if (!freeVars[v]) {
+ rc.Error(tr, "trigger must mention all quantified variables, but does not mention: {0}", v);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ int oldErrorCount = rc.ErrorCount;
+
+ this.MergeAdjecentQuantifier();
+
+ base.Resolve(rc);
+
+ if (oldErrorCount == rc.ErrorCount) {
+ this.ApplyNeverTriggers();
+ }
+ }
+
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Typecheck(tc);
+ }
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ tr.Typecheck(tc);
+ }
+ Body.Typecheck(tc);
+ Contract.Assert(Body.Type != null); // follows from postcondition of Expr.Typecheck
+ if (!Body.Type.Unify(Type.Bool)) {
+ tc.Error(this, "quantifier body must be of type bool");
+ }
+ this.Type = Type.Bool;
+
+ // Check that type parameters occur in the types of the
+ // dummies, or otherwise in the triggers. This can only be
+ // done after typechecking
+ List<TypeVariable>/*!*/ unmentionedParameters = GetUnmentionedTypeParameters();
+ Contract.Assert(unmentionedParameters != null);
+
+ if (unmentionedParameters.Count > 0) {
+ // all the type parameters that do not occur in dummy types
+ // have to occur in triggers
+
+ for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
+ // for positive triggers, make sure all bound variables are mentioned
+ if (tr.Pos) {
+ Set /*Variable*/ freeVars = new Set /*Variable*/ ();
+ tr.ComputeFreeVariables(freeVars);
+ foreach (TypeVariable/*!*/ v in unmentionedParameters) {
+ Contract.Assert(v != null);
+ if (!freeVars[v])
+ tc.Error(tr,
+ "trigger does not mention {0}, which does not occur in variables types either",
+ v);
+ }
+ }
+ }
+ }
+ }
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Type.Bool;
+ }
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as QuantifierExpr;
+ if (other == null) {
+ return false;
+ } else {
+ return this.BinderEquals(obj) &&
+ (!CompareAttributesAndTriggers || object.Equals(Triggers, other.Triggers));
+ }
+ }
+ }
+
+
+ public class LambdaExpr : BinderExpr {
+ public LambdaExpr(IToken/*!*/ tok, List<TypeVariable>/*!*/ typeParameters,
+ List<Variable>/*!*/ dummies, QKeyValue kv, Expr/*!*/ body, bool immutable=false)
+ : base(tok, typeParameters, dummies, kv, body, immutable) {
+ Contract.Requires(tok != null);
+ Contract.Requires(typeParameters != null);
+ Contract.Requires(dummies != null);
+ Contract.Requires(body != null);
+ Contract.Requires(dummies.Count + typeParameters.Count > 0);
+ }
+
+ public override BinderKind Kind {
+ get {
+ return BinderKind.Lambda;
+ }
+ }
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ base.Resolve(rc);
+ }
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
+ kv.Typecheck(tc);
+ }
+ Body.Typecheck(tc);
+ Contract.Assert(Body.Type != null); // follows from postcondition of Expr.Typecheck
+
+ List<Type>/*!*/ argTypes = new List<Type>();
+ foreach (Variable/*!*/ v in Dummies) {
+ Contract.Assert(v != null);
+ argTypes.Add(v.TypedIdent.Type);
+ }
+ this.Type = new MapType(this.tok, this.TypeParameters, argTypes, Body.Type);
+
+ // Check that type parameters occur in the types of the
+ // dummies, or otherwise in the triggers. This can only be
+ // done after typechecking
+ List<TypeVariable>/*!*/ unmentionedParameters = GetUnmentionedTypeParameters();
+ Contract.Assert(unmentionedParameters != null);
+
+ if (unmentionedParameters.Count > 0) {
+ tc.Error(this, "the type variable {0} does not occur in types of the lambda parameters", unmentionedParameters[0]);
+ }
+ }
+
+ private Type mapType;
+ public override Type/*!*/ ShallowType {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ if (mapType == null) {
+ List<Type>/*!*/ argTypes = new List<Type>();
+ foreach (Variable/*!*/ v in Dummies) {
+ Contract.Assert(v != null);
+ argTypes.Add(v.TypedIdent.Type);
+ }
+ mapType = new MapType(this.tok, this.TypeParameters, argTypes, Body.ShallowType);
+ }
+
+ return mapType;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitLambdaExpr(this);
+ }
+
+ }
+}
diff --git a/Source/Core/AbsyType.cs b/Source/Core/AbsyType.cs
index 5d41a8dd..96de5c0b 100644
--- a/Source/Core/AbsyType.cs
+++ b/Source/Core/AbsyType.cs
@@ -1,3907 +1,3907 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie {
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Linq;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using System.Diagnostics.Contracts;
-
- //=====================================================================
- //---------------------------------------------------------------------
- // Types
- [ContractClass(typeof(TypeContracts))]
- public abstract class Type : Absy {
- public Type(IToken/*!*/ token)
- : base(token) {
- Contract.Requires(token != null);
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively. Applying Clone to a type will return
- // a type in which all bound variables have been replaced with new
- // variables, whereas free variables have not changed
-
- public override Absy Clone() {
- Contract.Ensures(Contract.Result<Absy>() != null);
- return this.Clone(new Dictionary<TypeVariable/*!*/, TypeVariable/*!*/>());
- }
-
- public abstract Type/*!*/ Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap);
-
- /// <summary>
- /// Clones the type, but only syntactically. Anything resolved in the source
- /// type is left unresolved (that is, with just the name) in the destination type.
- /// </summary>
- public abstract Type/*!*/ CloneUnresolved();
-
- //----------- Linearisation ----------------------------------
-
- public void Emit(TokenTextWriter stream) {
- Contract.Requires(stream != null);
- this.Emit(stream, 0);
- }
-
- public abstract void Emit(TokenTextWriter/*!*/ stream, int contextBindingStrength);
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/false, /*pretty=*/ false)) {
- this.Emit(stream);
- }
- return buffer.ToString();
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (ReferenceEquals(this, that))
- return true;
- Type thatType = that as Type;
- return thatType != null && this.Equals(thatType,
- new List<TypeVariable>(),
- new List<TypeVariable>());
- }
-
- [Pure]
- public abstract bool Equals(Type/*!*/ that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables);
-
- // used to skip leading type annotations (subexpressions of the
- // resulting type might still contain annotations)
- internal virtual Type/*!*/ Expanded {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return this;
- }
- }
-
- //----------- Unification of types -----------
-
- /// <summary>
- /// Add a constraint that this==that, if possible, and return true.
- /// If not possible, return false (which may have added some partial constraints).
- /// No error is printed.
- /// </summary>
- public bool Unify(Type that) {
- Contract.Requires(that != null);
- return Unify(that, new List<TypeVariable>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>());
- }
-
- public abstract bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier);
-
-
- [Pure]
- public static bool IsIdempotent(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
- Contract.Requires(cce.NonNullDictionaryAndValues(unifier));
- return unifier.Values.All(val => val.FreeVariables.All(var => !unifier.ContainsKey(var)));
- }
-
-
-#if OLD_UNIFICATION
- // Compute a most general unification of two types. null is returned if
- // no such unifier exists. The unifier is not allowed to subtitute any
- // type variables other than the ones in "unifiableVariables"
- public IDictionary<TypeVariable!, Type!> Unify(Type! that,
- List<TypeVariable>! unifiableVariables) {
- Dictionary<TypeVariable!, Type!>! result = new Dictionary<TypeVariable!, Type!> ();
- try {
- this.Unify(that, unifiableVariables,
- new List<TypeVariable> (), new List<TypeVariable> (), result);
- } catch (UnificationFailedException) {
- return null;
- }
- return result;
- }
-
- // Compute an idempotent most general unifier and add the result to the argument
- // unifier. The result is true iff the unification succeeded
- public bool Unify(Type! that,
- List<TypeVariable>! unifiableVariables,
- // given mappings that need to be taken into account
- // the old unifier has to be idempotent as well
- IDictionary<TypeVariable!, Type!>! unifier)
- {
- Contract.Requires(Contract.ForAll(unifier.Keys , key=> unifiableVariables.Has(key)));
- Contract.Requires(IsIdempotent(unifier));
- try {
- this.Unify(that, unifiableVariables,
- new List<TypeVariable> (), new List<TypeVariable> (), unifier);
- } catch (UnificationFailedException) {
- return false;
- }
- return true;
- }
-
- public abstract void Unify(Type! that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable!, Type!>! result);
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public abstract Type/*!*/ Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst);
-
- //----------- Hashcodes ----------------------------------
-
- // Hack to be able to access the hashcode of superclasses further up
- // (from the subclasses of this class)
- [Pure]
- protected int GetBaseHashCode() {
- return base.GetHashCode();
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.GetHashCode(new List<TypeVariable>());
- }
-
- [Pure]
- public abstract int GetHashCode(List<TypeVariable>/*!*/ boundVariables);
-
- //----------- Resolution ----------------------------------
-
- public override void Resolve(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- System.Diagnostics.Debug.Fail("Type.Resolve should never be called." +
- " Use Type.ResolveType instead");
- }
-
- public abstract Type/*!*/ ResolveType(ResolutionContext/*!*/ rc);
-
- public override void Typecheck(TypecheckingContext tc) {
- //Contract.Requires(tc != null);
- System.Diagnostics.Debug.Fail("Type.Typecheck should never be called");
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public abstract List<TypeVariable>/*!*/ FreeVariables {
- get;
- }
-
- // determine the free type proxies in a type, in the order in which they occur
- public abstract List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get;
- }
-
- protected static void AppendWithoutDups<A>(List<A> a, List<A> b) {
- Contract.Requires(b != null);
- Contract.Requires(a != null);
- foreach (A x in b)
- if (!a.Contains(x))
- a.Add(x);
- }
-
- public bool IsClosed {
- get {
- return FreeVariables.Count == 0;
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- // the following methods should be used instead of simple casts or the
- // C# "is" operator, because they handle type synonym annotations and
- // type proxies correctly
-
- public virtual bool IsBasic {
- get {
- return false;
- }
- }
- public virtual bool IsInt {
- get {
- return false;
- }
- }
- public virtual bool IsReal {
- get {
- return false;
- }
- }
- public virtual bool IsFloat {
- get {
- return false;
- }
- }
- public virtual bool IsBool {
- get {
- return false;
- }
- }
-
- public virtual bool IsVariable {
- get {
- return false;
- }
- }
- public virtual TypeVariable/*!*/ AsVariable {
- get {
- Contract.Ensures(Contract.Result<TypeVariable>() != null);
-
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.AsVariable should never be called
- }
- }
- public virtual bool IsCtor {
- get {
- return false;
- }
- }
- public virtual CtorType/*!*/ AsCtor {
- get {
- Contract.Ensures(Contract.Result<CtorType>() != null);
-
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.AsCtor should never be called
- }
- }
- public virtual bool IsMap {
- get {
- return false;
- }
- }
- public virtual MapType/*!*/ AsMap {
- get {
- Contract.Ensures(Contract.Result<MapType>() != null);
-
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.AsMap should never be called
- }
- }
- public virtual int MapArity {
- get {
-
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.MapArity should never be called
- }
- }
- public virtual bool IsUnresolved {
- get {
- return false;
- }
- }
- public virtual UnresolvedTypeIdentifier/*!*/ AsUnresolved {
- get {
- Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
-
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.AsUnresolved should never be called
- }
- }
-
- public virtual bool isFloat {
- get {
- return false;
- }
- }
- public virtual int FloatExponent
- {
- get
- {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.FloatExponent should never be called
- }
- }
- public virtual int FloatMantissa {
- get {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.FloatMantissa should never be called
- }
- }
- public virtual bool IsBv {
- get {
- return false;
- }
- }
- public virtual int BvBits {
- get {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // Type.BvBits should never be called
- }
- }
-
- public static readonly Type/*!*/ Int = new BasicType(SimpleType.Int);
- public static readonly Type/*!*/ Real = new BasicType(SimpleType.Real);
- public static readonly Type/*!*/ Bool = new BasicType(SimpleType.Bool);
- private static BvType[] bvtypeCache;
-
- static public BvType GetBvType(int sz) {
- Contract.Requires(0 <= sz);
- Contract.Ensures(Contract.Result<BvType>() != null);
-
- if (bvtypeCache == null) {
- bvtypeCache = new BvType[128];
- }
- if (sz < bvtypeCache.Length) {
- BvType t = bvtypeCache[sz];
- if (t == null) {
- t = new BvType(sz);
- bvtypeCache[sz] = t;
- }
- return t;
- } else {
- return new BvType(sz);
- }
- }
-
- static public FloatType GetFloatType(int exp, int man) {
- Contract.Requires(0 <= exp);
- Contract.Requires(0 <= man);
- Contract.Ensures(Contract.Result<FloatType>() != null);
-
- return new FloatType(exp, man);
- }
-
- //------------ Match formal argument types on actual argument types
- //------------ and return the resulting substitution of type variables
-
-#if OLD_UNIFICATION
- public static IDictionary<TypeVariable!, Type!>!
- MatchArgumentTypes(List<TypeVariable>! typeParams,
- List<Type>! formalArgs,
- List<Expr>! actualArgs,
- List<Type> formalOuts,
- List<IdentifierExpr> actualOuts,
- string! opName,
- TypecheckingContext! tc)
- {
- Contract.Requires(formalArgs.Length == actualArgs.Length);
- Contract.Requires(formalOuts == null <==> actualOuts == null);
- Contract.Requires(formalOuts != null ==> formalOuts.Length == actualOuts.Length);
- List<TypeVariable>! boundVarSeq0 = new List<TypeVariable> ();
- List<TypeVariable>! boundVarSeq1 = new List<TypeVariable> ();
- Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
-
- for (int i = 0; i < formalArgs.Length; ++i) {
- try {
- Type! actualType = cce.NonNull((!)actualArgs[i]).Type;
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- Contract.Assert(forall{TypeVariable! var in typeParams);
- !actualType.FreeVariables.Has(var)};
- formalArgs[i].Unify(actualType,
- typeParams,
- boundVarSeq0, boundVarSeq1,
- subst);
- } catch (UnificationFailedException) {
- tc.Error(actualArgs[i],
- "invalid type for argument {0} in {1}: {2} (expected: {3})",
- i, opName, actualArgs[i].Type,
- // we insert the type parameters that have already been
- // chosen to get a more precise error message
- formalArgs[i].Substitute(subst));
- // the bound variable sequences should be empty ...
- // so that we can continue with the unification
- Contract.Assert(boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0);
- }
- }
-
- if (formalOuts != null) {
- for (int i = 0; i < formalOuts.Length; ++i) {
- try {
- Type! actualType = cce.NonNull((!)actualOuts[i]).Type;
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- Contract.Assert(forall{TypeVariable! var in typeParams);
- !actualType.FreeVariables.Has(var)};
- formalOuts[i].Unify(actualType,
- typeParams,
- boundVarSeq0, boundVarSeq1,
- subst);
- } catch (UnificationFailedException) {
- tc.Error(actualOuts[i],
- "invalid type for result {0} in {1}: {2} (expected: {3})",
- i, opName, actualOuts[i].Type,
- // we insert the type parameters that have already been
- // chosen to get a more precise error message
- formalOuts[i].Substitute(subst));
- // the bound variable sequences should be empty ...
- // so that we can continue with the unification
- Contract.Assert(boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0);
- }
- }
- }
-
- // we only allow type parameters to be substituted
- Contract.Assert(Contract.ForAll(subst.Keys , var=> typeParams.Has(var)));
-
- return subst;
- }
-#else
- public static IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/
- MatchArgumentTypes(List<TypeVariable>/*!*/ typeParams,
- List<Type>/*!*/ formalArgs,
- IList<Expr>/*!*/ actualArgs,
- List<Type> formalOuts,
- List<IdentifierExpr> actualOuts,
- string/*!*/ opName,
- TypecheckingContext/*!*/ tc) {
- Contract.Requires(typeParams != null);
- Contract.Requires(formalArgs != null);
- Contract.Requires(actualArgs != null);
- Contract.Requires(opName != null);
- Contract.Requires(tc != null);
- Contract.Requires(formalArgs.Count == actualArgs.Count);
- Contract.Requires((formalOuts == null) == (actualOuts == null));
- Contract.Requires(formalOuts == null || formalOuts.Count == cce.NonNull(actualOuts).Count);
- Contract.Requires(tc == null || opName != null);//Redundant
- Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
-
- // requires "actualArgs" and "actualOuts" to have been type checked
-
- Dictionary<TypeVariable/*!*/, Type/*!*/> subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- foreach (TypeVariable/*!*/ tv in typeParams) {
- Contract.Assert(tv != null);
- TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
- subst.Add(tv, proxy);
- }
-
- for (int i = 0; i < formalArgs.Count; i++) {
- Type formal = formalArgs[i].Substitute(subst);
- Type actual = cce.NonNull(cce.NonNull(actualArgs[i]).Type);
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- Contract.Assert(Contract.ForAll(0, typeParams.Count, index => !actual.FreeVariables.Contains(typeParams[index])));
-
- if (!formal.Unify(actual)) {
- Contract.Assume(tc != null); // caller expected no errors
- Contract.Assert(opName != null); // follows from precondition
- tc.Error(cce.NonNull(actualArgs[i]),
- "invalid type for argument {0} in {1}: {2} (expected: {3})",
- i, opName, actual, formalArgs[i]);
- }
- }
-
- if (formalOuts != null) {
- for (int i = 0; i < formalOuts.Count; ++i) {
- Type formal = formalOuts[i].Substitute(subst);
- Type actual = cce.NonNull(cce.NonNull(actualOuts)[i].Type);
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- Contract.Assert(Contract.ForAll(0, typeParams.Count, var => !actual.FreeVariables.Contains(typeParams[var])));
-
- if (!formal.Unify(actual)) {
- Contract.Assume(tc != null); // caller expected no errors
- Contract.Assert(opName != null); // follows from precondition
- tc.Error(actualOuts[i],
- "invalid type for out-parameter {0} in {1}: {2} (expected: {3})",
- i, opName, actual, formal);
- }
- }
- }
-
- return subst;
- }
-#endif
-
- //------------ Match formal argument types of a function or map
- //------------ on concrete types, substitute the result into the
- //------------ result type. Null is returned for type errors
-
- public static List<Type> CheckArgumentTypes(List<TypeVariable>/*!*/ typeParams,
- out List<Type/*!*/>/*!*/ actualTypeParams,
- List<Type>/*!*/ formalIns,
- IList<Expr>/*!*/ actualIns,
- List<Type>/*!*/ formalOuts,
- List<IdentifierExpr> actualOuts,
- IToken/*!*/ typeCheckingSubject,
- string/*!*/ opName,
- TypecheckingContext/*!*/ tc)
- // requires "actualIns" and "actualOuts" to have been type checked
- {
- Contract.Requires(typeParams != null);
-
- Contract.Requires(formalIns != null);
- Contract.Requires(formalOuts != null);
- Contract.Requires(actualIns != null);
- Contract.Requires(typeCheckingSubject != null);
- Contract.Requires(opName != null);Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out actualTypeParams)));
- actualTypeParams = new List<Type/*!*/>();
-
- if (formalIns.Count != actualIns.Count) {
- tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1}",
- opName, actualIns.Count);
- // if there are no type parameters, we can still return the result
- // type and hope that the type checking proceeds
- return typeParams.Count == 0 ? formalOuts : null;
- } else if (actualOuts != null && formalOuts.Count != actualOuts.Count) {
- tc.Error(typeCheckingSubject, "wrong number of result variables in {0}: {1}",
- opName, actualOuts.Count);
- // if there are no type parameters, we can still return the result
- // type and hope that the type checking proceeds
- actualTypeParams = new List<Type>();
- return typeParams.Count == 0 ? formalOuts : null;
- }
-
- int previousErrorCount = tc.ErrorCount;
- IDictionary<TypeVariable/*!*/, Type/*!*/> subst =
- MatchArgumentTypes(typeParams, formalIns, actualIns,
- actualOuts != null ? formalOuts : null, actualOuts, opName, tc);
- Contract.Assert(cce.NonNullDictionaryAndValues(subst));
- foreach (TypeVariable/*!*/ var in typeParams) {
- Contract.Assert(var != null);
- actualTypeParams.Add(subst[var]);
- }
-
- List<Type>/*!*/ actualResults = new List<Type>();
- foreach (Type/*!*/ t in formalOuts) {
- Contract.Assert(t != null);
- actualResults.Add(t.Substitute(subst));
- }
- List<TypeVariable> resultFreeVars = FreeVariablesIn(actualResults);
- if (previousErrorCount != tc.ErrorCount) {
- // errors occured when matching the formal arguments
- // in case we have been able to substitute all type parameters,
- // we can still return the result type and hope that the
- // type checking proceeds in a meaningful manner
- if (typeParams.All(param => !resultFreeVars.Contains(param)))
- return actualResults;
- else
- // otherwise there is no point in returning the result type,
- // type checking would only get confused even further
- return null;
- }
-
- Contract.Assert(Contract.ForAll(0, typeParams.Count, index => !resultFreeVars.Contains(typeParams[index])));
- return actualResults;
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- // about the same as Type.CheckArgumentTypes, but without
- // detailed error reports
- public static Type/*!*/ InferValueType(List<TypeVariable>/*!*/ typeParams,
- List<Type>/*!*/ formalArgs,
- Type/*!*/ formalResult,
- List<Type>/*!*/ actualArgs) {
- Contract.Requires(typeParams != null);
- Contract.Requires(formalArgs != null);
- Contract.Requires(formalResult != null);
- Contract.Requires(actualArgs != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst =
- InferTypeParameters(typeParams, formalArgs, actualArgs);
- Contract.Assert(cce.NonNullDictionaryAndValues(subst));
-
- Type/*!*/ res = formalResult.Substitute(subst);
- Contract.Assert(res != null);
- // all type parameters have to be substituted with concrete types
- List<TypeVariable>/*!*/ resFreeVars = res.FreeVariables;
- Contract.Assert(resFreeVars != null);
- Contract.Assert(Contract.ForAll(0, typeParams.Count, var => !resFreeVars.Contains(typeParams[var])));
- return res;
- }
-
-#if OLD_UNIFICATION
- public static IDictionary<TypeVariable!, Type!>!
- InferTypeParameters(List<TypeVariable>! typeParams,
- List<Type>! formalArgs,
- List<Type>! actualArgs)
- {
- Contract.Requires(formalArgs.Length == actualArgs.Length);
-
- List<TypeVariable>! boundVarSeq0 = new List<TypeVariable> ();
- List<TypeVariable>! boundVarSeq1 = new List<TypeVariable> ();
- Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
-
- for (int i = 0; i < formalArgs.Length; ++i) {
- try {
- Contract.Assert(forall{TypeVariable! var in typeParams);
- !actualArgs[i].FreeVariables.Has(var)};
- formalArgs[i].Unify(actualArgs[i], typeParams,
- boundVarSeq0, boundVarSeq1, subst);
- } catch (UnificationFailedException) {
- System.Diagnostics.Debug.Fail("Type unification failed: " +
- formalArgs[i] + " vs " + actualArgs[i]);
- }
- }
-
- // we only allow type parameters to be substituted
- Contract.Assert(Contract.ForAll(subst.Keys , var=> typeParams.Has(var)));
- return subst;
- }
-#else
- /// <summary>
- /// like Type.CheckArgumentTypes, but assumes no errors
- /// (and only does arguments, not results; and takes actuals as List<Type>, not List<Expr>)
- /// </summary>
- public static IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/
- InferTypeParameters(List<TypeVariable>/*!*/ typeParams,
- List<Type>/*!*/ formalArgs,
- List<Type>/*!*/ actualArgs) {
- Contract.Requires(typeParams != null);
- Contract.Requires(formalArgs != null);
- Contract.Requires(actualArgs != null);Contract.Requires(formalArgs.Count == actualArgs.Count);
- Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
-
-
- List<Type> proxies = new List<Type>();
- Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- foreach (TypeVariable/*!*/ tv in typeParams) {
- Contract.Assert(tv != null);
- TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
- proxies.Add(proxy);
- subst.Add(tv, proxy);
- }
-
- for (int i = 0; i < formalArgs.Count; i++) {
- Type formal = formalArgs[i].Substitute(subst);
- Type actual = actualArgs[i];
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- Contract.Assert(Contract.ForAll(0, typeParams.Count, index => !actual.FreeVariables.Contains(typeParams[index])));
-
- if (!formal.Unify(actual)) {
- Contract.Assume(false); // caller expected no errors
- }
- }
-
- return subst;
- }
-#endif
-
- //----------- Helper methods to deal with bound type variables ---------------
-
- public static void EmitOptionalTypeParams(TokenTextWriter stream, List<TypeVariable> typeParams) {
- Contract.Requires(typeParams != null);
- Contract.Requires(stream != null);
- if (typeParams.Count > 0) {
- stream.Write("<");
- typeParams.Emit(stream, ","); // default binding strength of 0 is ok
- stream.Write(">");
- }
- }
-
- // Sort the type parameters according to the order of occurrence in the argument types
- public static List<TypeVariable>/*!*/ SortTypeParams(List<TypeVariable>/*!*/ typeParams, List<Type>/*!*/ argumentTypes, Type resultType) {
- Contract.Requires(typeParams != null);
- Contract.Requires(argumentTypes != null);
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- Contract.Ensures(Contract.Result<List<TypeVariable>>().Count == typeParams.Count);
- if (typeParams.Count == 0) {
- return typeParams;
- }
-
- List<TypeVariable> freeVarsInUse = FreeVariablesIn(argumentTypes);
- if (resultType != null) {
- freeVarsInUse.AppendWithoutDups(resultType.FreeVariables);
- }
- // "freeVarsInUse" is already sorted, but it may contain type variables not in "typeParams".
- // So, project "freeVarsInUse" onto "typeParams":
- List<TypeVariable> sortedTypeParams = new List<TypeVariable>();
- foreach (TypeVariable/*!*/ var in freeVarsInUse) {
- Contract.Assert(var != null);
- if (typeParams.Contains(var)) {
- sortedTypeParams.Add(var);
- }
- }
-
- if (sortedTypeParams.Count < typeParams.Count)
- // add the type parameters not mentioned in "argumentTypes" in
- // the end of the list (this can happen for quantifiers)
- sortedTypeParams.AppendWithoutDups(typeParams);
-
- return sortedTypeParams;
- }
-
- // Check that each of the type parameters occurs in at least one argument type.
- // Return true if some type parameters appear only among "moreArgumentTypes" and
- // not in "argumentTypes".
- [Pure]
- public static bool CheckBoundVariableOccurrences(List<TypeVariable>/*!*/ typeParams,
- List<Type>/*!*/ argumentTypes,
- List<Type> moreArgumentTypes,
- IToken/*!*/ resolutionSubject,
- string/*!*/ subjectName,
- ResolutionContext/*!*/ rc) {
- Contract.Requires(typeParams != null);
- Contract.Requires(argumentTypes != null);
- Contract.Requires(resolutionSubject != null);
- Contract.Requires(subjectName != null);
- Contract.Requires(rc != null);
- List<TypeVariable> freeVarsInArgs = FreeVariablesIn(argumentTypes);
- List<TypeVariable> moFreeVarsInArgs = moreArgumentTypes == null ? null : FreeVariablesIn(moreArgumentTypes);
- bool someTypeParamsAppearOnlyAmongMo = false;
- foreach (TypeVariable/*!*/ var in typeParams) {
- Contract.Assert(var != null);
- if (rc.LookUpTypeBinder(var.Name) == var) // avoid to complain twice about variables that are bound multiple times
- {
- if (freeVarsInArgs.Contains(var)) {
- // cool
- } else if (moFreeVarsInArgs != null && moFreeVarsInArgs.Contains(var)) {
- someTypeParamsAppearOnlyAmongMo = true;
- } else {
- rc.Error(resolutionSubject,
- "type variable must occur in {0}: {1}",
- subjectName, var);
- }
- }
- }
- return someTypeParamsAppearOnlyAmongMo;
- }
-
- [Pure]
- public static List<TypeVariable> FreeVariablesIn(List<Type> arguments) {
- Contract.Requires(arguments != null);
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
- List<TypeVariable>/*!*/ res = new List<TypeVariable>();
- foreach (Type/*!*/ t in arguments) {
- Contract.Assert(t != null);
- res.AppendWithoutDups(t.FreeVariables);
- }
- return res;
- }
- }
- [ContractClassFor(typeof(Type))]
- public abstract class TypeContracts : Type {
- public TypeContracts() :base(null){
-
- }
- public override List<TypeProxy> FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- throw new NotImplementedException();
- }
- }
- public override List<TypeVariable> FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
- throw new NotImplementedException();
- }
- }
- public override Type Clone(IDictionary<TypeVariable, TypeVariable> varMap) {
- Contract.Requires(cce.NonNullDictionaryAndValues(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- Contract.Requires(stream != null);
- throw new NotImplementedException();
- }
- public override bool Equals(Type that, List<TypeVariable> thisBoundVariables, List<TypeVariable> thatBoundVariables) {
- Contract.Requires(that != null);
- Contract.Requires(thisBoundVariables != null);
- Contract.Requires(thatBoundVariables != null);
- throw new NotImplementedException();
- }
- public override bool Unify(Type that, List<TypeVariable> unifiableVariables, IDictionary<TypeVariable, Type> unifier) {
- Contract.Requires(that != null);
- Contract.Requires(unifiableVariables != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(unifier));
- Contract.Requires(Contract.ForAll(unifier.Keys, key => unifiableVariables.Contains(key)));
- Contract.Requires(IsIdempotent(unifier));
- throw new NotImplementedException();
- }
- public override Type Substitute(IDictionary<TypeVariable, Type> subst) {
- Contract.Requires(cce.NonNullDictionaryAndValues(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- public override Type ResolveType(ResolutionContext rc) {
- Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- Contract.Requires(boundVariables != null);
- throw new NotImplementedException();
- }
- }
- //=====================================================================
-
- public class BasicType : Type {
- public readonly SimpleType T;
- public BasicType(IToken/*!*/ token, SimpleType t)
- : base(token) {
- Contract.Requires(token != null);
- T = t;
- }
- public BasicType(SimpleType t)
- : base(Token.NoToken) {
- T = t;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively.
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- // BasicTypes are immutable anyway, we do not clone
- return this;
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- // no parentheses are necessary for basic types
- stream.SetToken(this);
- stream.Write("{0}", this);
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- switch (T) {
- case SimpleType.Int:
- return "int";
- case SimpleType.Real:
- return "real";
- case SimpleType.Bool:
- return "bool";
- }
- Debug.Assert(false, "bad type " + T);
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // make compiler happy
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- // shortcut
- Type thatType = that as Type;
- if (thatType == null)
- return false;
- BasicType thatBasicType = TypeProxy.FollowProxy(thatType.Expanded) as BasicType;
- return thatBasicType != null && this.T == thatBasicType.T;
- }
-
- [Pure]
- public override bool Equals(Type that, List<TypeVariable> thisBoundVariables, List<TypeVariable> thatBoundVariables) {
- //Contract.Requires(thatBoundVariables != null);
- //Contract.Requires(thisBoundVariables != null);
- //Contract.Requires(that != null);
- return this.Equals(that);
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type that, List<TypeVariable> unifiableVariables, IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(that != null);
- //Contract.Requires(cce.NonNullElements(unifier));
- // an idempotent substitution that describes the
- // unification result up to a certain point
-
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable) {
- return that.Unify(this, unifiableVariables, unifier);
- } else {
- return this.Equals(that);
- }
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- } else {
- if (!this.Equals(that))
- throw UNIFICATION_FAILED;
- }
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- return this.T.GetHashCode();
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // nothing to resolve
- return this;
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- return new List<TypeVariable>(); // basic type are closed
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- return new List<TypeProxy/*!*/>();
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBasic {
- get {
- return true;
- }
- }
- public override bool IsInt {
- get {
- return this.T == SimpleType.Int;
- }
- }
- public override bool IsReal {
- get {
- return this.T == SimpleType.Real;
- }
- }
- public override bool IsBool {
- get {
- return this.T == SimpleType.Bool;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBasicType(this);
- }
- }
-
- //=====================================================================
-
- //Note that the functions in this class were directly copied from the BV class just below
- public class FloatType : Type {
- public readonly int Mantissa; //Size of mantissa in bits
- public readonly int Exponent; //Size of exponent in bits
-
- public FloatType(IToken token, int exponent, int mantissa)
- : base(token) {
- Contract.Requires(token != null);
- Exponent = exponent;
- Mantissa = mantissa;
- }
-
- public FloatType(int exponent, int mantissa)
- : base(Token.NoToken) {
- Exponent = exponent;
- Mantissa = mantissa;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively.
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap)
- {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- // FloatTypes are immutable anyway, we do not clone
- return this;
- }
-
- public override Type CloneUnresolved()
- {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength)
- {
- //Contract.Requires(stream != null);
- // no parentheses are necessary for bitvector-types
- stream.SetToken(this);
- stream.Write("{0}", this);
- }
-
- public override string ToString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return "float (" + Exponent + " " + Mantissa + ")";
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type/*!*/ that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables)
- {
- FloatType thatFloatType = TypeProxy.FollowProxy(that.Expanded) as FloatType;
- return thatFloatType != null && this.Mantissa == thatFloatType.Mantissa && this.Exponent == thatFloatType.Exponent;
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier)
- {
- //Contract.Requires(that != null);
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(cce.NonNullElements(unifier));
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable) {
- return that.Unify(this, unifiableVariables, unifier);
- }
- else {
- return this.Equals(that);
- }
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst)
- {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables)
- {
- return this.Mantissa.GetHashCode() + this.Exponent.GetHashCode();
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc)
- {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // nothing to resolve
- return this;
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public override List<TypeVariable>/*!*/ FreeVariables
- {
- get
- {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- return new List<TypeVariable>(); // bitvector-type are closed
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- return new List<TypeProxy/*!*/>();
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsFloat {
- get {
- return true;
- }
- }
- public override int FloatMantissa {
- get {
- return Mantissa;
- }
- }
- public override int FloatExponent {
- get {
- return Exponent;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor)
- {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitFloatType(this);
- }
-
- }
-
- //=====================================================================
-
- public class BvType : Type {
- public readonly int Bits;
-
- public BvType(IToken token, int bits)
- : base(token) {
- Contract.Requires(token != null);
- Bits = bits;
- }
-
- public BvType(int bits)
- : base(Token.NoToken) {
- Bits = bits;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively.
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- // BvTypes are immutable anyway, we do not clone
- return this;
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- // no parentheses are necessary for bitvector-types
- stream.SetToken(this);
- stream.Write("{0}", this);
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "bv" + Bits;
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type/*!*/ that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables) {
- //Contract.Requires(thisBoundVariables != null);
- //Contract.Requires(thatBoundVariables != null);
- //Contract.Requires(that != null);
- BvType thatBvType = TypeProxy.FollowProxy(that.Expanded) as BvType;
- return thatBvType != null && this.Bits == thatBvType.Bits;
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
- //Contract.Requires(that != null);
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(cce.NonNullElements(unifier));
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable) {
- return that.Unify(this, unifiableVariables, unifier);
- } else {
- return this.Equals(that);
- }
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!> result){
-Contract.Requires(result != null);
-Contract.Requires(that != null);
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- } else {
- if (!this.Equals(that))
- throw UNIFICATION_FAILED;
- }
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- return this.Bits.GetHashCode();
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // nothing to resolve
- return this;
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- return new List<TypeVariable>(); // bitvector-type are closed
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- return new List<TypeProxy/*!*/>();
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBv {
- get {
- return true;
- }
- }
- public override int BvBits {
- get {
- return Bits;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBvType(this);
- }
- }
-
- //=====================================================================
-
- // An AST node containing an identifier and a sequence of type arguments, which
- // will be turned either into a TypeVariable, into a CtorType or into a BvType
- // during the resolution phase
- public class UnresolvedTypeIdentifier : Type {
- public readonly string/*!*/ Name;
- public readonly List<Type>/*!*/ Arguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- Contract.Invariant(Arguments != null);
- }
-
-
- public UnresolvedTypeIdentifier(IToken token, string name)
- : this(token, name, new List<Type>()) {
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- }
-
- public UnresolvedTypeIdentifier(IToken token, string name, List<Type> arguments)
- : base(token) {
- Contract.Requires(arguments != null);
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- this.Name = name;
- this.Arguments = arguments;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.Clone(varMap));
- }
- return new UnresolvedTypeIdentifier(tok, Name, newArgs);
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.CloneUnresolved());
- }
- return new UnresolvedTypeIdentifier(tok, Name, newArgs);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables) {
- //Contract.Requires(thisBoundVariables != null);
- //Contract.Requires(thatBoundVariables != null);
- //Contract.Requires(that != null);
- System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Equals should never be called");
- return false; // to make the compiler happy
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/> result) {
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(cce.NonNullElements(result));
- //Contract.Requires(that != null);
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // UnresolvedTypeIdentifier.Unify should never be called
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!> result){
-Contract.Requires(result != null);
-Contract.Requires(that != null);
- System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Unify should never be called");
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // UnresolvedTypeIdentifier.Substitute should never be called
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // UnresolvedTypeIdentifier.GetHashCode should never be called
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // first case: the type name denotes a bitvector-type
- if (Name.StartsWith("bv") && Name.Length > 2) {
- bool is_bv = true;
- for (int i = 2; i < Name.Length; ++i) {
- if (!char.IsDigit(Name[i])) {
- is_bv = false;
- break;
- }
- }
- if (is_bv) {
- if (Arguments.Count > 0) {
- rc.Error(this,
- "bitvector types must not be applied to arguments: {0}",
- Name);
- }
- return new BvType(tok, int.Parse(Name.Substring(2)));
- }
- }
-
- // second case: the identifier is resolved to a type variable
- TypeVariable var = rc.LookUpTypeBinder(Name);
- if (var != null) {
- if (Arguments.Count > 0) {
- rc.Error(this,
- "type variables must not be applied to arguments: {0}",
- var);
- }
- return var;
- }
-
- // third case: the identifier denotes a type constructor and we
- // recursively resolve the arguments
- TypeCtorDecl ctorDecl = rc.LookUpType(Name);
- if (ctorDecl != null) {
- if (Arguments.Count != ctorDecl.Arity) {
- rc.Error(this,
- "type constructor received wrong number of arguments: {0}",
- ctorDecl);
- return this;
- }
- return new CtorType(tok, ctorDecl, ResolveArguments(rc));
- }
-
- // fourth case: the identifier denotes a type synonym
- TypeSynonymDecl synDecl = rc.LookUpTypeSynonym(Name);
- if (synDecl != null) {
- if (Arguments.Count != synDecl.TypeParameters.Count) {
- rc.Error(this,
- "type synonym received wrong number of arguments: {0}",
- synDecl);
- return this;
- }
- List<Type>/*!*/ resolvedArgs = ResolveArguments(rc);
- Contract.Assert(resolvedArgs != null);
-
- return new TypeSynonymAnnotation(this.tok, synDecl, resolvedArgs);
-
- }
-
- // otherwise: this name is not declared anywhere
- rc.Error(this, "undeclared type: {0}", Name);
- return this;
- }
-
- private List<Type> ResolveArguments(ResolutionContext rc) {
- Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<List<Type>>() != null);
- List<Type>/*!*/ resolvedArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- resolvedArgs.Add(t.ResolveType(rc));
- }
- return resolvedArgs;
- }
-
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- return new List<TypeVariable>();
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- return new List<TypeProxy/*!*/>();
- }
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- // PR: should unresolved types be syntactically distinguished from resolved types?
- CtorType.EmitCtorType(this.Name, Arguments, stream, contextBindingStrength);
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsUnresolved {
- get {
- return true;
- }
- }
- public override UnresolvedTypeIdentifier/*!*/ AsUnresolved {
- get {
- Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
- return this;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitUnresolvedTypeIdentifier(this);
- }
- }
-
- //=====================================================================
-
- public class TypeVariable : Type {
- public readonly string/*!*/ Name;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- }
-
-
- public TypeVariable(IToken token, string name)
- : base(token) {
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- this.Name = name;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- // if this variable is mapped to some new variable, we take the new one
- // otherwise, return this
- TypeVariable res;
- varMap.TryGetValue(this, out res);
- if (res == null)
- return this;
- else
- return res;
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- return this;
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables) {
- //Contract.Requires(thisBoundVariables != null);
- //Contract.Requires(thatBoundVariables != null);
- //Contract.Requires(that != null);
- TypeVariable thatAsTypeVar = TypeProxy.FollowProxy(that.Expanded) as TypeVariable;
-
- if (thatAsTypeVar == null)
- return false;
-
- int thisIndex = thisBoundVariables.LastIndexOf(this);
- int thatIndex = thatBoundVariables.LastIndexOf(thatAsTypeVar);
- return (thisIndex >= 0 && thisIndex == thatIndex) ||
- (thisIndex == -1 && thatIndex == -1 &&
- Object.ReferenceEquals(this, thatAsTypeVar));
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
- //Contract.Requires(that != null);
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(cce.NonNullElements(unifier));
- that = that.Expanded;
- if (that is TypeProxy && !(that is ConstrainedProxy))
- return that.Unify(this, unifiableVariables, unifier);
-
- if (this.Equals(that))
- return true;
-
- if (unifiableVariables.Contains(this)) {
- Type previousSubst;
- unifier.TryGetValue(this, out previousSubst);
- if (previousSubst == null) {
- return addSubstitution(unifier, that);
- } else {
- // we have to unify the old instantiation with the new one
- return previousSubst.Unify(that, unifiableVariables, unifier);
- }
- }
-
- // this cannot be instantiated with anything
- // but that possibly can ...
-
- TypeVariable tv = that as TypeVariable;
-
- return tv != null &&
- unifiableVariables.Contains(tv) &&
- that.Unify(this, unifiableVariables, unifier);
- }
-
- // TODO: the following might cause problems, because when applying substitutions
- // to type proxies the substitutions are not propagated to the proxy
- // constraints (right now at least)
- private bool addSubstitution(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ oldSolution,
- // the type that "this" is instantiated with
- Type/*!*/ newSubst) {
- Contract.Requires(cce.NonNullDictionaryAndValues(oldSolution));
- Contract.Requires(newSubst != null);
- Contract.Requires(!oldSolution.ContainsKey(this));
-
- Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ newMapping = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- // apply the old (idempotent) substitution to the new instantiation
- Type/*!*/ substSubst = newSubst.Substitute(oldSolution);
- Contract.Assert(substSubst != null);
- // occurs check
- if (substSubst.FreeVariables.Contains(this))
- return false;
- newMapping.Add(this, substSubst);
-
- // apply the new substitution to the old ones to ensure idempotence
- List<TypeVariable/*!*/>/*!*/ keys = new List<TypeVariable/*!*/>();
- keys.AddRange(oldSolution.Keys);
- foreach (TypeVariable/*!*/ var in keys) {
- Contract.Assert(var != null);
- oldSolution[var] = oldSolution[var].Substitute(newMapping);
- }
- oldSolution.Add(this, substSubst);
-
- Contract.Assert(IsIdempotent(oldSolution));
- return true;
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!> result){
-Contract.Requires(result != null);
-Contract.Requires(that != null);
- that = that.Expanded;
- int thisIndex = thisBoundVariables.LastIndexOf(this);
- if (thisIndex == -1) {
- // this is not a bound variable and can possibly be matched on that
- // that must not contain any bound variables
- List<TypeVariable>! thatFreeVars = that.FreeVariables;
- if (thatBoundVariables.Any(var=> thatFreeVars.Has(var)))
- throw UNIFICATION_FAILED;
-
- // otherwise, in case that is a typevariable it cannot be bound and
- // we can just check for equality
- if (this.Equals(that))
- return;
-
- if (!unifiableVariables.Has(this)) {
- // this cannot be instantiated with anything
- // but that possibly can ...
- if ((that is TypeVariable) &&
- unifiableVariables.Has(that as TypeVariable)) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- return;
- } else {
- throw UNIFICATION_FAILED;
- }
- }
-
- Type previousSubst;
- result.TryGetValue(this, out previousSubst);
- if (previousSubst == null) {
- addSubstitution(result, that);
- } else {
- // we have to unify the old instantiation with the new one
- previousSubst.Unify(that, unifiableVariables, thisBoundVariables, thatBoundVariables, result);
- }
- } else {
- // this is a bound variable, that also has to be one (with the same index)
- if (!(that is TypeVariable) ||
- thatBoundVariables.LastIndexOf(that) != thisIndex)
- throw UNIFICATION_FAILED;
- }
- }
-
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- Type res;
- if (subst.TryGetValue(this, out res)) {
- Contract.Assert(res != null);
- return res;
- } else {
- return this;
- }
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- int thisIndex = boundVariables.LastIndexOf(this);
- if (thisIndex == -1)
- return GetBaseHashCode();
- return thisIndex * 27473671;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- // never put parentheses around variables
- stream.SetToken(this);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- //Contract.Ensures(Contract.Result<Type>() != null);
- // nothing to resolve
- return this;
- }
-
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
- return new List<TypeVariable> { this };
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- return new List<TypeProxy/*!*/>();
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsVariable {
- get {
- return true;
- }
- }
- public override TypeVariable/*!*/ AsVariable {
- get {
- Contract.Ensures(Contract.Result<TypeVariable>() != null);
- return this;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- //Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTypeVariable(this);
- }
- }
-
- //=====================================================================
-
- public class TypeProxy : Type {
- static int proxies = 0;
- protected readonly string/*!*/ Name;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- }
-
-
- public TypeProxy(IToken token, string givenName)
- : this(token, givenName, "proxy") {
- Contract.Requires(givenName != null);
- Contract.Requires(token != null);
- }
-
- protected TypeProxy(IToken token, string givenName, string kind)
- : base(token) {
- Contract.Requires(kind != null);
- Contract.Requires(givenName != null);
- Contract.Requires(token != null);
- Name = givenName + "$" + kind + "#" + proxies;
- proxies++;
- }
-
- private Type proxyFor;
- public Type ProxyFor {
- // apply path shortening, and then return the value of proxyFor
- get {
- TypeProxy anotherProxy = proxyFor as TypeProxy;
- if (anotherProxy != null && anotherProxy.proxyFor != null) {
- // apply path shortening by bypassing "anotherProxy" (and possibly others)
- proxyFor = anotherProxy.ProxyFor;
- Contract.Assert(proxyFor != null);
- }
- return proxyFor;
- }
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Everything)]
- public static Type FollowProxy(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Ensures(!(Contract.Result<Type>() is TypeProxy) || ((TypeProxy)Contract.Result<Type>()).proxyFor == null);
- if (t is TypeProxy) {
- Type p = ((TypeProxy)t).ProxyFor;
- if (p != null) {
- return p;
- }
- }
- return t;
- }
-
- protected void DefineProxy(Type ty) {
- Contract.Requires(ty != null);
- Contract.Requires(ProxyFor == null);
- // follow ty down to the leaf level, so that we can avoid creating a cycle
- ty = FollowProxy(ty);
- if (!object.ReferenceEquals(this, ty)) {
- proxyFor = ty;
- }
- }
-
- //----------- Cloning ----------------------------------
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.Clone(varMap);
- } else {
- return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
- }
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables) {
- //Contract.Requires(thisBoundVariables != null);
- //Contract.Requires(thatBoundVariables != null);
- //Contract.Requires(that != null);
- if (object.ReferenceEquals(this, that)) {
- return true;
- }
- Type p = ProxyFor;
- if (p != null) {
- return p.Equals(that, thisBoundVariables, thatBoundVariables);
- } else {
- // This proxy could be made to be equal to anything, so what to return?
- return false;
- }
- }
-
- //----------- Unification of types -----------
-
- // determine whether the occurs check fails: this is a strict subtype of that
- protected bool ReallyOccursIn(Type that) {
- Contract.Requires(that != null);
- that = FollowProxy(that.Expanded);
- return that.FreeProxies.Contains(this) &&
- (that.IsCtor || that.IsMap && this != that && this.ProxyFor != that);
- }
-
- public override bool Unify(Type that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/> result) {
- //Contract.Requires(cce.NonNullElements(result));
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(that != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.Unify(that, unifiableVariables, result);
- } else {
- // unify this with that
- if (this.ReallyOccursIn(that))
- return false;
- DefineProxy(that.Expanded);
- return true;
- }
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.Substitute(subst);
- } else {
- return this;
- }
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.GetHashCode(boundVariables);
- } else {
- return GetBaseHashCode();
- }
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- Type p = ProxyFor;
- if (p != null) {
- p.Emit(stream, contextBindingStrength);
- } else {
- // no need for parentheses
- stream.SetToken(this);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.ResolveType(rc);
- } else {
- return this;
- }
- }
-
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- Type p = ProxyFor;
- if (p != null) {
- return p.FreeVariables;
- } else {
- return new List<TypeVariable>();
- }
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- Type p = ProxyFor;
- if (p != null) {
- return p.FreeProxies;
- } else {
- List<TypeProxy/*!*/>/*!*/ res = new List<TypeProxy/*!*/>();
- res.Add(this);
- return res;
- }
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBasic {
- get {
- Type p = ProxyFor;
- return p != null && p.IsBasic;
- }
- }
- public override bool IsInt {
- get {
- Type p = ProxyFor;
- return p != null && p.IsInt;
- }
- }
- public override bool IsReal {
- get {
- Type p = ProxyFor;
- return p != null && p.IsReal;
- }
- }
- public override bool IsFloat {
- get {
- Type p = ProxyFor;
- return p != null && p.IsFloat;
- }
- }
- public override bool IsBool {
- get {
- Type p = ProxyFor;
- return p != null && p.IsBool;
- }
- }
-
- public override bool IsVariable {
- get {
- Type p = ProxyFor;
- return p != null && p.IsVariable;
- }
- }
- public override TypeVariable/*!*/ AsVariable {
- get {
- Contract.Ensures(Contract.Result<TypeVariable>() != null);
-
- Type p = ProxyFor;
- Contract.Assume(p != null);
- return p.AsVariable;
- }
- }
-
- public override bool IsCtor {
- get {
- Type p = ProxyFor;
- return p != null && p.IsCtor;
- }
- }
- public override CtorType/*!*/ AsCtor {
- get {
- Contract.Ensures(Contract.Result<CtorType>() != null);
-
- Type p = ProxyFor;
- Contract.Assume(p != null);
- return p.AsCtor;
- }
- }
- public override bool IsMap {
- get {
- Type p = ProxyFor;
- return p != null && p.IsMap;
- }
- }
- public override MapType/*!*/ AsMap {
- get {
- Contract.Ensures(Contract.Result<MapType>() != null);
-
- Type p = ProxyFor;
- Contract.Assume(p != null);
- return p.AsMap;
- }
- }
- public override int MapArity {
- get {
- Type p = ProxyFor;
- Contract.Assume(p != null);
- return p.MapArity;
- }
- }
- public override bool IsUnresolved {
- get {
- Type p = ProxyFor;
- return p != null && p.IsUnresolved;
- }
- }
- public override UnresolvedTypeIdentifier/*!*/ AsUnresolved {
- get {
- Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
-
- Type p = ProxyFor;
- Contract.Assume(p != null);
- return p.AsUnresolved;
- }
- }
-
- public override bool IsBv {
- get {
- Type p = ProxyFor;
- return p != null && p.IsBv;
- }
- }
- public override int BvBits {
- get {
- Type p = ProxyFor;
- Contract.Assume(p != null);
- return p.BvBits;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTypeProxy(this);
- }
- }
-
- public abstract class ConstrainedProxy : TypeProxy {
- protected ConstrainedProxy(IToken token, string givenName, string kind)
- : base(token, givenName, kind) {
- Contract.Requires(kind != null);
- Contract.Requires(givenName != null);
- Contract.Requires(token != null);
- }
- }
-
- /// <summary>
- /// Each instance of this class represents a set of bitvector types. In particular, it represents
- /// a bitvector type bvN iff
- /// minBits ATMOST N and
- /// foreach constraint (t0,t1), the types represented by t0 and t1 are bitvector types whose
- /// number of bits add up to N.
- /// This means that the size of a BvTypeProxy p is constrained not only by p.minBits, but also
- /// by the size of various t0 and t1 types that are transitively part of BvTypeProxy constraints.
- /// If such a t0 or t1 were to get its ProxyFor field defined, then p would have to be further
- /// constrained too. This doesn't seem like it would ever occur in a Boogie 2 program, because:
- /// the only place where a BvTypeProxy with constraints can occur is as the type of a
- /// BvConcatExpr, and
- /// the types of all local variables are explicitly declared, which means that the types of
- /// subexpressions of a BvConcatExpr are not going to change other than via the type of the
- /// BvConcatExpr.
- /// So, this implementation of BvTypeProxy does not keep track of where a BvTypeProxy may occur
- /// transitively in some other BvTypeProxy's constraints.
- /// </summary>
- public class BvTypeProxy : ConstrainedProxy {
- public int MinBits;
- List<BvTypeConstraint/*!*/> constraints;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(constraints, true));
- }
-
- class BvTypeConstraint {
- public Type/*!*/ T0;
- public Type/*!*/ T1;
- public BvTypeConstraint(Type t0, Type t1) {
- Contract.Requires(t1 != null);
- Contract.Requires(t0 != null);
- Contract.Requires(t0.IsBv && t1.IsBv);
- T0 = t0;
- T1 = t1;
- }
- }
-
- public BvTypeProxy(IToken token, string name, int minBits)
- : base(token, name, "bv" + minBits + "proxy") {
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- this.MinBits = minBits;
- }
-
- /// <summary>
- /// Requires that any further constraints to be placed on t0 and t1 go via the object to
- /// be constructed.
- /// </summary>
- public BvTypeProxy(IToken token, string name, Type t0, Type t1)
- : base(token, name, "bvproxy") {
- Contract.Requires(t1 != null);
- Contract.Requires(t0 != null);
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- Contract.Requires(t0.IsBv && t1.IsBv);
- t0 = FollowProxy(t0);
- t1 = FollowProxy(t1);
- this.MinBits = MinBitsFor(t0) + MinBitsFor(t1);
- List<BvTypeConstraint/*!*/> list = new List<BvTypeConstraint/*!*/>();
- list.Add(new BvTypeConstraint(t0, t1));
- this.constraints = list;
- }
-
- /// <summary>
- /// Construct a BvTypeProxy like p, but with minBits.
- /// </summary>
- private BvTypeProxy(BvTypeProxy p, int minBits)
- : base(p.tok, p.Name, "") {
- Contract.Requires(p != null);
- this.MinBits = minBits;
- this.constraints = p.constraints;
- }
-
- private BvTypeProxy(IToken token, string name, int minBits, List<BvTypeConstraint/*!*/> constraints)
- : base(token, name, "") {
- Contract.Requires(cce.NonNullElements(constraints, true));
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- this.MinBits = minBits;
- this.constraints = constraints;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Everything)]
- private static int MinBitsFor(Type t) {
- Contract.Requires(t != null);
- Contract.Requires(t.IsBv);
- Contract.Ensures(0 <= Contract.Result<int>());
-
- if (t is TypeSynonymAnnotation) {
- return MinBitsFor(((TypeSynonymAnnotation)t).ExpandedType);
- }
-
- if (t is BvType) {
- return t.BvBits;
- } else {
- return ((BvTypeProxy)t).MinBits;
- }
- }
-
- //----------- Cloning ----------------------------------
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.Clone(varMap);
- } else {
- return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
- }
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type that,
- List<TypeVariable> unifiableVariables,
- IDictionary<TypeVariable, Type> result) {
- //Contract.Requires(cce.NonNullElements(result));
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(that != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.Unify(that, unifiableVariables, result);
- }
-
- // unify this with that, if possible
- that = that.Expanded;
- that = FollowProxy(that);
-
- if (this.ReallyOccursIn(that))
- return false;
-
- TypeVariable tv = that as TypeVariable;
-
- if (tv != null && unifiableVariables.Contains(tv))
- return that.Unify(this, unifiableVariables, result);
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- } else if (that is BvType) {
- if (MinBits <= that.BvBits) {
- if (constraints != null) {
- foreach (BvTypeConstraint btc in constraints) {
- int minT1 = MinBitsFor(btc.T1);
- int left = IncreaseBits(btc.T0, that.BvBits - minT1);
- left = IncreaseBits(btc.T1, minT1 + left);
- Contract.Assert(left == 0); // because it should always be possible to increase the total size of a BvTypeConstraint pair (t0,t1) arbitrarily
- }
- }
- DefineProxy(that);
- return true;
- }
- } else if (that is BvTypeProxy) {
- BvTypeProxy bt = (BvTypeProxy)that;
- // keep the proxy with the stronger constraint (that is, the higher minBits), but if either
- // has a constraints list, then concatenate both constraints lists and define the previous
- // proxies to the new one
- if (this.constraints != null || bt.constraints != null) {
- List<BvTypeConstraint/*!*/> list = new List<BvTypeConstraint/*!*/>();
- if (this.constraints != null) {
- list.AddRange(this.constraints);
- }
- if (bt.constraints != null) {
- list.AddRange(bt.constraints);
- }
- BvTypeProxy np = new BvTypeProxy(this.tok, this.Name, Math.Max(this.MinBits, bt.MinBits), list);
- this.DefineProxy(np);
- bt.DefineProxy(np);
- } else if (this.MinBits <= bt.MinBits) {
- this.DefineProxy(bt);
- } else {
- bt.DefineProxy(this);
- }
- return true;
- } else if (that is ConstrainedProxy) {
- // only bitvector proxies can be unified with this BvTypeProxy
- return false;
- } else if (that is TypeProxy) {
- // define: that.ProxyFor := this;
- return that.Unify(this, unifiableVariables, result);
- }
- return false;
- }
-
- private static int IncreaseBits(Type t, int to) {
- Contract.Requires(t != null);
- Contract.Requires(t.IsBv && 0 <= to && MinBitsFor(t) <= to);
- Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() <= to);
-
- if(t is TypeSynonymAnnotation) {
- return IncreaseBits(((TypeSynonymAnnotation)t).ExpandedType, to);
- }
-
- t = FollowProxy(t);
- if (t is BvType) {
- return to - t.BvBits;
- } else {
- BvTypeProxy p = (BvTypeProxy)t;
- Contract.Assert(p.MinBits <= to);
- if (p.MinBits < to) {
- BvTypeProxy q = new BvTypeProxy(p, to);
- p.DefineProxy(q);
- }
- return 0; // we were able to satisfy the request completely
- }
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- if (this.ProxyFor == null) {
- // check that the constraints are clean and do not contain any
- // of the substituted variables (otherwise, we are in big trouble)
- Contract.Assert(Contract.ForAll(constraints, c =>
- Contract.ForAll(subst.Keys, var =>
- !c.T0.FreeVariables.Contains(var) && !c.T1.FreeVariables.Contains(var))));
- }
- return base.Substitute(subst);
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBv {
- get {
- return true;
- }
- }
- public override int BvBits {
- get {
- // This method is supposed to return the number of bits supplied, but unless the proxy has been resolved,
- // we only have a lower bound on the number of bits supplied. But this method is not supposed to be
- // called until type checking has finished, at which time the minBits is stable.
- Type p = ProxyFor;
- if (p != null) {
- return p.BvBits;
- } else {
- return MinBits;
- }
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitBvTypeProxy(this);
- }
- }
-
- // Proxy representing map types with a certain arity. Apart from the arity,
- // a number of constraints on the index and value type of the map type may
- // be known (such constraints result from applied select and store operations).
- // Because map type can be polymorphic (in the most general case, each index or
- // value type is described by a separate type parameter) any combination of
- // constraints can be satisfied.
- public class MapTypeProxy : ConstrainedProxy {
- public readonly int Arity;
- private readonly List<Constraint>/*!*/ constraints = new List<Constraint>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(constraints != null);
- }
-
-
- // each constraint specifies that the given combination of argument/result
- // types must be a possible instance of the formal map argument/result types
- private struct Constraint {
- public readonly List<Type>/*!*/ Arguments;
- public readonly Type/*!*/ Result;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Arguments != null);
- Contract.Invariant(Result != null);
- }
-
-
- public Constraint(List<Type> arguments, Type result) {
- Contract.Requires(result != null);
- Contract.Requires(arguments != null);
- Arguments = arguments;
- Result = result;
- }
-
- public Constraint Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- Contract.Requires(cce.NonNullDictionaryAndValues(varMap));
- List<Type>/*!*/ args = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- args.Add(t.Clone(varMap));
- }
- Type/*!*/ res = Result.Clone(varMap);
- Contract.Assert(res != null);
- return new Constraint(args, res);
- }
-
- public bool Unify(MapType that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
- Contract.Requires(unifiableVariables != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(result));
- Contract.Requires(that != null);
- Contract.Requires(Arguments.Count == that.Arguments.Count);
- Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- foreach (TypeVariable/*!*/ tv in that.TypeParameters) {
- Contract.Assert(tv != null);
- TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
- subst.Add(tv, proxy);
- }
-
- bool good = true;
- for (int i = 0; i < that.Arguments.Count; i++) {
- Type t0 = that.Arguments[i].Substitute(subst);
- Type t1 = this.Arguments[i];
- good &= t0.Unify(t1, unifiableVariables, result);
- }
- good &= that.Result.Substitute(subst).Unify(this.Result, unifiableVariables, result);
- return good;
- }
- }
-
- public MapTypeProxy(IToken token, string name, int arity)
- : base(token, name, "mapproxy") {
- Contract.Requires(name != null);
- Contract.Requires(token != null);
- Contract.Requires(0 <= arity);
- this.Arity = arity;
- }
-
- private void AddConstraint(Constraint c) {
- Contract.Requires(c.Arguments.Count == Arity);
-
- Type f = ProxyFor;
- MapType mf = f as MapType;
- if (mf != null) {
- bool success = c.Unify(mf, new List<TypeVariable>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>());
- Contract.Assert(success);
- return;
- }
-
- MapTypeProxy mpf = f as MapTypeProxy;
- if (mpf != null) {
- mpf.AddConstraint(c);
- return;
- }
-
- Contract.Assert(f == null); // no other types should occur as specialisations of this proxy
-
- constraints.Add(c);
- }
-
- public Type CheckArgumentTypes(List<Expr>/*!*/ actualArgs,
- out TypeParamInstantiation/*!*/ tpInstantiation,
- IToken/*!*/ typeCheckingSubject,
- string/*!*/ opName,
- TypecheckingContext/*!*/ tc) {
- Contract.Requires(actualArgs != null);
- Contract.Requires(typeCheckingSubject != null);
- Contract.Requires(opName != null);
- Contract.Requires(tc != null);
- Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
-
-
-
- Type f = ProxyFor;
- MapType mf = f as MapType;
- if (mf != null)
- return mf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
-
- MapTypeProxy mpf = f as MapTypeProxy;
- if (mpf != null)
- return mpf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
-
- Contract.Assert(f == null); // no other types should occur as specialisations of this proxy
-
- // otherwise, we just record the constraints given by this usage of the map type
- List<Type>/*!*/ arguments = new List<Type>();
- foreach (Expr/*!*/ e in actualArgs) {
- Contract.Assert(e != null);
- arguments.Add(e.Type);
- }
- Type/*!*/ result = new TypeProxy(tok, "result");
- Contract.Assert(result != null);
- AddConstraint(new Constraint(arguments, result));
-
- List<Type>/*!*/ argumentsResult = new List<Type>();
- foreach (Expr/*!*/ e in actualArgs) {
- Contract.Assert(e != null);
- argumentsResult.Add(e.Type);
- }
- argumentsResult.Add(result);
-
- tpInstantiation = new MapTypeProxyParamInstantiation(this, argumentsResult);
- return result;
- }
-
- //----------- Cloning ----------------------------------
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- Type p = ProxyFor;
- if (p != null) {
- return p.Clone(varMap);
- } else {
- MapTypeProxy p2 = new MapTypeProxy(tok, Name, Arity);
- foreach (Constraint c in constraints)
- p2.AddConstraint(c.Clone(varMap));
- return p2; // the clone will have a name that ends with $mapproxy<n>$mapproxy<m> (hopefully)
- }
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- Type p = ProxyFor;
- if (p != null) {
- p.Emit(stream, contextBindingStrength);
- } else {
- stream.Write("[");
- string/*!*/ sep = "";
- for (int i = 0; i < Arity; ++i) {
- stream.Write(sep);
- sep = ", ";
- stream.Write("?");
- }
- stream.Write("]?");
- }
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
- //Contract.Requires(that != null);
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(cce.NonNullElements(result));
- Type p = ProxyFor;
- if (p != null) {
- return p.Unify(that, unifiableVariables, result);
- }
-
- // unify this with that, if possible
- that = that.Expanded;
- that = FollowProxy(that);
-
- if (this.ReallyOccursIn(that))
- return false;
-
- TypeVariable tv = that as TypeVariable;
-
- if (tv != null && unifiableVariables.Contains(tv))
- return that.Unify(this, unifiableVariables, result);
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- } else if (that is MapType) {
- MapType mapType = (MapType)that;
- if (mapType.Arguments.Count == Arity) {
- bool good = true;
- foreach (Constraint c in constraints)
- good &= c.Unify(mapType, unifiableVariables, result);
- if (good) {
- DefineProxy(mapType);
- return true;
- }
- }
- } else if (that is MapTypeProxy) {
- MapTypeProxy mt = (MapTypeProxy)that;
- if (mt.Arity == this.Arity) {
- // we propagate the constraints of this proxy to the more specific one
- foreach (Constraint c in constraints)
- mt.AddConstraint(c);
- DefineProxy(mt);
- return true;
- }
- } else if (that is ConstrainedProxy) {
- // only map-type proxies can be unified with this MapTypeProxy
- return false;
- } else if (that is TypeProxy) {
- // define: that.ProxyFor := this;
- return that.Unify(this, unifiableVariables, result);
- }
- return false;
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- if (this.ProxyFor == null) {
- // check that the constraints are clean and do not contain any
- // of the substituted variables (otherwise, we are in big trouble)
- Contract.Assert(Contract.ForAll(constraints, c =>
- Contract.ForAll(subst.Keys, var =>
- Contract.ForAll(0, c.Arguments.Count, t => !c.Arguments[t].FreeVariables.Contains(var)) &&
- !c.Result.FreeVariables.Contains(var))));
- }
- return base.Substitute(subst);
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsMap {
- get {
- return true;
- }
- }
- public override MapType/*!*/ AsMap {
- get {
- Contract.Ensures(Contract.Result<MapType>() != null);
-
- Type p = ProxyFor;
- if (p != null) {
- return p.AsMap;
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // what to do now?
- }
- }
- }
- public override int MapArity {
- get {
- return Arity;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitMapTypeProxy(this);
- }
- }
-
- //=====================================================================
-
- // Used to annotate types with type synoyms that were used in the
- // original unresolved types. Such types should be considered as
- // equivalent to ExpandedType, the annotations are only used to enable
- // better pretty-printing
- public class TypeSynonymAnnotation : Type {
- public Type/*!*/ ExpandedType;
-
- public readonly List<Type>/*!*/ Arguments;
- // is set during resolution and determines whether the right number of arguments is given
- public readonly TypeSynonymDecl/*!*/ Decl;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ExpandedType != null);
- Contract.Invariant(Arguments != null);
- Contract.Invariant(Decl != null);
- }
-
-
- public TypeSynonymAnnotation(IToken/*!*/ token, TypeSynonymDecl/*!*/ decl, List<Type>/*!*/ arguments)
- : base(token) {
- Contract.Requires(token != null);
- Contract.Requires(decl != null);
- Contract.Requires(arguments != null);
- Contract.Requires(arguments.Count == decl.TypeParameters.Count);
- this.Decl = decl;
- this.Arguments = arguments;
-
- // build a substitution that can be applied to the definition of
- // the type synonym
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst =
- new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- for (int i = 0; i < arguments.Count; ++i)
- subst.Add(decl.TypeParameters[i], arguments[i]);
-
- ExpandedType = decl.Body.Substitute(subst);
- }
-
- private TypeSynonymAnnotation(IToken/*!*/ token, TypeSynonymDecl/*!*/ decl, List<Type>/*!*/ arguments,
- Type/*!*/ expandedType)
- : base(token) {
- Contract.Requires(token != null);
- Contract.Requires(decl != null);
- Contract.Requires(arguments != null);
- Contract.Requires(expandedType != null);
-
- this.Decl = decl;
- this.Arguments = arguments;
- this.ExpandedType = expandedType;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.Clone(varMap));
- }
- Type/*!*/ newExpandedType = ExpandedType.Clone(varMap);
- Contract.Assert(newExpandedType != null);
- return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.CloneUnresolved());
- }
- return new TypeSynonymAnnotation(tok, Decl, newArgs);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type/*!*/ that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables) {
- //Contract.Requires(that != null);
- //Contract.Requires(thisBoundVariables != null);
- //Contract.Requires(thatBoundVariables != null);
- return ExpandedType.Equals(that, thisBoundVariables, thatBoundVariables);
- }
-
- // used to skip leading type annotations
- internal override Type/*!*/ Expanded {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return ExpandedType.Expanded;
- }
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
- //Contract.Requires(that != null);
- //Contract.Requires(unifiableVariables != null);
- //Contract.Requires(cce.NonNullElements(result));
- return ExpandedType.Unify(that, unifiableVariables, result);
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- ExpandedType.Unify(that, unifiableVariables,
- thisBoundVariables, thatBoundVariables, result);
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- if (subst.Count == 0)
- return this;
- List<Type> newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.Substitute(subst));
- }
- Type/*!*/ newExpandedType = ExpandedType.Substitute(subst);
- Contract.Assert(newExpandedType != null);
- return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- return ExpandedType.GetHashCode(boundVariables);
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- CtorType.EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type> resolvedArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- resolvedArgs.Add(t.ResolveType(rc));
- }
- return new TypeSynonymAnnotation(tok, Decl, resolvedArgs);
- }
-
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
-
- return ExpandedType.FreeVariables;
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
- return ExpandedType.FreeProxies;
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBasic {
- get {
- return ExpandedType.IsBasic;
- }
- }
- public override bool IsInt {
- get {
- return ExpandedType.IsInt;
- }
- }
- public override bool IsReal
- {
- get
- {
- return ExpandedType.IsReal;
- }
- }
- public override bool IsFloat
- {
- get
- {
- return ExpandedType.IsFloat;
- }
- }
- public override bool IsBool {
- get {
- return ExpandedType.IsBool;
- }
- }
-
- public override bool IsVariable {
- get {
- return ExpandedType.IsVariable;
- }
- }
- public override TypeVariable/*!*/ AsVariable {
- get {
- Contract.Ensures(Contract.Result<TypeVariable>() != null);
- return ExpandedType.AsVariable;
- }
- }
- public override bool IsCtor {
- get {
- return ExpandedType.IsCtor;
- }
- }
- public override CtorType/*!*/ AsCtor {
- get {
- Contract.Ensures(Contract.Result<CtorType>() != null);
- return ExpandedType.AsCtor;
- }
- }
- public override bool IsMap {
- get {
- return ExpandedType.IsMap;
- }
- }
- public override MapType/*!*/ AsMap {
- get {
- Contract.Ensures(Contract.Result<MapType>() != null);
- return ExpandedType.AsMap;
- }
- }
- public override bool IsUnresolved {
- get {
- return ExpandedType.IsUnresolved;
- }
- }
- public override UnresolvedTypeIdentifier/*!*/ AsUnresolved {
- get {
- Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
-
- return ExpandedType.AsUnresolved;
- }
- }
-
- public override bool IsBv {
- get {
- return ExpandedType.IsBv;
- }
- }
- public override int BvBits {
- get {
- return ExpandedType.BvBits;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitTypeSynonymAnnotation(this);
- }
- }
-
- //=====================================================================
-
- public class CtorType : Type {
- public readonly List<Type>/*!*/ Arguments;
- // is set during resolution and determines whether the right number of arguments is given
- public readonly TypeCtorDecl/*!*/ Decl;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Arguments != null);
- Contract.Invariant(Decl != null);
- }
-
-
- public CtorType(IToken/*!*/ token, TypeCtorDecl/*!*/ decl, List<Type>/*!*/ arguments)
- : base(token) {
- Contract.Requires(token != null);
- Contract.Requires(decl != null);
- Contract.Requires(arguments != null);
- Contract.Requires(arguments.Count == decl.Arity);
- this.Decl = decl;
- this.Arguments = arguments;
- }
-
- public bool IsDatatype() {
- return QKeyValue.FindBoolAttribute(Decl.Attributes, "datatype");
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.Clone(varMap));
- }
- return new CtorType(tok, Decl, newArgs);
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.CloneUnresolved());
- }
- return new CtorType(tok, Decl, newArgs);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- Type thatType = that as Type;
- if (thatType == null)
- return false;
- thatType = TypeProxy.FollowProxy(thatType.Expanded);
- // shortcut
- CtorType thatCtorType = thatType as CtorType;
- if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
- return false;
- if (Arguments.Count == 0)
- return true;
- return base.Equals(thatType);
- }
-
- [Pure]
- public override bool Equals(Type/*!*/ that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables) {
- that = TypeProxy.FollowProxy(that.Expanded);
- CtorType thatCtorType = that as CtorType;
- if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
- return false;
- for (int i = 0; i < Arguments.Count; ++i) {
- if (!Arguments[i].Equals(thatCtorType.Arguments[i],
- thisBoundVariables, thatBoundVariables))
- return false;
- }
- return true;
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable)
- return that.Unify(this, unifiableVariables, result);
-
- CtorType thatCtorType = that as CtorType;
- if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl)) {
- return false;
- } else {
- bool good = true;
- for (int i = 0; i < Arguments.Count; ++i)
- good &= Arguments[i].Unify(thatCtorType.Arguments[i], unifiableVariables, result);
- return good;
- }
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- return;
- }
-
- CtorType thatCtorType = that as CtorType;
- if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl))
- throw UNIFICATION_FAILED;
- for (int i = 0; i < Arguments.Length; ++i)
- Arguments[i].Unify(thatCtorType.Arguments[i],
- unifiableVariables,
- thisBoundVariables, thatBoundVariables,
- result);
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- if (subst.Count == 0)
- return this;
- List<Type> newArgs = new List<Type>();
- lock (Arguments)
- {
- foreach (Type/*!*/ t in Arguments)
- {
- Contract.Assert(t != null);
- newArgs.Add(t.Substitute(subst));
- }
- }
- return new CtorType(tok, Decl, newArgs);
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- int res = 1637643879 * Decl.GetHashCode();
- foreach (Type/*!*/ t in Arguments.ToArray()) {
- Contract.Assert(t != null);
- res = res * 3 + t.GetHashCode(boundVariables);
- }
- return res;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
- EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
- }
-
- internal static void EmitCtorType(string name, List<Type> args, TokenTextWriter stream, int contextBindingStrength) {
- Contract.Requires(stream != null);
- Contract.Requires(args != null);
- Contract.Requires(name != null);
- int opBindingStrength = args.Count > 0 ? 0 : 2;
- if (opBindingStrength < contextBindingStrength)
- stream.Write("(");
-
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(name));
- int i = args.Count;
- foreach (Type/*!*/ t in args) {
- Contract.Assert(t != null);
- stream.Write(" ");
- // use a lower binding strength for the last argument
- // to allow map-types without parentheses
- t.Emit(stream, i == 1 ? 1 : 2);
- i = i - 1;
- }
-
- if (opBindingStrength < contextBindingStrength)
- stream.Write(")");
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- List<Type> resolvedArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- resolvedArgs.Add(t.ResolveType(rc));
- }
- return new CtorType(tok, Decl, resolvedArgs);
- }
-
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- List<TypeVariable>/*!*/ res = new List<TypeVariable>();
- foreach (Type/*!*/ t in Arguments.ToArray()) {
- Contract.Assert(t != null);
- res.AppendWithoutDups(t.FreeVariables);
- }
- return res;
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- List<TypeProxy/*!*/>/*!*/ res = new List<TypeProxy/*!*/>();
- foreach (Type/*!*/ t in Arguments.ToArray()) {
- Contract.Assert(t != null);
- AppendWithoutDups(res, t.FreeProxies);
- }
- return res;
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsCtor {
- get {
- return true;
- }
- }
- public override CtorType/*!*/ AsCtor {
- get {
- return this;
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitCtorType(this);
- }
- }
-
- //=====================================================================
-
- public class MapType : Type {
- // an invariant is that each of the type parameters has to occur as
- // free variable in at least one of the arguments
- public readonly List<TypeVariable>/*!*/ TypeParameters;
- public readonly List<Type>/*!*/ Arguments;
- public Type/*!*/ Result;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(TypeParameters != null);
- Contract.Invariant(Arguments != null);
- Contract.Invariant(Result != null);
- }
-
-
- public MapType(IToken/*!*/ token, List<TypeVariable>/*!*/ typeParameters, List<Type>/*!*/ arguments, Type/*!*/ result)
- : base(token) {
- Contract.Requires(token != null);
- Contract.Requires(typeParameters != null);
- Contract.Requires(arguments != null);
- Contract.Requires(result != null);
-
- this.TypeParameters = typeParameters;
- this.Result = result;
- this.Arguments = arguments;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
- //Contract.Requires(cce.NonNullElements(varMap));
- Contract.Ensures(Contract.Result<Type>() != null);
- IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ newVarMap =
- new Dictionary<TypeVariable/*!*/, TypeVariable/*!*/>();
- foreach (KeyValuePair<TypeVariable/*!*/, TypeVariable/*!*/> p in varMap) {
- Contract.Assert(cce.NonNullElements(p));
- if (!TypeParameters.Contains(p.Key))
- newVarMap.Add(p);
- }
-
- List<TypeVariable>/*!*/ newTypeParams = new List<TypeVariable>();
- foreach (TypeVariable/*!*/ var in TypeParameters) {
- Contract.Assert(var != null);
- TypeVariable/*!*/ newVar = new TypeVariable(var.tok, var.Name);
- Contract.Assert(newVar != null);
- newVarMap.Add(var, newVar);
- newTypeParams.Add(newVar);
- }
-
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.Clone(newVarMap));
- }
- Type/*!*/ newResult = Result.Clone(newVarMap);
- Contract.Assert(newResult != null);
-
- return new MapType(this.tok, newTypeParams, newArgs, newResult);
- }
-
- public override Type CloneUnresolved() {
- Contract.Ensures(Contract.Result<Type>() != null);
- List<TypeVariable>/*!*/ newTypeParams = new List<TypeVariable>();
- foreach (TypeVariable/*!*/ var in TypeParameters) {
- Contract.Assert(var != null);
- TypeVariable/*!*/ newVar = new TypeVariable(var.tok, var.Name);
- Contract.Assert(newVar != null);
- newTypeParams.Add(newVar);
- }
-
- List<Type>/*!*/ newArgs = new List<Type>();
- foreach (Type/*!*/ t in Arguments) {
- Contract.Assert(t != null);
- newArgs.Add(t.CloneUnresolved());
- }
- Type/*!*/ newResult = Result.CloneUnresolved();
- Contract.Assert(newResult != null);
-
- return new MapType(this.tok, newTypeParams, newArgs, newResult);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type/*!*/ that,
- List<TypeVariable>/*!*/ thisBoundVariables,
- List<TypeVariable>/*!*/ thatBoundVariables)
- {
- that = TypeProxy.FollowProxy(that.Expanded);
- MapType thatMapType = that as MapType;
- if (thatMapType == null ||
- this.TypeParameters.Count != thatMapType.TypeParameters.Count ||
- this.Arguments.Count != thatMapType.Arguments.Count)
- return false;
-
- thisBoundVariables = thisBoundVariables.ToList();
- foreach (TypeVariable/*!*/ var in this.TypeParameters)
- {
- Contract.Assert(var != null);
- thisBoundVariables.Add(var);
- }
- thatBoundVariables = thatBoundVariables.ToList();
- foreach (TypeVariable/*!*/ var in thatMapType.TypeParameters)
- {
- Contract.Assert(var != null);
- thatBoundVariables.Add(var);
- }
-
- for (int i = 0; i < Arguments.Count; ++i)
- {
- if (!Arguments[i].Equals(thatMapType.Arguments[i],
- thisBoundVariables, thatBoundVariables))
- return false;
- }
-
- return this.Result.Equals(thatMapType.Result,
- thisBoundVariables, thatBoundVariables);
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type/*!*/ that,
- List<TypeVariable>/*!*/ unifiableVariables,
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable)
- return that.Unify(this, unifiableVariables, result);
-
- MapType thatMapType = that as MapType;
- if (thatMapType == null ||
- this.TypeParameters.Count != thatMapType.TypeParameters.Count ||
- this.Arguments.Count != thatMapType.Arguments.Count)
- return false;
-
- // treat the bound variables of the two map types as equal...
- Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst0 =
- new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst1 =
- new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- List<TypeVariable> freshies = new List<TypeVariable>();
- for (int i = 0; i < this.TypeParameters.Count; i++) {
- TypeVariable tp0 = this.TypeParameters[i];
- TypeVariable tp1 = thatMapType.TypeParameters[i];
- TypeVariable freshVar = new TypeVariable(tp0.tok, tp0.Name);
- freshies.Add(freshVar);
- subst0.Add(tp0, freshVar);
- subst1.Add(tp1, freshVar);
- }
- // ... and then unify the domain and range types
- bool good = true;
- for (int i = 0; i < this.Arguments.Count; i++) {
- Type t0 = this.Arguments[i].Substitute(subst0);
- Type t1 = thatMapType.Arguments[i].Substitute(subst1);
- good &= t0.Unify(t1, unifiableVariables, result);
- }
- Type r0 = this.Result.Substitute(subst0);
- Type r1 = thatMapType.Result.Substitute(subst1);
- good &= r0.Unify(r1, unifiableVariables, result);
-
- // Finally, check that none of the bound variables has escaped
- if (good && freshies.Count != 0) {
- // This is done by looking for occurrences of the fresh variables in the
- // non-substituted types ...
- List<TypeVariable> freeVars = this.FreeVariables;
- foreach (TypeVariable fr in freshies)
- if (freeVars.Contains(fr)) {
- return false;
- } // fresh variable escaped
- freeVars = thatMapType.FreeVariables;
- foreach (TypeVariable fr in freshies)
- if (freeVars.Contains(fr)) {
- return false;
- } // fresh variable escaped
-
- // ... and in the resulting unifier of type variables
- foreach (KeyValuePair<TypeVariable/*!*/, Type/*!*/> pair in result) {
- Contract.Assert(cce.NonNullElements(pair));
- freeVars = pair.Value.FreeVariables;
- foreach (TypeVariable fr in freshies)
- if (freeVars.Contains(fr)) {
- return false;
- } // fresh variable escaped
- }
- }
-
- return good;
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- List<TypeVariable>! unifiableVariables,
- List<TypeVariable>! thisBoundVariables,
- List<TypeVariable>! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- return;
- }
-
- MapType thatMapType = that as MapType;
- if (thatMapType == null ||
- this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
- this.Arguments.Length != thatMapType.Arguments.Length)
- throw UNIFICATION_FAILED;
-
- // ensure that no collisions occur
- if (this.collisionsPossible(result)) {
- ((MapType)this.Clone())
- .Unify(that, unifiableVariables,
- thisBoundVariables, thatBoundVariables, result);
- return;
- }
- if (thatMapType.collisionsPossible(result))
- thatMapType = (MapType)that.Clone();
-
- foreach(TypeVariable/*!*/ var in this.TypeParameters){
-Contract.Assert(var != null);
- thisBoundVariables.Add(var);}
- foreach(TypeVariable/*!*/ var in thatMapType.TypeParameters){
-Contract.Assert(var != null);
- thatBoundVariables.Add(var);}
-
- try {
-
- for (int i = 0; i < Arguments.Length; ++i)
- Arguments[i].Unify(thatMapType.Arguments[i],
- unifiableVariables,
- thisBoundVariables, thatBoundVariables,
- result);
- Result.Unify(thatMapType.Result,
- unifiableVariables,
- thisBoundVariables, thatBoundVariables,
- result);
-
- } finally {
- // make sure that the bound variables are removed again
- for (int i = 0; i < this.TypeParameters.Length; ++i) {
- thisBoundVariables.Remove();
- thatBoundVariables.Remove();
- }
- }
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- [Pure]
- private bool collisionsPossible(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- Contract.Requires(cce.NonNullDictionaryAndValues(subst));
- // PR: could be written more efficiently
- return TypeParameters.Any(param => subst.ContainsKey(param) || subst.Values.Any(val => val.FreeVariables.Contains(param)));
- }
-
- public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
- //Contract.Requires(cce.NonNullElements(subst));
- Contract.Ensures(Contract.Result<Type>() != null);
- if (subst.Count == 0)
- return this;
-
- // there are two cases in which we have to be careful:
- // * a variable to be substituted is shadowed by a variable binder
- // * a substituted term contains variables that are bound in the
- // type (variable capture)
- //
- // in both cases, we first clone the type to ensure that bound
- // variables are fresh
-
- if (collisionsPossible(subst)) {
- MapType/*!*/ newType = (MapType)this.Clone();
- Contract.Assert(newType != null);
- Contract.Assert(newType.Equals(this) && !newType.collisionsPossible(subst));
- return newType.Substitute(subst);
- }
-
- List<Type> newArgs = new List<Type>();
- lock (Arguments)
- {
- foreach (Type/*!*/ t in Arguments)
- {
- Contract.Assert(t != null);
- newArgs.Add(t.Substitute(subst));
- }
- }
- Type/*!*/ newResult = Result.Substitute(subst);
- Contract.Assert(newResult != null);
-
- return new MapType(tok, TypeParameters, newArgs, newResult);
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(List<TypeVariable> boundVariables) {
- //Contract.Requires(boundVariables != null);
- int res = 7643761 * TypeParameters.Count + 65121 * Arguments.Count;
-
- boundVariables = boundVariables.ToList();
- foreach (TypeVariable/*!*/ var in this.TypeParameters) {
- Contract.Assert(var != null);
- boundVariables.Add(var);
- }
-
- foreach (Type/*!*/ t in Arguments.ToArray()) {
- Contract.Assert(t != null);
- res = res * 5 + t.GetHashCode(boundVariables);
- }
- res = res * 7 + Result.GetHashCode(boundVariables);
-
- return res;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
- //Contract.Requires(stream != null);
- stream.SetToken(this);
-
- const int opBindingStrength = 1;
- if (opBindingStrength < contextBindingStrength)
- stream.Write("(");
-
- EmitOptionalTypeParams(stream, TypeParameters);
-
- stream.Write("[");
- Arguments.Emit(stream, ","); // default binding strength of 0 is ok
- stream.Write("]");
- Result.Emit(stream); // default binding strength of 0 is ok
-
- if (opBindingStrength < contextBindingStrength)
- stream.Write(")");
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type ResolveType(ResolutionContext rc) {
- //Contract.Requires(rc != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- int previousState = rc.TypeBinderState;
- try {
- foreach (TypeVariable/*!*/ v in TypeParameters) {
- Contract.Assert(v != null);
- rc.AddTypeBinder(v);
- }
-
- List<Type> resolvedArgs = new List<Type>();
- foreach (Type/*!*/ ty in Arguments) {
- Contract.Assert(ty != null);
- resolvedArgs.Add(ty.ResolveType(rc));
- }
-
- Type resolvedResult = Result.ResolveType(rc);
-
- CheckBoundVariableOccurrences(TypeParameters,
- resolvedArgs, new List<Type> { resolvedResult },
- this.tok, "map arguments",
- rc);
-
- // sort the type parameters so that they are bound in the order of occurrence
- List<TypeVariable>/*!*/ sortedTypeParams = SortTypeParams(TypeParameters, resolvedArgs, resolvedResult);
- Contract.Assert(sortedTypeParams != null);
- return new MapType(tok, sortedTypeParams, resolvedArgs, resolvedResult);
- } finally {
- rc.TypeBinderState = previousState;
- }
- }
-
- public override List<TypeVariable>/*!*/ FreeVariables {
- get {
- List<TypeVariable>/*!*/ res = FreeVariablesIn(Arguments.ToList());
- Contract.Assert(res != null);
- res.AppendWithoutDups(Result.FreeVariables);
- foreach (TypeVariable/*!*/ v in TypeParameters.ToArray()) {
- Contract.Assert(v != null);
- res.Remove(v);
- }
- return res;
- }
- }
-
- public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
- get {
- List<TypeProxy/*!*/>/*!*/ res = new List<TypeProxy/*!*//*!*/>();
- foreach (Type/*!*/ t in Arguments.ToArray()) {
- Contract.Assert(t != null);
- AppendWithoutDups(res, t.FreeProxies);
- }
- AppendWithoutDups(res, Result.FreeProxies);
- return res;
- }
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsMap {
- get {
- return true;
- }
- }
- public override MapType/*!*/ AsMap {
- get {
- return this;
- }
- }
- public override int MapArity {
- get {
- return Arguments.Count;
- }
- }
-
- //------------ Match formal argument types of the map
- //------------ on concrete types, substitute the result into the
- //------------ result type. Null is returned if so many type checking
- //------------ errors occur that the situation is hopeless
-
- public Type CheckArgumentTypes(List<Expr>/*!*/ actualArgs,
- out TypeParamInstantiation/*!*/ tpInstantiation,
- IToken/*!*/ typeCheckingSubject,
- string/*!*/ opName,
- TypecheckingContext/*!*/ tc) {
- Contract.Requires(actualArgs != null);
- Contract.Requires(typeCheckingSubject != null);
-
- Contract.Requires(opName != null);
- Contract.Requires(tc != null);
-Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
- List<Type/*!*/>/*!*/ actualTypeParams;
- List<Type> actualResult =
- Type.CheckArgumentTypes(TypeParameters, out actualTypeParams, Arguments, actualArgs,
- new List<Type> { Result }, null, typeCheckingSubject, opName, tc);
- if (actualResult == null) {
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- } else {
- Contract.Assert(actualResult.Count == 1);
- tpInstantiation = SimpleTypeParamInstantiation.From(TypeParameters, actualTypeParams);
- return actualResult[0];
- }
- }
-
- public override Absy StdDispatch(StandardVisitor visitor) {
- //Contract.Requires(visitor != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- return visitor.VisitMapType(this);
- }
- }
-
- //---------------------------------------------------------------------
-
- public enum SimpleType {
- Int,
- Real,
- Bool
- };
-
-
- //=====================================================================
-
- // Interface for representing the instantiations of type parameters of
- // polymorphic functions or maps. We introduce an own interface for this
- // instead of using a simple list or dictionary, because in some cases
- // (due to the type proxies for map types) the actual number and instantiation
- // of type parameters can only be determined very late.
- [ContractClass(typeof(TypeParamInstantiationContracts))]
- public interface TypeParamInstantiation {
- // return what formal type parameters there are
- List<TypeVariable/*!*/>/*!*/ FormalTypeParams {
- get;
- }
- // given a formal type parameter, return the actual instantiation
- Type/*!*/ this[TypeVariable/*!*/ var] {
- get;
- }
- }
- [ContractClassFor(typeof(TypeParamInstantiation))]
- public abstract class TypeParamInstantiationContracts : TypeParamInstantiation {
- #region TypeParamInstantiation Members
-
- public List<TypeVariable> FormalTypeParams {
-
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
- throw new NotImplementedException();
- }
- }
-
- public Type this[TypeVariable var] {
- get {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- }
-
- #endregion
- }
-
-
- public class SimpleTypeParamInstantiation : TypeParamInstantiation {
- private readonly List<TypeVariable/*!*/>/*!*/ TypeParams;
- [ContractInvariantMethod]
- void TypeParamsInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(TypeParams));
- }
- private readonly IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ Instantiations;
- [ContractInvariantMethod]
- void InstantiationsInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(Instantiations));
- }
-
- public SimpleTypeParamInstantiation(List<TypeVariable/*!*/>/*!*/ typeParams,
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ instantiations) {
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(cce.NonNullDictionaryAndValues(instantiations));
- this.TypeParams = typeParams;
- this.Instantiations = instantiations;
- }
-
- public static TypeParamInstantiation/*!*/ From(List<TypeVariable> typeParams, List<Type/*!*/>/*!*/ actualTypeParams) {
- Contract.Requires(cce.NonNullElements(actualTypeParams));
- Contract.Requires(typeParams != null);
- Contract.Requires(typeParams.Count == actualTypeParams.Count);
- Contract.Ensures(Contract.Result<TypeParamInstantiation>() != null);
-
- if (typeParams.Count == 0)
- return EMPTY;
-
- List<TypeVariable/*!*/>/*!*/ typeParamList = new List<TypeVariable/*!*/>();
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- for (int i = 0; i < typeParams.Count; ++i) {
- typeParamList.Add(typeParams[i]);
- dict.Add(typeParams[i], actualTypeParams[i]);
- }
- return new SimpleTypeParamInstantiation(typeParamList, dict);
- }
-
- public static readonly TypeParamInstantiation EMPTY =
- new SimpleTypeParamInstantiation(new List<TypeVariable/*!*/>(),
- new Dictionary<TypeVariable/*!*/, Type/*!*/>());
-
- // return what formal type parameters there are
- public List<TypeVariable/*!*/>/*!*/ FormalTypeParams {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
- return TypeParams;
- }
- }
- // given a formal type parameter, return the actual instantiation
- public Type/*!*/ this[TypeVariable/*!*/ var] {
- get {
- return Instantiations[var];
- }
- }
- }
-
- // Implementation of TypeParamInstantiation that refers to the current
- // value of a MapTypeProxy. This means that the values return by the
- // methods of this implementation can change in case the MapTypeProxy
- // receives further unifications.
- class MapTypeProxyParamInstantiation : TypeParamInstantiation {
- private readonly MapTypeProxy/*!*/ Proxy;
-
- // the argument and result type of this particular usage of the map
- // type. these are necessary to derive the values of the type parameters
- private readonly List<Type>/*!*/ ArgumentsResult;
-
- // field that is initialised once all necessary information is available
- // (the MapTypeProxy is instantiated to an actual type) and the instantiation
- // of a type parameter is queried
- private IDictionary<TypeVariable/*!*/, Type/*!*/> Instantiations = null;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Proxy != null);
- Contract.Invariant(ArgumentsResult != null);
- Contract.Invariant(Instantiations == null || cce.NonNullDictionaryAndValues(Instantiations));
- }
-
-
- public MapTypeProxyParamInstantiation(MapTypeProxy/*!*/ proxy,
- List<Type>/*!*/ argumentsResult) {
- Contract.Requires(proxy != null);
- Contract.Requires(argumentsResult != null);
- this.Proxy = proxy;
- this.ArgumentsResult = argumentsResult;
- }
-
- // return what formal type parameters there are
- public List<TypeVariable/*!*/>/*!*/ FormalTypeParams {
- get {
- MapType realType = Proxy.ProxyFor as MapType;
- if (realType == null)
- // no instantiation of the map type is known, which means
- // that the map type is assumed to be monomorphic
- return new List<TypeVariable/*!*/>();
- else
- return realType.TypeParameters.ToList();
- }
- }
-
- // given a formal type parameter, return the actual instantiation
- public Type/*!*/ this[TypeVariable/*!*/ var] {
- get {
- // then there has to be an instantiation that is a polymorphic map type
- if (Instantiations == null) {
- MapType realType = Proxy.ProxyFor as MapType;
- Contract.Assert(realType != null);
- List<Type>/*!*/ formalArgs = new List<Type>();
- foreach (Type/*!*/ t in realType.Arguments) {
- Contract.Assert(t != null);
- formalArgs.Add(t);
- }
- formalArgs.Add(realType.Result);
- Instantiations =
- Type.InferTypeParameters(realType.TypeParameters, formalArgs, ArgumentsResult);
- }
- return Instantiations[var];
- }
- }
- }
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Absy.cs
+//---------------------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie {
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Linq;
+ using System.Collections.Generic;
+ using Microsoft.Boogie.AbstractInterpretation;
+ using System.Diagnostics.Contracts;
+
+ //=====================================================================
+ //---------------------------------------------------------------------
+ // Types
+ [ContractClass(typeof(TypeContracts))]
+ public abstract class Type : Absy {
+ public Type(IToken/*!*/ token)
+ : base(token) {
+ Contract.Requires(token != null);
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively. Applying Clone to a type will return
+ // a type in which all bound variables have been replaced with new
+ // variables, whereas free variables have not changed
+
+ public override Absy Clone() {
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return this.Clone(new Dictionary<TypeVariable/*!*/, TypeVariable/*!*/>());
+ }
+
+ public abstract Type/*!*/ Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap);
+
+ /// <summary>
+ /// Clones the type, but only syntactically. Anything resolved in the source
+ /// type is left unresolved (that is, with just the name) in the destination type.
+ /// </summary>
+ public abstract Type/*!*/ CloneUnresolved();
+
+ //----------- Linearisation ----------------------------------
+
+ public void Emit(TokenTextWriter stream) {
+ Contract.Requires(stream != null);
+ this.Emit(stream, 0);
+ }
+
+ public abstract void Emit(TokenTextWriter/*!*/ stream, int contextBindingStrength);
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/false, /*pretty=*/ false)) {
+ this.Emit(stream);
+ }
+ return buffer.ToString();
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (ReferenceEquals(this, that))
+ return true;
+ Type thatType = that as Type;
+ return thatType != null && this.Equals(thatType,
+ new List<TypeVariable>(),
+ new List<TypeVariable>());
+ }
+
+ [Pure]
+ public abstract bool Equals(Type/*!*/ that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables);
+
+ // used to skip leading type annotations (subexpressions of the
+ // resulting type might still contain annotations)
+ internal virtual Type/*!*/ Expanded {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return this;
+ }
+ }
+
+ //----------- Unification of types -----------
+
+ /// <summary>
+ /// Add a constraint that this==that, if possible, and return true.
+ /// If not possible, return false (which may have added some partial constraints).
+ /// No error is printed.
+ /// </summary>
+ public bool Unify(Type that) {
+ Contract.Requires(that != null);
+ return Unify(that, new List<TypeVariable>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>());
+ }
+
+ public abstract bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier);
+
+
+ [Pure]
+ public static bool IsIdempotent(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(unifier));
+ return unifier.Values.All(val => val.FreeVariables.All(var => !unifier.ContainsKey(var)));
+ }
+
+
+#if OLD_UNIFICATION
+ // Compute a most general unification of two types. null is returned if
+ // no such unifier exists. The unifier is not allowed to subtitute any
+ // type variables other than the ones in "unifiableVariables"
+ public IDictionary<TypeVariable!, Type!> Unify(Type! that,
+ List<TypeVariable>! unifiableVariables) {
+ Dictionary<TypeVariable!, Type!>! result = new Dictionary<TypeVariable!, Type!> ();
+ try {
+ this.Unify(that, unifiableVariables,
+ new List<TypeVariable> (), new List<TypeVariable> (), result);
+ } catch (UnificationFailedException) {
+ return null;
+ }
+ return result;
+ }
+
+ // Compute an idempotent most general unifier and add the result to the argument
+ // unifier. The result is true iff the unification succeeded
+ public bool Unify(Type! that,
+ List<TypeVariable>! unifiableVariables,
+ // given mappings that need to be taken into account
+ // the old unifier has to be idempotent as well
+ IDictionary<TypeVariable!, Type!>! unifier)
+ {
+ Contract.Requires(Contract.ForAll(unifier.Keys , key=> unifiableVariables.Has(key)));
+ Contract.Requires(IsIdempotent(unifier));
+ try {
+ this.Unify(that, unifiableVariables,
+ new List<TypeVariable> (), new List<TypeVariable> (), unifier);
+ } catch (UnificationFailedException) {
+ return false;
+ }
+ return true;
+ }
+
+ public abstract void Unify(Type! that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable!, Type!>! result);
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public abstract Type/*!*/ Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst);
+
+ //----------- Hashcodes ----------------------------------
+
+ // Hack to be able to access the hashcode of superclasses further up
+ // (from the subclasses of this class)
+ [Pure]
+ protected int GetBaseHashCode() {
+ return base.GetHashCode();
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.GetHashCode(new List<TypeVariable>());
+ }
+
+ [Pure]
+ public abstract int GetHashCode(List<TypeVariable>/*!*/ boundVariables);
+
+ //----------- Resolution ----------------------------------
+
+ public override void Resolve(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ System.Diagnostics.Debug.Fail("Type.Resolve should never be called." +
+ " Use Type.ResolveType instead");
+ }
+
+ public abstract Type/*!*/ ResolveType(ResolutionContext/*!*/ rc);
+
+ public override void Typecheck(TypecheckingContext tc) {
+ //Contract.Requires(tc != null);
+ System.Diagnostics.Debug.Fail("Type.Typecheck should never be called");
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public abstract List<TypeVariable>/*!*/ FreeVariables {
+ get;
+ }
+
+ // determine the free type proxies in a type, in the order in which they occur
+ public abstract List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get;
+ }
+
+ protected static void AppendWithoutDups<A>(List<A> a, List<A> b) {
+ Contract.Requires(b != null);
+ Contract.Requires(a != null);
+ foreach (A x in b)
+ if (!a.Contains(x))
+ a.Add(x);
+ }
+
+ public bool IsClosed {
+ get {
+ return FreeVariables.Count == 0;
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ // the following methods should be used instead of simple casts or the
+ // C# "is" operator, because they handle type synonym annotations and
+ // type proxies correctly
+
+ public virtual bool IsBasic {
+ get {
+ return false;
+ }
+ }
+ public virtual bool IsInt {
+ get {
+ return false;
+ }
+ }
+ public virtual bool IsReal {
+ get {
+ return false;
+ }
+ }
+ public virtual bool IsFloat {
+ get {
+ return false;
+ }
+ }
+ public virtual bool IsBool {
+ get {
+ return false;
+ }
+ }
+
+ public virtual bool IsVariable {
+ get {
+ return false;
+ }
+ }
+ public virtual TypeVariable/*!*/ AsVariable {
+ get {
+ Contract.Ensures(Contract.Result<TypeVariable>() != null);
+
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.AsVariable should never be called
+ }
+ }
+ public virtual bool IsCtor {
+ get {
+ return false;
+ }
+ }
+ public virtual CtorType/*!*/ AsCtor {
+ get {
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.AsCtor should never be called
+ }
+ }
+ public virtual bool IsMap {
+ get {
+ return false;
+ }
+ }
+ public virtual MapType/*!*/ AsMap {
+ get {
+ Contract.Ensures(Contract.Result<MapType>() != null);
+
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.AsMap should never be called
+ }
+ }
+ public virtual int MapArity {
+ get {
+
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.MapArity should never be called
+ }
+ }
+ public virtual bool IsUnresolved {
+ get {
+ return false;
+ }
+ }
+ public virtual UnresolvedTypeIdentifier/*!*/ AsUnresolved {
+ get {
+ Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
+
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.AsUnresolved should never be called
+ }
+ }
+
+ public virtual bool isFloat {
+ get {
+ return false;
+ }
+ }
+ public virtual int FloatExponent
+ {
+ get
+ {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.FloatExponent should never be called
+ }
+ }
+ public virtual int FloatMantissa {
+ get {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.FloatMantissa should never be called
+ }
+ }
+ public virtual bool IsBv {
+ get {
+ return false;
+ }
+ }
+ public virtual int BvBits {
+ get {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // Type.BvBits should never be called
+ }
+ }
+
+ public static readonly Type/*!*/ Int = new BasicType(SimpleType.Int);
+ public static readonly Type/*!*/ Real = new BasicType(SimpleType.Real);
+ public static readonly Type/*!*/ Bool = new BasicType(SimpleType.Bool);
+ private static BvType[] bvtypeCache;
+
+ static public BvType GetBvType(int sz) {
+ Contract.Requires(0 <= sz);
+ Contract.Ensures(Contract.Result<BvType>() != null);
+
+ if (bvtypeCache == null) {
+ bvtypeCache = new BvType[128];
+ }
+ if (sz < bvtypeCache.Length) {
+ BvType t = bvtypeCache[sz];
+ if (t == null) {
+ t = new BvType(sz);
+ bvtypeCache[sz] = t;
+ }
+ return t;
+ } else {
+ return new BvType(sz);
+ }
+ }
+
+ static public FloatType GetFloatType(int exp, int man) {
+ Contract.Requires(0 <= exp);
+ Contract.Requires(0 <= man);
+ Contract.Ensures(Contract.Result<FloatType>() != null);
+
+ return new FloatType(exp, man);
+ }
+
+ //------------ Match formal argument types on actual argument types
+ //------------ and return the resulting substitution of type variables
+
+#if OLD_UNIFICATION
+ public static IDictionary<TypeVariable!, Type!>!
+ MatchArgumentTypes(List<TypeVariable>! typeParams,
+ List<Type>! formalArgs,
+ List<Expr>! actualArgs,
+ List<Type> formalOuts,
+ List<IdentifierExpr> actualOuts,
+ string! opName,
+ TypecheckingContext! tc)
+ {
+ Contract.Requires(formalArgs.Length == actualArgs.Length);
+ Contract.Requires(formalOuts == null <==> actualOuts == null);
+ Contract.Requires(formalOuts != null ==> formalOuts.Length == actualOuts.Length);
+ List<TypeVariable>! boundVarSeq0 = new List<TypeVariable> ();
+ List<TypeVariable>! boundVarSeq1 = new List<TypeVariable> ();
+ Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
+
+ for (int i = 0; i < formalArgs.Length; ++i) {
+ try {
+ Type! actualType = cce.NonNull((!)actualArgs[i]).Type;
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ Contract.Assert(forall{TypeVariable! var in typeParams);
+ !actualType.FreeVariables.Has(var)};
+ formalArgs[i].Unify(actualType,
+ typeParams,
+ boundVarSeq0, boundVarSeq1,
+ subst);
+ } catch (UnificationFailedException) {
+ tc.Error(actualArgs[i],
+ "invalid type for argument {0} in {1}: {2} (expected: {3})",
+ i, opName, actualArgs[i].Type,
+ // we insert the type parameters that have already been
+ // chosen to get a more precise error message
+ formalArgs[i].Substitute(subst));
+ // the bound variable sequences should be empty ...
+ // so that we can continue with the unification
+ Contract.Assert(boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0);
+ }
+ }
+
+ if (formalOuts != null) {
+ for (int i = 0; i < formalOuts.Length; ++i) {
+ try {
+ Type! actualType = cce.NonNull((!)actualOuts[i]).Type;
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ Contract.Assert(forall{TypeVariable! var in typeParams);
+ !actualType.FreeVariables.Has(var)};
+ formalOuts[i].Unify(actualType,
+ typeParams,
+ boundVarSeq0, boundVarSeq1,
+ subst);
+ } catch (UnificationFailedException) {
+ tc.Error(actualOuts[i],
+ "invalid type for result {0} in {1}: {2} (expected: {3})",
+ i, opName, actualOuts[i].Type,
+ // we insert the type parameters that have already been
+ // chosen to get a more precise error message
+ formalOuts[i].Substitute(subst));
+ // the bound variable sequences should be empty ...
+ // so that we can continue with the unification
+ Contract.Assert(boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0);
+ }
+ }
+ }
+
+ // we only allow type parameters to be substituted
+ Contract.Assert(Contract.ForAll(subst.Keys , var=> typeParams.Has(var)));
+
+ return subst;
+ }
+#else
+ public static IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/
+ MatchArgumentTypes(List<TypeVariable>/*!*/ typeParams,
+ List<Type>/*!*/ formalArgs,
+ IList<Expr>/*!*/ actualArgs,
+ List<Type> formalOuts,
+ List<IdentifierExpr> actualOuts,
+ string/*!*/ opName,
+ TypecheckingContext/*!*/ tc) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(formalArgs != null);
+ Contract.Requires(actualArgs != null);
+ Contract.Requires(opName != null);
+ Contract.Requires(tc != null);
+ Contract.Requires(formalArgs.Count == actualArgs.Count);
+ Contract.Requires((formalOuts == null) == (actualOuts == null));
+ Contract.Requires(formalOuts == null || formalOuts.Count == cce.NonNull(actualOuts).Count);
+ Contract.Requires(tc == null || opName != null);//Redundant
+ Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
+
+ // requires "actualArgs" and "actualOuts" to have been type checked
+
+ Dictionary<TypeVariable/*!*/, Type/*!*/> subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ foreach (TypeVariable/*!*/ tv in typeParams) {
+ Contract.Assert(tv != null);
+ TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
+ subst.Add(tv, proxy);
+ }
+
+ for (int i = 0; i < formalArgs.Count; i++) {
+ Type formal = formalArgs[i].Substitute(subst);
+ Type actual = cce.NonNull(cce.NonNull(actualArgs[i]).Type);
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ Contract.Assert(Contract.ForAll(0, typeParams.Count, index => !actual.FreeVariables.Contains(typeParams[index])));
+
+ if (!formal.Unify(actual)) {
+ Contract.Assume(tc != null); // caller expected no errors
+ Contract.Assert(opName != null); // follows from precondition
+ tc.Error(cce.NonNull(actualArgs[i]),
+ "invalid type for argument {0} in {1}: {2} (expected: {3})",
+ i, opName, actual, formalArgs[i]);
+ }
+ }
+
+ if (formalOuts != null) {
+ for (int i = 0; i < formalOuts.Count; ++i) {
+ Type formal = formalOuts[i].Substitute(subst);
+ Type actual = cce.NonNull(cce.NonNull(actualOuts)[i].Type);
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ Contract.Assert(Contract.ForAll(0, typeParams.Count, var => !actual.FreeVariables.Contains(typeParams[var])));
+
+ if (!formal.Unify(actual)) {
+ Contract.Assume(tc != null); // caller expected no errors
+ Contract.Assert(opName != null); // follows from precondition
+ tc.Error(actualOuts[i],
+ "invalid type for out-parameter {0} in {1}: {2} (expected: {3})",
+ i, opName, actual, formal);
+ }
+ }
+ }
+
+ return subst;
+ }
+#endif
+
+ //------------ Match formal argument types of a function or map
+ //------------ on concrete types, substitute the result into the
+ //------------ result type. Null is returned for type errors
+
+ public static List<Type> CheckArgumentTypes(List<TypeVariable>/*!*/ typeParams,
+ out List<Type/*!*/>/*!*/ actualTypeParams,
+ List<Type>/*!*/ formalIns,
+ IList<Expr>/*!*/ actualIns,
+ List<Type>/*!*/ formalOuts,
+ List<IdentifierExpr> actualOuts,
+ IToken/*!*/ typeCheckingSubject,
+ string/*!*/ opName,
+ TypecheckingContext/*!*/ tc)
+ // requires "actualIns" and "actualOuts" to have been type checked
+ {
+ Contract.Requires(typeParams != null);
+
+ Contract.Requires(formalIns != null);
+ Contract.Requires(formalOuts != null);
+ Contract.Requires(actualIns != null);
+ Contract.Requires(typeCheckingSubject != null);
+ Contract.Requires(opName != null);Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out actualTypeParams)));
+ actualTypeParams = new List<Type/*!*/>();
+
+ if (formalIns.Count != actualIns.Count) {
+ tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1}",
+ opName, actualIns.Count);
+ // if there are no type parameters, we can still return the result
+ // type and hope that the type checking proceeds
+ return typeParams.Count == 0 ? formalOuts : null;
+ } else if (actualOuts != null && formalOuts.Count != actualOuts.Count) {
+ tc.Error(typeCheckingSubject, "wrong number of result variables in {0}: {1}",
+ opName, actualOuts.Count);
+ // if there are no type parameters, we can still return the result
+ // type and hope that the type checking proceeds
+ actualTypeParams = new List<Type>();
+ return typeParams.Count == 0 ? formalOuts : null;
+ }
+
+ int previousErrorCount = tc.ErrorCount;
+ IDictionary<TypeVariable/*!*/, Type/*!*/> subst =
+ MatchArgumentTypes(typeParams, formalIns, actualIns,
+ actualOuts != null ? formalOuts : null, actualOuts, opName, tc);
+ Contract.Assert(cce.NonNullDictionaryAndValues(subst));
+ foreach (TypeVariable/*!*/ var in typeParams) {
+ Contract.Assert(var != null);
+ actualTypeParams.Add(subst[var]);
+ }
+
+ List<Type>/*!*/ actualResults = new List<Type>();
+ foreach (Type/*!*/ t in formalOuts) {
+ Contract.Assert(t != null);
+ actualResults.Add(t.Substitute(subst));
+ }
+ List<TypeVariable> resultFreeVars = FreeVariablesIn(actualResults);
+ if (previousErrorCount != tc.ErrorCount) {
+ // errors occured when matching the formal arguments
+ // in case we have been able to substitute all type parameters,
+ // we can still return the result type and hope that the
+ // type checking proceeds in a meaningful manner
+ if (typeParams.All(param => !resultFreeVars.Contains(param)))
+ return actualResults;
+ else
+ // otherwise there is no point in returning the result type,
+ // type checking would only get confused even further
+ return null;
+ }
+
+ Contract.Assert(Contract.ForAll(0, typeParams.Count, index => !resultFreeVars.Contains(typeParams[index])));
+ return actualResults;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // about the same as Type.CheckArgumentTypes, but without
+ // detailed error reports
+ public static Type/*!*/ InferValueType(List<TypeVariable>/*!*/ typeParams,
+ List<Type>/*!*/ formalArgs,
+ Type/*!*/ formalResult,
+ List<Type>/*!*/ actualArgs) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(formalArgs != null);
+ Contract.Requires(formalResult != null);
+ Contract.Requires(actualArgs != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst =
+ InferTypeParameters(typeParams, formalArgs, actualArgs);
+ Contract.Assert(cce.NonNullDictionaryAndValues(subst));
+
+ Type/*!*/ res = formalResult.Substitute(subst);
+ Contract.Assert(res != null);
+ // all type parameters have to be substituted with concrete types
+ List<TypeVariable>/*!*/ resFreeVars = res.FreeVariables;
+ Contract.Assert(resFreeVars != null);
+ Contract.Assert(Contract.ForAll(0, typeParams.Count, var => !resFreeVars.Contains(typeParams[var])));
+ return res;
+ }
+
+#if OLD_UNIFICATION
+ public static IDictionary<TypeVariable!, Type!>!
+ InferTypeParameters(List<TypeVariable>! typeParams,
+ List<Type>! formalArgs,
+ List<Type>! actualArgs)
+ {
+ Contract.Requires(formalArgs.Length == actualArgs.Length);
+
+ List<TypeVariable>! boundVarSeq0 = new List<TypeVariable> ();
+ List<TypeVariable>! boundVarSeq1 = new List<TypeVariable> ();
+ Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
+
+ for (int i = 0; i < formalArgs.Length; ++i) {
+ try {
+ Contract.Assert(forall{TypeVariable! var in typeParams);
+ !actualArgs[i].FreeVariables.Has(var)};
+ formalArgs[i].Unify(actualArgs[i], typeParams,
+ boundVarSeq0, boundVarSeq1, subst);
+ } catch (UnificationFailedException) {
+ System.Diagnostics.Debug.Fail("Type unification failed: " +
+ formalArgs[i] + " vs " + actualArgs[i]);
+ }
+ }
+
+ // we only allow type parameters to be substituted
+ Contract.Assert(Contract.ForAll(subst.Keys , var=> typeParams.Has(var)));
+ return subst;
+ }
+#else
+ /// <summary>
+ /// like Type.CheckArgumentTypes, but assumes no errors
+ /// (and only does arguments, not results; and takes actuals as List<Type>, not List<Expr>)
+ /// </summary>
+ public static IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/
+ InferTypeParameters(List<TypeVariable>/*!*/ typeParams,
+ List<Type>/*!*/ formalArgs,
+ List<Type>/*!*/ actualArgs) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(formalArgs != null);
+ Contract.Requires(actualArgs != null);Contract.Requires(formalArgs.Count == actualArgs.Count);
+ Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
+
+
+ List<Type> proxies = new List<Type>();
+ Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ foreach (TypeVariable/*!*/ tv in typeParams) {
+ Contract.Assert(tv != null);
+ TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
+ proxies.Add(proxy);
+ subst.Add(tv, proxy);
+ }
+
+ for (int i = 0; i < formalArgs.Count; i++) {
+ Type formal = formalArgs[i].Substitute(subst);
+ Type actual = actualArgs[i];
+ // if the type variables to be matched occur in the actual
+ // argument types, something has gone very wrong
+ Contract.Assert(Contract.ForAll(0, typeParams.Count, index => !actual.FreeVariables.Contains(typeParams[index])));
+
+ if (!formal.Unify(actual)) {
+ Contract.Assume(false); // caller expected no errors
+ }
+ }
+
+ return subst;
+ }
+#endif
+
+ //----------- Helper methods to deal with bound type variables ---------------
+
+ public static void EmitOptionalTypeParams(TokenTextWriter stream, List<TypeVariable> typeParams) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(stream != null);
+ if (typeParams.Count > 0) {
+ stream.Write("<");
+ typeParams.Emit(stream, ","); // default binding strength of 0 is ok
+ stream.Write(">");
+ }
+ }
+
+ // Sort the type parameters according to the order of occurrence in the argument types
+ public static List<TypeVariable>/*!*/ SortTypeParams(List<TypeVariable>/*!*/ typeParams, List<Type>/*!*/ argumentTypes, Type resultType) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(argumentTypes != null);
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ Contract.Ensures(Contract.Result<List<TypeVariable>>().Count == typeParams.Count);
+ if (typeParams.Count == 0) {
+ return typeParams;
+ }
+
+ List<TypeVariable> freeVarsInUse = FreeVariablesIn(argumentTypes);
+ if (resultType != null) {
+ freeVarsInUse.AppendWithoutDups(resultType.FreeVariables);
+ }
+ // "freeVarsInUse" is already sorted, but it may contain type variables not in "typeParams".
+ // So, project "freeVarsInUse" onto "typeParams":
+ List<TypeVariable> sortedTypeParams = new List<TypeVariable>();
+ foreach (TypeVariable/*!*/ var in freeVarsInUse) {
+ Contract.Assert(var != null);
+ if (typeParams.Contains(var)) {
+ sortedTypeParams.Add(var);
+ }
+ }
+
+ if (sortedTypeParams.Count < typeParams.Count)
+ // add the type parameters not mentioned in "argumentTypes" in
+ // the end of the list (this can happen for quantifiers)
+ sortedTypeParams.AppendWithoutDups(typeParams);
+
+ return sortedTypeParams;
+ }
+
+ // Check that each of the type parameters occurs in at least one argument type.
+ // Return true if some type parameters appear only among "moreArgumentTypes" and
+ // not in "argumentTypes".
+ [Pure]
+ public static bool CheckBoundVariableOccurrences(List<TypeVariable>/*!*/ typeParams,
+ List<Type>/*!*/ argumentTypes,
+ List<Type> moreArgumentTypes,
+ IToken/*!*/ resolutionSubject,
+ string/*!*/ subjectName,
+ ResolutionContext/*!*/ rc) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(argumentTypes != null);
+ Contract.Requires(resolutionSubject != null);
+ Contract.Requires(subjectName != null);
+ Contract.Requires(rc != null);
+ List<TypeVariable> freeVarsInArgs = FreeVariablesIn(argumentTypes);
+ List<TypeVariable> moFreeVarsInArgs = moreArgumentTypes == null ? null : FreeVariablesIn(moreArgumentTypes);
+ bool someTypeParamsAppearOnlyAmongMo = false;
+ foreach (TypeVariable/*!*/ var in typeParams) {
+ Contract.Assert(var != null);
+ if (rc.LookUpTypeBinder(var.Name) == var) // avoid to complain twice about variables that are bound multiple times
+ {
+ if (freeVarsInArgs.Contains(var)) {
+ // cool
+ } else if (moFreeVarsInArgs != null && moFreeVarsInArgs.Contains(var)) {
+ someTypeParamsAppearOnlyAmongMo = true;
+ } else {
+ rc.Error(resolutionSubject,
+ "type variable must occur in {0}: {1}",
+ subjectName, var);
+ }
+ }
+ }
+ return someTypeParamsAppearOnlyAmongMo;
+ }
+
+ [Pure]
+ public static List<TypeVariable> FreeVariablesIn(List<Type> arguments) {
+ Contract.Requires(arguments != null);
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+ List<TypeVariable>/*!*/ res = new List<TypeVariable>();
+ foreach (Type/*!*/ t in arguments) {
+ Contract.Assert(t != null);
+ res.AppendWithoutDups(t.FreeVariables);
+ }
+ return res;
+ }
+ }
+ [ContractClassFor(typeof(Type))]
+ public abstract class TypeContracts : Type {
+ public TypeContracts() :base(null){
+
+ }
+ public override List<TypeProxy> FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ throw new NotImplementedException();
+ }
+ }
+ public override List<TypeVariable> FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+ throw new NotImplementedException();
+ }
+ }
+ public override Type Clone(IDictionary<TypeVariable, TypeVariable> varMap) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ Contract.Requires(stream != null);
+ throw new NotImplementedException();
+ }
+ public override bool Equals(Type that, List<TypeVariable> thisBoundVariables, List<TypeVariable> thatBoundVariables) {
+ Contract.Requires(that != null);
+ Contract.Requires(thisBoundVariables != null);
+ Contract.Requires(thatBoundVariables != null);
+ throw new NotImplementedException();
+ }
+ public override bool Unify(Type that, List<TypeVariable> unifiableVariables, IDictionary<TypeVariable, Type> unifier) {
+ Contract.Requires(that != null);
+ Contract.Requires(unifiableVariables != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(unifier));
+ Contract.Requires(Contract.ForAll(unifier.Keys, key => unifiableVariables.Contains(key)));
+ Contract.Requires(IsIdempotent(unifier));
+ throw new NotImplementedException();
+ }
+ public override Type Substitute(IDictionary<TypeVariable, Type> subst) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ public override Type ResolveType(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ Contract.Requires(boundVariables != null);
+ throw new NotImplementedException();
+ }
+ }
+ //=====================================================================
+
+ public class BasicType : Type {
+ public readonly SimpleType T;
+ public BasicType(IToken/*!*/ token, SimpleType t)
+ : base(token) {
+ Contract.Requires(token != null);
+ T = t;
+ }
+ public BasicType(SimpleType t)
+ : base(Token.NoToken) {
+ T = t;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively.
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // BasicTypes are immutable anyway, we do not clone
+ return this;
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ // no parentheses are necessary for basic types
+ stream.SetToken(this);
+ stream.Write("{0}", this);
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ switch (T) {
+ case SimpleType.Int:
+ return "int";
+ case SimpleType.Real:
+ return "real";
+ case SimpleType.Bool:
+ return "bool";
+ }
+ Debug.Assert(false, "bad type " + T);
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // make compiler happy
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ // shortcut
+ Type thatType = that as Type;
+ if (thatType == null)
+ return false;
+ BasicType thatBasicType = TypeProxy.FollowProxy(thatType.Expanded) as BasicType;
+ return thatBasicType != null && this.T == thatBasicType.T;
+ }
+
+ [Pure]
+ public override bool Equals(Type that, List<TypeVariable> thisBoundVariables, List<TypeVariable> thatBoundVariables) {
+ //Contract.Requires(thatBoundVariables != null);
+ //Contract.Requires(thisBoundVariables != null);
+ //Contract.Requires(that != null);
+ return this.Equals(that);
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type that, List<TypeVariable> unifiableVariables, IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(that != null);
+ //Contract.Requires(cce.NonNullElements(unifier));
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable) {
+ return that.Unify(this, unifiableVariables, unifier);
+ } else {
+ return this.Equals(that);
+ }
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ } else {
+ if (!this.Equals(that))
+ throw UNIFICATION_FAILED;
+ }
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ return this.T.GetHashCode();
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // nothing to resolve
+ return this;
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ return new List<TypeVariable>(); // basic type are closed
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ return new List<TypeProxy/*!*/>();
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBasic {
+ get {
+ return true;
+ }
+ }
+ public override bool IsInt {
+ get {
+ return this.T == SimpleType.Int;
+ }
+ }
+ public override bool IsReal {
+ get {
+ return this.T == SimpleType.Real;
+ }
+ }
+ public override bool IsBool {
+ get {
+ return this.T == SimpleType.Bool;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBasicType(this);
+ }
+ }
+
+ //=====================================================================
+
+ //Note that the functions in this class were directly copied from the BV class just below
+ public class FloatType : Type {
+ public readonly int Mantissa; //Size of mantissa in bits
+ public readonly int Exponent; //Size of exponent in bits
+
+ public FloatType(IToken token, int exponent, int mantissa)
+ : base(token) {
+ Contract.Requires(token != null);
+ Exponent = exponent;
+ Mantissa = mantissa;
+ }
+
+ public FloatType(int exponent, int mantissa)
+ : base(Token.NoToken) {
+ Exponent = exponent;
+ Mantissa = mantissa;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively.
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap)
+ {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // FloatTypes are immutable anyway, we do not clone
+ return this;
+ }
+
+ public override Type CloneUnresolved()
+ {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength)
+ {
+ //Contract.Requires(stream != null);
+ // no parentheses are necessary for bitvector-types
+ stream.SetToken(this);
+ stream.Write("{0}", this);
+ }
+
+ public override string ToString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "float (" + Exponent + " " + Mantissa + ")";
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type/*!*/ that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables)
+ {
+ FloatType thatFloatType = TypeProxy.FollowProxy(that.Expanded) as FloatType;
+ return thatFloatType != null && this.Mantissa == thatFloatType.Mantissa && this.Exponent == thatFloatType.Exponent;
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier)
+ {
+ //Contract.Requires(that != null);
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(cce.NonNullElements(unifier));
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable) {
+ return that.Unify(this, unifiableVariables, unifier);
+ }
+ else {
+ return this.Equals(that);
+ }
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst)
+ {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables)
+ {
+ return this.Mantissa.GetHashCode() + this.Exponent.GetHashCode();
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc)
+ {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // nothing to resolve
+ return this;
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public override List<TypeVariable>/*!*/ FreeVariables
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ return new List<TypeVariable>(); // bitvector-type are closed
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ return new List<TypeProxy/*!*/>();
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsFloat {
+ get {
+ return true;
+ }
+ }
+ public override int FloatMantissa {
+ get {
+ return Mantissa;
+ }
+ }
+ public override int FloatExponent {
+ get {
+ return Exponent;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor)
+ {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitFloatType(this);
+ }
+
+ }
+
+ //=====================================================================
+
+ public class BvType : Type {
+ public readonly int Bits;
+
+ public BvType(IToken token, int bits)
+ : base(token) {
+ Contract.Requires(token != null);
+ Bits = bits;
+ }
+
+ public BvType(int bits)
+ : base(Token.NoToken) {
+ Bits = bits;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively.
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // BvTypes are immutable anyway, we do not clone
+ return this;
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ // no parentheses are necessary for bitvector-types
+ stream.SetToken(this);
+ stream.Write("{0}", this);
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "bv" + Bits;
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type/*!*/ that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables) {
+ //Contract.Requires(thisBoundVariables != null);
+ //Contract.Requires(thatBoundVariables != null);
+ //Contract.Requires(that != null);
+ BvType thatBvType = TypeProxy.FollowProxy(that.Expanded) as BvType;
+ return thatBvType != null && this.Bits == thatBvType.Bits;
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(cce.NonNullElements(unifier));
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable) {
+ return that.Unify(this, unifiableVariables, unifier);
+ } else {
+ return this.Equals(that);
+ }
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!> result){
+Contract.Requires(result != null);
+Contract.Requires(that != null);
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ } else {
+ if (!this.Equals(that))
+ throw UNIFICATION_FAILED;
+ }
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ return this.Bits.GetHashCode();
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // nothing to resolve
+ return this;
+ }
+
+ // determine the free variables in a type, in the order in which the variables occur
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ return new List<TypeVariable>(); // bitvector-type are closed
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ return new List<TypeProxy/*!*/>();
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBv {
+ get {
+ return true;
+ }
+ }
+ public override int BvBits {
+ get {
+ return Bits;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBvType(this);
+ }
+ }
+
+ //=====================================================================
+
+ // An AST node containing an identifier and a sequence of type arguments, which
+ // will be turned either into a TypeVariable, into a CtorType or into a BvType
+ // during the resolution phase
+ public class UnresolvedTypeIdentifier : Type {
+ public readonly string/*!*/ Name;
+ public readonly List<Type>/*!*/ Arguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ Contract.Invariant(Arguments != null);
+ }
+
+
+ public UnresolvedTypeIdentifier(IToken token, string name)
+ : this(token, name, new List<Type>()) {
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ }
+
+ public UnresolvedTypeIdentifier(IToken token, string name, List<Type> arguments)
+ : base(token) {
+ Contract.Requires(arguments != null);
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ this.Name = name;
+ this.Arguments = arguments;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Clone(varMap));
+ }
+ return new UnresolvedTypeIdentifier(tok, Name, newArgs);
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.CloneUnresolved());
+ }
+ return new UnresolvedTypeIdentifier(tok, Name, newArgs);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables) {
+ //Contract.Requires(thisBoundVariables != null);
+ //Contract.Requires(thatBoundVariables != null);
+ //Contract.Requires(that != null);
+ System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Equals should never be called");
+ return false; // to make the compiler happy
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/> result) {
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(cce.NonNullElements(result));
+ //Contract.Requires(that != null);
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // UnresolvedTypeIdentifier.Unify should never be called
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!> result){
+Contract.Requires(result != null);
+Contract.Requires(that != null);
+ System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Unify should never be called");
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // UnresolvedTypeIdentifier.Substitute should never be called
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // UnresolvedTypeIdentifier.GetHashCode should never be called
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // first case: the type name denotes a bitvector-type
+ if (Name.StartsWith("bv") && Name.Length > 2) {
+ bool is_bv = true;
+ for (int i = 2; i < Name.Length; ++i) {
+ if (!char.IsDigit(Name[i])) {
+ is_bv = false;
+ break;
+ }
+ }
+ if (is_bv) {
+ if (Arguments.Count > 0) {
+ rc.Error(this,
+ "bitvector types must not be applied to arguments: {0}",
+ Name);
+ }
+ return new BvType(tok, int.Parse(Name.Substring(2)));
+ }
+ }
+
+ // second case: the identifier is resolved to a type variable
+ TypeVariable var = rc.LookUpTypeBinder(Name);
+ if (var != null) {
+ if (Arguments.Count > 0) {
+ rc.Error(this,
+ "type variables must not be applied to arguments: {0}",
+ var);
+ }
+ return var;
+ }
+
+ // third case: the identifier denotes a type constructor and we
+ // recursively resolve the arguments
+ TypeCtorDecl ctorDecl = rc.LookUpType(Name);
+ if (ctorDecl != null) {
+ if (Arguments.Count != ctorDecl.Arity) {
+ rc.Error(this,
+ "type constructor received wrong number of arguments: {0}",
+ ctorDecl);
+ return this;
+ }
+ return new CtorType(tok, ctorDecl, ResolveArguments(rc));
+ }
+
+ // fourth case: the identifier denotes a type synonym
+ TypeSynonymDecl synDecl = rc.LookUpTypeSynonym(Name);
+ if (synDecl != null) {
+ if (Arguments.Count != synDecl.TypeParameters.Count) {
+ rc.Error(this,
+ "type synonym received wrong number of arguments: {0}",
+ synDecl);
+ return this;
+ }
+ List<Type>/*!*/ resolvedArgs = ResolveArguments(rc);
+ Contract.Assert(resolvedArgs != null);
+
+ return new TypeSynonymAnnotation(this.tok, synDecl, resolvedArgs);
+
+ }
+
+ // otherwise: this name is not declared anywhere
+ rc.Error(this, "undeclared type: {0}", Name);
+ return this;
+ }
+
+ private List<Type> ResolveArguments(ResolutionContext rc) {
+ Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<List<Type>>() != null);
+ List<Type>/*!*/ resolvedArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ resolvedArgs.Add(t.ResolveType(rc));
+ }
+ return resolvedArgs;
+ }
+
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ return new List<TypeVariable>();
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ return new List<TypeProxy/*!*/>();
+ }
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ // PR: should unresolved types be syntactically distinguished from resolved types?
+ CtorType.EmitCtorType(this.Name, Arguments, stream, contextBindingStrength);
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsUnresolved {
+ get {
+ return true;
+ }
+ }
+ public override UnresolvedTypeIdentifier/*!*/ AsUnresolved {
+ get {
+ Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
+ return this;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitUnresolvedTypeIdentifier(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class TypeVariable : Type {
+ public readonly string/*!*/ Name;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ }
+
+
+ public TypeVariable(IToken token, string name)
+ : base(token) {
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ this.Name = name;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // if this variable is mapped to some new variable, we take the new one
+ // otherwise, return this
+ TypeVariable res;
+ varMap.TryGetValue(this, out res);
+ if (res == null)
+ return this;
+ else
+ return res;
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this;
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables) {
+ //Contract.Requires(thisBoundVariables != null);
+ //Contract.Requires(thatBoundVariables != null);
+ //Contract.Requires(that != null);
+ TypeVariable thatAsTypeVar = TypeProxy.FollowProxy(that.Expanded) as TypeVariable;
+
+ if (thatAsTypeVar == null)
+ return false;
+
+ int thisIndex = thisBoundVariables.LastIndexOf(this);
+ int thatIndex = thatBoundVariables.LastIndexOf(thatAsTypeVar);
+ return (thisIndex >= 0 && thisIndex == thatIndex) ||
+ (thisIndex == -1 && thatIndex == -1 &&
+ Object.ReferenceEquals(this, thatAsTypeVar));
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ // an idempotent substitution that describes the
+ // unification result up to a certain point
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ unifier) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(cce.NonNullElements(unifier));
+ that = that.Expanded;
+ if (that is TypeProxy && !(that is ConstrainedProxy))
+ return that.Unify(this, unifiableVariables, unifier);
+
+ if (this.Equals(that))
+ return true;
+
+ if (unifiableVariables.Contains(this)) {
+ Type previousSubst;
+ unifier.TryGetValue(this, out previousSubst);
+ if (previousSubst == null) {
+ return addSubstitution(unifier, that);
+ } else {
+ // we have to unify the old instantiation with the new one
+ return previousSubst.Unify(that, unifiableVariables, unifier);
+ }
+ }
+
+ // this cannot be instantiated with anything
+ // but that possibly can ...
+
+ TypeVariable tv = that as TypeVariable;
+
+ return tv != null &&
+ unifiableVariables.Contains(tv) &&
+ that.Unify(this, unifiableVariables, unifier);
+ }
+
+ // TODO: the following might cause problems, because when applying substitutions
+ // to type proxies the substitutions are not propagated to the proxy
+ // constraints (right now at least)
+ private bool addSubstitution(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ oldSolution,
+ // the type that "this" is instantiated with
+ Type/*!*/ newSubst) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(oldSolution));
+ Contract.Requires(newSubst != null);
+ Contract.Requires(!oldSolution.ContainsKey(this));
+
+ Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ newMapping = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ // apply the old (idempotent) substitution to the new instantiation
+ Type/*!*/ substSubst = newSubst.Substitute(oldSolution);
+ Contract.Assert(substSubst != null);
+ // occurs check
+ if (substSubst.FreeVariables.Contains(this))
+ return false;
+ newMapping.Add(this, substSubst);
+
+ // apply the new substitution to the old ones to ensure idempotence
+ List<TypeVariable/*!*/>/*!*/ keys = new List<TypeVariable/*!*/>();
+ keys.AddRange(oldSolution.Keys);
+ foreach (TypeVariable/*!*/ var in keys) {
+ Contract.Assert(var != null);
+ oldSolution[var] = oldSolution[var].Substitute(newMapping);
+ }
+ oldSolution.Add(this, substSubst);
+
+ Contract.Assert(IsIdempotent(oldSolution));
+ return true;
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!> result){
+Contract.Requires(result != null);
+Contract.Requires(that != null);
+ that = that.Expanded;
+ int thisIndex = thisBoundVariables.LastIndexOf(this);
+ if (thisIndex == -1) {
+ // this is not a bound variable and can possibly be matched on that
+ // that must not contain any bound variables
+ List<TypeVariable>! thatFreeVars = that.FreeVariables;
+ if (thatBoundVariables.Any(var=> thatFreeVars.Has(var)))
+ throw UNIFICATION_FAILED;
+
+ // otherwise, in case that is a typevariable it cannot be bound and
+ // we can just check for equality
+ if (this.Equals(that))
+ return;
+
+ if (!unifiableVariables.Has(this)) {
+ // this cannot be instantiated with anything
+ // but that possibly can ...
+ if ((that is TypeVariable) &&
+ unifiableVariables.Has(that as TypeVariable)) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ return;
+ } else {
+ throw UNIFICATION_FAILED;
+ }
+ }
+
+ Type previousSubst;
+ result.TryGetValue(this, out previousSubst);
+ if (previousSubst == null) {
+ addSubstitution(result, that);
+ } else {
+ // we have to unify the old instantiation with the new one
+ previousSubst.Unify(that, unifiableVariables, thisBoundVariables, thatBoundVariables, result);
+ }
+ } else {
+ // this is a bound variable, that also has to be one (with the same index)
+ if (!(that is TypeVariable) ||
+ thatBoundVariables.LastIndexOf(that) != thisIndex)
+ throw UNIFICATION_FAILED;
+ }
+ }
+
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Type res;
+ if (subst.TryGetValue(this, out res)) {
+ Contract.Assert(res != null);
+ return res;
+ } else {
+ return this;
+ }
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ int thisIndex = boundVariables.LastIndexOf(this);
+ if (thisIndex == -1)
+ return GetBaseHashCode();
+ return thisIndex * 27473671;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ // never put parentheses around variables
+ stream.SetToken(this);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ //Contract.Ensures(Contract.Result<Type>() != null);
+ // nothing to resolve
+ return this;
+ }
+
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+ return new List<TypeVariable> { this };
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ return new List<TypeProxy/*!*/>();
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsVariable {
+ get {
+ return true;
+ }
+ }
+ public override TypeVariable/*!*/ AsVariable {
+ get {
+ Contract.Ensures(Contract.Result<TypeVariable>() != null);
+ return this;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ //Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTypeVariable(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class TypeProxy : Type {
+ static int proxies = 0;
+ protected readonly string/*!*/ Name;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ }
+
+
+ public TypeProxy(IToken token, string givenName)
+ : this(token, givenName, "proxy") {
+ Contract.Requires(givenName != null);
+ Contract.Requires(token != null);
+ }
+
+ protected TypeProxy(IToken token, string givenName, string kind)
+ : base(token) {
+ Contract.Requires(kind != null);
+ Contract.Requires(givenName != null);
+ Contract.Requires(token != null);
+ Name = givenName + "$" + kind + "#" + proxies;
+ proxies++;
+ }
+
+ private Type proxyFor;
+ public Type ProxyFor {
+ // apply path shortening, and then return the value of proxyFor
+ get {
+ TypeProxy anotherProxy = proxyFor as TypeProxy;
+ if (anotherProxy != null && anotherProxy.proxyFor != null) {
+ // apply path shortening by bypassing "anotherProxy" (and possibly others)
+ proxyFor = anotherProxy.ProxyFor;
+ Contract.Assert(proxyFor != null);
+ }
+ return proxyFor;
+ }
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Everything)]
+ public static Type FollowProxy(Type t) {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Ensures(!(Contract.Result<Type>() is TypeProxy) || ((TypeProxy)Contract.Result<Type>()).proxyFor == null);
+ if (t is TypeProxy) {
+ Type p = ((TypeProxy)t).ProxyFor;
+ if (p != null) {
+ return p;
+ }
+ }
+ return t;
+ }
+
+ protected void DefineProxy(Type ty) {
+ Contract.Requires(ty != null);
+ Contract.Requires(ProxyFor == null);
+ // follow ty down to the leaf level, so that we can avoid creating a cycle
+ ty = FollowProxy(ty);
+ if (!object.ReferenceEquals(this, ty)) {
+ proxyFor = ty;
+ }
+ }
+
+ //----------- Cloning ----------------------------------
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Clone(varMap);
+ } else {
+ return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
+ }
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables) {
+ //Contract.Requires(thisBoundVariables != null);
+ //Contract.Requires(thatBoundVariables != null);
+ //Contract.Requires(that != null);
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ }
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Equals(that, thisBoundVariables, thatBoundVariables);
+ } else {
+ // This proxy could be made to be equal to anything, so what to return?
+ return false;
+ }
+ }
+
+ //----------- Unification of types -----------
+
+ // determine whether the occurs check fails: this is a strict subtype of that
+ protected bool ReallyOccursIn(Type that) {
+ Contract.Requires(that != null);
+ that = FollowProxy(that.Expanded);
+ return that.FreeProxies.Contains(this) &&
+ (that.IsCtor || that.IsMap && this != that && this.ProxyFor != that);
+ }
+
+ public override bool Unify(Type that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/> result) {
+ //Contract.Requires(cce.NonNullElements(result));
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(that != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Unify(that, unifiableVariables, result);
+ } else {
+ // unify this with that
+ if (this.ReallyOccursIn(that))
+ return false;
+ DefineProxy(that.Expanded);
+ return true;
+ }
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Substitute(subst);
+ } else {
+ return this;
+ }
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.GetHashCode(boundVariables);
+ } else {
+ return GetBaseHashCode();
+ }
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ p.Emit(stream, contextBindingStrength);
+ } else {
+ // no need for parentheses
+ stream.SetToken(this);
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
+ }
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.ResolveType(rc);
+ } else {
+ return this;
+ }
+ }
+
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.FreeVariables;
+ } else {
+ return new List<TypeVariable>();
+ }
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.FreeProxies;
+ } else {
+ List<TypeProxy/*!*/>/*!*/ res = new List<TypeProxy/*!*/>();
+ res.Add(this);
+ return res;
+ }
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBasic {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsBasic;
+ }
+ }
+ public override bool IsInt {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsInt;
+ }
+ }
+ public override bool IsReal {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsReal;
+ }
+ }
+ public override bool IsFloat {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsFloat;
+ }
+ }
+ public override bool IsBool {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsBool;
+ }
+ }
+
+ public override bool IsVariable {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsVariable;
+ }
+ }
+ public override TypeVariable/*!*/ AsVariable {
+ get {
+ Contract.Ensures(Contract.Result<TypeVariable>() != null);
+
+ Type p = ProxyFor;
+ Contract.Assume(p != null);
+ return p.AsVariable;
+ }
+ }
+
+ public override bool IsCtor {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsCtor;
+ }
+ }
+ public override CtorType/*!*/ AsCtor {
+ get {
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+
+ Type p = ProxyFor;
+ Contract.Assume(p != null);
+ return p.AsCtor;
+ }
+ }
+ public override bool IsMap {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsMap;
+ }
+ }
+ public override MapType/*!*/ AsMap {
+ get {
+ Contract.Ensures(Contract.Result<MapType>() != null);
+
+ Type p = ProxyFor;
+ Contract.Assume(p != null);
+ return p.AsMap;
+ }
+ }
+ public override int MapArity {
+ get {
+ Type p = ProxyFor;
+ Contract.Assume(p != null);
+ return p.MapArity;
+ }
+ }
+ public override bool IsUnresolved {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsUnresolved;
+ }
+ }
+ public override UnresolvedTypeIdentifier/*!*/ AsUnresolved {
+ get {
+ Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
+
+ Type p = ProxyFor;
+ Contract.Assume(p != null);
+ return p.AsUnresolved;
+ }
+ }
+
+ public override bool IsBv {
+ get {
+ Type p = ProxyFor;
+ return p != null && p.IsBv;
+ }
+ }
+ public override int BvBits {
+ get {
+ Type p = ProxyFor;
+ Contract.Assume(p != null);
+ return p.BvBits;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTypeProxy(this);
+ }
+ }
+
+ public abstract class ConstrainedProxy : TypeProxy {
+ protected ConstrainedProxy(IToken token, string givenName, string kind)
+ : base(token, givenName, kind) {
+ Contract.Requires(kind != null);
+ Contract.Requires(givenName != null);
+ Contract.Requires(token != null);
+ }
+ }
+
+ /// <summary>
+ /// Each instance of this class represents a set of bitvector types. In particular, it represents
+ /// a bitvector type bvN iff
+ /// minBits ATMOST N and
+ /// foreach constraint (t0,t1), the types represented by t0 and t1 are bitvector types whose
+ /// number of bits add up to N.
+ /// This means that the size of a BvTypeProxy p is constrained not only by p.minBits, but also
+ /// by the size of various t0 and t1 types that are transitively part of BvTypeProxy constraints.
+ /// If such a t0 or t1 were to get its ProxyFor field defined, then p would have to be further
+ /// constrained too. This doesn't seem like it would ever occur in a Boogie 2 program, because:
+ /// the only place where a BvTypeProxy with constraints can occur is as the type of a
+ /// BvConcatExpr, and
+ /// the types of all local variables are explicitly declared, which means that the types of
+ /// subexpressions of a BvConcatExpr are not going to change other than via the type of the
+ /// BvConcatExpr.
+ /// So, this implementation of BvTypeProxy does not keep track of where a BvTypeProxy may occur
+ /// transitively in some other BvTypeProxy's constraints.
+ /// </summary>
+ public class BvTypeProxy : ConstrainedProxy {
+ public int MinBits;
+ List<BvTypeConstraint/*!*/> constraints;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(constraints, true));
+ }
+
+ class BvTypeConstraint {
+ public Type/*!*/ T0;
+ public Type/*!*/ T1;
+ public BvTypeConstraint(Type t0, Type t1) {
+ Contract.Requires(t1 != null);
+ Contract.Requires(t0 != null);
+ Contract.Requires(t0.IsBv && t1.IsBv);
+ T0 = t0;
+ T1 = t1;
+ }
+ }
+
+ public BvTypeProxy(IToken token, string name, int minBits)
+ : base(token, name, "bv" + minBits + "proxy") {
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ this.MinBits = minBits;
+ }
+
+ /// <summary>
+ /// Requires that any further constraints to be placed on t0 and t1 go via the object to
+ /// be constructed.
+ /// </summary>
+ public BvTypeProxy(IToken token, string name, Type t0, Type t1)
+ : base(token, name, "bvproxy") {
+ Contract.Requires(t1 != null);
+ Contract.Requires(t0 != null);
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ Contract.Requires(t0.IsBv && t1.IsBv);
+ t0 = FollowProxy(t0);
+ t1 = FollowProxy(t1);
+ this.MinBits = MinBitsFor(t0) + MinBitsFor(t1);
+ List<BvTypeConstraint/*!*/> list = new List<BvTypeConstraint/*!*/>();
+ list.Add(new BvTypeConstraint(t0, t1));
+ this.constraints = list;
+ }
+
+ /// <summary>
+ /// Construct a BvTypeProxy like p, but with minBits.
+ /// </summary>
+ private BvTypeProxy(BvTypeProxy p, int minBits)
+ : base(p.tok, p.Name, "") {
+ Contract.Requires(p != null);
+ this.MinBits = minBits;
+ this.constraints = p.constraints;
+ }
+
+ private BvTypeProxy(IToken token, string name, int minBits, List<BvTypeConstraint/*!*/> constraints)
+ : base(token, name, "") {
+ Contract.Requires(cce.NonNullElements(constraints, true));
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ this.MinBits = minBits;
+ this.constraints = constraints;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Everything)]
+ private static int MinBitsFor(Type t) {
+ Contract.Requires(t != null);
+ Contract.Requires(t.IsBv);
+ Contract.Ensures(0 <= Contract.Result<int>());
+
+ if (t is TypeSynonymAnnotation) {
+ return MinBitsFor(((TypeSynonymAnnotation)t).ExpandedType);
+ }
+
+ if (t is BvType) {
+ return t.BvBits;
+ } else {
+ return ((BvTypeProxy)t).MinBits;
+ }
+ }
+
+ //----------- Cloning ----------------------------------
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Clone(varMap);
+ } else {
+ return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
+ }
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type that,
+ List<TypeVariable> unifiableVariables,
+ IDictionary<TypeVariable, Type> result) {
+ //Contract.Requires(cce.NonNullElements(result));
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(that != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Unify(that, unifiableVariables, result);
+ }
+
+ // unify this with that, if possible
+ that = that.Expanded;
+ that = FollowProxy(that);
+
+ if (this.ReallyOccursIn(that))
+ return false;
+
+ TypeVariable tv = that as TypeVariable;
+
+ if (tv != null && unifiableVariables.Contains(tv))
+ return that.Unify(this, unifiableVariables, result);
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ } else if (that is BvType) {
+ if (MinBits <= that.BvBits) {
+ if (constraints != null) {
+ foreach (BvTypeConstraint btc in constraints) {
+ int minT1 = MinBitsFor(btc.T1);
+ int left = IncreaseBits(btc.T0, that.BvBits - minT1);
+ left = IncreaseBits(btc.T1, minT1 + left);
+ Contract.Assert(left == 0); // because it should always be possible to increase the total size of a BvTypeConstraint pair (t0,t1) arbitrarily
+ }
+ }
+ DefineProxy(that);
+ return true;
+ }
+ } else if (that is BvTypeProxy) {
+ BvTypeProxy bt = (BvTypeProxy)that;
+ // keep the proxy with the stronger constraint (that is, the higher minBits), but if either
+ // has a constraints list, then concatenate both constraints lists and define the previous
+ // proxies to the new one
+ if (this.constraints != null || bt.constraints != null) {
+ List<BvTypeConstraint/*!*/> list = new List<BvTypeConstraint/*!*/>();
+ if (this.constraints != null) {
+ list.AddRange(this.constraints);
+ }
+ if (bt.constraints != null) {
+ list.AddRange(bt.constraints);
+ }
+ BvTypeProxy np = new BvTypeProxy(this.tok, this.Name, Math.Max(this.MinBits, bt.MinBits), list);
+ this.DefineProxy(np);
+ bt.DefineProxy(np);
+ } else if (this.MinBits <= bt.MinBits) {
+ this.DefineProxy(bt);
+ } else {
+ bt.DefineProxy(this);
+ }
+ return true;
+ } else if (that is ConstrainedProxy) {
+ // only bitvector proxies can be unified with this BvTypeProxy
+ return false;
+ } else if (that is TypeProxy) {
+ // define: that.ProxyFor := this;
+ return that.Unify(this, unifiableVariables, result);
+ }
+ return false;
+ }
+
+ private static int IncreaseBits(Type t, int to) {
+ Contract.Requires(t != null);
+ Contract.Requires(t.IsBv && 0 <= to && MinBitsFor(t) <= to);
+ Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() <= to);
+
+ if(t is TypeSynonymAnnotation) {
+ return IncreaseBits(((TypeSynonymAnnotation)t).ExpandedType, to);
+ }
+
+ t = FollowProxy(t);
+ if (t is BvType) {
+ return to - t.BvBits;
+ } else {
+ BvTypeProxy p = (BvTypeProxy)t;
+ Contract.Assert(p.MinBits <= to);
+ if (p.MinBits < to) {
+ BvTypeProxy q = new BvTypeProxy(p, to);
+ p.DefineProxy(q);
+ }
+ return 0; // we were able to satisfy the request completely
+ }
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (this.ProxyFor == null) {
+ // check that the constraints are clean and do not contain any
+ // of the substituted variables (otherwise, we are in big trouble)
+ Contract.Assert(Contract.ForAll(constraints, c =>
+ Contract.ForAll(subst.Keys, var =>
+ !c.T0.FreeVariables.Contains(var) && !c.T1.FreeVariables.Contains(var))));
+ }
+ return base.Substitute(subst);
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBv {
+ get {
+ return true;
+ }
+ }
+ public override int BvBits {
+ get {
+ // This method is supposed to return the number of bits supplied, but unless the proxy has been resolved,
+ // we only have a lower bound on the number of bits supplied. But this method is not supposed to be
+ // called until type checking has finished, at which time the minBits is stable.
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.BvBits;
+ } else {
+ return MinBits;
+ }
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitBvTypeProxy(this);
+ }
+ }
+
+ // Proxy representing map types with a certain arity. Apart from the arity,
+ // a number of constraints on the index and value type of the map type may
+ // be known (such constraints result from applied select and store operations).
+ // Because map type can be polymorphic (in the most general case, each index or
+ // value type is described by a separate type parameter) any combination of
+ // constraints can be satisfied.
+ public class MapTypeProxy : ConstrainedProxy {
+ public readonly int Arity;
+ private readonly List<Constraint>/*!*/ constraints = new List<Constraint>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(constraints != null);
+ }
+
+
+ // each constraint specifies that the given combination of argument/result
+ // types must be a possible instance of the formal map argument/result types
+ private struct Constraint {
+ public readonly List<Type>/*!*/ Arguments;
+ public readonly Type/*!*/ Result;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Arguments != null);
+ Contract.Invariant(Result != null);
+ }
+
+
+ public Constraint(List<Type> arguments, Type result) {
+ Contract.Requires(result != null);
+ Contract.Requires(arguments != null);
+ Arguments = arguments;
+ Result = result;
+ }
+
+ public Constraint Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(varMap));
+ List<Type>/*!*/ args = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ args.Add(t.Clone(varMap));
+ }
+ Type/*!*/ res = Result.Clone(varMap);
+ Contract.Assert(res != null);
+ return new Constraint(args, res);
+ }
+
+ public bool Unify(MapType that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
+ Contract.Requires(unifiableVariables != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(result));
+ Contract.Requires(that != null);
+ Contract.Requires(Arguments.Count == that.Arguments.Count);
+ Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ foreach (TypeVariable/*!*/ tv in that.TypeParameters) {
+ Contract.Assert(tv != null);
+ TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
+ subst.Add(tv, proxy);
+ }
+
+ bool good = true;
+ for (int i = 0; i < that.Arguments.Count; i++) {
+ Type t0 = that.Arguments[i].Substitute(subst);
+ Type t1 = this.Arguments[i];
+ good &= t0.Unify(t1, unifiableVariables, result);
+ }
+ good &= that.Result.Substitute(subst).Unify(this.Result, unifiableVariables, result);
+ return good;
+ }
+ }
+
+ public MapTypeProxy(IToken token, string name, int arity)
+ : base(token, name, "mapproxy") {
+ Contract.Requires(name != null);
+ Contract.Requires(token != null);
+ Contract.Requires(0 <= arity);
+ this.Arity = arity;
+ }
+
+ private void AddConstraint(Constraint c) {
+ Contract.Requires(c.Arguments.Count == Arity);
+
+ Type f = ProxyFor;
+ MapType mf = f as MapType;
+ if (mf != null) {
+ bool success = c.Unify(mf, new List<TypeVariable>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>());
+ Contract.Assert(success);
+ return;
+ }
+
+ MapTypeProxy mpf = f as MapTypeProxy;
+ if (mpf != null) {
+ mpf.AddConstraint(c);
+ return;
+ }
+
+ Contract.Assert(f == null); // no other types should occur as specialisations of this proxy
+
+ constraints.Add(c);
+ }
+
+ public Type CheckArgumentTypes(List<Expr>/*!*/ actualArgs,
+ out TypeParamInstantiation/*!*/ tpInstantiation,
+ IToken/*!*/ typeCheckingSubject,
+ string/*!*/ opName,
+ TypecheckingContext/*!*/ tc) {
+ Contract.Requires(actualArgs != null);
+ Contract.Requires(typeCheckingSubject != null);
+ Contract.Requires(opName != null);
+ Contract.Requires(tc != null);
+ Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+
+
+
+ Type f = ProxyFor;
+ MapType mf = f as MapType;
+ if (mf != null)
+ return mf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
+
+ MapTypeProxy mpf = f as MapTypeProxy;
+ if (mpf != null)
+ return mpf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
+
+ Contract.Assert(f == null); // no other types should occur as specialisations of this proxy
+
+ // otherwise, we just record the constraints given by this usage of the map type
+ List<Type>/*!*/ arguments = new List<Type>();
+ foreach (Expr/*!*/ e in actualArgs) {
+ Contract.Assert(e != null);
+ arguments.Add(e.Type);
+ }
+ Type/*!*/ result = new TypeProxy(tok, "result");
+ Contract.Assert(result != null);
+ AddConstraint(new Constraint(arguments, result));
+
+ List<Type>/*!*/ argumentsResult = new List<Type>();
+ foreach (Expr/*!*/ e in actualArgs) {
+ Contract.Assert(e != null);
+ argumentsResult.Add(e.Type);
+ }
+ argumentsResult.Add(result);
+
+ tpInstantiation = new MapTypeProxyParamInstantiation(this, argumentsResult);
+ return result;
+ }
+
+ //----------- Cloning ----------------------------------
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Clone(varMap);
+ } else {
+ MapTypeProxy p2 = new MapTypeProxy(tok, Name, Arity);
+ foreach (Constraint c in constraints)
+ p2.AddConstraint(c.Clone(varMap));
+ return p2; // the clone will have a name that ends with $mapproxy<n>$mapproxy<m> (hopefully)
+ }
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ Type p = ProxyFor;
+ if (p != null) {
+ p.Emit(stream, contextBindingStrength);
+ } else {
+ stream.Write("[");
+ string/*!*/ sep = "";
+ for (int i = 0; i < Arity; ++i) {
+ stream.Write(sep);
+ sep = ", ";
+ stream.Write("?");
+ }
+ stream.Write("]?");
+ }
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(cce.NonNullElements(result));
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.Unify(that, unifiableVariables, result);
+ }
+
+ // unify this with that, if possible
+ that = that.Expanded;
+ that = FollowProxy(that);
+
+ if (this.ReallyOccursIn(that))
+ return false;
+
+ TypeVariable tv = that as TypeVariable;
+
+ if (tv != null && unifiableVariables.Contains(tv))
+ return that.Unify(this, unifiableVariables, result);
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ } else if (that is MapType) {
+ MapType mapType = (MapType)that;
+ if (mapType.Arguments.Count == Arity) {
+ bool good = true;
+ foreach (Constraint c in constraints)
+ good &= c.Unify(mapType, unifiableVariables, result);
+ if (good) {
+ DefineProxy(mapType);
+ return true;
+ }
+ }
+ } else if (that is MapTypeProxy) {
+ MapTypeProxy mt = (MapTypeProxy)that;
+ if (mt.Arity == this.Arity) {
+ // we propagate the constraints of this proxy to the more specific one
+ foreach (Constraint c in constraints)
+ mt.AddConstraint(c);
+ DefineProxy(mt);
+ return true;
+ }
+ } else if (that is ConstrainedProxy) {
+ // only map-type proxies can be unified with this MapTypeProxy
+ return false;
+ } else if (that is TypeProxy) {
+ // define: that.ProxyFor := this;
+ return that.Unify(this, unifiableVariables, result);
+ }
+ return false;
+ }
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (this.ProxyFor == null) {
+ // check that the constraints are clean and do not contain any
+ // of the substituted variables (otherwise, we are in big trouble)
+ Contract.Assert(Contract.ForAll(constraints, c =>
+ Contract.ForAll(subst.Keys, var =>
+ Contract.ForAll(0, c.Arguments.Count, t => !c.Arguments[t].FreeVariables.Contains(var)) &&
+ !c.Result.FreeVariables.Contains(var))));
+ }
+ return base.Substitute(subst);
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsMap {
+ get {
+ return true;
+ }
+ }
+ public override MapType/*!*/ AsMap {
+ get {
+ Contract.Ensures(Contract.Result<MapType>() != null);
+
+ Type p = ProxyFor;
+ if (p != null) {
+ return p.AsMap;
+ } else {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // what to do now?
+ }
+ }
+ }
+ public override int MapArity {
+ get {
+ return Arity;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitMapTypeProxy(this);
+ }
+ }
+
+ //=====================================================================
+
+ // Used to annotate types with type synoyms that were used in the
+ // original unresolved types. Such types should be considered as
+ // equivalent to ExpandedType, the annotations are only used to enable
+ // better pretty-printing
+ public class TypeSynonymAnnotation : Type {
+ public Type/*!*/ ExpandedType;
+
+ public readonly List<Type>/*!*/ Arguments;
+ // is set during resolution and determines whether the right number of arguments is given
+ public readonly TypeSynonymDecl/*!*/ Decl;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExpandedType != null);
+ Contract.Invariant(Arguments != null);
+ Contract.Invariant(Decl != null);
+ }
+
+
+ public TypeSynonymAnnotation(IToken/*!*/ token, TypeSynonymDecl/*!*/ decl, List<Type>/*!*/ arguments)
+ : base(token) {
+ Contract.Requires(token != null);
+ Contract.Requires(decl != null);
+ Contract.Requires(arguments != null);
+ Contract.Requires(arguments.Count == decl.TypeParameters.Count);
+ this.Decl = decl;
+ this.Arguments = arguments;
+
+ // build a substitution that can be applied to the definition of
+ // the type synonym
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst =
+ new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ for (int i = 0; i < arguments.Count; ++i)
+ subst.Add(decl.TypeParameters[i], arguments[i]);
+
+ ExpandedType = decl.Body.Substitute(subst);
+ }
+
+ private TypeSynonymAnnotation(IToken/*!*/ token, TypeSynonymDecl/*!*/ decl, List<Type>/*!*/ arguments,
+ Type/*!*/ expandedType)
+ : base(token) {
+ Contract.Requires(token != null);
+ Contract.Requires(decl != null);
+ Contract.Requires(arguments != null);
+ Contract.Requires(expandedType != null);
+
+ this.Decl = decl;
+ this.Arguments = arguments;
+ this.ExpandedType = expandedType;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Clone(varMap));
+ }
+ Type/*!*/ newExpandedType = ExpandedType.Clone(varMap);
+ Contract.Assert(newExpandedType != null);
+ return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.CloneUnresolved());
+ }
+ return new TypeSynonymAnnotation(tok, Decl, newArgs);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type/*!*/ that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(thisBoundVariables != null);
+ //Contract.Requires(thatBoundVariables != null);
+ return ExpandedType.Equals(that, thisBoundVariables, thatBoundVariables);
+ }
+
+ // used to skip leading type annotations
+ internal override Type/*!*/ Expanded {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return ExpandedType.Expanded;
+ }
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(unifiableVariables != null);
+ //Contract.Requires(cce.NonNullElements(result));
+ return ExpandedType.Unify(that, unifiableVariables, result);
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ ExpandedType.Unify(that, unifiableVariables,
+ thisBoundVariables, thatBoundVariables, result);
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (subst.Count == 0)
+ return this;
+ List<Type> newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Substitute(subst));
+ }
+ Type/*!*/ newExpandedType = ExpandedType.Substitute(subst);
+ Contract.Assert(newExpandedType != null);
+ return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ return ExpandedType.GetHashCode(boundVariables);
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ CtorType.EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type> resolvedArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ resolvedArgs.Add(t.ResolveType(rc));
+ }
+ return new TypeSynonymAnnotation(tok, Decl, resolvedArgs);
+ }
+
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ Contract.Ensures(Contract.Result<List<TypeVariable>>() != null);
+
+ return ExpandedType.FreeVariables;
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeProxy>>()));
+ return ExpandedType.FreeProxies;
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsBasic {
+ get {
+ return ExpandedType.IsBasic;
+ }
+ }
+ public override bool IsInt {
+ get {
+ return ExpandedType.IsInt;
+ }
+ }
+ public override bool IsReal
+ {
+ get
+ {
+ return ExpandedType.IsReal;
+ }
+ }
+ public override bool IsFloat
+ {
+ get
+ {
+ return ExpandedType.IsFloat;
+ }
+ }
+ public override bool IsBool {
+ get {
+ return ExpandedType.IsBool;
+ }
+ }
+
+ public override bool IsVariable {
+ get {
+ return ExpandedType.IsVariable;
+ }
+ }
+ public override TypeVariable/*!*/ AsVariable {
+ get {
+ Contract.Ensures(Contract.Result<TypeVariable>() != null);
+ return ExpandedType.AsVariable;
+ }
+ }
+ public override bool IsCtor {
+ get {
+ return ExpandedType.IsCtor;
+ }
+ }
+ public override CtorType/*!*/ AsCtor {
+ get {
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+ return ExpandedType.AsCtor;
+ }
+ }
+ public override bool IsMap {
+ get {
+ return ExpandedType.IsMap;
+ }
+ }
+ public override MapType/*!*/ AsMap {
+ get {
+ Contract.Ensures(Contract.Result<MapType>() != null);
+ return ExpandedType.AsMap;
+ }
+ }
+ public override bool IsUnresolved {
+ get {
+ return ExpandedType.IsUnresolved;
+ }
+ }
+ public override UnresolvedTypeIdentifier/*!*/ AsUnresolved {
+ get {
+ Contract.Ensures(Contract.Result<UnresolvedTypeIdentifier>() != null);
+
+ return ExpandedType.AsUnresolved;
+ }
+ }
+
+ public override bool IsBv {
+ get {
+ return ExpandedType.IsBv;
+ }
+ }
+ public override int BvBits {
+ get {
+ return ExpandedType.BvBits;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitTypeSynonymAnnotation(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class CtorType : Type {
+ public readonly List<Type>/*!*/ Arguments;
+ // is set during resolution and determines whether the right number of arguments is given
+ public readonly TypeCtorDecl/*!*/ Decl;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Arguments != null);
+ Contract.Invariant(Decl != null);
+ }
+
+
+ public CtorType(IToken/*!*/ token, TypeCtorDecl/*!*/ decl, List<Type>/*!*/ arguments)
+ : base(token) {
+ Contract.Requires(token != null);
+ Contract.Requires(decl != null);
+ Contract.Requires(arguments != null);
+ Contract.Requires(arguments.Count == decl.Arity);
+ this.Decl = decl;
+ this.Arguments = arguments;
+ }
+
+ public bool IsDatatype() {
+ return QKeyValue.FindBoolAttribute(Decl.Attributes, "datatype");
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Clone(varMap));
+ }
+ return new CtorType(tok, Decl, newArgs);
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.CloneUnresolved());
+ }
+ return new CtorType(tok, Decl, newArgs);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ Type thatType = that as Type;
+ if (thatType == null)
+ return false;
+ thatType = TypeProxy.FollowProxy(thatType.Expanded);
+ // shortcut
+ CtorType thatCtorType = thatType as CtorType;
+ if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
+ return false;
+ if (Arguments.Count == 0)
+ return true;
+ return base.Equals(thatType);
+ }
+
+ [Pure]
+ public override bool Equals(Type/*!*/ that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables) {
+ that = TypeProxy.FollowProxy(that.Expanded);
+ CtorType thatCtorType = that as CtorType;
+ if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
+ return false;
+ for (int i = 0; i < Arguments.Count; ++i) {
+ if (!Arguments[i].Equals(thatCtorType.Arguments[i],
+ thisBoundVariables, thatBoundVariables))
+ return false;
+ }
+ return true;
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable)
+ return that.Unify(this, unifiableVariables, result);
+
+ CtorType thatCtorType = that as CtorType;
+ if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl)) {
+ return false;
+ } else {
+ bool good = true;
+ for (int i = 0; i < Arguments.Count; ++i)
+ good &= Arguments[i].Unify(thatCtorType.Arguments[i], unifiableVariables, result);
+ return good;
+ }
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ return;
+ }
+
+ CtorType thatCtorType = that as CtorType;
+ if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl))
+ throw UNIFICATION_FAILED;
+ for (int i = 0; i < Arguments.Length; ++i)
+ Arguments[i].Unify(thatCtorType.Arguments[i],
+ unifiableVariables,
+ thisBoundVariables, thatBoundVariables,
+ result);
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (subst.Count == 0)
+ return this;
+ List<Type> newArgs = new List<Type>();
+ lock (Arguments)
+ {
+ foreach (Type/*!*/ t in Arguments)
+ {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Substitute(subst));
+ }
+ }
+ return new CtorType(tok, Decl, newArgs);
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ int res = 1637643879 * Decl.GetHashCode();
+ foreach (Type/*!*/ t in Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ res = res * 3 + t.GetHashCode(boundVariables);
+ }
+ return res;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+ EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
+ }
+
+ internal static void EmitCtorType(string name, List<Type> args, TokenTextWriter stream, int contextBindingStrength) {
+ Contract.Requires(stream != null);
+ Contract.Requires(args != null);
+ Contract.Requires(name != null);
+ int opBindingStrength = args.Count > 0 ? 0 : 2;
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write("(");
+
+ stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(name));
+ int i = args.Count;
+ foreach (Type/*!*/ t in args) {
+ Contract.Assert(t != null);
+ stream.Write(" ");
+ // use a lower binding strength for the last argument
+ // to allow map-types without parentheses
+ t.Emit(stream, i == 1 ? 1 : 2);
+ i = i - 1;
+ }
+
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write(")");
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<Type> resolvedArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ resolvedArgs.Add(t.ResolveType(rc));
+ }
+ return new CtorType(tok, Decl, resolvedArgs);
+ }
+
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ List<TypeVariable>/*!*/ res = new List<TypeVariable>();
+ foreach (Type/*!*/ t in Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ res.AppendWithoutDups(t.FreeVariables);
+ }
+ return res;
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ List<TypeProxy/*!*/>/*!*/ res = new List<TypeProxy/*!*/>();
+ foreach (Type/*!*/ t in Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ AppendWithoutDups(res, t.FreeProxies);
+ }
+ return res;
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsCtor {
+ get {
+ return true;
+ }
+ }
+ public override CtorType/*!*/ AsCtor {
+ get {
+ return this;
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitCtorType(this);
+ }
+ }
+
+ //=====================================================================
+
+ public class MapType : Type {
+ // an invariant is that each of the type parameters has to occur as
+ // free variable in at least one of the arguments
+ public readonly List<TypeVariable>/*!*/ TypeParameters;
+ public readonly List<Type>/*!*/ Arguments;
+ public Type/*!*/ Result;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(TypeParameters != null);
+ Contract.Invariant(Arguments != null);
+ Contract.Invariant(Result != null);
+ }
+
+
+ public MapType(IToken/*!*/ token, List<TypeVariable>/*!*/ typeParameters, List<Type>/*!*/ arguments, Type/*!*/ result)
+ : base(token) {
+ Contract.Requires(token != null);
+ Contract.Requires(typeParameters != null);
+ Contract.Requires(arguments != null);
+ Contract.Requires(result != null);
+
+ this.TypeParameters = typeParameters;
+ this.Result = result;
+ this.Arguments = arguments;
+ }
+
+ //----------- Cloning ----------------------------------
+ // We implement our own clone-method, because bound type variables
+ // have to be created in the right way. It is /not/ ok to just clone
+ // everything recursively
+
+ public override Type Clone(IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ varMap) {
+ //Contract.Requires(cce.NonNullElements(varMap));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ IDictionary<TypeVariable/*!*/, TypeVariable/*!*/>/*!*/ newVarMap =
+ new Dictionary<TypeVariable/*!*/, TypeVariable/*!*/>();
+ foreach (KeyValuePair<TypeVariable/*!*/, TypeVariable/*!*/> p in varMap) {
+ Contract.Assert(cce.NonNullElements(p));
+ if (!TypeParameters.Contains(p.Key))
+ newVarMap.Add(p);
+ }
+
+ List<TypeVariable>/*!*/ newTypeParams = new List<TypeVariable>();
+ foreach (TypeVariable/*!*/ var in TypeParameters) {
+ Contract.Assert(var != null);
+ TypeVariable/*!*/ newVar = new TypeVariable(var.tok, var.Name);
+ Contract.Assert(newVar != null);
+ newVarMap.Add(var, newVar);
+ newTypeParams.Add(newVar);
+ }
+
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Clone(newVarMap));
+ }
+ Type/*!*/ newResult = Result.Clone(newVarMap);
+ Contract.Assert(newResult != null);
+
+ return new MapType(this.tok, newTypeParams, newArgs, newResult);
+ }
+
+ public override Type CloneUnresolved() {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ List<TypeVariable>/*!*/ newTypeParams = new List<TypeVariable>();
+ foreach (TypeVariable/*!*/ var in TypeParameters) {
+ Contract.Assert(var != null);
+ TypeVariable/*!*/ newVar = new TypeVariable(var.tok, var.Name);
+ Contract.Assert(newVar != null);
+ newTypeParams.Add(newVar);
+ }
+
+ List<Type>/*!*/ newArgs = new List<Type>();
+ foreach (Type/*!*/ t in Arguments) {
+ Contract.Assert(t != null);
+ newArgs.Add(t.CloneUnresolved());
+ }
+ Type/*!*/ newResult = Result.CloneUnresolved();
+ Contract.Assert(newResult != null);
+
+ return new MapType(this.tok, newTypeParams, newArgs, newResult);
+ }
+
+ //----------- Equality ----------------------------------
+
+ [Pure]
+ public override bool Equals(Type/*!*/ that,
+ List<TypeVariable>/*!*/ thisBoundVariables,
+ List<TypeVariable>/*!*/ thatBoundVariables)
+ {
+ that = TypeProxy.FollowProxy(that.Expanded);
+ MapType thatMapType = that as MapType;
+ if (thatMapType == null ||
+ this.TypeParameters.Count != thatMapType.TypeParameters.Count ||
+ this.Arguments.Count != thatMapType.Arguments.Count)
+ return false;
+
+ thisBoundVariables = thisBoundVariables.ToList();
+ foreach (TypeVariable/*!*/ var in this.TypeParameters)
+ {
+ Contract.Assert(var != null);
+ thisBoundVariables.Add(var);
+ }
+ thatBoundVariables = thatBoundVariables.ToList();
+ foreach (TypeVariable/*!*/ var in thatMapType.TypeParameters)
+ {
+ Contract.Assert(var != null);
+ thatBoundVariables.Add(var);
+ }
+
+ for (int i = 0; i < Arguments.Count; ++i)
+ {
+ if (!Arguments[i].Equals(thatMapType.Arguments[i],
+ thisBoundVariables, thatBoundVariables))
+ return false;
+ }
+
+ return this.Result.Equals(thatMapType.Result,
+ thisBoundVariables, thatBoundVariables);
+ }
+
+ //----------- Unification of types -----------
+
+ public override bool Unify(Type/*!*/ that,
+ List<TypeVariable>/*!*/ unifiableVariables,
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ result) {
+ that = that.Expanded;
+ if (that is TypeProxy || that is TypeVariable)
+ return that.Unify(this, unifiableVariables, result);
+
+ MapType thatMapType = that as MapType;
+ if (thatMapType == null ||
+ this.TypeParameters.Count != thatMapType.TypeParameters.Count ||
+ this.Arguments.Count != thatMapType.Arguments.Count)
+ return false;
+
+ // treat the bound variables of the two map types as equal...
+ Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst0 =
+ new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ Dictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst1 =
+ new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ List<TypeVariable> freshies = new List<TypeVariable>();
+ for (int i = 0; i < this.TypeParameters.Count; i++) {
+ TypeVariable tp0 = this.TypeParameters[i];
+ TypeVariable tp1 = thatMapType.TypeParameters[i];
+ TypeVariable freshVar = new TypeVariable(tp0.tok, tp0.Name);
+ freshies.Add(freshVar);
+ subst0.Add(tp0, freshVar);
+ subst1.Add(tp1, freshVar);
+ }
+ // ... and then unify the domain and range types
+ bool good = true;
+ for (int i = 0; i < this.Arguments.Count; i++) {
+ Type t0 = this.Arguments[i].Substitute(subst0);
+ Type t1 = thatMapType.Arguments[i].Substitute(subst1);
+ good &= t0.Unify(t1, unifiableVariables, result);
+ }
+ Type r0 = this.Result.Substitute(subst0);
+ Type r1 = thatMapType.Result.Substitute(subst1);
+ good &= r0.Unify(r1, unifiableVariables, result);
+
+ // Finally, check that none of the bound variables has escaped
+ if (good && freshies.Count != 0) {
+ // This is done by looking for occurrences of the fresh variables in the
+ // non-substituted types ...
+ List<TypeVariable> freeVars = this.FreeVariables;
+ foreach (TypeVariable fr in freshies)
+ if (freeVars.Contains(fr)) {
+ return false;
+ } // fresh variable escaped
+ freeVars = thatMapType.FreeVariables;
+ foreach (TypeVariable fr in freshies)
+ if (freeVars.Contains(fr)) {
+ return false;
+ } // fresh variable escaped
+
+ // ... and in the resulting unifier of type variables
+ foreach (KeyValuePair<TypeVariable/*!*/, Type/*!*/> pair in result) {
+ Contract.Assert(cce.NonNullElements(pair));
+ freeVars = pair.Value.FreeVariables;
+ foreach (TypeVariable fr in freshies)
+ if (freeVars.Contains(fr)) {
+ return false;
+ } // fresh variable escaped
+ }
+ }
+
+ return good;
+ }
+
+#if OLD_UNIFICATION
+ public override void Unify(Type! that,
+ List<TypeVariable>! unifiableVariables,
+ List<TypeVariable>! thisBoundVariables,
+ List<TypeVariable>! thatBoundVariables,
+ IDictionary<TypeVariable!, Type!>! result) {
+ that = that.Expanded;
+ if (that is TypeVariable) {
+ that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
+ return;
+ }
+
+ MapType thatMapType = that as MapType;
+ if (thatMapType == null ||
+ this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
+ this.Arguments.Length != thatMapType.Arguments.Length)
+ throw UNIFICATION_FAILED;
+
+ // ensure that no collisions occur
+ if (this.collisionsPossible(result)) {
+ ((MapType)this.Clone())
+ .Unify(that, unifiableVariables,
+ thisBoundVariables, thatBoundVariables, result);
+ return;
+ }
+ if (thatMapType.collisionsPossible(result))
+ thatMapType = (MapType)that.Clone();
+
+ foreach(TypeVariable/*!*/ var in this.TypeParameters){
+Contract.Assert(var != null);
+ thisBoundVariables.Add(var);}
+ foreach(TypeVariable/*!*/ var in thatMapType.TypeParameters){
+Contract.Assert(var != null);
+ thatBoundVariables.Add(var);}
+
+ try {
+
+ for (int i = 0; i < Arguments.Length; ++i)
+ Arguments[i].Unify(thatMapType.Arguments[i],
+ unifiableVariables,
+ thisBoundVariables, thatBoundVariables,
+ result);
+ Result.Unify(thatMapType.Result,
+ unifiableVariables,
+ thisBoundVariables, thatBoundVariables,
+ result);
+
+ } finally {
+ // make sure that the bound variables are removed again
+ for (int i = 0; i < this.TypeParameters.Length; ++i) {
+ thisBoundVariables.Remove();
+ thatBoundVariables.Remove();
+ }
+ }
+ }
+#endif
+
+ //----------- Substitution of free variables with types not containing bound variables -----------------
+
+ [Pure]
+ private bool collisionsPossible(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(subst));
+ // PR: could be written more efficiently
+ return TypeParameters.Any(param => subst.ContainsKey(param) || subst.Values.Any(val => val.FreeVariables.Contains(param)));
+ }
+
+ public override Type Substitute(IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst) {
+ //Contract.Requires(cce.NonNullElements(subst));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (subst.Count == 0)
+ return this;
+
+ // there are two cases in which we have to be careful:
+ // * a variable to be substituted is shadowed by a variable binder
+ // * a substituted term contains variables that are bound in the
+ // type (variable capture)
+ //
+ // in both cases, we first clone the type to ensure that bound
+ // variables are fresh
+
+ if (collisionsPossible(subst)) {
+ MapType/*!*/ newType = (MapType)this.Clone();
+ Contract.Assert(newType != null);
+ Contract.Assert(newType.Equals(this) && !newType.collisionsPossible(subst));
+ return newType.Substitute(subst);
+ }
+
+ List<Type> newArgs = new List<Type>();
+ lock (Arguments)
+ {
+ foreach (Type/*!*/ t in Arguments)
+ {
+ Contract.Assert(t != null);
+ newArgs.Add(t.Substitute(subst));
+ }
+ }
+ Type/*!*/ newResult = Result.Substitute(subst);
+ Contract.Assert(newResult != null);
+
+ return new MapType(tok, TypeParameters, newArgs, newResult);
+ }
+
+ //----------- Hashcodes ----------------------------------
+
+ [Pure]
+ public override int GetHashCode(List<TypeVariable> boundVariables) {
+ //Contract.Requires(boundVariables != null);
+ int res = 7643761 * TypeParameters.Count + 65121 * Arguments.Count;
+
+ boundVariables = boundVariables.ToList();
+ foreach (TypeVariable/*!*/ var in this.TypeParameters) {
+ Contract.Assert(var != null);
+ boundVariables.Add(var);
+ }
+
+ foreach (Type/*!*/ t in Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ res = res * 5 + t.GetHashCode(boundVariables);
+ }
+ res = res * 7 + Result.GetHashCode(boundVariables);
+
+ return res;
+ }
+
+ //----------- Linearisation ----------------------------------
+
+ public override void Emit(TokenTextWriter stream, int contextBindingStrength) {
+ //Contract.Requires(stream != null);
+ stream.SetToken(this);
+
+ const int opBindingStrength = 1;
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write("(");
+
+ EmitOptionalTypeParams(stream, TypeParameters);
+
+ stream.Write("[");
+ Arguments.Emit(stream, ","); // default binding strength of 0 is ok
+ stream.Write("]");
+ Result.Emit(stream); // default binding strength of 0 is ok
+
+ if (opBindingStrength < contextBindingStrength)
+ stream.Write(")");
+ }
+
+ //----------- Resolution ----------------------------------
+
+ public override Type ResolveType(ResolutionContext rc) {
+ //Contract.Requires(rc != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ int previousState = rc.TypeBinderState;
+ try {
+ foreach (TypeVariable/*!*/ v in TypeParameters) {
+ Contract.Assert(v != null);
+ rc.AddTypeBinder(v);
+ }
+
+ List<Type> resolvedArgs = new List<Type>();
+ foreach (Type/*!*/ ty in Arguments) {
+ Contract.Assert(ty != null);
+ resolvedArgs.Add(ty.ResolveType(rc));
+ }
+
+ Type resolvedResult = Result.ResolveType(rc);
+
+ CheckBoundVariableOccurrences(TypeParameters,
+ resolvedArgs, new List<Type> { resolvedResult },
+ this.tok, "map arguments",
+ rc);
+
+ // sort the type parameters so that they are bound in the order of occurrence
+ List<TypeVariable>/*!*/ sortedTypeParams = SortTypeParams(TypeParameters, resolvedArgs, resolvedResult);
+ Contract.Assert(sortedTypeParams != null);
+ return new MapType(tok, sortedTypeParams, resolvedArgs, resolvedResult);
+ } finally {
+ rc.TypeBinderState = previousState;
+ }
+ }
+
+ public override List<TypeVariable>/*!*/ FreeVariables {
+ get {
+ List<TypeVariable>/*!*/ res = FreeVariablesIn(Arguments.ToList());
+ Contract.Assert(res != null);
+ res.AppendWithoutDups(Result.FreeVariables);
+ foreach (TypeVariable/*!*/ v in TypeParameters.ToArray()) {
+ Contract.Assert(v != null);
+ res.Remove(v);
+ }
+ return res;
+ }
+ }
+
+ public override List<TypeProxy/*!*/>/*!*/ FreeProxies {
+ get {
+ List<TypeProxy/*!*/>/*!*/ res = new List<TypeProxy/*!*//*!*/>();
+ foreach (Type/*!*/ t in Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ AppendWithoutDups(res, t.FreeProxies);
+ }
+ AppendWithoutDups(res, Result.FreeProxies);
+ return res;
+ }
+ }
+
+ //----------- Getters/Issers ----------------------------------
+
+ public override bool IsMap {
+ get {
+ return true;
+ }
+ }
+ public override MapType/*!*/ AsMap {
+ get {
+ return this;
+ }
+ }
+ public override int MapArity {
+ get {
+ return Arguments.Count;
+ }
+ }
+
+ //------------ Match formal argument types of the map
+ //------------ on concrete types, substitute the result into the
+ //------------ result type. Null is returned if so many type checking
+ //------------ errors occur that the situation is hopeless
+
+ public Type CheckArgumentTypes(List<Expr>/*!*/ actualArgs,
+ out TypeParamInstantiation/*!*/ tpInstantiation,
+ IToken/*!*/ typeCheckingSubject,
+ string/*!*/ opName,
+ TypecheckingContext/*!*/ tc) {
+ Contract.Requires(actualArgs != null);
+ Contract.Requires(typeCheckingSubject != null);
+
+ Contract.Requires(opName != null);
+ Contract.Requires(tc != null);
+Contract.Ensures(Contract.ValueAtReturn(out tpInstantiation) != null);
+ List<Type/*!*/>/*!*/ actualTypeParams;
+ List<Type> actualResult =
+ Type.CheckArgumentTypes(TypeParameters, out actualTypeParams, Arguments, actualArgs,
+ new List<Type> { Result }, null, typeCheckingSubject, opName, tc);
+ if (actualResult == null) {
+ tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
+ return null;
+ } else {
+ Contract.Assert(actualResult.Count == 1);
+ tpInstantiation = SimpleTypeParamInstantiation.From(TypeParameters, actualTypeParams);
+ return actualResult[0];
+ }
+ }
+
+ public override Absy StdDispatch(StandardVisitor visitor) {
+ //Contract.Requires(visitor != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ return visitor.VisitMapType(this);
+ }
+ }
+
+ //---------------------------------------------------------------------
+
+ public enum SimpleType {
+ Int,
+ Real,
+ Bool
+ };
+
+
+ //=====================================================================
+
+ // Interface for representing the instantiations of type parameters of
+ // polymorphic functions or maps. We introduce an own interface for this
+ // instead of using a simple list or dictionary, because in some cases
+ // (due to the type proxies for map types) the actual number and instantiation
+ // of type parameters can only be determined very late.
+ [ContractClass(typeof(TypeParamInstantiationContracts))]
+ public interface TypeParamInstantiation {
+ // return what formal type parameters there are
+ List<TypeVariable/*!*/>/*!*/ FormalTypeParams {
+ get;
+ }
+ // given a formal type parameter, return the actual instantiation
+ Type/*!*/ this[TypeVariable/*!*/ var] {
+ get;
+ }
+ }
+ [ContractClassFor(typeof(TypeParamInstantiation))]
+ public abstract class TypeParamInstantiationContracts : TypeParamInstantiation {
+ #region TypeParamInstantiation Members
+
+ public List<TypeVariable> FormalTypeParams {
+
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
+ throw new NotImplementedException();
+ }
+ }
+
+ public Type this[TypeVariable var] {
+ get {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ #endregion
+ }
+
+
+ public class SimpleTypeParamInstantiation : TypeParamInstantiation {
+ private readonly List<TypeVariable/*!*/>/*!*/ TypeParams;
+ [ContractInvariantMethod]
+ void TypeParamsInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(TypeParams));
+ }
+ private readonly IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ Instantiations;
+ [ContractInvariantMethod]
+ void InstantiationsInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Instantiations));
+ }
+
+ public SimpleTypeParamInstantiation(List<TypeVariable/*!*/>/*!*/ typeParams,
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ instantiations) {
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(cce.NonNullDictionaryAndValues(instantiations));
+ this.TypeParams = typeParams;
+ this.Instantiations = instantiations;
+ }
+
+ public static TypeParamInstantiation/*!*/ From(List<TypeVariable> typeParams, List<Type/*!*/>/*!*/ actualTypeParams) {
+ Contract.Requires(cce.NonNullElements(actualTypeParams));
+ Contract.Requires(typeParams != null);
+ Contract.Requires(typeParams.Count == actualTypeParams.Count);
+ Contract.Ensures(Contract.Result<TypeParamInstantiation>() != null);
+
+ if (typeParams.Count == 0)
+ return EMPTY;
+
+ List<TypeVariable/*!*/>/*!*/ typeParamList = new List<TypeVariable/*!*/>();
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ for (int i = 0; i < typeParams.Count; ++i) {
+ typeParamList.Add(typeParams[i]);
+ dict.Add(typeParams[i], actualTypeParams[i]);
+ }
+ return new SimpleTypeParamInstantiation(typeParamList, dict);
+ }
+
+ public static readonly TypeParamInstantiation EMPTY =
+ new SimpleTypeParamInstantiation(new List<TypeVariable/*!*/>(),
+ new Dictionary<TypeVariable/*!*/, Type/*!*/>());
+
+ // return what formal type parameters there are
+ public List<TypeVariable/*!*/>/*!*/ FormalTypeParams {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
+ return TypeParams;
+ }
+ }
+ // given a formal type parameter, return the actual instantiation
+ public Type/*!*/ this[TypeVariable/*!*/ var] {
+ get {
+ return Instantiations[var];
+ }
+ }
+ }
+
+ // Implementation of TypeParamInstantiation that refers to the current
+ // value of a MapTypeProxy. This means that the values return by the
+ // methods of this implementation can change in case the MapTypeProxy
+ // receives further unifications.
+ class MapTypeProxyParamInstantiation : TypeParamInstantiation {
+ private readonly MapTypeProxy/*!*/ Proxy;
+
+ // the argument and result type of this particular usage of the map
+ // type. these are necessary to derive the values of the type parameters
+ private readonly List<Type>/*!*/ ArgumentsResult;
+
+ // field that is initialised once all necessary information is available
+ // (the MapTypeProxy is instantiated to an actual type) and the instantiation
+ // of a type parameter is queried
+ private IDictionary<TypeVariable/*!*/, Type/*!*/> Instantiations = null;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Proxy != null);
+ Contract.Invariant(ArgumentsResult != null);
+ Contract.Invariant(Instantiations == null || cce.NonNullDictionaryAndValues(Instantiations));
+ }
+
+
+ public MapTypeProxyParamInstantiation(MapTypeProxy/*!*/ proxy,
+ List<Type>/*!*/ argumentsResult) {
+ Contract.Requires(proxy != null);
+ Contract.Requires(argumentsResult != null);
+ this.Proxy = proxy;
+ this.ArgumentsResult = argumentsResult;
+ }
+
+ // return what formal type parameters there are
+ public List<TypeVariable/*!*/>/*!*/ FormalTypeParams {
+ get {
+ MapType realType = Proxy.ProxyFor as MapType;
+ if (realType == null)
+ // no instantiation of the map type is known, which means
+ // that the map type is assumed to be monomorphic
+ return new List<TypeVariable/*!*/>();
+ else
+ return realType.TypeParameters.ToList();
+ }
+ }
+
+ // given a formal type parameter, return the actual instantiation
+ public Type/*!*/ this[TypeVariable/*!*/ var] {
+ get {
+ // then there has to be an instantiation that is a polymorphic map type
+ if (Instantiations == null) {
+ MapType realType = Proxy.ProxyFor as MapType;
+ Contract.Assert(realType != null);
+ List<Type>/*!*/ formalArgs = new List<Type>();
+ foreach (Type/*!*/ t in realType.Arguments) {
+ Contract.Assert(t != null);
+ formalArgs.Add(t);
+ }
+ formalArgs.Add(realType.Result);
+ Instantiations =
+ Type.InferTypeParameters(realType.TypeParameters, formalArgs, ArgumentsResult);
+ }
+ return Instantiations[var];
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Core/AlphaEquality.cs b/Source/Core/AlphaEquality.cs
index 1d4a1d95..986cc4bd 100644
--- a/Source/Core/AlphaEquality.cs
+++ b/Source/Core/AlphaEquality.cs
@@ -1,162 +1,162 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System.ComponentModel;
-
-namespace Microsoft.Boogie
-{
-
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
-
- public class AlphaEquality : IEqualityComparer<Expr>
- {
- private readonly DeBruijnRenamer deBruijn = new DeBruijnRenamer();
-
- bool IEqualityComparer<Expr>.Equals(Expr x, Expr y) {
- var nx = deBruijn.Rename(x);
- var ny = deBruijn.Rename(y);
- return BinderExpr.EqualWithAttributesAndTriggers(nx, ny);
- }
-
- int IEqualityComparer<Expr>.GetHashCode(Expr obj) {
- return 0;
- // Best we can do because GetHashCode for Expression don't respect its equality.
- // When it does, we can instead use:
- // return deBruijn.Rename(obj).GetHashCode();
- }
-
- // Renames expressions into deBruijn indicies, such as
- // (lambda x : int :: x + a)
- // into
- // (lambda bv#0 : int :: bv#0 + fv#0)
- // It does not handle type variables yet, but it could be added.
- //
- // This class could be made public, but it is not since the Rename method
- // could then leak FreeVariables out of here.
- private class DeBruijnRenamer : Duplicator
- {
-
- // Maps from index positions and types to new variables
- private readonly TypeDict<BoundVariable> boundVars =
- new TypeDict<BoundVariable>("bv", ti => new BoundVariable(Token.NoToken, ti));
-
- private readonly TypeDict<FreeVariable> freeVars =
- new TypeDict<FreeVariable>("fv", ti => new FreeVariable(ti));
-
- // These three variables are reset at the beginning of every renaming
- private int boundVarCount, freeVarCount;
- private Dictionary<Variable, FreeVariable> freeVarMap;
-
- // Cached, previous results
- private readonly Dictionary<Expr, Expr> cache = new Dictionary<Expr, Expr>();
-
- public Expr Rename(Expr e) {
- Expr ne;
- if (!cache.TryGetValue(e, out ne)) {
- boundVarCount = 0;
- freeVarCount = 0;
- freeVarMap = new Dictionary<Variable, FreeVariable>();
-
- ne = VisitExpr(e);
- cache[e] = ne;
-#if DEBUG_ALPHA_RENAMING
- var wr = new TokenTextWriter("<console>", Console.Out, true);
- Console.Write("nm( ");
- e.Emit(wr);
- Console.WriteLine(" )");
- Console.Write(" = ");
- ne.Emit(wr);
- Console.WriteLine("");
- Console.WriteLine("h = " + ne.GetHashCode());
-#endif
- }
- return ne;
- }
-
- public override BinderExpr VisitBinderExpr(BinderExpr node) {
- var subst = new Dictionary<Variable, Expr>();
- var newBound = new List<Variable>();
- foreach (var bv in node.Dummies) {
- var bvNew = boundVars[boundVarCount++, bv.TypedIdent.Type];
- newBound.Add(bvNew);
- subst[bv] = new IdentifierExpr(Token.NoToken, bvNew);
- }
- node.Dummies = this.VisitVariableSeq(newBound);
- node.Body = this.VisitExpr(Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), node.Body));
- return node;
- }
-
- public override Variable VisitVariable(Variable node) {
- FreeVariable fv;
- var bv = node as BoundVariable;
- if (boundVars.ContainsValue(bv)) {
- return node;
- } else if (freeVarMap.TryGetValue(node, out fv)) {
- return fv;
- } else {
- return freeVarMap[node] = freeVars[freeVarCount++, node.TypedIdent.Type];
- }
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- var ie = (IdentifierExpr) base.VisitIdentifierExpr(node);
- // Need to fix up the name, since IdentifierExpr's equality also checks the name
- ie.Name = ie.Decl.TypedIdent.Name;
- return ie;
- }
-
- private class TypeDict<A>
- {
- private readonly Dictionary<Tuple<int, Type>, A> vars = new Dictionary<Tuple<int, Type>, A>();
-
- private readonly string Prefix; // either "bv" or "fv"
- private readonly Func<TypedIdent, A> Mk; // either new BoundVar or new FreeVar
-
- public TypeDict(string prefix, Func<TypedIdent, A> mk) {
- Prefix = prefix;
- Mk = mk;
- }
-
- // For debugging purposes, we create unique names when types differ, but the index are the same.
- private int created = 0;
-
- // Make sure that this index and this type is always mapped to the same variable
- public A this[int i, Type t] {
- get {
- A v;
- if (!vars.TryGetValue(Tuple.Create(i, t), out v)) {
- v = Mk(new TypedIdent(Token.NoToken, Prefix + i + "#" + created++, t));
- vars[Tuple.Create(i, t)] = v;
- }
- return v;
- }
- }
-
- public bool ContainsValue(A a) {
- return vars.ContainsValue(a);
- }
- }
-
- private class FreeVariable : Variable
- {
- public FreeVariable(TypedIdent ti) : base(Token.NoToken, ti) {}
-
- public override bool IsMutable {
- get { throw new cce.UnreachableException(); }
- }
-
- public override void Register(ResolutionContext rc) {
- throw new cce.UnreachableException();
- }
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System.ComponentModel;
+
+namespace Microsoft.Boogie
+{
+
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ public class AlphaEquality : IEqualityComparer<Expr>
+ {
+ private readonly DeBruijnRenamer deBruijn = new DeBruijnRenamer();
+
+ bool IEqualityComparer<Expr>.Equals(Expr x, Expr y) {
+ var nx = deBruijn.Rename(x);
+ var ny = deBruijn.Rename(y);
+ return BinderExpr.EqualWithAttributesAndTriggers(nx, ny);
+ }
+
+ int IEqualityComparer<Expr>.GetHashCode(Expr obj) {
+ return 0;
+ // Best we can do because GetHashCode for Expression don't respect its equality.
+ // When it does, we can instead use:
+ // return deBruijn.Rename(obj).GetHashCode();
+ }
+
+ // Renames expressions into deBruijn indicies, such as
+ // (lambda x : int :: x + a)
+ // into
+ // (lambda bv#0 : int :: bv#0 + fv#0)
+ // It does not handle type variables yet, but it could be added.
+ //
+ // This class could be made public, but it is not since the Rename method
+ // could then leak FreeVariables out of here.
+ private class DeBruijnRenamer : Duplicator
+ {
+
+ // Maps from index positions and types to new variables
+ private readonly TypeDict<BoundVariable> boundVars =
+ new TypeDict<BoundVariable>("bv", ti => new BoundVariable(Token.NoToken, ti));
+
+ private readonly TypeDict<FreeVariable> freeVars =
+ new TypeDict<FreeVariable>("fv", ti => new FreeVariable(ti));
+
+ // These three variables are reset at the beginning of every renaming
+ private int boundVarCount, freeVarCount;
+ private Dictionary<Variable, FreeVariable> freeVarMap;
+
+ // Cached, previous results
+ private readonly Dictionary<Expr, Expr> cache = new Dictionary<Expr, Expr>();
+
+ public Expr Rename(Expr e) {
+ Expr ne;
+ if (!cache.TryGetValue(e, out ne)) {
+ boundVarCount = 0;
+ freeVarCount = 0;
+ freeVarMap = new Dictionary<Variable, FreeVariable>();
+
+ ne = VisitExpr(e);
+ cache[e] = ne;
+#if DEBUG_ALPHA_RENAMING
+ var wr = new TokenTextWriter("<console>", Console.Out, true);
+ Console.Write("nm( ");
+ e.Emit(wr);
+ Console.WriteLine(" )");
+ Console.Write(" = ");
+ ne.Emit(wr);
+ Console.WriteLine("");
+ Console.WriteLine("h = " + ne.GetHashCode());
+#endif
+ }
+ return ne;
+ }
+
+ public override BinderExpr VisitBinderExpr(BinderExpr node) {
+ var subst = new Dictionary<Variable, Expr>();
+ var newBound = new List<Variable>();
+ foreach (var bv in node.Dummies) {
+ var bvNew = boundVars[boundVarCount++, bv.TypedIdent.Type];
+ newBound.Add(bvNew);
+ subst[bv] = new IdentifierExpr(Token.NoToken, bvNew);
+ }
+ node.Dummies = this.VisitVariableSeq(newBound);
+ node.Body = this.VisitExpr(Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), node.Body));
+ return node;
+ }
+
+ public override Variable VisitVariable(Variable node) {
+ FreeVariable fv;
+ var bv = node as BoundVariable;
+ if (boundVars.ContainsValue(bv)) {
+ return node;
+ } else if (freeVarMap.TryGetValue(node, out fv)) {
+ return fv;
+ } else {
+ return freeVarMap[node] = freeVars[freeVarCount++, node.TypedIdent.Type];
+ }
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ var ie = (IdentifierExpr) base.VisitIdentifierExpr(node);
+ // Need to fix up the name, since IdentifierExpr's equality also checks the name
+ ie.Name = ie.Decl.TypedIdent.Name;
+ return ie;
+ }
+
+ private class TypeDict<A>
+ {
+ private readonly Dictionary<Tuple<int, Type>, A> vars = new Dictionary<Tuple<int, Type>, A>();
+
+ private readonly string Prefix; // either "bv" or "fv"
+ private readonly Func<TypedIdent, A> Mk; // either new BoundVar or new FreeVar
+
+ public TypeDict(string prefix, Func<TypedIdent, A> mk) {
+ Prefix = prefix;
+ Mk = mk;
+ }
+
+ // For debugging purposes, we create unique names when types differ, but the index are the same.
+ private int created = 0;
+
+ // Make sure that this index and this type is always mapped to the same variable
+ public A this[int i, Type t] {
+ get {
+ A v;
+ if (!vars.TryGetValue(Tuple.Create(i, t), out v)) {
+ v = Mk(new TypedIdent(Token.NoToken, Prefix + i + "#" + created++, t));
+ vars[Tuple.Create(i, t)] = v;
+ }
+ return v;
+ }
+ }
+
+ public bool ContainsValue(A a) {
+ return vars.ContainsValue(a);
+ }
+ }
+
+ private class FreeVariable : Variable
+ {
+ public FreeVariable(TypedIdent ti) : base(Token.NoToken, ti) {}
+
+ public override bool IsMutable {
+ get { throw new cce.UnreachableException(); }
+ }
+
+ public override void Register(ResolutionContext rc) {
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Core/BoogiePL.atg b/Source/Core/BoogiePL.atg
index 644a5d3d..091ceeb0 100644
--- a/Source/Core/BoogiePL.atg
+++ b/Source/Core/BoogiePL.atg
@@ -1,1511 +1,1511 @@
-
-/*---------------------------------------------------------------------------
-// BoogiePL -
-//--------------------------------------------------------------------------*/
-
-/*using System;*/
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using Bpl = Microsoft.Boogie;
-
-
-COMPILER BoogiePL
-
-/*--------------------------------------------------------------------------*/
-
-readonly Program/*!*/ Pgm;
-
-readonly Expr/*!*/ dummyExpr;
-readonly Cmd/*!*/ dummyCmd;
-readonly Block/*!*/ dummyBlock;
-readonly Bpl.Type/*!*/ dummyType;
-readonly List<Expr>/*!*/ dummyExprSeq;
-readonly TransferCmd/*!*/ dummyTransferCmd;
-readonly StructuredCmd/*!*/ dummyStructuredCmd;
-
-///<summary>
-///Returns the number of parsing errors encountered. If 0, "program" returns as
-///the parsed program.
-///</summary>
-public static int Parse (string/*!*/ filename, /*maybe null*/ List<string/*!*/> defines, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
- Contract.Requires(filename != null);
- Contract.Requires(cce.NonNullElements(defines,true));
-
- if (defines == null) {
- defines = new List<string/*!*/>();
- }
-
- if (filename == "stdin.bpl") {
- var s = ParserHelper.Fill(Console.In, defines);
- return Parse(s, filename, out program, useBaseName);
- } else {
- FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
- var s = ParserHelper.Fill(stream, defines);
- var ret = Parse(s, filename, out program, useBaseName);
- stream.Close();
- return ret;
- }
-}
-
-
-public static int Parse (string s, string/*!*/ filename, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
- Contract.Requires(s != null);
- Contract.Requires(filename != null);
-
- byte[]/*!*/ buffer = cce.NonNull(UTF8Encoding.Default.GetBytes(s));
- MemoryStream ms = new MemoryStream(buffer,false);
- Errors errors = new Errors();
- Scanner scanner = new Scanner(ms, errors, filename, useBaseName);
-
- Parser parser = new Parser(scanner, errors, false);
- parser.Parse();
- if (parser.errors.count == 0)
- {
- program = parser.Pgm;
- program.ProcessDatatypeConstructors();
- return 0;
- }
- else
- {
- program = null;
- return parser.errors.count;
- }
-}
-
-public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, bool disambiguation)
- : this(scanner, errors)
-{
- // initialize readonly fields
- Pgm = new Program();
- dummyExpr = new LiteralExpr(Token.NoToken, false);
- dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
- dummyBlock = new Block(Token.NoToken, "dummyBlock", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
- dummyExprSeq = new List<Expr> ();
- dummyTransferCmd = new ReturnCmd(Token.NoToken);
- dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
-}
-
-// Class to represent the bounds of a bitvector expression t[a:b].
-// Objects of this class only exist during parsing and are directly
-// turned into BvExtract before they get anywhere else
-private class BvBounds : Expr {
- public BigNum Lower;
- public BigNum Upper;
- public BvBounds(IToken/*!*/ tok, BigNum lower, BigNum upper)
- : base(tok) {
- Contract.Requires(tok != null);
- this.Lower = lower;
- this.Upper = upper;
- }
- public override Bpl.Type/*!*/ ShallowType { get {Contract.Ensures(Contract.Result<Bpl.Type>() != null); return Bpl.Type.Int; } }
- public override void Resolve(ResolutionContext/*!*/ rc) {
- // Contract.Requires(rc != null);
- rc.Error(this, "bitvector bounds in illegal position");
- }
- public override void Emit(TokenTextWriter/*!*/ stream,
- int contextBindingStrength, bool fragileContext) {
- Contract.Assert(false);throw new cce.UnreachableException();
- }
- public override void ComputeFreeVariables(GSet<object>/*!*/ freeVars) { Contract.Assert(false);throw new cce.UnreachableException(); }
-}
-
-/*--------------------------------------------------------------------------*/
-CHARACTERS
- letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
- digit = "0123456789".
- special = "'~#$^_.?`".
- glyph = "`~!@#$%^&*()-_=+[{]}|;:',<.>/?\\".
-
- cr = '\r'.
- lf = '\n'.
- tab = '\t'.
-
- space = ' '.
- quote = '"'.
-
- newLine = cr + lf.
- regularStringChar = ANY - quote - newLine.
-
- nondigit = letter + special.
- nonquote = letter + digit + space + glyph.
-
-
-/*------------------------------------------------------------------------*/
-TOKENS
- ident = [ '\\' ] nondigit {nondigit | digit}.
- bvlit = digit {digit} 'b' 'v' digit {digit}.
- digits = digit {digit}.
-
- string = quote { regularStringChar | "\\\"" } quote.
-
- decimal = digit {digit} 'e' [ '-' ] digit {digit} .
- float = digit {digit} '.' digit {digit} [ 'e' [ '-' ] digit {digit} ] .
-
-COMMENTS FROM "/*" TO "*/" NESTED
-COMMENTS FROM "//" TO lf
-
-IGNORE cr + lf + tab
-
-
-/*------------------------------------------------------------------------*/
-PRODUCTIONS
-
-
-/*------------------------------------------------------------------------*/
-BoogiePL
-= (. List<Variable>/*!*/ vs;
- List<Declaration>/*!*/ ds;
- Axiom/*!*/ ax;
- List<Declaration/*!*/>/*!*/ ts;
- Procedure/*!*/ pr;
- Implementation im;
- Implementation/*!*/ nnim;
- .)
- { Consts<out vs> (. foreach(Bpl.Variable/*!*/ v in vs){
- Contract.Assert(v != null);
- Pgm.AddTopLevelDeclaration(v);
- }
- .)
- | Function<out ds> (. foreach(Bpl.Declaration/*!*/ d in ds){
- Contract.Assert(d != null);
- Pgm.AddTopLevelDeclaration(d);
- }
- .)
- | Axiom<out ax> (. Pgm.AddTopLevelDeclaration(ax); .)
- | UserDefinedTypes<out ts> (. foreach(Declaration/*!*/ td in ts){
- Contract.Assert(td != null);
- Pgm.AddTopLevelDeclaration(td);
- }
- .)
- | GlobalVars<out vs> (. foreach(Bpl.Variable/*!*/ v in vs){
- Contract.Assert(v != null);
- Pgm.AddTopLevelDeclaration(v);
- }
- .)
- | Procedure<out pr, out im> (. Pgm.AddTopLevelDeclaration(pr);
- if (im != null) {
- Pgm.AddTopLevelDeclaration(im);
- }
- .)
- | Implementation<out nnim> (. Pgm.AddTopLevelDeclaration(nnim); .)
- }
- EOF
- .
-
-/*------------------------------------------------------------------------*/
-GlobalVars<.out List<Variable>/*!*/ ds.>
-= (.
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- QKeyValue kv = null;
- ds = new List<Variable>();
- var dsx = ds;
- .)
- "var"
- { Attribute<ref kv> }
- IdsTypeWheres<true, "global variables", delegate(TypedIdent tyd) { dsx.Add(new GlobalVariable(tyd.tok, tyd, kv)); } > ";"
- .
-
-LocalVars<.List<Variable>/*!*/ ds.>
-= (.
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- QKeyValue kv = null;
- .)
- "var"
- { Attribute<ref kv> }
- IdsTypeWheres<true, "local variables", delegate(TypedIdent tyd) { ds.Add(new LocalVariable(tyd.tok, tyd, kv)); } > ";"
- .
-
-ProcFormals<.bool incoming, bool allowWhereClauses, out List<Variable>/*!*/ ds.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- ds = new List<Variable>();
- var dsx = ds;
- var context = allowWhereClauses ? "procedure formals" : "the 'implementation' copies of formals";
- .)
- "("
- [ AttrsIdsTypeWheres<allowWhereClauses, allowWhereClauses, context, delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new Formal(tyd.tok, tyd, incoming, kv)); }>
- ]
- ")"
- .
-
-BoundVars<.IToken/*!*/ x, out List<Variable>/*!*/ ds.>
-= (.
- Contract.Requires(x != null);
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- List<TypedIdent>/*!*/ tyds = new List<TypedIdent>();
- ds = new List<Variable>();
- var dsx = ds;
- .)
- AttrsIdsTypeWheres<true, false, "bound variables", delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new BoundVariable(tyd.tok, tyd, kv)); } >
- .
-
-/*------------------------------------------------------------------------*/
-/* IdsType is used with const declarations */
-IdsType<.out List<TypedIdent>/*!*/ tyds.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out tyds) != null); List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty; .)
- Idents<out ids> ":" Type<out ty>
- (. tyds = new List<TypedIdent>();
- foreach(Token/*!*/ id in ids){
- Contract.Assert(id != null);
- tyds.Add(new TypedIdent(id, id.val, ty, null));
- }
- .)
- .
-
-/* AttrsIdsTypeWheres is used with the declarations of formals and bound variables */
-AttrsIdsTypeWheres<. bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action .>
-=
- AttributesIdsTypeWhere<allowAttributes, allowWhereClauses, context, action>
- { "," AttributesIdsTypeWhere<allowAttributes, allowWhereClauses, context, action> }
- .
-
-IdsTypeWheres<. bool allowWhereClauses, string context, System.Action<TypedIdent> action .>
-=
- IdsTypeWhere<allowWhereClauses, context, action>
- { "," IdsTypeWhere<allowWhereClauses, context, action> }
- .
-
-AttributesIdsTypeWhere<. bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action .>
-= (. QKeyValue kv = null; .)
- { Attribute<ref kv> (. if (!allowAttributes) {
- kv = null;
- this.SemErr("attributes are not allowed on " + context);
- }
- .)
- }
- IdsTypeWhere<allowWhereClauses, context, delegate(TypedIdent tyd) { action(tyd, kv); }>
- .
-
-/* context is allowed to be null if allowWhereClauses is true */
-IdsTypeWhere<. bool allowWhereClauses, string context, System.Action<TypedIdent> action .>
-= (. List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty; Expr wh = null; Expr/*!*/ nne; .)
- Idents<out ids> ":" Type<out ty>
- [ "where" Expression<out nne> (. if (!allowWhereClauses) {
- this.SemErr("where clause not allowed on " + context);
- } else {
- wh = nne;
- }
- .)
- ]
- (. foreach(Token/*!*/ id in ids){
- Contract.Assert(id != null);
- action(new TypedIdent(id, id.val, ty, wh));
- }
- .)
- .
-
-/*------------------------------------------------------------------------*/
-Type<out Bpl.Type/*!*/ ty>
-= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; ty = dummyType; .)
- (
- TypeAtom<out ty>
- |
- Ident<out tok> (. List<Bpl.Type>/*!*/ args = new List<Bpl.Type> (); .)
- [ TypeArgs<args> ] (. ty = new UnresolvedTypeIdentifier (tok, tok.val, args); .)
- |
- MapType<out ty>
- )
- .
-
-TypeArgs<.List<Bpl.Type>/*!*/ ts.>
-= (.Contract.Requires(ts != null); IToken/*!*/ tok; Bpl.Type/*!*/ ty; .)
- (
- TypeAtom<out ty> (. ts.Add(ty); .)
- [ TypeArgs<ts> ]
- |
- Ident<out tok> (. List<Bpl.Type>/*!*/ args = new List<Bpl.Type> ();
- ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args)); .)
- [ TypeArgs<ts> ]
- |
- MapType<out ty> (. ts.Add(ty); .)
- )
- .
-
-TypeAtom<out Bpl.Type/*!*/ ty>
-= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType; .)
- ( "int" (. ty = new BasicType(t, SimpleType.Int); .)
- | "real" (. ty = new BasicType(t, SimpleType.Real); .)
- | "bool" (. ty = new BasicType(t, SimpleType.Bool); .)
- /* note: bitvectors are handled in UnresolvedTypeIdentifier */
- |
- "("
- Type<out ty>
- ")"
- )
- .
-
-MapType<out Bpl.Type/*!*/ ty>
-= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken tok = null;
- IToken/*!*/ nnTok;
- List<Bpl.Type>/*!*/ arguments = new List<Bpl.Type>();
- Bpl.Type/*!*/ result;
- List<TypeVariable>/*!*/ typeParameters = new List<TypeVariable>();
- .)
- [ TypeParams<out nnTok, out typeParameters> (. tok = nnTok; .) ]
- "[" (. if (tok == null) tok = t; .)
- [ Types<arguments> ]
- "]"
- Type<out result>
- (.
- ty = new MapType(tok, typeParameters, arguments, result);
- .)
- .
-
-TypeParams<.out IToken/*!*/ tok, out List<TypeVariable>/*!*/ typeParams.>
-= (.Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); List<IToken>/*!*/ typeParamToks; .)
- "<" (. tok = t; .)
- Idents<out typeParamToks>
- ">"
- (.
- typeParams = new List<TypeVariable> ();
- foreach(Token/*!*/ id in typeParamToks){
- Contract.Assert(id != null);
- typeParams.Add(new TypeVariable(id, id.val));}
- .)
- .
-
-Types<.List<Bpl.Type>/*!*/ ts.>
-= (. Contract.Requires(ts != null); Bpl.Type/*!*/ ty; .)
- Type<out ty> (. ts.Add(ty); .)
- { "," Type<out ty> (. ts.Add(ty); .)
- }
- .
-
-
-/*------------------------------------------------------------------------*/
-Consts<.out List<Variable>/*!*/ ds.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null); IToken/*!*/ y; List<TypedIdent>/*!*/ xs;
- ds = new List<Variable>();
- bool u = false; QKeyValue kv = null;
- bool ChildrenComplete = false;
- List<ConstantParent/*!*/> Parents = null; .)
- "const" (. y = t; .)
- { Attribute<ref kv> }
- [ "unique" (. u = true; .)
- ]
- IdsType<out xs>
- [ OrderSpec<out ChildrenComplete, out Parents> ]
- (. bool makeClone = false;
- foreach(TypedIdent/*!*/ x in xs){
- Contract.Assert(x != null);
-
- // ensure that no sharing is introduced
- List<ConstantParent/*!*/> ParentsClone;
- if (makeClone && Parents != null) {
- ParentsClone = new List<ConstantParent/*!*/> ();
- foreach (ConstantParent/*!*/ p in Parents){
- Contract.Assert(p != null);
- ParentsClone.Add(new ConstantParent (
- new IdentifierExpr (p.Parent.tok, p.Parent.Name),
- p.Unique));}
- } else {
- ParentsClone = Parents;
- }
- makeClone = true;
-
- ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
- }
- .)
- ";"
- .
-
-OrderSpec<.out bool ChildrenComplete, out List<ConstantParent/*!*/> Parents.>
-= (.Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out Parents),true)); ChildrenComplete = false;
- Parents = null;
- bool u;
- IToken/*!*/ parent; .)
- "extends" (. Parents = new List<ConstantParent/*!*/> ();
- u = false; .)
- [
- [ "unique" (. u = true; .)
- ]
- Ident<out parent> (. Parents.Add(new ConstantParent (
- new IdentifierExpr(parent, parent.val), u)); .)
- {
- "," (. u = false; .)
- [ "unique" (. u = true; .)
- ]
- Ident<out parent> (. Parents.Add(new ConstantParent (
- new IdentifierExpr(parent, parent.val), u)); .)
- }
- ]
- [ "complete" (. ChildrenComplete = true; .)
- ]
- .
-
-/*------------------------------------------------------------------------*/
-Function<.out List<Declaration>/*!*/ ds.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- ds = new List<Declaration>(); IToken/*!*/ z;
- IToken/*!*/ typeParamTok;
- var typeParams = new List<TypeVariable>();
- var arguments = new List<Variable>();
- TypedIdent/*!*/ tyd;
- TypedIdent retTyd = null;
- Bpl.Type/*!*/ retTy;
- QKeyValue argKv = null;
- QKeyValue kv = null;
- Expr definition = null;
- Expr/*!*/ tmp;
- .)
- "function" { Attribute<ref kv> } Ident<out z>
- [ TypeParams<out typeParamTok, out typeParams> ]
- "("
- [ VarOrType<out tyd, out argKv> (. arguments.Add(new Formal(tyd.tok, tyd, true, argKv)); .)
- { "," VarOrType<out tyd, out argKv> (. arguments.Add(new Formal(tyd.tok, tyd, true, argKv)); .)
- } ] ")"
- (. argKv = null; .)
- (
- "returns" "(" VarOrType<out retTyd, out argKv> ")"
- |
- ":" Type<out retTy> (. retTyd = new TypedIdent(retTy.tok, TypedIdent.NoName, retTy); .)
- )
- ( "{" Expression<out tmp> (. definition = tmp; .) "}" | ";" )
- (.
- if (retTyd == null) {
- // construct a dummy type for the case of syntax error
- retTyd = new TypedIdent(t, TypedIdent.NoName, new BasicType(t, SimpleType.Int));
- }
- Function/*!*/ func = new Function(z, z.val, typeParams, arguments,
- new Formal(retTyd.tok, retTyd, false, argKv), null, kv);
- Contract.Assert(func != null);
- ds.Add(func);
- bool allUnnamed = true;
- foreach(Formal/*!*/ f in arguments){
- Contract.Assert(f != null);
- if (f.TypedIdent.HasName) {
- allUnnamed = false;
- break;
- }
- }
- if (!allUnnamed) {
- Bpl.Type prevType = null;
- for (int i = arguments.Count; 0 <= --i; ) {
- TypedIdent/*!*/ curr = cce.NonNull(arguments[i]).TypedIdent;
- if (curr.HasName) {
- // the argument was given as both an identifier and a type
- prevType = curr.Type;
- } else {
- // the argument was given as just one "thing", which syntactically parsed as a type
- if (prevType == null) {
- this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
- break;
- }
- Bpl.Type ty = curr.Type;
- var uti = ty as UnresolvedTypeIdentifier;
- if (uti != null && uti.Arguments.Count == 0) {
- // the given "thing" was just an identifier, so let's use it as the name of the parameter
- curr.Name = uti.Name;
- curr.Type = prevType;
- } else {
- this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
- }
- }
- }
- }
- if (definition != null) {
- // generate either an axiom or a function body
- if (QKeyValue.FindBoolAttribute(kv, "inline")) {
- func.Body = definition;
- } else {
- ds.Add(func.CreateDefinitionAxiom(definition, kv));
- }
- }
- .)
- .
-
-VarOrType<out TypedIdent/*!*/ tyd, out QKeyValue kv>
-= (.
- Contract.Ensures(Contract.ValueAtReturn(out tyd) != null);
- string/*!*/ varName = TypedIdent.NoName;
- Bpl.Type/*!*/ ty;
- IToken/*!*/ tok;
- kv = null;
- .)
- { Attribute<ref kv> }
- Type<out ty> (. tok = ty.tok; .)
- [ ":" (. var uti = ty as UnresolvedTypeIdentifier;
- if (uti != null && uti.Arguments.Count == 0) {
- varName = uti.Name;
- } else {
- this.SemErr("expected identifier before ':'");
- }
- .)
- Type<out ty>
- ]
- (. tyd = new TypedIdent(tok, varName, ty); .)
- .
-
-/*------------------------------------------------------------------------*/
-Axiom<out Axiom/*!*/ m>
-= (.Contract.Ensures(Contract.ValueAtReturn(out m) != null); Expr/*!*/ e; QKeyValue kv = null; .)
- "axiom"
- { Attribute<ref kv> }
- (. IToken/*!*/ x = t; .)
- Proposition<out e> ";" (. m = new Axiom(x,e, null, kv); .)
- .
-
-/*------------------------------------------------------------------------*/
-UserDefinedTypes<.out List<Declaration/*!*/>/*!*/ ts.>
-= (. Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out ts))); Declaration/*!*/ decl; QKeyValue kv = null; ts = new List<Declaration/*!*/> (); .)
- "type"
- { Attribute<ref kv> }
- UserDefinedType<out decl, kv> (. ts.Add(decl); .)
- { "," UserDefinedType<out decl, kv> (. ts.Add(decl); .) }
- ";"
- .
-
-UserDefinedType<out Declaration/*!*/ decl, QKeyValue kv>
-= (. Contract.Ensures(Contract.ValueAtReturn(out decl) != null); IToken/*!*/ id; List<IToken>/*!*/ paramTokens = new List<IToken> ();
- Bpl.Type/*!*/ body = dummyType; bool synonym = false; .)
- Ident<out id>
- [ WhiteSpaceIdents<out paramTokens> ]
- [
- "=" Type<out body>
- (. synonym = true; .)
- ]
- (.
- if (synonym) {
- List<TypeVariable>/*!*/ typeParams = new List<TypeVariable>();
- foreach(Token/*!*/ t in paramTokens){
- Contract.Assert(t != null);
- typeParams.Add(new TypeVariable(t, t.val));}
- decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
- } else {
- decl = new TypeCtorDecl(id, id.val, paramTokens.Count, kv);
- }
- .)
- .
-
-
-/*------------------------------------------------------------------------*/
-Procedure<out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl>
-= (. Contract.Ensures(Contract.ValueAtReturn(out proc) != null); IToken/*!*/ x;
- List<TypeVariable>/*!*/ typeParams;
- List<Variable>/*!*/ ins, outs;
- List<Requires>/*!*/ pre = new List<Requires>();
- List<IdentifierExpr>/*!*/ mods = new List<IdentifierExpr>();
- List<Ensures>/*!*/ post = new List<Ensures>();
-
- List<Variable>/*!*/ locals = new List<Variable>();
- StmtList/*!*/ stmtList;
- QKeyValue kv = null;
- impl = null;
- .)
-
- "procedure"
- ProcSignature<true, out x, out typeParams, out ins, out outs, out kv>
- ( ";"
- { Spec<pre, mods, post> }
- | { Spec<pre, mods, post> }
- ImplBody<out locals, out stmtList>
- (.
- impl = new Implementation(x, x.val, typeParams,
- Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors);
- .)
- )
- (. proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv); .)
- .
-
-
-Implementation<out Implementation/*!*/ impl>
-= (. Contract.Ensures(Contract.ValueAtReturn(out impl) != null); IToken/*!*/ x;
- List<TypeVariable>/*!*/ typeParams;
- List<Variable>/*!*/ ins, outs;
- List<Variable>/*!*/ locals;
- StmtList/*!*/ stmtList;
- QKeyValue kv;
- .)
-
- "implementation"
- ProcSignature<false, out x, out typeParams, out ins, out outs, out kv>
- ImplBody<out locals, out stmtList>
- (. impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); .)
- .
-
-
-ProcSignature<.bool allowWhereClausesOnFormals, out IToken/*!*/ name, out List<TypeVariable>/*!*/ typeParams,
- out List<Variable>/*!*/ ins, out List<Variable>/*!*/ outs, out QKeyValue kv.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null);
- IToken/*!*/ typeParamTok; typeParams = new List<TypeVariable>();
- outs = new List<Variable>(); kv = null; .)
- { Attribute<ref kv> }
- Ident<out name>
- [ TypeParams<out typeParamTok, out typeParams> ]
- ProcFormals<true, allowWhereClausesOnFormals, out ins>
- [ "returns" ProcFormals<false, allowWhereClausesOnFormals, out outs> ]
- .
-
-
-Spec<.List<Requires>/*!*/ pre, List<IdentifierExpr>/*!*/ mods, List<Ensures>/*!*/ post.>
-= (.Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); List<IToken>/*!*/ ms; .)
- ( "modifies"
- [ Idents<out ms> (. foreach(IToken/*!*/ m in ms){
- Contract.Assert(m != null);
- mods.Add(new IdentifierExpr(m, m.val));
- }
- .)
- ] ";"
- | "free" SpecPrePost<true, pre, post>
- | SpecPrePost<false, pre, post>
- )
- .
-
-SpecPrePost<.bool free, List<Requires>/*!*/ pre, List<Ensures>/*!*/ post.>
-= (. Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null; .)
- ( "requires" (. tok = t; .)
- { Attribute<ref kv> }
- Proposition<out e> ";" (. pre.Add(new Requires(tok, free, e, null, kv)); .)
- | "ensures" (. tok = t; .)
- { Attribute<ref kv> }
- Proposition<out e> ";" (. post.Add(new Ensures(tok, free, e, null, kv)); .)
- )
- .
-
-/*------------------------------------------------------------------------*/
-
-ImplBody<.out List<Variable>/*!*/ locals, out StmtList/*!*/ stmtList.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List<Variable>(); .)
- "{"
- { LocalVars<locals> }
- StmtList<out stmtList>
- .
-
-/* the StmtList also reads the final curly brace */
-StmtList<out StmtList/*!*/ stmtList>
-= (. Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List<BigBlock/*!*/> bigblocks = new List<BigBlock/*!*/>();
- /* built-up state for the current BigBlock: */
- IToken startToken = null; string currentLabel = null;
- List<Cmd> cs = null; /* invariant: startToken != null ==> cs != null */
- /* temporary variables: */
- IToken label; Cmd c; BigBlock b;
- StructuredCmd ec = null; StructuredCmd/*!*/ ecn;
- TransferCmd tc = null; TransferCmd/*!*/ tcn;
- .)
-
- {
- ( LabelOrCmd<out c, out label>
- (. if (c != null) {
- // LabelOrCmd read a Cmd
- Contract.Assert(label == null);
- if (startToken == null) { startToken = c.tok; cs = new List<Cmd>(); }
- Contract.Assert(cs != null);
- cs.Add(c);
- } else {
- // LabelOrCmd read a label
- Contract.Assert(label != null);
- if (startToken != null) {
- Contract.Assert(cs != null);
- // dump the built-up state into a BigBlock
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- cs = null;
- }
- startToken = label;
- currentLabel = label.val;
- cs = new List<Cmd>();
- }
- .)
-
- | StructuredCmd<out ecn>
- (. ec = ecn;
- if (startToken == null) { startToken = ec.tok; cs = new List<Cmd>(); }
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, ec, null);
- bigblocks.Add(b);
- startToken = null; currentLabel = null; cs = null;
- .)
-
- | TransferCmd<out tcn>
- (. tc = tcn;
- if (startToken == null) { startToken = tc.tok; cs = new List<Cmd>(); }
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, null, tc);
- bigblocks.Add(b);
- startToken = null; currentLabel = null; cs = null;
- .)
-
- )
- }
- "}"
- (. IToken/*!*/ endCurly = t;
- if (startToken == null && bigblocks.Count == 0) {
- startToken = t; cs = new List<Cmd>();
- }
- if (startToken != null) {
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- }
-
- stmtList = new StmtList(bigblocks, endCurly);
- .)
- .
-
-TransferCmd<out TransferCmd/*!*/ tc>
-= (. Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
- Token y; List<IToken>/*!*/ xs;
- List<String> ss = new List<String>();
- .)
- ( "goto" (. y = t; .)
- Idents<out xs> (. foreach(IToken/*!*/ s in xs){
- Contract.Assert(s != null);
- ss.Add(s.val); }
- tc = new GotoCmd(y, ss);
- .)
- | "return" (. tc = new ReturnCmd(t); .)
- ) ";"
- .
-
-StructuredCmd<out StructuredCmd/*!*/ ec>
-= (. Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec));
- IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd;
- .)
- ( IfCmd<out ifcmd> (. ec = ifcmd; .)
- | WhileCmd<out wcmd> (. ec = wcmd; .)
- | BreakCmd<out bcmd> (. ec = bcmd; .)
- )
- .
-
-IfCmd<out IfCmd/*!*/ ifcmd>
-= (. Contract.Ensures(Contract.ValueAtReturn(out ifcmd) != null); IToken/*!*/ x;
- Expr guard;
- StmtList/*!*/ thn;
- IfCmd/*!*/ elseIf; IfCmd elseIfOption = null;
- StmtList/*!*/ els; StmtList elseOption = null;
- .)
- "if" (. x = t; .)
- Guard<out guard>
- "{" StmtList<out thn>
- [ "else"
- ( IfCmd<out elseIf> (. elseIfOption = elseIf; .)
- | "{"
- StmtList<out els> (. elseOption = els; .)
- )
- ]
- (. ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption); .)
- .
-
-WhileCmd<out WhileCmd/*!*/ wcmd>
-= (. Contract.Ensures(Contract.ValueAtReturn(out wcmd) != null); IToken/*!*/ x; Token z;
- Expr guard; Expr/*!*/ e; bool isFree;
- List<PredicateCmd/*!*/> invariants = new List<PredicateCmd/*!*/>();
- StmtList/*!*/ body;
- QKeyValue kv = null;
- .)
- "while" (. x = t; .)
- Guard<out guard> (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
- { (. isFree = false; z = la/*lookahead token*/; .)
- [ "free" (. isFree = true; .)
- ]
- "invariant"
- { Attribute<ref kv> }
- Expression<out e> (. if (isFree) {
- invariants.Add(new AssumeCmd(z, e, kv));
- } else {
- invariants.Add(new AssertCmd(z, e, kv));
- }
- kv = null;
- .)
- ";"
- }
- "{"
- StmtList<out body> (. wcmd = new WhileCmd(x, guard, invariants, body); .)
- .
-
-Guard<out Expr e>
-= (. Expr/*!*/ ee; e = null; .)
- "("
- ( "*" (. e = null; .)
- | Expression<out ee> (. e = ee; .)
- )
- ")"
- .
-
-BreakCmd<out BreakCmd/*!*/ bcmd>
-= (.Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y;
- string breakLabel = null;
- .)
- "break" (. x = t; .)
- [ Ident<out y> (. breakLabel = y.val; .)
- ] ";" (. bcmd = new BreakCmd(x, breakLabel); .)
- .
-
-/*------------------------------------------------------------------------*/
-
-LabelOrCmd<out Cmd c, out IToken label>
-/* ensures (c == null) != (label != null) */
-= (. IToken/*!*/ x; Expr/*!*/ e;
- List<IToken>/*!*/ xs;
- List<IdentifierExpr> ids;
- c = dummyCmd; label = null;
- Cmd/*!*/ cn;
- QKeyValue kv = null;
- .)
- ( LabelOrAssign<out c, out label>
- | "assert" (. x = t; .)
- { Attribute<ref kv> }
- Proposition<out e> (. c = new AssertCmd(x, e, kv); .)
- ";"
- | "assume" (. x = t; .)
- { Attribute<ref kv> }
- Proposition<out e> (. c = new AssumeCmd(x, e, kv); .)
- ";"
- | "havoc" (. x = t; .)
- Idents<out xs> ";" (. ids = new List<IdentifierExpr>();
- foreach(IToken/*!*/ y in xs){
- Contract.Assert(y != null);
- ids.Add(new IdentifierExpr(y, y.val));
- }
- c = new HavocCmd(x,ids);
- .)
- | CallCmd<out cn> ";" (. c = cn; .)
- | ParCallCmd<out cn> (. c = cn; .)
- | "yield" (. x = t; .)
- ";" (. c = new YieldCmd(x); .)
- )
- .
-
-/*------------------------------------------------------------------------*/
-
-LabelOrAssign<out Cmd c, out IToken label>
-/* ensures (c == null) != (label != null) */
-= (. IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0;
- c = dummyCmd; label = null;
- AssignLhs/*!*/ lhs;
- List<AssignLhs/*!*/>/*!*/ lhss;
- List<Expr/*!*/>/*!*/ rhss;
- List<Expr/*!*/>/*!*/ indexes;
- .)
- Ident<out id> (. x = t; .)
- ( ":" (. c = null; label = x; .)
-
- | (. lhss = new List<AssignLhs/*!*/>(); .)
- (. lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); .)
-
- { MapAssignIndex<out y, out indexes> (. lhs = new MapAssignLhs(y, lhs, indexes); .) }
- (. lhss.Add(lhs); .)
-
- { ","
- Ident<out id>
- (. lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); .)
- { MapAssignIndex<out y, out indexes> (. lhs = new MapAssignLhs(y, lhs, indexes); .) }
- (. lhss.Add(lhs); .)
- }
-
- ":=" (. x = t; /* use location of := */ .)
- Expression<out e0> (. rhss = new List<Expr/*!*/> ();
- rhss.Add(e0); .)
- { ","
- Expression<out e0> (. rhss.Add(e0); .)
- }
- ";" (. c = new AssignCmd(x, lhss, rhss); .)
- )
- .
-
-MapAssignIndex<.out IToken/*!*/ x, out List<Expr/*!*/>/*!*/ indexes.>
-= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List<Expr/*!*/> ();
- Expr/*!*/ e;
- .)
- "[" (. x = t; .)
- [
- Expression<out e> (. indexes.Add(e); .)
- { ","
- Expression<out e> (. indexes.Add(e); .)
- }
- ]
- "]"
- .
-
-/*------------------------------------------------------------------------*/
-CallCmd<out Cmd c>
-= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null);
- IToken x;
- bool isAsync = false;
- bool isFree = false;
- QKeyValue kv = null;
- c = null;
- .)
- [ "async" (. isAsync = true; .)
- ]
- [ "free" (. isFree = true; .)
- ]
- "call" (. x = t; .)
- { Attribute<ref kv> }
- CallParams<isAsync, isFree, kv, x, out c> (. .)
- .
-
-ParCallCmd<out Cmd d>
-= (. Contract.Ensures(Contract.ValueAtReturn(out d) != null);
- IToken x;
- QKeyValue kv = null;
- Cmd c = null;
- List<CallCmd> callCmds = new List<CallCmd>();
- .)
- "par" (. x = t; .)
- { Attribute<ref kv> }
- CallParams<false, false, kv, x, out c> (. callCmds.Add((CallCmd)c); .)
- { "|" CallParams<false, false, kv, x, out c> (. callCmds.Add((CallCmd)c); .)
- }
- ";" (. d = new ParCallCmd(x, callCmds, kv); .)
- .
-
-CallParams<bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c>
-= (.
- List<IdentifierExpr> ids = new List<IdentifierExpr>();
- List<Expr> es = new List<Expr>();
- Expr en;
- IToken first;
- IToken p;
- c = null;
- .)
- Ident<out first>
- ( "("
- [ Expression<out en> (. es.Add(en); .)
- { "," Expression<out en> (. es.Add(en); .)
- }
- ]
- ")" (. c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; .)
- |
- (. ids.Add(new IdentifierExpr(first, first.val)); .)
- [ "," Ident<out p> (. ids.Add(new IdentifierExpr(p, p.val)); .)
- { "," Ident<out p> (. ids.Add(new IdentifierExpr(p, p.val)); .)
- }
- ] ":="
- Ident<out first> "("
- [ Expression<out en> (. es.Add(en); .)
- { "," Expression<out en> (. es.Add(en); .)
- }
- ]
- ")" (. c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; .)
- )
- .
-
-/*------------------------------------------------------------------------*/
-Proposition<out Expr/*!*/ e>
-=(.Contract.Ensures(Contract.ValueAtReturn(out e) != null);.)
- Expression<out e>
- .
-
-/*------------------------------------------------------------------------*/
-Idents<.out List<IToken>/*!*/ xs.>
-= (.Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>(); .)
- Ident<out id> (. xs.Add(id); .)
- { "," Ident<out id> (. xs.Add(id); .)
- }
- .
-
-/*------------------------------------------------------------------------*/
-WhiteSpaceIdents<.out List<IToken>/*!*/ xs.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>(); .)
- Ident<out id> (. xs.Add(id); .)
- { Ident<out id> (. xs.Add(id); .)
- }
- .
-
-/*------------------------------------------------------------------------*/
-Expressions<.out List<Expr>/*!*/ es.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new List<Expr>(); .)
- Expression<out e> (. es.Add(e); .)
- { "," Expression<out e> (. es.Add(e); .)
- }
- .
-
-/*------------------------------------------------------------------------*/
-Expression<.out Expr/*!*/ e0.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
- ImpliesExpression<false, out e0>
- { EquivOp (. x = t; .)
- ImpliesExpression<false, out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1); .)
- }
- .
-
-EquivOp = "<==>" | '\u21d4'.
-
-/*------------------------------------------------------------------------*/
-ImpliesExpression<bool noExplies, out Expr/*!*/ e0>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
- LogicalExpression<out e0>
- [
- ImpliesOp (. x = t; .)
- /* recurse because implication is right-associative */
- ImpliesExpression<true, out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1); .)
- |
- ExpliesOp (. if (noExplies)
- this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
- x = t; .)
- LogicalExpression<out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
- /* loop because explies is left-associative */
- {
- ExpliesOp (. x = t; .)
- LogicalExpression<out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
- }
- ]
- .
-
-ImpliesOp = "==>" | '\u21d2'.
-ExpliesOp = "<==" | '\u21d0'.
-
-/*------------------------------------------------------------------------*/
-LogicalExpression<out Expr/*!*/ e0>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
- RelationalExpression<out e0>
- [ AndOp (. x = t; .)
- RelationalExpression<out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
- { AndOp (. x = t; .)
- RelationalExpression<out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
- }
- | OrOp (. x = t; .)
- RelationalExpression<out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
- { OrOp (. x = t; .)
- RelationalExpression<out e1>
- (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
- }
- ]
- .
-
-AndOp = "&&" | '\u2227'.
-OrOp = "||" | '\u2228'.
-
-/*------------------------------------------------------------------------*/
-RelationalExpression<out Expr/*!*/ e0>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
- BvTerm<out e0>
- [ RelOp<out x, out op>
- BvTerm<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
- ]
- .
-
-RelOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
-= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
- ( "==" (. x = t; op=BinaryOperator.Opcode.Eq; .)
- | "<" (. x = t; op=BinaryOperator.Opcode.Lt; .)
- | ">" (. x = t; op=BinaryOperator.Opcode.Gt; .)
- | "<=" (. x = t; op=BinaryOperator.Opcode.Le; .)
- | ">=" (. x = t; op=BinaryOperator.Opcode.Ge; .)
- | "!=" (. x = t; op=BinaryOperator.Opcode.Neq; .)
- | "<:" (. x = t; op=BinaryOperator.Opcode.Subtype; .)
- | '\u2260' (. x = t; op=BinaryOperator.Opcode.Neq; .)
- | '\u2264' (. x = t; op=BinaryOperator.Opcode.Le; .)
- | '\u2265' (. x = t; op=BinaryOperator.Opcode.Ge; .)
- )
- .
-
-/*------------------------------------------------------------------------*/
-BvTerm<out Expr/*!*/ e0>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
- Term<out e0>
- { "++" (. x = t; .)
- Term<out e1> (. e0 = new BvConcatExpr(x, e0, e1); .)
- }
- .
-
-
-/*------------------------------------------------------------------------*/
-Term<out Expr/*!*/ e0>
-= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
- Factor<out e0>
- { AddOp<out x, out op>
- Factor<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
- }
- .
-
-AddOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
-= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
- ( "+" (. x = t; op=BinaryOperator.Opcode.Add; .)
- | "-" (. x = t; op=BinaryOperator.Opcode.Sub; .)
- )
- .
-
-/*------------------------------------------------------------------------*/
-Factor<out Expr/*!*/ e0>
-= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
- Power<out e0>
- { MulOp<out x, out op>
- Power<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
- }
- .
-
-MulOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
-= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
- ( "*" (. x = t; op=BinaryOperator.Opcode.Mul; .)
- | "div" (. x = t; op=BinaryOperator.Opcode.Div; .)
- | "mod" (. x = t; op=BinaryOperator.Opcode.Mod; .)
- | "/" (. x = t; op=BinaryOperator.Opcode.RealDiv; .)
- )
- .
-
-/*------------------------------------------------------------------------*/
-Power<out Expr/*!*/ e0>
-= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
- UnaryExpression<out e0>
- [
- "**" (. x = t; .)
- /* recurse because exponentation is right-associative */
- Power<out e1> (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Pow, e0, e1); .)
- ]
- .
-
-/*------------------------------------------------------------------------*/
-UnaryExpression<out Expr/*!*/ e>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- e = dummyExpr;
- .)
- ( "-" (. x = t; .)
- UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e); .)
- | NegOp (. x = t; .)
- UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Not, e); .)
- | CoercionExpression<out e>
- )
- .
-
-NegOp = "!" | '\u00ac'.
-
-/*------------------------------------------------------------------------*/
-
-/* This production creates ambiguities, because types can start with "<"
- (polymorphic map types), but can also be followed by "<" (inequalities).
- Coco deals with these ambiguities in a reasonable way by preferring to read
- further types (type arguments) over relational symbols. E.g., "5 : C < 0"
- will cause a parse error because "<" is treated as the beginning of a
- map type. */
-
-CoercionExpression<out Expr/*!*/ e>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- Bpl.Type/*!*/ coercedTo;
- BigNum bn;
- .)
- ArrayExpression<out e>
- { ":" (. x = t; .)
- (
- Type<out coercedTo> (. e = Expr.CoerceType(x, e, coercedTo); .)
- |
- Nat<out bn> /* This means that we really look at a bitvector
- expression t[a:b] */
- (. if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
- this.SemErr("arguments of extract need to be integer literals");
- e = new BvBounds(x, bn, BigNum.ZERO);
- } else {
- e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
- }
- .)
- )
- }
- .
-
-/*------------------------------------------------------------------------*/
-ArrayExpression<out Expr/*!*/ e>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- Expr/*!*/ index0 = dummyExpr; Expr/*!*/ e1;
- bool store; bool bvExtract;
- List<Expr>/*!*/ allArgs = dummyExprSeq;
- .)
- AtomExpression<out e>
- { "[" (. x = t; allArgs = new List<Expr> ();
- allArgs.Add(e);
- store = false; bvExtract = false; .)
- [
- Expression<out index0>
- (. if (index0 is BvBounds)
- bvExtract = true;
- else
- allArgs.Add(index0);
- .)
- { "," Expression<out e1>
- (. if (bvExtract || e1 is BvBounds)
- this.SemErr("bitvectors only have one dimension");
- allArgs.Add(e1);
- .)
- }
- [ ":=" Expression<out e1>
- (. if (bvExtract || e1 is BvBounds)
- this.SemErr("assignment to bitvectors is not possible");
- allArgs.Add(e1); store = true;
- .)
- ]
- | ":=" Expression<out e1> (. allArgs.Add(e1); store = true; .)
- ]
- "]"
- (. if (store)
- e = new NAryExpr(x, new MapStore(x, allArgs.Count - 2), allArgs);
- else if (bvExtract)
- e = new BvExtractExpr(x, e,
- ((BvBounds)index0).Upper.ToIntSafe,
- ((BvBounds)index0).Lower.ToIntSafe);
- else
- e = new NAryExpr(x, new MapSelect(x, allArgs.Count - 1), allArgs);
- .)
- }
- .
-
-
-/*------------------------------------------------------------------------*/
-AtomExpression<out Expr/*!*/ e>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd;
- List<Expr>/*!*/ es; List<Variable>/*!*/ ds; Trigger trig;
- List<TypeVariable>/*!*/ typeParams;
- IdentifierExpr/*!*/ id;
- QKeyValue kv;
- e = dummyExpr;
- List<Variable>/*!*/ locals;
- List<Block/*!*/>/*!*/ blocks;
- .)
- ( "false" (. e = new LiteralExpr(t, false); .)
- | "true" (. e = new LiteralExpr(t, true); .)
- | Nat<out bn> (. e = new LiteralExpr(t, bn); .)
- | Dec<out bd> (. e = new LiteralExpr(t, bd); .)
- | BvLit<out bn, out n> (. e = new LiteralExpr(t, bn, n); .)
-
- | Ident<out x> (. id = new IdentifierExpr(x, x.val); e = id; .)
- [ "("
- ( Expressions<out es> (. e = new NAryExpr(x, new FunctionCall(id), es); .)
- | /* empty */ (. e = new NAryExpr(x, new FunctionCall(id), new List<Expr>()); .)
- )
- ")"
- ]
-
- | "old" (. x = t; .)
- "("
- Expression<out e>
- ")" (. e = new OldExpr(x, e); .)
-
- | "int" (. x = t; .)
- "("
- Expression<out e>
- ")" (. e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new List<Expr>{ e }); .)
-
- | "real" (. x = t; .)
- "("
- Expression<out e>
- ")" (. e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new List<Expr>{ e }); .)
-
- | "(" ( Expression<out e> (. if (e is BvBounds)
- this.SemErr("parentheses around bitvector bounds " +
- "are not allowed"); .)
- | Forall (. x = t; .)
- QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
- (. if (typeParams.Count + ds.Count > 0)
- e = new ForallExpr(x, typeParams, ds, kv, trig, e); .)
- | Exists (. x = t; .)
- QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
- (. if (typeParams.Count + ds.Count > 0)
- e = new ExistsExpr(x, typeParams, ds, kv, trig, e); .)
- | Lambda (. x = t; .)
- QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
- (. if (trig != null)
- SemErr("triggers not allowed in lambda expressions");
- if (typeParams.Count + ds.Count > 0)
- e = new LambdaExpr(x, typeParams, ds, kv, e); .)
- )
- ")"
- | IfThenElseExpression<out e>
- | CodeExpression<out locals, out blocks> (. e = new CodeExpr(locals, blocks); .)
- )
- .
-
-CodeExpression<.out List<Variable>/*!*/ locals, out List<Block/*!*/>/*!*/ blocks.>
-= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new List<Variable>(); Block/*!*/ b;
- blocks = new List<Block/*!*/>();
- .)
- "|{"
- { LocalVars<locals> }
- SpecBlock<out b> (. blocks.Add(b); .)
- { SpecBlock<out b> (. blocks.Add(b); .)
- }
- "}|"
- .
-
-SpecBlock<out Block/*!*/ b>
-= (. Contract.Ensures(Contract.ValueAtReturn(out b) != null); IToken/*!*/ x; IToken/*!*/ y;
- Cmd c; IToken label;
- List<Cmd> cs = new List<Cmd>();
- List<IToken>/*!*/ xs;
- List<String> ss = new List<String>();
- b = dummyBlock;
- Expr/*!*/ e;
- .)
- Ident<out x> ":"
- { LabelOrCmd<out c, out label>
- (. if (c != null) {
- Contract.Assert(label == null);
- cs.Add(c);
- } else {
- Contract.Assert(label != null);
- SemErr("SpecBlock's can only have one label");
- }
- .)
- }
- ( "goto" (. y = t; .)
- Idents<out xs> (. foreach(IToken/*!*/ s in xs){
- Contract.Assert(s != null);
- ss.Add(s.val); }
- b = new Block(x,x.val,cs,new GotoCmd(y,ss));
- .)
- | "return" Expression<out e>
- (. b = new Block(x,x.val,cs,new ReturnExprCmd(t,e)); .)
- )
- ";"
- .
-
-Attribute<ref QKeyValue kv>
-= (. Trigger trig = null; .)
- AttributeOrTrigger<ref kv, ref trig> (. if (trig != null) this.SemErr("only attributes, not triggers, allowed here"); .)
-.
-
-AttributeOrTrigger<ref QKeyValue kv, ref Trigger trig>
-= (. IToken/*!*/ tok; Expr/*!*/ e; List<Expr>/*!*/ es;
- string key;
- List<object/*!*/> parameters; object/*!*/ param;
- .)
- "{" (. tok = t; .)
- (
- ":" ident (. key = t.val; parameters = new List<object/*!*/>(); .)
- [ AttributeParameter<out param> (. parameters.Add(param); .)
- { "," AttributeParameter<out param> (. parameters.Add(param); .)
- }
- ]
- (. if (key == "nopats") {
- if (parameters.Count == 1 && parameters[0] is Expr) {
- e = (Expr)parameters[0];
- if(trig==null){
- trig = new Trigger(tok, false, new List<Expr> { e }, null);
- } else {
- trig.AddLast(new Trigger(tok, false, new List<Expr> { e }, null));
- }
- } else {
- this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
- }
- } else {
- if (kv==null) {
- kv = new QKeyValue(tok, key, parameters, null);
- } else {
- kv.AddLast(new QKeyValue(tok, key, parameters, null));
- }
- }
- .)
- |
- Expression<out e> (. es = new List<Expr> { e }; .)
- { "," Expression<out e> (. es.Add(e); .)
- } (. if (trig==null) {
- trig = new Trigger(tok, true, es, null);
- } else {
- trig.AddLast(new Trigger(tok, true, es, null));
- }
- .)
- )
- "}"
- .
-
-AttributeParameter<out object/*!*/ o>
-= (. Contract.Ensures(Contract.ValueAtReturn(out o) != null);
- o = "error";
- Expr/*!*/ e;
- .)
- ( string (. o = t.val.Substring(1, t.val.Length-2); .)
- | Expression<out e> (. o = e; .)
- )
- .
-
-IfThenElseExpression<out Expr/*!*/ e>
-= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
- IToken/*!*/ tok;
- Expr/*!*/ e0, e1, e2;
- e = dummyExpr; .)
- "if" (. tok = t; .) Expression<out e0> "then" Expression<out e1> "else" Expression<out e2>
- (. e = new NAryExpr(tok, new IfThenElse(tok), new List<Expr>{ e0, e1, e2 }); .)
- .
-
-
-QuantifierBody<.IToken/*!*/ q, out List<TypeVariable>/*!*/ typeParams, out List<Variable>/*!*/ ds,
- out QKeyValue kv, out Trigger trig, out Expr/*!*/ body.>
-= (. Contract.Requires(q != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ds) != null); Contract.Ensures(Contract.ValueAtReturn(out body) != null);
- trig = null; typeParams = new List<TypeVariable> ();
- IToken/*!*/ tok;
- kv = null;
- ds = new List<Variable> ();
- .)
- (
- TypeParams<out tok, out typeParams>
- [ BoundVars<q, out ds> ]
- |
- BoundVars<q, out ds>
- )
- QSep
- { AttributeOrTrigger<ref kv, ref trig> }
- Expression<out body>
- .
-
-Forall = "forall" | '\u2200'.
-Exists = "exists" | '\u2203'.
-Lambda = "lambda" | '\u03bb'.
-QSep = "::" | '\u2022'.
-
-/*------------------------------------------------------------------------*/
-Ident<out IToken/*!*/ x>
-=(.Contract.Ensures(Contract.ValueAtReturn(out x) != null);.)
- ident (. x = t;
- if (x.val.StartsWith("\\"))
- x.val = x.val.Substring(1);
- .)
- .
-
-/*------------------------------------------------------------------------*/
-Nat<out BigNum n>
-=
- digits
- (. try {
- n = BigNum.FromString(t.val);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted number");
- n = BigNum.ZERO;
- }
- .)
- .
-
-/*------------------------------------------------------------------------*/
-Dec<out BigDec n>
-= (. string s = ""; .)
- (
- decimal (. s = t.val; .)
- |
- float (. s = t.val; .)
- )
- (. try {
- n = BigDec.FromString(s);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted number");
- n = BigDec.ZERO;
- }
- .)
- .
-
-/*------------------------------------------------------------------------*/
-BvLit<out BigNum n, out int m>
-=
- bvlit
- (.
- int pos = t.val.IndexOf("bv");
- string a = t.val.Substring(0, pos);
- string b = t.val.Substring(pos + 2);
- try {
- n = BigNum.FromString(a);
- m = Convert.ToInt32(b);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted bitvector");
- n = BigNum.ZERO;
- m = 0;
- }
- .)
- .
-END BoogiePL.
+
+/*---------------------------------------------------------------------------
+// BoogiePL -
+//--------------------------------------------------------------------------*/
+
+/*using System;*/
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using Bpl = Microsoft.Boogie;
+
+
+COMPILER BoogiePL
+
+/*--------------------------------------------------------------------------*/
+
+readonly Program/*!*/ Pgm;
+
+readonly Expr/*!*/ dummyExpr;
+readonly Cmd/*!*/ dummyCmd;
+readonly Block/*!*/ dummyBlock;
+readonly Bpl.Type/*!*/ dummyType;
+readonly List<Expr>/*!*/ dummyExprSeq;
+readonly TransferCmd/*!*/ dummyTransferCmd;
+readonly StructuredCmd/*!*/ dummyStructuredCmd;
+
+///<summary>
+///Returns the number of parsing errors encountered. If 0, "program" returns as
+///the parsed program.
+///</summary>
+public static int Parse (string/*!*/ filename, /*maybe null*/ List<string/*!*/> defines, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
+ Contract.Requires(filename != null);
+ Contract.Requires(cce.NonNullElements(defines,true));
+
+ if (defines == null) {
+ defines = new List<string/*!*/>();
+ }
+
+ if (filename == "stdin.bpl") {
+ var s = ParserHelper.Fill(Console.In, defines);
+ return Parse(s, filename, out program, useBaseName);
+ } else {
+ FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+ var s = ParserHelper.Fill(stream, defines);
+ var ret = Parse(s, filename, out program, useBaseName);
+ stream.Close();
+ return ret;
+ }
+}
+
+
+public static int Parse (string s, string/*!*/ filename, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
+ Contract.Requires(s != null);
+ Contract.Requires(filename != null);
+
+ byte[]/*!*/ buffer = cce.NonNull(UTF8Encoding.Default.GetBytes(s));
+ MemoryStream ms = new MemoryStream(buffer,false);
+ Errors errors = new Errors();
+ Scanner scanner = new Scanner(ms, errors, filename, useBaseName);
+
+ Parser parser = new Parser(scanner, errors, false);
+ parser.Parse();
+ if (parser.errors.count == 0)
+ {
+ program = parser.Pgm;
+ program.ProcessDatatypeConstructors();
+ return 0;
+ }
+ else
+ {
+ program = null;
+ return parser.errors.count;
+ }
+}
+
+public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, bool disambiguation)
+ : this(scanner, errors)
+{
+ // initialize readonly fields
+ Pgm = new Program();
+ dummyExpr = new LiteralExpr(Token.NoToken, false);
+ dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
+ dummyBlock = new Block(Token.NoToken, "dummyBlock", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
+ dummyExprSeq = new List<Expr> ();
+ dummyTransferCmd = new ReturnCmd(Token.NoToken);
+ dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
+}
+
+// Class to represent the bounds of a bitvector expression t[a:b].
+// Objects of this class only exist during parsing and are directly
+// turned into BvExtract before they get anywhere else
+private class BvBounds : Expr {
+ public BigNum Lower;
+ public BigNum Upper;
+ public BvBounds(IToken/*!*/ tok, BigNum lower, BigNum upper)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ this.Lower = lower;
+ this.Upper = upper;
+ }
+ public override Bpl.Type/*!*/ ShallowType { get {Contract.Ensures(Contract.Result<Bpl.Type>() != null); return Bpl.Type.Int; } }
+ public override void Resolve(ResolutionContext/*!*/ rc) {
+ // Contract.Requires(rc != null);
+ rc.Error(this, "bitvector bounds in illegal position");
+ }
+ public override void Emit(TokenTextWriter/*!*/ stream,
+ int contextBindingStrength, bool fragileContext) {
+ Contract.Assert(false);throw new cce.UnreachableException();
+ }
+ public override void ComputeFreeVariables(GSet<object>/*!*/ freeVars) { Contract.Assert(false);throw new cce.UnreachableException(); }
+}
+
+/*--------------------------------------------------------------------------*/
+CHARACTERS
+ letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
+ digit = "0123456789".
+ special = "'~#$^_.?`".
+ glyph = "`~!@#$%^&*()-_=+[{]}|;:',<.>/?\\".
+
+ cr = '\r'.
+ lf = '\n'.
+ tab = '\t'.
+
+ space = ' '.
+ quote = '"'.
+
+ newLine = cr + lf.
+ regularStringChar = ANY - quote - newLine.
+
+ nondigit = letter + special.
+ nonquote = letter + digit + space + glyph.
+
+
+/*------------------------------------------------------------------------*/
+TOKENS
+ ident = [ '\\' ] nondigit {nondigit | digit}.
+ bvlit = digit {digit} 'b' 'v' digit {digit}.
+ digits = digit {digit}.
+
+ string = quote { regularStringChar | "\\\"" } quote.
+
+ decimal = digit {digit} 'e' [ '-' ] digit {digit} .
+ float = digit {digit} '.' digit {digit} [ 'e' [ '-' ] digit {digit} ] .
+
+COMMENTS FROM "/*" TO "*/" NESTED
+COMMENTS FROM "//" TO lf
+
+IGNORE cr + lf + tab
+
+
+/*------------------------------------------------------------------------*/
+PRODUCTIONS
+
+
+/*------------------------------------------------------------------------*/
+BoogiePL
+= (. List<Variable>/*!*/ vs;
+ List<Declaration>/*!*/ ds;
+ Axiom/*!*/ ax;
+ List<Declaration/*!*/>/*!*/ ts;
+ Procedure/*!*/ pr;
+ Implementation im;
+ Implementation/*!*/ nnim;
+ .)
+ { Consts<out vs> (. foreach(Bpl.Variable/*!*/ v in vs){
+ Contract.Assert(v != null);
+ Pgm.AddTopLevelDeclaration(v);
+ }
+ .)
+ | Function<out ds> (. foreach(Bpl.Declaration/*!*/ d in ds){
+ Contract.Assert(d != null);
+ Pgm.AddTopLevelDeclaration(d);
+ }
+ .)
+ | Axiom<out ax> (. Pgm.AddTopLevelDeclaration(ax); .)
+ | UserDefinedTypes<out ts> (. foreach(Declaration/*!*/ td in ts){
+ Contract.Assert(td != null);
+ Pgm.AddTopLevelDeclaration(td);
+ }
+ .)
+ | GlobalVars<out vs> (. foreach(Bpl.Variable/*!*/ v in vs){
+ Contract.Assert(v != null);
+ Pgm.AddTopLevelDeclaration(v);
+ }
+ .)
+ | Procedure<out pr, out im> (. Pgm.AddTopLevelDeclaration(pr);
+ if (im != null) {
+ Pgm.AddTopLevelDeclaration(im);
+ }
+ .)
+ | Implementation<out nnim> (. Pgm.AddTopLevelDeclaration(nnim); .)
+ }
+ EOF
+ .
+
+/*------------------------------------------------------------------------*/
+GlobalVars<.out List<Variable>/*!*/ ds.>
+= (.
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ QKeyValue kv = null;
+ ds = new List<Variable>();
+ var dsx = ds;
+ .)
+ "var"
+ { Attribute<ref kv> }
+ IdsTypeWheres<true, "global variables", delegate(TypedIdent tyd) { dsx.Add(new GlobalVariable(tyd.tok, tyd, kv)); } > ";"
+ .
+
+LocalVars<.List<Variable>/*!*/ ds.>
+= (.
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ QKeyValue kv = null;
+ .)
+ "var"
+ { Attribute<ref kv> }
+ IdsTypeWheres<true, "local variables", delegate(TypedIdent tyd) { ds.Add(new LocalVariable(tyd.tok, tyd, kv)); } > ";"
+ .
+
+ProcFormals<.bool incoming, bool allowWhereClauses, out List<Variable>/*!*/ ds.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ ds = new List<Variable>();
+ var dsx = ds;
+ var context = allowWhereClauses ? "procedure formals" : "the 'implementation' copies of formals";
+ .)
+ "("
+ [ AttrsIdsTypeWheres<allowWhereClauses, allowWhereClauses, context, delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new Formal(tyd.tok, tyd, incoming, kv)); }>
+ ]
+ ")"
+ .
+
+BoundVars<.IToken/*!*/ x, out List<Variable>/*!*/ ds.>
+= (.
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ List<TypedIdent>/*!*/ tyds = new List<TypedIdent>();
+ ds = new List<Variable>();
+ var dsx = ds;
+ .)
+ AttrsIdsTypeWheres<true, false, "bound variables", delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new BoundVariable(tyd.tok, tyd, kv)); } >
+ .
+
+/*------------------------------------------------------------------------*/
+/* IdsType is used with const declarations */
+IdsType<.out List<TypedIdent>/*!*/ tyds.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out tyds) != null); List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty; .)
+ Idents<out ids> ":" Type<out ty>
+ (. tyds = new List<TypedIdent>();
+ foreach(Token/*!*/ id in ids){
+ Contract.Assert(id != null);
+ tyds.Add(new TypedIdent(id, id.val, ty, null));
+ }
+ .)
+ .
+
+/* AttrsIdsTypeWheres is used with the declarations of formals and bound variables */
+AttrsIdsTypeWheres<. bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action .>
+=
+ AttributesIdsTypeWhere<allowAttributes, allowWhereClauses, context, action>
+ { "," AttributesIdsTypeWhere<allowAttributes, allowWhereClauses, context, action> }
+ .
+
+IdsTypeWheres<. bool allowWhereClauses, string context, System.Action<TypedIdent> action .>
+=
+ IdsTypeWhere<allowWhereClauses, context, action>
+ { "," IdsTypeWhere<allowWhereClauses, context, action> }
+ .
+
+AttributesIdsTypeWhere<. bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action .>
+= (. QKeyValue kv = null; .)
+ { Attribute<ref kv> (. if (!allowAttributes) {
+ kv = null;
+ this.SemErr("attributes are not allowed on " + context);
+ }
+ .)
+ }
+ IdsTypeWhere<allowWhereClauses, context, delegate(TypedIdent tyd) { action(tyd, kv); }>
+ .
+
+/* context is allowed to be null if allowWhereClauses is true */
+IdsTypeWhere<. bool allowWhereClauses, string context, System.Action<TypedIdent> action .>
+= (. List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty; Expr wh = null; Expr/*!*/ nne; .)
+ Idents<out ids> ":" Type<out ty>
+ [ "where" Expression<out nne> (. if (!allowWhereClauses) {
+ this.SemErr("where clause not allowed on " + context);
+ } else {
+ wh = nne;
+ }
+ .)
+ ]
+ (. foreach(Token/*!*/ id in ids){
+ Contract.Assert(id != null);
+ action(new TypedIdent(id, id.val, ty, wh));
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+Type<out Bpl.Type/*!*/ ty>
+= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; ty = dummyType; .)
+ (
+ TypeAtom<out ty>
+ |
+ Ident<out tok> (. List<Bpl.Type>/*!*/ args = new List<Bpl.Type> (); .)
+ [ TypeArgs<args> ] (. ty = new UnresolvedTypeIdentifier (tok, tok.val, args); .)
+ |
+ MapType<out ty>
+ )
+ .
+
+TypeArgs<.List<Bpl.Type>/*!*/ ts.>
+= (.Contract.Requires(ts != null); IToken/*!*/ tok; Bpl.Type/*!*/ ty; .)
+ (
+ TypeAtom<out ty> (. ts.Add(ty); .)
+ [ TypeArgs<ts> ]
+ |
+ Ident<out tok> (. List<Bpl.Type>/*!*/ args = new List<Bpl.Type> ();
+ ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args)); .)
+ [ TypeArgs<ts> ]
+ |
+ MapType<out ty> (. ts.Add(ty); .)
+ )
+ .
+
+TypeAtom<out Bpl.Type/*!*/ ty>
+= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType; .)
+ ( "int" (. ty = new BasicType(t, SimpleType.Int); .)
+ | "real" (. ty = new BasicType(t, SimpleType.Real); .)
+ | "bool" (. ty = new BasicType(t, SimpleType.Bool); .)
+ /* note: bitvectors are handled in UnresolvedTypeIdentifier */
+ |
+ "("
+ Type<out ty>
+ ")"
+ )
+ .
+
+MapType<out Bpl.Type/*!*/ ty>
+= (.Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken tok = null;
+ IToken/*!*/ nnTok;
+ List<Bpl.Type>/*!*/ arguments = new List<Bpl.Type>();
+ Bpl.Type/*!*/ result;
+ List<TypeVariable>/*!*/ typeParameters = new List<TypeVariable>();
+ .)
+ [ TypeParams<out nnTok, out typeParameters> (. tok = nnTok; .) ]
+ "[" (. if (tok == null) tok = t; .)
+ [ Types<arguments> ]
+ "]"
+ Type<out result>
+ (.
+ ty = new MapType(tok, typeParameters, arguments, result);
+ .)
+ .
+
+TypeParams<.out IToken/*!*/ tok, out List<TypeVariable>/*!*/ typeParams.>
+= (.Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); List<IToken>/*!*/ typeParamToks; .)
+ "<" (. tok = t; .)
+ Idents<out typeParamToks>
+ ">"
+ (.
+ typeParams = new List<TypeVariable> ();
+ foreach(Token/*!*/ id in typeParamToks){
+ Contract.Assert(id != null);
+ typeParams.Add(new TypeVariable(id, id.val));}
+ .)
+ .
+
+Types<.List<Bpl.Type>/*!*/ ts.>
+= (. Contract.Requires(ts != null); Bpl.Type/*!*/ ty; .)
+ Type<out ty> (. ts.Add(ty); .)
+ { "," Type<out ty> (. ts.Add(ty); .)
+ }
+ .
+
+
+/*------------------------------------------------------------------------*/
+Consts<.out List<Variable>/*!*/ ds.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null); IToken/*!*/ y; List<TypedIdent>/*!*/ xs;
+ ds = new List<Variable>();
+ bool u = false; QKeyValue kv = null;
+ bool ChildrenComplete = false;
+ List<ConstantParent/*!*/> Parents = null; .)
+ "const" (. y = t; .)
+ { Attribute<ref kv> }
+ [ "unique" (. u = true; .)
+ ]
+ IdsType<out xs>
+ [ OrderSpec<out ChildrenComplete, out Parents> ]
+ (. bool makeClone = false;
+ foreach(TypedIdent/*!*/ x in xs){
+ Contract.Assert(x != null);
+
+ // ensure that no sharing is introduced
+ List<ConstantParent/*!*/> ParentsClone;
+ if (makeClone && Parents != null) {
+ ParentsClone = new List<ConstantParent/*!*/> ();
+ foreach (ConstantParent/*!*/ p in Parents){
+ Contract.Assert(p != null);
+ ParentsClone.Add(new ConstantParent (
+ new IdentifierExpr (p.Parent.tok, p.Parent.Name),
+ p.Unique));}
+ } else {
+ ParentsClone = Parents;
+ }
+ makeClone = true;
+
+ ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
+ }
+ .)
+ ";"
+ .
+
+OrderSpec<.out bool ChildrenComplete, out List<ConstantParent/*!*/> Parents.>
+= (.Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out Parents),true)); ChildrenComplete = false;
+ Parents = null;
+ bool u;
+ IToken/*!*/ parent; .)
+ "extends" (. Parents = new List<ConstantParent/*!*/> ();
+ u = false; .)
+ [
+ [ "unique" (. u = true; .)
+ ]
+ Ident<out parent> (. Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u)); .)
+ {
+ "," (. u = false; .)
+ [ "unique" (. u = true; .)
+ ]
+ Ident<out parent> (. Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u)); .)
+ }
+ ]
+ [ "complete" (. ChildrenComplete = true; .)
+ ]
+ .
+
+/*------------------------------------------------------------------------*/
+Function<.out List<Declaration>/*!*/ ds.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ ds = new List<Declaration>(); IToken/*!*/ z;
+ IToken/*!*/ typeParamTok;
+ var typeParams = new List<TypeVariable>();
+ var arguments = new List<Variable>();
+ TypedIdent/*!*/ tyd;
+ TypedIdent retTyd = null;
+ Bpl.Type/*!*/ retTy;
+ QKeyValue argKv = null;
+ QKeyValue kv = null;
+ Expr definition = null;
+ Expr/*!*/ tmp;
+ .)
+ "function" { Attribute<ref kv> } Ident<out z>
+ [ TypeParams<out typeParamTok, out typeParams> ]
+ "("
+ [ VarOrType<out tyd, out argKv> (. arguments.Add(new Formal(tyd.tok, tyd, true, argKv)); .)
+ { "," VarOrType<out tyd, out argKv> (. arguments.Add(new Formal(tyd.tok, tyd, true, argKv)); .)
+ } ] ")"
+ (. argKv = null; .)
+ (
+ "returns" "(" VarOrType<out retTyd, out argKv> ")"
+ |
+ ":" Type<out retTy> (. retTyd = new TypedIdent(retTy.tok, TypedIdent.NoName, retTy); .)
+ )
+ ( "{" Expression<out tmp> (. definition = tmp; .) "}" | ";" )
+ (.
+ if (retTyd == null) {
+ // construct a dummy type for the case of syntax error
+ retTyd = new TypedIdent(t, TypedIdent.NoName, new BasicType(t, SimpleType.Int));
+ }
+ Function/*!*/ func = new Function(z, z.val, typeParams, arguments,
+ new Formal(retTyd.tok, retTyd, false, argKv), null, kv);
+ Contract.Assert(func != null);
+ ds.Add(func);
+ bool allUnnamed = true;
+ foreach(Formal/*!*/ f in arguments){
+ Contract.Assert(f != null);
+ if (f.TypedIdent.HasName) {
+ allUnnamed = false;
+ break;
+ }
+ }
+ if (!allUnnamed) {
+ Bpl.Type prevType = null;
+ for (int i = arguments.Count; 0 <= --i; ) {
+ TypedIdent/*!*/ curr = cce.NonNull(arguments[i]).TypedIdent;
+ if (curr.HasName) {
+ // the argument was given as both an identifier and a type
+ prevType = curr.Type;
+ } else {
+ // the argument was given as just one "thing", which syntactically parsed as a type
+ if (prevType == null) {
+ this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
+ break;
+ }
+ Bpl.Type ty = curr.Type;
+ var uti = ty as UnresolvedTypeIdentifier;
+ if (uti != null && uti.Arguments.Count == 0) {
+ // the given "thing" was just an identifier, so let's use it as the name of the parameter
+ curr.Name = uti.Name;
+ curr.Type = prevType;
+ } else {
+ this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
+ }
+ }
+ }
+ }
+ if (definition != null) {
+ // generate either an axiom or a function body
+ if (QKeyValue.FindBoolAttribute(kv, "inline")) {
+ func.Body = definition;
+ } else {
+ ds.Add(func.CreateDefinitionAxiom(definition, kv));
+ }
+ }
+ .)
+ .
+
+VarOrType<out TypedIdent/*!*/ tyd, out QKeyValue kv>
+= (.
+ Contract.Ensures(Contract.ValueAtReturn(out tyd) != null);
+ string/*!*/ varName = TypedIdent.NoName;
+ Bpl.Type/*!*/ ty;
+ IToken/*!*/ tok;
+ kv = null;
+ .)
+ { Attribute<ref kv> }
+ Type<out ty> (. tok = ty.tok; .)
+ [ ":" (. var uti = ty as UnresolvedTypeIdentifier;
+ if (uti != null && uti.Arguments.Count == 0) {
+ varName = uti.Name;
+ } else {
+ this.SemErr("expected identifier before ':'");
+ }
+ .)
+ Type<out ty>
+ ]
+ (. tyd = new TypedIdent(tok, varName, ty); .)
+ .
+
+/*------------------------------------------------------------------------*/
+Axiom<out Axiom/*!*/ m>
+= (.Contract.Ensures(Contract.ValueAtReturn(out m) != null); Expr/*!*/ e; QKeyValue kv = null; .)
+ "axiom"
+ { Attribute<ref kv> }
+ (. IToken/*!*/ x = t; .)
+ Proposition<out e> ";" (. m = new Axiom(x,e, null, kv); .)
+ .
+
+/*------------------------------------------------------------------------*/
+UserDefinedTypes<.out List<Declaration/*!*/>/*!*/ ts.>
+= (. Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out ts))); Declaration/*!*/ decl; QKeyValue kv = null; ts = new List<Declaration/*!*/> (); .)
+ "type"
+ { Attribute<ref kv> }
+ UserDefinedType<out decl, kv> (. ts.Add(decl); .)
+ { "," UserDefinedType<out decl, kv> (. ts.Add(decl); .) }
+ ";"
+ .
+
+UserDefinedType<out Declaration/*!*/ decl, QKeyValue kv>
+= (. Contract.Ensures(Contract.ValueAtReturn(out decl) != null); IToken/*!*/ id; List<IToken>/*!*/ paramTokens = new List<IToken> ();
+ Bpl.Type/*!*/ body = dummyType; bool synonym = false; .)
+ Ident<out id>
+ [ WhiteSpaceIdents<out paramTokens> ]
+ [
+ "=" Type<out body>
+ (. synonym = true; .)
+ ]
+ (.
+ if (synonym) {
+ List<TypeVariable>/*!*/ typeParams = new List<TypeVariable>();
+ foreach(Token/*!*/ t in paramTokens){
+ Contract.Assert(t != null);
+ typeParams.Add(new TypeVariable(t, t.val));}
+ decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
+ } else {
+ decl = new TypeCtorDecl(id, id.val, paramTokens.Count, kv);
+ }
+ .)
+ .
+
+
+/*------------------------------------------------------------------------*/
+Procedure<out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl>
+= (. Contract.Ensures(Contract.ValueAtReturn(out proc) != null); IToken/*!*/ x;
+ List<TypeVariable>/*!*/ typeParams;
+ List<Variable>/*!*/ ins, outs;
+ List<Requires>/*!*/ pre = new List<Requires>();
+ List<IdentifierExpr>/*!*/ mods = new List<IdentifierExpr>();
+ List<Ensures>/*!*/ post = new List<Ensures>();
+
+ List<Variable>/*!*/ locals = new List<Variable>();
+ StmtList/*!*/ stmtList;
+ QKeyValue kv = null;
+ impl = null;
+ .)
+
+ "procedure"
+ ProcSignature<true, out x, out typeParams, out ins, out outs, out kv>
+ ( ";"
+ { Spec<pre, mods, post> }
+ | { Spec<pre, mods, post> }
+ ImplBody<out locals, out stmtList>
+ (.
+ impl = new Implementation(x, x.val, typeParams,
+ Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors);
+ .)
+ )
+ (. proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv); .)
+ .
+
+
+Implementation<out Implementation/*!*/ impl>
+= (. Contract.Ensures(Contract.ValueAtReturn(out impl) != null); IToken/*!*/ x;
+ List<TypeVariable>/*!*/ typeParams;
+ List<Variable>/*!*/ ins, outs;
+ List<Variable>/*!*/ locals;
+ StmtList/*!*/ stmtList;
+ QKeyValue kv;
+ .)
+
+ "implementation"
+ ProcSignature<false, out x, out typeParams, out ins, out outs, out kv>
+ ImplBody<out locals, out stmtList>
+ (. impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); .)
+ .
+
+
+ProcSignature<.bool allowWhereClausesOnFormals, out IToken/*!*/ name, out List<TypeVariable>/*!*/ typeParams,
+ out List<Variable>/*!*/ ins, out List<Variable>/*!*/ outs, out QKeyValue kv.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null);
+ IToken/*!*/ typeParamTok; typeParams = new List<TypeVariable>();
+ outs = new List<Variable>(); kv = null; .)
+ { Attribute<ref kv> }
+ Ident<out name>
+ [ TypeParams<out typeParamTok, out typeParams> ]
+ ProcFormals<true, allowWhereClausesOnFormals, out ins>
+ [ "returns" ProcFormals<false, allowWhereClausesOnFormals, out outs> ]
+ .
+
+
+Spec<.List<Requires>/*!*/ pre, List<IdentifierExpr>/*!*/ mods, List<Ensures>/*!*/ post.>
+= (.Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); List<IToken>/*!*/ ms; .)
+ ( "modifies"
+ [ Idents<out ms> (. foreach(IToken/*!*/ m in ms){
+ Contract.Assert(m != null);
+ mods.Add(new IdentifierExpr(m, m.val));
+ }
+ .)
+ ] ";"
+ | "free" SpecPrePost<true, pre, post>
+ | SpecPrePost<false, pre, post>
+ )
+ .
+
+SpecPrePost<.bool free, List<Requires>/*!*/ pre, List<Ensures>/*!*/ post.>
+= (. Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null; .)
+ ( "requires" (. tok = t; .)
+ { Attribute<ref kv> }
+ Proposition<out e> ";" (. pre.Add(new Requires(tok, free, e, null, kv)); .)
+ | "ensures" (. tok = t; .)
+ { Attribute<ref kv> }
+ Proposition<out e> ";" (. post.Add(new Ensures(tok, free, e, null, kv)); .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+
+ImplBody<.out List<Variable>/*!*/ locals, out StmtList/*!*/ stmtList.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List<Variable>(); .)
+ "{"
+ { LocalVars<locals> }
+ StmtList<out stmtList>
+ .
+
+/* the StmtList also reads the final curly brace */
+StmtList<out StmtList/*!*/ stmtList>
+= (. Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List<BigBlock/*!*/> bigblocks = new List<BigBlock/*!*/>();
+ /* built-up state for the current BigBlock: */
+ IToken startToken = null; string currentLabel = null;
+ List<Cmd> cs = null; /* invariant: startToken != null ==> cs != null */
+ /* temporary variables: */
+ IToken label; Cmd c; BigBlock b;
+ StructuredCmd ec = null; StructuredCmd/*!*/ ecn;
+ TransferCmd tc = null; TransferCmd/*!*/ tcn;
+ .)
+
+ {
+ ( LabelOrCmd<out c, out label>
+ (. if (c != null) {
+ // LabelOrCmd read a Cmd
+ Contract.Assert(label == null);
+ if (startToken == null) { startToken = c.tok; cs = new List<Cmd>(); }
+ Contract.Assert(cs != null);
+ cs.Add(c);
+ } else {
+ // LabelOrCmd read a label
+ Contract.Assert(label != null);
+ if (startToken != null) {
+ Contract.Assert(cs != null);
+ // dump the built-up state into a BigBlock
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ cs = null;
+ }
+ startToken = label;
+ currentLabel = label.val;
+ cs = new List<Cmd>();
+ }
+ .)
+
+ | StructuredCmd<out ecn>
+ (. ec = ecn;
+ if (startToken == null) { startToken = ec.tok; cs = new List<Cmd>(); }
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, ec, null);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+ .)
+
+ | TransferCmd<out tcn>
+ (. tc = tcn;
+ if (startToken == null) { startToken = tc.tok; cs = new List<Cmd>(); }
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, null, tc);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+ .)
+
+ )
+ }
+ "}"
+ (. IToken/*!*/ endCurly = t;
+ if (startToken == null && bigblocks.Count == 0) {
+ startToken = t; cs = new List<Cmd>();
+ }
+ if (startToken != null) {
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ }
+
+ stmtList = new StmtList(bigblocks, endCurly);
+ .)
+ .
+
+TransferCmd<out TransferCmd/*!*/ tc>
+= (. Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
+ Token y; List<IToken>/*!*/ xs;
+ List<String> ss = new List<String>();
+ .)
+ ( "goto" (. y = t; .)
+ Idents<out xs> (. foreach(IToken/*!*/ s in xs){
+ Contract.Assert(s != null);
+ ss.Add(s.val); }
+ tc = new GotoCmd(y, ss);
+ .)
+ | "return" (. tc = new ReturnCmd(t); .)
+ ) ";"
+ .
+
+StructuredCmd<out StructuredCmd/*!*/ ec>
+= (. Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec));
+ IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd;
+ .)
+ ( IfCmd<out ifcmd> (. ec = ifcmd; .)
+ | WhileCmd<out wcmd> (. ec = wcmd; .)
+ | BreakCmd<out bcmd> (. ec = bcmd; .)
+ )
+ .
+
+IfCmd<out IfCmd/*!*/ ifcmd>
+= (. Contract.Ensures(Contract.ValueAtReturn(out ifcmd) != null); IToken/*!*/ x;
+ Expr guard;
+ StmtList/*!*/ thn;
+ IfCmd/*!*/ elseIf; IfCmd elseIfOption = null;
+ StmtList/*!*/ els; StmtList elseOption = null;
+ .)
+ "if" (. x = t; .)
+ Guard<out guard>
+ "{" StmtList<out thn>
+ [ "else"
+ ( IfCmd<out elseIf> (. elseIfOption = elseIf; .)
+ | "{"
+ StmtList<out els> (. elseOption = els; .)
+ )
+ ]
+ (. ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption); .)
+ .
+
+WhileCmd<out WhileCmd/*!*/ wcmd>
+= (. Contract.Ensures(Contract.ValueAtReturn(out wcmd) != null); IToken/*!*/ x; Token z;
+ Expr guard; Expr/*!*/ e; bool isFree;
+ List<PredicateCmd/*!*/> invariants = new List<PredicateCmd/*!*/>();
+ StmtList/*!*/ body;
+ QKeyValue kv = null;
+ .)
+ "while" (. x = t; .)
+ Guard<out guard> (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
+ { (. isFree = false; z = la/*lookahead token*/; .)
+ [ "free" (. isFree = true; .)
+ ]
+ "invariant"
+ { Attribute<ref kv> }
+ Expression<out e> (. if (isFree) {
+ invariants.Add(new AssumeCmd(z, e, kv));
+ } else {
+ invariants.Add(new AssertCmd(z, e, kv));
+ }
+ kv = null;
+ .)
+ ";"
+ }
+ "{"
+ StmtList<out body> (. wcmd = new WhileCmd(x, guard, invariants, body); .)
+ .
+
+Guard<out Expr e>
+= (. Expr/*!*/ ee; e = null; .)
+ "("
+ ( "*" (. e = null; .)
+ | Expression<out ee> (. e = ee; .)
+ )
+ ")"
+ .
+
+BreakCmd<out BreakCmd/*!*/ bcmd>
+= (.Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y;
+ string breakLabel = null;
+ .)
+ "break" (. x = t; .)
+ [ Ident<out y> (. breakLabel = y.val; .)
+ ] ";" (. bcmd = new BreakCmd(x, breakLabel); .)
+ .
+
+/*------------------------------------------------------------------------*/
+
+LabelOrCmd<out Cmd c, out IToken label>
+/* ensures (c == null) != (label != null) */
+= (. IToken/*!*/ x; Expr/*!*/ e;
+ List<IToken>/*!*/ xs;
+ List<IdentifierExpr> ids;
+ c = dummyCmd; label = null;
+ Cmd/*!*/ cn;
+ QKeyValue kv = null;
+ .)
+ ( LabelOrAssign<out c, out label>
+ | "assert" (. x = t; .)
+ { Attribute<ref kv> }
+ Proposition<out e> (. c = new AssertCmd(x, e, kv); .)
+ ";"
+ | "assume" (. x = t; .)
+ { Attribute<ref kv> }
+ Proposition<out e> (. c = new AssumeCmd(x, e, kv); .)
+ ";"
+ | "havoc" (. x = t; .)
+ Idents<out xs> ";" (. ids = new List<IdentifierExpr>();
+ foreach(IToken/*!*/ y in xs){
+ Contract.Assert(y != null);
+ ids.Add(new IdentifierExpr(y, y.val));
+ }
+ c = new HavocCmd(x,ids);
+ .)
+ | CallCmd<out cn> ";" (. c = cn; .)
+ | ParCallCmd<out cn> (. c = cn; .)
+ | "yield" (. x = t; .)
+ ";" (. c = new YieldCmd(x); .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+
+LabelOrAssign<out Cmd c, out IToken label>
+/* ensures (c == null) != (label != null) */
+= (. IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0;
+ c = dummyCmd; label = null;
+ AssignLhs/*!*/ lhs;
+ List<AssignLhs/*!*/>/*!*/ lhss;
+ List<Expr/*!*/>/*!*/ rhss;
+ List<Expr/*!*/>/*!*/ indexes;
+ .)
+ Ident<out id> (. x = t; .)
+ ( ":" (. c = null; label = x; .)
+
+ | (. lhss = new List<AssignLhs/*!*/>(); .)
+ (. lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); .)
+
+ { MapAssignIndex<out y, out indexes> (. lhs = new MapAssignLhs(y, lhs, indexes); .) }
+ (. lhss.Add(lhs); .)
+
+ { ","
+ Ident<out id>
+ (. lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); .)
+ { MapAssignIndex<out y, out indexes> (. lhs = new MapAssignLhs(y, lhs, indexes); .) }
+ (. lhss.Add(lhs); .)
+ }
+
+ ":=" (. x = t; /* use location of := */ .)
+ Expression<out e0> (. rhss = new List<Expr/*!*/> ();
+ rhss.Add(e0); .)
+ { ","
+ Expression<out e0> (. rhss.Add(e0); .)
+ }
+ ";" (. c = new AssignCmd(x, lhss, rhss); .)
+ )
+ .
+
+MapAssignIndex<.out IToken/*!*/ x, out List<Expr/*!*/>/*!*/ indexes.>
+= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List<Expr/*!*/> ();
+ Expr/*!*/ e;
+ .)
+ "[" (. x = t; .)
+ [
+ Expression<out e> (. indexes.Add(e); .)
+ { ","
+ Expression<out e> (. indexes.Add(e); .)
+ }
+ ]
+ "]"
+ .
+
+/*------------------------------------------------------------------------*/
+CallCmd<out Cmd c>
+= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null);
+ IToken x;
+ bool isAsync = false;
+ bool isFree = false;
+ QKeyValue kv = null;
+ c = null;
+ .)
+ [ "async" (. isAsync = true; .)
+ ]
+ [ "free" (. isFree = true; .)
+ ]
+ "call" (. x = t; .)
+ { Attribute<ref kv> }
+ CallParams<isAsync, isFree, kv, x, out c> (. .)
+ .
+
+ParCallCmd<out Cmd d>
+= (. Contract.Ensures(Contract.ValueAtReturn(out d) != null);
+ IToken x;
+ QKeyValue kv = null;
+ Cmd c = null;
+ List<CallCmd> callCmds = new List<CallCmd>();
+ .)
+ "par" (. x = t; .)
+ { Attribute<ref kv> }
+ CallParams<false, false, kv, x, out c> (. callCmds.Add((CallCmd)c); .)
+ { "|" CallParams<false, false, kv, x, out c> (. callCmds.Add((CallCmd)c); .)
+ }
+ ";" (. d = new ParCallCmd(x, callCmds, kv); .)
+ .
+
+CallParams<bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c>
+= (.
+ List<IdentifierExpr> ids = new List<IdentifierExpr>();
+ List<Expr> es = new List<Expr>();
+ Expr en;
+ IToken first;
+ IToken p;
+ c = null;
+ .)
+ Ident<out first>
+ ( "("
+ [ Expression<out en> (. es.Add(en); .)
+ { "," Expression<out en> (. es.Add(en); .)
+ }
+ ]
+ ")" (. c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; .)
+ |
+ (. ids.Add(new IdentifierExpr(first, first.val)); .)
+ [ "," Ident<out p> (. ids.Add(new IdentifierExpr(p, p.val)); .)
+ { "," Ident<out p> (. ids.Add(new IdentifierExpr(p, p.val)); .)
+ }
+ ] ":="
+ Ident<out first> "("
+ [ Expression<out en> (. es.Add(en); .)
+ { "," Expression<out en> (. es.Add(en); .)
+ }
+ ]
+ ")" (. c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Proposition<out Expr/*!*/ e>
+=(.Contract.Ensures(Contract.ValueAtReturn(out e) != null);.)
+ Expression<out e>
+ .
+
+/*------------------------------------------------------------------------*/
+Idents<.out List<IToken>/*!*/ xs.>
+= (.Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>(); .)
+ Ident<out id> (. xs.Add(id); .)
+ { "," Ident<out id> (. xs.Add(id); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+WhiteSpaceIdents<.out List<IToken>/*!*/ xs.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>(); .)
+ Ident<out id> (. xs.Add(id); .)
+ { Ident<out id> (. xs.Add(id); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+Expressions<.out List<Expr>/*!*/ es.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new List<Expr>(); .)
+ Expression<out e> (. es.Add(e); .)
+ { "," Expression<out e> (. es.Add(e); .)
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+Expression<.out Expr/*!*/ e0.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
+ ImpliesExpression<false, out e0>
+ { EquivOp (. x = t; .)
+ ImpliesExpression<false, out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1); .)
+ }
+ .
+
+EquivOp = "<==>" | '\u21d4'.
+
+/*------------------------------------------------------------------------*/
+ImpliesExpression<bool noExplies, out Expr/*!*/ e0>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
+ LogicalExpression<out e0>
+ [
+ ImpliesOp (. x = t; .)
+ /* recurse because implication is right-associative */
+ ImpliesExpression<true, out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1); .)
+ |
+ ExpliesOp (. if (noExplies)
+ this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
+ x = t; .)
+ LogicalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
+ /* loop because explies is left-associative */
+ {
+ ExpliesOp (. x = t; .)
+ LogicalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
+ }
+ ]
+ .
+
+ImpliesOp = "==>" | '\u21d2'.
+ExpliesOp = "<==" | '\u21d0'.
+
+/*------------------------------------------------------------------------*/
+LogicalExpression<out Expr/*!*/ e0>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
+ RelationalExpression<out e0>
+ [ AndOp (. x = t; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
+ { AndOp (. x = t; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
+ }
+ | OrOp (. x = t; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
+ { OrOp (. x = t; .)
+ RelationalExpression<out e1>
+ (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
+ }
+ ]
+ .
+
+AndOp = "&&" | '\u2227'.
+OrOp = "||" | '\u2228'.
+
+/*------------------------------------------------------------------------*/
+RelationalExpression<out Expr/*!*/ e0>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
+ BvTerm<out e0>
+ [ RelOp<out x, out op>
+ BvTerm<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ ]
+ .
+
+RelOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
+= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
+ ( "==" (. x = t; op=BinaryOperator.Opcode.Eq; .)
+ | "<" (. x = t; op=BinaryOperator.Opcode.Lt; .)
+ | ">" (. x = t; op=BinaryOperator.Opcode.Gt; .)
+ | "<=" (. x = t; op=BinaryOperator.Opcode.Le; .)
+ | ">=" (. x = t; op=BinaryOperator.Opcode.Ge; .)
+ | "!=" (. x = t; op=BinaryOperator.Opcode.Neq; .)
+ | "<:" (. x = t; op=BinaryOperator.Opcode.Subtype; .)
+ | '\u2260' (. x = t; op=BinaryOperator.Opcode.Neq; .)
+ | '\u2264' (. x = t; op=BinaryOperator.Opcode.Le; .)
+ | '\u2265' (. x = t; op=BinaryOperator.Opcode.Ge; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+BvTerm<out Expr/*!*/ e0>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
+ Term<out e0>
+ { "++" (. x = t; .)
+ Term<out e1> (. e0 = new BvConcatExpr(x, e0, e1); .)
+ }
+ .
+
+
+/*------------------------------------------------------------------------*/
+Term<out Expr/*!*/ e0>
+= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
+ Factor<out e0>
+ { AddOp<out x, out op>
+ Factor<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ }
+ .
+
+AddOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
+= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
+ ( "+" (. x = t; op=BinaryOperator.Opcode.Add; .)
+ | "-" (. x = t; op=BinaryOperator.Opcode.Sub; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Factor<out Expr/*!*/ e0>
+= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
+ Power<out e0>
+ { MulOp<out x, out op>
+ Power<out e1> (. e0 = Expr.Binary(x, op, e0, e1); .)
+ }
+ .
+
+MulOp<out IToken/*!*/ x, out BinaryOperator.Opcode op>
+= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
+ ( "*" (. x = t; op=BinaryOperator.Opcode.Mul; .)
+ | "div" (. x = t; op=BinaryOperator.Opcode.Div; .)
+ | "mod" (. x = t; op=BinaryOperator.Opcode.Mod; .)
+ | "/" (. x = t; op=BinaryOperator.Opcode.RealDiv; .)
+ )
+ .
+
+/*------------------------------------------------------------------------*/
+Power<out Expr/*!*/ e0>
+= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
+ UnaryExpression<out e0>
+ [
+ "**" (. x = t; .)
+ /* recurse because exponentation is right-associative */
+ Power<out e1> (. e0 = Expr.Binary(x, BinaryOperator.Opcode.Pow, e0, e1); .)
+ ]
+ .
+
+/*------------------------------------------------------------------------*/
+UnaryExpression<out Expr/*!*/ e>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ e = dummyExpr;
+ .)
+ ( "-" (. x = t; .)
+ UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e); .)
+ | NegOp (. x = t; .)
+ UnaryExpression<out e> (. e = Expr.Unary(x, UnaryOperator.Opcode.Not, e); .)
+ | CoercionExpression<out e>
+ )
+ .
+
+NegOp = "!" | '\u00ac'.
+
+/*------------------------------------------------------------------------*/
+
+/* This production creates ambiguities, because types can start with "<"
+ (polymorphic map types), but can also be followed by "<" (inequalities).
+ Coco deals with these ambiguities in a reasonable way by preferring to read
+ further types (type arguments) over relational symbols. E.g., "5 : C < 0"
+ will cause a parse error because "<" is treated as the beginning of a
+ map type. */
+
+CoercionExpression<out Expr/*!*/ e>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ Bpl.Type/*!*/ coercedTo;
+ BigNum bn;
+ .)
+ ArrayExpression<out e>
+ { ":" (. x = t; .)
+ (
+ Type<out coercedTo> (. e = Expr.CoerceType(x, e, coercedTo); .)
+ |
+ Nat<out bn> /* This means that we really look at a bitvector
+ expression t[a:b] */
+ (. if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
+ this.SemErr("arguments of extract need to be integer literals");
+ e = new BvBounds(x, bn, BigNum.ZERO);
+ } else {
+ e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
+ }
+ .)
+ )
+ }
+ .
+
+/*------------------------------------------------------------------------*/
+ArrayExpression<out Expr/*!*/ e>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ Expr/*!*/ index0 = dummyExpr; Expr/*!*/ e1;
+ bool store; bool bvExtract;
+ List<Expr>/*!*/ allArgs = dummyExprSeq;
+ .)
+ AtomExpression<out e>
+ { "[" (. x = t; allArgs = new List<Expr> ();
+ allArgs.Add(e);
+ store = false; bvExtract = false; .)
+ [
+ Expression<out index0>
+ (. if (index0 is BvBounds)
+ bvExtract = true;
+ else
+ allArgs.Add(index0);
+ .)
+ { "," Expression<out e1>
+ (. if (bvExtract || e1 is BvBounds)
+ this.SemErr("bitvectors only have one dimension");
+ allArgs.Add(e1);
+ .)
+ }
+ [ ":=" Expression<out e1>
+ (. if (bvExtract || e1 is BvBounds)
+ this.SemErr("assignment to bitvectors is not possible");
+ allArgs.Add(e1); store = true;
+ .)
+ ]
+ | ":=" Expression<out e1> (. allArgs.Add(e1); store = true; .)
+ ]
+ "]"
+ (. if (store)
+ e = new NAryExpr(x, new MapStore(x, allArgs.Count - 2), allArgs);
+ else if (bvExtract)
+ e = new BvExtractExpr(x, e,
+ ((BvBounds)index0).Upper.ToIntSafe,
+ ((BvBounds)index0).Lower.ToIntSafe);
+ else
+ e = new NAryExpr(x, new MapSelect(x, allArgs.Count - 1), allArgs);
+ .)
+ }
+ .
+
+
+/*------------------------------------------------------------------------*/
+AtomExpression<out Expr/*!*/ e>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd;
+ List<Expr>/*!*/ es; List<Variable>/*!*/ ds; Trigger trig;
+ List<TypeVariable>/*!*/ typeParams;
+ IdentifierExpr/*!*/ id;
+ QKeyValue kv;
+ e = dummyExpr;
+ List<Variable>/*!*/ locals;
+ List<Block/*!*/>/*!*/ blocks;
+ .)
+ ( "false" (. e = new LiteralExpr(t, false); .)
+ | "true" (. e = new LiteralExpr(t, true); .)
+ | Nat<out bn> (. e = new LiteralExpr(t, bn); .)
+ | Dec<out bd> (. e = new LiteralExpr(t, bd); .)
+ | BvLit<out bn, out n> (. e = new LiteralExpr(t, bn, n); .)
+
+ | Ident<out x> (. id = new IdentifierExpr(x, x.val); e = id; .)
+ [ "("
+ ( Expressions<out es> (. e = new NAryExpr(x, new FunctionCall(id), es); .)
+ | /* empty */ (. e = new NAryExpr(x, new FunctionCall(id), new List<Expr>()); .)
+ )
+ ")"
+ ]
+
+ | "old" (. x = t; .)
+ "("
+ Expression<out e>
+ ")" (. e = new OldExpr(x, e); .)
+
+ | "int" (. x = t; .)
+ "("
+ Expression<out e>
+ ")" (. e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new List<Expr>{ e }); .)
+
+ | "real" (. x = t; .)
+ "("
+ Expression<out e>
+ ")" (. e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new List<Expr>{ e }); .)
+
+ | "(" ( Expression<out e> (. if (e is BvBounds)
+ this.SemErr("parentheses around bitvector bounds " +
+ "are not allowed"); .)
+ | Forall (. x = t; .)
+ QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
+ (. if (typeParams.Count + ds.Count > 0)
+ e = new ForallExpr(x, typeParams, ds, kv, trig, e); .)
+ | Exists (. x = t; .)
+ QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
+ (. if (typeParams.Count + ds.Count > 0)
+ e = new ExistsExpr(x, typeParams, ds, kv, trig, e); .)
+ | Lambda (. x = t; .)
+ QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
+ (. if (trig != null)
+ SemErr("triggers not allowed in lambda expressions");
+ if (typeParams.Count + ds.Count > 0)
+ e = new LambdaExpr(x, typeParams, ds, kv, e); .)
+ )
+ ")"
+ | IfThenElseExpression<out e>
+ | CodeExpression<out locals, out blocks> (. e = new CodeExpr(locals, blocks); .)
+ )
+ .
+
+CodeExpression<.out List<Variable>/*!*/ locals, out List<Block/*!*/>/*!*/ blocks.>
+= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new List<Variable>(); Block/*!*/ b;
+ blocks = new List<Block/*!*/>();
+ .)
+ "|{"
+ { LocalVars<locals> }
+ SpecBlock<out b> (. blocks.Add(b); .)
+ { SpecBlock<out b> (. blocks.Add(b); .)
+ }
+ "}|"
+ .
+
+SpecBlock<out Block/*!*/ b>
+= (. Contract.Ensures(Contract.ValueAtReturn(out b) != null); IToken/*!*/ x; IToken/*!*/ y;
+ Cmd c; IToken label;
+ List<Cmd> cs = new List<Cmd>();
+ List<IToken>/*!*/ xs;
+ List<String> ss = new List<String>();
+ b = dummyBlock;
+ Expr/*!*/ e;
+ .)
+ Ident<out x> ":"
+ { LabelOrCmd<out c, out label>
+ (. if (c != null) {
+ Contract.Assert(label == null);
+ cs.Add(c);
+ } else {
+ Contract.Assert(label != null);
+ SemErr("SpecBlock's can only have one label");
+ }
+ .)
+ }
+ ( "goto" (. y = t; .)
+ Idents<out xs> (. foreach(IToken/*!*/ s in xs){
+ Contract.Assert(s != null);
+ ss.Add(s.val); }
+ b = new Block(x,x.val,cs,new GotoCmd(y,ss));
+ .)
+ | "return" Expression<out e>
+ (. b = new Block(x,x.val,cs,new ReturnExprCmd(t,e)); .)
+ )
+ ";"
+ .
+
+Attribute<ref QKeyValue kv>
+= (. Trigger trig = null; .)
+ AttributeOrTrigger<ref kv, ref trig> (. if (trig != null) this.SemErr("only attributes, not triggers, allowed here"); .)
+.
+
+AttributeOrTrigger<ref QKeyValue kv, ref Trigger trig>
+= (. IToken/*!*/ tok; Expr/*!*/ e; List<Expr>/*!*/ es;
+ string key;
+ List<object/*!*/> parameters; object/*!*/ param;
+ .)
+ "{" (. tok = t; .)
+ (
+ ":" ident (. key = t.val; parameters = new List<object/*!*/>(); .)
+ [ AttributeParameter<out param> (. parameters.Add(param); .)
+ { "," AttributeParameter<out param> (. parameters.Add(param); .)
+ }
+ ]
+ (. if (key == "nopats") {
+ if (parameters.Count == 1 && parameters[0] is Expr) {
+ e = (Expr)parameters[0];
+ if(trig==null){
+ trig = new Trigger(tok, false, new List<Expr> { e }, null);
+ } else {
+ trig.AddLast(new Trigger(tok, false, new List<Expr> { e }, null));
+ }
+ } else {
+ this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
+ }
+ } else {
+ if (kv==null) {
+ kv = new QKeyValue(tok, key, parameters, null);
+ } else {
+ kv.AddLast(new QKeyValue(tok, key, parameters, null));
+ }
+ }
+ .)
+ |
+ Expression<out e> (. es = new List<Expr> { e }; .)
+ { "," Expression<out e> (. es.Add(e); .)
+ } (. if (trig==null) {
+ trig = new Trigger(tok, true, es, null);
+ } else {
+ trig.AddLast(new Trigger(tok, true, es, null));
+ }
+ .)
+ )
+ "}"
+ .
+
+AttributeParameter<out object/*!*/ o>
+= (. Contract.Ensures(Contract.ValueAtReturn(out o) != null);
+ o = "error";
+ Expr/*!*/ e;
+ .)
+ ( string (. o = t.val.Substring(1, t.val.Length-2); .)
+ | Expression<out e> (. o = e; .)
+ )
+ .
+
+IfThenElseExpression<out Expr/*!*/ e>
+= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
+ IToken/*!*/ tok;
+ Expr/*!*/ e0, e1, e2;
+ e = dummyExpr; .)
+ "if" (. tok = t; .) Expression<out e0> "then" Expression<out e1> "else" Expression<out e2>
+ (. e = new NAryExpr(tok, new IfThenElse(tok), new List<Expr>{ e0, e1, e2 }); .)
+ .
+
+
+QuantifierBody<.IToken/*!*/ q, out List<TypeVariable>/*!*/ typeParams, out List<Variable>/*!*/ ds,
+ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body.>
+= (. Contract.Requires(q != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ds) != null); Contract.Ensures(Contract.ValueAtReturn(out body) != null);
+ trig = null; typeParams = new List<TypeVariable> ();
+ IToken/*!*/ tok;
+ kv = null;
+ ds = new List<Variable> ();
+ .)
+ (
+ TypeParams<out tok, out typeParams>
+ [ BoundVars<q, out ds> ]
+ |
+ BoundVars<q, out ds>
+ )
+ QSep
+ { AttributeOrTrigger<ref kv, ref trig> }
+ Expression<out body>
+ .
+
+Forall = "forall" | '\u2200'.
+Exists = "exists" | '\u2203'.
+Lambda = "lambda" | '\u03bb'.
+QSep = "::" | '\u2022'.
+
+/*------------------------------------------------------------------------*/
+Ident<out IToken/*!*/ x>
+=(.Contract.Ensures(Contract.ValueAtReturn(out x) != null);.)
+ ident (. x = t;
+ if (x.val.StartsWith("\\"))
+ x.val = x.val.Substring(1);
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+Nat<out BigNum n>
+=
+ digits
+ (. try {
+ n = BigNum.FromString(t.val);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted number");
+ n = BigNum.ZERO;
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+Dec<out BigDec n>
+= (. string s = ""; .)
+ (
+ decimal (. s = t.val; .)
+ |
+ float (. s = t.val; .)
+ )
+ (. try {
+ n = BigDec.FromString(s);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted number");
+ n = BigDec.ZERO;
+ }
+ .)
+ .
+
+/*------------------------------------------------------------------------*/
+BvLit<out BigNum n, out int m>
+=
+ bvlit
+ (.
+ int pos = t.val.IndexOf("bv");
+ string a = t.val.Substring(0, pos);
+ string b = t.val.Substring(pos + 2);
+ try {
+ n = BigNum.FromString(a);
+ m = Convert.ToInt32(b);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted bitvector");
+ n = BigNum.ZERO;
+ m = 0;
+ }
+ .)
+ .
+END BoogiePL.
diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs
index dbbb6fd0..e9aa3ceb 100644
--- a/Source/Core/CommandLineOptions.cs
+++ b/Source/Core/CommandLineOptions.cs
@@ -1,2143 +1,2185 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.IO;
-using System.Linq;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie {
- public class CommandLineOptionEngine
- {
- public readonly string ToolName;
- public readonly string DescriptiveToolName;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ToolName != null);
- Contract.Invariant(DescriptiveToolName != null);
- Contract.Invariant(this._environment != null);
- Contract.Invariant(cce.NonNullElements(this._files));
- Contract.Invariant(this._fileTimestamp != null);
- }
-
- private string/*!*/ _environment = "";
-
- public string Environment {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return this._environment;
- }
- set {
- Contract.Requires(value != null);
- this._environment = value;
- }
- }
-
- private readonly List<string/*!*/>/*!*/ _files = new List<string/*!*/>();
-
- public IList<string/*!*/>/*!*/ Files {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IList<string>>()));
- Contract.Ensures(Contract.Result<IList<string>>().IsReadOnly);
- return this._files.AsReadOnly();
- }
- }
-
- public bool HelpRequested = false;
- public bool AttrHelpRequested = false;
-
- public CommandLineOptionEngine(string toolName, string descriptiveName) {
- Contract.Requires(toolName != null);
- Contract.Requires(descriptiveName != null);
- ToolName = toolName;
- DescriptiveToolName = descriptiveName;
- }
-
- public virtual string/*!*/ VersionNumber {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return cce.NonNull(cce.NonNull(System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location)).FileVersion);
- }
- }
- public virtual string/*!*/ VersionSuffix {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return " version " + VersionNumber + ", Copyright (c) 2003-2014, Microsoft.";
- }
- }
- public virtual string/*!*/ Version {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return DescriptiveToolName + VersionSuffix;
- }
- }
-
- private string/*!*/ _fileTimestamp = cce.NonNull(DateTime.Now.ToString("o")).Replace(':', '.');
-
- public string FileTimestamp {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return this._fileTimestamp;
- }
- set {
- Contract.Requires(value != null);
- this._fileTimestamp = value;
- }
- }
-
- public void ExpandFilename(ref string pattern, string logPrefix, string fileTimestamp) {
- if (pattern != null) {
- pattern = pattern.Replace("@PREFIX@", logPrefix).Replace("@TIME@", fileTimestamp);
- string fn = Files.Count == 0 ? "" : Files[Files.Count - 1];
- fn = fn.Replace('/', '-').Replace('\\', '-');
- pattern = pattern.Replace("@FILE@", fn);
- }
- }
-
- /// <summary>
- /// Process the option and modify "ps" accordingly.
- /// Return true if the option is one that is recognized.
- /// </summary>
- protected virtual bool ParseOption(string name, CommandLineParseState ps) {
- Contract.Requires(name != null);
- Contract.Requires(ps != null);
-
- switch (name) {
- case "help":
- case "?":
- if (ps.ConfirmArgumentCount(0)) {
- HelpRequested = true;
- }
- return true;
- case "attrHelp":
- if (ps.ConfirmArgumentCount(0)) {
- AttrHelpRequested = true;
- }
- return true;
- default:
- break;
- }
- return false; // unrecognized option
- }
-
- protected class CommandLineParseState
- {
- public string s;
- public bool hasColonArgument;
- public readonly string[]/*!*/ args;
- public int i;
- public int nextIndex;
- public bool EncounteredErrors;
- public readonly string ToolName;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(args != null);
- Contract.Invariant(0 <= i && i <= args.Length);
- Contract.Invariant(0 <= nextIndex && nextIndex <= args.Length);
- }
-
-
- public CommandLineParseState(string[] args, string toolName) {
- Contract.Requires(args != null);
- Contract.Requires(Contract.ForAll(0, args.Length, i => args[i] != null));
- Contract.Requires(toolName != null);
- Contract.Ensures(this.args == args);
- this.ToolName = toolName;
- this.s = null; // set later by client
- this.hasColonArgument = false; // set later by client
- this.args = args;
- this.i = 0;
- this.nextIndex = 0; // set later by client
- this.EncounteredErrors = false;
- }
-
- public bool CheckBooleanFlag(string flagName, ref bool flag, bool valueWhenPresent) {
- Contract.Requires(flagName != null);
- //modifies nextIndex, encounteredErrors, Console.Error.*;
- bool flagPresent = false;
-
- if ((s == "/" + flagName || s == "-" + flagName) && ConfirmArgumentCount(0)) {
- flag = valueWhenPresent;
- flagPresent = true;
- }
- return flagPresent;
- }
-
- public bool CheckBooleanFlag(string flagName, ref bool flag) {
- Contract.Requires(flagName != null);
- //modifies nextIndex, encounteredErrors, Console.Error.*;
- return CheckBooleanFlag(flagName, ref flag, true);
- }
-
- /// <summary>
- /// If there is one argument and it is a non-negative integer, then set "arg" to that number and return "true".
- /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref int arg) {
- //modifies nextIndex, encounteredErrors, Console.Error.*;
- return GetNumericArgument(ref arg, a => 0 <= a);
- }
-
- /// <summary>
- /// If there is one argument and the filtering predicate holds, then set "arg" to that number and return "true".
- /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref int arg, Predicate<int> filter) {
- Contract.Requires(filter != null);
-
- if (this.ConfirmArgumentCount(1)) {
- try {
- Contract.Assume(args[i] != null);
- Contract.Assert(args[i] is string); // needed to prove args[i].IsPeerConsistent
- int d = Convert.ToInt32(this.args[this.i]);
- if (filter == null || filter(d)) {
- arg = d;
- return true;
- }
- } catch (System.FormatException) {
- } catch (System.OverflowException) {
- }
- } else {
- return false;
- }
- Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
- return false;
- }
-
- /// <summary>
- /// If there is one argument and it is a non-negative integer less than "limit",
- /// then set "arg" to that number and return "true".
- /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref int arg, int limit) {
- Contract.Requires(this.i < args.Length);
- Contract.Ensures(Math.Min(arg, 0) <= Contract.ValueAtReturn(out arg) && Contract.ValueAtReturn(out arg) < limit);
- //modifies nextIndex, encounteredErrors, Console.Error.*;
- int a = arg;
- if (!GetNumericArgument(ref a)) {
- return false;
- } else if (a < limit) {
- arg = a;
- return true;
- } else {
- Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
- return false;
- }
- }
-
- /// <summary>
- /// If there is one argument and it is a non-negative real, then set "arg" to that number and return "true".
- /// Otherwise, emit an error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref double arg) {
- Contract.Ensures(Contract.ValueAtReturn(out arg) >= 0);
- //modifies nextIndex, encounteredErrors, Console.Error.*;
- if (this.ConfirmArgumentCount(1)) {
- try {
- Contract.Assume(args[i] != null);
- Contract.Assert(args[i] is string); // needed to prove args[i].IsPeerConsistent
- double d = Convert.ToDouble(this.args[this.i]);
- if (0 <= d) {
- arg = d;
- return true;
- }
- } catch (System.FormatException) {
- } catch (System.OverflowException) {
- }
- } else {
- return false;
- }
- Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
- return false;
- }
-
- public bool ConfirmArgumentCount(int argCount) {
- Contract.Requires(0 <= argCount);
- //modifies nextIndex, encounteredErrors, Console.Error.*;
- Contract.Ensures(Contract.Result<bool>() == (!(hasColonArgument && argCount != 1) && !(args.Length < i + argCount)));
- if (hasColonArgument && argCount != 1) {
- Error("\"{0}\" cannot take a colon argument", s);
- nextIndex = args.Length;
- return false;
- } else if (args.Length < i + argCount) {
- Error("\"{0}\" expects {1} argument{2}", s, argCount.ToString(), (string)(argCount == 1 ? "" : "s"));
- nextIndex = args.Length;
- return false;
- } else {
- nextIndex = i + argCount;
- return true;
- }
- }
-
- public void Error(string message, params string[] args) {
- Contract.Requires(args != null);
- Contract.Requires(message != null);
- //modifies encounteredErrors, Console.Error.*;
- Console.Error.WriteLine("{0}: Error: {1}", ToolName, String.Format(message, args));
- EncounteredErrors = true;
- }
- }
-
- public virtual void Usage() {
- Console.WriteLine("{0}: usage: {0} [ option ... ] [ filename ... ]", ToolName);
- Console.WriteLine(@" where <option> is one of
-
- ---- General options -------------------------------------------------------
-
- /help this message
- /attrHelp print a message about declaration attributes supported by
- this implementation");
- }
-
- public virtual void AttributeUsage() {
- }
-
- /// <summary>
- /// This method is called after all parsing is done, if no parse errors were encountered.
- /// </summary>
- public virtual void ApplyDefaultOptions() {
- }
-
- /// <summary>
- /// Parses the command-line arguments "args" into the global flag variables. Returns true
- /// if there were no errors.
- /// </summary>
- /// <param name="args">Consumed ("captured" and possibly modified) by the method.</param>
- public bool Parse([Captured] string[]/*!*/ args) {
- Contract.Requires(cce.NonNullElements(args));
-
- // save the command line options for the log files
- Environment += "Command Line Options: " + args.Concat(" ");
- args = cce.NonNull((string[])args.Clone()); // the operations performed may mutate the array, so make a copy
- var ps = new CommandLineParseState(args, ToolName);
-
- while (ps.i < args.Length) {
- cce.LoopInvariant(ps.args == args);
- string arg = args[ps.i];
- Contract.Assert(arg != null);
- ps.s = arg.Trim();
-
- bool isOption = ps.s.StartsWith("-") || ps.s.StartsWith("/");
- int colonIndex = ps.s.IndexOf(':');
- if (0 <= colonIndex && isOption) {
- ps.hasColonArgument = true;
- args[ps.i] = ps.s.Substring(colonIndex + 1);
- ps.s = ps.s.Substring(0, colonIndex);
- } else {
- ps.i++;
- ps.hasColonArgument = false;
- }
- ps.nextIndex = ps.i;
-
- if (isOption) {
- if (!ParseOption(ps.s.Substring(1), ps)) {
- if (Path.DirectorySeparatorChar == '/' && ps.s.StartsWith("/"))
- this._files.Add(arg);
- else
- ps.Error("unknown switch: {0}", ps.s);
- }
- } else {
- this._files.Add(arg);
- }
-
- ps.i = ps.nextIndex;
- }
-
- if (HelpRequested) {
- Usage();
- } else if (AttrHelpRequested) {
- AttributeUsage();
- } else if (ps.EncounteredErrors) {
- Console.WriteLine("Use /help for available options");
- }
-
- if (ps.EncounteredErrors) {
- return false;
- } else {
- this.ApplyDefaultOptions();
- return true;
- }
- }
-
- }
-
- /// <summary>
- /// Boogie command-line options (other tools can subclass this class in order to support a
- /// superset of Boogie's options.
- /// </summary>
- public class CommandLineOptions : CommandLineOptionEngine {
-
- public CommandLineOptions()
- : base("Boogie", "Boogie program verifier") {
- }
-
- protected CommandLineOptions(string toolName, string descriptiveName)
- : base(toolName, descriptiveName) {
- Contract.Requires(toolName != null);
- Contract.Requires(descriptiveName != null);
- }
-
- private static CommandLineOptions clo;
- public static CommandLineOptions/*!*/ Clo
- {
- get { return clo; }
- }
-
- public static void Install(CommandLineOptions options) {
- Contract.Requires(options != null);
- clo = options;
- }
-
- public const long Megabyte = 1048576;
-
- // Flags and arguments
-
- public bool RunningBoogieFromCommandLine = false; // "false" means running Boogie from the plug-in
-
- [ContractInvariantMethod]
- void ObjectInvariant2() {
- Contract.Invariant(LogPrefix != null);
- Contract.Invariant(0 <= PrintUnstructured && PrintUnstructured < 3); // 0 = print only structured, 1 = both structured and unstructured, 2 = only unstructured
- }
-
- public int VerifySnapshots = -1;
- public bool VerifySeparately = false;
- public string PrintFile = null;
- public int PrintUnstructured = 0;
- public bool UseBaseNameForFileName = false;
- public int DoomStrategy = -1;
- public bool DoomRestartTP = false;
- public bool PrintDesugarings = false;
- public string SimplifyLogFilePath = null;
- public bool PrintInstrumented = false;
- public bool InstrumentWithAsserts = false;
- public enum InstrumentationPlaces {
- LoopHeaders,
- Everywhere
- }
- public InstrumentationPlaces InstrumentInfer = InstrumentationPlaces.LoopHeaders;
- public bool PrintWithUniqueASTIds = false;
- private string XmlSinkFilename = null;
- [Peer]
- public XmlSink XmlSink = null;
- public bool Wait = false;
- public bool Trace = false;
- public bool TraceTimes = false;
- public bool TraceProofObligations = false;
- public bool TraceCachingForTesting
- {
- get
- {
- return TraceCaching == 1 || TraceCaching == 3;
- }
- }
- public bool TraceCachingForBenchmarking
- {
- get
- {
- return TraceCaching == 2 || TraceCaching == 3;
- }
- }
- public bool TraceCachingForDebugging
- {
- get
- {
- return TraceCaching == 3;
- }
- }
- internal int TraceCaching = 0;
- public bool NoResolve = false;
- public bool NoTypecheck = false;
- public bool OverlookBoogieTypeErrors = false;
- public bool Verify = true;
- public bool TraceVerify = false;
- public int /*(0:3)*/ ErrorTrace = 1;
- public bool IntraproceduralInfer = true;
- public bool ContractInfer = false;
- public bool ExplainHoudini = false;
- public bool ReverseHoudiniWorklist = false;
- public bool ConcurrentHoudini = false;
- public bool ModifyTopologicalSorting = false;
- public bool DebugConcurrentHoudini = false;
- public bool HoudiniUseCrossDependencies = false;
- public string StagedHoudini = null;
- public bool DebugStagedHoudini = false;
- public bool StagedHoudiniReachabilityAnalysis = false;
- public bool StagedHoudiniMergeIgnoredAnnotations = false;
- public int StagedHoudiniThreads = 1;
- public string VariableDependenceIgnore = null;
- public string AbstractHoudini = null;
- public bool UseUnsatCoreForContractInfer = false;
- public bool PrintAssignment = false;
- public int InlineDepth = -1;
- public bool UseProverEvaluate = false; // Use ProverInterface's Evaluate method, instead of model to get variable values
- public bool UseUncheckedContracts = false;
- public bool SimplifyLogFileAppend = false;
- public bool SoundnessSmokeTest = false;
- public string Z3ExecutablePath = null;
- public string CVC4ExecutablePath = null;
- public int KInductionDepth = -1;
-
- private string/*!*/ _logPrefix = "";
-
- public string LogPrefix {
- get {
- Contract.Ensures(Contract.Result<string>() != null);
- return this._logPrefix;
- }
- set {
- Contract.Requires(value != null);
- this._logPrefix = value;
- }
- }
-
- public bool PrettyPrint = true;
-
- public enum ProverWarnings {
- None,
- Stdout,
- Stderr
- }
- public ProverWarnings PrintProverWarnings = ProverWarnings.None;
- public int ProverShutdownLimit = 0;
-
- public enum SubsumptionOption {
- Never,
- NotForQuantifiers,
- Always
- }
- public SubsumptionOption UseSubsumption = SubsumptionOption.Always;
-
- public bool AlwaysAssumeFreeLoopInvariants = false;
-
- public enum ShowEnvironment {
- Never,
- DuringPrint,
- Always
- }
- public ShowEnvironment ShowEnv = ShowEnvironment.DuringPrint;
- public bool DontShowLogo = false;
- [ContractInvariantMethod]
- void ObjectInvariant3() {
- Contract.Invariant(-1 <= LoopFrameConditions && LoopFrameConditions < 3);
- Contract.Invariant(0 <= ModifiesDefault && ModifiesDefault < 7);
- Contract.Invariant((0 <= PrintErrorModel && PrintErrorModel <= 2) || PrintErrorModel == 4);
- Contract.Invariant(0 <= EnhancedErrorMessages && EnhancedErrorMessages < 2);
- Contract.Invariant(0 <= StepsBeforeWidening && StepsBeforeWidening <= 9);
- Contract.Invariant(-1 <= this.bracketIdsInVC && this.bracketIdsInVC <= 1);
- Contract.Invariant(cce.NonNullElements(this.proverOptions));
- }
-
- public int LoopUnrollCount = -1; // -1 means don't unroll loops
- public bool SoundLoopUnrolling = false;
- public int LoopFrameConditions = -1; // -1 means not specified -- this will be replaced by the "implications" section below
- public int ModifiesDefault = 5;
- public bool LocalModifiesChecks = true;
- public bool NoVerifyByDefault = false;
- public enum OwnershipModelOption {
- Standard,
- Experimental,
- Trivial
- }
- public OwnershipModelOption OwnershipModelEncoding = OwnershipModelOption.Standard;
- public int PrintErrorModel = 0;
- public string PrintErrorModelFile = null;
- public string/*?*/ ModelViewFile = null;
- public int EnhancedErrorMessages = 0;
- public string PrintCFGPrefix = null;
- public bool ForceBplErrors = false; // if true, boogie error is shown even if "msg" attribute is present
- public bool UseArrayTheory = false;
- public bool UseSmtOutputFormat = false;
- public bool WeakArrayTheory = false;
- public bool UseLabels = true;
- public bool SIBoolControlVC = false;
- public bool MonomorphicArrays {
- get {
- return UseArrayTheory || TypeEncodingMethod == TypeEncoding.Monomorphic;
- }
- }
- public bool ExpandLambdas = true; // not useful from command line, only to be set to false programatically
- public bool DoModSetAnalysis = false;
- public bool UseAbstractInterpretation = true; // true iff the user want to use abstract interpretation
- private int /*0..9*/stepsBeforeWidening = 0; // The number of steps that must be done before applying a widen operator
-
- public int StepsBeforeWidening
- {
- get
- {
- Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() <= 9);
- return this.stepsBeforeWidening;
- }
- set
- {
- Contract.Requires(0 <= value && value <= 9);
- this.stepsBeforeWidening = value;
- }
- }
-
- public string OwickiGriesDesugaredOutputFile = null;
- public bool TrustAtomicityTypes = false;
- public bool TrustNonInterference = false;
- public int TrustLayersUpto = -1;
- public int TrustLayersDownto = int.MaxValue;
-
- public enum VCVariety {
- Structured,
- Block,
- Local,
- BlockNested,
- BlockReach,
- BlockNestedReach,
- Dag,
- DagIterative,
- Doomed,
- Unspecified
- }
- public VCVariety vcVariety = VCVariety.Unspecified; // will not be Unspecified after command line has been parsed
-
- public bool RemoveEmptyBlocks = true;
- public bool CoalesceBlocks = true;
- public bool PruneInfeasibleEdges = true;
-
- [Rep]
- public ProverFactory TheProverFactory;
- public string ProverName;
- [Peer]
- private List<string> proverOptions = new List<string>();
-
- public IEnumerable<string> ProverOptions
- {
- set
- {
- Contract.Requires(cce.NonNullElements(value));
-
- this.proverOptions = new List<string>(value);
- }
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string>>()));
-
- foreach (string s in this.proverOptions)
- yield return s;
- }
- }
-
- [Obsolete("use the setter for 'ProverOptions' directly")]
- public void AddProverOption(string option)
- {
- Contract.Requires(option != null);
-
- this.ProverOptions = this.ProverOptions.Concat1(option);
- }
-
- [Obsolete("use the setter for 'ProverOptions' directly")]
- public void RemoveAllProverOptions(Predicate<string> match)
- {
- this.ProverOptions = this.ProverOptions.Where(s => !match(s));
- }
-
- private int bracketIdsInVC = -1; // -1 - not specified, 0 - no, 1 - yes
-
- public int BracketIdsInVC {
- get {
- Contract.Ensures(-1 <= Contract.Result<int>() && Contract.Result<int>() <= 1);
- return this.bracketIdsInVC;
- }
- set {
- Contract.Requires(-1 <= value && value <= 1);
- this.bracketIdsInVC = value;
- }
- }
-
- public bool CausalImplies = false;
-
- public int SimplifyProverMatchDepth = -1; // -1 means not specified
- public int ProverKillTime = -1; // -1 means not specified
- public int SmokeTimeout = 10; // default to 10s
- public int ProverCCLimit = 5;
- public bool z3AtFlag = true;
- public bool RestartProverPerVC = false;
-
- public double VcsMaxCost = 1.0;
- public double VcsPathJoinMult = 0.8;
- public double VcsPathCostMult = 1.0;
- public double VcsAssumeMult = 0.01;
- public double VcsPathSplitMult = 0.5; // 0.5-always, 2-rarely do path splitting
- public int VcsMaxSplits = 1;
- public int VcsMaxKeepGoingSplits = 1;
- public int VcsFinalAssertTimeout = 30;
- public int VcsKeepGoingTimeout = 1;
- public int VcsCores = 1;
- public bool VcsDumpSplits = false;
-
- public bool DebugRefuted = false;
-
- public XmlSink XmlRefuted {
- get {
- if (DebugRefuted)
- return XmlSink;
- else
- return null;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant4() {
- Contract.Invariant(cce.NonNullElements(this.z3Options));
- Contract.Invariant(0 <= Z3lets && Z3lets < 4);
- }
-
- [Peer]
- private List<string> z3Options = new List<string>();
-
- public IEnumerable<string> Z3Options
- {
- get
- {
- Contract.Ensures(Contract.Result<IEnumerable<string>>() != null);
- foreach (string s in z3Options)
- yield return s;
- }
- }
-
- public void AddZ3Option(string option)
- {
- Contract.Requires(option != null);
- this.z3Options.Add(option);
- }
-
- public bool Z3types = false;
- public int Z3lets = 3; // 0 - none, 1 - only LET TERM, 2 - only LET FORMULA, 3 - (default) any
-
-
- // Maximum amount of virtual memory (in bytes) for the prover to use
- //
- // Non-positive number indicates unbounded.
- public long MaxProverMemory = 100 * Megabyte;
-
- // Minimum number of prover calls before restart
- public int MinNumOfProverCalls = 5;
-
- public enum PlatformType {
- notSpecified,
- v1,
- v11,
- v2,
- cli1
- }
- public PlatformType TargetPlatform;
- public string TargetPlatformLocation;
- public string StandardLibraryLocation;
-
- // whether procedure inlining is enabled at call sites.
- public enum Inlining {
- None,
- Assert,
- Assume,
- Spec
- };
- public Inlining ProcedureInlining = Inlining.Assume;
- public bool PrintInlined = false;
- public bool ExtractLoops = false;
- public bool DeterministicExtractLoops = false;
- public string SecureVcGen = null;
- public int StratifiedInlining = 0;
- public string FixedPointEngine = null;
- public int StratifiedInliningOption = 0;
- public bool StratifiedInliningWithoutModels = false; // disable model generation for SI
- public int StratifiedInliningVerbose = 0; // verbosity level
- public int RecursionBound = 500;
- public bool NonUniformUnfolding = false;
- public int StackDepthBound = 0;
- public string inferLeastForUnsat = null;
-
- // Inference mode for fixed point engine
- public enum FixedPointInferenceMode {
- Corral,
- OldCorral,
- Flat,
- Procedure,
- Call
- };
- public FixedPointInferenceMode FixedPointMode = FixedPointInferenceMode.Procedure;
-
- public string PrintFixedPoint = null;
-
- public string PrintConjectures = null;
-
- public bool ExtractLoopsUnrollIrreducible = true; // unroll irreducible loops? (set programmatically)
-
- public enum TypeEncoding {
- None,
- Predicates,
- Arguments,
- Monomorphic
- };
- public TypeEncoding TypeEncodingMethod = TypeEncoding.Predicates;
-
- public bool Monomorphize = false;
-
- public bool ReflectAdd = false;
-
- public int LiveVariableAnalysis = 1;
-
- // Static constructor
- static CommandLineOptions() {
- if (System.Type.GetType("Mono.Runtime") == null) { // MONO
- TraceListenerCollection/*!*/ dbl = Debug.Listeners;
- Contract.Assert(dbl != null);
- Contract.Assume(cce.IsPeerConsistent(dbl)); // hangs off static field
- dbl.Add(new DefaultTraceListener());
- }
- }
-
- public IEnumerable<string/*!*/> ProcsToCheck {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string/*!*/>>(), true));
- return this.procsToCheck != null ? this.procsToCheck.AsEnumerable() : null;
- }
- }
-
- private List<string/*!*/> procsToCheck = null; // null means "no restriction"
-
- [ContractInvariantMethod]
- void ObjectInvariant5() {
- Contract.Invariant(cce.NonNullElements(this.procsToCheck, true));
- Contract.Invariant(Ai != null);
- }
-
- public class AiFlags {
- public bool J_Trivial = false;
- public bool J_Intervals = false;
- public bool DebugStatistics = false;
- }
- public readonly AiFlags/*!*/ Ai = new AiFlags();
-
- public class ConcurrentHoudiniOptions
- {
- public List<string> ProverOptions = new List<string>();
- public int ProverCCLimit = 5;
- public bool DisableLoopInvEntryAssert = false;
- public bool DisableLoopInvMaintainedAssert = false;
- public bool ModifyTopologicalSorting = false;
- }
- public List<ConcurrentHoudiniOptions> Cho = new List<ConcurrentHoudiniOptions>();
-
- protected override bool ParseOption(string name, CommandLineOptionEngine.CommandLineParseState ps) {
- var args = ps.args; // convenient synonym
- switch (name) {
- case "infer":
- if (ps.ConfirmArgumentCount(1)) {
- foreach (char c in cce.NonNull(args[ps.i])) {
- switch (c) {
- case 't':
- Ai.J_Trivial = true;
- UseAbstractInterpretation = true;
- break;
- case 'j':
- Ai.J_Intervals = true;
- UseAbstractInterpretation = true;
- break;
- case 's':
- Ai.DebugStatistics = true;
- UseAbstractInterpretation = true;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- StepsBeforeWidening = (int)char.GetNumericValue(c);
- break;
- default:
- ps.Error("Invalid argument '{0}' to option {1}", c.ToString(), ps.s);
- break;
- }
- }
- }
- return true;
-
- case "noinfer":
- if (ps.ConfirmArgumentCount(0)) {
- UseAbstractInterpretation = false;
- }
- return true;
-
- case "break":
- case "launch":
- if (ps.ConfirmArgumentCount(0)) {
- System.Diagnostics.Debugger.Launch();
- }
- return true;
-
- case "proc":
- if (this.procsToCheck == null) {
- this.procsToCheck = new List<string/*!*/>();
- }
- if (ps.ConfirmArgumentCount(1)) {
- this.procsToCheck.Add(cce.NonNull(args[ps.i]));
- }
- return true;
-
- case "xml":
- if (ps.ConfirmArgumentCount(1)) {
- XmlSinkFilename = args[ps.i];
- }
- return true;
-
- case "print":
- if (ps.ConfirmArgumentCount(1)) {
- PrintFile = args[ps.i];
- }
- return true;
-
- case "pretty":
- int val = 1;
- if (ps.GetNumericArgument(ref val, 2)) {
- PrettyPrint = val == 1;
- }
- return true;
-
- case "OwickiGries":
- if (ps.ConfirmArgumentCount(1)) {
- OwickiGriesDesugaredOutputFile = args[ps.i];
- }
- return true;
-
- case "trustLayersUpto":
- if (ps.ConfirmArgumentCount(1))
- {
- ps.GetNumericArgument(ref TrustLayersUpto);
- }
- return true;
-
- case "trustLayersDownto":
- if (ps.ConfirmArgumentCount(1))
- {
- ps.GetNumericArgument(ref TrustLayersDownto);
- }
- return true;
-
- case "proverLog":
- if (ps.ConfirmArgumentCount(1)) {
- SimplifyLogFilePath = args[ps.i];
- }
- return true;
-
- case "logPrefix":
- if (ps.ConfirmArgumentCount(1)) {
- string s = cce.NonNull(args[ps.i]);
- LogPrefix += s.Replace('/', '-').Replace('\\', '-');
- }
- return true;
-
- case "proverShutdownLimit":
- ps.GetNumericArgument(ref ProverShutdownLimit);
- return true;
-
- case "errorTrace":
- ps.GetNumericArgument(ref ErrorTrace, 3);
- return true;
-
- case "proverWarnings": {
- int pw = 0;
- if (ps.GetNumericArgument(ref pw, 3)) {
- switch (pw) {
- case 0:
- PrintProverWarnings = ProverWarnings.None;
- break;
- case 1:
- PrintProverWarnings = ProverWarnings.Stdout;
- break;
- case 2:
- PrintProverWarnings = ProverWarnings.Stderr;
- break;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // postcondition of GetNumericArgument guarantees that we don't get here
- }
- }
- return true;
- }
-
- case "env": {
- int e = 0;
- if (ps.GetNumericArgument(ref e, 3)) {
- switch (e) {
- case 0:
- ShowEnv = ShowEnvironment.Never;
- break;
- case 1:
- ShowEnv = ShowEnvironment.DuringPrint;
- break;
- case 2:
- ShowEnv = ShowEnvironment.Always;
- break;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // postcondition of GetNumericArgument guarantees that we don't get here
- }
- }
- return true;
- }
-
- case "loopUnroll":
- ps.GetNumericArgument(ref LoopUnrollCount);
- return true;
-
- case "printModel":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i]) {
- case "0":
- PrintErrorModel = 0;
- break;
- case "1":
- PrintErrorModel = 1;
- break;
- case "2":
- PrintErrorModel = 2;
- break;
- case "4":
- PrintErrorModel = 4;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
-
- case "mv":
- if (ps.ConfirmArgumentCount(1)) {
- ModelViewFile = args[ps.i];
- }
- return true;
-
- case "printModelToFile":
- if (ps.ConfirmArgumentCount(1)) {
- PrintErrorModelFile = args[ps.i];
- }
- return true;
-
- case "enhancedErrorMessages":
- ps.GetNumericArgument(ref EnhancedErrorMessages, 2);
- return true;
-
- case "printCFG":
- if (ps.ConfirmArgumentCount(1)) {
- PrintCFGPrefix = args[ps.i];
- }
- return true;
-
- case "inlineDepth":
- ps.GetNumericArgument(ref InlineDepth);
- return true;
-
- case "subsumption": {
- int s = 0;
- if (ps.GetNumericArgument(ref s, 3)) {
- switch (s) {
- case 0:
- UseSubsumption = SubsumptionOption.Never;
- break;
- case 1:
- UseSubsumption = SubsumptionOption.NotForQuantifiers;
- break;
- case 2:
- UseSubsumption = SubsumptionOption.Always;
- break;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- } // postcondition of GetNumericArgument guarantees that we don't get here
- }
- }
- return true;
- }
-
- case "liveVariableAnalysis": {
- int lva = 0;
- if (ps.GetNumericArgument(ref lva, 3)) {
- LiveVariableAnalysis = lva;
- }
- return true;
- }
-
- case "removeEmptyBlocks": {
- int reb = 0;
- if (ps.GetNumericArgument(ref reb, 2)) {
- RemoveEmptyBlocks = reb == 1;
- }
- return true;
- }
-
- case "coalesceBlocks": {
- int cb = 0;
- if (ps.GetNumericArgument(ref cb, 2)) {
- CoalesceBlocks = cb == 1;
- }
- return true;
- }
-
- case "noPruneInfeasibleEdges": {
- if (ps.ConfirmArgumentCount(0)) {
- PruneInfeasibleEdges = false;
- }
- return true;
- }
-
- case "stagedHoudini": {
- if (ps.ConfirmArgumentCount(1)) {
- if(args[ps.i] == "COARSE" ||
- args[ps.i] == "FINE" ||
- args[ps.i] == "BALANCED") {
- StagedHoudini = args[ps.i];
- } else {
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- }
- }
- return true;
- }
-
- case "stagedHoudiniThreads": {
- ps.GetNumericArgument(ref StagedHoudiniThreads);
- return true;
- }
-
- case "stagedHoudiniReachabilityAnalysis": {
- if (ps.ConfirmArgumentCount(0)) {
- StagedHoudiniReachabilityAnalysis = true;
- }
- return true;
- }
-
- case "stagedHoudiniMergeIgnoredAnnotations": {
- if (ps.ConfirmArgumentCount(0)) {
- StagedHoudiniMergeIgnoredAnnotations = true;
- }
- return true;
- }
-
- case "debugStagedHoudini": {
- if (ps.ConfirmArgumentCount(0)) {
- DebugStagedHoudini = true;
- }
- return true;
- }
-
- case "variableDependenceIgnore": {
- if (ps.ConfirmArgumentCount(1)) {
- VariableDependenceIgnore = args[ps.i];
- }
- return true;
- }
-
- case "abstractHoudini":
- {
- if (ps.ConfirmArgumentCount(1))
- {
- AbstractHoudini = args[ps.i];
- }
- return true;
- }
- case "vc":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i]) {
- case "s":
- case "structured":
- vcVariety = VCVariety.Structured;
- break;
- case "b":
- case "block":
- vcVariety = VCVariety.Block;
- break;
- case "l":
- case "local":
- vcVariety = VCVariety.Local;
- break;
- case "n":
- case "nested":
- vcVariety = VCVariety.BlockNested;
- break;
- case "m":
- vcVariety = VCVariety.BlockNestedReach;
- break;
- case "r":
- vcVariety = VCVariety.BlockReach;
- break;
- case "d":
- case "dag":
- vcVariety = VCVariety.Dag;
- break;
- case "i":
- vcVariety = VCVariety.DagIterative;
- break;
- case "doomed":
- vcVariety = VCVariety.Doomed;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
-
- case "prover":
- if (ps.ConfirmArgumentCount(1)) {
- TheProverFactory = ProverFactory.Load(cce.NonNull(args[ps.i]));
- ProverName = cce.NonNull(args[ps.i]).ToUpper();
- }
- return true;
-
- case "p":
- case "proverOpt":
- if (ps.ConfirmArgumentCount(1)) {
- ProverOptions = ProverOptions.Concat1(cce.NonNull(args[ps.i]));
- }
- return true;
-
- case "DoomStrategy":
- ps.GetNumericArgument(ref DoomStrategy);
- return true;
-
- case "DoomRestartTP":
- if (ps.ConfirmArgumentCount(0)) {
- DoomRestartTP = true;
- }
- return true;
-
- case "extractLoops":
- if (ps.ConfirmArgumentCount(0)) {
- ExtractLoops = true;
- }
- return true;
-
- case "deterministicExtractLoops":
- if (ps.ConfirmArgumentCount(0)) {
- DeterministicExtractLoops = true;
- }
- return true;
-
- case "inline":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i]) {
- case "none":
- ProcedureInlining = Inlining.None;
- break;
- case "assert":
- ProcedureInlining = Inlining.Assert;
- break;
- case "assume":
- ProcedureInlining = Inlining.Assume;
- break;
- case "spec":
- ProcedureInlining = Inlining.Spec;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
- case "secure":
- if (ps.ConfirmArgumentCount(1))
- SecureVcGen = args[ps.i];
- return true;
- case "stratifiedInline":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i]) {
- case "0":
- StratifiedInlining = 0;
- break;
- case "1":
- StratifiedInlining = 1;
- break;
- default:
- StratifiedInlining = Int32.Parse(cce.NonNull(args[ps.i]));
- //ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
- case "fixedPointEngine":
- if (ps.ConfirmArgumentCount(1))
- {
- FixedPointEngine = args[ps.i];
- }
- return true;
- case "fixedPointInfer":
- if (ps.ConfirmArgumentCount(1))
- {
- switch (args[ps.i])
- {
- case "corral":
- FixedPointMode = FixedPointInferenceMode.Corral;
- break;
- case "oldCorral":
- FixedPointMode = FixedPointInferenceMode.OldCorral;
- break;
- case "flat":
- FixedPointMode = FixedPointInferenceMode.Flat;
- break;
- case "procedure":
- FixedPointMode = FixedPointInferenceMode.Procedure;
- break;
- case "call":
- FixedPointMode = FixedPointInferenceMode.Call;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
- case "printFixedPoint":
- if (ps.ConfirmArgumentCount(1))
- {
- PrintFixedPoint = args[ps.i];
- }
- return true;
- case "printConjectures":
- if (ps.ConfirmArgumentCount(1))
- {
- PrintConjectures = args[ps.i];
- }
- return true;
- case "siVerbose":
- if (ps.ConfirmArgumentCount(1)) {
- StratifiedInliningVerbose = Int32.Parse(cce.NonNull(args[ps.i]));
- }
- return true;
- case "recursionBound":
- if (ps.ConfirmArgumentCount(1)) {
- RecursionBound = Int32.Parse(cce.NonNull(args[ps.i]));
- }
- return true;
- case "stackDepthBound":
- if (ps.ConfirmArgumentCount(1))
- {
- StackDepthBound = Int32.Parse(cce.NonNull(args[ps.i]));
- }
- return true;
- case "stratifiedInlineOption":
- if (ps.ConfirmArgumentCount(1)) {
- StratifiedInliningOption = Int32.Parse(cce.NonNull(args[ps.i]));
- }
- return true;
-
- case "inferLeastForUnsat":
- if (ps.ConfirmArgumentCount(1)) {
- inferLeastForUnsat = args[ps.i];
- }
- return true;
-
- case "typeEncoding":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i]) {
- case "n":
- case "none":
- TypeEncodingMethod = TypeEncoding.None;
- break;
- case "p":
- case "predicates":
- TypeEncodingMethod = TypeEncoding.Predicates;
- break;
- case "a":
- case "arguments":
- TypeEncodingMethod = TypeEncoding.Arguments;
- break;
- case "m":
- case "monomorphic":
- TypeEncodingMethod = TypeEncoding.Monomorphic;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
-
- case "instrumentInfer":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i]) {
- case "e":
- InstrumentInfer = InstrumentationPlaces.Everywhere;
- break;
- case "h":
- InstrumentInfer = InstrumentationPlaces.LoopHeaders;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- return true;
-
- case "concurrentHoudini":
- if (ps.ConfirmArgumentCount(0)) {
- ConcurrentHoudini = true;
- }
- return true;
-
- case "modifyTopologicalSorting":
- if (ps.ConfirmArgumentCount(0)) {
- ModifyTopologicalSorting = true;
- }
- return true;
-
- case "debugConcurrentHoudini":
- if (ps.ConfirmArgumentCount(0)) {
- DebugConcurrentHoudini = true;
- }
- return true;
-
- case "vcBrackets":
- ps.GetNumericArgument(ref bracketIdsInVC, 2);
- return true;
-
- case "proverMemoryLimit": {
- int d = 0;
- if (ps.GetNumericArgument(ref d)) {
- MaxProverMemory = d * Megabyte;
- }
- return true;
- }
-
- case "vcsMaxCost":
- ps.GetNumericArgument(ref VcsMaxCost);
- return true;
-
- case "vcsPathJoinMult":
- ps.GetNumericArgument(ref VcsPathJoinMult);
- return true;
-
- case "vcsPathCostMult":
- ps.GetNumericArgument(ref VcsPathCostMult);
- return true;
-
- case "vcsAssumeMult":
- ps.GetNumericArgument(ref VcsAssumeMult);
- return true;
-
- case "vcsPathSplitMult":
- ps.GetNumericArgument(ref VcsPathSplitMult);
- return true;
-
- case "vcsMaxSplits":
- ps.GetNumericArgument(ref VcsMaxSplits);
- return true;
-
- case "vcsMaxKeepGoingSplits":
- ps.GetNumericArgument(ref VcsMaxKeepGoingSplits);
- return true;
-
- case "vcsFinalAssertTimeout":
- ps.GetNumericArgument(ref VcsFinalAssertTimeout);
- return true;
-
- case "vcsKeepGoingTimeout":
- ps.GetNumericArgument(ref VcsKeepGoingTimeout);
- return true;
-
- case "vcsCores":
- ps.GetNumericArgument(ref VcsCores, a => 1 <= a);
- return true;
-
- case "vcsLoad":
- double load = 0.0;
- if (ps.GetNumericArgument(ref load)) {
- if (3.0 <= load) {
- ps.Error("surprisingly high load specified; got {0}, expected nothing above 3.0", load.ToString());
- load = 3.0;
- }
- int p = (int)Math.Round(System.Environment.ProcessorCount * load);
- VcsCores = p < 1 ? 1 : p;
- }
- return true;
-
- case "simplifyMatchDepth":
- ps.GetNumericArgument(ref SimplifyProverMatchDepth);
- return true;
-
- case "timeLimit":
- ps.GetNumericArgument(ref ProverKillTime);
- return true;
-
- case "smokeTimeout":
- ps.GetNumericArgument(ref SmokeTimeout);
- return true;
-
- case "errorLimit":
- ps.GetNumericArgument(ref ProverCCLimit);
- return true;
-
- case "verifySnapshots":
- ps.GetNumericArgument(ref VerifySnapshots, 3);
- return true;
-
- case "traceCaching":
- ps.GetNumericArgument(ref TraceCaching, 4);
- return true;
-
- case "useSmtOutputFormat": {
- if (ps.ConfirmArgumentCount(0)) {
- UseSmtOutputFormat = true;
- }
- return true;
- }
-
- case "z3opt":
- if (ps.ConfirmArgumentCount(1)) {
- AddZ3Option(cce.NonNull(args[ps.i]));
- }
- return true;
-
- case "z3lets":
- ps.GetNumericArgument(ref Z3lets, 4);
- return true;
-
- case "platform":
- if (ps.ConfirmArgumentCount(1)) {
- StringCollection platformOptions = this.ParseNamedArgumentList(args[ps.i]);
- if (platformOptions != null && platformOptions.Count > 0) {
- try {
- this.TargetPlatform = (PlatformType)cce.NonNull(Enum.Parse(typeof(PlatformType), cce.NonNull(platformOptions[0])));
- } catch {
- ps.Error("Bad /platform type '{0}'", platformOptions[0]);
- break;
- }
- if (platformOptions.Count > 1) {
- this.TargetPlatformLocation = platformOptions[1];
- if (!Directory.Exists(platformOptions[1])) {
- ps.Error("/platform directory '{0}' does not exist", platformOptions[1]);
- break;
- }
- }
- }
- }
- return true;
-
- case "z3exe":
- if (ps.ConfirmArgumentCount(1)) {
- Z3ExecutablePath = args[ps.i];
- }
- return true;
-
- case "cvc4exe":
- if (ps.ConfirmArgumentCount(1)) {
- CVC4ExecutablePath = args[ps.i];
- }
- return true;
-
- case "kInductionDepth":
- ps.GetNumericArgument(ref KInductionDepth);
- return true;
-
- default:
- bool optionValue = false;
- if (ps.CheckBooleanFlag("printUnstructured", ref optionValue)) {
- PrintUnstructured = optionValue ? 1 : 0;
- return true;
- }
-
- if (ps.CheckBooleanFlag("printDesugared", ref PrintDesugarings) ||
- ps.CheckBooleanFlag("printInstrumented", ref PrintInstrumented) ||
- ps.CheckBooleanFlag("printWithUniqueIds", ref PrintWithUniqueASTIds) ||
- ps.CheckBooleanFlag("wait", ref Wait) ||
- ps.CheckBooleanFlag("trace", ref Trace) ||
- ps.CheckBooleanFlag("traceTimes", ref TraceTimes) ||
- ps.CheckBooleanFlag("tracePOs", ref TraceProofObligations) ||
- ps.CheckBooleanFlag("noResolve", ref NoResolve) ||
- ps.CheckBooleanFlag("noTypecheck", ref NoTypecheck) ||
- ps.CheckBooleanFlag("overlookTypeErrors", ref OverlookBoogieTypeErrors) ||
- ps.CheckBooleanFlag("noVerify", ref Verify, false) ||
- ps.CheckBooleanFlag("traceverify", ref TraceVerify) ||
- ps.CheckBooleanFlag("alwaysAssumeFreeLoopInvariants", ref AlwaysAssumeFreeLoopInvariants, true) ||
- ps.CheckBooleanFlag("nologo", ref DontShowLogo) ||
- ps.CheckBooleanFlag("proverLogAppend", ref SimplifyLogFileAppend) ||
- ps.CheckBooleanFlag("soundLoopUnrolling", ref SoundLoopUnrolling) ||
- ps.CheckBooleanFlag("checkInfer", ref InstrumentWithAsserts) ||
- ps.CheckBooleanFlag("interprocInfer", ref IntraproceduralInfer, false) ||
- ps.CheckBooleanFlag("restartProver", ref RestartProverPerVC) ||
- ps.CheckBooleanFlag("printInlined", ref PrintInlined) ||
- ps.CheckBooleanFlag("smoke", ref SoundnessSmokeTest) ||
- ps.CheckBooleanFlag("vcsDumpSplits", ref VcsDumpSplits) ||
- ps.CheckBooleanFlag("dbgRefuted", ref DebugRefuted) ||
- ps.CheckBooleanFlag("causalImplies", ref CausalImplies) ||
- ps.CheckBooleanFlag("reflectAdd", ref ReflectAdd) ||
- ps.CheckBooleanFlag("z3types", ref Z3types) ||
- ps.CheckBooleanFlag("z3multipleErrors", ref z3AtFlag, false) ||
- ps.CheckBooleanFlag("monomorphize", ref Monomorphize) ||
- ps.CheckBooleanFlag("useArrayTheory", ref UseArrayTheory) ||
- ps.CheckBooleanFlag("weakArrayTheory", ref WeakArrayTheory) ||
- ps.CheckBooleanFlag("doModSetAnalysis", ref DoModSetAnalysis) ||
- ps.CheckBooleanFlag("doNotUseLabels", ref UseLabels, false) ||
- ps.CheckBooleanFlag("boolControlVC", ref SIBoolControlVC, true) ||
- ps.CheckBooleanFlag("contractInfer", ref ContractInfer) ||
- ps.CheckBooleanFlag("explainHoudini", ref ExplainHoudini) ||
- ps.CheckBooleanFlag("reverseHoudiniWorklist", ref ReverseHoudiniWorklist) ||
- ps.CheckBooleanFlag("crossDependencies", ref HoudiniUseCrossDependencies) ||
- ps.CheckBooleanFlag("useUnsatCoreForContractInfer", ref UseUnsatCoreForContractInfer) ||
- ps.CheckBooleanFlag("printAssignment", ref PrintAssignment) ||
- ps.CheckBooleanFlag("useProverEvaluate", ref UseProverEvaluate) ||
- ps.CheckBooleanFlag("nonUniformUnfolding", ref NonUniformUnfolding) ||
- ps.CheckBooleanFlag("deterministicExtractLoops", ref DeterministicExtractLoops) ||
- ps.CheckBooleanFlag("verifySeparately", ref VerifySeparately) ||
- ps.CheckBooleanFlag("trustAtomicityTypes", ref TrustAtomicityTypes) ||
- ps.CheckBooleanFlag("trustNonInterference", ref TrustNonInterference) ||
- ps.CheckBooleanFlag("useBaseNameForFileName", ref UseBaseNameForFileName)
- ) {
- // one of the boolean flags matched
- return true;
- }
- break;
- }
-
- return base.ParseOption(name, ps); // defer to superclass
- }
-
- public override void ApplyDefaultOptions() {
- Contract.Ensures(TheProverFactory != null);
- Contract.Ensures(vcVariety != VCVariety.Unspecified);
-
- base.ApplyDefaultOptions();
-
- // expand macros in filenames, now that LogPrefix is fully determined
- ExpandFilename(ref XmlSinkFilename, LogPrefix, FileTimestamp);
- ExpandFilename(ref PrintFile, LogPrefix, FileTimestamp);
- ExpandFilename(ref SimplifyLogFilePath, LogPrefix, FileTimestamp);
- ExpandFilename(ref PrintErrorModelFile, LogPrefix, FileTimestamp);
-
- Contract.Assume(XmlSink == null); // XmlSink is to be set here
- if (XmlSinkFilename != null) {
- XmlSink = new XmlSink(XmlSinkFilename);
- }
-
- if (TheProverFactory == null) {
- TheProverFactory = ProverFactory.Load("SMTLib");
- ProverName = "SMTLib".ToUpper();
- }
-
- var proverOpts = TheProverFactory.BlankProverOptions();
- proverOpts.Parse(ProverOptions);
- if (!TheProverFactory.SupportsLabels(proverOpts)) {
- UseLabels = false;
- }
-
- if (vcVariety == VCVariety.Unspecified) {
- vcVariety = TheProverFactory.DefaultVCVariety;
- }
-
- if (UseArrayTheory) {
- Monomorphize = true;
- }
-
- if (inferLeastForUnsat != null) {
- StratifiedInlining = 1;
- }
-
- if (StratifiedInlining > 0) {
- TypeEncodingMethod = TypeEncoding.Monomorphic;
- UseArrayTheory = true;
- UseAbstractInterpretation = false;
- MaxProverMemory = 0; // no max: avoids restarts
- if (ProverName == "Z3API" || ProverName == "SMTLIB") {
- ProverCCLimit = 1;
- }
- if (UseProverEvaluate)
- StratifiedInliningWithoutModels = true;
- }
-
- if (Trace) {
- BoogieDebug.DoPrinting = true; // reuse the -trace option for debug printing
- }
- }
-
-
-
- public bool UserWantsToCheckRoutine(string methodFullname) {
- Contract.Requires(methodFullname != null);
- if (ProcsToCheck == null) {
- // no preference
- return true;
- }
- return ProcsToCheck.Any(s => 0 <= methodFullname.IndexOf(s));
- }
-
- public virtual StringCollection ParseNamedArgumentList(string argList) {
- if (argList == null || argList.Length == 0)
- return null;
- StringCollection result = new StringCollection();
- int i = 0;
- for (int n = argList.Length; i < n; ) {
- cce.LoopInvariant(0 <= i);
- int separatorIndex = this.GetArgumentSeparatorIndex(argList, i);
- if (separatorIndex > i) {
- result.Add(argList.Substring(i, separatorIndex - i));
- i = separatorIndex + 1;
- continue;
- }
- result.Add(argList.Substring(i));
- break;
- }
- return result;
- }
- public int GetArgumentSeparatorIndex(string argList, int startIndex) {
- Contract.Requires(argList != null);
- Contract.Requires(0 <= startIndex && startIndex <= argList.Length);
- Contract.Ensures(Contract.Result<int>() < argList.Length);
- int commaIndex = argList.IndexOf(",", startIndex);
- int semicolonIndex = argList.IndexOf(";", startIndex);
- if (commaIndex == -1)
- return semicolonIndex;
- if (semicolonIndex == -1)
- return commaIndex;
- if (commaIndex < semicolonIndex)
- return commaIndex;
- return semicolonIndex;
- }
-
- public override void AttributeUsage() {
- Console.WriteLine(
-@"Boogie: The following attributes are supported by this implementation.
-
- ---- On top-level declarations ---------------------------------------------
-
- {:ignore}
- Ignore the declaration (after checking for duplicate names).
-
- {:extern}
- If two top-level declarations introduce the same name (for example, two
- constants with the same name or two procedures with the same name), then
- Boogie usually produces an error message. However, if at least one of
- the declarations is declared with :extern, one of the declarations is
- ignored. If both declarations are :extern, Boogie arbitrarily chooses
- one of them to keep; otherwise, Boogie ignore the :extern declaration
- and keeps the other.
-
- {:checksum <string>}
- Attach a checksum to be used for verification result caching.
-
- ---- On implementations and procedures -------------------------------------
-
- {:inline N}
- Inline given procedure (can be also used on implementation).
- N should be a non-negative number and represents the inlining depth.
- With /inline:assume call is replaced with ""assume false"" once inlining depth is reached.
- With /inline:assert call is replaced with ""assert false"" once inlining depth is reached.
- With /inline:spec call is left as is once inlining depth is reached.
- With the above three options, methods with the attribute {:inline N} are not verified.
- With /inline:none the entire attribute is ignored.
-
- {:verify false}
- Skip verification of an implementation.
-
- {:vcs_max_cost N}
- {:vcs_max_splits N}
- {:vcs_max_keep_going_splits N}
- Per-implementation versions of
- /vcsMaxCost, /vcsMaxSplits and /vcsMaxKeepGoingSplits.
-
- {:selective_checking true}
- Turn all asserts into assumes except for the ones reachable from
- assumptions marked with the attribute {:start_checking_here}.
- Thus, ""assume {:start_checking_here} something;"" becomes an inverse
- of ""assume false;"": the first one disables all verification before
- it, and the second one disables all verification after.
-
- {:priority N}
- Assign a positive priority 'N' to an implementation to control the order
- in which implementations are verified (default: N = 1).
-
- {:id <string>}
- Assign a unique ID to an implementation to be used for verification
- result caching (default: ""<impl. name>:0"").
-
- {:timeLimit N}
- Set the time limit for a given implementation.
-
- ---- On functions ----------------------------------------------------------
-
- {:builtin ""spec""}
- {:bvbuiltin ""spec""}
- Rewrite the function to built-in prover function symbol 'fn'.
-
- {:inline}
- {:inline true}
- Expand function according to its definition before going to the prover.
-
- {:never_pattern true}
- Terms starting with this function symbol will never be
- automatically selected as patterns. It does not prevent them
- from being used inside the triggers, and does not affect explicit
- trigger annotations. Internally it works by adding {:nopats ...}
- annotations to quantifiers.
-
- {:identity}
- {:identity true}
- If the function has 1 argument and the use of it has type X->X for
- some X, then the abstract interpreter will treat the function as an
- identity function. Note, the abstract interpreter trusts the
- attribute--it does not try to verify that the function really is an
- identity function.
-
- ---- On variables ----------------------------------------------------------
-
- {:existential true}
- Marks a global Boolean variable as existentially quantified. If
- used in combination with option /contractInfer Boogie will check
- whether there exists a Boolean assignment to the existentials
- that makes all verification conditions valid. Without option
- /contractInfer the attribute is ignored.
-
- ---- On assert statements --------------------------------------------------
-
- {:subsumption n}
- Overrides the /subsumption command-line setting for this assertion.
-
- {:split_here}
- Verifies code leading to this point and code leading from this point
- to the next split_here as separate pieces. May help with timeouts.
- May also occasionally double-report errors.
-
- ---- The end ---------------------------------------------------------------
-");
- }
-
- public override void Usage() {
- Console.WriteLine(@"
- /nologo suppress printing of version number, copyright message
- /env:<n> print command line arguments
- 0 - never, 1 (default) - during BPL print and prover log,
- 2 - like 1 and also to standard output
- /wait await Enter from keyboard before terminating program
- /xml:<file> also produce output in XML format to <file>
-
- ---- Boogie options --------------------------------------------------------
-
- Multiple .bpl files supplied on the command line are concatenated into one
- Boogie program.
-
- /proc:<p> : limits which procedures to check
- /noResolve : parse only
- /noTypecheck : parse and resolve only
-
- /print:<file> : print Boogie program after parsing it
- (use - as <file> to print to console)
- /pretty:<n>
- 0 - print each Boogie statement on one line (faster).
- 1 (default) - pretty-print with some line breaks.
- /printWithUniqueIds : print augmented information that uniquely
- identifies variables
- /printUnstructured : with /print option, desugars all structured statements
- /printDesugared : with /print option, desugars calls
-
- /overlookTypeErrors : skip any implementation with resolution or type
- checking errors
-
- /loopUnroll:<n>
- unroll loops, following up to n back edges (and then some)
- /soundLoopUnrolling
- sound loop unrolling
- /printModel:<n>
- 0 (default) - do not print Z3's error model
- 1 - print Z3's error model
- 2 - print Z3's error model plus reverse mappings
- 4 - print Z3's error model in a more human readable way
- /printModelToFile:<file>
- print model to <file> instead of console
- /mv:<file> Specify file where to save the model in BVD format
- /enhancedErrorMessages:<n>
- 0 (default) - no enhanced error messages
- 1 - Z3 error model enhanced error messages
-
- /printCFG:<prefix> : print control flow graph of each implementation in
- Graphviz format to files named:
- <prefix>.<procedure name>.dot
-
- /useBaseNameForFileName : When parsing use basename of file for tokens instead
- of the path supplied on the command line
-
- ---- Inference options -----------------------------------------------------
-
- /infer:<flags>
- use abstract interpretation to infer invariants
- The default is /infer:i"
- // This is not 100% true, as the /infer ALWAYS creates
- // a multilattice, whereas if nothing is specified then
- // intervals are isntantiated WITHOUT being embedded in
- // a multilattice
- + @"
- <flags> are as follows (missing <flags> means all)
- i = intervals
- c = constant propagation
- d = dynamic type
- n = nullness
- p = polyhedra for linear inequalities
- t = trivial bottom/top lattice (cannot be combined with
- other domains)
- j = stronger intervals (cannot be combined with other
- domains)
- or the following (which denote options, not domains):
- s = debug statistics
- 0..9 = number of iterations before applying a widen (default=0)
- /noinfer turn off the default inference, and overrides the /infer
- switch on its left
- /checkInfer instrument inferred invariants as asserts to be checked by
- theorem prover
- /interprocInfer
- perform interprocedural inference (deprecated, not supported)
- /contractInfer
- perform procedure contract inference
- /instrumentInfer
- h - instrument inferred invariants only at beginning of
- loop headers (default)
- e - instrument inferred invariants at beginning and end
- of every block (this mode is intended for use in
- debugging of abstract domains)
- /printInstrumented
- print Boogie program after it has been instrumented with
- invariants
-
- ---- Debugging and general tracing options ---------------------------------
-
- /trace blurt out various debug trace information
- /traceTimes output timing information at certain points in the pipeline
- /tracePOs output information about the number of proof obligations
- (also included in the /trace output)
- /log[:method] Print debug output during translation
-
- /break launch and break into debugger
-
- ---- Verification-condition generation options -----------------------------
-
- /liveVariableAnalysis:<c>
- 0 = do not perform live variable analysis
- 1 = perform live variable analysis (default)
- 2 = perform interprocedural live variable analysis
- /noVerify skip VC generation and invocation of the theorem prover
- /verifySnapshots:<n>
- verify several program snapshots (named <filename>.v0.bpl
- to <filename>.vN.bpl) using verification result caching:
- 0 - do not use any verification result caching (default)
- 1 - use the basic verification result caching
- 2 - use the more advanced verification result caching
- /verifySeparately
- verify each input program separately
- /removeEmptyBlocks:<c>
- 0 - do not remove empty blocks during VC generation
- 1 - remove empty blocks (default)
- /coalesceBlocks:<c>
- 0 = do not coalesce blocks
- 1 = coalesce blocks (default)
- /vc:<variety> n = nested block (default for /prover:Simplify),
- m = nested block reach,
- b = flat block, r = flat block reach,
- s = structured, l = local,
- d = dag (default, except with /prover:Simplify)
- doomed = doomed
- /traceverify print debug output during verification condition generation
- /subsumption:<c>
- apply subsumption to asserted conditions:
- 0 - never, 1 - not for quantifiers, 2 (default) - always
- /alwaysAssumeFreeLoopInvariants
- usually, a free loop invariant (or assume
- statement in that position) is ignored in checking contexts
- (like other free things); this option includes these free
- loop invariants as assumes in both contexts
- /inline:<i> use inlining strategy <i> for procedures with the :inline
- attribute, see /attrHelp for details:
- none
- assume (default)
- assert
- spec
- /printInlined
- print the implementation after inlining calls to
- procedures with the :inline attribute (works with /inline)
- /lazyInline:1
- Use the lazy inlining algorithm
- /stratifiedInline:1
- Use the stratified inlining algorithm
- /fixedPointEngine:<engine>
- Use the specified fixed point engine for inference
- /recursionBound:<n>
- Set the recursion bound for stratified inlining to
- be n (default 500)
- /inferLeastForUnsat:<str>
- Infer the least number of constants (whose names
- are prefixed by <str>) that need to be set to
- true for the program to be correct. This turns
- on stratified inlining.
- /smoke Soundness Smoke Test: try to stick assert false; in some
- places in the BPL and see if we can still prove it
- /smokeTimeout:<n>
- Timeout, in seconds, for a single theorem prover
- invocation during smoke test, defaults to 10.
- /causalImplies
- Translate Boogie's A ==> B into prover's A ==> A && B.
- /typeEncoding:<m>
- how to encode types when sending VC to theorem prover
- n = none (unsound)
- p = predicates (default)
- a = arguments
- m = monomorphic
- /monomorphize
- Do not abstract map types in the encoding (this is an
- experimental feature that will not do the right thing if
- the program uses polymorphism)
- /reflectAdd In the VC, generate an auxiliary symbol, elsewhere defined
- to be +, instead of +.
-
- ---- Verification-condition splitting --------------------------------------
-
- /vcsMaxCost:<f>
- VC will not be split unless the cost of a VC exceeds this
- number, defaults to 2000.0. This does NOT apply in the
- keep-going mode after first round of splitting.
- /vcsMaxSplits:<n>
- Maximal number of VC generated per method. In keep
- going mode only applies to the first round.
- Defaults to 1.
- /vcsMaxKeepGoingSplits:<n>
- If set to more than 1, activates the keep
- going mode, where after the first round of splitting,
- VCs that timed out are split into <n> pieces and retried
- until we succeed proving them, or there is only one
- assertion on a single path and it timeouts (in which
- case error is reported for that assertion).
- Defaults to 1.
- /vcsKeepGoingTimeout:<n>
- Timeout in seconds for a single theorem prover
- invocation in keep going mode, except for the final
- single-assertion case. Defaults to 1s.
- /vcsFinalAssertTimeout:<n>
- Timeout in seconds for the single last
- assertion in the keep going mode. Defaults to 30s.
- /vcsPathJoinMult:<f>
- If more than one path join at a block, by how much
- multiply the number of paths in that block, to accomodate
- for the fact that the prover will learn something on one
- paths, before proceeding to another. Defaults to 0.8.
- /vcsPathCostMult:<f1>
- /vcsAssumeMult:<f2>
- The cost of a block is
- (<assert-cost> + <f2>*<assume-cost>) *
- (1.0 + <f1>*<entering-paths>)
- <f1> defaults to 1.0, <f2> defaults to 0.01.
- The cost of a single assertion or assumption is
- currently always 1.0.
- /vcsPathSplitMult:<f>
- If the best path split of a VC of cost A is into
- VCs of cost B and C, then the split is applied if
- A >= <f>*(B+C), otherwise assertion splitting will be
- applied. Defaults to 0.5 (always do path splitting if
- possible), set to more to do less path splitting
- and more assertion splitting.
- /vcsDumpSplits
- For split #n dump split.n.dot and split.n.bpl.
- Warning: Affects error reporting.
- /vcsCores:<n>
- Try to verify <n> VCs at once. Defaults to 1.
- /vcsLoad:<f> Sets vcsCores to the machine's ProcessorCount * f,
- rounded to the nearest integer (where 0.0 <= f <= 3.0),
- but never to less than 1.
-
- ---- Prover options --------------------------------------------------------
-
- /errorLimit:<num>
- Limit the number of errors produced for each procedure
- (default is 5, some provers may support only 1)
- /timeLimit:<num>
- Limit the number of seconds spent trying to verify
- each procedure
- /errorTrace:<n>
- 0 - no Trace labels in the error output,
- 1 (default) - include useful Trace labels in error output,
- 2 - include all Trace labels in the error output
- /vcBrackets:<b>
- bracket odd-charactered identifier names with |'s. <b> is:
- 0 - no (default with non-/prover:Simplify),
- 1 - yes (default with /prover:Simplify)
- /prover:<tp> use theorem prover <tp>, where <tp> is either the name of
- a DLL containing the prover interface located in the
- Boogie directory, or a full path to a DLL containing such
- an interface. The standard interfaces shipped include:
- SMTLib (default, uses the SMTLib2 format and calls Z3)
- Z3 (uses Z3 with the Simplify format)
- Simplify
- ContractInference (uses Z3)
- Z3api (Z3 using Managed .NET API)
- /proverOpt:KEY[=VALUE]
- Provide a prover-specific option (short form /p).
- /proverLog:<file>
- Log input for the theorem prover. Like filenames
- supplied as arguments to other options, <file> can use the
- following macros:
- @TIME@ expands to the current time
- @PREFIX@ expands to the concatenation of strings given
- by /logPrefix options
- @FILE@ expands to the last filename specified on the
- command line
- In addition, /proverLog can also use the macro '@PROC@',
- which causes there to be one prover log file per
- verification condition, and the macro then expands to the
- name of the procedure that the verification condition is for.
- /logPrefix:<str>
- Defines the expansion of the macro '@PREFIX@', which can
- be used in various filenames specified by other options.
- /proverLogAppend
- Append (not overwrite) the specified prover log file
- /proverWarnings
- 0 (default) - don't print, 1 - print to stdout,
- 2 - print to stderr
- /proverMemoryLimit:<num>
- Limit on the virtual memory for prover before
- restart in MB (default:100MB)
- /restartProver
- Restart the prover after each query
- /proverShutdownLimit<num>
- Time between closing the stream to the prover and
- killing the prover process (default: 0s)
- /platform:<ptype>,<location>
- ptype = v11,v2,cli1
- location = platform libraries directory
-
- Simplify specific options:
- /simplifyMatchDepth:<num>
- Set Simplify prover's matching depth limit
-
- Z3 specific options:
- /z3opt:<arg> specify additional Z3 options
- /z3multipleErrors
- report multiple counterexamples for each error
- /useArrayTheory
- use Z3's native theory (as opposed to axioms). Currently
- implies /monomorphize.
- /useSmtOutputFormat
- Z3 outputs a model in the SMTLIB2 format.
- /z3types generate multi-sorted VC that make use of Z3 types
- /z3lets:<n> 0 - no LETs, 1 - only LET TERM, 2 - only LET FORMULA,
- 3 - (default) any
- /z3exe:<path>
- path to Z3 executable
-
- CVC4 specific options:
- /cvc4exe:<path>
- path to CVC4 executable
-");
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie {
+ public class CommandLineOptionEngine
+ {
+ public readonly string ToolName;
+ public readonly string DescriptiveToolName;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ToolName != null);
+ Contract.Invariant(DescriptiveToolName != null);
+ Contract.Invariant(this._environment != null);
+ Contract.Invariant(cce.NonNullElements(this._files));
+ Contract.Invariant(this._fileTimestamp != null);
+ }
+
+ private string/*!*/ _environment = "";
+
+ public string Environment {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this._environment;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._environment = value;
+ }
+ }
+
+ private readonly List<string/*!*/>/*!*/ _files = new List<string/*!*/>();
+
+ public IList<string/*!*/>/*!*/ Files {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IList<string>>()));
+ Contract.Ensures(Contract.Result<IList<string>>().IsReadOnly);
+ return this._files.AsReadOnly();
+ }
+ }
+
+ public bool HelpRequested = false;
+ public bool AttrHelpRequested = false;
+
+ public CommandLineOptionEngine(string toolName, string descriptiveName) {
+ Contract.Requires(toolName != null);
+ Contract.Requires(descriptiveName != null);
+ ToolName = toolName;
+ DescriptiveToolName = descriptiveName;
+ }
+
+ public virtual string/*!*/ VersionNumber {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return cce.NonNull(cce.NonNull(System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location)).FileVersion);
+ }
+ }
+ public virtual string/*!*/ VersionSuffix {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return " version " + VersionNumber + ", Copyright (c) 2003-2014, Microsoft.";
+ }
+ }
+ public virtual string/*!*/ Version {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return DescriptiveToolName + VersionSuffix;
+ }
+ }
+
+ private string/*!*/ _fileTimestamp = cce.NonNull(DateTime.Now.ToString("o")).Replace(':', '.');
+
+ public string FileTimestamp {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this._fileTimestamp;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._fileTimestamp = value;
+ }
+ }
+
+ public void ExpandFilename(ref string pattern, string logPrefix, string fileTimestamp) {
+ if (pattern != null) {
+ pattern = pattern.Replace("@PREFIX@", logPrefix).Replace("@TIME@", fileTimestamp);
+ string fn = Files.Count == 0 ? "" : Files[Files.Count - 1];
+ fn = fn.Replace('/', '-').Replace('\\', '-');
+ pattern = pattern.Replace("@FILE@", fn);
+ }
+ }
+
+ /// <summary>
+ /// Process the option and modify "ps" accordingly.
+ /// Return true if the option is one that is recognized.
+ /// </summary>
+ protected virtual bool ParseOption(string name, CommandLineParseState ps) {
+ Contract.Requires(name != null);
+ Contract.Requires(ps != null);
+
+ switch (name) {
+ case "help":
+ case "?":
+ if (ps.ConfirmArgumentCount(0)) {
+ HelpRequested = true;
+ }
+ return true;
+ case "attrHelp":
+ if (ps.ConfirmArgumentCount(0)) {
+ AttrHelpRequested = true;
+ }
+ return true;
+ default:
+ break;
+ }
+ return false; // unrecognized option
+ }
+
+ protected class CommandLineParseState
+ {
+ public string s;
+ public bool hasColonArgument;
+ public readonly string[]/*!*/ args;
+ public int i;
+ public int nextIndex;
+ public bool EncounteredErrors;
+ public readonly string ToolName;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(args != null);
+ Contract.Invariant(0 <= i && i <= args.Length);
+ Contract.Invariant(0 <= nextIndex && nextIndex <= args.Length);
+ }
+
+
+ public CommandLineParseState(string[] args, string toolName) {
+ Contract.Requires(args != null);
+ Contract.Requires(Contract.ForAll(0, args.Length, i => args[i] != null));
+ Contract.Requires(toolName != null);
+ Contract.Ensures(this.args == args);
+ this.ToolName = toolName;
+ this.s = null; // set later by client
+ this.hasColonArgument = false; // set later by client
+ this.args = args;
+ this.i = 0;
+ this.nextIndex = 0; // set later by client
+ this.EncounteredErrors = false;
+ }
+
+ public bool CheckBooleanFlag(string flagName, ref bool flag, bool valueWhenPresent) {
+ Contract.Requires(flagName != null);
+ //modifies nextIndex, encounteredErrors, Console.Error.*;
+ bool flagPresent = false;
+
+ if ((s == "/" + flagName || s == "-" + flagName) && ConfirmArgumentCount(0)) {
+ flag = valueWhenPresent;
+ flagPresent = true;
+ }
+ return flagPresent;
+ }
+
+ public bool CheckBooleanFlag(string flagName, ref bool flag) {
+ Contract.Requires(flagName != null);
+ //modifies nextIndex, encounteredErrors, Console.Error.*;
+ return CheckBooleanFlag(flagName, ref flag, true);
+ }
+
+ /// <summary>
+ /// If there is one argument and it is a non-negative integer, then set "arg" to that number and return "true".
+ /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref int arg) {
+ //modifies nextIndex, encounteredErrors, Console.Error.*;
+ return GetNumericArgument(ref arg, a => 0 <= a);
+ }
+
+ /// <summary>
+ /// If there is one argument and the filtering predicate holds, then set "arg" to that number and return "true".
+ /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref int arg, Predicate<int> filter) {
+ Contract.Requires(filter != null);
+
+ if (this.ConfirmArgumentCount(1)) {
+ try {
+ Contract.Assume(args[i] != null);
+ Contract.Assert(args[i] is string); // needed to prove args[i].IsPeerConsistent
+ int d = Convert.ToInt32(this.args[this.i]);
+ if (filter == null || filter(d)) {
+ arg = d;
+ return true;
+ }
+ } catch (System.FormatException) {
+ } catch (System.OverflowException) {
+ }
+ } else {
+ return false;
+ }
+ Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
+ return false;
+ }
+
+ /// <summary>
+ /// If there is one argument and it is a non-negative integer less than "limit",
+ /// then set "arg" to that number and return "true".
+ /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref int arg, int limit) {
+ Contract.Requires(this.i < args.Length);
+ Contract.Ensures(Math.Min(arg, 0) <= Contract.ValueAtReturn(out arg) && Contract.ValueAtReturn(out arg) < limit);
+ //modifies nextIndex, encounteredErrors, Console.Error.*;
+ int a = arg;
+ if (!GetNumericArgument(ref a)) {
+ return false;
+ } else if (a < limit) {
+ arg = a;
+ return true;
+ } else {
+ Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// If there is one argument and it is a non-negative real, then set "arg" to that number and return "true".
+ /// Otherwise, emit an error message, leave "arg" unchanged, and return "false".
+ /// </summary>
+ public bool GetNumericArgument(ref double arg) {
+ Contract.Ensures(Contract.ValueAtReturn(out arg) >= 0);
+ //modifies nextIndex, encounteredErrors, Console.Error.*;
+ if (this.ConfirmArgumentCount(1)) {
+ try {
+ Contract.Assume(args[i] != null);
+ Contract.Assert(args[i] is string); // needed to prove args[i].IsPeerConsistent
+ double d = Convert.ToDouble(this.args[this.i]);
+ if (0 <= d) {
+ arg = d;
+ return true;
+ }
+ } catch (System.FormatException) {
+ } catch (System.OverflowException) {
+ }
+ } else {
+ return false;
+ }
+ Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
+ return false;
+ }
+
+ public bool ConfirmArgumentCount(int argCount) {
+ Contract.Requires(0 <= argCount);
+ //modifies nextIndex, encounteredErrors, Console.Error.*;
+ Contract.Ensures(Contract.Result<bool>() == (!(hasColonArgument && argCount != 1) && !(args.Length < i + argCount)));
+ if (hasColonArgument && argCount != 1) {
+ Error("\"{0}\" cannot take a colon argument", s);
+ nextIndex = args.Length;
+ return false;
+ } else if (args.Length < i + argCount) {
+ Error("\"{0}\" expects {1} argument{2}", s, argCount.ToString(), (string)(argCount == 1 ? "" : "s"));
+ nextIndex = args.Length;
+ return false;
+ } else {
+ nextIndex = i + argCount;
+ return true;
+ }
+ }
+
+ public void Error(string message, params string[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(message != null);
+ //modifies encounteredErrors, Console.Error.*;
+ Console.Error.WriteLine("{0}: Error: {1}", ToolName, String.Format(message, args));
+ EncounteredErrors = true;
+ }
+ }
+
+ public virtual void Usage() {
+ Console.WriteLine("{0}: usage: {0} [ option ... ] [ filename ... ]", ToolName);
+ Console.WriteLine(@" where <option> is one of
+
+ ---- General options -------------------------------------------------------
+
+ /help this message
+ /attrHelp print a message about declaration attributes supported by
+ this implementation");
+ }
+
+ public virtual void AttributeUsage() {
+ }
+
+ /// <summary>
+ /// This method is called after all parsing is done, if no parse errors were encountered.
+ /// </summary>
+ public virtual void ApplyDefaultOptions() {
+ }
+
+ /// <summary>
+ /// Parses the command-line arguments "args" into the global flag variables. Returns true
+ /// if there were no errors.
+ /// </summary>
+ /// <param name="args">Consumed ("captured" and possibly modified) by the method.</param>
+ public bool Parse([Captured] string[]/*!*/ args) {
+ Contract.Requires(cce.NonNullElements(args));
+
+ // save the command line options for the log files
+ Environment += "Command Line Options: " + args.Concat(" ");
+ args = cce.NonNull((string[])args.Clone()); // the operations performed may mutate the array, so make a copy
+ var ps = new CommandLineParseState(args, ToolName);
+
+ while (ps.i < args.Length) {
+ cce.LoopInvariant(ps.args == args);
+ string arg = args[ps.i];
+ Contract.Assert(arg != null);
+ ps.s = arg.Trim();
+
+ bool isOption = ps.s.StartsWith("-") || ps.s.StartsWith("/");
+ int colonIndex = ps.s.IndexOf(':');
+ if (0 <= colonIndex && isOption) {
+ ps.hasColonArgument = true;
+ args[ps.i] = ps.s.Substring(colonIndex + 1);
+ ps.s = ps.s.Substring(0, colonIndex);
+ } else {
+ ps.i++;
+ ps.hasColonArgument = false;
+ }
+ ps.nextIndex = ps.i;
+
+ if (isOption) {
+ if (!ParseOption(ps.s.Substring(1), ps)) {
+ if (Path.DirectorySeparatorChar == '/' && ps.s.StartsWith("/"))
+ this._files.Add(arg);
+ else
+ ps.Error("unknown switch: {0}", ps.s);
+ }
+ } else {
+ this._files.Add(arg);
+ }
+
+ ps.i = ps.nextIndex;
+ }
+
+ if (HelpRequested) {
+ Usage();
+ } else if (AttrHelpRequested) {
+ AttributeUsage();
+ } else if (ps.EncounteredErrors) {
+ Console.WriteLine("Use /help for available options");
+ }
+
+ if (ps.EncounteredErrors) {
+ return false;
+ } else {
+ this.ApplyDefaultOptions();
+ return true;
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Boogie command-line options (other tools can subclass this class in order to support a
+ /// superset of Boogie's options.
+ /// </summary>
+ public class CommandLineOptions : CommandLineOptionEngine {
+
+ public CommandLineOptions()
+ : base("Boogie", "Boogie program verifier") {
+ }
+
+ protected CommandLineOptions(string toolName, string descriptiveName)
+ : base(toolName, descriptiveName) {
+ Contract.Requires(toolName != null);
+ Contract.Requires(descriptiveName != null);
+ }
+
+ private static CommandLineOptions clo;
+ public static CommandLineOptions/*!*/ Clo
+ {
+ get { return clo; }
+ }
+
+ public static void Install(CommandLineOptions options) {
+ Contract.Requires(options != null);
+ clo = options;
+ }
+
+ public const long Megabyte = 1048576;
+
+ // Flags and arguments
+
+ public bool RunningBoogieFromCommandLine = false; // "false" means running Boogie from the plug-in
+
+ [ContractInvariantMethod]
+ void ObjectInvariant2() {
+ Contract.Invariant(LogPrefix != null);
+ Contract.Invariant(0 <= PrintUnstructured && PrintUnstructured < 3); // 0 = print only structured, 1 = both structured and unstructured, 2 = only unstructured
+ }
+
+ public int VerifySnapshots = -1;
+ public bool VerifySeparately = false;
+ public string PrintFile = null;
+ public int PrintUnstructured = 0;
+ public bool UseBaseNameForFileName = false;
+ public int DoomStrategy = -1;
+ public bool DoomRestartTP = false;
+ public bool PrintDesugarings = false;
+ public string SimplifyLogFilePath = null;
+ public bool PrintInstrumented = false;
+ public bool InstrumentWithAsserts = false;
+ public string ProverPreamble = null;
+
+ public enum InstrumentationPlaces {
+ LoopHeaders,
+ Everywhere
+ }
+ public InstrumentationPlaces InstrumentInfer = InstrumentationPlaces.LoopHeaders;
+ public bool PrintWithUniqueASTIds = false;
+ private string XmlSinkFilename = null;
+ [Peer]
+ public XmlSink XmlSink = null;
+ public bool Wait = false;
+ public bool Trace = false;
+ public bool TraceTimes = false;
+ public bool TraceProofObligations = false;
+ public bool TraceCachingForTesting
+ {
+ get
+ {
+ return TraceCaching == 1 || TraceCaching == 3;
+ }
+ }
+ public bool TraceCachingForBenchmarking
+ {
+ get
+ {
+ return TraceCaching == 2 || TraceCaching == 3;
+ }
+ }
+ public bool TraceCachingForDebugging
+ {
+ get
+ {
+ return TraceCaching == 3;
+ }
+ }
+ internal int TraceCaching = 0;
+ public bool NoResolve = false;
+ public bool NoTypecheck = false;
+ public bool OverlookBoogieTypeErrors = false;
+ public bool Verify = true;
+ public bool TraceVerify = false;
+ public int /*(0:3)*/ ErrorTrace = 1;
+ public bool IntraproceduralInfer = true;
+ public bool ContractInfer = false;
+ public bool ExplainHoudini = false;
+ public bool ReverseHoudiniWorklist = false;
+ public bool ConcurrentHoudini = false;
+ public bool ModifyTopologicalSorting = false;
+ public bool DebugConcurrentHoudini = false;
+ public bool HoudiniUseCrossDependencies = false;
+ public string StagedHoudini = null;
+ public bool DebugStagedHoudini = false;
+ public bool StagedHoudiniReachabilityAnalysis = false;
+ public bool StagedHoudiniMergeIgnoredAnnotations = false;
+ public int StagedHoudiniThreads = 1;
+ public string VariableDependenceIgnore = null;
+ public string AbstractHoudini = null;
+ public bool UseUnsatCoreForContractInfer = false;
+ public bool PrintAssignment = false;
+ // TODO(wuestholz): Add documentation for this flag.
+ public bool PrintNecessaryAssumes = false;
+ public int InlineDepth = -1;
+ public bool UseProverEvaluate = false; // Use ProverInterface's Evaluate method, instead of model to get variable values
+ public bool UseUncheckedContracts = false;
+ public bool SimplifyLogFileAppend = false;
+ public bool SoundnessSmokeTest = false;
+ public string Z3ExecutablePath = null;
+ public string Z3ExecutableName = null;
+ public string CVC4ExecutablePath = null;
+ public int KInductionDepth = -1;
+
+ private string/*!*/ _logPrefix = "";
+
+ public string LogPrefix {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return this._logPrefix;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._logPrefix = value;
+ }
+ }
+
+ public bool PrettyPrint = true;
+
+ public enum ProverWarnings {
+ None,
+ Stdout,
+ Stderr
+ }
+ public ProverWarnings PrintProverWarnings = ProverWarnings.None;
+ public int ProverShutdownLimit = 0;
+
+ public enum SubsumptionOption {
+ Never,
+ NotForQuantifiers,
+ Always
+ }
+ public SubsumptionOption UseSubsumption = SubsumptionOption.Always;
+
+ public bool AlwaysAssumeFreeLoopInvariants = false;
+
+ public enum ShowEnvironment {
+ Never,
+ DuringPrint,
+ Always
+ }
+ public ShowEnvironment ShowEnv = ShowEnvironment.DuringPrint;
+ public bool DontShowLogo = false;
+ [ContractInvariantMethod]
+ void ObjectInvariant3() {
+ Contract.Invariant(-1 <= LoopFrameConditions && LoopFrameConditions < 3);
+ Contract.Invariant(0 <= ModifiesDefault && ModifiesDefault < 7);
+ Contract.Invariant((0 <= PrintErrorModel && PrintErrorModel <= 2) || PrintErrorModel == 4);
+ Contract.Invariant(0 <= EnhancedErrorMessages && EnhancedErrorMessages < 2);
+ Contract.Invariant(0 <= StepsBeforeWidening && StepsBeforeWidening <= 9);
+ Contract.Invariant(-1 <= this.bracketIdsInVC && this.bracketIdsInVC <= 1);
+ Contract.Invariant(cce.NonNullElements(this.proverOptions));
+ }
+
+ public int LoopUnrollCount = -1; // -1 means don't unroll loops
+ public bool SoundLoopUnrolling = false;
+ public int LoopFrameConditions = -1; // -1 means not specified -- this will be replaced by the "implications" section below
+ public int ModifiesDefault = 5;
+ public bool LocalModifiesChecks = true;
+ public bool NoVerifyByDefault = false;
+ public enum OwnershipModelOption {
+ Standard,
+ Experimental,
+ Trivial
+ }
+ public OwnershipModelOption OwnershipModelEncoding = OwnershipModelOption.Standard;
+ public int PrintErrorModel = 0;
+ public string PrintErrorModelFile = null;
+ public string/*?*/ ModelViewFile = null;
+ public int EnhancedErrorMessages = 0;
+ public string PrintCFGPrefix = null;
+ public bool ForceBplErrors = false; // if true, boogie error is shown even if "msg" attribute is present
+ public bool UseArrayTheory = false;
+ public bool UseSmtOutputFormat = false;
+ public bool WeakArrayTheory = false;
+ public bool UseLabels = true;
+ public bool RunDiagnosticsOnTimeout = false;
+ public bool TraceDiagnosticsOnTimeout = false;
+ public int TimeLimitPerAssertionInPercent = 10;
+ public bool SIBoolControlVC = false;
+ public bool MonomorphicArrays {
+ get {
+ return UseArrayTheory || TypeEncodingMethod == TypeEncoding.Monomorphic;
+ }
+ }
+ public bool ExpandLambdas = true; // not useful from command line, only to be set to false programatically
+ public bool DoModSetAnalysis = false;
+ public bool UseAbstractInterpretation = true; // true iff the user want to use abstract interpretation
+ private int /*0..9*/stepsBeforeWidening = 0; // The number of steps that must be done before applying a widen operator
+
+ public int StepsBeforeWidening
+ {
+ get
+ {
+ Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() <= 9);
+ return this.stepsBeforeWidening;
+ }
+ set
+ {
+ Contract.Requires(0 <= value && value <= 9);
+ this.stepsBeforeWidening = value;
+ }
+ }
+
+ public string CivlDesugaredFile = null;
+ public bool TrustAtomicityTypes = false;
+ public bool TrustNonInterference = false;
+ public int TrustLayersUpto = -1;
+ public int TrustLayersDownto = int.MaxValue;
+
+ public enum VCVariety {
+ Structured,
+ Block,
+ Local,
+ BlockNested,
+ BlockReach,
+ BlockNestedReach,
+ Dag,
+ DagIterative,
+ Doomed,
+ Unspecified
+ }
+ public VCVariety vcVariety = VCVariety.Unspecified; // will not be Unspecified after command line has been parsed
+
+ public bool RemoveEmptyBlocks = true;
+ public bool CoalesceBlocks = true;
+ public bool PruneInfeasibleEdges = true;
+
+ [Rep]
+ public ProverFactory TheProverFactory;
+ public string ProverName;
+ [Peer]
+ private List<string> proverOptions = new List<string>();
+
+ public IEnumerable<string> ProverOptions
+ {
+ set
+ {
+ Contract.Requires(cce.NonNullElements(value));
+
+ this.proverOptions = new List<string>(value);
+ }
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string>>()));
+
+ foreach (string s in this.proverOptions)
+ yield return s;
+ }
+ }
+
+ [Obsolete("use the setter for 'ProverOptions' directly")]
+ public void AddProverOption(string option)
+ {
+ Contract.Requires(option != null);
+
+ this.ProverOptions = this.ProverOptions.Concat1(option);
+ }
+
+ [Obsolete("use the setter for 'ProverOptions' directly")]
+ public void RemoveAllProverOptions(Predicate<string> match)
+ {
+ this.ProverOptions = this.ProverOptions.Where(s => !match(s));
+ }
+
+ private int bracketIdsInVC = -1; // -1 - not specified, 0 - no, 1 - yes
+
+ public int BracketIdsInVC {
+ get {
+ Contract.Ensures(-1 <= Contract.Result<int>() && Contract.Result<int>() <= 1);
+ return this.bracketIdsInVC;
+ }
+ set {
+ Contract.Requires(-1 <= value && value <= 1);
+ this.bracketIdsInVC = value;
+ }
+ }
+
+ public bool CausalImplies = false;
+
+ public int SimplifyProverMatchDepth = -1; // -1 means not specified
+ public int ProverKillTime = -1; // -1 means not specified
+ public int SmokeTimeout = 10; // default to 10s
+ public int ProverCCLimit = 5;
+ public bool z3AtFlag = true;
+ public bool RestartProverPerVC = false;
+
+ public double VcsMaxCost = 1.0;
+ public double VcsPathJoinMult = 0.8;
+ public double VcsPathCostMult = 1.0;
+ public double VcsAssumeMult = 0.01;
+ public double VcsPathSplitMult = 0.5; // 0.5-always, 2-rarely do path splitting
+ public int VcsMaxSplits = 1;
+ public int VcsMaxKeepGoingSplits = 1;
+ public int VcsFinalAssertTimeout = 30;
+ public int VcsKeepGoingTimeout = 1;
+ public int VcsCores = 1;
+ public bool VcsDumpSplits = false;
+
+ public bool DebugRefuted = false;
+
+ public XmlSink XmlRefuted {
+ get {
+ if (DebugRefuted)
+ return XmlSink;
+ else
+ return null;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant4() {
+ Contract.Invariant(cce.NonNullElements(this.z3Options));
+ Contract.Invariant(0 <= Z3lets && Z3lets < 4);
+ }
+
+ [Peer]
+ private List<string> z3Options = new List<string>();
+
+ public IEnumerable<string> Z3Options
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IEnumerable<string>>() != null);
+ foreach (string s in z3Options)
+ yield return s;
+ }
+ }
+
+ public void AddZ3Option(string option)
+ {
+ Contract.Requires(option != null);
+ this.z3Options.Add(option);
+ }
+
+ public bool Z3types = false;
+ public int Z3lets = 3; // 0 - none, 1 - only LET TERM, 2 - only LET FORMULA, 3 - (default) any
+
+
+ // Maximum amount of virtual memory (in bytes) for the prover to use
+ //
+ // Non-positive number indicates unbounded.
+ public long MaxProverMemory = 100 * Megabyte;
+
+ // Minimum number of prover calls before restart
+ public int MinNumOfProverCalls = 5;
+
+ public enum PlatformType {
+ notSpecified,
+ v1,
+ v11,
+ v2,
+ cli1
+ }
+ public PlatformType TargetPlatform;
+ public string TargetPlatformLocation;
+ public string StandardLibraryLocation;
+
+ // whether procedure inlining is enabled at call sites.
+ public enum Inlining {
+ None,
+ Assert,
+ Assume,
+ Spec
+ };
+ public Inlining ProcedureInlining = Inlining.Assume;
+ public bool PrintInlined = false;
+ public bool ExtractLoops = false;
+ public bool DeterministicExtractLoops = false;
+ public string SecureVcGen = null;
+ public int StratifiedInlining = 0;
+ public string FixedPointEngine = null;
+ public int StratifiedInliningOption = 0;
+ public bool StratifiedInliningWithoutModels = false; // disable model generation for SI
+ public int StratifiedInliningVerbose = 0; // verbosity level
+ public int RecursionBound = 500;
+ public bool NonUniformUnfolding = false;
+ public int StackDepthBound = 0;
+ public string inferLeastForUnsat = null;
+
+ // Inference mode for fixed point engine
+ public enum FixedPointInferenceMode {
+ Corral,
+ OldCorral,
+ Flat,
+ Procedure,
+ Call
+ };
+ public FixedPointInferenceMode FixedPointMode = FixedPointInferenceMode.Procedure;
+
+ public string PrintFixedPoint = null;
+
+ public string PrintConjectures = null;
+
+ public bool ExtractLoopsUnrollIrreducible = true; // unroll irreducible loops? (set programmatically)
+
+ public enum TypeEncoding {
+ None,
+ Predicates,
+ Arguments,
+ Monomorphic
+ };
+ public TypeEncoding TypeEncodingMethod = TypeEncoding.Predicates;
+
+ public bool Monomorphize = false;
+
+ public bool ReflectAdd = false;
+
+ public int LiveVariableAnalysis = 1;
+
+ // Static constructor
+ static CommandLineOptions() {
+ if (System.Type.GetType("Mono.Runtime") == null) { // MONO
+ TraceListenerCollection/*!*/ dbl = Debug.Listeners;
+ Contract.Assert(dbl != null);
+ Contract.Assume(cce.IsPeerConsistent(dbl)); // hangs off static field
+ dbl.Add(new DefaultTraceListener());
+ }
+ }
+
+ public IEnumerable<string/*!*/> ProcsToCheck {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<string/*!*/>>(), true));
+ return this.procsToCheck != null ? this.procsToCheck.AsEnumerable() : null;
+ }
+ }
+
+ private List<string/*!*/> procsToCheck = null; // null means "no restriction"
+
+ [ContractInvariantMethod]
+ void ObjectInvariant5() {
+ Contract.Invariant(cce.NonNullElements(this.procsToCheck, true));
+ Contract.Invariant(Ai != null);
+ }
+
+ public class AiFlags {
+ public bool J_Trivial = false;
+ public bool J_Intervals = false;
+ public bool DebugStatistics = false;
+ }
+ public readonly AiFlags/*!*/ Ai = new AiFlags();
+
+ public class ConcurrentHoudiniOptions
+ {
+ public List<string> ProverOptions = new List<string>();
+ public int ProverCCLimit = 5;
+ public bool DisableLoopInvEntryAssert = false;
+ public bool DisableLoopInvMaintainedAssert = false;
+ public bool ModifyTopologicalSorting = false;
+ }
+ public List<ConcurrentHoudiniOptions> Cho = new List<ConcurrentHoudiniOptions>();
+
+ protected override bool ParseOption(string name, CommandLineOptionEngine.CommandLineParseState ps) {
+ var args = ps.args; // convenient synonym
+ switch (name) {
+ case "infer":
+ if (ps.ConfirmArgumentCount(1)) {
+ foreach (char c in cce.NonNull(args[ps.i])) {
+ switch (c) {
+ case 't':
+ Ai.J_Trivial = true;
+ UseAbstractInterpretation = true;
+ break;
+ case 'j':
+ Ai.J_Intervals = true;
+ UseAbstractInterpretation = true;
+ break;
+ case 's':
+ Ai.DebugStatistics = true;
+ UseAbstractInterpretation = true;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ StepsBeforeWidening = (int)char.GetNumericValue(c);
+ break;
+ default:
+ ps.Error("Invalid argument '{0}' to option {1}", c.ToString(), ps.s);
+ break;
+ }
+ }
+ }
+ return true;
+
+ case "noinfer":
+ if (ps.ConfirmArgumentCount(0)) {
+ UseAbstractInterpretation = false;
+ }
+ return true;
+
+ case "break":
+ case "launch":
+ if (ps.ConfirmArgumentCount(0)) {
+ System.Diagnostics.Debugger.Launch();
+ }
+ return true;
+
+ case "proc":
+ if (this.procsToCheck == null) {
+ this.procsToCheck = new List<string/*!*/>();
+ }
+ if (ps.ConfirmArgumentCount(1)) {
+ this.procsToCheck.Add(cce.NonNull(args[ps.i]));
+ }
+ return true;
+
+ case "xml":
+ if (ps.ConfirmArgumentCount(1)) {
+ XmlSinkFilename = args[ps.i];
+ }
+ return true;
+
+ case "print":
+ if (ps.ConfirmArgumentCount(1)) {
+ PrintFile = args[ps.i];
+ }
+ return true;
+
+ case "pretty":
+ int val = 1;
+ if (ps.GetNumericArgument(ref val, 2)) {
+ PrettyPrint = val == 1;
+ }
+ return true;
+
+ case "CivlDesugaredFile":
+ if (ps.ConfirmArgumentCount(1)) {
+ CivlDesugaredFile = args[ps.i];
+ }
+ return true;
+
+ case "trustLayersUpto":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ ps.GetNumericArgument(ref TrustLayersUpto);
+ }
+ return true;
+
+ case "trustLayersDownto":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ ps.GetNumericArgument(ref TrustLayersDownto);
+ }
+ return true;
+
+ case "proverLog":
+ if (ps.ConfirmArgumentCount(1)) {
+ SimplifyLogFilePath = args[ps.i];
+ }
+ return true;
+
+ case "proverPreamble":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ ProverPreamble = args[ps.i];
+ }
+ return true;
+
+ case "logPrefix":
+ if (ps.ConfirmArgumentCount(1)) {
+ string s = cce.NonNull(args[ps.i]);
+ LogPrefix += s.Replace('/', '-').Replace('\\', '-');
+ }
+ return true;
+
+ case "proverShutdownLimit":
+ ps.GetNumericArgument(ref ProverShutdownLimit);
+ return true;
+
+ case "errorTrace":
+ ps.GetNumericArgument(ref ErrorTrace, 3);
+ return true;
+
+ case "proverWarnings": {
+ int pw = 0;
+ if (ps.GetNumericArgument(ref pw, 3)) {
+ switch (pw) {
+ case 0:
+ PrintProverWarnings = ProverWarnings.None;
+ break;
+ case 1:
+ PrintProverWarnings = ProverWarnings.Stdout;
+ break;
+ case 2:
+ PrintProverWarnings = ProverWarnings.Stderr;
+ break;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // postcondition of GetNumericArgument guarantees that we don't get here
+ }
+ }
+ return true;
+ }
+
+ case "env": {
+ int e = 0;
+ if (ps.GetNumericArgument(ref e, 3)) {
+ switch (e) {
+ case 0:
+ ShowEnv = ShowEnvironment.Never;
+ break;
+ case 1:
+ ShowEnv = ShowEnvironment.DuringPrint;
+ break;
+ case 2:
+ ShowEnv = ShowEnvironment.Always;
+ break;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // postcondition of GetNumericArgument guarantees that we don't get here
+ }
+ }
+ return true;
+ }
+
+ case "loopUnroll":
+ ps.GetNumericArgument(ref LoopUnrollCount);
+ return true;
+
+ case "printModel":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i]) {
+ case "0":
+ PrintErrorModel = 0;
+ break;
+ case "1":
+ PrintErrorModel = 1;
+ break;
+ case "2":
+ PrintErrorModel = 2;
+ break;
+ case "4":
+ PrintErrorModel = 4;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+
+ case "mv":
+ if (ps.ConfirmArgumentCount(1)) {
+ ModelViewFile = args[ps.i];
+ }
+ return true;
+
+ case "printModelToFile":
+ if (ps.ConfirmArgumentCount(1)) {
+ PrintErrorModelFile = args[ps.i];
+ }
+ return true;
+
+ case "enhancedErrorMessages":
+ ps.GetNumericArgument(ref EnhancedErrorMessages, 2);
+ return true;
+
+ case "printCFG":
+ if (ps.ConfirmArgumentCount(1)) {
+ PrintCFGPrefix = args[ps.i];
+ }
+ return true;
+
+ case "inlineDepth":
+ ps.GetNumericArgument(ref InlineDepth);
+ return true;
+
+ case "subsumption": {
+ int s = 0;
+ if (ps.GetNumericArgument(ref s, 3)) {
+ switch (s) {
+ case 0:
+ UseSubsumption = SubsumptionOption.Never;
+ break;
+ case 1:
+ UseSubsumption = SubsumptionOption.NotForQuantifiers;
+ break;
+ case 2:
+ UseSubsumption = SubsumptionOption.Always;
+ break;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ } // postcondition of GetNumericArgument guarantees that we don't get here
+ }
+ }
+ return true;
+ }
+
+ case "liveVariableAnalysis": {
+ int lva = 0;
+ if (ps.GetNumericArgument(ref lva, 3)) {
+ LiveVariableAnalysis = lva;
+ }
+ return true;
+ }
+
+ case "removeEmptyBlocks": {
+ int reb = 0;
+ if (ps.GetNumericArgument(ref reb, 2)) {
+ RemoveEmptyBlocks = reb == 1;
+ }
+ return true;
+ }
+
+ case "coalesceBlocks": {
+ int cb = 0;
+ if (ps.GetNumericArgument(ref cb, 2)) {
+ CoalesceBlocks = cb == 1;
+ }
+ return true;
+ }
+
+ case "noPruneInfeasibleEdges": {
+ if (ps.ConfirmArgumentCount(0)) {
+ PruneInfeasibleEdges = false;
+ }
+ return true;
+ }
+
+ case "stagedHoudini": {
+ if (ps.ConfirmArgumentCount(1)) {
+ if(args[ps.i] == "COARSE" ||
+ args[ps.i] == "FINE" ||
+ args[ps.i] == "BALANCED") {
+ StagedHoudini = args[ps.i];
+ } else {
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ }
+ }
+ return true;
+ }
+
+ case "stagedHoudiniThreads": {
+ ps.GetNumericArgument(ref StagedHoudiniThreads);
+ return true;
+ }
+
+ case "stagedHoudiniReachabilityAnalysis": {
+ if (ps.ConfirmArgumentCount(0)) {
+ StagedHoudiniReachabilityAnalysis = true;
+ }
+ return true;
+ }
+
+ case "stagedHoudiniMergeIgnoredAnnotations": {
+ if (ps.ConfirmArgumentCount(0)) {
+ StagedHoudiniMergeIgnoredAnnotations = true;
+ }
+ return true;
+ }
+
+ case "debugStagedHoudini": {
+ if (ps.ConfirmArgumentCount(0)) {
+ DebugStagedHoudini = true;
+ }
+ return true;
+ }
+
+ case "variableDependenceIgnore": {
+ if (ps.ConfirmArgumentCount(1)) {
+ VariableDependenceIgnore = args[ps.i];
+ }
+ return true;
+ }
+
+ case "abstractHoudini":
+ {
+ if (ps.ConfirmArgumentCount(1))
+ {
+ AbstractHoudini = args[ps.i];
+ }
+ return true;
+ }
+ case "vc":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i]) {
+ case "s":
+ case "structured":
+ vcVariety = VCVariety.Structured;
+ break;
+ case "b":
+ case "block":
+ vcVariety = VCVariety.Block;
+ break;
+ case "l":
+ case "local":
+ vcVariety = VCVariety.Local;
+ break;
+ case "n":
+ case "nested":
+ vcVariety = VCVariety.BlockNested;
+ break;
+ case "m":
+ vcVariety = VCVariety.BlockNestedReach;
+ break;
+ case "r":
+ vcVariety = VCVariety.BlockReach;
+ break;
+ case "d":
+ case "dag":
+ vcVariety = VCVariety.Dag;
+ break;
+ case "i":
+ vcVariety = VCVariety.DagIterative;
+ break;
+ case "doomed":
+ vcVariety = VCVariety.Doomed;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+
+ case "prover":
+ if (ps.ConfirmArgumentCount(1)) {
+ TheProverFactory = ProverFactory.Load(cce.NonNull(args[ps.i]));
+ ProverName = cce.NonNull(args[ps.i]).ToUpper();
+ }
+ return true;
+
+ case "p":
+ case "proverOpt":
+ if (ps.ConfirmArgumentCount(1)) {
+ ProverOptions = ProverOptions.Concat1(cce.NonNull(args[ps.i]));
+ }
+ return true;
+
+ case "DoomStrategy":
+ ps.GetNumericArgument(ref DoomStrategy);
+ return true;
+
+ case "DoomRestartTP":
+ if (ps.ConfirmArgumentCount(0)) {
+ DoomRestartTP = true;
+ }
+ return true;
+
+ case "extractLoops":
+ if (ps.ConfirmArgumentCount(0)) {
+ ExtractLoops = true;
+ }
+ return true;
+
+ case "deterministicExtractLoops":
+ if (ps.ConfirmArgumentCount(0)) {
+ DeterministicExtractLoops = true;
+ }
+ return true;
+
+ case "inline":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i]) {
+ case "none":
+ ProcedureInlining = Inlining.None;
+ break;
+ case "assert":
+ ProcedureInlining = Inlining.Assert;
+ break;
+ case "assume":
+ ProcedureInlining = Inlining.Assume;
+ break;
+ case "spec":
+ ProcedureInlining = Inlining.Spec;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+ case "secure":
+ if (ps.ConfirmArgumentCount(1))
+ SecureVcGen = args[ps.i];
+ return true;
+ case "stratifiedInline":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i]) {
+ case "0":
+ StratifiedInlining = 0;
+ break;
+ case "1":
+ StratifiedInlining = 1;
+ break;
+ default:
+ StratifiedInlining = Int32.Parse(cce.NonNull(args[ps.i]));
+ //ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+ case "fixedPointEngine":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ FixedPointEngine = args[ps.i];
+ }
+ return true;
+ case "fixedPointInfer":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ switch (args[ps.i])
+ {
+ case "corral":
+ FixedPointMode = FixedPointInferenceMode.Corral;
+ break;
+ case "oldCorral":
+ FixedPointMode = FixedPointInferenceMode.OldCorral;
+ break;
+ case "flat":
+ FixedPointMode = FixedPointInferenceMode.Flat;
+ break;
+ case "procedure":
+ FixedPointMode = FixedPointInferenceMode.Procedure;
+ break;
+ case "call":
+ FixedPointMode = FixedPointInferenceMode.Call;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+ case "printFixedPoint":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ PrintFixedPoint = args[ps.i];
+ }
+ return true;
+ case "printConjectures":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ PrintConjectures = args[ps.i];
+ }
+ return true;
+ case "siVerbose":
+ if (ps.ConfirmArgumentCount(1)) {
+ StratifiedInliningVerbose = Int32.Parse(cce.NonNull(args[ps.i]));
+ }
+ return true;
+ case "recursionBound":
+ if (ps.ConfirmArgumentCount(1)) {
+ RecursionBound = Int32.Parse(cce.NonNull(args[ps.i]));
+ }
+ return true;
+ case "stackDepthBound":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ StackDepthBound = Int32.Parse(cce.NonNull(args[ps.i]));
+ }
+ return true;
+ case "stratifiedInlineOption":
+ if (ps.ConfirmArgumentCount(1)) {
+ StratifiedInliningOption = Int32.Parse(cce.NonNull(args[ps.i]));
+ }
+ return true;
+
+ case "inferLeastForUnsat":
+ if (ps.ConfirmArgumentCount(1)) {
+ inferLeastForUnsat = args[ps.i];
+ }
+ return true;
+
+ case "typeEncoding":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i]) {
+ case "n":
+ case "none":
+ TypeEncodingMethod = TypeEncoding.None;
+ break;
+ case "p":
+ case "predicates":
+ TypeEncodingMethod = TypeEncoding.Predicates;
+ break;
+ case "a":
+ case "arguments":
+ TypeEncodingMethod = TypeEncoding.Arguments;
+ break;
+ case "m":
+ case "monomorphic":
+ TypeEncodingMethod = TypeEncoding.Monomorphic;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+
+ case "instrumentInfer":
+ if (ps.ConfirmArgumentCount(1)) {
+ switch (args[ps.i]) {
+ case "e":
+ InstrumentInfer = InstrumentationPlaces.Everywhere;
+ break;
+ case "h":
+ InstrumentInfer = InstrumentationPlaces.LoopHeaders;
+ break;
+ default:
+ ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
+ break;
+ }
+ }
+ return true;
+
+ case "concurrentHoudini":
+ if (ps.ConfirmArgumentCount(0)) {
+ ConcurrentHoudini = true;
+ }
+ return true;
+
+ case "modifyTopologicalSorting":
+ if (ps.ConfirmArgumentCount(0)) {
+ ModifyTopologicalSorting = true;
+ }
+ return true;
+
+ case "debugConcurrentHoudini":
+ if (ps.ConfirmArgumentCount(0)) {
+ DebugConcurrentHoudini = true;
+ }
+ return true;
+
+ case "vcBrackets":
+ ps.GetNumericArgument(ref bracketIdsInVC, 2);
+ return true;
+
+ case "proverMemoryLimit": {
+ int d = 0;
+ if (ps.GetNumericArgument(ref d)) {
+ MaxProverMemory = d * Megabyte;
+ }
+ return true;
+ }
+
+ case "vcsMaxCost":
+ ps.GetNumericArgument(ref VcsMaxCost);
+ return true;
+
+ case "vcsPathJoinMult":
+ ps.GetNumericArgument(ref VcsPathJoinMult);
+ return true;
+
+ case "vcsPathCostMult":
+ ps.GetNumericArgument(ref VcsPathCostMult);
+ return true;
+
+ case "vcsAssumeMult":
+ ps.GetNumericArgument(ref VcsAssumeMult);
+ return true;
+
+ case "vcsPathSplitMult":
+ ps.GetNumericArgument(ref VcsPathSplitMult);
+ return true;
+
+ case "vcsMaxSplits":
+ ps.GetNumericArgument(ref VcsMaxSplits);
+ return true;
+
+ case "vcsMaxKeepGoingSplits":
+ ps.GetNumericArgument(ref VcsMaxKeepGoingSplits);
+ return true;
+
+ case "vcsFinalAssertTimeout":
+ ps.GetNumericArgument(ref VcsFinalAssertTimeout);
+ return true;
+
+ case "vcsKeepGoingTimeout":
+ ps.GetNumericArgument(ref VcsKeepGoingTimeout);
+ return true;
+
+ case "vcsCores":
+ ps.GetNumericArgument(ref VcsCores, a => 1 <= a);
+ return true;
+
+ case "vcsLoad":
+ double load = 0.0;
+ if (ps.GetNumericArgument(ref load)) {
+ if (3.0 <= load) {
+ ps.Error("surprisingly high load specified; got {0}, expected nothing above 3.0", load.ToString());
+ load = 3.0;
+ }
+ int p = (int)Math.Round(System.Environment.ProcessorCount * load);
+ VcsCores = p < 1 ? 1 : p;
+ }
+ return true;
+
+ case "simplifyMatchDepth":
+ ps.GetNumericArgument(ref SimplifyProverMatchDepth);
+ return true;
+
+ case "timeLimit":
+ ps.GetNumericArgument(ref ProverKillTime);
+ return true;
+
+ case "timeLimitPerAssertionInPercent":
+ ps.GetNumericArgument(ref TimeLimitPerAssertionInPercent, a => 0 < a);
+ return true;
+
+ case "smokeTimeout":
+ ps.GetNumericArgument(ref SmokeTimeout);
+ return true;
+
+ case "errorLimit":
+ ps.GetNumericArgument(ref ProverCCLimit);
+ return true;
+
+ case "verifySnapshots":
+ ps.GetNumericArgument(ref VerifySnapshots, 4);
+ return true;
+
+ case "traceCaching":
+ ps.GetNumericArgument(ref TraceCaching, 4);
+ return true;
+
+ case "useSmtOutputFormat": {
+ if (ps.ConfirmArgumentCount(0)) {
+ UseSmtOutputFormat = true;
+ }
+ return true;
+ }
+
+ case "z3opt":
+ if (ps.ConfirmArgumentCount(1)) {
+ AddZ3Option(cce.NonNull(args[ps.i]));
+ }
+ return true;
+
+ case "z3lets":
+ ps.GetNumericArgument(ref Z3lets, 4);
+ return true;
+
+ case "platform":
+ if (ps.ConfirmArgumentCount(1)) {
+ StringCollection platformOptions = this.ParseNamedArgumentList(args[ps.i]);
+ if (platformOptions != null && platformOptions.Count > 0) {
+ try {
+ this.TargetPlatform = (PlatformType)cce.NonNull(Enum.Parse(typeof(PlatformType), cce.NonNull(platformOptions[0])));
+ } catch {
+ ps.Error("Bad /platform type '{0}'", platformOptions[0]);
+ break;
+ }
+ if (platformOptions.Count > 1) {
+ this.TargetPlatformLocation = platformOptions[1];
+ if (!Directory.Exists(platformOptions[1])) {
+ ps.Error("/platform directory '{0}' does not exist", platformOptions[1]);
+ break;
+ }
+ }
+ }
+ }
+ return true;
+
+ case "z3exe":
+ if (ps.ConfirmArgumentCount(1)) {
+ Z3ExecutablePath = args[ps.i];
+ }
+ return true;
+ // This sets name of z3 binary boogie binary directory, not path
+ case "z3name":
+ if (ps.ConfirmArgumentCount(1))
+ {
+ Z3ExecutableName = args[ps.i];
+ }
+ return true;
+
+ case "cvc4exe":
+ if (ps.ConfirmArgumentCount(1)) {
+ CVC4ExecutablePath = args[ps.i];
+ }
+ return true;
+
+ case "kInductionDepth":
+ ps.GetNumericArgument(ref KInductionDepth);
+ return true;
+
+ default:
+ bool optionValue = false;
+ if (ps.CheckBooleanFlag("printUnstructured", ref optionValue)) {
+ PrintUnstructured = optionValue ? 1 : 0;
+ return true;
+ }
+
+ if (ps.CheckBooleanFlag("printDesugared", ref PrintDesugarings) ||
+ ps.CheckBooleanFlag("printInstrumented", ref PrintInstrumented) ||
+ ps.CheckBooleanFlag("printWithUniqueIds", ref PrintWithUniqueASTIds) ||
+ ps.CheckBooleanFlag("wait", ref Wait) ||
+ ps.CheckBooleanFlag("trace", ref Trace) ||
+ ps.CheckBooleanFlag("traceTimes", ref TraceTimes) ||
+ ps.CheckBooleanFlag("tracePOs", ref TraceProofObligations) ||
+ ps.CheckBooleanFlag("noResolve", ref NoResolve) ||
+ ps.CheckBooleanFlag("noTypecheck", ref NoTypecheck) ||
+ ps.CheckBooleanFlag("overlookTypeErrors", ref OverlookBoogieTypeErrors) ||
+ ps.CheckBooleanFlag("noVerify", ref Verify, false) ||
+ ps.CheckBooleanFlag("traceverify", ref TraceVerify) ||
+ ps.CheckBooleanFlag("alwaysAssumeFreeLoopInvariants", ref AlwaysAssumeFreeLoopInvariants, true) ||
+ ps.CheckBooleanFlag("nologo", ref DontShowLogo) ||
+ ps.CheckBooleanFlag("proverLogAppend", ref SimplifyLogFileAppend) ||
+ ps.CheckBooleanFlag("soundLoopUnrolling", ref SoundLoopUnrolling) ||
+ ps.CheckBooleanFlag("checkInfer", ref InstrumentWithAsserts) ||
+ ps.CheckBooleanFlag("interprocInfer", ref IntraproceduralInfer, false) ||
+ ps.CheckBooleanFlag("restartProver", ref RestartProverPerVC) ||
+ ps.CheckBooleanFlag("printInlined", ref PrintInlined) ||
+ ps.CheckBooleanFlag("smoke", ref SoundnessSmokeTest) ||
+ ps.CheckBooleanFlag("vcsDumpSplits", ref VcsDumpSplits) ||
+ ps.CheckBooleanFlag("dbgRefuted", ref DebugRefuted) ||
+ ps.CheckBooleanFlag("causalImplies", ref CausalImplies) ||
+ ps.CheckBooleanFlag("reflectAdd", ref ReflectAdd) ||
+ ps.CheckBooleanFlag("z3types", ref Z3types) ||
+ ps.CheckBooleanFlag("z3multipleErrors", ref z3AtFlag, false) ||
+ ps.CheckBooleanFlag("monomorphize", ref Monomorphize) ||
+ ps.CheckBooleanFlag("useArrayTheory", ref UseArrayTheory) ||
+ ps.CheckBooleanFlag("weakArrayTheory", ref WeakArrayTheory) ||
+ ps.CheckBooleanFlag("doModSetAnalysis", ref DoModSetAnalysis) ||
+ ps.CheckBooleanFlag("doNotUseLabels", ref UseLabels, false) ||
+ ps.CheckBooleanFlag("runDiagnosticsOnTimeout", ref RunDiagnosticsOnTimeout) ||
+ ps.CheckBooleanFlag("traceDiagnosticsOnTimeout", ref TraceDiagnosticsOnTimeout) ||
+ ps.CheckBooleanFlag("boolControlVC", ref SIBoolControlVC, true) ||
+ ps.CheckBooleanFlag("contractInfer", ref ContractInfer) ||
+ ps.CheckBooleanFlag("explainHoudini", ref ExplainHoudini) ||
+ ps.CheckBooleanFlag("reverseHoudiniWorklist", ref ReverseHoudiniWorklist) ||
+ ps.CheckBooleanFlag("crossDependencies", ref HoudiniUseCrossDependencies) ||
+ ps.CheckBooleanFlag("useUnsatCoreForContractInfer", ref UseUnsatCoreForContractInfer) ||
+ ps.CheckBooleanFlag("printAssignment", ref PrintAssignment) ||
+ ps.CheckBooleanFlag("printNecessaryAssumes", ref PrintNecessaryAssumes) ||
+ ps.CheckBooleanFlag("useProverEvaluate", ref UseProverEvaluate) ||
+ ps.CheckBooleanFlag("nonUniformUnfolding", ref NonUniformUnfolding) ||
+ ps.CheckBooleanFlag("deterministicExtractLoops", ref DeterministicExtractLoops) ||
+ ps.CheckBooleanFlag("verifySeparately", ref VerifySeparately) ||
+ ps.CheckBooleanFlag("trustAtomicityTypes", ref TrustAtomicityTypes) ||
+ ps.CheckBooleanFlag("trustNonInterference", ref TrustNonInterference) ||
+ ps.CheckBooleanFlag("useBaseNameForFileName", ref UseBaseNameForFileName)
+ ) {
+ // one of the boolean flags matched
+ return true;
+ }
+ break;
+ }
+
+ return base.ParseOption(name, ps); // defer to superclass
+ }
+
+ public override void ApplyDefaultOptions() {
+ Contract.Ensures(TheProverFactory != null);
+ Contract.Ensures(vcVariety != VCVariety.Unspecified);
+
+ base.ApplyDefaultOptions();
+
+ // expand macros in filenames, now that LogPrefix is fully determined
+ ExpandFilename(ref XmlSinkFilename, LogPrefix, FileTimestamp);
+ ExpandFilename(ref PrintFile, LogPrefix, FileTimestamp);
+ ExpandFilename(ref SimplifyLogFilePath, LogPrefix, FileTimestamp);
+ ExpandFilename(ref PrintErrorModelFile, LogPrefix, FileTimestamp);
+
+ Contract.Assume(XmlSink == null); // XmlSink is to be set here
+ if (XmlSinkFilename != null) {
+ XmlSink = new XmlSink(XmlSinkFilename);
+ }
+
+ if (TheProverFactory == null) {
+ TheProverFactory = ProverFactory.Load("SMTLib");
+ ProverName = "SMTLib".ToUpper();
+ }
+
+ var proverOpts = TheProverFactory.BlankProverOptions();
+ proverOpts.Parse(ProverOptions);
+ if (!TheProverFactory.SupportsLabels(proverOpts)) {
+ UseLabels = false;
+ }
+
+ if (vcVariety == VCVariety.Unspecified) {
+ vcVariety = TheProverFactory.DefaultVCVariety;
+ }
+
+ if (UseArrayTheory) {
+ Monomorphize = true;
+ }
+
+ if (inferLeastForUnsat != null) {
+ StratifiedInlining = 1;
+ }
+
+ if (StratifiedInlining > 0) {
+ TypeEncodingMethod = TypeEncoding.Monomorphic;
+ UseArrayTheory = true;
+ UseAbstractInterpretation = false;
+ MaxProverMemory = 0; // no max: avoids restarts
+ if (ProverName == "Z3API" || ProverName == "SMTLIB") {
+ ProverCCLimit = 1;
+ }
+ if (UseProverEvaluate)
+ StratifiedInliningWithoutModels = true;
+ }
+
+ if (Trace) {
+ BoogieDebug.DoPrinting = true; // reuse the -trace option for debug printing
+ }
+ }
+
+
+
+ public bool UserWantsToCheckRoutine(string methodFullname) {
+ Contract.Requires(methodFullname != null);
+ if (ProcsToCheck == null) {
+ // no preference
+ return true;
+ }
+ return ProcsToCheck.Any(s => Regex.IsMatch(methodFullname, "^" + Regex.Escape(s).Replace(@"\*", ".*") + "$"));
+ }
+
+ public virtual StringCollection ParseNamedArgumentList(string argList) {
+ if (argList == null || argList.Length == 0)
+ return null;
+ StringCollection result = new StringCollection();
+ int i = 0;
+ for (int n = argList.Length; i < n; ) {
+ cce.LoopInvariant(0 <= i);
+ int separatorIndex = this.GetArgumentSeparatorIndex(argList, i);
+ if (separatorIndex > i) {
+ result.Add(argList.Substring(i, separatorIndex - i));
+ i = separatorIndex + 1;
+ continue;
+ }
+ result.Add(argList.Substring(i));
+ break;
+ }
+ return result;
+ }
+ public int GetArgumentSeparatorIndex(string argList, int startIndex) {
+ Contract.Requires(argList != null);
+ Contract.Requires(0 <= startIndex && startIndex <= argList.Length);
+ Contract.Ensures(Contract.Result<int>() < argList.Length);
+ int commaIndex = argList.IndexOf(",", startIndex);
+ int semicolonIndex = argList.IndexOf(";", startIndex);
+ if (commaIndex == -1)
+ return semicolonIndex;
+ if (semicolonIndex == -1)
+ return commaIndex;
+ if (commaIndex < semicolonIndex)
+ return commaIndex;
+ return semicolonIndex;
+ }
+
+ public override void AttributeUsage() {
+ Console.WriteLine(
+@"Boogie: The following attributes are supported by this implementation.
+
+ ---- On top-level declarations ---------------------------------------------
+
+ {:ignore}
+ Ignore the declaration (after checking for duplicate names).
+
+ {:extern}
+ If two top-level declarations introduce the same name (for example, two
+ constants with the same name or two procedures with the same name), then
+ Boogie usually produces an error message. However, if at least one of
+ the declarations is declared with :extern, one of the declarations is
+ ignored. If both declarations are :extern, Boogie arbitrarily chooses
+ one of them to keep; otherwise, Boogie ignore the :extern declaration
+ and keeps the other.
+
+ {:checksum <string>}
+ Attach a checksum to be used for verification result caching.
+
+ ---- On implementations and procedures -------------------------------------
+
+ {:inline N}
+ Inline given procedure (can be also used on implementation).
+ N should be a non-negative number and represents the inlining depth.
+ With /inline:assume call is replaced with ""assume false"" once inlining depth is reached.
+ With /inline:assert call is replaced with ""assert false"" once inlining depth is reached.
+ With /inline:spec call is left as is once inlining depth is reached.
+ With the above three options, methods with the attribute {:inline N} are not verified.
+ With /inline:none the entire attribute is ignored.
+
+ {:verify false}
+ Skip verification of an implementation.
+
+ {:vcs_max_cost N}
+ {:vcs_max_splits N}
+ {:vcs_max_keep_going_splits N}
+ Per-implementation versions of
+ /vcsMaxCost, /vcsMaxSplits and /vcsMaxKeepGoingSplits.
+
+ {:selective_checking true}
+ Turn all asserts into assumes except for the ones reachable from
+ assumptions marked with the attribute {:start_checking_here}.
+ Thus, ""assume {:start_checking_here} something;"" becomes an inverse
+ of ""assume false;"": the first one disables all verification before
+ it, and the second one disables all verification after.
+
+ {:priority N}
+ Assign a positive priority 'N' to an implementation to control the order
+ in which implementations are verified (default: N = 1).
+
+ {:id <string>}
+ Assign a unique ID to an implementation to be used for verification
+ result caching (default: ""<impl. name>:0"").
+
+ {:timeLimit N}
+ Set the time limit for a given implementation.
+
+ ---- On functions ----------------------------------------------------------
+
+ {:builtin ""spec""}
+ {:bvbuiltin ""spec""}
+ Rewrite the function to built-in prover function symbol 'fn'.
+
+ {:inline}
+ {:inline true}
+ Expand function according to its definition before going to the prover.
+
+ {:never_pattern true}
+ Terms starting with this function symbol will never be
+ automatically selected as patterns. It does not prevent them
+ from being used inside the triggers, and does not affect explicit
+ trigger annotations. Internally it works by adding {:nopats ...}
+ annotations to quantifiers.
+
+ {:identity}
+ {:identity true}
+ If the function has 1 argument and the use of it has type X->X for
+ some X, then the abstract interpreter will treat the function as an
+ identity function. Note, the abstract interpreter trusts the
+ attribute--it does not try to verify that the function really is an
+ identity function.
+
+ ---- On variables ----------------------------------------------------------
+
+ {:existential true}
+ Marks a global Boolean variable as existentially quantified. If
+ used in combination with option /contractInfer Boogie will check
+ whether there exists a Boolean assignment to the existentials
+ that makes all verification conditions valid. Without option
+ /contractInfer the attribute is ignored.
+
+ ---- On assert statements --------------------------------------------------
+
+ {:subsumption n}
+ Overrides the /subsumption command-line setting for this assertion.
+
+ {:split_here}
+ Verifies code leading to this point and code leading from this point
+ to the next split_here as separate pieces. May help with timeouts.
+ May also occasionally double-report errors.
+
+ ---- The end ---------------------------------------------------------------
+");
+ }
+
+ public override void Usage() {
+ Console.WriteLine(@"
+ /nologo suppress printing of version number, copyright message
+ /env:<n> print command line arguments
+ 0 - never, 1 (default) - during BPL print and prover log,
+ 2 - like 1 and also to standard output
+ /wait await Enter from keyboard before terminating program
+ /xml:<file> also produce output in XML format to <file>
+
+ ---- Boogie options --------------------------------------------------------
+
+ Multiple .bpl files supplied on the command line are concatenated into one
+ Boogie program.
+
+ /proc:<p> : Only check procedures matched by pattern <p>. This option
+ may be specified multiple times to match multiple patterns.
+ The pattern <p> matches the whole procedure name (i.e.
+ pattern ""foo"" will only match a procedure called foo and
+ not fooBar). The pattern <p> may contain * wildcards which
+ match any character zero or more times. For example the
+ pattern ""ab*d"" would match abd, abcd and abccd but not
+ Aabd nor abdD. The pattern ""*ab*d*"" would match abd,
+ abcd, abccd, Abd and abdD.
+ /noResolve : parse only
+ /noTypecheck : parse and resolve only
+
+ /print:<file> : print Boogie program after parsing it
+ (use - as <file> to print to console)
+ /pretty:<n>
+ 0 - print each Boogie statement on one line (faster).
+ 1 (default) - pretty-print with some line breaks.
+ /printWithUniqueIds : print augmented information that uniquely
+ identifies variables
+ /printUnstructured : with /print option, desugars all structured statements
+ /printDesugared : with /print option, desugars calls
+
+ /overlookTypeErrors : skip any implementation with resolution or type
+ checking errors
+
+ /loopUnroll:<n>
+ unroll loops, following up to n back edges (and then some)
+ /soundLoopUnrolling
+ sound loop unrolling
+ /printModel:<n>
+ 0 (default) - do not print Z3's error model
+ 1 - print Z3's error model
+ 2 - print Z3's error model plus reverse mappings
+ 4 - print Z3's error model in a more human readable way
+ /printModelToFile:<file>
+ print model to <file> instead of console
+ /mv:<file> Specify file where to save the model in BVD format
+ /enhancedErrorMessages:<n>
+ 0 (default) - no enhanced error messages
+ 1 - Z3 error model enhanced error messages
+
+ /printCFG:<prefix> : print control flow graph of each implementation in
+ Graphviz format to files named:
+ <prefix>.<procedure name>.dot
+
+ /useBaseNameForFileName : When parsing use basename of file for tokens instead
+ of the path supplied on the command line
+
+ ---- Inference options -----------------------------------------------------
+
+ /infer:<flags>
+ use abstract interpretation to infer invariants
+ The default is /infer:i"
+ // This is not 100% true, as the /infer ALWAYS creates
+ // a multilattice, whereas if nothing is specified then
+ // intervals are isntantiated WITHOUT being embedded in
+ // a multilattice
+ + @"
+ <flags> are as follows (missing <flags> means all)
+ i = intervals
+ c = constant propagation
+ d = dynamic type
+ n = nullness
+ p = polyhedra for linear inequalities
+ t = trivial bottom/top lattice (cannot be combined with
+ other domains)
+ j = stronger intervals (cannot be combined with other
+ domains)
+ or the following (which denote options, not domains):
+ s = debug statistics
+ 0..9 = number of iterations before applying a widen (default=0)
+ /noinfer turn off the default inference, and overrides the /infer
+ switch on its left
+ /checkInfer instrument inferred invariants as asserts to be checked by
+ theorem prover
+ /interprocInfer
+ perform interprocedural inference (deprecated, not supported)
+ /contractInfer
+ perform procedure contract inference
+ /instrumentInfer
+ h - instrument inferred invariants only at beginning of
+ loop headers (default)
+ e - instrument inferred invariants at beginning and end
+ of every block (this mode is intended for use in
+ debugging of abstract domains)
+ /printInstrumented
+ print Boogie program after it has been instrumented with
+ invariants
+
+ ---- Debugging and general tracing options ---------------------------------
+
+ /trace blurt out various debug trace information
+ /traceTimes output timing information at certain points in the pipeline
+ /tracePOs output information about the number of proof obligations
+ (also included in the /trace output)
+ /log[:method] Print debug output during translation
+
+ /break launch and break into debugger
+
+ ---- Verification-condition generation options -----------------------------
+
+ /liveVariableAnalysis:<c>
+ 0 = do not perform live variable analysis
+ 1 = perform live variable analysis (default)
+ 2 = perform interprocedural live variable analysis
+ /noVerify skip VC generation and invocation of the theorem prover
+ /verifySnapshots:<n>
+ verify several program snapshots (named <filename>.v0.bpl
+ to <filename>.vN.bpl) using verification result caching:
+ 0 - do not use any verification result caching (default)
+ 1 - use the basic verification result caching
+ 2 - use the more advanced verification result caching
+ 3 - use the more advanced caching and report errors according
+ to the new source locations for errors and their
+ related locations (but not /errorTrace and CaptureState
+ locations)
+ /verifySeparately
+ verify each input program separately
+ /removeEmptyBlocks:<c>
+ 0 - do not remove empty blocks during VC generation
+ 1 - remove empty blocks (default)
+ /coalesceBlocks:<c>
+ 0 = do not coalesce blocks
+ 1 = coalesce blocks (default)
+ /vc:<variety> n = nested block (default for /prover:Simplify),
+ m = nested block reach,
+ b = flat block, r = flat block reach,
+ s = structured, l = local,
+ d = dag (default, except with /prover:Simplify)
+ doomed = doomed
+ /traceverify print debug output during verification condition generation
+ /subsumption:<c>
+ apply subsumption to asserted conditions:
+ 0 - never, 1 - not for quantifiers, 2 (default) - always
+ /alwaysAssumeFreeLoopInvariants
+ usually, a free loop invariant (or assume
+ statement in that position) is ignored in checking contexts
+ (like other free things); this option includes these free
+ loop invariants as assumes in both contexts
+ /inline:<i> use inlining strategy <i> for procedures with the :inline
+ attribute, see /attrHelp for details:
+ none
+ assume (default)
+ assert
+ spec
+ /printInlined
+ print the implementation after inlining calls to
+ procedures with the :inline attribute (works with /inline)
+ /lazyInline:1
+ Use the lazy inlining algorithm
+ /stratifiedInline:1
+ Use the stratified inlining algorithm
+ /fixedPointEngine:<engine>
+ Use the specified fixed point engine for inference
+ /recursionBound:<n>
+ Set the recursion bound for stratified inlining to
+ be n (default 500)
+ /inferLeastForUnsat:<str>
+ Infer the least number of constants (whose names
+ are prefixed by <str>) that need to be set to
+ true for the program to be correct. This turns
+ on stratified inlining.
+ /smoke Soundness Smoke Test: try to stick assert false; in some
+ places in the BPL and see if we can still prove it
+ /smokeTimeout:<n>
+ Timeout, in seconds, for a single theorem prover
+ invocation during smoke test, defaults to 10.
+ /causalImplies
+ Translate Boogie's A ==> B into prover's A ==> A && B.
+ /typeEncoding:<m>
+ how to encode types when sending VC to theorem prover
+ n = none (unsound)
+ p = predicates (default)
+ a = arguments
+ m = monomorphic
+ /monomorphize
+ Do not abstract map types in the encoding (this is an
+ experimental feature that will not do the right thing if
+ the program uses polymorphism)
+ /reflectAdd In the VC, generate an auxiliary symbol, elsewhere defined
+ to be +, instead of +.
+
+ ---- Verification-condition splitting --------------------------------------
+
+ /vcsMaxCost:<f>
+ VC will not be split unless the cost of a VC exceeds this
+ number, defaults to 2000.0. This does NOT apply in the
+ keep-going mode after first round of splitting.
+ /vcsMaxSplits:<n>
+ Maximal number of VC generated per method. In keep
+ going mode only applies to the first round.
+ Defaults to 1.
+ /vcsMaxKeepGoingSplits:<n>
+ If set to more than 1, activates the keep
+ going mode, where after the first round of splitting,
+ VCs that timed out are split into <n> pieces and retried
+ until we succeed proving them, or there is only one
+ assertion on a single path and it timeouts (in which
+ case error is reported for that assertion).
+ Defaults to 1.
+ /vcsKeepGoingTimeout:<n>
+ Timeout in seconds for a single theorem prover
+ invocation in keep going mode, except for the final
+ single-assertion case. Defaults to 1s.
+ /vcsFinalAssertTimeout:<n>
+ Timeout in seconds for the single last
+ assertion in the keep going mode. Defaults to 30s.
+ /vcsPathJoinMult:<f>
+ If more than one path join at a block, by how much
+ multiply the number of paths in that block, to accomodate
+ for the fact that the prover will learn something on one
+ paths, before proceeding to another. Defaults to 0.8.
+ /vcsPathCostMult:<f1>
+ /vcsAssumeMult:<f2>
+ The cost of a block is
+ (<assert-cost> + <f2>*<assume-cost>) *
+ (1.0 + <f1>*<entering-paths>)
+ <f1> defaults to 1.0, <f2> defaults to 0.01.
+ The cost of a single assertion or assumption is
+ currently always 1.0.
+ /vcsPathSplitMult:<f>
+ If the best path split of a VC of cost A is into
+ VCs of cost B and C, then the split is applied if
+ A >= <f>*(B+C), otherwise assertion splitting will be
+ applied. Defaults to 0.5 (always do path splitting if
+ possible), set to more to do less path splitting
+ and more assertion splitting.
+ /vcsDumpSplits
+ For split #n dump split.n.dot and split.n.bpl.
+ Warning: Affects error reporting.
+ /vcsCores:<n>
+ Try to verify <n> VCs at once. Defaults to 1.
+ /vcsLoad:<f> Sets vcsCores to the machine's ProcessorCount * f,
+ rounded to the nearest integer (where 0.0 <= f <= 3.0),
+ but never to less than 1.
+
+ ---- Prover options --------------------------------------------------------
+
+ /errorLimit:<num>
+ Limit the number of errors produced for each procedure
+ (default is 5, some provers may support only 1)
+ /timeLimit:<num>
+ Limit the number of seconds spent trying to verify
+ each procedure
+ /errorTrace:<n>
+ 0 - no Trace labels in the error output,
+ 1 (default) - include useful Trace labels in error output,
+ 2 - include all Trace labels in the error output
+ /vcBrackets:<b>
+ bracket odd-charactered identifier names with |'s. <b> is:
+ 0 - no (default with non-/prover:Simplify),
+ 1 - yes (default with /prover:Simplify)
+ /prover:<tp> use theorem prover <tp>, where <tp> is either the name of
+ a DLL containing the prover interface located in the
+ Boogie directory, or a full path to a DLL containing such
+ an interface. The standard interfaces shipped include:
+ SMTLib (default, uses the SMTLib2 format and calls Z3)
+ Z3 (uses Z3 with the Simplify format)
+ Simplify
+ ContractInference (uses Z3)
+ Z3api (Z3 using Managed .NET API)
+ /proverOpt:KEY[=VALUE]
+ Provide a prover-specific option (short form /p).
+ /proverLog:<file>
+ Log input for the theorem prover. Like filenames
+ supplied as arguments to other options, <file> can use the
+ following macros:
+ @TIME@ expands to the current time
+ @PREFIX@ expands to the concatenation of strings given
+ by /logPrefix options
+ @FILE@ expands to the last filename specified on the
+ command line
+ In addition, /proverLog can also use the macro '@PROC@',
+ which causes there to be one prover log file per
+ verification condition, and the macro then expands to the
+ name of the procedure that the verification condition is for.
+ /logPrefix:<str>
+ Defines the expansion of the macro '@PREFIX@', which can
+ be used in various filenames specified by other options.
+ /proverLogAppend
+ Append (not overwrite) the specified prover log file
+ /proverWarnings
+ 0 (default) - don't print, 1 - print to stdout,
+ 2 - print to stderr
+ /proverMemoryLimit:<num>
+ Limit on the virtual memory for prover before
+ restart in MB (default:100MB)
+ /restartProver
+ Restart the prover after each query
+ /proverShutdownLimit<num>
+ Time between closing the stream to the prover and
+ killing the prover process (default: 0s)
+ /platform:<ptype>,<location>
+ ptype = v11,v2,cli1
+ location = platform libraries directory
+
+ Simplify specific options:
+ /simplifyMatchDepth:<num>
+ Set Simplify prover's matching depth limit
+
+ Z3 specific options:
+ /z3opt:<arg> specify additional Z3 options
+ /z3multipleErrors
+ report multiple counterexamples for each error
+ /useArrayTheory
+ use Z3's native theory (as opposed to axioms). Currently
+ implies /monomorphize.
+ /useSmtOutputFormat
+ Z3 outputs a model in the SMTLIB2 format.
+ /z3types generate multi-sorted VC that make use of Z3 types
+ /z3lets:<n> 0 - no LETs, 1 - only LET TERM, 2 - only LET FORMULA,
+ 3 - (default) any
+ /z3exe:<path>
+ path to Z3 executable
+
+ CVC4 specific options:
+ /cvc4exe:<path>
+ path to CVC4 executable
+");
+ }
+ }
+}
diff --git a/Source/Core/Core.csproj b/Source/Core/Core.csproj
index fbb23cfe..7c4cb7ae 100644
--- a/Source/Core/Core.csproj
+++ b/Source/Core/Core.csproj
@@ -1,236 +1,236 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{B230A69C-C466-4065-B9C1-84D80E76D802}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Core</RootNamespace>
- <AssemblyName>Core</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Core.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Core.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Numerics" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Absy.cs" />
- <Compile Include="AbsyCmd.cs" />
- <Compile Include="AbsyExpr.cs" />
- <Compile Include="AbsyQuant.cs" />
- <Compile Include="AbsyType.cs" />
- <Compile Include="AlphaEquality.cs" />
- <Compile Include="InterProceduralReachabilityGraph.cs" />
- <Compile Include="CommandLineOptions.cs" />
- <Compile Include="DeadVarElim.cs" />
- <Compile Include="Duplicator.cs" />
- <Compile Include="Inline.cs" />
- <Compile Include="LambdaHelper.cs" />
- <Compile Include="LoopUnroll.cs" />
- <Compile Include="OOLongUtil.cs" />
- <Compile Include="Parser.cs" />
- <Compile Include="ResolutionContext.cs" />
- <Compile Include="Scanner.cs" />
- <Compile Include="StandardVisitor.cs" />
- <Compile Include="TypeAmbiguitySeeker.cs" />
- <Compile Include="Util.cs" />
- <Compile Include="VariableDependenceAnalyser.cs" />
- <Compile Include="VCExp.cs" />
- <Compile Include="..\version.cs" />
- <Compile Include="Xml.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <ItemGroup>
- <None Include="BoogiePL.atg" />
- </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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B230A69C-C466-4065-B9C1-84D80E76D802}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Core</RootNamespace>
+ <AssemblyName>BoogieCore</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for Core.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Core.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Numerics" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Absy.cs" />
+ <Compile Include="AbsyCmd.cs" />
+ <Compile Include="AbsyExpr.cs" />
+ <Compile Include="AbsyQuant.cs" />
+ <Compile Include="AbsyType.cs" />
+ <Compile Include="AlphaEquality.cs" />
+ <Compile Include="InterProceduralReachabilityGraph.cs" />
+ <Compile Include="CommandLineOptions.cs" />
+ <Compile Include="DeadVarElim.cs" />
+ <Compile Include="Duplicator.cs" />
+ <Compile Include="Inline.cs" />
+ <Compile Include="LambdaHelper.cs" />
+ <Compile Include="LoopUnroll.cs" />
+ <Compile Include="OOLongUtil.cs" />
+ <Compile Include="Parser.cs" />
+ <Compile Include="ResolutionContext.cs" />
+ <Compile Include="Scanner.cs" />
+ <Compile Include="StandardVisitor.cs" />
+ <Compile Include="TypeAmbiguitySeeker.cs" />
+ <Compile Include="Util.cs" />
+ <Compile Include="VariableDependenceAnalyser.cs" />
+ <Compile Include="VCExp.cs" />
+ <Compile Include="..\version.cs" />
+ <Compile Include="Xml.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="BoogiePL.atg" />
+ </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/Core/DeadVarElim.cs b/Source/Core/DeadVarElim.cs
index 77086f0f..fc39debb 100644
--- a/Source/Core/DeadVarElim.cs
+++ b/Source/Core/DeadVarElim.cs
@@ -1,1753 +1,1762 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-
-
-namespace Microsoft.Boogie {
- public class UnusedVarEliminator : VariableCollector {
- public static void Eliminate(Program program) {
- Contract.Requires(program != null);
- UnusedVarEliminator elim = new UnusedVarEliminator();
- elim.Visit(program);
- }
-
- private UnusedVarEliminator()
- : base() {
-
- }
-
- public override Implementation VisitImplementation(Implementation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- //Console.WriteLine("Procedure {0}", node.Name);
- Implementation/*!*/ impl = base.VisitImplementation(node);
- Contract.Assert(impl != null);
- //Console.WriteLine("Old number of local variables = {0}", impl.LocVars.Length);
- List<Variable>/*!*/ vars = new List<Variable>();
- foreach (Variable/*!*/ var in impl.LocVars) {
- Contract.Assert(var != null);
- if (_usedVars.Contains(var))
- vars.Add(var);
- }
- impl.LocVars = vars;
- //Console.WriteLine("New number of local variables = {0}", impl.LocVars.Length);
- //Console.WriteLine("---------------------------------");
- _usedVars.Clear();
- return impl;
- }
- }
-
- public class ModSetCollector : ReadOnlyVisitor {
- private Procedure enclosingProc;
- private Dictionary<Procedure/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ modSets;
- private HashSet<Procedure> yieldingProcs;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(modSets));
- Contract.Invariant(Contract.ForAll(modSets.Values, v => cce.NonNullElements(v)));
- }
-
- public ModSetCollector() {
- modSets = new Dictionary<Procedure/*!*/, HashSet<Variable/*!*/>/*!*/>();
- yieldingProcs = new HashSet<Procedure>();
- }
-
- private bool moreProcessingRequired;
-
- public void DoModSetAnalysis(Program program) {
- Contract.Requires(program != null);
-
- if (CommandLineOptions.Clo.Trace)
- {
-// Console.WriteLine();
-// Console.WriteLine("Running modset analysis ...");
-// int procCount = 0;
-// foreach (Declaration/*!*/ decl in program.TopLevelDeclarations)
-// {
-// Contract.Assert(decl != null);
-// if (decl is Procedure)
-// procCount++;
-// }
-// Console.WriteLine("Number of procedures = {0}", procCount);*/
- }
-
- HashSet<Procedure/*!*/> implementedProcs = new HashSet<Procedure/*!*/>();
- foreach (var impl in program.Implementations) {
- if (impl.Proc != null)
- implementedProcs.Add(impl.Proc);
- }
- foreach (var proc in program.Procedures) {
- if (!implementedProcs.Contains(proc))
- {
- enclosingProc = proc;
- foreach (var expr in proc.Modifies)
- {
- Contract.Assert(expr != null);
- ProcessVariable(expr.Decl);
- }
- enclosingProc = null;
- }
- else
- {
- modSets.Add(proc, new HashSet<Variable>());
- }
- }
-
- moreProcessingRequired = true;
- while (moreProcessingRequired) {
- moreProcessingRequired = false;
- this.Visit(program);
- }
-
- foreach (Procedure x in modSets.Keys)
- {
- x.Modifies = new List<IdentifierExpr>();
- foreach (Variable v in modSets[x])
- {
- x.Modifies.Add(new IdentifierExpr(v.tok, v));
- }
- }
- foreach (Procedure x in yieldingProcs)
- {
- if (!QKeyValue.FindBoolAttribute(x.Attributes, "yields"))
- {
- x.AddAttribute("yields");
- }
- }
-
-#if DEBUG_PRINT
- Console.WriteLine("Number of procedures with nonempty modsets = {0}", modSets.Keys.Count);
- foreach (Procedure/*!*/ x in modSets.Keys) {
- Contract.Assert(x != null);
- Console.Write("{0} : ", x.Name);
- bool first = true;
- foreach (Variable/*!*/ y in modSets[x]) {
- Contract.Assert(y != null);
- if (first)
- first = false;
- else
- Console.Write(", ");
- Console.Write("{0}", y.Name);
- }
- Console.WriteLine("");
- }
-#endif
- }
-
- public override Implementation VisitImplementation(Implementation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- enclosingProc = node.Proc;
- Implementation/*!*/ ret = base.VisitImplementation(node);
- Contract.Assert(ret != null);
- enclosingProc = null;
-
- return ret;
- }
- public override YieldCmd VisitYieldCmd(YieldCmd node)
- {
- if (!yieldingProcs.Contains(enclosingProc))
- {
- yieldingProcs.Add(enclosingProc);
- moreProcessingRequired = true;
- }
- return base.VisitYieldCmd(node);
- }
- public override Cmd VisitAssignCmd(AssignCmd assignCmd) {
- //Contract.Requires(assignCmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Cmd ret = base.VisitAssignCmd(assignCmd);
- foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) {
- Contract.Assert(lhs != null);
- ProcessVariable(lhs.DeepAssignedVariable);
- }
- return ret;
- }
- public override Cmd VisitHavocCmd(HavocCmd havocCmd) {
- //Contract.Requires(havocCmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Cmd ret = base.VisitHavocCmd(havocCmd);
- foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) {
- Contract.Assert(expr != null);
- ProcessVariable(expr.Decl);
- }
- return ret;
- }
- public override Cmd VisitCallCmd(CallCmd callCmd) {
- //Contract.Requires(callCmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Cmd ret = base.VisitCallCmd(callCmd);
- foreach (IdentifierExpr ie in callCmd.Outs)
- {
- if (ie != null) ProcessVariable(ie.Decl);
- }
- Procedure callee = callCmd.Proc;
- if (callee == null)
- return ret;
- if (modSets.ContainsKey(callee)) {
- foreach (Variable var in modSets[callee]) {
- ProcessVariable(var);
- }
- }
- if (!yieldingProcs.Contains(enclosingProc) && (yieldingProcs.Contains(callCmd.Proc) || callCmd.IsAsync))
- {
- yieldingProcs.Add(enclosingProc);
- moreProcessingRequired = true;
- }
- if (callCmd.IsAsync)
- {
- if (!yieldingProcs.Contains(callCmd.Proc))
- {
- yieldingProcs.Add(callCmd.Proc);
- moreProcessingRequired = true;
- }
- }
- return ret;
- }
- public override Cmd VisitParCallCmd(ParCallCmd node)
- {
- //Contract.Requires(callCmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Cmd ret = base.VisitParCallCmd(node);
- if (!yieldingProcs.Contains(enclosingProc))
- {
- yieldingProcs.Add(enclosingProc);
- moreProcessingRequired = true;
- }
- foreach (CallCmd callCmd in node.CallCmds)
- {
- if (!yieldingProcs.Contains(callCmd.Proc))
- {
- yieldingProcs.Add(callCmd.Proc);
- moreProcessingRequired = true;
- }
- }
- return ret;
- }
- private void ProcessVariable(Variable var) {
- Procedure/*!*/ localProc = cce.NonNull(enclosingProc);
- if (var == null)
- return;
- if (!(var is GlobalVariable))
- return;
- if (!modSets.ContainsKey(localProc)) {
- modSets[localProc] = new HashSet<Variable/*!*/>();
- }
- if (modSets[localProc].Contains(var))
- return;
- moreProcessingRequired = true;
- modSets[localProc].Add(var);
- }
- public override Expr VisitCodeExpr(CodeExpr node) {
- // don't go into the code expression, since it can only modify variables local to the code expression,
- // and the mod-set analysis is interested in global variables
- return node;
- }
- }
-
- public class MutableVariableCollector : ReadOnlyVisitor
- {
- public HashSet<Variable> UsedVariables = new HashSet<Variable>();
-
- public void AddUsedVariables(HashSet<Variable> usedVariables)
- {
- Contract.Requires(usedVariables != null);
-
- foreach (var v in usedVariables)
- {
- UsedVariables.Add(v);
- }
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() != null);
-
- if (node.Decl != null && node.Decl.IsMutable)
- {
- UsedVariables.Add(node.Decl);
- }
- return base.VisitIdentifierExpr(node);
- }
- }
-
- public class VariableCollector : ReadOnlyVisitor {
- protected HashSet<Variable/*!*/>/*!*/ _usedVars;
- public IEnumerable<Variable /*!*/>/*!*/ usedVars
- {
- get
- {
- return _usedVars.AsEnumerable();
- }
- }
-
- protected HashSet<Variable/*!*/>/*!*/ _oldVarsUsed;
- public IEnumerable<Variable /*!*/>/*!*/ oldVarsUsed
- {
- get
- {
- return _oldVarsUsed.AsEnumerable();
- }
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(_usedVars));
- Contract.Invariant(cce.NonNullElements(_oldVarsUsed));
- }
-
- int insideOldExpr;
-
- public VariableCollector() {
- _usedVars = new System.Collections.Generic.HashSet<Variable/*!*/>();
- _oldVarsUsed = new System.Collections.Generic.HashSet<Variable/*!*/>();
- insideOldExpr = 0;
- }
-
- public override Expr VisitOldExpr(OldExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- insideOldExpr++;
- node.Expr = this.VisitExpr(node.Expr);
- insideOldExpr--;
- return node;
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- if (node.Decl != null) {
- _usedVars.Add(node.Decl);
- if (insideOldExpr > 0) {
- _oldVarsUsed.Add(node.Decl);
- }
- }
- return node;
- }
- }
-
- public class BlockCoalescer : ReadOnlyVisitor {
- public static void CoalesceBlocks(Program program) {
- Contract.Requires(program != null);
- BlockCoalescer blockCoalescer = new BlockCoalescer();
- blockCoalescer.Visit(program);
- }
-
- private static HashSet<Block/*!*/>/*!*/ ComputeMultiPredecessorBlocks(Implementation/*!*/ impl) {
- Contract.Requires(impl != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Block>>()));
- HashSet<Block/*!*/> visitedBlocks = new HashSet<Block/*!*/>();
- HashSet<Block/*!*/> multiPredBlocks = new HashSet<Block/*!*/>();
- Stack<Block/*!*/> dfsStack = new Stack<Block/*!*/>();
- dfsStack.Push(impl.Blocks[0]);
- while (dfsStack.Count > 0) {
- Block/*!*/ b = dfsStack.Pop();
- Contract.Assert(b != null);
- if (visitedBlocks.Contains(b)) {
- multiPredBlocks.Add(b);
- continue;
- }
- visitedBlocks.Add(b);
- if (b.TransferCmd == null)
- continue;
- if (b.TransferCmd is ReturnCmd)
- continue;
- Contract.Assert(b.TransferCmd is GotoCmd);
- GotoCmd gotoCmd = (GotoCmd)b.TransferCmd;
- if (gotoCmd.labelTargets == null)
- continue;
- foreach (Block/*!*/ succ in gotoCmd.labelTargets) {
- Contract.Assert(succ != null);
- dfsStack.Push(succ);
- }
- }
- return multiPredBlocks;
- }
-
- public override Implementation VisitImplementation(Implementation impl) {
- //Contract.Requires(impl != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- //Console.WriteLine("Procedure {0}", impl.Name);
- //Console.WriteLine("Initial number of blocks = {0}", impl.Blocks.Count);
-
- HashSet<Block/*!*/> multiPredBlocks = ComputeMultiPredecessorBlocks(impl);
- Contract.Assert(cce.NonNullElements(multiPredBlocks));
- HashSet<Block/*!*/> visitedBlocks = new HashSet<Block/*!*/>();
- HashSet<Block/*!*/> removedBlocks = new HashSet<Block/*!*/>();
- Stack<Block/*!*/> dfsStack = new Stack<Block/*!*/>();
- dfsStack.Push(impl.Blocks[0]);
- while (dfsStack.Count > 0) {
- Block/*!*/ b = dfsStack.Pop();
- Contract.Assert(b != null);
- if (visitedBlocks.Contains(b))
- continue;
- visitedBlocks.Add(b);
- if (b.TransferCmd == null)
- continue;
- if (b.TransferCmd is ReturnCmd)
- continue;
- Contract.Assert(b.TransferCmd is GotoCmd);
- GotoCmd gotoCmd = (GotoCmd)b.TransferCmd;
- if (gotoCmd.labelTargets == null)
- continue;
- if (gotoCmd.labelTargets.Count == 1) {
- Block/*!*/ succ = cce.NonNull(gotoCmd.labelTargets[0]);
- if (!multiPredBlocks.Contains(succ)) {
- foreach (Cmd/*!*/ cmd in succ.Cmds) {
- Contract.Assert(cmd != null);
- b.Cmds.Add(cmd);
- }
- b.TransferCmd = succ.TransferCmd;
- if (!b.tok.IsValid && succ.tok.IsValid) {
- b.tok = succ.tok;
- b.Label = succ.Label;
- }
- removedBlocks.Add(succ);
- dfsStack.Push(b);
- visitedBlocks.Remove(b);
- continue;
- }
- }
- foreach (Block/*!*/ succ in gotoCmd.labelTargets) {
- Contract.Assert(succ != null);
- dfsStack.Push(succ);
- }
- }
-
- List<Block/*!*/> newBlocks = new List<Block/*!*/>();
- foreach (Block/*!*/ b in impl.Blocks) {
- Contract.Assert(b != null);
- if (visitedBlocks.Contains(b) && !removedBlocks.Contains(b)) {
- newBlocks.Add(b);
- }
- }
- impl.Blocks = newBlocks;
-
- // Console.WriteLine("Final number of blocks = {0}", impl.Blocks.Count);
- return impl;
- }
- }
-
- public class LiveVariableAnalysis {
- public static void ClearLiveVariables(Implementation impl) {
- Contract.Requires(impl != null);
- foreach (Block/*!*/ block in impl.Blocks) {
- Contract.Assert(block != null);
- block.liveVarsBefore = null;
- }
- }
-
- public static void ComputeLiveVariables(Implementation impl) {
- Contract.Requires(impl != null);
- Microsoft.Boogie.Helpers.ExtraTraceInformation("Starting live variable analysis");
- Graph<Block> dag = new Graph<Block>();
- dag.AddSource(cce.NonNull(impl.Blocks[0])); // there is always at least one node in the graph
- foreach (Block b in impl.Blocks) {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- Contract.Assume(gtc.labelTargets != null);
- foreach (Block/*!*/ dest in gtc.labelTargets) {
- Contract.Assert(dest != null);
- dag.AddEdge(dest, b);
- }
- }
- }
-
- IEnumerable<Block> sortedNodes;
- if (CommandLineOptions.Clo.ModifyTopologicalSorting) {
- sortedNodes = dag.TopologicalSort(true);
- } else {
- sortedNodes = dag.TopologicalSort();
- }
- foreach (Block/*!*/ block in sortedNodes) {
- Contract.Assert(block != null);
- HashSet<Variable/*!*/>/*!*/ liveVarsAfter = new HashSet<Variable/*!*/>();
-
- // The injected assumption variables should always be considered to be live.
- foreach (var v in impl.InjectedAssumptionVariables.Concat(impl.DoomedInjectedAssumptionVariables))
- {
- liveVarsAfter.Add(v);
- }
-
- if (block.TransferCmd is GotoCmd) {
- GotoCmd gotoCmd = (GotoCmd)block.TransferCmd;
- if (gotoCmd.labelTargets != null) {
- foreach (Block/*!*/ succ in gotoCmd.labelTargets) {
- Contract.Assert(succ != null);
- Contract.Assert(succ.liveVarsBefore != null);
- liveVarsAfter.UnionWith(succ.liveVarsBefore);
- }
- }
- }
-
- List<Cmd> cmds = block.Cmds;
- int len = cmds.Count;
- for (int i = len - 1; i >= 0; i--) {
- if (cmds[i] is CallCmd) {
- Procedure/*!*/ proc = cce.NonNull(cce.NonNull((CallCmd/*!*/)cmds[i]).Proc);
- if (InterProcGenKill.HasSummary(proc.Name)) {
- liveVarsAfter =
- InterProcGenKill.PropagateLiveVarsAcrossCall(cce.NonNull((CallCmd/*!*/)cmds[i]), liveVarsAfter);
- continue;
- }
- }
- Propagate(cmds[i], liveVarsAfter);
- }
-
- block.liveVarsBefore = liveVarsAfter;
-
- }
- }
-
- // perform in place update of liveSet
- public static void Propagate(Cmd cmd, HashSet<Variable/*!*/>/*!*/ liveSet) {
- Contract.Requires(cmd != null);
- Contract.Requires(cce.NonNullElements(liveSet));
- if (cmd is AssignCmd) {
- AssignCmd/*!*/ assignCmd = (AssignCmd)cce.NonNull(cmd);
- // I must first iterate over all the targets and remove the live ones.
- // After the removals are done, I must add the variables referred on
- // the right side of the removed targets
-
- AssignCmd simpleAssignCmd = assignCmd.AsSimpleAssignCmd;
- HashSet<int> indexSet = new HashSet<int>();
- int index = 0;
- foreach (AssignLhs/*!*/ lhs in simpleAssignCmd.Lhss) {
- Contract.Assert(lhs != null);
- SimpleAssignLhs salhs = lhs as SimpleAssignLhs;
- Contract.Assert(salhs != null);
- Variable var = salhs.DeepAssignedVariable;
- if (var != null && liveSet.Contains(var)) {
- indexSet.Add(index);
- liveSet.Remove(var);
- }
- index++;
- }
- index = 0;
- foreach (Expr/*!*/ expr in simpleAssignCmd.Rhss) {
- Contract.Assert(expr != null);
- if (indexSet.Contains(index)) {
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(expr);
- liveSet.UnionWith(collector.usedVars);
- }
- index++;
- }
- } else if (cmd is HavocCmd) {
- HavocCmd/*!*/ havocCmd = (HavocCmd)cmd;
- foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) {
- Contract.Assert(expr != null);
- if (expr.Decl != null && !(QKeyValue.FindBoolAttribute(expr.Decl.Attributes, "assumption") && expr.Decl.Name.StartsWith("a##post##"))) {
- liveSet.Remove(expr.Decl);
- }
- }
- } else if (cmd is PredicateCmd) {
- Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd));
- PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd);
- if (predicateCmd.Expr is LiteralExpr) {
- LiteralExpr le = (LiteralExpr)predicateCmd.Expr;
- if (le.IsFalse) {
- liveSet.Clear();
- }
- } else {
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(predicateCmd.Expr);
- liveSet.UnionWith(collector.usedVars);
- }
- } else if (cmd is CommentCmd) {
- // comments are just for debugging and don't affect verification
- } else if (cmd is SugaredCmd) {
- SugaredCmd/*!*/ sugCmd = (SugaredCmd)cce.NonNull(cmd);
- Propagate(sugCmd.Desugaring, liveSet);
- } else if (cmd is StateCmd) {
- StateCmd/*!*/ stCmd = (StateCmd)cce.NonNull(cmd);
- List<Cmd>/*!*/ cmds = cce.NonNull(stCmd.Cmds);
- int len = cmds.Count;
- for (int i = len - 1; i >= 0; i--) {
- Propagate(cmds[i], liveSet);
- }
- foreach (Variable/*!*/ v in stCmd.Locals) {
- Contract.Assert(v != null);
- liveSet.Remove(v);
- }
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- }
- }
-
- /*
- // An idempotent semiring interface
- abstract public class Weight {
- abstract public Weight! one();
- abstract public Weight! zero();
- abstract public Weight! extend(Weight! w1, Weight! w2);
- abstract public Weight! combine(Weight! w1, Weight! w2);
- abstract public Weight! isEqual(Weight! w);
- abstract public Weight! projectLocals()
- }
- */
-
- // Weight domain for LiveVariableAnalysis (Gen/Kill)
-
- public class GenKillWeight {
- // lambda S. (S - kill) union gen
- HashSet<Variable/*!*/>/*!*/ gen;
- HashSet<Variable/*!*/>/*!*/ kill;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(gen));
- Contract.Invariant(cce.NonNullElements(kill));
- Contract.Invariant(oneWeight != null);
- Contract.Invariant(zeroWeight != null);
- }
-
- bool isZero;
-
- public static GenKillWeight/*!*/ oneWeight = new GenKillWeight(new HashSet<Variable/*!*/>(), new HashSet<Variable/*!*/>());
- public static GenKillWeight/*!*/ zeroWeight = new GenKillWeight();
-
- // initializes to zero
- public GenKillWeight() {
- this.isZero = true;
- this.gen = new HashSet<Variable/*!*/>();
- this.kill = new HashSet<Variable/*!*/>();
- }
-
- public GenKillWeight(HashSet<Variable/*!*/> gen, HashSet<Variable/*!*/> kill) {
- Contract.Requires(cce.NonNullElements(gen));
- Contract.Requires(cce.NonNullElements(kill));
- Contract.Assert(gen != null);
- Contract.Assert(kill != null);
- this.gen = gen;
- this.kill = kill;
- this.isZero = false;
- }
-
- public static GenKillWeight one() {
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- return oneWeight;
- }
-
- public static GenKillWeight zero() {
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- return zeroWeight;
- }
-
- public static GenKillWeight extend(GenKillWeight w1, GenKillWeight w2) {
- Contract.Requires(w2 != null);
- Contract.Requires(w1 != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- if (w1.isZero || w2.isZero)
- return zero();
-
- HashSet<Variable> t = new HashSet<Variable>(w2.gen);
- t.ExceptWith(w1.kill);
- HashSet<Variable> g = new HashSet<Variable>(w1.gen);
- g.UnionWith(t);
- HashSet<Variable> k = new HashSet<Variable>(w1.kill);
- k.UnionWith(w2.kill);
- return new GenKillWeight(g, k);
- //return new GenKillWeight(w1.gen.Union(w2.gen.Difference(w1.kill)), w1.kill.Union(w2.kill));
- }
-
- public static GenKillWeight combine(GenKillWeight w1, GenKillWeight w2) {
- Contract.Requires(w2 != null);
- Contract.Requires(w1 != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- if (w1.isZero)
- return w2;
- if (w2.isZero)
- return w1;
-
- HashSet<Variable> g = new HashSet<Variable>(w1.gen);
- g.UnionWith(w2.gen);
- HashSet<Variable> k = new HashSet<Variable>(w1.kill);
- k.IntersectWith(w2.kill);
- return new GenKillWeight(g, k);
- //return new GenKillWeight(w1.gen.Union(w2.gen), w1.kill.Intersection(w2.kill));
- }
-
- public static GenKillWeight projectLocals(GenKillWeight w) {
- Contract.Requires(w != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- HashSet<Variable/*!*/> gen = new HashSet<Variable>();
- foreach (Variable v in w.gen)
- {
- if (isGlobal(v))
- gen.Add(v);
- }
- HashSet<Variable/*!*/> kill = new HashSet<Variable>();
- foreach (Variable v in w.kill)
- {
- if (isGlobal(v))
- kill.Add(v);
- }
-
- return new GenKillWeight(gen, kill);
- }
-
- public static bool isEqual(GenKillWeight w1, GenKillWeight w2) {
- Contract.Requires(w2 != null);
- Contract.Requires(w1 != null);
- if (w1.isZero)
- return w2.isZero;
- if (w2.isZero)
- return w1.isZero;
-
- return (w1.gen.Equals(w2.gen) && w1.kill.Equals(w2.kill));
- }
-
- private static bool isGlobal(Variable v) {
- Contract.Requires(v != null);
- return (v is GlobalVariable);
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return string.Format("({0},{1})", gen.ToString(), kill.ToString());
- }
-
- public HashSet<Variable/*!*/>/*!*/ getLiveVars() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
- return gen;
- }
-
- public HashSet<Variable/*!*/>/*!*/ getLiveVars(HashSet<Variable/*!*/>/*!*/ lv) {
- Contract.Requires(cce.NonNullElements(lv));
- Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
- HashSet<Variable> temp = new HashSet<Variable>(lv);
- temp.ExceptWith(kill);
- temp.UnionWith(gen);
- return temp;
- }
-
- }
-
- public class ICFG {
- public Graph<Block/*!*/>/*!*/ graph;
- // Map from procedure to the list of blocks that call that procedure
- public Dictionary<string/*!*/, List<Block/*!*/>/*!*/>/*!*/ procsCalled;
- public HashSet<Block/*!*/>/*!*/ nodes;
- public Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>/*!*/ succEdges;
- public Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>/*!*/ predEdges;
- private Dictionary<Block/*!*/, int>/*!*/ priority;
-
- public HashSet<Block/*!*/>/*!*/ srcNodes;
- public HashSet<Block/*!*/>/*!*/ exitNodes;
-
- public Dictionary<Block/*!*/, GenKillWeight/*!*/>/*!*/ weightBefore;
- public Dictionary<Block/*!*/, GenKillWeight/*!*/>/*!*/ weightAfter;
- public Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ liveVarsAfter;
- public Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ liveVarsBefore;
-
- public GenKillWeight/*!*/ summary;
- public Implementation/*!*/ impl;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(graph.Nodes));
- Contract.Invariant(cce.NonNullDictionaryAndValues(procsCalled));
- Contract.Invariant(cce.NonNullElements(nodes));
- Contract.Invariant(cce.NonNullDictionaryAndValues(succEdges));
- Contract.Invariant(cce.NonNullDictionaryAndValues(predEdges));
- Contract.Invariant(priority != null);
- Contract.Invariant(cce.NonNullElements(srcNodes));
- Contract.Invariant(cce.NonNullElements(exitNodes));
- Contract.Invariant(cce.NonNullDictionaryAndValues(weightBefore));
- Contract.Invariant(cce.NonNullDictionaryAndValues(weightAfter));
- Contract.Invariant(cce.NonNullDictionaryAndValues(liveVarsAfter));
- Contract.Invariant(cce.NonNullDictionaryAndValues(liveVarsBefore));
- Contract.Invariant(summary != null);
- Contract.Invariant(impl != null);
- }
-
-
- [NotDelayed]
- public ICFG(Implementation impl) {
- Contract.Requires(impl != null);
- this.graph = new Graph<Block/*!*/>();
- this.procsCalled = new Dictionary<string/*!*/, List<Block/*!*/>/*!*/>();
- this.nodes = new HashSet<Block/*!*/>();
- this.succEdges = new Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>();
- this.predEdges = new Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>();
-
- this.priority = new Dictionary<Block/*!*/, int>();
-
- this.srcNodes = new HashSet<Block/*!*/>();
- this.exitNodes = new HashSet<Block/*!*/>();
-
- this.weightBefore = new Dictionary<Block/*!*/, GenKillWeight/*!*/>();
- this.weightAfter = new Dictionary<Block/*!*/, GenKillWeight/*!*/>();
- this.liveVarsAfter = new Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>();
- this.liveVarsBefore = new Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>();
-
- summary = GenKillWeight.zero();
- this.impl = impl;
-
- Initialize(impl);
-
- }
-
- private void Initialize(Implementation impl) {
- Contract.Requires(impl != null);
- addSource(impl.Blocks[0]);
- graph.AddSource(impl.Blocks[0]);
-
- foreach (Block/*!*/ b in impl.Blocks) {
- Contract.Assert(b != null);
- if (b.TransferCmd is ReturnCmd) {
- exitNodes.Add(b);
- } else {
- GotoCmd gc = b.TransferCmd as GotoCmd;
- Contract.Assert(gc != null);
- Contract.Assert(gc.labelTargets != null);
- foreach (Block/*!*/ t in gc.labelTargets) {
- Contract.Assert(t != null);
- addEdge(b, t);
- graph.AddEdge(b, t);
- }
- }
-
- weightBefore[b] = GenKillWeight.zero();
- weightAfter[b] = GenKillWeight.zero();
-
- foreach (Cmd/*!*/ c in b.Cmds) {
- Contract.Assert(c != null);
- if (c is CallCmd) {
- CallCmd/*!*/ cc = cce.NonNull((CallCmd/*!*/)c);
- Contract.Assert(cc.Proc != null);
- string/*!*/ procName = cc.Proc.Name;
- Contract.Assert(procName != null);
- if (!procsCalled.ContainsKey(procName)) {
- procsCalled.Add(procName, new List<Block/*!*/>());
- }
- procsCalled[procName].Add(b);
- }
- }
- }
-
- List<Block>/*!*/ sortedNodes;
- bool acyclic;
-
- graph.TarjanTopSort(out acyclic, out sortedNodes);
-
- if (!acyclic) {
- Console.WriteLine("Warning: graph is not a dag");
- }
-
- int num = sortedNodes.Count;
- foreach (Block/*!*/ b in sortedNodes) {
- Contract.Assert(b != null);
- priority.Add(b, num);
- num--;
- }
-
- }
-
- public int getPriority(Block b) {
- Contract.Requires(b != null);
- if (priority.ContainsKey(b))
- return priority[b];
- return Int32.MaxValue;
- }
-
- private void addSource(Block b) {
- Contract.Requires(b != null);
- registerNode(b);
- this.srcNodes.Add(b);
- }
-
- private void addExit(Block b) {
- Contract.Requires(b != null);
- registerNode(b);
- this.exitNodes.Add(b);
- }
-
- private void registerNode(Block b) {
- Contract.Requires(b != null);
- if (!succEdges.ContainsKey(b)) {
- succEdges.Add(b, new HashSet<Block/*!*/>());
- }
-
- if (!predEdges.ContainsKey(b)) {
- predEdges.Add(b, new HashSet<Block/*!*/>());
- }
-
- nodes.Add(b);
- }
-
- private void addEdge(Block src, Block tgt) {
- Contract.Requires(tgt != null);
- Contract.Requires(src != null);
- registerNode(src);
- registerNode(tgt);
-
- succEdges[src].Add(tgt);
- predEdges[tgt].Add(src);
- }
-
-
- }
-
- // Interprocedural Gen/Kill Analysis
- public class InterProcGenKill {
- Program/*!*/ program;
- Dictionary<string/*!*/, ICFG/*!*/>/*!*/ procICFG;
- Dictionary<string/*!*/, Procedure/*!*/>/*!*/ name2Proc;
- Dictionary<string/*!*/, List<WorkItem/*!*/>/*!*/>/*!*/ callers;
- Graph<string/*!*/>/*!*/ callGraph;
- Dictionary<string/*!*/, int>/*!*/ procPriority;
- int maxBlocksInProc;
-
- WorkList/*!*/ workList;
-
- Implementation/*!*/ mainImpl;
-
- static Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ varsLiveAtExit = new Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>();
- static Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ varsLiveAtEntry = new Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>();
- static Dictionary<string/*!*/, GenKillWeight/*!*/>/*!*/ varsLiveSummary = new Dictionary<string/*!*/, GenKillWeight/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(workList != null);
- Contract.Invariant(mainImpl != null);
- Contract.Invariant(program != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(procICFG));
- Contract.Invariant(cce.NonNullDictionaryAndValues(name2Proc));
- Contract.Invariant(cce.NonNullDictionaryAndValues(callers) &&
- Contract.ForAll(callers.Values, v => cce.NonNullElements(v)));
- Contract.Invariant(cce.NonNullElements(callGraph.Nodes));
- Contract.Invariant(procPriority != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(varsLiveAtEntry));
- Contract.Invariant(cce.NonNullDictionaryAndValues(varsLiveAtExit) &&
- Contract.ForAll(varsLiveAtExit.Values, v => cce.NonNullElements(v)));
- Contract.Invariant(cce.NonNullDictionaryAndValues(varsLiveSummary));
- Contract.Invariant(cce.NonNullDictionaryAndValues(weightCacheAfterCall));
- Contract.Invariant(cce.NonNullDictionaryAndValues(weightCacheBeforeCall));
- }
-
-
- [NotDelayed]
- public InterProcGenKill(Implementation impl, Program program) {
- Contract.Requires(program != null);
- Contract.Requires(impl != null);
- this.program = program;
- procICFG = new Dictionary<string/*!*/, ICFG/*!*/>();
- name2Proc = new Dictionary<string/*!*/, Procedure/*!*/>();
- workList = new WorkList();
- this.callers = new Dictionary<string/*!*/, List<WorkItem/*!*/>/*!*/>();
- this.callGraph = new Graph<string/*!*/>();
- this.procPriority = new Dictionary<string/*!*/, int>();
- this.maxBlocksInProc = 0;
- this.mainImpl = impl;
-
- Dictionary<string/*!*/, Implementation/*!*/>/*!*/ name2Impl = new Dictionary<string/*!*/, Implementation/*!*/>();
- varsLiveAtExit.Clear();
- varsLiveAtEntry.Clear();
- varsLiveSummary.Clear();
-
- foreach (var decl in program.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- if (decl is Implementation) {
- Implementation/*!*/ imp = (Implementation/*!*/)cce.NonNull(decl);
- name2Impl[imp.Name] = imp;
- } else if (decl is Procedure) {
- Procedure/*!*/ proc = cce.NonNull(decl as Procedure);
- name2Proc[proc.Name] = proc;
- }
- }
-
- ICFG/*!*/ mainICFG = new ICFG(mainImpl);
- Contract.Assert(mainICFG != null);
- procICFG.Add(mainICFG.impl.Name, mainICFG);
- callGraph.AddSource(mainICFG.impl.Name);
-
- List<ICFG/*!*/>/*!*/ procsToConsider = new List<ICFG/*!*/>();
- procsToConsider.Add(mainICFG);
-
- while (procsToConsider.Count != 0) {
- ICFG/*!*/ p = procsToConsider[0];
- Contract.Assert(p != null);
- procsToConsider.RemoveAt(0);
-
- foreach (string/*!*/ callee in p.procsCalled.Keys) {
- Contract.Assert(callee != null);
- if (!name2Impl.ContainsKey(callee))
- continue;
-
- callGraph.AddEdge(p.impl.Name, callee);
-
- if (maxBlocksInProc < p.nodes.Count) {
- maxBlocksInProc = p.nodes.Count;
- }
-
- if (!callers.ContainsKey(callee)) {
- callers.Add(callee, new List<WorkItem/*!*/>());
- }
- foreach (Block/*!*/ b in p.procsCalled[callee]) {
- Contract.Assert(b != null);
- callers[callee].Add(new WorkItem(p, b));
- }
-
- if (procICFG.ContainsKey(callee))
- continue;
- ICFG/*!*/ ncfg = new ICFG(name2Impl[callee]);
- Contract.Assert(ncfg != null);
- procICFG.Add(callee, ncfg);
- procsToConsider.Add(ncfg);
- }
- }
-
- bool acyclic;
- List<string>/*!*/ sortedNodes;
- callGraph.TarjanTopSort(out acyclic, out sortedNodes);
-
- Contract.Assert(acyclic);
-
- int cnt = 0;
- for (int i = sortedNodes.Count - 1; i >= 0; i--) {
- string s = sortedNodes[i];
- if (s == null)
- continue;
- procPriority.Add(s, cnt);
- cnt++;
- }
-
- }
-
- public static HashSet<Variable/*!*/>/*!*/ GetVarsLiveAtExit(Implementation impl, Program prog) {
- Contract.Requires(prog != null);
- Contract.Requires(impl != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
- if (varsLiveAtExit.ContainsKey(impl.Name)) {
- return varsLiveAtExit[impl.Name];
- }
- // Return default: all globals and out params
- HashSet<Variable/*!*/>/*!*/ lv = new HashSet<Variable/*!*/>();
- foreach (Variable/*!*/ v in prog.GlobalVariables) {
- Contract.Assert(v != null);
- lv.Add(v);
- }
- foreach (Variable/*!*/ v in impl.OutParams) {
- Contract.Assert(v != null);
- lv.Add(v);
- }
- return lv;
- }
-
- public static HashSet<Variable/*!*/>/*!*/ GetVarsLiveAtEntry(Implementation impl, Program prog) {
- Contract.Requires(prog != null);
- Contract.Requires(impl != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
- if (varsLiveAtEntry.ContainsKey(impl.Name)) {
- return varsLiveAtEntry[impl.Name];
- }
- // Return default: all globals and in params
- HashSet<Variable/*!*/>/*!*/ lv = new HashSet<Variable/*!*/>();
- foreach (Variable/*!*/ v in prog.GlobalVariables) {
- Contract.Assert(v != null);
- lv.Add(v);
- }
- foreach (Variable/*!*/ v in impl.InParams) {
- Contract.Assert(v != null);
- lv.Add(v);
- }
- return lv;
- }
-
- public static bool HasSummary(string name) {
- Contract.Requires(name != null);
- return varsLiveSummary.ContainsKey(name);
- }
-
- public static HashSet<Variable/*!*/>/*!*/ PropagateLiveVarsAcrossCall(CallCmd cmd, HashSet<Variable/*!*/>/*!*/ lvAfter) {
- Contract.Requires(cmd != null);
- Contract.Requires(cce.NonNullElements(lvAfter));
- Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
- Procedure/*!*/ proc = cce.NonNull(cmd.Proc);
- if (varsLiveSummary.ContainsKey(proc.Name)) {
- GenKillWeight/*!*/ w1 = getWeightBeforeCall(cmd);
- Contract.Assert(w1 != null);
- GenKillWeight/*!*/ w2 = varsLiveSummary[proc.Name];
- Contract.Assert(w2 != null);
- GenKillWeight/*!*/ w3 = getWeightAfterCall(cmd);
- Contract.Assert(w3 != null);
- GenKillWeight/*!*/ w = GenKillWeight.extend(w1, GenKillWeight.extend(w2, w3));
- Contract.Assert(w != null);
- return w.getLiveVars(lvAfter);
- }
- HashSet<Variable/*!*/>/*!*/ ret = new HashSet<Variable/*!*/>();
- ret.UnionWith(lvAfter);
- LiveVariableAnalysis.Propagate(cmd, ret);
- return ret;
- }
-
- class WorkItem {
- public ICFG/*!*/ cfg;
- public Block/*!*/ block;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cfg != null);
- Contract.Invariant(block != null);
- }
-
-
- public WorkItem(ICFG cfg, Block block) {
- Contract.Requires(block != null);
- Contract.Requires(cfg != null);
- this.cfg = cfg;
- this.block = block;
- }
-
- public GenKillWeight getWeightAfter() {
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- return cfg.weightAfter[block];
- }
-
- public bool setWeightBefore(GenKillWeight w) {
- Contract.Requires(w != null);
- GenKillWeight/*!*/ prev = cfg.weightBefore[block];
- Contract.Assert(prev != null);
- GenKillWeight/*!*/ curr = GenKillWeight.combine(w, prev);
- Contract.Assert(curr != null);
- if (GenKillWeight.isEqual(prev, curr))
- return false;
- cfg.weightBefore[block] = curr;
- return true;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- WorkItem/*!*/ wi = (WorkItem/*!*/)cce.NonNull(other);
- return (wi.cfg == cfg && wi.block == block);
- }
-
- [Pure]
- public override int GetHashCode() {
- return 0;
- }
-
- public string getLabel() {
- Contract.Ensures(Contract.Result<string>() != null);
- return cfg.impl.Name + "::" + block.Label;
- }
-
- }
-
- private void AddToWorkList(WorkItem wi) {
- Contract.Requires(wi != null);
- int i = procPriority[wi.cfg.impl.Name];
- int j = wi.cfg.getPriority(wi.block);
- int priority = (i * maxBlocksInProc) + j;
-
- workList.Add(wi, priority);
- }
-
- private void AddToWorkListReverse(WorkItem wi) {
- Contract.Requires(wi != null);
- int i = procPriority[wi.cfg.impl.Name];
- int j = wi.cfg.getPriority(wi.block);
- int priority = (procPriority.Count - i) * maxBlocksInProc + j;
- workList.Add(wi, priority);
- }
-
- class WorkList {
- SortedList<int, int>/*!*/ priorities;
- HashSet<string/*!*/>/*!*/ labels;
-
- Dictionary<int, List<WorkItem/*!*/>/*!*/>/*!*/ workList;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(priorities != null);
- Contract.Invariant(cce.NonNullElements(labels));
- Contract.Invariant(cce.NonNullDictionaryAndValues(workList) &&
- Contract.ForAll(workList.Values, v => cce.NonNullElements(v)));
- }
-
-
- public WorkList() {
- labels = new HashSet<string/*!*/>();
- priorities = new SortedList<int, int>();
- workList = new Dictionary<int, List<WorkItem/*!*/>/*!*/>();
- }
-
- public void Add(WorkItem wi, int priority) {
- Contract.Requires(wi != null);
- string/*!*/ lab = wi.getLabel();
- Contract.Assert(lab != null);
- if (labels.Contains(lab)) {
- // Already on worklist
- return;
- }
- labels.Add(lab);
- if (!workList.ContainsKey(priority)) {
- workList.Add(priority, new List<WorkItem/*!*/>());
- }
- workList[priority].Add(wi);
- if (!priorities.ContainsKey(priority)) {
- priorities.Add(priority, 0);
- }
-
- priorities[priority] = priorities[priority] + 1;
- }
-
- public WorkItem Get() {
- Contract.Ensures(Contract.Result<WorkItem>() != null);
- // Get minimum priority
- int p = cce.NonNull(priorities.Keys)[0];
- priorities[p] = priorities[p] - 1;
- if (priorities[p] == 0) {
- priorities.Remove(p);
- }
-
- // Get a WI with this priority
- WorkItem/*!*/ wi = workList[p][0];
- Contract.Assert(wi != null);
- workList[p].RemoveAt(0);
-
- // update labels
- labels.Remove(wi.getLabel());
- return wi;
- }
-
- public int Count {
- get {
- return labels.Count;
- }
- }
- }
-
- private GenKillWeight getSummary(CallCmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- Contract.Assert(cmd.Proc != null);
- string/*!*/ procName = cmd.Proc.Name;
- Contract.Assert(procName != null);
- if (procICFG.ContainsKey(procName)) {
- ICFG/*!*/ cfg = procICFG[procName];
- Contract.Assert(cfg != null);
- return GenKillWeight.projectLocals(cfg.summary);
- }
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- public static void ComputeLiveVars(Implementation impl, Program/*!*/ prog) {
- Contract.Requires(prog != null);
- Contract.Requires(impl != null);
- InterProcGenKill/*!*/ ipgk = new InterProcGenKill(impl, prog);
- Contract.Assert(ipgk != null);
- ipgk.Compute();
- }
-
- public void Compute() {
- // Put all exit nodes in the worklist
- foreach (ICFG/*!*/ cfg in procICFG.Values) {
- Contract.Assert(cfg != null);
- foreach (Block/*!*/ eb in cfg.exitNodes) {
- Contract.Assert(eb != null);
- WorkItem/*!*/ wi = new WorkItem(cfg, eb);
- Contract.Assert(wi != null);
- cfg.weightAfter[eb] = GenKillWeight.one();
- AddToWorkList(wi);
- }
- }
-
- while (workList.Count != 0) {
- WorkItem/*!*/ wi = workList.Get();
- Contract.Assert(wi != null);
- process(wi);
- }
-
- // Propagate LV to all procedures
- foreach (ICFG/*!*/ cfg in procICFG.Values) {
- Contract.Assert(cfg != null);
- foreach (Block/*!*/ b in cfg.nodes) {
- Contract.Assert(b != null);
- cfg.liveVarsAfter.Add(b, new HashSet<Variable/*!*/>());
- cfg.liveVarsBefore.Add(b, new HashSet<Variable/*!*/>());
- }
- }
-
- ICFG/*!*/ mainCfg = procICFG[mainImpl.Name];
- Contract.Assert(mainCfg != null);
- foreach (Block/*!*/ eb in mainCfg.exitNodes) {
- Contract.Assert(eb != null);
- WorkItem/*!*/ wi = new WorkItem(mainCfg, eb);
- Contract.Assert(wi != null);
- AddToWorkListReverse(wi);
- }
-
- while (workList.Count != 0) {
- WorkItem/*!*/ wi = workList.Get();
- Contract.Assert(wi != null);
- processLV(wi);
- }
-
- // Set live variable info
- foreach (ICFG/*!*/ cfg in procICFG.Values) {
- Contract.Assert(cfg != null);
- HashSet<Variable/*!*/>/*!*/ lv = new HashSet<Variable/*!*/>();
- foreach (Block/*!*/ eb in cfg.exitNodes) {
- Contract.Assert(eb != null);
- lv.UnionWith(cfg.liveVarsAfter[eb]);
- }
- varsLiveAtExit.Add(cfg.impl.Name, lv);
- lv = new HashSet<Variable/*!*/>();
- foreach (Block/*!*/ eb in cfg.srcNodes) {
- Contract.Assert(eb != null);
- lv.UnionWith(cfg.liveVarsBefore[eb]);
- }
- varsLiveAtEntry.Add(cfg.impl.Name, lv);
- varsLiveSummary.Add(cfg.impl.Name, cfg.summary);
- }
-
- /*
- foreach(Block/*!*/
- /* b in mainImpl.Blocks){
-Contract.Assert(b != null);
-//Set<Variable!> lv = cfg.weightBefore[b].getLiveVars();
-b.liveVarsBefore = procICFG[mainImpl.Name].liveVarsAfter[b];
-//foreach(GlobalVariable/*!*/
- /* v in program.GlobalVariables){Contract.Assert(v != null);
-// b.liveVarsBefore.Add(v);
-//}
-}
-*/
- }
-
- // Called when summaries have already been computed
- private void processLV(WorkItem wi) {
- Contract.Requires(wi != null);
- ICFG/*!*/ cfg = wi.cfg;
- Contract.Assert(cfg != null);
- Block/*!*/ block = wi.block;
- Contract.Assert(block != null);
- HashSet<Variable/*!*/>/*!*/ lv = cfg.liveVarsAfter[block];
- Contract.Assert(cce.NonNullElements(lv));
- // Propagate backwards in the block
- HashSet<Variable/*!*/>/*!*/ prop = new HashSet<Variable/*!*/>();
- prop.UnionWith(lv);
- for (int i = block.Cmds.Count - 1; i >= 0; i--) {
- Cmd/*!*/ cmd = block.Cmds[i];
- Contract.Assert(cmd != null);
- if (cmd is CallCmd) {
- string/*!*/ procName = cce.NonNull(cce.NonNull((CallCmd)cmd).Proc).Name;
- Contract.Assert(procName != null);
- if (procICFG.ContainsKey(procName)) {
- ICFG/*!*/ callee = procICFG[procName];
- Contract.Assert(callee != null);
- // Inter propagation
- // Remove local variables; add return variables
- HashSet<Variable/*!*/>/*!*/ elv = new HashSet<Variable/*!*/>();
- foreach (Variable/*!*/ v in prop) {
- Contract.Assert(v != null);
- if (v is GlobalVariable)
- elv.Add(v);
- }
- foreach (Variable/*!*/ v in callee.impl.OutParams) {
- Contract.Assert(v != null);
- elv.Add(v);
- }
-
- foreach (Block/*!*/ eb in callee.exitNodes) {
- Contract.Assert(eb != null);
- callee.liveVarsAfter[eb].UnionWith(elv);
- // TODO: check if modified before inserting
- AddToWorkListReverse(new WorkItem(callee, eb));
- }
-
- // Continue with intra propagation
- GenKillWeight/*!*/ summary = getWeightCall(cce.NonNull((CallCmd/*!*/)cmd));
- prop = summary.getLiveVars(prop);
- } else {
- LiveVariableAnalysis.Propagate(cmd, prop);
- }
- } else {
- LiveVariableAnalysis.Propagate(cmd, prop);
- }
- }
-
- cfg.liveVarsBefore[block].UnionWith(prop);
-
- foreach (Block/*!*/ b in cfg.predEdges[block]) {
- Contract.Assert(b != null);
- HashSet<Variable/*!*/>/*!*/ prev = cfg.liveVarsAfter[b];
- Contract.Assert(cce.NonNullElements(prev));
- HashSet<Variable/*!*/>/*!*/ curr = new HashSet<Variable>(prev);
- curr.UnionWith(cfg.liveVarsBefore[block]);
- Contract.Assert(cce.NonNullElements(curr));
- if (curr.Count != prev.Count) {
- cfg.liveVarsAfter[b] = curr;
- AddToWorkListReverse(new WorkItem(cfg, b));
- }
- }
- }
-
- private void process(WorkItem wi) {
- Contract.Requires(wi != null);
- GenKillWeight/*!*/ w = wi.getWeightAfter();
- Contract.Assert(w != null);
-
- for (int i = wi.block.Cmds.Count - 1; i >= 0; i--) {
- Cmd/*!*/ c = wi.block.Cmds[i];
- Contract.Assert(c != null);
- if (c is CallCmd && procICFG.ContainsKey(cce.NonNull(cce.NonNull((CallCmd)c).Proc).Name)) {
- w = GenKillWeight.extend(getWeightCall(cce.NonNull((CallCmd)c)), w);
- } else {
- GenKillWeight/*!*/ cweight = getWeight(c, wi.cfg.impl, program);
- Contract.Assert(cweight != null);
- w = GenKillWeight.extend(cweight, w);
- }
- }
-
- bool change = wi.setWeightBefore(w);
-
- if (change && wi.cfg.srcNodes.Contains(wi.block)) {
- GenKillWeight/*!*/ prev = wi.cfg.summary;
- Contract.Assert(prev != null);
- GenKillWeight/*!*/ curr = GenKillWeight.combine(prev, wi.cfg.weightBefore[wi.block]);
- Contract.Assert(curr != null);
- if (!GenKillWeight.isEqual(prev, curr)) {
- wi.cfg.summary = curr;
- // push callers onto the worklist
- if (callers.ContainsKey(wi.cfg.impl.Name)) {
- foreach (WorkItem/*!*/ caller in callers[wi.cfg.impl.Name]) {
- Contract.Assert(caller != null);
- AddToWorkList(caller);
- }
- }
- }
- }
-
- foreach (Block/*!*/ b in wi.cfg.predEdges[wi.block]) {
- Contract.Assert(b != null);
- GenKillWeight/*!*/ prev = wi.cfg.weightAfter[b];
- Contract.Assert(prev != null);
- GenKillWeight/*!*/ curr = GenKillWeight.combine(prev, w);
- Contract.Assert(curr != null);
- if (!GenKillWeight.isEqual(prev, curr)) {
- wi.cfg.weightAfter[b] = curr;
- AddToWorkList(new WorkItem(wi.cfg, b));
- }
- }
-
- }
-
- static Dictionary<Cmd/*!*/, GenKillWeight/*!*/>/*!*/ weightCache = new Dictionary<Cmd/*!*/, GenKillWeight/*!*/>();
-
- private static GenKillWeight getWeight(Cmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- return getWeight(cmd, null, null);
- }
-
- private GenKillWeight getWeightCall(CallCmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- GenKillWeight/*!*/ w1 = getWeightBeforeCall(cmd);
- GenKillWeight/*!*/ w2 = getSummary(cmd);
- GenKillWeight/*!*/ w3 = getWeightAfterCall(cmd);
- Contract.Assert(w1 != null);
- Contract.Assert(w2 != null);
- Contract.Assert(w3 != null);
- return GenKillWeight.extend(w1, GenKillWeight.extend(w2, w3));
- }
-
- private static GenKillWeight getWeight(Cmd cmd, Implementation impl, Program prog) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
-
- if (weightCache.ContainsKey(cmd))
- return weightCache[cmd];
-
- HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>();
- HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>();
- GenKillWeight/*!*/ ret;
-
- if (cmd is AssignCmd) {
- AssignCmd/*!*/ assignCmd = (AssignCmd)cmd;
- Contract.Assert(cmd != null);
- // I must first iterate over all the targets and remove the live ones.
- // After the removals are done, I must add the variables referred on
- // the right side of the removed targets
- foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) {
- Contract.Assert(lhs != null);
- Variable var = lhs.DeepAssignedVariable;
- if (var != null) {
- if (lhs is SimpleAssignLhs) {
- // we should only remove non-map target variables because there is an implicit
- // read of a map variable in an assignment to it
- kill.Add(var);
- }
- }
- }
- int index = 0;
- foreach (Expr/*!*/ expr in assignCmd.Rhss) {
- Contract.Assert(expr != null);
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(expr);
- gen.UnionWith(collector.usedVars);
- AssignLhs lhs = assignCmd.Lhss[index];
- if (lhs is MapAssignLhs) {
- // If the target is a map, then all indices are also read
- MapAssignLhs malhs = (MapAssignLhs)lhs;
- foreach (Expr e in malhs.Indexes) {
- VariableCollector/*!*/ c = new VariableCollector();
- c.Visit(e);
- gen.UnionWith(c.usedVars);
- }
- }
- index++;
- }
- ret = new GenKillWeight(gen, kill);
- } else if (cmd is HavocCmd) {
- HavocCmd/*!*/ havocCmd = (HavocCmd)cce.NonNull(cmd);
- foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) {
- Contract.Assert(expr != null);
- if (expr.Decl != null) {
- kill.Add(expr.Decl);
- }
- }
- ret = new GenKillWeight(gen, kill);
- } else if (cmd is PredicateCmd) {
- Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd));
- PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd);
- if (predicateCmd.Expr is LiteralExpr && prog != null && impl != null) {
- LiteralExpr le = (LiteralExpr)predicateCmd.Expr;
- if (le.IsFalse) {
- var globals = prog.GlobalVariables;
- Contract.Assert(cce.NonNullElements(globals));
- foreach (Variable/*!*/ v in globals) {
- Contract.Assert(v != null);
- kill.Add(v);
- }
- foreach (Variable/*!*/ v in impl.LocVars) {
- Contract.Assert(v != null);
- kill.Add(v);
- }
- foreach (Variable/*!*/ v in impl.OutParams) {
- Contract.Assert(v != null);
- kill.Add(v);
- }
- }
- } else {
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(predicateCmd.Expr);
- gen.UnionWith(collector.usedVars);
- }
- ret = new GenKillWeight(gen, kill);
- } else if (cmd is CommentCmd) {
- ret = new GenKillWeight(gen, kill);
- // comments are just for debugging and don't affect verification
- } else if (cmd is SugaredCmd) {
- SugaredCmd/*!*/ sugCmd = (SugaredCmd)cmd;
- Contract.Assert(sugCmd != null);
- ret = getWeight(sugCmd.Desugaring, impl, prog);
- } else if (cmd is StateCmd) {
- StateCmd/*!*/ stCmd = (StateCmd)cmd;
- Contract.Assert(stCmd != null);
- List<Cmd>/*!*/ cmds = stCmd.Cmds;
- Contract.Assert(cmds != null);
- int len = cmds.Count;
- ret = GenKillWeight.one();
- for (int i = len - 1; i >= 0; i--) {
- GenKillWeight/*!*/ w = getWeight(cmds[i], impl, prog);
- Contract.Assert(w != null);
- ret = GenKillWeight.extend(w, ret);
- }
- foreach (Variable/*!*/ v in stCmd.Locals) {
- Contract.Assert(v != null);
- kill.Add(v);
- }
- ret = GenKillWeight.extend(new GenKillWeight(gen, kill), ret);
- } else {
- {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- weightCache[cmd] = ret;
- return ret;
- }
-
- static Dictionary<Cmd/*!*/, GenKillWeight/*!*/>/*!*/ weightCacheAfterCall = new Dictionary<Cmd/*!*/, GenKillWeight/*!*/>();
- static Dictionary<Cmd/*!*/, GenKillWeight/*!*/>/*!*/ weightCacheBeforeCall = new Dictionary<Cmd/*!*/, GenKillWeight/*!*/>();
-
- private static GenKillWeight getWeightAfterCall(Cmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
-
- if (weightCacheAfterCall.ContainsKey(cmd))
- return weightCacheAfterCall[cmd];
-
- HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>();
- HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>();
-
- Contract.Assert(cmd is CallCmd);
- CallCmd/*!*/ ccmd = cce.NonNull((CallCmd)cmd);
-
- foreach (IdentifierExpr/*!*/ ie in ccmd.Outs) {
- Contract.Assert(ie != null);
- if (ie.Decl != null)
- kill.Add(ie.Decl);
- }
-
- // Variables in ensures are considered as "read"
- foreach (Ensures/*!*/ re in cce.NonNull(ccmd.Proc).Ensures) {
- Contract.Assert(re != null);
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(re.Condition);
- foreach (Variable/*!*/ v in collector.usedVars) {
- Contract.Assert(v != null);
- if (v is GlobalVariable) {
- gen.Add(v);
- }
- }
- }
-
- GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill);
- Contract.Assert(ret != null);
- weightCacheAfterCall[cmd] = ret;
- return ret;
- }
-
- private static GenKillWeight getWeightBeforeCall(Cmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<GenKillWeight>() != null);
- Contract.Assert((cmd is CallCmd));
- if (weightCacheBeforeCall.ContainsKey(cmd))
- return weightCacheBeforeCall[cmd];
-
- HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>();
- HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>();
- CallCmd/*!*/ ccmd = cce.NonNull((CallCmd/*!*/)cmd);
-
- foreach (Expr/*!*/ expr in ccmd.Ins) {
- Contract.Assert(expr != null);
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(expr);
- gen.UnionWith(collector.usedVars);
- }
-
- Contract.Assert(ccmd.Proc != null);
-
- // Variables in requires are considered as "read"
- foreach (Requires/*!*/ re in ccmd.Proc.Requires) {
- Contract.Assert(re != null);
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(re.Condition);
- foreach (Variable/*!*/ v in collector.usedVars) {
- Contract.Assert(v != null);
- if (v is GlobalVariable) {
- gen.Add(v);
- }
- }
- }
-
- // Old variables in ensures are considered as "read"
- foreach (Ensures/*!*/ re in ccmd.Proc.Ensures) {
- Contract.Assert(re != null);
- VariableCollector/*!*/ collector = new VariableCollector();
- collector.Visit(re.Condition);
- foreach (Variable/*!*/ v in collector.oldVarsUsed) {
- Contract.Assert(v != null);
- if (v is GlobalVariable) {
- gen.Add(v);
- }
- }
- }
-
- GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill);
- Contract.Assert(ret != null);
- weightCacheAfterCall[cmd] = ret;
- return ret;
- }
- }
-
- public class TokenEliminator : ReadOnlyVisitor
- {
- public int TokenCount = 0;
- public override Expr VisitExpr(Expr node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitExpr(node);
- }
- public override Variable VisitVariable(Variable node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitVariable(node);
- }
- public override Function VisitFunction(Function node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitFunction(node);
- }
- public override Implementation VisitImplementation(Implementation node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitImplementation(node);
- }
- public override Procedure VisitProcedure(Procedure node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitProcedure(node);
- }
- public override Axiom VisitAxiom(Axiom node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitAxiom(node);
- }
- public override Cmd VisitAssignCmd(AssignCmd node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitAssignCmd(node);
- }
- public override Cmd VisitAssumeCmd(AssumeCmd node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitAssumeCmd(node);
- }
- public override Cmd VisitHavocCmd(HavocCmd node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitHavocCmd(node);
- }
- public override Constant VisitConstant(Constant node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitConstant(node);
- }
- public override TransferCmd VisitTransferCmd(TransferCmd node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitTransferCmd(node);
- }
- public override Block VisitBlock(Block node)
- {
- node.tok = Token.NoToken;
- TokenCount++;
- return base.VisitBlock(node);
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+
+
+namespace Microsoft.Boogie {
+ public class UnusedVarEliminator : VariableCollector {
+ public static void Eliminate(Program program) {
+ Contract.Requires(program != null);
+ UnusedVarEliminator elim = new UnusedVarEliminator();
+ elim.Visit(program);
+ }
+
+ private UnusedVarEliminator()
+ : base() {
+
+ }
+
+ public override Implementation VisitImplementation(Implementation node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Implementation>() != null);
+ //Console.WriteLine("Procedure {0}", node.Name);
+ Implementation/*!*/ impl = base.VisitImplementation(node);
+ Contract.Assert(impl != null);
+ //Console.WriteLine("Old number of local variables = {0}", impl.LocVars.Length);
+ List<Variable>/*!*/ vars = new List<Variable>();
+ foreach (Variable/*!*/ var in impl.LocVars) {
+ Contract.Assert(var != null);
+ if (_usedVars.Contains(var))
+ vars.Add(var);
+ }
+ impl.LocVars = vars;
+ //Console.WriteLine("New number of local variables = {0}", impl.LocVars.Length);
+ //Console.WriteLine("---------------------------------");
+ _usedVars.Clear();
+ return impl;
+ }
+ }
+
+ public class ModSetCollector : ReadOnlyVisitor {
+ private Procedure enclosingProc;
+ private Dictionary<Procedure/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ modSets;
+ private HashSet<Procedure> yieldingProcs;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(modSets));
+ Contract.Invariant(Contract.ForAll(modSets.Values, v => cce.NonNullElements(v)));
+ }
+
+ public ModSetCollector() {
+ modSets = new Dictionary<Procedure/*!*/, HashSet<Variable/*!*/>/*!*/>();
+ yieldingProcs = new HashSet<Procedure>();
+ }
+
+ private bool moreProcessingRequired;
+
+ public void DoModSetAnalysis(Program program) {
+ Contract.Requires(program != null);
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+// Console.WriteLine();
+// Console.WriteLine("Running modset analysis ...");
+// int procCount = 0;
+// foreach (Declaration/*!*/ decl in program.TopLevelDeclarations)
+// {
+// Contract.Assert(decl != null);
+// if (decl is Procedure)
+// procCount++;
+// }
+// Console.WriteLine("Number of procedures = {0}", procCount);*/
+ }
+
+ HashSet<Procedure/*!*/> implementedProcs = new HashSet<Procedure/*!*/>();
+ foreach (var impl in program.Implementations) {
+ if (impl.Proc != null)
+ implementedProcs.Add(impl.Proc);
+ }
+ foreach (var proc in program.Procedures) {
+ if (!implementedProcs.Contains(proc))
+ {
+ enclosingProc = proc;
+ foreach (var expr in proc.Modifies)
+ {
+ Contract.Assert(expr != null);
+ ProcessVariable(expr.Decl);
+ }
+ enclosingProc = null;
+ }
+ else
+ {
+ modSets.Add(proc, new HashSet<Variable>());
+ }
+ }
+
+ moreProcessingRequired = true;
+ while (moreProcessingRequired) {
+ moreProcessingRequired = false;
+ this.Visit(program);
+ }
+
+ foreach (Procedure x in modSets.Keys)
+ {
+ x.Modifies = new List<IdentifierExpr>();
+ foreach (Variable v in modSets[x])
+ {
+ x.Modifies.Add(new IdentifierExpr(v.tok, v));
+ }
+ }
+ foreach (Procedure x in yieldingProcs)
+ {
+ if (!QKeyValue.FindBoolAttribute(x.Attributes, "yields"))
+ {
+ x.AddAttribute("yields");
+ }
+ }
+
+#if DEBUG_PRINT
+ Console.WriteLine("Number of procedures with nonempty modsets = {0}", modSets.Keys.Count);
+ foreach (Procedure/*!*/ x in modSets.Keys) {
+ Contract.Assert(x != null);
+ Console.Write("{0} : ", x.Name);
+ bool first = true;
+ foreach (Variable/*!*/ y in modSets[x]) {
+ Contract.Assert(y != null);
+ if (first)
+ first = false;
+ else
+ Console.Write(", ");
+ Console.Write("{0}", y.Name);
+ }
+ Console.WriteLine("");
+ }
+#endif
+ }
+
+ public override Implementation VisitImplementation(Implementation node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Implementation>() != null);
+ enclosingProc = node.Proc;
+ Implementation/*!*/ ret = base.VisitImplementation(node);
+ Contract.Assert(ret != null);
+ enclosingProc = null;
+
+ return ret;
+ }
+ public override YieldCmd VisitYieldCmd(YieldCmd node)
+ {
+ if (!yieldingProcs.Contains(enclosingProc))
+ {
+ yieldingProcs.Add(enclosingProc);
+ moreProcessingRequired = true;
+ }
+ return base.VisitYieldCmd(node);
+ }
+ public override Cmd VisitAssignCmd(AssignCmd assignCmd) {
+ //Contract.Requires(assignCmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Cmd ret = base.VisitAssignCmd(assignCmd);
+ foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) {
+ Contract.Assert(lhs != null);
+ ProcessVariable(lhs.DeepAssignedVariable);
+ }
+ return ret;
+ }
+ public override Cmd VisitHavocCmd(HavocCmd havocCmd) {
+ //Contract.Requires(havocCmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Cmd ret = base.VisitHavocCmd(havocCmd);
+ foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) {
+ Contract.Assert(expr != null);
+ ProcessVariable(expr.Decl);
+ }
+ return ret;
+ }
+ public override Cmd VisitCallCmd(CallCmd callCmd) {
+ //Contract.Requires(callCmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Cmd ret = base.VisitCallCmd(callCmd);
+ foreach (IdentifierExpr ie in callCmd.Outs)
+ {
+ if (ie != null) ProcessVariable(ie.Decl);
+ }
+ Procedure callee = callCmd.Proc;
+ if (callee == null)
+ return ret;
+ if (modSets.ContainsKey(callee)) {
+ foreach (Variable var in modSets[callee]) {
+ ProcessVariable(var);
+ }
+ }
+ if (!yieldingProcs.Contains(enclosingProc) && (yieldingProcs.Contains(callCmd.Proc) || callCmd.IsAsync))
+ {
+ yieldingProcs.Add(enclosingProc);
+ moreProcessingRequired = true;
+ }
+ if (callCmd.IsAsync)
+ {
+ if (!yieldingProcs.Contains(callCmd.Proc))
+ {
+ yieldingProcs.Add(callCmd.Proc);
+ moreProcessingRequired = true;
+ }
+ }
+ return ret;
+ }
+ public override Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ //Contract.Requires(callCmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Cmd ret = base.VisitParCallCmd(node);
+ if (!yieldingProcs.Contains(enclosingProc))
+ {
+ yieldingProcs.Add(enclosingProc);
+ moreProcessingRequired = true;
+ }
+ foreach (CallCmd callCmd in node.CallCmds)
+ {
+ if (!yieldingProcs.Contains(callCmd.Proc))
+ {
+ yieldingProcs.Add(callCmd.Proc);
+ moreProcessingRequired = true;
+ }
+ }
+ return ret;
+ }
+ private void ProcessVariable(Variable var) {
+ Procedure/*!*/ localProc = cce.NonNull(enclosingProc);
+ if (var == null)
+ return;
+ if (!(var is GlobalVariable))
+ return;
+ if (!modSets.ContainsKey(localProc)) {
+ modSets[localProc] = new HashSet<Variable/*!*/>();
+ }
+ if (modSets[localProc].Contains(var))
+ return;
+ moreProcessingRequired = true;
+ modSets[localProc].Add(var);
+ }
+ public override Expr VisitCodeExpr(CodeExpr node) {
+ // don't go into the code expression, since it can only modify variables local to the code expression,
+ // and the mod-set analysis is interested in global variables
+ return node;
+ }
+ }
+
+ public class MutableVariableCollector : ReadOnlyVisitor
+ {
+ public HashSet<Variable> UsedVariables = new HashSet<Variable>();
+
+ public void AddUsedVariables(HashSet<Variable> usedVariables)
+ {
+ Contract.Requires(usedVariables != null);
+
+ foreach (var v in usedVariables)
+ {
+ UsedVariables.Add(v);
+ }
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+
+ if (node.Decl != null && node.Decl.IsMutable)
+ {
+ UsedVariables.Add(node.Decl);
+ }
+ return base.VisitIdentifierExpr(node);
+ }
+ }
+
+ public class VariableCollector : ReadOnlyVisitor {
+ protected HashSet<Variable/*!*/>/*!*/ _usedVars;
+ public IEnumerable<Variable /*!*/>/*!*/ usedVars
+ {
+ get
+ {
+ return _usedVars.AsEnumerable();
+ }
+ }
+
+ protected HashSet<Variable/*!*/>/*!*/ _oldVarsUsed;
+ public IEnumerable<Variable /*!*/>/*!*/ oldVarsUsed
+ {
+ get
+ {
+ return _oldVarsUsed.AsEnumerable();
+ }
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(_usedVars));
+ Contract.Invariant(cce.NonNullElements(_oldVarsUsed));
+ }
+
+ int insideOldExpr;
+
+ public VariableCollector() {
+ _usedVars = new System.Collections.Generic.HashSet<Variable/*!*/>();
+ _oldVarsUsed = new System.Collections.Generic.HashSet<Variable/*!*/>();
+ insideOldExpr = 0;
+ }
+
+ public override Expr VisitOldExpr(OldExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ insideOldExpr++;
+ node.Expr = this.VisitExpr(node.Expr);
+ insideOldExpr--;
+ return node;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ if (node.Decl != null) {
+ _usedVars.Add(node.Decl);
+ if (insideOldExpr > 0) {
+ _oldVarsUsed.Add(node.Decl);
+ }
+ }
+ return node;
+ }
+ }
+
+ public class BlockCoalescer : ReadOnlyVisitor {
+ public static void CoalesceBlocks(Program program) {
+ Contract.Requires(program != null);
+ BlockCoalescer blockCoalescer = new BlockCoalescer();
+ blockCoalescer.Visit(program);
+ }
+
+ private static HashSet<Block/*!*/>/*!*/ ComputeMultiPredecessorBlocks(Implementation/*!*/ impl) {
+ Contract.Requires(impl != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Block>>()));
+ HashSet<Block/*!*/> visitedBlocks = new HashSet<Block/*!*/>();
+ HashSet<Block/*!*/> multiPredBlocks = new HashSet<Block/*!*/>();
+ Stack<Block/*!*/> dfsStack = new Stack<Block/*!*/>();
+ dfsStack.Push(impl.Blocks[0]);
+ while (dfsStack.Count > 0) {
+ Block/*!*/ b = dfsStack.Pop();
+ Contract.Assert(b != null);
+ if (visitedBlocks.Contains(b)) {
+ multiPredBlocks.Add(b);
+ continue;
+ }
+ visitedBlocks.Add(b);
+ if (b.TransferCmd == null)
+ continue;
+ if (b.TransferCmd is ReturnCmd)
+ continue;
+ Contract.Assert(b.TransferCmd is GotoCmd);
+ GotoCmd gotoCmd = (GotoCmd)b.TransferCmd;
+ if (gotoCmd.labelTargets == null)
+ continue;
+ foreach (Block/*!*/ succ in gotoCmd.labelTargets) {
+ Contract.Assert(succ != null);
+ dfsStack.Push(succ);
+ }
+ }
+ return multiPredBlocks;
+ }
+
+ public override Implementation VisitImplementation(Implementation impl) {
+ //Contract.Requires(impl != null);
+ Contract.Ensures(Contract.Result<Implementation>() != null);
+ //Console.WriteLine("Procedure {0}", impl.Name);
+ //Console.WriteLine("Initial number of blocks = {0}", impl.Blocks.Count);
+
+ HashSet<Block/*!*/> multiPredBlocks = ComputeMultiPredecessorBlocks(impl);
+ Contract.Assert(cce.NonNullElements(multiPredBlocks));
+ HashSet<Block/*!*/> visitedBlocks = new HashSet<Block/*!*/>();
+ HashSet<Block/*!*/> removedBlocks = new HashSet<Block/*!*/>();
+ Stack<Block/*!*/> dfsStack = new Stack<Block/*!*/>();
+ dfsStack.Push(impl.Blocks[0]);
+ while (dfsStack.Count > 0) {
+ Block/*!*/ b = dfsStack.Pop();
+ Contract.Assert(b != null);
+ if (visitedBlocks.Contains(b))
+ continue;
+ visitedBlocks.Add(b);
+ if (b.TransferCmd == null)
+ continue;
+ if (b.TransferCmd is ReturnCmd)
+ continue;
+ Contract.Assert(b.TransferCmd is GotoCmd);
+ GotoCmd gotoCmd = (GotoCmd)b.TransferCmd;
+ if (gotoCmd.labelTargets == null)
+ continue;
+ if (gotoCmd.labelTargets.Count == 1) {
+ Block/*!*/ succ = cce.NonNull(gotoCmd.labelTargets[0]);
+ if (!multiPredBlocks.Contains(succ)) {
+ foreach (Cmd/*!*/ cmd in succ.Cmds) {
+ Contract.Assert(cmd != null);
+ b.Cmds.Add(cmd);
+ }
+ b.TransferCmd = succ.TransferCmd;
+ if (!b.tok.IsValid && succ.tok.IsValid) {
+ b.tok = succ.tok;
+ b.Label = succ.Label;
+ }
+ removedBlocks.Add(succ);
+ dfsStack.Push(b);
+ visitedBlocks.Remove(b);
+ continue;
+ }
+ }
+ foreach (Block/*!*/ succ in gotoCmd.labelTargets) {
+ Contract.Assert(succ != null);
+ dfsStack.Push(succ);
+ }
+ }
+
+ List<Block/*!*/> newBlocks = new List<Block/*!*/>();
+ foreach (Block/*!*/ b in impl.Blocks) {
+ Contract.Assert(b != null);
+ if (visitedBlocks.Contains(b) && !removedBlocks.Contains(b)) {
+ newBlocks.Add(b);
+ }
+ }
+ impl.Blocks = newBlocks;
+ foreach (Block b in impl.Blocks)
+ {
+ if (b.TransferCmd is ReturnCmd) continue;
+ GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
+ gotoCmd.labelNames = new List<string>();
+ foreach (Block succ in gotoCmd.labelTargets)
+ {
+ gotoCmd.labelNames.Add(succ.Label);
+ }
+ }
+ // Console.WriteLine("Final number of blocks = {0}", impl.Blocks.Count);
+ return impl;
+ }
+ }
+
+ public class LiveVariableAnalysis {
+ public static void ClearLiveVariables(Implementation impl) {
+ Contract.Requires(impl != null);
+ foreach (Block/*!*/ block in impl.Blocks) {
+ Contract.Assert(block != null);
+ block.liveVarsBefore = null;
+ }
+ }
+
+ public static void ComputeLiveVariables(Implementation impl) {
+ Contract.Requires(impl != null);
+ Microsoft.Boogie.Helpers.ExtraTraceInformation("Starting live variable analysis");
+ Graph<Block> dag = new Graph<Block>();
+ dag.AddSource(cce.NonNull(impl.Blocks[0])); // there is always at least one node in the graph
+ foreach (Block b in impl.Blocks) {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null) {
+ Contract.Assume(gtc.labelTargets != null);
+ foreach (Block/*!*/ dest in gtc.labelTargets) {
+ Contract.Assert(dest != null);
+ dag.AddEdge(dest, b);
+ }
+ }
+ }
+
+ IEnumerable<Block> sortedNodes;
+ if (CommandLineOptions.Clo.ModifyTopologicalSorting) {
+ sortedNodes = dag.TopologicalSort(true);
+ } else {
+ sortedNodes = dag.TopologicalSort();
+ }
+ foreach (Block/*!*/ block in sortedNodes) {
+ Contract.Assert(block != null);
+ HashSet<Variable/*!*/>/*!*/ liveVarsAfter = new HashSet<Variable/*!*/>();
+
+ // The injected assumption variables should always be considered to be live.
+ foreach (var v in impl.InjectedAssumptionVariables.Concat(impl.DoomedInjectedAssumptionVariables))
+ {
+ liveVarsAfter.Add(v);
+ }
+
+ if (block.TransferCmd is GotoCmd) {
+ GotoCmd gotoCmd = (GotoCmd)block.TransferCmd;
+ if (gotoCmd.labelTargets != null) {
+ foreach (Block/*!*/ succ in gotoCmd.labelTargets) {
+ Contract.Assert(succ != null);
+ Contract.Assert(succ.liveVarsBefore != null);
+ liveVarsAfter.UnionWith(succ.liveVarsBefore);
+ }
+ }
+ }
+
+ List<Cmd> cmds = block.Cmds;
+ int len = cmds.Count;
+ for (int i = len - 1; i >= 0; i--) {
+ if (cmds[i] is CallCmd) {
+ Procedure/*!*/ proc = cce.NonNull(cce.NonNull((CallCmd/*!*/)cmds[i]).Proc);
+ if (InterProcGenKill.HasSummary(proc.Name)) {
+ liveVarsAfter =
+ InterProcGenKill.PropagateLiveVarsAcrossCall(cce.NonNull((CallCmd/*!*/)cmds[i]), liveVarsAfter);
+ continue;
+ }
+ }
+ Propagate(cmds[i], liveVarsAfter);
+ }
+
+ block.liveVarsBefore = liveVarsAfter;
+
+ }
+ }
+
+ // perform in place update of liveSet
+ public static void Propagate(Cmd cmd, HashSet<Variable/*!*/>/*!*/ liveSet) {
+ Contract.Requires(cmd != null);
+ Contract.Requires(cce.NonNullElements(liveSet));
+ if (cmd is AssignCmd) {
+ AssignCmd/*!*/ assignCmd = (AssignCmd)cce.NonNull(cmd);
+ // I must first iterate over all the targets and remove the live ones.
+ // After the removals are done, I must add the variables referred on
+ // the right side of the removed targets
+
+ AssignCmd simpleAssignCmd = assignCmd.AsSimpleAssignCmd;
+ HashSet<int> indexSet = new HashSet<int>();
+ int index = 0;
+ foreach (AssignLhs/*!*/ lhs in simpleAssignCmd.Lhss) {
+ Contract.Assert(lhs != null);
+ SimpleAssignLhs salhs = lhs as SimpleAssignLhs;
+ Contract.Assert(salhs != null);
+ Variable var = salhs.DeepAssignedVariable;
+ if (var != null && liveSet.Contains(var)) {
+ indexSet.Add(index);
+ liveSet.Remove(var);
+ }
+ index++;
+ }
+ index = 0;
+ foreach (Expr/*!*/ expr in simpleAssignCmd.Rhss) {
+ Contract.Assert(expr != null);
+ if (indexSet.Contains(index)) {
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(expr);
+ liveSet.UnionWith(collector.usedVars);
+ }
+ index++;
+ }
+ } else if (cmd is HavocCmd) {
+ HavocCmd/*!*/ havocCmd = (HavocCmd)cmd;
+ foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) {
+ Contract.Assert(expr != null);
+ if (expr.Decl != null && !(QKeyValue.FindBoolAttribute(expr.Decl.Attributes, "assumption") && expr.Decl.Name.StartsWith("a##cached##"))) {
+ liveSet.Remove(expr.Decl);
+ }
+ }
+ } else if (cmd is PredicateCmd) {
+ Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd));
+ PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd);
+ if (predicateCmd.Expr is LiteralExpr) {
+ LiteralExpr le = (LiteralExpr)predicateCmd.Expr;
+ if (le.IsFalse) {
+ liveSet.Clear();
+ }
+ } else {
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(predicateCmd.Expr);
+ liveSet.UnionWith(collector.usedVars);
+ }
+ } else if (cmd is CommentCmd) {
+ // comments are just for debugging and don't affect verification
+ } else if (cmd is SugaredCmd) {
+ SugaredCmd/*!*/ sugCmd = (SugaredCmd)cce.NonNull(cmd);
+ Propagate(sugCmd.Desugaring, liveSet);
+ } else if (cmd is StateCmd) {
+ StateCmd/*!*/ stCmd = (StateCmd)cce.NonNull(cmd);
+ List<Cmd>/*!*/ cmds = cce.NonNull(stCmd.Cmds);
+ int len = cmds.Count;
+ for (int i = len - 1; i >= 0; i--) {
+ Propagate(cmds[i], liveSet);
+ }
+ foreach (Variable/*!*/ v in stCmd.Locals) {
+ Contract.Assert(v != null);
+ liveSet.Remove(v);
+ }
+ } else {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+ }
+
+ /*
+ // An idempotent semiring interface
+ abstract public class Weight {
+ abstract public Weight! one();
+ abstract public Weight! zero();
+ abstract public Weight! extend(Weight! w1, Weight! w2);
+ abstract public Weight! combine(Weight! w1, Weight! w2);
+ abstract public Weight! isEqual(Weight! w);
+ abstract public Weight! projectLocals()
+ }
+ */
+
+ // Weight domain for LiveVariableAnalysis (Gen/Kill)
+
+ public class GenKillWeight {
+ // lambda S. (S - kill) union gen
+ HashSet<Variable/*!*/>/*!*/ gen;
+ HashSet<Variable/*!*/>/*!*/ kill;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(gen));
+ Contract.Invariant(cce.NonNullElements(kill));
+ Contract.Invariant(oneWeight != null);
+ Contract.Invariant(zeroWeight != null);
+ }
+
+ bool isZero;
+
+ public static GenKillWeight/*!*/ oneWeight = new GenKillWeight(new HashSet<Variable/*!*/>(), new HashSet<Variable/*!*/>());
+ public static GenKillWeight/*!*/ zeroWeight = new GenKillWeight();
+
+ // initializes to zero
+ public GenKillWeight() {
+ this.isZero = true;
+ this.gen = new HashSet<Variable/*!*/>();
+ this.kill = new HashSet<Variable/*!*/>();
+ }
+
+ public GenKillWeight(HashSet<Variable/*!*/> gen, HashSet<Variable/*!*/> kill) {
+ Contract.Requires(cce.NonNullElements(gen));
+ Contract.Requires(cce.NonNullElements(kill));
+ Contract.Assert(gen != null);
+ Contract.Assert(kill != null);
+ this.gen = gen;
+ this.kill = kill;
+ this.isZero = false;
+ }
+
+ public static GenKillWeight one() {
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ return oneWeight;
+ }
+
+ public static GenKillWeight zero() {
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ return zeroWeight;
+ }
+
+ public static GenKillWeight extend(GenKillWeight w1, GenKillWeight w2) {
+ Contract.Requires(w2 != null);
+ Contract.Requires(w1 != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ if (w1.isZero || w2.isZero)
+ return zero();
+
+ HashSet<Variable> t = new HashSet<Variable>(w2.gen);
+ t.ExceptWith(w1.kill);
+ HashSet<Variable> g = new HashSet<Variable>(w1.gen);
+ g.UnionWith(t);
+ HashSet<Variable> k = new HashSet<Variable>(w1.kill);
+ k.UnionWith(w2.kill);
+ return new GenKillWeight(g, k);
+ //return new GenKillWeight(w1.gen.Union(w2.gen.Difference(w1.kill)), w1.kill.Union(w2.kill));
+ }
+
+ public static GenKillWeight combine(GenKillWeight w1, GenKillWeight w2) {
+ Contract.Requires(w2 != null);
+ Contract.Requires(w1 != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ if (w1.isZero)
+ return w2;
+ if (w2.isZero)
+ return w1;
+
+ HashSet<Variable> g = new HashSet<Variable>(w1.gen);
+ g.UnionWith(w2.gen);
+ HashSet<Variable> k = new HashSet<Variable>(w1.kill);
+ k.IntersectWith(w2.kill);
+ return new GenKillWeight(g, k);
+ //return new GenKillWeight(w1.gen.Union(w2.gen), w1.kill.Intersection(w2.kill));
+ }
+
+ public static GenKillWeight projectLocals(GenKillWeight w) {
+ Contract.Requires(w != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ HashSet<Variable/*!*/> gen = new HashSet<Variable>();
+ foreach (Variable v in w.gen)
+ {
+ if (isGlobal(v))
+ gen.Add(v);
+ }
+ HashSet<Variable/*!*/> kill = new HashSet<Variable>();
+ foreach (Variable v in w.kill)
+ {
+ if (isGlobal(v))
+ kill.Add(v);
+ }
+
+ return new GenKillWeight(gen, kill);
+ }
+
+ public static bool isEqual(GenKillWeight w1, GenKillWeight w2) {
+ Contract.Requires(w2 != null);
+ Contract.Requires(w1 != null);
+ if (w1.isZero)
+ return w2.isZero;
+ if (w2.isZero)
+ return w1.isZero;
+
+ return (w1.gen.Equals(w2.gen) && w1.kill.Equals(w2.kill));
+ }
+
+ private static bool isGlobal(Variable v) {
+ Contract.Requires(v != null);
+ return (v is GlobalVariable);
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return string.Format("({0},{1})", gen.ToString(), kill.ToString());
+ }
+
+ public HashSet<Variable/*!*/>/*!*/ getLiveVars() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
+ return gen;
+ }
+
+ public HashSet<Variable/*!*/>/*!*/ getLiveVars(HashSet<Variable/*!*/>/*!*/ lv) {
+ Contract.Requires(cce.NonNullElements(lv));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
+ HashSet<Variable> temp = new HashSet<Variable>(lv);
+ temp.ExceptWith(kill);
+ temp.UnionWith(gen);
+ return temp;
+ }
+
+ }
+
+ public class ICFG {
+ public Graph<Block/*!*/>/*!*/ graph;
+ // Map from procedure to the list of blocks that call that procedure
+ public Dictionary<string/*!*/, List<Block/*!*/>/*!*/>/*!*/ procsCalled;
+ public HashSet<Block/*!*/>/*!*/ nodes;
+ public Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>/*!*/ succEdges;
+ public Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>/*!*/ predEdges;
+ private Dictionary<Block/*!*/, int>/*!*/ priority;
+
+ public HashSet<Block/*!*/>/*!*/ srcNodes;
+ public HashSet<Block/*!*/>/*!*/ exitNodes;
+
+ public Dictionary<Block/*!*/, GenKillWeight/*!*/>/*!*/ weightBefore;
+ public Dictionary<Block/*!*/, GenKillWeight/*!*/>/*!*/ weightAfter;
+ public Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ liveVarsAfter;
+ public Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ liveVarsBefore;
+
+ public GenKillWeight/*!*/ summary;
+ public Implementation/*!*/ impl;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(graph.Nodes));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(procsCalled));
+ Contract.Invariant(cce.NonNullElements(nodes));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(succEdges));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(predEdges));
+ Contract.Invariant(priority != null);
+ Contract.Invariant(cce.NonNullElements(srcNodes));
+ Contract.Invariant(cce.NonNullElements(exitNodes));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(weightBefore));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(weightAfter));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(liveVarsAfter));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(liveVarsBefore));
+ Contract.Invariant(summary != null);
+ Contract.Invariant(impl != null);
+ }
+
+
+ [NotDelayed]
+ public ICFG(Implementation impl) {
+ Contract.Requires(impl != null);
+ this.graph = new Graph<Block/*!*/>();
+ this.procsCalled = new Dictionary<string/*!*/, List<Block/*!*/>/*!*/>();
+ this.nodes = new HashSet<Block/*!*/>();
+ this.succEdges = new Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>();
+ this.predEdges = new Dictionary<Block/*!*/, HashSet<Block/*!*/>/*!*/>();
+
+ this.priority = new Dictionary<Block/*!*/, int>();
+
+ this.srcNodes = new HashSet<Block/*!*/>();
+ this.exitNodes = new HashSet<Block/*!*/>();
+
+ this.weightBefore = new Dictionary<Block/*!*/, GenKillWeight/*!*/>();
+ this.weightAfter = new Dictionary<Block/*!*/, GenKillWeight/*!*/>();
+ this.liveVarsAfter = new Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>();
+ this.liveVarsBefore = new Dictionary<Block/*!*/, HashSet<Variable/*!*/>/*!*/>();
+
+ summary = GenKillWeight.zero();
+ this.impl = impl;
+
+ Initialize(impl);
+
+ }
+
+ private void Initialize(Implementation impl) {
+ Contract.Requires(impl != null);
+ addSource(impl.Blocks[0]);
+ graph.AddSource(impl.Blocks[0]);
+
+ foreach (Block/*!*/ b in impl.Blocks) {
+ Contract.Assert(b != null);
+ if (b.TransferCmd is ReturnCmd) {
+ exitNodes.Add(b);
+ } else {
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ Contract.Assert(gc != null);
+ Contract.Assert(gc.labelTargets != null);
+ foreach (Block/*!*/ t in gc.labelTargets) {
+ Contract.Assert(t != null);
+ addEdge(b, t);
+ graph.AddEdge(b, t);
+ }
+ }
+
+ weightBefore[b] = GenKillWeight.zero();
+ weightAfter[b] = GenKillWeight.zero();
+
+ foreach (Cmd/*!*/ c in b.Cmds) {
+ Contract.Assert(c != null);
+ if (c is CallCmd) {
+ CallCmd/*!*/ cc = cce.NonNull((CallCmd/*!*/)c);
+ Contract.Assert(cc.Proc != null);
+ string/*!*/ procName = cc.Proc.Name;
+ Contract.Assert(procName != null);
+ if (!procsCalled.ContainsKey(procName)) {
+ procsCalled.Add(procName, new List<Block/*!*/>());
+ }
+ procsCalled[procName].Add(b);
+ }
+ }
+ }
+
+ List<Block>/*!*/ sortedNodes;
+ bool acyclic;
+
+ graph.TarjanTopSort(out acyclic, out sortedNodes);
+
+ if (!acyclic) {
+ Console.WriteLine("Warning: graph is not a dag");
+ }
+
+ int num = sortedNodes.Count;
+ foreach (Block/*!*/ b in sortedNodes) {
+ Contract.Assert(b != null);
+ priority.Add(b, num);
+ num--;
+ }
+
+ }
+
+ public int getPriority(Block b) {
+ Contract.Requires(b != null);
+ if (priority.ContainsKey(b))
+ return priority[b];
+ return Int32.MaxValue;
+ }
+
+ private void addSource(Block b) {
+ Contract.Requires(b != null);
+ registerNode(b);
+ this.srcNodes.Add(b);
+ }
+
+ private void addExit(Block b) {
+ Contract.Requires(b != null);
+ registerNode(b);
+ this.exitNodes.Add(b);
+ }
+
+ private void registerNode(Block b) {
+ Contract.Requires(b != null);
+ if (!succEdges.ContainsKey(b)) {
+ succEdges.Add(b, new HashSet<Block/*!*/>());
+ }
+
+ if (!predEdges.ContainsKey(b)) {
+ predEdges.Add(b, new HashSet<Block/*!*/>());
+ }
+
+ nodes.Add(b);
+ }
+
+ private void addEdge(Block src, Block tgt) {
+ Contract.Requires(tgt != null);
+ Contract.Requires(src != null);
+ registerNode(src);
+ registerNode(tgt);
+
+ succEdges[src].Add(tgt);
+ predEdges[tgt].Add(src);
+ }
+
+
+ }
+
+ // Interprocedural Gen/Kill Analysis
+ public class InterProcGenKill {
+ Program/*!*/ program;
+ Dictionary<string/*!*/, ICFG/*!*/>/*!*/ procICFG;
+ Dictionary<string/*!*/, Procedure/*!*/>/*!*/ name2Proc;
+ Dictionary<string/*!*/, List<WorkItem/*!*/>/*!*/>/*!*/ callers;
+ Graph<string/*!*/>/*!*/ callGraph;
+ Dictionary<string/*!*/, int>/*!*/ procPriority;
+ int maxBlocksInProc;
+
+ WorkList/*!*/ workList;
+
+ Implementation/*!*/ mainImpl;
+
+ static Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ varsLiveAtExit = new Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>();
+ static Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>/*!*/ varsLiveAtEntry = new Dictionary<string/*!*/, HashSet<Variable/*!*/>/*!*/>();
+ static Dictionary<string/*!*/, GenKillWeight/*!*/>/*!*/ varsLiveSummary = new Dictionary<string/*!*/, GenKillWeight/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(workList != null);
+ Contract.Invariant(mainImpl != null);
+ Contract.Invariant(program != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(procICFG));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(name2Proc));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(callers) &&
+ Contract.ForAll(callers.Values, v => cce.NonNullElements(v)));
+ Contract.Invariant(cce.NonNullElements(callGraph.Nodes));
+ Contract.Invariant(procPriority != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(varsLiveAtEntry));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(varsLiveAtExit) &&
+ Contract.ForAll(varsLiveAtExit.Values, v => cce.NonNullElements(v)));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(varsLiveSummary));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(weightCacheAfterCall));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(weightCacheBeforeCall));
+ }
+
+
+ [NotDelayed]
+ public InterProcGenKill(Implementation impl, Program program) {
+ Contract.Requires(program != null);
+ Contract.Requires(impl != null);
+ this.program = program;
+ procICFG = new Dictionary<string/*!*/, ICFG/*!*/>();
+ name2Proc = new Dictionary<string/*!*/, Procedure/*!*/>();
+ workList = new WorkList();
+ this.callers = new Dictionary<string/*!*/, List<WorkItem/*!*/>/*!*/>();
+ this.callGraph = new Graph<string/*!*/>();
+ this.procPriority = new Dictionary<string/*!*/, int>();
+ this.maxBlocksInProc = 0;
+ this.mainImpl = impl;
+
+ Dictionary<string/*!*/, Implementation/*!*/>/*!*/ name2Impl = new Dictionary<string/*!*/, Implementation/*!*/>();
+ varsLiveAtExit.Clear();
+ varsLiveAtEntry.Clear();
+ varsLiveSummary.Clear();
+
+ foreach (var decl in program.TopLevelDeclarations) {
+ Contract.Assert(decl != null);
+ if (decl is Implementation) {
+ Implementation/*!*/ imp = (Implementation/*!*/)cce.NonNull(decl);
+ name2Impl[imp.Name] = imp;
+ } else if (decl is Procedure) {
+ Procedure/*!*/ proc = cce.NonNull(decl as Procedure);
+ name2Proc[proc.Name] = proc;
+ }
+ }
+
+ ICFG/*!*/ mainICFG = new ICFG(mainImpl);
+ Contract.Assert(mainICFG != null);
+ procICFG.Add(mainICFG.impl.Name, mainICFG);
+ callGraph.AddSource(mainICFG.impl.Name);
+
+ List<ICFG/*!*/>/*!*/ procsToConsider = new List<ICFG/*!*/>();
+ procsToConsider.Add(mainICFG);
+
+ while (procsToConsider.Count != 0) {
+ ICFG/*!*/ p = procsToConsider[0];
+ Contract.Assert(p != null);
+ procsToConsider.RemoveAt(0);
+
+ foreach (string/*!*/ callee in p.procsCalled.Keys) {
+ Contract.Assert(callee != null);
+ if (!name2Impl.ContainsKey(callee))
+ continue;
+
+ callGraph.AddEdge(p.impl.Name, callee);
+
+ if (maxBlocksInProc < p.nodes.Count) {
+ maxBlocksInProc = p.nodes.Count;
+ }
+
+ if (!callers.ContainsKey(callee)) {
+ callers.Add(callee, new List<WorkItem/*!*/>());
+ }
+ foreach (Block/*!*/ b in p.procsCalled[callee]) {
+ Contract.Assert(b != null);
+ callers[callee].Add(new WorkItem(p, b));
+ }
+
+ if (procICFG.ContainsKey(callee))
+ continue;
+ ICFG/*!*/ ncfg = new ICFG(name2Impl[callee]);
+ Contract.Assert(ncfg != null);
+ procICFG.Add(callee, ncfg);
+ procsToConsider.Add(ncfg);
+ }
+ }
+
+ bool acyclic;
+ List<string>/*!*/ sortedNodes;
+ callGraph.TarjanTopSort(out acyclic, out sortedNodes);
+
+ Contract.Assert(acyclic);
+
+ int cnt = 0;
+ for (int i = sortedNodes.Count - 1; i >= 0; i--) {
+ string s = sortedNodes[i];
+ if (s == null)
+ continue;
+ procPriority.Add(s, cnt);
+ cnt++;
+ }
+
+ }
+
+ public static HashSet<Variable/*!*/>/*!*/ GetVarsLiveAtExit(Implementation impl, Program prog) {
+ Contract.Requires(prog != null);
+ Contract.Requires(impl != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
+ if (varsLiveAtExit.ContainsKey(impl.Name)) {
+ return varsLiveAtExit[impl.Name];
+ }
+ // Return default: all globals and out params
+ HashSet<Variable/*!*/>/*!*/ lv = new HashSet<Variable/*!*/>();
+ foreach (Variable/*!*/ v in prog.GlobalVariables) {
+ Contract.Assert(v != null);
+ lv.Add(v);
+ }
+ foreach (Variable/*!*/ v in impl.OutParams) {
+ Contract.Assert(v != null);
+ lv.Add(v);
+ }
+ return lv;
+ }
+
+ public static HashSet<Variable/*!*/>/*!*/ GetVarsLiveAtEntry(Implementation impl, Program prog) {
+ Contract.Requires(prog != null);
+ Contract.Requires(impl != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
+ if (varsLiveAtEntry.ContainsKey(impl.Name)) {
+ return varsLiveAtEntry[impl.Name];
+ }
+ // Return default: all globals and in params
+ HashSet<Variable/*!*/>/*!*/ lv = new HashSet<Variable/*!*/>();
+ foreach (Variable/*!*/ v in prog.GlobalVariables) {
+ Contract.Assert(v != null);
+ lv.Add(v);
+ }
+ foreach (Variable/*!*/ v in impl.InParams) {
+ Contract.Assert(v != null);
+ lv.Add(v);
+ }
+ return lv;
+ }
+
+ public static bool HasSummary(string name) {
+ Contract.Requires(name != null);
+ return varsLiveSummary.ContainsKey(name);
+ }
+
+ public static HashSet<Variable/*!*/>/*!*/ PropagateLiveVarsAcrossCall(CallCmd cmd, HashSet<Variable/*!*/>/*!*/ lvAfter) {
+ Contract.Requires(cmd != null);
+ Contract.Requires(cce.NonNullElements(lvAfter));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<HashSet<Variable>>()));
+ Procedure/*!*/ proc = cce.NonNull(cmd.Proc);
+ if (varsLiveSummary.ContainsKey(proc.Name)) {
+ GenKillWeight/*!*/ w1 = getWeightBeforeCall(cmd);
+ Contract.Assert(w1 != null);
+ GenKillWeight/*!*/ w2 = varsLiveSummary[proc.Name];
+ Contract.Assert(w2 != null);
+ GenKillWeight/*!*/ w3 = getWeightAfterCall(cmd);
+ Contract.Assert(w3 != null);
+ GenKillWeight/*!*/ w = GenKillWeight.extend(w1, GenKillWeight.extend(w2, w3));
+ Contract.Assert(w != null);
+ return w.getLiveVars(lvAfter);
+ }
+ HashSet<Variable/*!*/>/*!*/ ret = new HashSet<Variable/*!*/>();
+ ret.UnionWith(lvAfter);
+ LiveVariableAnalysis.Propagate(cmd, ret);
+ return ret;
+ }
+
+ class WorkItem {
+ public ICFG/*!*/ cfg;
+ public Block/*!*/ block;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cfg != null);
+ Contract.Invariant(block != null);
+ }
+
+
+ public WorkItem(ICFG cfg, Block block) {
+ Contract.Requires(block != null);
+ Contract.Requires(cfg != null);
+ this.cfg = cfg;
+ this.block = block;
+ }
+
+ public GenKillWeight getWeightAfter() {
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ return cfg.weightAfter[block];
+ }
+
+ public bool setWeightBefore(GenKillWeight w) {
+ Contract.Requires(w != null);
+ GenKillWeight/*!*/ prev = cfg.weightBefore[block];
+ Contract.Assert(prev != null);
+ GenKillWeight/*!*/ curr = GenKillWeight.combine(w, prev);
+ Contract.Assert(curr != null);
+ if (GenKillWeight.isEqual(prev, curr))
+ return false;
+ cfg.weightBefore[block] = curr;
+ return true;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object other) {
+ WorkItem/*!*/ wi = (WorkItem/*!*/)cce.NonNull(other);
+ return (wi.cfg == cfg && wi.block == block);
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return 0;
+ }
+
+ public string getLabel() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return cfg.impl.Name + "::" + block.Label;
+ }
+
+ }
+
+ private void AddToWorkList(WorkItem wi) {
+ Contract.Requires(wi != null);
+ int i = procPriority[wi.cfg.impl.Name];
+ int j = wi.cfg.getPriority(wi.block);
+ int priority = (i * maxBlocksInProc) + j;
+
+ workList.Add(wi, priority);
+ }
+
+ private void AddToWorkListReverse(WorkItem wi) {
+ Contract.Requires(wi != null);
+ int i = procPriority[wi.cfg.impl.Name];
+ int j = wi.cfg.getPriority(wi.block);
+ int priority = (procPriority.Count - i) * maxBlocksInProc + j;
+ workList.Add(wi, priority);
+ }
+
+ class WorkList {
+ SortedList<int, int>/*!*/ priorities;
+ HashSet<string/*!*/>/*!*/ labels;
+
+ Dictionary<int, List<WorkItem/*!*/>/*!*/>/*!*/ workList;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(priorities != null);
+ Contract.Invariant(cce.NonNullElements(labels));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(workList) &&
+ Contract.ForAll(workList.Values, v => cce.NonNullElements(v)));
+ }
+
+
+ public WorkList() {
+ labels = new HashSet<string/*!*/>();
+ priorities = new SortedList<int, int>();
+ workList = new Dictionary<int, List<WorkItem/*!*/>/*!*/>();
+ }
+
+ public void Add(WorkItem wi, int priority) {
+ Contract.Requires(wi != null);
+ string/*!*/ lab = wi.getLabel();
+ Contract.Assert(lab != null);
+ if (labels.Contains(lab)) {
+ // Already on worklist
+ return;
+ }
+ labels.Add(lab);
+ if (!workList.ContainsKey(priority)) {
+ workList.Add(priority, new List<WorkItem/*!*/>());
+ }
+ workList[priority].Add(wi);
+ if (!priorities.ContainsKey(priority)) {
+ priorities.Add(priority, 0);
+ }
+
+ priorities[priority] = priorities[priority] + 1;
+ }
+
+ public WorkItem Get() {
+ Contract.Ensures(Contract.Result<WorkItem>() != null);
+ // Get minimum priority
+ int p = cce.NonNull(priorities.Keys)[0];
+ priorities[p] = priorities[p] - 1;
+ if (priorities[p] == 0) {
+ priorities.Remove(p);
+ }
+
+ // Get a WI with this priority
+ WorkItem/*!*/ wi = workList[p][0];
+ Contract.Assert(wi != null);
+ workList[p].RemoveAt(0);
+
+ // update labels
+ labels.Remove(wi.getLabel());
+ return wi;
+ }
+
+ public int Count {
+ get {
+ return labels.Count;
+ }
+ }
+ }
+
+ private GenKillWeight getSummary(CallCmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ Contract.Assert(cmd.Proc != null);
+ string/*!*/ procName = cmd.Proc.Name;
+ Contract.Assert(procName != null);
+ if (procICFG.ContainsKey(procName)) {
+ ICFG/*!*/ cfg = procICFG[procName];
+ Contract.Assert(cfg != null);
+ return GenKillWeight.projectLocals(cfg.summary);
+ }
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ public static void ComputeLiveVars(Implementation impl, Program/*!*/ prog) {
+ Contract.Requires(prog != null);
+ Contract.Requires(impl != null);
+ InterProcGenKill/*!*/ ipgk = new InterProcGenKill(impl, prog);
+ Contract.Assert(ipgk != null);
+ ipgk.Compute();
+ }
+
+ public void Compute() {
+ // Put all exit nodes in the worklist
+ foreach (ICFG/*!*/ cfg in procICFG.Values) {
+ Contract.Assert(cfg != null);
+ foreach (Block/*!*/ eb in cfg.exitNodes) {
+ Contract.Assert(eb != null);
+ WorkItem/*!*/ wi = new WorkItem(cfg, eb);
+ Contract.Assert(wi != null);
+ cfg.weightAfter[eb] = GenKillWeight.one();
+ AddToWorkList(wi);
+ }
+ }
+
+ while (workList.Count != 0) {
+ WorkItem/*!*/ wi = workList.Get();
+ Contract.Assert(wi != null);
+ process(wi);
+ }
+
+ // Propagate LV to all procedures
+ foreach (ICFG/*!*/ cfg in procICFG.Values) {
+ Contract.Assert(cfg != null);
+ foreach (Block/*!*/ b in cfg.nodes) {
+ Contract.Assert(b != null);
+ cfg.liveVarsAfter.Add(b, new HashSet<Variable/*!*/>());
+ cfg.liveVarsBefore.Add(b, new HashSet<Variable/*!*/>());
+ }
+ }
+
+ ICFG/*!*/ mainCfg = procICFG[mainImpl.Name];
+ Contract.Assert(mainCfg != null);
+ foreach (Block/*!*/ eb in mainCfg.exitNodes) {
+ Contract.Assert(eb != null);
+ WorkItem/*!*/ wi = new WorkItem(mainCfg, eb);
+ Contract.Assert(wi != null);
+ AddToWorkListReverse(wi);
+ }
+
+ while (workList.Count != 0) {
+ WorkItem/*!*/ wi = workList.Get();
+ Contract.Assert(wi != null);
+ processLV(wi);
+ }
+
+ // Set live variable info
+ foreach (ICFG/*!*/ cfg in procICFG.Values) {
+ Contract.Assert(cfg != null);
+ HashSet<Variable/*!*/>/*!*/ lv = new HashSet<Variable/*!*/>();
+ foreach (Block/*!*/ eb in cfg.exitNodes) {
+ Contract.Assert(eb != null);
+ lv.UnionWith(cfg.liveVarsAfter[eb]);
+ }
+ varsLiveAtExit.Add(cfg.impl.Name, lv);
+ lv = new HashSet<Variable/*!*/>();
+ foreach (Block/*!*/ eb in cfg.srcNodes) {
+ Contract.Assert(eb != null);
+ lv.UnionWith(cfg.liveVarsBefore[eb]);
+ }
+ varsLiveAtEntry.Add(cfg.impl.Name, lv);
+ varsLiveSummary.Add(cfg.impl.Name, cfg.summary);
+ }
+
+ /*
+ foreach(Block/*!*/
+ /* b in mainImpl.Blocks){
+Contract.Assert(b != null);
+//Set<Variable!> lv = cfg.weightBefore[b].getLiveVars();
+b.liveVarsBefore = procICFG[mainImpl.Name].liveVarsAfter[b];
+//foreach(GlobalVariable/*!*/
+ /* v in program.GlobalVariables){Contract.Assert(v != null);
+// b.liveVarsBefore.Add(v);
+//}
+}
+*/
+ }
+
+ // Called when summaries have already been computed
+ private void processLV(WorkItem wi) {
+ Contract.Requires(wi != null);
+ ICFG/*!*/ cfg = wi.cfg;
+ Contract.Assert(cfg != null);
+ Block/*!*/ block = wi.block;
+ Contract.Assert(block != null);
+ HashSet<Variable/*!*/>/*!*/ lv = cfg.liveVarsAfter[block];
+ Contract.Assert(cce.NonNullElements(lv));
+ // Propagate backwards in the block
+ HashSet<Variable/*!*/>/*!*/ prop = new HashSet<Variable/*!*/>();
+ prop.UnionWith(lv);
+ for (int i = block.Cmds.Count - 1; i >= 0; i--) {
+ Cmd/*!*/ cmd = block.Cmds[i];
+ Contract.Assert(cmd != null);
+ if (cmd is CallCmd) {
+ string/*!*/ procName = cce.NonNull(cce.NonNull((CallCmd)cmd).Proc).Name;
+ Contract.Assert(procName != null);
+ if (procICFG.ContainsKey(procName)) {
+ ICFG/*!*/ callee = procICFG[procName];
+ Contract.Assert(callee != null);
+ // Inter propagation
+ // Remove local variables; add return variables
+ HashSet<Variable/*!*/>/*!*/ elv = new HashSet<Variable/*!*/>();
+ foreach (Variable/*!*/ v in prop) {
+ Contract.Assert(v != null);
+ if (v is GlobalVariable)
+ elv.Add(v);
+ }
+ foreach (Variable/*!*/ v in callee.impl.OutParams) {
+ Contract.Assert(v != null);
+ elv.Add(v);
+ }
+
+ foreach (Block/*!*/ eb in callee.exitNodes) {
+ Contract.Assert(eb != null);
+ callee.liveVarsAfter[eb].UnionWith(elv);
+ // TODO: check if modified before inserting
+ AddToWorkListReverse(new WorkItem(callee, eb));
+ }
+
+ // Continue with intra propagation
+ GenKillWeight/*!*/ summary = getWeightCall(cce.NonNull((CallCmd/*!*/)cmd));
+ prop = summary.getLiveVars(prop);
+ } else {
+ LiveVariableAnalysis.Propagate(cmd, prop);
+ }
+ } else {
+ LiveVariableAnalysis.Propagate(cmd, prop);
+ }
+ }
+
+ cfg.liveVarsBefore[block].UnionWith(prop);
+
+ foreach (Block/*!*/ b in cfg.predEdges[block]) {
+ Contract.Assert(b != null);
+ HashSet<Variable/*!*/>/*!*/ prev = cfg.liveVarsAfter[b];
+ Contract.Assert(cce.NonNullElements(prev));
+ HashSet<Variable/*!*/>/*!*/ curr = new HashSet<Variable>(prev);
+ curr.UnionWith(cfg.liveVarsBefore[block]);
+ Contract.Assert(cce.NonNullElements(curr));
+ if (curr.Count != prev.Count) {
+ cfg.liveVarsAfter[b] = curr;
+ AddToWorkListReverse(new WorkItem(cfg, b));
+ }
+ }
+ }
+
+ private void process(WorkItem wi) {
+ Contract.Requires(wi != null);
+ GenKillWeight/*!*/ w = wi.getWeightAfter();
+ Contract.Assert(w != null);
+
+ for (int i = wi.block.Cmds.Count - 1; i >= 0; i--) {
+ Cmd/*!*/ c = wi.block.Cmds[i];
+ Contract.Assert(c != null);
+ if (c is CallCmd && procICFG.ContainsKey(cce.NonNull(cce.NonNull((CallCmd)c).Proc).Name)) {
+ w = GenKillWeight.extend(getWeightCall(cce.NonNull((CallCmd)c)), w);
+ } else {
+ GenKillWeight/*!*/ cweight = getWeight(c, wi.cfg.impl, program);
+ Contract.Assert(cweight != null);
+ w = GenKillWeight.extend(cweight, w);
+ }
+ }
+
+ bool change = wi.setWeightBefore(w);
+
+ if (change && wi.cfg.srcNodes.Contains(wi.block)) {
+ GenKillWeight/*!*/ prev = wi.cfg.summary;
+ Contract.Assert(prev != null);
+ GenKillWeight/*!*/ curr = GenKillWeight.combine(prev, wi.cfg.weightBefore[wi.block]);
+ Contract.Assert(curr != null);
+ if (!GenKillWeight.isEqual(prev, curr)) {
+ wi.cfg.summary = curr;
+ // push callers onto the worklist
+ if (callers.ContainsKey(wi.cfg.impl.Name)) {
+ foreach (WorkItem/*!*/ caller in callers[wi.cfg.impl.Name]) {
+ Contract.Assert(caller != null);
+ AddToWorkList(caller);
+ }
+ }
+ }
+ }
+
+ foreach (Block/*!*/ b in wi.cfg.predEdges[wi.block]) {
+ Contract.Assert(b != null);
+ GenKillWeight/*!*/ prev = wi.cfg.weightAfter[b];
+ Contract.Assert(prev != null);
+ GenKillWeight/*!*/ curr = GenKillWeight.combine(prev, w);
+ Contract.Assert(curr != null);
+ if (!GenKillWeight.isEqual(prev, curr)) {
+ wi.cfg.weightAfter[b] = curr;
+ AddToWorkList(new WorkItem(wi.cfg, b));
+ }
+ }
+
+ }
+
+ static Dictionary<Cmd/*!*/, GenKillWeight/*!*/>/*!*/ weightCache = new Dictionary<Cmd/*!*/, GenKillWeight/*!*/>();
+
+ private static GenKillWeight getWeight(Cmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ return getWeight(cmd, null, null);
+ }
+
+ private GenKillWeight getWeightCall(CallCmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ GenKillWeight/*!*/ w1 = getWeightBeforeCall(cmd);
+ GenKillWeight/*!*/ w2 = getSummary(cmd);
+ GenKillWeight/*!*/ w3 = getWeightAfterCall(cmd);
+ Contract.Assert(w1 != null);
+ Contract.Assert(w2 != null);
+ Contract.Assert(w3 != null);
+ return GenKillWeight.extend(w1, GenKillWeight.extend(w2, w3));
+ }
+
+ private static GenKillWeight getWeight(Cmd cmd, Implementation impl, Program prog) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+
+ if (weightCache.ContainsKey(cmd))
+ return weightCache[cmd];
+
+ HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>();
+ HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>();
+ GenKillWeight/*!*/ ret;
+
+ if (cmd is AssignCmd) {
+ AssignCmd/*!*/ assignCmd = (AssignCmd)cmd;
+ Contract.Assert(cmd != null);
+ // I must first iterate over all the targets and remove the live ones.
+ // After the removals are done, I must add the variables referred on
+ // the right side of the removed targets
+ foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) {
+ Contract.Assert(lhs != null);
+ Variable var = lhs.DeepAssignedVariable;
+ if (var != null) {
+ if (lhs is SimpleAssignLhs) {
+ // we should only remove non-map target variables because there is an implicit
+ // read of a map variable in an assignment to it
+ kill.Add(var);
+ }
+ }
+ }
+ int index = 0;
+ foreach (Expr/*!*/ expr in assignCmd.Rhss) {
+ Contract.Assert(expr != null);
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(expr);
+ gen.UnionWith(collector.usedVars);
+ AssignLhs lhs = assignCmd.Lhss[index];
+ if (lhs is MapAssignLhs) {
+ // If the target is a map, then all indices are also read
+ MapAssignLhs malhs = (MapAssignLhs)lhs;
+ foreach (Expr e in malhs.Indexes) {
+ VariableCollector/*!*/ c = new VariableCollector();
+ c.Visit(e);
+ gen.UnionWith(c.usedVars);
+ }
+ }
+ index++;
+ }
+ ret = new GenKillWeight(gen, kill);
+ } else if (cmd is HavocCmd) {
+ HavocCmd/*!*/ havocCmd = (HavocCmd)cce.NonNull(cmd);
+ foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) {
+ Contract.Assert(expr != null);
+ if (expr.Decl != null) {
+ kill.Add(expr.Decl);
+ }
+ }
+ ret = new GenKillWeight(gen, kill);
+ } else if (cmd is PredicateCmd) {
+ Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd));
+ PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd);
+ if (predicateCmd.Expr is LiteralExpr && prog != null && impl != null) {
+ LiteralExpr le = (LiteralExpr)predicateCmd.Expr;
+ if (le.IsFalse) {
+ var globals = prog.GlobalVariables;
+ Contract.Assert(cce.NonNullElements(globals));
+ foreach (Variable/*!*/ v in globals) {
+ Contract.Assert(v != null);
+ kill.Add(v);
+ }
+ foreach (Variable/*!*/ v in impl.LocVars) {
+ Contract.Assert(v != null);
+ kill.Add(v);
+ }
+ foreach (Variable/*!*/ v in impl.OutParams) {
+ Contract.Assert(v != null);
+ kill.Add(v);
+ }
+ }
+ } else {
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(predicateCmd.Expr);
+ gen.UnionWith(collector.usedVars);
+ }
+ ret = new GenKillWeight(gen, kill);
+ } else if (cmd is CommentCmd) {
+ ret = new GenKillWeight(gen, kill);
+ // comments are just for debugging and don't affect verification
+ } else if (cmd is SugaredCmd) {
+ SugaredCmd/*!*/ sugCmd = (SugaredCmd)cmd;
+ Contract.Assert(sugCmd != null);
+ ret = getWeight(sugCmd.Desugaring, impl, prog);
+ } else if (cmd is StateCmd) {
+ StateCmd/*!*/ stCmd = (StateCmd)cmd;
+ Contract.Assert(stCmd != null);
+ List<Cmd>/*!*/ cmds = stCmd.Cmds;
+ Contract.Assert(cmds != null);
+ int len = cmds.Count;
+ ret = GenKillWeight.one();
+ for (int i = len - 1; i >= 0; i--) {
+ GenKillWeight/*!*/ w = getWeight(cmds[i], impl, prog);
+ Contract.Assert(w != null);
+ ret = GenKillWeight.extend(w, ret);
+ }
+ foreach (Variable/*!*/ v in stCmd.Locals) {
+ Contract.Assert(v != null);
+ kill.Add(v);
+ }
+ ret = GenKillWeight.extend(new GenKillWeight(gen, kill), ret);
+ } else {
+ {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ weightCache[cmd] = ret;
+ return ret;
+ }
+
+ static Dictionary<Cmd/*!*/, GenKillWeight/*!*/>/*!*/ weightCacheAfterCall = new Dictionary<Cmd/*!*/, GenKillWeight/*!*/>();
+ static Dictionary<Cmd/*!*/, GenKillWeight/*!*/>/*!*/ weightCacheBeforeCall = new Dictionary<Cmd/*!*/, GenKillWeight/*!*/>();
+
+ private static GenKillWeight getWeightAfterCall(Cmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+
+ if (weightCacheAfterCall.ContainsKey(cmd))
+ return weightCacheAfterCall[cmd];
+
+ HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>();
+ HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>();
+
+ Contract.Assert(cmd is CallCmd);
+ CallCmd/*!*/ ccmd = cce.NonNull((CallCmd)cmd);
+
+ foreach (IdentifierExpr/*!*/ ie in ccmd.Outs) {
+ Contract.Assert(ie != null);
+ if (ie.Decl != null)
+ kill.Add(ie.Decl);
+ }
+
+ // Variables in ensures are considered as "read"
+ foreach (Ensures/*!*/ re in cce.NonNull(ccmd.Proc).Ensures) {
+ Contract.Assert(re != null);
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(re.Condition);
+ foreach (Variable/*!*/ v in collector.usedVars) {
+ Contract.Assert(v != null);
+ if (v is GlobalVariable) {
+ gen.Add(v);
+ }
+ }
+ }
+
+ GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill);
+ Contract.Assert(ret != null);
+ weightCacheAfterCall[cmd] = ret;
+ return ret;
+ }
+
+ private static GenKillWeight getWeightBeforeCall(Cmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<GenKillWeight>() != null);
+ Contract.Assert((cmd is CallCmd));
+ if (weightCacheBeforeCall.ContainsKey(cmd))
+ return weightCacheBeforeCall[cmd];
+
+ HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>();
+ HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>();
+ CallCmd/*!*/ ccmd = cce.NonNull((CallCmd/*!*/)cmd);
+
+ foreach (Expr/*!*/ expr in ccmd.Ins) {
+ Contract.Assert(expr != null);
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(expr);
+ gen.UnionWith(collector.usedVars);
+ }
+
+ Contract.Assert(ccmd.Proc != null);
+
+ // Variables in requires are considered as "read"
+ foreach (Requires/*!*/ re in ccmd.Proc.Requires) {
+ Contract.Assert(re != null);
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(re.Condition);
+ foreach (Variable/*!*/ v in collector.usedVars) {
+ Contract.Assert(v != null);
+ if (v is GlobalVariable) {
+ gen.Add(v);
+ }
+ }
+ }
+
+ // Old variables in ensures are considered as "read"
+ foreach (Ensures/*!*/ re in ccmd.Proc.Ensures) {
+ Contract.Assert(re != null);
+ VariableCollector/*!*/ collector = new VariableCollector();
+ collector.Visit(re.Condition);
+ foreach (Variable/*!*/ v in collector.oldVarsUsed) {
+ Contract.Assert(v != null);
+ if (v is GlobalVariable) {
+ gen.Add(v);
+ }
+ }
+ }
+
+ GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill);
+ Contract.Assert(ret != null);
+ weightCacheAfterCall[cmd] = ret;
+ return ret;
+ }
+ }
+
+ public class TokenEliminator : ReadOnlyVisitor
+ {
+ public int TokenCount = 0;
+ public override Expr VisitExpr(Expr node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitExpr(node);
+ }
+ public override Variable VisitVariable(Variable node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitVariable(node);
+ }
+ public override Function VisitFunction(Function node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitFunction(node);
+ }
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitImplementation(node);
+ }
+ public override Procedure VisitProcedure(Procedure node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitProcedure(node);
+ }
+ public override Axiom VisitAxiom(Axiom node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitAxiom(node);
+ }
+ public override Cmd VisitAssignCmd(AssignCmd node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitAssignCmd(node);
+ }
+ public override Cmd VisitAssumeCmd(AssumeCmd node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitAssumeCmd(node);
+ }
+ public override Cmd VisitHavocCmd(HavocCmd node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitHavocCmd(node);
+ }
+ public override Constant VisitConstant(Constant node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitConstant(node);
+ }
+ public override TransferCmd VisitTransferCmd(TransferCmd node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitTransferCmd(node);
+ }
+ public override Block VisitBlock(Block node)
+ {
+ node.tok = Token.NoToken;
+ TokenCount++;
+ return base.VisitBlock(node);
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Core/Duplicator.cs b/Source/Core/Duplicator.cs
index 181b80a1..bbc7e0ad 100644
--- a/Source/Core/Duplicator.cs
+++ b/Source/Core/Duplicator.cs
@@ -1,794 +1,829 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Duplicator.cs
-//---------------------------------------------------------------------------------------------
-
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-
-namespace Microsoft.Boogie {
- public class Duplicator : StandardVisitor {
- // This is used to ensure that Procedures get duplicated only once
- // and that Implementation.Proc is resolved to the correct duplicated
- // Procedure.
- private Dictionary<Procedure,Procedure> OldToNewProcedureMap = null;
-
- public override Absy Visit(Absy node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
- node = base.Visit(node);
- return node;
- }
-
- public override Cmd VisitAssertCmd(AssertCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitAssertCmd((AssertCmd)node.Clone());
- }
- public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitAssertEnsuresCmd((AssertEnsuresCmd)node.Clone());
- }
- public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitAssertRequiresCmd((AssertRequiresCmd)node.Clone());
- }
- public override Cmd VisitAssignCmd(AssignCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- AssignCmd clone = (AssignCmd)node.Clone();
- clone.Lhss = new List<AssignLhs/*!*/>(clone.Lhss);
- clone.Rhss = new List<Expr/*!*/>(clone.Rhss);
- return base.VisitAssignCmd(clone);
- }
- public override Cmd VisitAssumeCmd(AssumeCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitAssumeCmd((AssumeCmd)node.Clone());
- }
- public override AtomicRE VisitAtomicRE(AtomicRE node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AtomicRE>() != null);
- return base.VisitAtomicRE((AtomicRE)node.Clone());
- }
- public override Axiom VisitAxiom(Axiom node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Axiom>() != null);
- return base.VisitAxiom((Axiom)node.Clone());
- }
- public override Type VisitBasicType(BasicType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // do /not/ clone the type recursively
- return (BasicType)node.Clone();
- }
- public override Block VisitBlock(Block node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Block>() != null);
- return base.VisitBlock((Block) node.Clone());
- }
- public override Expr VisitBvConcatExpr (BvConcatExpr node) {
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitBvConcatExpr((BvConcatExpr) node.Clone());
- }
- public override Expr VisitBvExtractExpr(BvExtractExpr node) {
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitBvExtractExpr((BvExtractExpr) node.Clone());
- }
- public override Expr VisitCodeExpr(CodeExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- CodeExpr clone = (CodeExpr)base.VisitCodeExpr((CodeExpr)node.Clone());
- // Before returning, fix up the resolved goto targets
- Contract.Assert(node.Blocks.Count == clone.Blocks.Count);
- Dictionary<Block, Block> subst = new Dictionary<Block, Block>();
- for (int i = 0; i < node.Blocks.Count; i++) {
- subst.Add(node.Blocks[i], clone.Blocks[i]);
- }
- foreach (Block/*!*/ b in clone.Blocks) {
- Contract.Assert(b != null);
- GotoCmd g = b.TransferCmd as GotoCmd;
- if (g != null) {
- List<Block> targets = new List<Block>();
- foreach (Block t in cce.NonNull(g.labelTargets)) {
- Block nt = subst[t];
- targets.Add(nt);
- }
- g.labelTargets = targets;
- }
- }
- return clone;
- }
- public override List<Block> VisitBlockSeq(List<Block> blockSeq) {
- //Contract.Requires(blockSeq != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
- return base.VisitBlockSeq(new List<Block>(blockSeq));
- }
- public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
- //Contract.Requires(cce.NonNullElements(blocks));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- return base.VisitBlockList(new List<Block/*!*/>(blocks));
- }
- public override BoundVariable VisitBoundVariable(BoundVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<BoundVariable>() != null);
- return base.VisitBoundVariable((BoundVariable)node.Clone());
- }
- public override Type VisitBvType(BvType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // do /not/ clone the type recursively
- return (BvType)node.Clone();
- }
- public override Cmd VisitCallCmd(CallCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- CallCmd clone = (CallCmd)node.Clone();
- Contract.Assert(clone != null);
- clone.Ins = new List<Expr>(clone.Ins);
- clone.Outs = new List<IdentifierExpr>(clone.Outs);
- return base.VisitCallCmd(clone);
- }
- public override Choice VisitChoice(Choice node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Choice>() != null);
- return base.VisitChoice((Choice)node.Clone());
- }
- public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
- //Contract.Requires(cmdSeq != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- return base.VisitCmdSeq(new List<Cmd>(cmdSeq));
- }
- public override Constant VisitConstant(Constant node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Constant>() != null);
- return base.VisitConstant((Constant)node.Clone());
- }
- public override CtorType VisitCtorType(CtorType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<CtorType>() != null);
- // do /not/ clone the type recursively
- return (CtorType)node.Clone();
- }
- public override Declaration VisitDeclaration(Declaration node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Declaration>() != null);
- return base.VisitDeclaration((Declaration)node.Clone());
- }
- public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
- //Contract.Requires(cce.NonNullElements(declarationList));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Declaration>>()));
-
- // For Implementation.Proc to resolve correctly to duplicated Procedures
- // we need to visit the procedures first
- for (int i = 0, n = declarationList.Count; i < n; i++) {
- if (!( declarationList[i] is Procedure ))
- continue;
-
- declarationList[i] = cce.NonNull((Declaration) this.Visit(declarationList[i]));
- }
-
- // Now visit everything else
- for (int i = 0, n = declarationList.Count; i < n; i++) {
- if (declarationList[i] is Procedure)
- continue;
-
- declarationList[i] = cce.NonNull((Declaration) this.Visit(declarationList[i]));
- }
- return declarationList;
- }
- public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
- return base.VisitDeclWithFormals((DeclWithFormals)node.Clone());
- }
- public override Ensures VisitEnsures(Ensures node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Ensures>() != null);
- return base.VisitEnsures((Ensures)node.Clone());
- }
- public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq)
- {
- //Contract.Requires(ensuresSeq != null);
- Contract.Ensures(Contract.Result<List<Ensures>>() != null);
- return base.VisitEnsuresSeq(new List<Ensures>(ensuresSeq));
- }
- public override Expr VisitExistsExpr(ExistsExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitExistsExpr((ExistsExpr)node.Clone());
- }
- public override Expr VisitExpr(Expr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitExpr((Expr)node.Clone());
- }
- public override IList<Expr> VisitExprSeq(IList<Expr> list) {
- //Contract.Requires(list != null);
- Contract.Ensures(Contract.Result<IList<Expr>>() != null);
- return base.VisitExprSeq(new List<Expr>(list));
- }
- public override Expr VisitForallExpr(ForallExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitForallExpr((ForallExpr)node.Clone());
- }
- public override Formal VisitFormal(Formal node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Formal>() != null);
- return base.VisitFormal((Formal)node.Clone());
- }
- public override Function VisitFunction(Function node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return base.VisitFunction((Function)node.Clone());
- }
- public override GlobalVariable VisitGlobalVariable(GlobalVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GlobalVariable>() != null);
- return base.VisitGlobalVariable((GlobalVariable)node.Clone());
- }
- public override GotoCmd VisitGotoCmd(GotoCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GotoCmd>() != null);
- // NOTE: This doesn't duplicate the labelTarget basic blocks
- // or resolve them to the new blocks
- // VisitImplementation() and VisitBlock() handle this
- return base.VisitGotoCmd( (GotoCmd)node.Clone());
- }
- public override Cmd VisitHavocCmd(HavocCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitHavocCmd((HavocCmd)node.Clone());
- }
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitIdentifierExpr((IdentifierExpr)node.Clone());
- }
- public override List<IdentifierExpr> VisitIdentifierExprSeq(List<IdentifierExpr> identifierExprSeq) {
- //Contract.Requires(identifierExprSeq != null);
- Contract.Ensures(Contract.Result<List<IdentifierExpr>>() != null);
- return base.VisitIdentifierExprSeq(new List<IdentifierExpr>(identifierExprSeq));
- }
- public override Implementation VisitImplementation(Implementation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- var impl = base.VisitImplementation((Implementation)node.Clone());
- var blockDuplicationMapping = new Dictionary<Block, Block>();
-
- // Compute the mapping between the blocks of the old implementation (node)
- // and the new implementation (impl).
- foreach (var blockPair in node.Blocks.Zip(impl.Blocks)) {
- blockDuplicationMapping.Add(blockPair.Item1, blockPair.Item2);
- }
-
- // The GotoCmds and blocks have now been duplicated.
- // Resolve GotoCmd targets to the duplicated blocks
- foreach (GotoCmd gotoCmd in impl.Blocks.Select( bb => bb.TransferCmd).OfType<GotoCmd>()) {
- var newLabelTargets = new List<Block>();
- var newLabelNames = new List<string>();
- for (int index = 0; index < gotoCmd.labelTargets.Count; ++index) {
- var newBlock = blockDuplicationMapping[gotoCmd.labelTargets[index]];
- newLabelTargets.Add(newBlock);
- newLabelNames.Add(newBlock.Label);
- }
- gotoCmd.labelTargets = newLabelTargets;
- gotoCmd.labelNames = newLabelNames;
- }
-
- return impl;
- }
- public override Expr VisitLiteralExpr(LiteralExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitLiteralExpr((LiteralExpr)node.Clone());
- }
- public override LocalVariable VisitLocalVariable(LocalVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<LocalVariable>() != null);
- return base.VisitLocalVariable((LocalVariable)node.Clone());
- }
- public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- MapAssignLhs clone = (MapAssignLhs)node.Clone();
- clone.Indexes = new List<Expr/*!*/>(clone.Indexes);
- return base.VisitMapAssignLhs(clone);
- }
- public override MapType VisitMapType(MapType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<MapType>() != null);
- // do /not/ clone the type recursively
- return (MapType)node.Clone();
- }
- public override Expr VisitNAryExpr(NAryExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitNAryExpr((NAryExpr)node.Clone());
- }
- public override Expr VisitOldExpr(OldExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return base.VisitOldExpr((OldExpr)node.Clone());
- }
- public override Cmd VisitParCallCmd(ParCallCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- ParCallCmd clone = (ParCallCmd)node.Clone();
- Contract.Assert(clone != null);
- clone.CallCmds = new List<CallCmd>(node.CallCmds);
- return base.VisitParCallCmd(clone);
- }
- public override Procedure VisitProcedure(Procedure node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Procedure>() != null);
- Procedure newProcedure = null;
- if (OldToNewProcedureMap != null && OldToNewProcedureMap.ContainsKey(node)) {
- newProcedure = OldToNewProcedureMap[node];
- } else {
- newProcedure = base.VisitProcedure((Procedure) node.Clone());
- if (OldToNewProcedureMap != null)
- OldToNewProcedureMap[node] = newProcedure;
- }
- return newProcedure;
- }
- public override Program VisitProgram(Program node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Program>() != null);
-
- // If cloning an entire program we need to ensure that
- // Implementation.Proc gets resolved to the right Procedure
- // (i.e. we don't duplicate Procedure twice) and CallCmds
- // call the right Procedure.
- // The map below is used to achieve this.
- OldToNewProcedureMap = new Dictionary<Procedure, Procedure>();
- var newProgram = base.VisitProgram((Program)node.Clone());
-
- // We need to make sure that CallCmds get resolved to call Procedures we duplicated
- // instead of pointing to procedures in the old program
- var callCmds = newProgram.Blocks().SelectMany(b => b.Cmds).OfType<CallCmd>();
- foreach (var callCmd in callCmds) {
- callCmd.Proc = OldToNewProcedureMap[callCmd.Proc];
- }
-
- OldToNewProcedureMap = null; // This Visitor could be used for other things later so remove the map.
- return newProgram;
- }
- public override QKeyValue VisitQKeyValue(QKeyValue node) {
- //Contract.Requires(node != null);
- var newParams = new List<object>();
- foreach (var o in node.Params) {
- var e = o as Expr;
- if (e == null) {
- newParams.Add(o);
- } else {
- newParams.Add((Expr)this.Visit(e));
- }
- }
- QKeyValue next = node.Next == null ? null : (QKeyValue)this.Visit(node.Next);
- return new QKeyValue(node.tok, node.Key, newParams, next);
- }
- public override BinderExpr VisitBinderExpr(BinderExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<BinderExpr>() != null);
- return base.VisitBinderExpr((BinderExpr)node.Clone());
- }
- public override Requires VisitRequires(Requires node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Requires>() != null);
- return base.VisitRequires((Requires)node.Clone());
- }
- public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq)
- {
- //Contract.Requires(requiresSeq != null);
- Contract.Ensures(Contract.Result<List<Requires>>() != null);
- return base.VisitRequiresSeq(new List<Requires>(requiresSeq));
- }
- public override Cmd VisitRE(RE node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitRE((RE)node.Clone());
- }
- public override List<RE> VisitRESeq(List<RE> reSeq) {
- //Contract.Requires(reSeq != null);
- Contract.Ensures(Contract.Result<List<RE>>() != null);
- return base.VisitRESeq(new List<RE>(reSeq));
- }
- public override ReturnCmd VisitReturnCmd(ReturnCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnCmd>() != null);
- return base.VisitReturnCmd((ReturnCmd)node.Clone());
- }
- public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
- return base.VisitReturnExprCmd((ReturnExprCmd)node.Clone());
- }
- public override Sequential VisitSequential(Sequential node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Sequential>() != null);
- return base.VisitSequential((Sequential)node.Clone());
- }
- public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- return base.VisitSimpleAssignLhs((SimpleAssignLhs)node.Clone());
- }
- public override Cmd VisitStateCmd(StateCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return base.VisitStateCmd((StateCmd)node.Clone());
- }
- public override TransferCmd VisitTransferCmd(TransferCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TransferCmd>() != null);
- return base.VisitTransferCmd((TransferCmd)node.Clone());
- }
- public override Trigger VisitTrigger(Trigger node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Trigger>() != null);
- return base.VisitTrigger((Trigger)node.Clone());
- }
- public override Type VisitType(Type node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // do /not/ clone the type recursively
- return (Type)node.Clone();
- }
- public override TypedIdent VisitTypedIdent(TypedIdent node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TypedIdent>() != null);
- return base.VisitTypedIdent((TypedIdent)node.Clone());
- }
- public override Variable VisitVariable(Variable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
- return node;
- }
- public override List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
- //Contract.Requires(variableSeq != null);
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- return base.VisitVariableSeq(new List<Variable>(variableSeq));
- }
- public override YieldCmd VisitYieldCmd(YieldCmd node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<YieldCmd>() != null);
- return base.VisitYieldCmd((YieldCmd)node.Clone());
- }
- }
-
-
- #region A duplicator that also does substitutions for a set of variables
- /// <summary>
- /// A substitution is a partial mapping from Variables to Exprs.
- /// </summary>
- public delegate Expr/*?*/ Substitution(Variable/*!*/ v);
-
- public static class Substituter {
- public static Substitution SubstitutionFromHashtable(Dictionary<Variable, Expr> map, bool fallBackOnName = false, Procedure proc = null)
- {
- Contract.Requires(map != null);
- Contract.Ensures(Contract.Result<Substitution>() != null);
- // TODO: With Whidbey, could use anonymous functions.
- return new Substitution(new CreateSubstitutionClosure(map, fallBackOnName, proc).Method);
- }
- private sealed class CreateSubstitutionClosure {
- Dictionary<Variable /*!*/, Expr /*!*/>/*!*/ map;
- Dictionary<string /*!*/, Expr /*!*/>/*!*/ nameMap;
- Procedure proc;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(map != null);
- }
-
- static string UniqueName(Variable variable, Procedure proc)
- {
- // TODO(wuestholz): Maybe we should define structural equality for variables instead.
- var scope = "#global_scope#";
- if (proc != null && !(variable is GlobalVariable || variable is Constant))
- {
- scope = proc.Name;
- }
- return string.Format("{0}.{1}", scope, variable.Name);
- }
-
- public CreateSubstitutionClosure(Dictionary<Variable, Expr> map, bool fallBackOnName = false, Procedure proc = null)
- : base() {
- Contract.Requires(map != null);
- this.map = map;
- this.proc = proc;
- if (fallBackOnName && proc != null)
- {
- this.nameMap = map.ToDictionary(kv => UniqueName(kv.Key, proc), kv => kv.Value);
- }
- }
- public Expr/*?*/ Method(Variable v) {
- Contract.Requires(v != null);
- if(map.ContainsKey(v)) {
- return map[v];
- }
- Expr e;
- if (nameMap != null && proc != null && nameMap.TryGetValue(UniqueName(v, proc), out e))
- {
- return e;
- }
- return null;
- }
- }
-
- // ----------------------------- Substitutions for Expr -------------------------------
-
- /// <summary>
- /// Apply a substitution to an expression. Any variables not in domain(subst)
- /// is not changed. The substitutions apply within the "old", but the "old"
- /// expression remains.
- /// </summary>
- public static Expr Apply(Substitution subst, Expr expr) {
- Contract.Requires(subst != null);
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return (Expr)new NormalSubstituter(subst).Visit(expr);
- }
-
- /// <summary>
- /// Apply a substitution to an expression.
- /// Outside "old" expressions, the substitution "always" is applied; any variable not in
- /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
- /// variables in domain(forOld), apply map "always" to variables in
- /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
- /// </summary>
- public static Expr Apply(Substitution always, Substitution forold, Expr expr) {
- Contract.Requires(always != null);
- Contract.Requires(forold != null);
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return (Expr)new NormalSubstituter(always, forold).Visit(expr);
- }
-
- /// <summary>
- /// Apply a substitution to an expression replacing "old" expressions.
- /// Outside "old" expressions, the substitution "always" is applied; any variable not in
- /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
- /// variables in domain(forOld), apply map "always" to variables in
- /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
- /// </summary>
- public static Expr ApplyReplacingOldExprs(Substitution always, Substitution forOld, Expr expr) {
- Contract.Requires(always != null);
- Contract.Requires(forOld != null);
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return (Expr)new ReplacingOldSubstituter(always, forOld).Visit(expr);
- }
-
- public static Expr FunctionCallReresolvingApplyReplacingOldExprs(Substitution always, Substitution forOld, Expr expr, Program program)
- {
- Contract.Requires(always != null);
- Contract.Requires(forOld != null);
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return (Expr)new FunctionCallReresolvingReplacingOldSubstituter(program, always, forOld).Visit(expr);
- }
-
- // ----------------------------- Substitutions for Cmd -------------------------------
-
- /// <summary>
- /// Apply a substitution to a command. Any variables not in domain(subst)
- /// is not changed. The substitutions apply within the "old", but the "old"
- /// expression remains.
- /// </summary>
- public static Cmd Apply(Substitution subst, Cmd cmd) {
- Contract.Requires(subst != null);
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return (Cmd)new NormalSubstituter(subst).Visit(cmd);
- }
-
- /// <summary>
- /// Apply a substitution to a command.
- /// Outside "old" expressions, the substitution "always" is applied; any variable not in
- /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
- /// variables in domain(forOld), apply map "always" to variables in
- /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
- /// </summary>
- public static Cmd Apply(Substitution always, Substitution forOld, Cmd cmd)
- {
- Contract.Requires(always != null);
- Contract.Requires(forOld != null);
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return (Cmd)new NormalSubstituter(always, forOld).Visit(cmd);
- }
-
- /// <summary>
- /// Apply a substitution to a command replacing "old" expressions.
- /// Outside "old" expressions, the substitution "always" is applied; any variable not in
- /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
- /// variables in domain(forOld), apply map "always" to variables in
- /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
- /// </summary>
- public static Cmd ApplyReplacingOldExprs(Substitution always, Substitution forOld, Cmd cmd) {
- Contract.Requires(always != null);
- Contract.Requires(forOld != null);
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return (Cmd)new ReplacingOldSubstituter(always, forOld).Visit(cmd);
- }
-
- // ----------------------------- Substitutions for QKeyValue -------------------------------
-
- /// <summary>
- /// Apply a substitution to a list of attributes. Any variables not in domain(subst)
- /// is not changed. The substitutions apply within the "old", but the "old"
- /// expression remains.
- /// </summary>
- public static QKeyValue Apply(Substitution subst, QKeyValue kv) {
- Contract.Requires(subst != null);
- if (kv == null) {
- return null;
- } else {
- return (QKeyValue)new NormalSubstituter(subst).Visit(kv);
- }
- }
-
- /// <summary>
- /// Apply a substitution to a list of attributes replacing "old" expressions.
- /// For a further description, see "ApplyReplacingOldExprs" above for Expr.
- /// </summary>
- public static QKeyValue ApplyReplacingOldExprs(Substitution always, Substitution forOld, QKeyValue kv) {
- Contract.Requires(always != null);
- Contract.Requires(forOld != null);
- if (kv == null) {
- return null;
- } else {
- return (QKeyValue)new ReplacingOldSubstituter(always, forOld).Visit(kv);
- }
- }
-
- // ------------------------------------------------------------
-
- private sealed class NormalSubstituter : Duplicator
- {
- private readonly Substitution/*!*/ always;
- private readonly Substitution/*!*/ forold;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(always != null);
- Contract.Invariant(forold != null);
- }
-
- public NormalSubstituter(Substitution subst)
- : base() {
- Contract.Requires(subst != null);
- this.always = subst;
- this.forold = Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>());
- }
-
- public NormalSubstituter(Substitution subst, Substitution forold)
- : base()
- {
- Contract.Requires(subst != null);
- this.always = subst;
- this.forold = forold;
- }
-
- private bool insideOldExpr = false;
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Expr/*?*/ e = null;
-
- if (insideOldExpr)
- {
- e = forold(cce.NonNull(node.Decl));
- }
-
- if (e == null)
- {
- e = always(cce.NonNull(node.Decl));
- }
-
- return e == null ? base.VisitIdentifierExpr(node) : e;
- }
-
- public override Expr VisitOldExpr(OldExpr node)
- {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- bool previouslyInOld = insideOldExpr;
- insideOldExpr = true;
- Expr/*!*/ e = (Expr/*!*/)cce.NonNull(this.Visit(node.Expr));
- insideOldExpr = previouslyInOld;
- return new OldExpr(node.tok, e);
- }
- }
-
- private sealed class FunctionCallReresolvingReplacingOldSubstituter : ReplacingOldSubstituter
- {
- readonly Program Program;
-
- public FunctionCallReresolvingReplacingOldSubstituter(Program program, Substitution always, Substitution forold)
- : base(always, forold)
- {
- Program = program;
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- var result = base.VisitNAryExpr(node);
- var nAryExpr = result as NAryExpr;
- if (nAryExpr != null)
- {
- var funCall = nAryExpr.Fun as FunctionCall;
- if (funCall != null)
- {
- funCall.Func = Program.FindFunction(funCall.FunctionName);
- }
- }
- return result;
- }
- }
-
- private class ReplacingOldSubstituter : Duplicator {
- private readonly Substitution/*!*/ always;
- private readonly Substitution/*!*/ forold;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(always != null);
- Contract.Invariant(forold != null);
- }
-
- public ReplacingOldSubstituter(Substitution always, Substitution forold)
- : base() {
- Contract.Requires(forold != null);
- Contract.Requires(always != null);
- this.always = always;
- this.forold = forold;
- }
-
- private bool insideOldExpr = false;
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Expr/*?*/ e = null;
-
- if (insideOldExpr) {
- e = forold(cce.NonNull(node.Decl));
- }
-
- if (e == null) {
- e = always(cce.NonNull(node.Decl));
- }
-
- return e == null ? base.VisitIdentifierExpr(node) : e;
- }
-
- public override Expr VisitOldExpr(OldExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- bool previouslyInOld = insideOldExpr;
- insideOldExpr = true;
- Expr/*!*/ e = (Expr/*!*/)cce.NonNull(this.Visit(node.Expr));
- insideOldExpr = previouslyInOld;
- return e;
- }
- }
- }
- #endregion
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - Duplicator.cs
+//---------------------------------------------------------------------------------------------
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+
+namespace Microsoft.Boogie {
+ public class Duplicator : StandardVisitor {
+ // This is used to ensure that Procedures get duplicated only once
+ // and that Implementation.Proc is resolved to the correct duplicated
+ // Procedure.
+ private Dictionary<Procedure,Procedure> OldToNewProcedureMap = null;
+
+ public override Absy Visit(Absy node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+ node = base.Visit(node);
+ return node;
+ }
+
+ public override Cmd VisitAssertCmd(AssertCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitAssertCmd((AssertCmd)node.Clone());
+ }
+ public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitAssertEnsuresCmd((AssertEnsuresCmd)node.Clone());
+ }
+ public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitAssertRequiresCmd((AssertRequiresCmd)node.Clone());
+ }
+ public override Cmd VisitAssignCmd(AssignCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ AssignCmd clone = (AssignCmd)node.Clone();
+ clone.Lhss = new List<AssignLhs/*!*/>(clone.Lhss);
+ clone.Rhss = new List<Expr/*!*/>(clone.Rhss);
+ return base.VisitAssignCmd(clone);
+ }
+ public override Cmd VisitAssumeCmd(AssumeCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitAssumeCmd((AssumeCmd)node.Clone());
+ }
+ public override AtomicRE VisitAtomicRE(AtomicRE node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AtomicRE>() != null);
+ return base.VisitAtomicRE((AtomicRE)node.Clone());
+ }
+ public override Axiom VisitAxiom(Axiom node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Axiom>() != null);
+ return base.VisitAxiom((Axiom)node.Clone());
+ }
+ public override Type VisitBasicType(BasicType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // do /not/ clone the type recursively
+ return (BasicType)node.Clone();
+ }
+ public override Block VisitBlock(Block node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+ return base.VisitBlock((Block) node.Clone());
+ }
+ public override Expr VisitBvConcatExpr (BvConcatExpr node) {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitBvConcatExpr((BvConcatExpr) node.Clone());
+ }
+ public override Expr VisitBvExtractExpr(BvExtractExpr node) {
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitBvExtractExpr((BvExtractExpr) node.Clone());
+ }
+ public override Expr VisitCodeExpr(CodeExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ CodeExpr clone = (CodeExpr)base.VisitCodeExpr((CodeExpr)node.Clone());
+ // Before returning, fix up the resolved goto targets
+ Contract.Assert(node.Blocks.Count == clone.Blocks.Count);
+ Dictionary<Block, Block> subst = new Dictionary<Block, Block>();
+ for (int i = 0; i < node.Blocks.Count; i++) {
+ subst.Add(node.Blocks[i], clone.Blocks[i]);
+ }
+ foreach (Block/*!*/ b in clone.Blocks) {
+ Contract.Assert(b != null);
+ GotoCmd g = b.TransferCmd as GotoCmd;
+ if (g != null) {
+ List<Block> targets = new List<Block>();
+ foreach (Block t in cce.NonNull(g.labelTargets)) {
+ Block nt = subst[t];
+ targets.Add(nt);
+ }
+ g.labelTargets = targets;
+ }
+ }
+ return clone;
+ }
+ public override List<Block> VisitBlockSeq(List<Block> blockSeq) {
+ //Contract.Requires(blockSeq != null);
+ Contract.Ensures(Contract.Result<List<Block>>() != null);
+ return base.VisitBlockSeq(new List<Block>(blockSeq));
+ }
+ public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
+ //Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+ return base.VisitBlockList(new List<Block/*!*/>(blocks));
+ }
+ public override BoundVariable VisitBoundVariable(BoundVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<BoundVariable>() != null);
+ return base.VisitBoundVariable((BoundVariable)node.Clone());
+ }
+ public override Type VisitBvType(BvType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // do /not/ clone the type recursively
+ return (BvType)node.Clone();
+ }
+ public override Cmd VisitCallCmd(CallCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ CallCmd clone = (CallCmd)node.Clone();
+ Contract.Assert(clone != null);
+ clone.Ins = new List<Expr>(clone.Ins);
+ clone.Outs = new List<IdentifierExpr>(clone.Outs);
+ return base.VisitCallCmd(clone);
+ }
+ public override Choice VisitChoice(Choice node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Choice>() != null);
+ return base.VisitChoice((Choice)node.Clone());
+ }
+ public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
+ //Contract.Requires(cmdSeq != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ return base.VisitCmdSeq(new List<Cmd>(cmdSeq));
+ }
+ public override Constant VisitConstant(Constant node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Constant>() != null);
+ return base.VisitConstant((Constant)node.Clone());
+ }
+ public override CtorType VisitCtorType(CtorType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+ // do /not/ clone the type recursively
+ return (CtorType)node.Clone();
+ }
+ public override Declaration VisitDeclaration(Declaration node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Declaration>() != null);
+ return base.VisitDeclaration((Declaration)node.Clone());
+ }
+ public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
+ //Contract.Requires(cce.NonNullElements(declarationList));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Declaration>>()));
+
+ // For Implementation.Proc to resolve correctly to duplicated Procedures
+ // we need to visit the procedures first
+ for (int i = 0, n = declarationList.Count; i < n; i++) {
+ if (!( declarationList[i] is Procedure ))
+ continue;
+
+ declarationList[i] = cce.NonNull((Declaration) this.Visit(declarationList[i]));
+ }
+
+ // Now visit everything else
+ for (int i = 0, n = declarationList.Count; i < n; i++) {
+ if (declarationList[i] is Procedure)
+ continue;
+
+ declarationList[i] = cce.NonNull((Declaration) this.Visit(declarationList[i]));
+ }
+ return declarationList;
+ }
+ public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
+ return base.VisitDeclWithFormals((DeclWithFormals)node.Clone());
+ }
+ public override Ensures VisitEnsures(Ensures node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Ensures>() != null);
+ return base.VisitEnsures((Ensures)node.Clone());
+ }
+ public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq)
+ {
+ //Contract.Requires(ensuresSeq != null);
+ Contract.Ensures(Contract.Result<List<Ensures>>() != null);
+ return base.VisitEnsuresSeq(new List<Ensures>(ensuresSeq));
+ }
+ public override Expr VisitExistsExpr(ExistsExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitExistsExpr((ExistsExpr)node.Clone());
+ }
+ public override Expr VisitExpr(Expr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitExpr((Expr)node.Clone());
+ }
+ public override IList<Expr> VisitExprSeq(IList<Expr> list) {
+ //Contract.Requires(list != null);
+ Contract.Ensures(Contract.Result<IList<Expr>>() != null);
+ return base.VisitExprSeq(new List<Expr>(list));
+ }
+ public override Expr VisitForallExpr(ForallExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitForallExpr((ForallExpr)node.Clone());
+ }
+ public override Formal VisitFormal(Formal node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Formal>() != null);
+ return base.VisitFormal((Formal)node.Clone());
+ }
+ public override Function VisitFunction(Function node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return base.VisitFunction((Function)node.Clone());
+ }
+ public override GlobalVariable VisitGlobalVariable(GlobalVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<GlobalVariable>() != null);
+ return base.VisitGlobalVariable((GlobalVariable)node.Clone());
+ }
+ public override GotoCmd VisitGotoCmd(GotoCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<GotoCmd>() != null);
+ // NOTE: This doesn't duplicate the labelTarget basic blocks
+ // or resolve them to the new blocks
+ // VisitImplementation() and VisitBlock() handle this
+ return base.VisitGotoCmd( (GotoCmd)node.Clone());
+ }
+ public override Cmd VisitHavocCmd(HavocCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitHavocCmd((HavocCmd)node.Clone());
+ }
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitIdentifierExpr((IdentifierExpr)node.Clone());
+ }
+ public override List<IdentifierExpr> VisitIdentifierExprSeq(List<IdentifierExpr> identifierExprSeq) {
+ //Contract.Requires(identifierExprSeq != null);
+ Contract.Ensures(Contract.Result<List<IdentifierExpr>>() != null);
+ return base.VisitIdentifierExprSeq(new List<IdentifierExpr>(identifierExprSeq));
+ }
+ public override Implementation VisitImplementation(Implementation node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Implementation>() != null);
+ var impl = base.VisitImplementation((Implementation)node.Clone());
+ var blockDuplicationMapping = new Dictionary<Block, Block>();
+
+ // Compute the mapping between the blocks of the old implementation (node)
+ // and the new implementation (impl).
+ foreach (var blockPair in node.Blocks.Zip(impl.Blocks)) {
+ blockDuplicationMapping.Add(blockPair.Item1, blockPair.Item2);
+ }
+
+ // The GotoCmds and blocks have now been duplicated.
+ // Resolve GotoCmd targets to the duplicated blocks
+ foreach (GotoCmd gotoCmd in impl.Blocks.Select( bb => bb.TransferCmd).OfType<GotoCmd>()) {
+ var newLabelTargets = new List<Block>();
+ var newLabelNames = new List<string>();
+ for (int index = 0; index < gotoCmd.labelTargets.Count; ++index) {
+ var newBlock = blockDuplicationMapping[gotoCmd.labelTargets[index]];
+ newLabelTargets.Add(newBlock);
+ newLabelNames.Add(newBlock.Label);
+ }
+ gotoCmd.labelTargets = newLabelTargets;
+ gotoCmd.labelNames = newLabelNames;
+ }
+
+ return impl;
+ }
+ public override Expr VisitLiteralExpr(LiteralExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitLiteralExpr((LiteralExpr)node.Clone());
+ }
+ public override LocalVariable VisitLocalVariable(LocalVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<LocalVariable>() != null);
+ return base.VisitLocalVariable((LocalVariable)node.Clone());
+ }
+ public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ MapAssignLhs clone = (MapAssignLhs)node.Clone();
+ clone.Indexes = new List<Expr/*!*/>(clone.Indexes);
+ return base.VisitMapAssignLhs(clone);
+ }
+ public override MapType VisitMapType(MapType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<MapType>() != null);
+ // do /not/ clone the type recursively
+ return (MapType)node.Clone();
+ }
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitNAryExpr((NAryExpr)node.Clone());
+ }
+ public override Expr VisitOldExpr(OldExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return base.VisitOldExpr((OldExpr)node.Clone());
+ }
+ public override Cmd VisitParCallCmd(ParCallCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ ParCallCmd clone = (ParCallCmd)node.Clone();
+ Contract.Assert(clone != null);
+ clone.CallCmds = new List<CallCmd>(node.CallCmds);
+ return base.VisitParCallCmd(clone);
+ }
+ public override Procedure VisitProcedure(Procedure node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Procedure>() != null);
+ Procedure newProcedure = null;
+ if (OldToNewProcedureMap != null && OldToNewProcedureMap.ContainsKey(node)) {
+ newProcedure = OldToNewProcedureMap[node];
+ } else {
+ newProcedure = base.VisitProcedure((Procedure) node.Clone());
+ if (OldToNewProcedureMap != null)
+ OldToNewProcedureMap[node] = newProcedure;
+ }
+ return newProcedure;
+ }
+ public override Program VisitProgram(Program node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Program>() != null);
+
+ // If cloning an entire program we need to ensure that
+ // Implementation.Proc gets resolved to the right Procedure
+ // (i.e. we don't duplicate Procedure twice) and CallCmds
+ // call the right Procedure.
+ // The map below is used to achieve this.
+ OldToNewProcedureMap = new Dictionary<Procedure, Procedure>();
+ var newProgram = base.VisitProgram((Program)node.Clone());
+
+ // We need to make sure that CallCmds get resolved to call Procedures we duplicated
+ // instead of pointing to procedures in the old program
+ var callCmds = newProgram.Blocks().SelectMany(b => b.Cmds).OfType<CallCmd>();
+ foreach (var callCmd in callCmds) {
+ callCmd.Proc = OldToNewProcedureMap[callCmd.Proc];
+ }
+
+ OldToNewProcedureMap = null; // This Visitor could be used for other things later so remove the map.
+ return newProgram;
+ }
+ public override QKeyValue VisitQKeyValue(QKeyValue node) {
+ //Contract.Requires(node != null);
+ var newParams = new List<object>();
+ foreach (var o in node.Params) {
+ var e = o as Expr;
+ if (e == null) {
+ newParams.Add(o);
+ } else {
+ newParams.Add((Expr)this.Visit(e));
+ }
+ }
+ QKeyValue next = node.Next == null ? null : (QKeyValue)this.Visit(node.Next);
+ return new QKeyValue(node.tok, node.Key, newParams, next);
+ }
+ public override BinderExpr VisitBinderExpr(BinderExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<BinderExpr>() != null);
+ return base.VisitBinderExpr((BinderExpr)node.Clone());
+ }
+ public override Requires VisitRequires(Requires node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Requires>() != null);
+ return base.VisitRequires((Requires)node.Clone());
+ }
+ public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq)
+ {
+ //Contract.Requires(requiresSeq != null);
+ Contract.Ensures(Contract.Result<List<Requires>>() != null);
+ return base.VisitRequiresSeq(new List<Requires>(requiresSeq));
+ }
+ public override Cmd VisitRE(RE node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitRE((RE)node.Clone());
+ }
+ public override List<RE> VisitRESeq(List<RE> reSeq) {
+ //Contract.Requires(reSeq != null);
+ Contract.Ensures(Contract.Result<List<RE>>() != null);
+ return base.VisitRESeq(new List<RE>(reSeq));
+ }
+ public override ReturnCmd VisitReturnCmd(ReturnCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<ReturnCmd>() != null);
+ return base.VisitReturnCmd((ReturnCmd)node.Clone());
+ }
+ public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
+ return base.VisitReturnExprCmd((ReturnExprCmd)node.Clone());
+ }
+ public override Sequential VisitSequential(Sequential node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Sequential>() != null);
+ return base.VisitSequential((Sequential)node.Clone());
+ }
+ public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ return base.VisitSimpleAssignLhs((SimpleAssignLhs)node.Clone());
+ }
+ public override Cmd VisitStateCmd(StateCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return base.VisitStateCmd((StateCmd)node.Clone());
+ }
+ public override TransferCmd VisitTransferCmd(TransferCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<TransferCmd>() != null);
+ return base.VisitTransferCmd((TransferCmd)node.Clone());
+ }
+ public override Trigger VisitTrigger(Trigger node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Trigger>() != null);
+ return base.VisitTrigger((Trigger)node.Clone());
+ }
+ public override Type VisitType(Type node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // do /not/ clone the type recursively
+ return (Type)node.Clone();
+ }
+ public override TypedIdent VisitTypedIdent(TypedIdent node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<TypedIdent>() != null);
+ return base.VisitTypedIdent((TypedIdent)node.Clone());
+ }
+ public override Variable VisitVariable(Variable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Variable>() != null);
+ return node;
+ }
+ public override List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
+ //Contract.Requires(variableSeq != null);
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ return base.VisitVariableSeq(new List<Variable>(variableSeq));
+ }
+ public override YieldCmd VisitYieldCmd(YieldCmd node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<YieldCmd>() != null);
+ return base.VisitYieldCmd((YieldCmd)node.Clone());
+ }
+ }
+
+
+ #region A duplicator that also does substitutions for a set of variables
+ /// <summary>
+ /// A substitution is a partial mapping from Variables to Exprs.
+ /// </summary>
+ public delegate Expr/*?*/ Substitution(Variable/*!*/ v);
+
+ public static class Substituter {
+ public static Substitution SubstitutionFromHashtable(Dictionary<Variable, Expr> map, bool fallBackOnName = false, Procedure proc = null)
+ {
+ Contract.Requires(map != null);
+ Contract.Ensures(Contract.Result<Substitution>() != null);
+ // TODO: With Whidbey, could use anonymous functions.
+ return new Substitution(new CreateSubstitutionClosure(map, fallBackOnName, proc).Method);
+ }
+ private sealed class CreateSubstitutionClosure {
+ Dictionary<Variable /*!*/, Expr /*!*/>/*!*/ map;
+ Dictionary<string /*!*/, Expr /*!*/>/*!*/ nameMap;
+ Procedure proc;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(map != null);
+ }
+
+ static string UniqueName(Variable variable, Procedure proc)
+ {
+ // TODO(wuestholz): Maybe we should define structural equality for variables instead.
+ var scope = "#global_scope#";
+ if (proc != null && !(variable is GlobalVariable || variable is Constant))
+ {
+ scope = proc.Name;
+ }
+ return string.Format("{0}.{1}", scope, variable.Name);
+ }
+
+ public CreateSubstitutionClosure(Dictionary<Variable, Expr> map, bool fallBackOnName = false, Procedure proc = null)
+ : base() {
+ Contract.Requires(map != null);
+ this.map = map;
+ this.proc = proc;
+ if (fallBackOnName && proc != null)
+ {
+ this.nameMap = map.ToDictionary(kv => UniqueName(kv.Key, proc), kv => kv.Value);
+ }
+ }
+ public Expr/*?*/ Method(Variable v) {
+ Contract.Requires(v != null);
+ if(map.ContainsKey(v)) {
+ return map[v];
+ }
+ Expr e;
+ if (nameMap != null && proc != null && nameMap.TryGetValue(UniqueName(v, proc), out e))
+ {
+ return e;
+ }
+ return null;
+ }
+ }
+
+ // ----------------------------- Substitutions for Expr -------------------------------
+
+ /// <summary>
+ /// Apply a substitution to an expression. Any variables not in domain(subst)
+ /// is not changed. The substitutions apply within the "old", but the "old"
+ /// expression remains.
+ /// </summary>
+ public static Expr Apply(Substitution subst, Expr expr) {
+ Contract.Requires(subst != null);
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return (Expr)new NormalSubstituter(subst).Visit(expr);
+ }
+
+ /// <summary>
+ /// Apply a substitution to an expression.
+ /// Outside "old" expressions, the substitution "always" is applied; any variable not in
+ /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
+ /// variables in domain(forOld), apply map "always" to variables in
+ /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
+ /// </summary>
+ public static Expr Apply(Substitution always, Substitution forold, Expr expr) {
+ Contract.Requires(always != null);
+ Contract.Requires(forold != null);
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return (Expr)new NormalSubstituter(always, forold).Visit(expr);
+ }
+
+ /// <summary>
+ /// Apply a substitution to an expression replacing "old" expressions.
+ /// Outside "old" expressions, the substitution "always" is applied; any variable not in
+ /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
+ /// variables in domain(forOld), apply map "always" to variables in
+ /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
+ /// </summary>
+ public static Expr ApplyReplacingOldExprs(Substitution always, Substitution forOld, Expr expr) {
+ Contract.Requires(always != null);
+ Contract.Requires(forOld != null);
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return (Expr)new ReplacingOldSubstituter(always, forOld).Visit(expr);
+ }
+
+ public static Expr FunctionCallReresolvingApplyReplacingOldExprs(Substitution always, Substitution forOld, Expr expr, Program program)
+ {
+ Contract.Requires(always != null);
+ Contract.Requires(forOld != null);
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return (Expr)new FunctionCallReresolvingReplacingOldSubstituter(program, always, forOld).Visit(expr);
+ }
+
+ public static Expr FunctionCallReresolvingApply(Substitution always, Substitution forOld, Expr expr, Program program)
+ {
+ Contract.Requires(always != null);
+ Contract.Requires(forOld != null);
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return (Expr)new FunctionCallReresolvingNormalSubstituter(program, always, forOld).Visit(expr);
+ }
+
+ // ----------------------------- Substitutions for Cmd -------------------------------
+
+ /// <summary>
+ /// Apply a substitution to a command. Any variables not in domain(subst)
+ /// is not changed. The substitutions apply within the "old", but the "old"
+ /// expression remains.
+ /// </summary>
+ public static Cmd Apply(Substitution subst, Cmd cmd) {
+ Contract.Requires(subst != null);
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return (Cmd)new NormalSubstituter(subst).Visit(cmd);
+ }
+
+ /// <summary>
+ /// Apply a substitution to a command.
+ /// Outside "old" expressions, the substitution "always" is applied; any variable not in
+ /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
+ /// variables in domain(forOld), apply map "always" to variables in
+ /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
+ /// </summary>
+ public static Cmd Apply(Substitution always, Substitution forOld, Cmd cmd)
+ {
+ Contract.Requires(always != null);
+ Contract.Requires(forOld != null);
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return (Cmd)new NormalSubstituter(always, forOld).Visit(cmd);
+ }
+
+ /// <summary>
+ /// Apply a substitution to a command replacing "old" expressions.
+ /// Outside "old" expressions, the substitution "always" is applied; any variable not in
+ /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to
+ /// variables in domain(forOld), apply map "always" to variables in
+ /// domain(always)-domain(forOld), and leave variable unchanged otherwise.
+ /// </summary>
+ public static Cmd ApplyReplacingOldExprs(Substitution always, Substitution forOld, Cmd cmd) {
+ Contract.Requires(always != null);
+ Contract.Requires(forOld != null);
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return (Cmd)new ReplacingOldSubstituter(always, forOld).Visit(cmd);
+ }
+
+ // ----------------------------- Substitutions for QKeyValue -------------------------------
+
+ /// <summary>
+ /// Apply a substitution to a list of attributes. Any variables not in domain(subst)
+ /// is not changed. The substitutions apply within the "old", but the "old"
+ /// expression remains.
+ /// </summary>
+ public static QKeyValue Apply(Substitution subst, QKeyValue kv) {
+ Contract.Requires(subst != null);
+ if (kv == null) {
+ return null;
+ } else {
+ return (QKeyValue)new NormalSubstituter(subst).Visit(kv);
+ }
+ }
+
+ /// <summary>
+ /// Apply a substitution to a list of attributes replacing "old" expressions.
+ /// For a further description, see "ApplyReplacingOldExprs" above for Expr.
+ /// </summary>
+ public static QKeyValue ApplyReplacingOldExprs(Substitution always, Substitution forOld, QKeyValue kv) {
+ Contract.Requires(always != null);
+ Contract.Requires(forOld != null);
+ if (kv == null) {
+ return null;
+ } else {
+ return (QKeyValue)new ReplacingOldSubstituter(always, forOld).Visit(kv);
+ }
+ }
+
+ // ------------------------------------------------------------
+
+ private class NormalSubstituter : Duplicator
+ {
+ private readonly Substitution/*!*/ always;
+ private readonly Substitution/*!*/ forold;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(always != null);
+ Contract.Invariant(forold != null);
+ }
+
+ public NormalSubstituter(Substitution subst)
+ : base() {
+ Contract.Requires(subst != null);
+ this.always = subst;
+ this.forold = Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>());
+ }
+
+ public NormalSubstituter(Substitution subst, Substitution forold)
+ : base()
+ {
+ Contract.Requires(subst != null);
+ this.always = subst;
+ this.forold = forold;
+ }
+
+ private bool insideOldExpr = false;
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Expr/*?*/ e = null;
+
+ if (insideOldExpr)
+ {
+ e = forold(cce.NonNull(node.Decl));
+ }
+
+ if (e == null)
+ {
+ e = always(cce.NonNull(node.Decl));
+ }
+
+ return e == null ? base.VisitIdentifierExpr(node) : e;
+ }
+
+ public override Expr VisitOldExpr(OldExpr node)
+ {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ bool previouslyInOld = insideOldExpr;
+ insideOldExpr = true;
+ Expr/*!*/ e = (Expr/*!*/)cce.NonNull(this.Visit(node.Expr));
+ insideOldExpr = previouslyInOld;
+ return new OldExpr(node.tok, e);
+ }
+ }
+
+ private sealed class FunctionCallReresolvingReplacingOldSubstituter : ReplacingOldSubstituter
+ {
+ readonly Program Program;
+
+ public FunctionCallReresolvingReplacingOldSubstituter(Program program, Substitution always, Substitution forold)
+ : base(always, forold)
+ {
+ Program = program;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ var result = base.VisitNAryExpr(node);
+ var nAryExpr = result as NAryExpr;
+ if (nAryExpr != null)
+ {
+ var funCall = nAryExpr.Fun as FunctionCall;
+ if (funCall != null)
+ {
+ funCall.Func = Program.FindFunction(funCall.FunctionName);
+ }
+ }
+ return result;
+ }
+ }
+
+ private sealed class FunctionCallReresolvingNormalSubstituter : NormalSubstituter
+ {
+ readonly Program Program;
+
+ public FunctionCallReresolvingNormalSubstituter(Program program, Substitution always, Substitution forold)
+ : base(always, forold)
+ {
+ Program = program;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ var result = base.VisitNAryExpr(node);
+ var nAryExpr = result as NAryExpr;
+ if (nAryExpr != null)
+ {
+ var funCall = nAryExpr.Fun as FunctionCall;
+ if (funCall != null)
+ {
+ funCall.Func = Program.FindFunction(funCall.FunctionName);
+ }
+ }
+ return result;
+ }
+ }
+
+ private class ReplacingOldSubstituter : Duplicator {
+ private readonly Substitution/*!*/ always;
+ private readonly Substitution/*!*/ forold;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(always != null);
+ Contract.Invariant(forold != null);
+ }
+
+ public ReplacingOldSubstituter(Substitution always, Substitution forold)
+ : base() {
+ Contract.Requires(forold != null);
+ Contract.Requires(always != null);
+ this.always = always;
+ this.forold = forold;
+ }
+
+ private bool insideOldExpr = false;
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Expr/*?*/ e = null;
+
+ if (insideOldExpr) {
+ e = forold(cce.NonNull(node.Decl));
+ }
+
+ if (e == null) {
+ e = always(cce.NonNull(node.Decl));
+ }
+
+ return e == null ? base.VisitIdentifierExpr(node) : e;
+ }
+
+ public override Expr VisitOldExpr(OldExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ bool previouslyInOld = insideOldExpr;
+ insideOldExpr = true;
+ Expr/*!*/ e = (Expr/*!*/)cce.NonNull(this.Visit(node.Expr));
+ insideOldExpr = previouslyInOld;
+ return e;
+ }
+ }
+ }
+ #endregion
+}
diff --git a/Source/Core/Graph.as b/Source/Core/Graph.as
deleted file mode 100644
index 1466c341..00000000
--- a/Source/Core/Graph.as
+++ /dev/null
@@ -1,352 +0,0 @@
-using System.Collections;
-namespace Graphing;
-
-type Node = object;
-type Edge = <Node,Node>;
-
-class PreHeader {
- Node myHeader;
- PreHeader(Node h) { myHeader = h; }
-
- public override string ToString() { return "#" + myHeader.ToString(); }
-}
-
-public class Graph {
- private Set<Edge> es;
- private Set<Node> ns;
- private Node source;
- private bool reducible;
- private Set<Node> headers;
- private Map<Node,Set<Node>> backEdgeNodes;
- private Map<Edge,Set<Node>> naturalLoops;
- private Map<Node,Set<Node>> dominatorMap;
- private Map<Node,Set<Node>> immediateDominatorMap;
-
- public Graph(Set<Edge> edges)
- {
- es = edges;
- ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
- }
- public Graph()
- { es = Set<Edge>{}; ns = Set<Node>{}; }
-
- public void AddSource(Node x)
- {
- ns += Set<Node>{x};
- source = x;
- }
- public void AddEdge(Node source, Node dest)
- {
- es += Set<Edge>{<source,dest>};
- ns += Set<Node>{source, dest};
- }
-
- public Set<Node> Nodes { get { return ns; } }
- public Set<Edge> Edges { get { return es; } }
-
- public bool Edge(Node x, Node y) { return <x,y> in es; }
- Set<Node> predecessors(Node n)
- {
- Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
- return result;
- }
- public override string ToString() { return es.ToString(); }
-
- public IEnumerable TopologicalSort()
- {
- <bool,Seq<Node>> <res,ns> = TopSort(this);
- return res ? ns : null;
- }
- public void ComputeLoops()
- {
- <bool, Set<Node>, Map<Node,Set<Node>>, Map<Edge,Set<Node>>>
- <reducible,headers,backEdgeNodes,naturalLoops> = Reducible(this,this.source);
- this.reducible = reducible;
- this.headers = headers;
- this.backEdgeNodes = backEdgeNodes;
- this.naturalLoops = naturalLoops;
- return;
- }
- public bool Reducible { get { return reducible; } }
- public IEnumerable Headers { get { return headers; } }
- public IEnumerable BackEdgeNodes(Node h) { return h in backEdgeNodes ? backEdgeNodes[h] : null; }
- public IEnumerable NaturalLoops(Node header, Node backEdgeNode)
- { Edge e = <backEdgeNode,header>; return e in naturalLoops ? naturalLoops[e] : null; }
- public bool Acyclic { get { return Acyclic(this,this.source); } }
- public Map<Node,Set<Node>> DominatorMap
- {
- get {
- if (dominatorMap == null) dominatorMap = ComputeDominators(this, source);
- return dominatorMap;
- }
- }
- public Map<Node,Set<Node>> ImmediateDominatorMap
- {
- get {
- if (immediateDominatorMap == null)
- {
- immediateDominatorMap = Map{};
- foreach(Node y in Nodes)
- {
- Set<Node> nodesThatYDominates = Set{ x : x in Nodes, x != y && (y in DominatorMap[x]) };
- Set<Node> immediateDominatees = Set{ x : x in nodesThatYDominates,
- !(Exists{ v != y && v != x && (v in DominatorMap[x]) : v in nodesThatYDominates })
- };
- immediateDominatorMap[y] = immediateDominatees;
- }
- }
- return immediateDominatorMap;
- }
- }
- public Set<Node> ImmediatelyDominatedBy(Node n) { return ImmediateDominatorMap[n]; }
-
-}
-
-// From AsmL distribution example: TopologicalSort
-<bool,Seq<Node>> TopSort(Graph g)
-{
- Seq<Node> S = Seq{};
- Set<Node> V = g.Nodes;
- bool change = true;
- while ( change )
- {
- change = false;
- Set<Node> X = V - ((Set<Node>) S);
- if ( X != Set{} )
- {
- Node temp = Choose{ v : v in X, !(Exists{ g.Edge(u,v) : u in X }) ifnone null };
- if ( temp == null )
- {
- return <false,Seq<Node>{}>;
- }
- else if ( temp != Seq<Node>{} )
- {
- S += Seq{temp};
- change = true;
- }
- }
- }
- return <true,S>;
-}
-
-bool Acyclic(Graph g, Node source)
-{
- <bool,Seq<Node>> <acyc,xs> = TopSort(g);
- return acyc;
-}
-
-//
-// [Dragon, pp. 670--671]
-// returns map D s.t. d in D(n) iff d dom n
-//
-Map<Node,Set<Node>> ComputeDominators(Graph g, Node source) {
- Set<Node> N = g.Nodes;
- Set<Node> nonSourceNodes = N - Set{source};
- Map<Node,Set<Node>> D = Map{};
- D[source] = Set<Node>{ source };
- foreach (Node n in nonSourceNodes)
- {
- D[n] = N;
- }
- bool change = true;
- while ( change )
- {
- change = false;
- foreach (Node n in nonSourceNodes)
- {
- Set<Set<Node>> allPreds = Set{ D[p] : p in g.predecessors(n) };
- Set<Node> temp = Set<Node>{ n } + BigIntersect(allPreds);
- if ( temp != D[n] )
- {
- change = true;
- D[n] = temp;
- }
- }
- }
- return D;
-}
-
-// [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
-Set<Node> NaturalLoop(Graph g, Edge backEdge)
-{
- <Node,Node> <n,d> = backEdge;
- Seq<Node> stack = Seq{};
- Set<Node> loop = Set{ d };
- if ( n != d ) // then n is not in loop
- {
- loop += Set{ n };
- stack = Seq{ n } + stack; // push n onto stack
- }
- while ( stack != Seq{} ) // not empty
- {
- Node m = Head(stack);
- stack = Tail(stack); // pop stack
- foreach (Node p in g.predecessors(m))
- {
- if ( !(p in loop) )
- {
- loop += Set{ p };
- stack = Seq{ p } + stack; // push p onto stack
- }
- }
- }
- return loop;
-}
-
-// [Dragon, p. 606]
-<bool, Set<Node>, Map<Node,Set<Node>>, Map<Edge,Set<Node>>>
- Reducible(Graph g, Node source) {
- // first, compute the dom relation
- Map<Node,Set<Node>> D = g.DominatorMap;
- return Reducible(g,source,D);
-}
-
-// [Dragon, p. 606]
-<bool, Set<Node>, Map<Node,Set<Node>>, Map<Edge,Set<Node>>>
- Reducible(Graph g, Node source, Map<Node,Set<Node>> DomRelation) {
-
- Set<Edge> edges = g.Edges;
- Set<Edge> backEdges = Set{};
- Set<Edge> nonBackEdges = Set{};
- foreach (Edge e in edges)
- {
- <Node,Node> <x,y> = e; // so there is an edge from x to y
- if ( y in DomRelation[x] ) // y dom x: which means y dominates x
- {
- backEdges += Set{ e };
- }
- else
- {
- nonBackEdges += Set{ e };
- }
- }
- if ( !Acyclic(new Graph(nonBackEdges), source) )
- {
- return <false,Set<Node>{},Map<Node,Set<Node>>{},Map<Edge,Set<Node>>{}>;
- }
- else
- {
- Set<Node> headers = Set{ d : <n,d> in backEdges };
- Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
- Map<Edge,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
-
- return <true, headers, backEdgeNodes, naturalLoops>;
- }
-}
-
-// [Dragon, p. 606]
-bool OldReducible(Graph g, Node source) {
- // first, compute the dom relation
- Map<Node,Set<Node>> D = ComputeDominators(g, source);
- return OldReducible(g,source,D);
-}
-
-// [Dragon, p. 606]
-bool OldReducible(Graph g, Node source, Map<Node,Set<Node>> DomRelation) {
-
- Set<Edge> edges = g.Edges;
- Set<Edge> backEdges = Set{};
- Set<Edge> nonBackEdges = Set{};
- foreach (Edge e in edges)
- {
- <Node,Node> <x,y> = e;
- if ( y in DomRelation[x] ) // y dom x
- {
- backEdges += Set{ e };
- }
- else
- {
- nonBackEdges += Set{ e };
- }
- }
- WriteLine("backEdges: " + backEdges);
- WriteLine("nonBackEdges: " + nonBackEdges);
- if ( Acyclic(new Graph(nonBackEdges), source) )
- {
- foreach(Edge e in backEdges)
- {
- Set<Node> naturalLoop = NaturalLoop(g,e);
- WriteLine("Natural loop for back edge '" + e + "' is: " + naturalLoop);
- }
- Set<Node> headers = Set{ d : <n,d> in backEdges };
- WriteLine("Loop headers = " + headers);
-
- edges -= backEdges; // this cuts all of the back edges
- foreach (Node h in headers)
- {
- Set<Edge> bs = Set{ <n,d> : <n,d> in backEdges, d == h };
- Set<Node> preds = Set<Node>{ p : <p,y> in edges, y == h };
- Node preheader = new PreHeader(h);
- edges += Set{ <preheader,h> };
- foreach (Node p in preds)
- {
- edges -= Set{ <p,h> };
- edges += Set{ <p,preheader> };
- }
- }
- Graph newGraph = new Graph(edges);
- WriteLine("transformed graph = " + newGraph);
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void Main()
-{
- Graph g;
- Map<Node,Set<Node>> D;
-/*
- g = new Graph(Set<Edge>{ <1,2>, <1,3>, <2,3> });
- g.AddSource(1);
- Map<Node,Set<Node>> doms = ComputeDominators(g,1);
- WriteLine(doms);
-*/
- g = new Graph(Set<Edge>{
- <1,2>, <1,3>,
- <2,3>,
- <3,4>,
- <4,3>, <4,5>, <4,6>,
- <5,7>,
- <6,7>,
- <7,4>, <7,8>,
- <8,3>, <8,9>, <8,10>,
- <9,1>,
- <10,7>
- });
- g.AddSource(1);
- WriteLine("G = " + g);
- D = ComputeDominators(g,1);
- WriteLine("Dom relation: " + D);
- WriteLine("G's Dominator Map = " + g.DominatorMap);
- WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap);
- WriteLine("G is reducible: " + OldReducible(g,1,D));
- g.ComputeLoops();
-
- WriteLine("");
-
- g = new Graph(Set<Edge>{ <1,2>, <1,3>, <2,3>, <3,2> });
- g.AddSource(1);
- WriteLine("G = " + g);
- D = ComputeDominators(g,1);
- WriteLine("Dom relation: " + D);
- WriteLine("G's Dominator Map = " + g.DominatorMap);
- WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap);
- WriteLine("G is reducible: " + OldReducible(g,1,D));
- g.ComputeLoops();
-
- WriteLine("");
-
- g = new Graph(Set<Edge>{ <1,2>, <2,3>, <2,4>, <3,2> });
- g.AddSource(1);
- WriteLine("G = " + g);
- WriteLine("G's Dominator Map = " + g.DominatorMap);
- WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap);
-// D = ComputeDominators(g,1);
-// WriteLine("Dom relation: " + D);
-// WriteLine("G is reducible: " + OldReducible(g,1,D));
- g.ComputeLoops();
-
-} \ No newline at end of file
diff --git a/Source/Core/Inline.cs b/Source/Core/Inline.cs
index cfeaeb8a..958051d5 100644
--- a/Source/Core/Inline.cs
+++ b/Source/Core/Inline.cs
@@ -1,770 +1,770 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
-
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
- using BoogiePL=Microsoft.Boogie;
- using System.Diagnostics;
- using System.Text.RegularExpressions; // for procedure inlining
-
- public delegate void InlineCallback(Implementation/*!*/ impl);
-
- public class Inliner : Duplicator {
- protected bool inlinedSomething;
-
- protected Program program;
-
- private InlineCallback inlineCallback;
-
- protected CodeCopier/*!*/ codeCopier;
-
- protected Dictionary<string/*!*/, int>/*!*/ /* Procedure.Name -> int */ recursiveProcUnrollMap;
-
- protected Dictionary<string/*!*/, int>/*!*/ /* Procedure.Name -> int */ inlinedProcLblMap;
-
- protected int inlineDepth;
-
- protected List<Variable>/*!*/ newLocalVars;
-
- protected List<IdentifierExpr>/*!*/ newModifies;
-
- protected string prefix;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(program != null);
- Contract.Invariant(newLocalVars != null);
- Contract.Invariant(newModifies != null);
- Contract.Invariant(codeCopier != null);
- Contract.Invariant(recursiveProcUnrollMap != null);
- Contract.Invariant(inlinedProcLblMap != null);
- }
-
- public override Expr VisitCodeExpr(CodeExpr node)
- {
- Inliner codeExprInliner = new Inliner(program, inlineCallback, CommandLineOptions.Clo.InlineDepth);
- codeExprInliner.newLocalVars.AddRange(node.LocVars);
- codeExprInliner.inlinedProcLblMap = this.inlinedProcLblMap;
- List<Block> newCodeExprBlocks = codeExprInliner.DoInlineBlocks(node.Blocks, ref inlinedSomething);
- return new CodeExpr(codeExprInliner.newLocalVars, newCodeExprBlocks);
- }
-
- protected void NextInlinedProcLabel(string procName) {
- Contract.Requires(procName != null);
- int currentId;
- if (inlinedProcLblMap.TryGetValue(procName, out currentId)) {
- inlinedProcLblMap[procName] = currentId + 1;
- } else {
- inlinedProcLblMap.Add(procName, 0);
- }
- }
-
- protected string GetInlinedProcLabel(string procName) {
- Contract.Requires(procName != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return prefix + procName + "$" + inlinedProcLblMap[procName];
- }
-
- protected string GetProcVarName(string procName, string formalName) {
- Contract.Requires(formalName != null);
- Contract.Requires(procName != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return GetInlinedProcLabel(procName) + "$" + formalName;
- }
-
- public Inliner(Program program, InlineCallback cb, int inlineDepth) {
- this.program = program;
- this.inlinedProcLblMap = new Dictionary<string/*!*/, int>();
- this.recursiveProcUnrollMap = new Dictionary<string/*!*/, int>();
- this.inlineDepth = inlineDepth;
- this.codeCopier = new CodeCopier();
- this.inlineCallback = cb;
- this.newLocalVars = new List<Variable>();
- this.newModifies = new List<IdentifierExpr>();
- this.prefix = null;
- }
-
- // This method calculates a prefix (storing it in the prefix field) so that prepending it to any string
- // is guaranteed not to create a conflict with the names of variables and blocks in scope inside impl.
- protected void ComputePrefix(Program program, Implementation impl)
- {
- this.prefix = "inline$";
- foreach (var v in impl.InParams)
- {
- DistinguishPrefix(v.Name);
- }
- foreach (var v in impl.OutParams)
- {
- DistinguishPrefix(v.Name);
- }
- foreach (var v in impl.LocVars)
- {
- DistinguishPrefix(v.Name);
- }
- foreach (var v in program.GlobalVariables)
- {
- DistinguishPrefix(v.Name);
- }
- foreach (Block b in impl.Blocks)
- {
- DistinguishPrefix(b.Label);
- }
- }
-
- private void DistinguishPrefix(string s)
- {
- if (!s.StartsWith(prefix)) return;
- for (int i = prefix.Length; i < s.Length; i++)
- {
- prefix = prefix + "$";
- if (s[i] != '$') break;
- }
- if (prefix == s)
- {
- prefix = prefix + "$";
- }
- }
-
- protected static void ProcessImplementation(Program program, Implementation impl, Inliner inliner) {
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
-
- inliner.ComputePrefix(program, impl);
-
- inliner.newLocalVars.AddRange(impl.LocVars);
- inliner.newModifies.AddRange(impl.Proc.Modifies);
-
- bool inlined = false;
- List<Block> newBlocks = inliner.DoInlineBlocks(impl.Blocks, ref inlined);
- Contract.Assert(cce.NonNullElements(newBlocks));
-
- if (!inlined)
- return;
-
- impl.InParams = new List<Variable>(impl.InParams);
- impl.OutParams = new List<Variable>(impl.OutParams);
- impl.LocVars = inliner.newLocalVars;
- impl.Proc.Modifies = inliner.newModifies;
- impl.Blocks = newBlocks;
-
- impl.ResetImplFormalMap();
-
- // we need to resolve the new code
- inliner.ResolveImpl(impl);
-
- if (CommandLineOptions.Clo.PrintInlined) {
- inliner.EmitImpl(impl);
- }
- }
-
- public static void ProcessImplementationForHoudini(Program program, Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(program != null);
- Contract.Requires(impl.Proc != null);
- ProcessImplementation(program, impl, new Inliner(program, null, CommandLineOptions.Clo.InlineDepth));
- }
-
- public static void ProcessImplementation(Program program, Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(program != null);
- Contract.Requires(impl.Proc != null);
- ProcessImplementation(program, impl, new Inliner(program, null, -1));
- }
-
- protected void EmitImpl(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
- Console.WriteLine("after inlining procedure calls");
- impl.Proc.Emit(new TokenTextWriter("<console>", Console.Out, /*pretty=*/ false), 0);
- impl.Emit(new TokenTextWriter("<console>", Console.Out, /*pretty=*/ false), 0);
- }
-
- private sealed class DummyErrorSink : IErrorSink {
- public void Error(IToken tok, string msg) {
- //Contract.Requires(msg != null);
- //Contract.Requires(tok != null);
- // FIXME
- // noop.
- // This is required because during the resolution, some resolution errors happen
- // (such as the ones caused addion of loop invariants J_(block.Label) by the AI package
- }
- }
-
- protected void ResolveImpl(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Ensures(impl.Proc != null);
- ResolutionContext rc = new ResolutionContext(new DummyErrorSink());
-
- foreach (var decl in program.TopLevelDeclarations) {
- decl.Register(rc);
- }
-
- impl.Proc = null; // to force Resolve() redo the operation
- impl.Resolve(rc);
-
- TypecheckingContext tc = new TypecheckingContext(new DummyErrorSink());
-
- impl.Typecheck(tc);
- }
-
- // Redundant for this class; but gives a chance for other classes to
- // override this and implement their own inlining policy
- protected virtual int GetInlineCount(CallCmd callCmd, Implementation impl)
- {
- return GetInlineCount(impl);
- }
-
- // returns true if it is ok to further unroll the procedure
- // otherwise, the procedure is not inlined at the call site
- protected int GetInlineCount(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
-
- string/*!*/ procName = impl.Name;
- Contract.Assert(procName != null);
- int c;
- if (recursiveProcUnrollMap.TryGetValue(procName, out c)) {
- return c;
- }
-
- c = -1; // TryGetValue above always overwrites c
- impl.CheckIntAttribute("inline", ref c);
- // procedure attribute overrides implementation
- impl.Proc.CheckIntAttribute("inline", ref c);
-
- recursiveProcUnrollMap[procName] = c;
- return c;
- }
-
- void CheckRecursion(Implementation impl, Stack<Procedure/*!*/>/*!*/ callStack) {
- Contract.Requires(impl != null);
- Contract.Requires(cce.NonNullElements(callStack));
- foreach (Procedure/*!*/ p in callStack) {
- Contract.Assert(p != null);
- if (p == impl.Proc) {
- string msg = "";
- foreach (Procedure/*!*/ q in callStack) {
- Contract.Assert(q != null);
- msg = q.Name + " -> " + msg;
- }
- msg += p.Name;
- //checkingCtx.Error(impl, "inlined procedure is recursive, call stack: {0}", msg);
- }
- }
- }
-
- private int InlineCallCmd(Block block, CallCmd callCmd, Implementation impl, List<Cmd> newCmds, List<Block> newBlocks, int lblCount)
- {
- Contract.Assume(impl != null);
- Contract.Assert(cce.NonNull(impl.OriginalBlocks).Count > 0);
-
- // do inline now
- int nextlblCount = lblCount + 1;
- string nextBlockLabel = block.Label + "$" + nextlblCount;
-
- // run the callback before each inline
- if (inlineCallback != null)
- {
- inlineCallback(impl);
- }
-
- // increment the counter for the procedure to be used in constructing the locals and formals
- NextInlinedProcLabel(impl.Proc.Name);
-
- BeginInline(impl);
-
- List<Block/*!*/>/*!*/ inlinedBlocks = CreateInlinedBlocks(callCmd, impl, nextBlockLabel);
- Contract.Assert(cce.NonNullElements(inlinedBlocks));
-
- EndInline();
-
- if (inlineDepth >= 0)
- {
- Debug.Assert(inlineDepth > 0);
- inlineDepth = inlineDepth - 1;
- }
- else
- {
- recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] - 1;
- }
-
- bool inlinedSomething = true;
- inlinedBlocks = DoInlineBlocks(inlinedBlocks, ref inlinedSomething);
-
- if (inlineDepth >= 0)
- {
- inlineDepth = inlineDepth + 1;
- }
- else
- {
- recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] + 1;
- }
-
- Block/*!*/ startBlock = inlinedBlocks[0];
- Contract.Assert(startBlock != null);
-
- GotoCmd gotoCmd = new GotoCmd(Token.NoToken, new List<String> { startBlock.Label });
- Block newBlock = new Block(block.tok, ((lblCount == 0) ? (block.Label) : (block.Label + "$" + lblCount)), newCmds, gotoCmd);
-
- newBlocks.Add(newBlock);
- newBlocks.AddRange(inlinedBlocks);
-
- return nextlblCount;
- }
-
- public virtual List<Block/*!*/>/*!*/ DoInlineBlocks(List<Block/*!*/>/*!*/ blocks, ref bool inlinedSomething) {
- Contract.Requires(cce.NonNullElements(blocks));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- List<Block/*!*/>/*!*/ newBlocks = new List<Block/*!*/>();
-
- foreach (Block block in blocks) {
- TransferCmd/*!*/ transferCmd = cce.NonNull(block.TransferCmd);
- List<Cmd> cmds = block.Cmds;
- List<Cmd> newCmds = new List<Cmd>();
- int lblCount = 0;
-
- for (int i = 0; i < cmds.Count; ++i)
- {
- Cmd cmd = cmds[i];
-
- if (cmd is CallCmd)
- {
- CallCmd callCmd = (CallCmd)cmd;
- Implementation impl = FindProcImpl(program, callCmd.Proc);
- if (impl == null)
- {
- newCmds.Add(codeCopier.CopyCmd(callCmd));
- continue;
- }
- int inline = inlineDepth >= 0 ? inlineDepth : GetInlineCount(callCmd, impl);
- if (inline > 0)
- {
- inlinedSomething = true;
- lblCount = InlineCallCmd(block, callCmd, impl, newCmds, newBlocks, lblCount);
- newCmds = new List<Cmd>();
- }
- else if (inline == 0)
- {
- inlinedSomething = true;
- if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assert)
- {
- // add assert
- newCmds.Add(new AssertCmd(callCmd.tok, Expr.False));
- }
- else if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assume)
- {
- // add assume
- newCmds.Add(new AssumeCmd(callCmd.tok, Expr.False));
- }
- else
- {
- // add call
- newCmds.Add(codeCopier.CopyCmd(callCmd));
- }
- }
- else
- {
- newCmds.Add(codeCopier.CopyCmd(callCmd));
- }
- }
- else if (cmd is PredicateCmd)
- {
- PredicateCmd predCmd = (PredicateCmd)cmd;
- this.inlinedSomething = false;
- Expr newExpr = this.VisitExpr(predCmd.Expr);
- if (this.inlinedSomething)
- {
- inlinedSomething = true;
- PredicateCmd newPredCmd = (PredicateCmd)codeCopier.CopyCmd(predCmd);
- newPredCmd.Expr = newExpr;
- newCmds.Add(newPredCmd);
- }
- else
- {
- newCmds.Add(codeCopier.CopyCmd(predCmd));
- }
- }
- else if (cmd is AssignCmd)
- {
- AssignCmd assignCmd = (AssignCmd)cmd;
- this.inlinedSomething = false;
- List<Expr> newRhss = new List<Expr>();
- foreach (Expr rhsExpr in assignCmd.Rhss)
- {
- newRhss.Add(this.VisitExpr(rhsExpr));
- }
- if (this.inlinedSomething)
- {
- inlinedSomething = true;
- AssignCmd newAssignCmd = (AssignCmd)codeCopier.CopyCmd(assignCmd);
- newAssignCmd.Rhss = newRhss;
- newCmds.Add(newAssignCmd);
- }
- else
- {
- newCmds.Add(codeCopier.CopyCmd(assignCmd));
- }
- }
- else
- {
- newCmds.Add(codeCopier.CopyCmd(cmd));
- }
- }
-
- Block newBlock = new Block(block.tok, ((lblCount == 0) ? (block.Label) : (block.Label + "$" + lblCount)), newCmds, codeCopier.CopyTransferCmd(transferCmd));
- newBlocks.Add(newBlock);
- }
-
- return newBlocks;
- }
-
- protected void BeginInline(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
- Contract.Requires(newModifies != null);
- Contract.Requires(newLocalVars != null);
-
- Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>();
- Procedure proc = impl.Proc;
-
- foreach (Variable/*!*/ locVar in cce.NonNull(impl.OriginalLocVars)) {
- Contract.Assert(locVar != null);
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, locVar.Name), locVar.TypedIdent.Type, locVar.TypedIdent.WhereExpr));
- localVar.Attributes = locVar.Attributes; // copy attributes
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMap.Add(locVar, ie);
- }
-
- for (int i = 0; i < impl.InParams.Count; i++) {
- Variable inVar = cce.NonNull(impl.InParams[i]);
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, inVar.Name), inVar.TypedIdent.Type, inVar.TypedIdent.WhereExpr));
- newLocalVars.Add(localVar);
- if (impl.Proc != null) localVar.Attributes = impl.Proc.InParams[i].Attributes; // copy attributes
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMap.Add(inVar, ie);
- // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
- Variable procInVar = cce.NonNull(proc.InParams[i]);
- if (procInVar != inVar) {
- substMap.Add(procInVar, ie);
- }
- }
-
- for (int i = 0; i < impl.OutParams.Count; i++) {
- Variable outVar = cce.NonNull(impl.OutParams[i]);
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, outVar.Name), outVar.TypedIdent.Type, outVar.TypedIdent.WhereExpr));
- if (impl.Proc != null) localVar.Attributes = impl.Proc.OutParams[i].Attributes; // copy attributes
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMap.Add(outVar, ie);
- // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
- Variable procOutVar = cce.NonNull(proc.OutParams[i]);
- if (procOutVar != outVar) {
- substMap.Add(procOutVar, ie);
- }
- }
-
- Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>();
-
- foreach (IdentifierExpr/*!*/ mie in proc.Modifies) {
- Contract.Assert(mie != null);
- Variable/*!*/ mVar = cce.NonNull(mie.Decl);
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, mVar.Name), mVar.TypedIdent.Type));
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMapOld.Add(mVar, ie);
- // FIXME why are we doing this? the modifies list should already include them.
- // add the modified variable to the modifies list of the procedure
- if (!newModifies.Contains(mie)) {
- newModifies.Add(mie);
- }
- }
-
- codeCopier.Subst = Substituter.SubstitutionFromHashtable(substMap);
- codeCopier.OldSubst = Substituter.SubstitutionFromHashtable(substMapOld);
- }
-
- protected void EndInline() {
- codeCopier.Subst = null;
- codeCopier.OldSubst = null;
- }
-
- private Cmd InlinedRequires(CallCmd callCmd, Requires req) {
- Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
- if (req.Free)
- reqCopy.Condition = Expr.True;
- else
- reqCopy.Condition = codeCopier.CopyExpr(req.Condition);
- AssertCmd/*!*/ a = new AssertRequiresCmd(callCmd, reqCopy);
- a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
- return a;
- }
-
- private Cmd InlinedEnsures(CallCmd callCmd, Ensures ens) {
- if (QKeyValue.FindBoolAttribute(ens.Attributes, "InlineAssume")) {
- return new AssumeCmd(ens.tok, codeCopier.CopyExpr(ens.Condition));
- } else if (ens.Free) {
- return new AssumeCmd(ens.tok, Expr.True);
- } else {
- Ensures/*!*/ ensCopy = (Ensures/*!*/)cce.NonNull(ens.Clone());
- ensCopy.Condition = codeCopier.CopyExpr(ens.Condition);
- return new AssertEnsuresCmd(ensCopy);
- }
- }
-
- private List<Cmd> RemoveAsserts(List<Cmd> cmds) {
- List<Cmd> newCmdSeq = new List<Cmd>();
- for (int i = 0; i < cmds.Count; i++) {
- Cmd cmd = cmds[i];
- if (cmd is AssertCmd) continue;
- newCmdSeq.Add(cmd);
- }
- return newCmdSeq;
- }
-
- // result[0] is the entry block
- protected List<Block/*!*/>/*!*/ CreateInlinedBlocks(CallCmd callCmd, Implementation impl, string nextBlockLabel) {
- Contract.Requires(nextBlockLabel != null);
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
- Contract.Requires(callCmd != null);
- Contract.Requires(codeCopier.Subst != null);
-
- Contract.Requires(codeCopier.OldSubst != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- List<Block/*!*/>/*!*/ implBlocks = cce.NonNull(impl.OriginalBlocks);
- Contract.Assert(implBlocks.Count > 0);
-
- Procedure proc = impl.Proc;
- string startLabel = implBlocks[0].Label;
-
- List<Block/*!*/>/*!*/ inlinedBlocks = new List<Block/*!*/>();
-
- // create in block
- List<Cmd> inCmds = new List<Cmd>();
-
- // assign in parameters
- for (int i = 0; i < impl.InParams.Count; ++i) {
- Cmd cmd = Cmd.SimpleAssign(impl.tok,
- (IdentifierExpr)cce.NonNull(codeCopier.Subst)(cce.NonNull(impl.InParams[i])),
- cce.NonNull(callCmd.Ins[i]));
- inCmds.Add(cmd);
- }
-
- // inject requires
- for (int i = 0; i < proc.Requires.Count; i++) {
- Requires/*!*/ req = cce.NonNull(proc.Requires[i]);
- inCmds.Add(InlinedRequires(callCmd, req));
- }
-
- List<Variable> locVars = cce.NonNull(impl.OriginalLocVars);
-
- // havoc locals and out parameters in case procedure is invoked in a loop
- List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
- foreach (Variable v in locVars)
- {
- havocVars.Add((IdentifierExpr)codeCopier.Subst(v));
- }
- foreach (Variable v in impl.OutParams)
- {
- havocVars.Add((IdentifierExpr)codeCopier.Subst(v));
- }
- if (havocVars.Count > 0)
- {
- inCmds.Add(new HavocCmd(Token.NoToken, havocVars));
- }
-
- // add where clauses of local vars as assume
- for (int i = 0; i < locVars.Count; ++i) {
- Expr whereExpr = (cce.NonNull(locVars[i])).TypedIdent.WhereExpr;
- if (whereExpr != null) {
- whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
- // FIXME we cannot overwrite it, can we?!
- (cce.NonNull(locVars[i])).TypedIdent.WhereExpr = whereExpr;
- AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr);
- Contract.Assert(a != null);
- inCmds.Add(a);
- }
- }
-
- // add where clauses of output params as assume
- for (int i = 0; i < impl.OutParams.Count; ++i) {
- Expr whereExpr = (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr;
- if (whereExpr != null) {
- whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
- // FIXME likewise
- (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr = whereExpr;
- AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr);
- Contract.Assert(a != null);
- inCmds.Add(a);
- }
- }
-
- // assign modifies old values
- foreach (IdentifierExpr/*!*/ mie in proc.Modifies) {
- Contract.Assert(mie != null);
- Variable/*!*/ mvar = cce.NonNull(mie.Decl);
- AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr)cce.NonNull(codeCopier.OldSubst(mvar)), mie);
- inCmds.Add(assign);
- }
-
- GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new List<String> { GetInlinedProcLabel(proc.Name) + "$" + startLabel });
- Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd);
- inlinedBlocks.Add(inBlock);
-
- // inject the blocks of the implementation
- Block intBlock;
- foreach (Block block in implBlocks) {
- List<Cmd> copyCmds = codeCopier.CopyCmdSeq(block.Cmds);
- if (0 <= inlineDepth) {
- copyCmds = RemoveAsserts(copyCmds);
- }
- TransferCmd transferCmd = CreateInlinedTransferCmd(cce.NonNull(block.TransferCmd), GetInlinedProcLabel(proc.Name));
- intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd);
- inlinedBlocks.Add(intBlock);
- }
-
- // create out block
- List<Cmd> outCmds = new List<Cmd>();
-
- // inject ensures
- for (int i = 0; i < proc.Ensures.Count; i++) {
- Ensures/*!*/ ens = cce.NonNull(proc.Ensures[i]);
- outCmds.Add(InlinedEnsures(callCmd, ens));
- }
-
- // assign out params
- for (int i = 0; i < impl.OutParams.Count; ++i) {
- Expr/*!*/ cout_exp = (IdentifierExpr)cce.NonNull(codeCopier.Subst(cce.NonNull(impl.OutParams[i])));
- Cmd cmd = Cmd.SimpleAssign(impl.tok, cce.NonNull(callCmd.Outs[i]), cout_exp);
- outCmds.Add(cmd);
- }
-
- // create out block
- GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new List<String> { nextBlockLabel });
- Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd);
- inlinedBlocks.Add(outBlock);
-
- return inlinedBlocks;
- }
-
- protected TransferCmd CreateInlinedTransferCmd(TransferCmd transferCmd, string procLabel) {
- Contract.Requires(procLabel != null);
- Contract.Requires(transferCmd != null);
- TransferCmd newTransferCmd;
-
- GotoCmd gotoCmd = transferCmd as GotoCmd;
- if (gotoCmd != null) {
- List<String> gotoSeq = gotoCmd.labelNames;
- List<String> newGotoSeq = new List<String>();
- foreach (string/*!*/ blockLabel in cce.NonNull(gotoSeq)) {
- Contract.Assert(blockLabel != null);
- newGotoSeq.Add(procLabel + "$" + blockLabel);
- }
- newTransferCmd = new GotoCmd(transferCmd.tok, newGotoSeq);
- } else {
- newTransferCmd = new GotoCmd(transferCmd.tok, new List<String> { procLabel + "$Return" });
- }
-
- return newTransferCmd;
- }
-
- protected static Implementation FindProcImpl(Program program, Procedure proc) {
- Contract.Requires(program != null);
- foreach (var impl in program.Implementations) {
- if (impl.Proc == proc) {
- return impl;
- }
- }
- return null;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- public class CodeCopier {
- public Substitution Subst;
- public Substitution OldSubst;
-
- public CodeCopier(Dictionary<Variable, Expr> substMap) {
- Contract.Requires(substMap != null);
- Subst = Substituter.SubstitutionFromHashtable(substMap);
- }
-
- public CodeCopier(Dictionary<Variable, Expr> substMap, Dictionary<Variable, Expr> oldSubstMap) {
- Contract.Requires(oldSubstMap != null);
- Contract.Requires(substMap != null);
- Subst = Substituter.SubstitutionFromHashtable(substMap);
- OldSubst = Substituter.SubstitutionFromHashtable(oldSubstMap);
- }
-
- public CodeCopier() {
- }
-
- public List<Cmd> CopyCmdSeq(List<Cmd> cmds) {
- Contract.Requires(cmds != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- List<Cmd> newCmds = new List<Cmd>();
- foreach (Cmd/*!*/ cmd in cmds) {
- Contract.Assert(cmd != null);
- newCmds.Add(CopyCmd(cmd));
- }
- return newCmds;
- }
-
- public TransferCmd CopyTransferCmd(TransferCmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<TransferCmd>() != null);
- TransferCmd transferCmd;
- GotoCmd gotocmd = cmd as GotoCmd;
- if (gotocmd != null) {
- Contract.Assert(gotocmd.labelNames != null);
- List<String> labels = new List<String>();
- labels.AddRange(gotocmd.labelNames);
- transferCmd = new GotoCmd(cmd.tok, labels);
- } else {
- ReturnExprCmd returnExprCmd = cmd as ReturnExprCmd;
- if (returnExprCmd != null)
- {
- transferCmd = new ReturnExprCmd(cmd.tok, CopyExpr(returnExprCmd.Expr));
- }
- else
- {
- transferCmd = new ReturnCmd(cmd.tok);
- }
- }
- return transferCmd;
- }
-
- public Cmd CopyCmd(Cmd cmd) {
- Contract.Requires(cmd != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- if (Subst == null) {
- return cmd;
- } else if (OldSubst == null) {
- return Substituter.Apply(Subst, cmd);
- } else {
- return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, cmd);
- }
- }
-
- public Expr CopyExpr(Expr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- if (Subst == null) {
- return expr;
- } else if (OldSubst == null) {
- return Substituter.Apply(Subst, expr);
- } else {
- return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, expr);
- }
- }
- } // end class CodeCopier
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using BoogiePL=Microsoft.Boogie;
+ using System.Diagnostics;
+ using System.Text.RegularExpressions; // for procedure inlining
+
+ public delegate void InlineCallback(Implementation/*!*/ impl);
+
+ public class Inliner : Duplicator {
+ protected bool inlinedSomething;
+
+ protected Program program;
+
+ private InlineCallback inlineCallback;
+
+ protected CodeCopier/*!*/ codeCopier;
+
+ protected Dictionary<string/*!*/, int>/*!*/ /* Procedure.Name -> int */ recursiveProcUnrollMap;
+
+ protected Dictionary<string/*!*/, int>/*!*/ /* Procedure.Name -> int */ inlinedProcLblMap;
+
+ protected int inlineDepth;
+
+ protected List<Variable>/*!*/ newLocalVars;
+
+ protected List<IdentifierExpr>/*!*/ newModifies;
+
+ protected string prefix;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(program != null);
+ Contract.Invariant(newLocalVars != null);
+ Contract.Invariant(newModifies != null);
+ Contract.Invariant(codeCopier != null);
+ Contract.Invariant(recursiveProcUnrollMap != null);
+ Contract.Invariant(inlinedProcLblMap != null);
+ }
+
+ public override Expr VisitCodeExpr(CodeExpr node)
+ {
+ Inliner codeExprInliner = new Inliner(program, inlineCallback, CommandLineOptions.Clo.InlineDepth);
+ codeExprInliner.newLocalVars.AddRange(node.LocVars);
+ codeExprInliner.inlinedProcLblMap = this.inlinedProcLblMap;
+ List<Block> newCodeExprBlocks = codeExprInliner.DoInlineBlocks(node.Blocks, ref inlinedSomething);
+ return new CodeExpr(codeExprInliner.newLocalVars, newCodeExprBlocks);
+ }
+
+ protected void NextInlinedProcLabel(string procName) {
+ Contract.Requires(procName != null);
+ int currentId;
+ if (inlinedProcLblMap.TryGetValue(procName, out currentId)) {
+ inlinedProcLblMap[procName] = currentId + 1;
+ } else {
+ inlinedProcLblMap.Add(procName, 0);
+ }
+ }
+
+ protected string GetInlinedProcLabel(string procName) {
+ Contract.Requires(procName != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return prefix + procName + "$" + inlinedProcLblMap[procName];
+ }
+
+ protected string GetProcVarName(string procName, string formalName) {
+ Contract.Requires(formalName != null);
+ Contract.Requires(procName != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return GetInlinedProcLabel(procName) + "$" + formalName;
+ }
+
+ public Inliner(Program program, InlineCallback cb, int inlineDepth) {
+ this.program = program;
+ this.inlinedProcLblMap = new Dictionary<string/*!*/, int>();
+ this.recursiveProcUnrollMap = new Dictionary<string/*!*/, int>();
+ this.inlineDepth = inlineDepth;
+ this.codeCopier = new CodeCopier();
+ this.inlineCallback = cb;
+ this.newLocalVars = new List<Variable>();
+ this.newModifies = new List<IdentifierExpr>();
+ this.prefix = null;
+ }
+
+ // This method calculates a prefix (storing it in the prefix field) so that prepending it to any string
+ // is guaranteed not to create a conflict with the names of variables and blocks in scope inside impl.
+ protected void ComputePrefix(Program program, Implementation impl)
+ {
+ this.prefix = "inline$";
+ foreach (var v in impl.InParams)
+ {
+ DistinguishPrefix(v.Name);
+ }
+ foreach (var v in impl.OutParams)
+ {
+ DistinguishPrefix(v.Name);
+ }
+ foreach (var v in impl.LocVars)
+ {
+ DistinguishPrefix(v.Name);
+ }
+ foreach (var v in program.GlobalVariables)
+ {
+ DistinguishPrefix(v.Name);
+ }
+ foreach (Block b in impl.Blocks)
+ {
+ DistinguishPrefix(b.Label);
+ }
+ }
+
+ private void DistinguishPrefix(string s)
+ {
+ if (!s.StartsWith(prefix)) return;
+ for (int i = prefix.Length; i < s.Length; i++)
+ {
+ prefix = prefix + "$";
+ if (s[i] != '$') break;
+ }
+ if (prefix == s)
+ {
+ prefix = prefix + "$";
+ }
+ }
+
+ protected static void ProcessImplementation(Program program, Implementation impl, Inliner inliner) {
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+
+ inliner.ComputePrefix(program, impl);
+
+ inliner.newLocalVars.AddRange(impl.LocVars);
+ inliner.newModifies.AddRange(impl.Proc.Modifies);
+
+ bool inlined = false;
+ List<Block> newBlocks = inliner.DoInlineBlocks(impl.Blocks, ref inlined);
+ Contract.Assert(cce.NonNullElements(newBlocks));
+
+ if (!inlined)
+ return;
+
+ impl.InParams = new List<Variable>(impl.InParams);
+ impl.OutParams = new List<Variable>(impl.OutParams);
+ impl.LocVars = inliner.newLocalVars;
+ impl.Proc.Modifies = inliner.newModifies;
+ impl.Blocks = newBlocks;
+
+ impl.ResetImplFormalMap();
+
+ // we need to resolve the new code
+ inliner.ResolveImpl(impl);
+
+ if (CommandLineOptions.Clo.PrintInlined) {
+ inliner.EmitImpl(impl);
+ }
+ }
+
+ public static void ProcessImplementationForHoudini(Program program, Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(program != null);
+ Contract.Requires(impl.Proc != null);
+ ProcessImplementation(program, impl, new Inliner(program, null, CommandLineOptions.Clo.InlineDepth));
+ }
+
+ public static void ProcessImplementation(Program program, Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(program != null);
+ Contract.Requires(impl.Proc != null);
+ ProcessImplementation(program, impl, new Inliner(program, null, -1));
+ }
+
+ protected void EmitImpl(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+ Console.WriteLine("after inlining procedure calls");
+ impl.Proc.Emit(new TokenTextWriter("<console>", Console.Out, /*pretty=*/ false), 0);
+ impl.Emit(new TokenTextWriter("<console>", Console.Out, /*pretty=*/ false), 0);
+ }
+
+ private sealed class DummyErrorSink : IErrorSink {
+ public void Error(IToken tok, string msg) {
+ //Contract.Requires(msg != null);
+ //Contract.Requires(tok != null);
+ // FIXME
+ // noop.
+ // This is required because during the resolution, some resolution errors happen
+ // (such as the ones caused addion of loop invariants J_(block.Label) by the AI package
+ }
+ }
+
+ protected void ResolveImpl(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Ensures(impl.Proc != null);
+ ResolutionContext rc = new ResolutionContext(new DummyErrorSink());
+
+ foreach (var decl in program.TopLevelDeclarations) {
+ decl.Register(rc);
+ }
+
+ impl.Proc = null; // to force Resolve() redo the operation
+ impl.Resolve(rc);
+
+ TypecheckingContext tc = new TypecheckingContext(new DummyErrorSink());
+
+ impl.Typecheck(tc);
+ }
+
+ // Redundant for this class; but gives a chance for other classes to
+ // override this and implement their own inlining policy
+ protected virtual int GetInlineCount(CallCmd callCmd, Implementation impl)
+ {
+ return GetInlineCount(impl);
+ }
+
+ // returns true if it is ok to further unroll the procedure
+ // otherwise, the procedure is not inlined at the call site
+ protected int GetInlineCount(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+
+ string/*!*/ procName = impl.Name;
+ Contract.Assert(procName != null);
+ int c;
+ if (recursiveProcUnrollMap.TryGetValue(procName, out c)) {
+ return c;
+ }
+
+ c = -1; // TryGetValue above always overwrites c
+ impl.CheckIntAttribute("inline", ref c);
+ // procedure attribute overrides implementation
+ impl.Proc.CheckIntAttribute("inline", ref c);
+
+ recursiveProcUnrollMap[procName] = c;
+ return c;
+ }
+
+ void CheckRecursion(Implementation impl, Stack<Procedure/*!*/>/*!*/ callStack) {
+ Contract.Requires(impl != null);
+ Contract.Requires(cce.NonNullElements(callStack));
+ foreach (Procedure/*!*/ p in callStack) {
+ Contract.Assert(p != null);
+ if (p == impl.Proc) {
+ string msg = "";
+ foreach (Procedure/*!*/ q in callStack) {
+ Contract.Assert(q != null);
+ msg = q.Name + " -> " + msg;
+ }
+ msg += p.Name;
+ //checkingCtx.Error(impl, "inlined procedure is recursive, call stack: {0}", msg);
+ }
+ }
+ }
+
+ private int InlineCallCmd(Block block, CallCmd callCmd, Implementation impl, List<Cmd> newCmds, List<Block> newBlocks, int lblCount)
+ {
+ Contract.Assume(impl != null);
+ Contract.Assert(cce.NonNull(impl.OriginalBlocks).Count > 0);
+
+ // do inline now
+ int nextlblCount = lblCount + 1;
+ string nextBlockLabel = block.Label + "$" + nextlblCount;
+
+ // run the callback before each inline
+ if (inlineCallback != null)
+ {
+ inlineCallback(impl);
+ }
+
+ // increment the counter for the procedure to be used in constructing the locals and formals
+ NextInlinedProcLabel(impl.Proc.Name);
+
+ BeginInline(impl);
+
+ List<Block/*!*/>/*!*/ inlinedBlocks = CreateInlinedBlocks(callCmd, impl, nextBlockLabel);
+ Contract.Assert(cce.NonNullElements(inlinedBlocks));
+
+ EndInline();
+
+ if (inlineDepth >= 0)
+ {
+ Debug.Assert(inlineDepth > 0);
+ inlineDepth = inlineDepth - 1;
+ }
+ else
+ {
+ recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] - 1;
+ }
+
+ bool inlinedSomething = true;
+ inlinedBlocks = DoInlineBlocks(inlinedBlocks, ref inlinedSomething);
+
+ if (inlineDepth >= 0)
+ {
+ inlineDepth = inlineDepth + 1;
+ }
+ else
+ {
+ recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] + 1;
+ }
+
+ Block/*!*/ startBlock = inlinedBlocks[0];
+ Contract.Assert(startBlock != null);
+
+ GotoCmd gotoCmd = new GotoCmd(Token.NoToken, new List<String> { startBlock.Label });
+ Block newBlock = new Block(block.tok, ((lblCount == 0) ? (block.Label) : (block.Label + "$" + lblCount)), newCmds, gotoCmd);
+
+ newBlocks.Add(newBlock);
+ newBlocks.AddRange(inlinedBlocks);
+
+ return nextlblCount;
+ }
+
+ public virtual List<Block/*!*/>/*!*/ DoInlineBlocks(List<Block/*!*/>/*!*/ blocks, ref bool inlinedSomething) {
+ Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+ List<Block/*!*/>/*!*/ newBlocks = new List<Block/*!*/>();
+
+ foreach (Block block in blocks) {
+ TransferCmd/*!*/ transferCmd = cce.NonNull(block.TransferCmd);
+ List<Cmd> cmds = block.Cmds;
+ List<Cmd> newCmds = new List<Cmd>();
+ int lblCount = 0;
+
+ for (int i = 0; i < cmds.Count; ++i)
+ {
+ Cmd cmd = cmds[i];
+
+ if (cmd is CallCmd)
+ {
+ CallCmd callCmd = (CallCmd)cmd;
+ Implementation impl = FindProcImpl(program, callCmd.Proc);
+ if (impl == null)
+ {
+ newCmds.Add(codeCopier.CopyCmd(callCmd));
+ continue;
+ }
+ int inline = inlineDepth >= 0 ? inlineDepth : GetInlineCount(callCmd, impl);
+ if (inline > 0)
+ {
+ inlinedSomething = true;
+ lblCount = InlineCallCmd(block, callCmd, impl, newCmds, newBlocks, lblCount);
+ newCmds = new List<Cmd>();
+ }
+ else if (inline == 0)
+ {
+ inlinedSomething = true;
+ if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assert)
+ {
+ // add assert
+ newCmds.Add(new AssertCmd(callCmd.tok, Expr.False));
+ }
+ else if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assume)
+ {
+ // add assume
+ newCmds.Add(new AssumeCmd(callCmd.tok, Expr.False));
+ }
+ else
+ {
+ // add call
+ newCmds.Add(codeCopier.CopyCmd(callCmd));
+ }
+ }
+ else
+ {
+ newCmds.Add(codeCopier.CopyCmd(callCmd));
+ }
+ }
+ else if (cmd is PredicateCmd)
+ {
+ PredicateCmd predCmd = (PredicateCmd)cmd;
+ this.inlinedSomething = false;
+ Expr newExpr = this.VisitExpr(predCmd.Expr);
+ if (this.inlinedSomething)
+ {
+ inlinedSomething = true;
+ PredicateCmd newPredCmd = (PredicateCmd)codeCopier.CopyCmd(predCmd);
+ newPredCmd.Expr = newExpr;
+ newCmds.Add(newPredCmd);
+ }
+ else
+ {
+ newCmds.Add(codeCopier.CopyCmd(predCmd));
+ }
+ }
+ else if (cmd is AssignCmd)
+ {
+ AssignCmd assignCmd = (AssignCmd)cmd;
+ this.inlinedSomething = false;
+ List<Expr> newRhss = new List<Expr>();
+ foreach (Expr rhsExpr in assignCmd.Rhss)
+ {
+ newRhss.Add(this.VisitExpr(rhsExpr));
+ }
+ if (this.inlinedSomething)
+ {
+ inlinedSomething = true;
+ AssignCmd newAssignCmd = (AssignCmd)codeCopier.CopyCmd(assignCmd);
+ newAssignCmd.Rhss = newRhss;
+ newCmds.Add(newAssignCmd);
+ }
+ else
+ {
+ newCmds.Add(codeCopier.CopyCmd(assignCmd));
+ }
+ }
+ else
+ {
+ newCmds.Add(codeCopier.CopyCmd(cmd));
+ }
+ }
+
+ Block newBlock = new Block(block.tok, ((lblCount == 0) ? (block.Label) : (block.Label + "$" + lblCount)), newCmds, codeCopier.CopyTransferCmd(transferCmd));
+ newBlocks.Add(newBlock);
+ }
+
+ return newBlocks;
+ }
+
+ protected void BeginInline(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+ Contract.Requires(newModifies != null);
+ Contract.Requires(newLocalVars != null);
+
+ Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>();
+ Procedure proc = impl.Proc;
+
+ foreach (Variable/*!*/ locVar in cce.NonNull(impl.OriginalLocVars)) {
+ Contract.Assert(locVar != null);
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, locVar.Name), locVar.TypedIdent.Type, locVar.TypedIdent.WhereExpr));
+ localVar.Attributes = locVar.Attributes; // copy attributes
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMap.Add(locVar, ie);
+ }
+
+ for (int i = 0; i < impl.InParams.Count; i++) {
+ Variable inVar = cce.NonNull(impl.InParams[i]);
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, inVar.Name), inVar.TypedIdent.Type, inVar.TypedIdent.WhereExpr));
+ newLocalVars.Add(localVar);
+ if (impl.Proc != null) localVar.Attributes = impl.Proc.InParams[i].Attributes; // copy attributes
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMap.Add(inVar, ie);
+ // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
+ Variable procInVar = cce.NonNull(proc.InParams[i]);
+ if (procInVar != inVar) {
+ substMap.Add(procInVar, ie);
+ }
+ }
+
+ for (int i = 0; i < impl.OutParams.Count; i++) {
+ Variable outVar = cce.NonNull(impl.OutParams[i]);
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, outVar.Name), outVar.TypedIdent.Type, outVar.TypedIdent.WhereExpr));
+ if (impl.Proc != null) localVar.Attributes = impl.Proc.OutParams[i].Attributes; // copy attributes
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMap.Add(outVar, ie);
+ // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
+ Variable procOutVar = cce.NonNull(proc.OutParams[i]);
+ if (procOutVar != outVar) {
+ substMap.Add(procOutVar, ie);
+ }
+ }
+
+ Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>();
+
+ foreach (IdentifierExpr/*!*/ mie in proc.Modifies) {
+ Contract.Assert(mie != null);
+ Variable/*!*/ mVar = cce.NonNull(mie.Decl);
+ LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, mVar.Name), mVar.TypedIdent.Type));
+ newLocalVars.Add(localVar);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
+ substMapOld.Add(mVar, ie);
+ // FIXME why are we doing this? the modifies list should already include them.
+ // add the modified variable to the modifies list of the procedure
+ if (!newModifies.Contains(mie)) {
+ newModifies.Add(mie);
+ }
+ }
+
+ codeCopier.Subst = Substituter.SubstitutionFromHashtable(substMap);
+ codeCopier.OldSubst = Substituter.SubstitutionFromHashtable(substMapOld);
+ }
+
+ protected void EndInline() {
+ codeCopier.Subst = null;
+ codeCopier.OldSubst = null;
+ }
+
+ private Cmd InlinedRequires(CallCmd callCmd, Requires req) {
+ Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
+ if (req.Free)
+ reqCopy.Condition = Expr.True;
+ else
+ reqCopy.Condition = codeCopier.CopyExpr(req.Condition);
+ AssertCmd/*!*/ a = new AssertRequiresCmd(callCmd, reqCopy);
+ a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
+ return a;
+ }
+
+ private Cmd InlinedEnsures(CallCmd callCmd, Ensures ens) {
+ if (QKeyValue.FindBoolAttribute(ens.Attributes, "InlineAssume")) {
+ return new AssumeCmd(ens.tok, codeCopier.CopyExpr(ens.Condition));
+ } else if (ens.Free) {
+ return new AssumeCmd(ens.tok, Expr.True);
+ } else {
+ Ensures/*!*/ ensCopy = (Ensures/*!*/)cce.NonNull(ens.Clone());
+ ensCopy.Condition = codeCopier.CopyExpr(ens.Condition);
+ return new AssertEnsuresCmd(ensCopy);
+ }
+ }
+
+ private List<Cmd> RemoveAsserts(List<Cmd> cmds) {
+ List<Cmd> newCmdSeq = new List<Cmd>();
+ for (int i = 0; i < cmds.Count; i++) {
+ Cmd cmd = cmds[i];
+ if (cmd is AssertCmd) continue;
+ newCmdSeq.Add(cmd);
+ }
+ return newCmdSeq;
+ }
+
+ // result[0] is the entry block
+ protected List<Block/*!*/>/*!*/ CreateInlinedBlocks(CallCmd callCmd, Implementation impl, string nextBlockLabel) {
+ Contract.Requires(nextBlockLabel != null);
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+ Contract.Requires(callCmd != null);
+ Contract.Requires(codeCopier.Subst != null);
+
+ Contract.Requires(codeCopier.OldSubst != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+ List<Block/*!*/>/*!*/ implBlocks = cce.NonNull(impl.OriginalBlocks);
+ Contract.Assert(implBlocks.Count > 0);
+
+ Procedure proc = impl.Proc;
+ string startLabel = implBlocks[0].Label;
+
+ List<Block/*!*/>/*!*/ inlinedBlocks = new List<Block/*!*/>();
+
+ // create in block
+ List<Cmd> inCmds = new List<Cmd>();
+
+ // assign in parameters
+ for (int i = 0; i < impl.InParams.Count; ++i) {
+ Cmd cmd = Cmd.SimpleAssign(impl.tok,
+ (IdentifierExpr)cce.NonNull(codeCopier.Subst)(cce.NonNull(impl.InParams[i])),
+ cce.NonNull(callCmd.Ins[i]));
+ inCmds.Add(cmd);
+ }
+
+ // inject requires
+ for (int i = 0; i < proc.Requires.Count; i++) {
+ Requires/*!*/ req = cce.NonNull(proc.Requires[i]);
+ inCmds.Add(InlinedRequires(callCmd, req));
+ }
+
+ List<Variable> locVars = cce.NonNull(impl.OriginalLocVars);
+
+ // havoc locals and out parameters in case procedure is invoked in a loop
+ List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
+ foreach (Variable v in locVars)
+ {
+ havocVars.Add((IdentifierExpr)codeCopier.Subst(v));
+ }
+ foreach (Variable v in impl.OutParams)
+ {
+ havocVars.Add((IdentifierExpr)codeCopier.Subst(v));
+ }
+ if (havocVars.Count > 0)
+ {
+ inCmds.Add(new HavocCmd(Token.NoToken, havocVars));
+ }
+
+ // add where clauses of local vars as assume
+ for (int i = 0; i < locVars.Count; ++i) {
+ Expr whereExpr = (cce.NonNull(locVars[i])).TypedIdent.WhereExpr;
+ if (whereExpr != null) {
+ whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
+ // FIXME we cannot overwrite it, can we?!
+ (cce.NonNull(locVars[i])).TypedIdent.WhereExpr = whereExpr;
+ AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr);
+ Contract.Assert(a != null);
+ inCmds.Add(a);
+ }
+ }
+
+ // add where clauses of output params as assume
+ for (int i = 0; i < impl.OutParams.Count; ++i) {
+ Expr whereExpr = (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr;
+ if (whereExpr != null) {
+ whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
+ // FIXME likewise
+ (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr = whereExpr;
+ AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr);
+ Contract.Assert(a != null);
+ inCmds.Add(a);
+ }
+ }
+
+ // assign modifies old values
+ foreach (IdentifierExpr/*!*/ mie in proc.Modifies) {
+ Contract.Assert(mie != null);
+ Variable/*!*/ mvar = cce.NonNull(mie.Decl);
+ AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr)cce.NonNull(codeCopier.OldSubst(mvar)), mie);
+ inCmds.Add(assign);
+ }
+
+ GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new List<String> { GetInlinedProcLabel(proc.Name) + "$" + startLabel });
+ Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd);
+ inlinedBlocks.Add(inBlock);
+
+ // inject the blocks of the implementation
+ Block intBlock;
+ foreach (Block block in implBlocks) {
+ List<Cmd> copyCmds = codeCopier.CopyCmdSeq(block.Cmds);
+ if (0 <= inlineDepth) {
+ copyCmds = RemoveAsserts(copyCmds);
+ }
+ TransferCmd transferCmd = CreateInlinedTransferCmd(cce.NonNull(block.TransferCmd), GetInlinedProcLabel(proc.Name));
+ intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd);
+ inlinedBlocks.Add(intBlock);
+ }
+
+ // create out block
+ List<Cmd> outCmds = new List<Cmd>();
+
+ // inject ensures
+ for (int i = 0; i < proc.Ensures.Count; i++) {
+ Ensures/*!*/ ens = cce.NonNull(proc.Ensures[i]);
+ outCmds.Add(InlinedEnsures(callCmd, ens));
+ }
+
+ // assign out params
+ for (int i = 0; i < impl.OutParams.Count; ++i) {
+ Expr/*!*/ cout_exp = (IdentifierExpr)cce.NonNull(codeCopier.Subst(cce.NonNull(impl.OutParams[i])));
+ Cmd cmd = Cmd.SimpleAssign(impl.tok, cce.NonNull(callCmd.Outs[i]), cout_exp);
+ outCmds.Add(cmd);
+ }
+
+ // create out block
+ GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new List<String> { nextBlockLabel });
+ Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd);
+ inlinedBlocks.Add(outBlock);
+
+ return inlinedBlocks;
+ }
+
+ protected TransferCmd CreateInlinedTransferCmd(TransferCmd transferCmd, string procLabel) {
+ Contract.Requires(procLabel != null);
+ Contract.Requires(transferCmd != null);
+ TransferCmd newTransferCmd;
+
+ GotoCmd gotoCmd = transferCmd as GotoCmd;
+ if (gotoCmd != null) {
+ List<String> gotoSeq = gotoCmd.labelNames;
+ List<String> newGotoSeq = new List<String>();
+ foreach (string/*!*/ blockLabel in cce.NonNull(gotoSeq)) {
+ Contract.Assert(blockLabel != null);
+ newGotoSeq.Add(procLabel + "$" + blockLabel);
+ }
+ newTransferCmd = new GotoCmd(transferCmd.tok, newGotoSeq);
+ } else {
+ newTransferCmd = new GotoCmd(transferCmd.tok, new List<String> { procLabel + "$Return" });
+ }
+
+ return newTransferCmd;
+ }
+
+ protected static Implementation FindProcImpl(Program program, Procedure proc) {
+ Contract.Requires(program != null);
+ foreach (var impl in program.Implementations) {
+ if (impl.Proc == proc) {
+ return impl;
+ }
+ }
+ return null;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public class CodeCopier {
+ public Substitution Subst;
+ public Substitution OldSubst;
+
+ public CodeCopier(Dictionary<Variable, Expr> substMap) {
+ Contract.Requires(substMap != null);
+ Subst = Substituter.SubstitutionFromHashtable(substMap);
+ }
+
+ public CodeCopier(Dictionary<Variable, Expr> substMap, Dictionary<Variable, Expr> oldSubstMap) {
+ Contract.Requires(oldSubstMap != null);
+ Contract.Requires(substMap != null);
+ Subst = Substituter.SubstitutionFromHashtable(substMap);
+ OldSubst = Substituter.SubstitutionFromHashtable(oldSubstMap);
+ }
+
+ public CodeCopier() {
+ }
+
+ public List<Cmd> CopyCmdSeq(List<Cmd> cmds) {
+ Contract.Requires(cmds != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ List<Cmd> newCmds = new List<Cmd>();
+ foreach (Cmd/*!*/ cmd in cmds) {
+ Contract.Assert(cmd != null);
+ newCmds.Add(CopyCmd(cmd));
+ }
+ return newCmds;
+ }
+
+ public TransferCmd CopyTransferCmd(TransferCmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<TransferCmd>() != null);
+ TransferCmd transferCmd;
+ GotoCmd gotocmd = cmd as GotoCmd;
+ if (gotocmd != null) {
+ Contract.Assert(gotocmd.labelNames != null);
+ List<String> labels = new List<String>();
+ labels.AddRange(gotocmd.labelNames);
+ transferCmd = new GotoCmd(cmd.tok, labels);
+ } else {
+ ReturnExprCmd returnExprCmd = cmd as ReturnExprCmd;
+ if (returnExprCmd != null)
+ {
+ transferCmd = new ReturnExprCmd(cmd.tok, CopyExpr(returnExprCmd.Expr));
+ }
+ else
+ {
+ transferCmd = new ReturnCmd(cmd.tok);
+ }
+ }
+ return transferCmd;
+ }
+
+ public Cmd CopyCmd(Cmd cmd) {
+ Contract.Requires(cmd != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ if (Subst == null) {
+ return cmd;
+ } else if (OldSubst == null) {
+ return Substituter.Apply(Subst, cmd);
+ } else {
+ return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, cmd);
+ }
+ }
+
+ public Expr CopyExpr(Expr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ if (Subst == null) {
+ return expr;
+ } else if (OldSubst == null) {
+ return Substituter.Apply(Subst, expr);
+ } else {
+ return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, expr);
+ }
+ }
+ } // end class CodeCopier
} // end namespace \ No newline at end of file
diff --git a/Source/Core/InterProceduralReachabilityGraph.cs b/Source/Core/InterProceduralReachabilityGraph.cs
index d75a4b7d..73c88bca 100644
--- a/Source/Core/InterProceduralReachabilityGraph.cs
+++ b/Source/Core/InterProceduralReachabilityGraph.cs
@@ -1,306 +1,306 @@
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie
-{
-
- public interface IInterproceduralReachabilityGraph {
-
- bool MayReach(Block src, Block dst);
-
- void dump();
-
- Block GetNewEntryBlock(string p);
-
- Block GetNewExitBlock(string p);
-
- Block GetNewBlock(Block block);
- }
-
- public class InterproceduralReachabilityGraph : IInterproceduralReachabilityGraph
- {
-
- private Program prog;
- private HashSet<Block> nodes;
- private Dictionary<Block, Block> originalToNew;
- private Dictionary<string, Block> newProcedureEntryNodes;
- private Dictionary<string, Block> newProcedureExitNodes;
-
- private Graph<Block> reachabilityGraph;
-
- public InterproceduralReachabilityGraph(Program prog) {
- this.prog = prog;
- originalToNew = new Dictionary<Block,Block>();
- newProcedureEntryNodes = new Dictionary<string,Block>();
- newProcedureExitNodes = new Dictionary<string,Block>();
- nodes = new HashSet<Block>();
-
- ProcessImplementations();
-
- ProcessBodilessProcedures();
-
- PatchUpGotoTargets();
-
- AddCallAndReturnEdges();
-
- reachabilityGraph = new Graph<Block>();
-
- foreach(var n in nodes) {
- GotoCmd gotoCmd = n.TransferCmd as GotoCmd;
- if(gotoCmd != null) {
- foreach(Block b in gotoCmd.labelTargets) {
- reachabilityGraph.AddEdge(n, b);
- }
- }
- }
-
- foreach(var n in nodes) {
- // If there are disconnected nodes, put them into the
- // graph as self-loops so that every node is represented in
- // the graph
- if(!reachabilityGraph.Nodes.Contains(n)) {
- reachabilityGraph.AddEdge(n, n);
- }
- }
- }
-
- private IEnumerable<Block> OriginalProgramBlocks()
- {
- return prog.Implementations.Select(Item => Item.Blocks).SelectMany(Item => Item);
- }
-
- private void AddCallAndReturnEdges()
- {
- #region Add call and return edges
- foreach (var n in nodes)
- {
- if (n.Cmds.Count == 1 && n.Cmds[0] is CallCmd)
- {
- string proc = ((CallCmd)n.Cmds[0]).callee;
- GotoCmd gotoCmd = n.TransferCmd as GotoCmd;
- Debug.Assert(gotoCmd != null);
-
- for (int i = 0; i < gotoCmd.labelTargets.Count; i++)
- {
- (newProcedureExitNodes[proc].TransferCmd as GotoCmd).labelTargets.Add(gotoCmd.labelTargets[i]);
- (newProcedureExitNodes[proc].TransferCmd as GotoCmd).labelNames.Add(gotoCmd.labelNames[i]);
- }
- gotoCmd.labelTargets = new List<Block> { newProcedureEntryNodes[proc] };
- gotoCmd.labelNames = new List<String> { newProcedureEntryNodes[proc].Label };
- }
- }
- #endregion
- }
-
- private void PatchUpGotoTargets()
- {
- #region Patch up goto targets
- foreach (var n in nodes)
- {
- var gotoCmd = n.TransferCmd as GotoCmd;
- if (gotoCmd != null)
- {
- List<Block> newTargets = new List<Block>();
- foreach (Block t in gotoCmd.labelTargets)
- {
- if (originalToNew.ContainsKey(t))
- {
- newTargets.Add(originalToNew[t]);
- }
- else
- {
- newTargets.Add(t);
- }
- }
- gotoCmd.labelTargets = newTargets;
- }
- }
- #endregion
- }
-
- private void ProcessBodilessProcedures()
- {
- #region Add single node CFG for procedures with no body
- foreach (var proc in prog.Procedures)
- {
- if (!newProcedureEntryNodes.ContainsKey(proc.Name))
- {
- Block newBlock = new Block(Token.NoToken, proc + "__dummy_node", new List<Cmd>(), new GotoCmd(Token.NoToken, new List<Block>()));
- nodes.Add(newBlock);
- newProcedureEntryNodes[proc.Name] = newBlock;
- newProcedureExitNodes[proc.Name] = newBlock;
- }
- }
- #endregion
- }
-
- private void ProcessImplementations()
- {
- #region Transform implementation CFGs so that every call is in its own basic block
- foreach (var impl in prog.Implementations)
- {
- string exitLabel = "__" + impl.Name + "_newExit";
- Block newExit = new Block(Token.NoToken, exitLabel, new List<Cmd>(), new GotoCmd(Token.NoToken, new List<Block>()));
- nodes.Add(newExit);
- newProcedureExitNodes[impl.Name] = newExit;
- foreach (Block b in impl.Blocks)
- {
- Block prev = null;
- int i = 0;
- foreach (List<Cmd> cmds in SeparateCallCmds(b.Cmds))
- {
- Block newBlock;
- if (prev == null)
- {
- newBlock = new Block(b.tok, "__" + impl.Name + "_" + b.Label, new List<Cmd>(cmds.ToArray()), null);
- nodes.Add(newBlock);
- originalToNew[b] = newBlock;
- if (impl.Blocks[0] == b)
- {
- newProcedureEntryNodes[impl.Name] = newBlock;
- }
- }
- else
- {
- string label = "__" + impl.Name + "_" + b.Label + "_call_" + i;
- newBlock = new Block(b.tok, label, new List<Cmd>(cmds.ToArray()), null);
- nodes.Add(newBlock);
- originalToNew[newBlock] = newBlock;
- prev.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { label }, new List<Block> { newBlock });
- }
- prev = newBlock;
- i++;
- }
- Debug.Assert(prev != null);
- if (b.TransferCmd is ReturnCmd || (b.TransferCmd is GotoCmd &&
- ((GotoCmd)b.TransferCmd).labelTargets.Count == 0))
- {
- prev.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { exitLabel }, new List<Block> { newExit });
- }
- else
- {
- if(b.TransferCmd is ReturnCmd) {
- prev.TransferCmd = new ReturnCmd(b.TransferCmd.tok);
- } else {
- var gotoCmd = b.TransferCmd as GotoCmd;
- Debug.Assert(gotoCmd != null);
- prev.TransferCmd = new GotoCmd(gotoCmd.tok, gotoCmd.labelNames, gotoCmd.labelTargets);
- }
- }
- }
- }
- #endregion
- }
-
- private static List<List<Cmd>> SeparateCallCmds(List<Cmd> Cmds) {
- List<List<Cmd>> result = new List<List<Cmd>>();
- int currentIndex = 0;
- while(currentIndex < Cmds.Count) {
- if(Cmds[currentIndex] is CallCmd) {
- result.Add(new List<Cmd> { Cmds[currentIndex] });
- currentIndex++;
- } else {
- List<Cmd> nonCallCmds = new List<Cmd>();
- while(currentIndex < Cmds.Count && !(Cmds[currentIndex] is CallCmd)) {
- nonCallCmds.Add(Cmds[currentIndex]);
- currentIndex++;
- }
- result.Add(nonCallCmds);
- }
- }
- if(result.Count == 0) {
- result.Add(new List<Cmd>());
- }
- return result;
- }
-
- private Graph<SCC<Block>> ReachabilityGraphSCCsDAG;
- private Dictionary<Block, SCC<Block>> BlockToSCC;
-
- private Dictionary<SCC<Block>, HashSet<Block>> MayReachCache = new Dictionary<SCC<Block>, HashSet<Block>>();
-
- public bool MayReach(Block src, Block dst) {
- if (ReachabilityGraphSCCsDAG == null) {
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Interprocedural reachability: computing SCCs");
- }
- Adjacency<Block> next = new Adjacency<Block>(reachabilityGraph.Successors);
- Adjacency<Block> prev = new Adjacency<Block>(reachabilityGraph.Predecessors);
- StronglyConnectedComponents<Block> ReachabilitySCCs = new StronglyConnectedComponents<Block>(
- reachabilityGraph.Nodes, next, prev);
- ReachabilitySCCs.Compute();
-
- BlockToSCC = new Dictionary<Block, SCC<Block>>();
- foreach (var scc in ReachabilitySCCs) {
- foreach (var s in scc) {
- BlockToSCC[s] = scc;
- }
- }
-
- ReachabilityGraphSCCsDAG = new Graph<SCC<Block>>();
- foreach (var edge in reachabilityGraph.Edges) {
- if (BlockToSCC[edge.Item1] != BlockToSCC[edge.Item2]) {
- ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[edge.Item1], BlockToSCC[edge.Item2]);
- }
- }
-
- SCC<Block> dummy = new SCC<Block>();
- foreach (var n in reachabilityGraph.Nodes) {
- ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[n], dummy);
- }
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Interprocedural reachability: SCCs computed!");
- }
- }
- return ReachableFrom(BlockToSCC[src]).Contains(dst);
- }
-
- private HashSet<Block> ReachableFrom(SCC<Block> scc) {
- if (!MayReachCache.ContainsKey(scc)) {
- HashSet<Block> result = new HashSet<Block>();
- if (scc.Count() > 0) {
- result.UnionWith(scc);
- foreach (var nextSCC in ReachabilityGraphSCCsDAG.Successors(scc)) {
- result.UnionWith(ReachableFrom(nextSCC));
- }
- }
- MayReachCache[scc] = result;
- }
- return MayReachCache[scc];
- }
-
- public void dump() {
- foreach(var n in nodes) {
- Console.WriteLine(n.Label + " -> {");
- GotoCmd gotoCmd = n.TransferCmd as GotoCmd;
- if(n != null) {
- foreach(Block m in gotoCmd.labelTargets) {
- Console.WriteLine(" " + m.Label);
- }
- }
- Console.WriteLine("}");
- }
- }
-
- public Block GetNewEntryBlock(string proc) {
- return newProcedureEntryNodes[proc];
- }
-
- public Block GetNewExitBlock(string proc) {
- return newProcedureExitNodes[proc];
- }
-
- public Block GetNewBlock(Block b) {
- return originalToNew[b];
- }
-
- }
-
-
-}
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie
+{
+
+ public interface IInterproceduralReachabilityGraph {
+
+ bool MayReach(Block src, Block dst);
+
+ void dump();
+
+ Block GetNewEntryBlock(string p);
+
+ Block GetNewExitBlock(string p);
+
+ Block GetNewBlock(Block block);
+ }
+
+ public class InterproceduralReachabilityGraph : IInterproceduralReachabilityGraph
+ {
+
+ private Program prog;
+ private HashSet<Block> nodes;
+ private Dictionary<Block, Block> originalToNew;
+ private Dictionary<string, Block> newProcedureEntryNodes;
+ private Dictionary<string, Block> newProcedureExitNodes;
+
+ private Graph<Block> reachabilityGraph;
+
+ public InterproceduralReachabilityGraph(Program prog) {
+ this.prog = prog;
+ originalToNew = new Dictionary<Block,Block>();
+ newProcedureEntryNodes = new Dictionary<string,Block>();
+ newProcedureExitNodes = new Dictionary<string,Block>();
+ nodes = new HashSet<Block>();
+
+ ProcessImplementations();
+
+ ProcessBodilessProcedures();
+
+ PatchUpGotoTargets();
+
+ AddCallAndReturnEdges();
+
+ reachabilityGraph = new Graph<Block>();
+
+ foreach(var n in nodes) {
+ GotoCmd gotoCmd = n.TransferCmd as GotoCmd;
+ if(gotoCmd != null) {
+ foreach(Block b in gotoCmd.labelTargets) {
+ reachabilityGraph.AddEdge(n, b);
+ }
+ }
+ }
+
+ foreach(var n in nodes) {
+ // If there are disconnected nodes, put them into the
+ // graph as self-loops so that every node is represented in
+ // the graph
+ if(!reachabilityGraph.Nodes.Contains(n)) {
+ reachabilityGraph.AddEdge(n, n);
+ }
+ }
+ }
+
+ private IEnumerable<Block> OriginalProgramBlocks()
+ {
+ return prog.Implementations.Select(Item => Item.Blocks).SelectMany(Item => Item);
+ }
+
+ private void AddCallAndReturnEdges()
+ {
+ #region Add call and return edges
+ foreach (var n in nodes)
+ {
+ if (n.Cmds.Count == 1 && n.Cmds[0] is CallCmd)
+ {
+ string proc = ((CallCmd)n.Cmds[0]).callee;
+ GotoCmd gotoCmd = n.TransferCmd as GotoCmd;
+ Debug.Assert(gotoCmd != null);
+
+ for (int i = 0; i < gotoCmd.labelTargets.Count; i++)
+ {
+ (newProcedureExitNodes[proc].TransferCmd as GotoCmd).labelTargets.Add(gotoCmd.labelTargets[i]);
+ (newProcedureExitNodes[proc].TransferCmd as GotoCmd).labelNames.Add(gotoCmd.labelNames[i]);
+ }
+ gotoCmd.labelTargets = new List<Block> { newProcedureEntryNodes[proc] };
+ gotoCmd.labelNames = new List<String> { newProcedureEntryNodes[proc].Label };
+ }
+ }
+ #endregion
+ }
+
+ private void PatchUpGotoTargets()
+ {
+ #region Patch up goto targets
+ foreach (var n in nodes)
+ {
+ var gotoCmd = n.TransferCmd as GotoCmd;
+ if (gotoCmd != null)
+ {
+ List<Block> newTargets = new List<Block>();
+ foreach (Block t in gotoCmd.labelTargets)
+ {
+ if (originalToNew.ContainsKey(t))
+ {
+ newTargets.Add(originalToNew[t]);
+ }
+ else
+ {
+ newTargets.Add(t);
+ }
+ }
+ gotoCmd.labelTargets = newTargets;
+ }
+ }
+ #endregion
+ }
+
+ private void ProcessBodilessProcedures()
+ {
+ #region Add single node CFG for procedures with no body
+ foreach (var proc in prog.Procedures)
+ {
+ if (!newProcedureEntryNodes.ContainsKey(proc.Name))
+ {
+ Block newBlock = new Block(Token.NoToken, proc + "__dummy_node", new List<Cmd>(), new GotoCmd(Token.NoToken, new List<Block>()));
+ nodes.Add(newBlock);
+ newProcedureEntryNodes[proc.Name] = newBlock;
+ newProcedureExitNodes[proc.Name] = newBlock;
+ }
+ }
+ #endregion
+ }
+
+ private void ProcessImplementations()
+ {
+ #region Transform implementation CFGs so that every call is in its own basic block
+ foreach (var impl in prog.Implementations)
+ {
+ string exitLabel = "__" + impl.Name + "_newExit";
+ Block newExit = new Block(Token.NoToken, exitLabel, new List<Cmd>(), new GotoCmd(Token.NoToken, new List<Block>()));
+ nodes.Add(newExit);
+ newProcedureExitNodes[impl.Name] = newExit;
+ foreach (Block b in impl.Blocks)
+ {
+ Block prev = null;
+ int i = 0;
+ foreach (List<Cmd> cmds in SeparateCallCmds(b.Cmds))
+ {
+ Block newBlock;
+ if (prev == null)
+ {
+ newBlock = new Block(b.tok, "__" + impl.Name + "_" + b.Label, new List<Cmd>(cmds.ToArray()), null);
+ nodes.Add(newBlock);
+ originalToNew[b] = newBlock;
+ if (impl.Blocks[0] == b)
+ {
+ newProcedureEntryNodes[impl.Name] = newBlock;
+ }
+ }
+ else
+ {
+ string label = "__" + impl.Name + "_" + b.Label + "_call_" + i;
+ newBlock = new Block(b.tok, label, new List<Cmd>(cmds.ToArray()), null);
+ nodes.Add(newBlock);
+ originalToNew[newBlock] = newBlock;
+ prev.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { label }, new List<Block> { newBlock });
+ }
+ prev = newBlock;
+ i++;
+ }
+ Debug.Assert(prev != null);
+ if (b.TransferCmd is ReturnCmd || (b.TransferCmd is GotoCmd &&
+ ((GotoCmd)b.TransferCmd).labelTargets.Count == 0))
+ {
+ prev.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { exitLabel }, new List<Block> { newExit });
+ }
+ else
+ {
+ if(b.TransferCmd is ReturnCmd) {
+ prev.TransferCmd = new ReturnCmd(b.TransferCmd.tok);
+ } else {
+ var gotoCmd = b.TransferCmd as GotoCmd;
+ Debug.Assert(gotoCmd != null);
+ prev.TransferCmd = new GotoCmd(gotoCmd.tok, gotoCmd.labelNames, gotoCmd.labelTargets);
+ }
+ }
+ }
+ }
+ #endregion
+ }
+
+ private static List<List<Cmd>> SeparateCallCmds(List<Cmd> Cmds) {
+ List<List<Cmd>> result = new List<List<Cmd>>();
+ int currentIndex = 0;
+ while(currentIndex < Cmds.Count) {
+ if(Cmds[currentIndex] is CallCmd) {
+ result.Add(new List<Cmd> { Cmds[currentIndex] });
+ currentIndex++;
+ } else {
+ List<Cmd> nonCallCmds = new List<Cmd>();
+ while(currentIndex < Cmds.Count && !(Cmds[currentIndex] is CallCmd)) {
+ nonCallCmds.Add(Cmds[currentIndex]);
+ currentIndex++;
+ }
+ result.Add(nonCallCmds);
+ }
+ }
+ if(result.Count == 0) {
+ result.Add(new List<Cmd>());
+ }
+ return result;
+ }
+
+ private Graph<SCC<Block>> ReachabilityGraphSCCsDAG;
+ private Dictionary<Block, SCC<Block>> BlockToSCC;
+
+ private Dictionary<SCC<Block>, HashSet<Block>> MayReachCache = new Dictionary<SCC<Block>, HashSet<Block>>();
+
+ public bool MayReach(Block src, Block dst) {
+ if (ReachabilityGraphSCCsDAG == null) {
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Interprocedural reachability: computing SCCs");
+ }
+ Adjacency<Block> next = new Adjacency<Block>(reachabilityGraph.Successors);
+ Adjacency<Block> prev = new Adjacency<Block>(reachabilityGraph.Predecessors);
+ StronglyConnectedComponents<Block> ReachabilitySCCs = new StronglyConnectedComponents<Block>(
+ reachabilityGraph.Nodes, next, prev);
+ ReachabilitySCCs.Compute();
+
+ BlockToSCC = new Dictionary<Block, SCC<Block>>();
+ foreach (var scc in ReachabilitySCCs) {
+ foreach (var s in scc) {
+ BlockToSCC[s] = scc;
+ }
+ }
+
+ ReachabilityGraphSCCsDAG = new Graph<SCC<Block>>();
+ foreach (var edge in reachabilityGraph.Edges) {
+ if (BlockToSCC[edge.Item1] != BlockToSCC[edge.Item2]) {
+ ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[edge.Item1], BlockToSCC[edge.Item2]);
+ }
+ }
+
+ SCC<Block> dummy = new SCC<Block>();
+ foreach (var n in reachabilityGraph.Nodes) {
+ ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[n], dummy);
+ }
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Interprocedural reachability: SCCs computed!");
+ }
+ }
+ return ReachableFrom(BlockToSCC[src]).Contains(dst);
+ }
+
+ private HashSet<Block> ReachableFrom(SCC<Block> scc) {
+ if (!MayReachCache.ContainsKey(scc)) {
+ HashSet<Block> result = new HashSet<Block>();
+ if (scc.Count() > 0) {
+ result.UnionWith(scc);
+ foreach (var nextSCC in ReachabilityGraphSCCsDAG.Successors(scc)) {
+ result.UnionWith(ReachableFrom(nextSCC));
+ }
+ }
+ MayReachCache[scc] = result;
+ }
+ return MayReachCache[scc];
+ }
+
+ public void dump() {
+ foreach(var n in nodes) {
+ Console.WriteLine(n.Label + " -> {");
+ GotoCmd gotoCmd = n.TransferCmd as GotoCmd;
+ if(n != null) {
+ foreach(Block m in gotoCmd.labelTargets) {
+ Console.WriteLine(" " + m.Label);
+ }
+ }
+ Console.WriteLine("}");
+ }
+ }
+
+ public Block GetNewEntryBlock(string proc) {
+ return newProcedureEntryNodes[proc];
+ }
+
+ public Block GetNewExitBlock(string proc) {
+ return newProcedureExitNodes[proc];
+ }
+
+ public Block GetNewBlock(Block b) {
+ return originalToNew[b];
+ }
+
+ }
+
+
+}
diff --git a/Source/Core/LambdaHelper.cs b/Source/Core/LambdaHelper.cs
index d07eaac6..a566daaf 100644
--- a/Source/Core/LambdaHelper.cs
+++ b/Source/Core/LambdaHelper.cs
@@ -1,259 +1,259 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
-
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
- using Set = GSet<object>; // for the purposes here, "object" really means "either Variable or TypeVariable"
-
- public static class LambdaHelper {
- public static Program Desugar(Program program, out List<Expr/*!*/>/*!*/ axioms, out List<Function/*!*/>/*!*/ functions) {
- Contract.Requires(program != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out functions)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out axioms)));
- Contract.Ensures(Contract.Result<Program>() != null);
- LambdaVisitor v = new LambdaVisitor();
- program = v.VisitProgram(program);
- axioms = v.lambdaAxioms;
- functions = v.lambdaFunctions;
- if (CommandLineOptions.Clo.TraceVerify) {
- Console.WriteLine("Desugaring of lambda expressions produced {0} functions and {1} axioms:", functions.Count, axioms.Count);
- TokenTextWriter wr = new TokenTextWriter("<console>", Console.Out, /*pretty=*/ false);
- foreach (Function f in functions) {
- f.Emit(wr, 0);
- }
- foreach (Expr ax in axioms) {
- ax.Emit(wr);
- Console.WriteLine();
- }
- }
- return program;
- }
-
- public static void ExpandLambdas(Program prog) {
- Contract.Requires(prog != null);
- List<Expr/*!*/>/*!*/ axioms;
- List<Function/*!*/>/*!*/ functions;
-
- Desugar(prog, out axioms, out functions);
- foreach (var f in functions) {
- prog.AddTopLevelDeclaration(f);
- }
- foreach (var a in axioms) {
- prog.AddTopLevelDeclaration(new Axiom(a.tok, a));
- }
- }
-
- private class LambdaVisitor : StandardVisitor {
- private readonly Dictionary<Expr, FunctionCall> liftedLambdas =
- new Dictionary<Expr, FunctionCall>(new AlphaEquality());
-
- internal List<Expr/*!*/>/*!*/ lambdaAxioms = new List<Expr/*!*/>();
- internal List<Function/*!*/>/*!*/ lambdaFunctions = new List<Function/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(lambdaAxioms));
- Contract.Invariant(cce.NonNullElements(lambdaFunctions));
- }
-
- int lambdaid = 0;
-
- string FreshLambdaFunctionName()
- {
- // TODO(wuestholz): Should we use a counter per top-level declaration?
- return string.Format("lambda#{0}", lambdaid++);
- }
-
- public override Expr VisitLambdaExpr(LambdaExpr lambda) {
- var baseResult = base.VisitLambdaExpr(lambda);
- lambda = baseResult as LambdaExpr;
- if (lambda == null) {
- return baseResult; // apparently, the base visitor already turned the lambda into something else
- }
-
- // We start by getting rid of any use of "old" inside the lambda. This is done as follows.
- // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og".
- // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers.
- var oldFinder = new OldFinder();
- oldFinder.Visit(lambda);
- var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0
- var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g)
- foreach (var v in oldFinder.FreeOldVars) {
- var g = v as GlobalVariable;
- if (g != null) {
- var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type));
- oldSubst.Add(g, new IdentifierExpr(g0.tok, g0));
- callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g)));
- }
- }
- var lambdaBody = Substituter.ApplyReplacingOldExprs(
- Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()),
- Substituter.SubstitutionFromHashtable(oldSubst),
- lambda.Body);
- var lambdaAttrs = Substituter.ApplyReplacingOldExprs(
- Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()),
- Substituter.SubstitutionFromHashtable(oldSubst),
- lambda.Attributes);
-
- if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null)
- {
- // Attach a dummy checksum to avoid issues in the dependency analysis.
- var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> { "stable" }, null);
- if (lambdaAttrs == null)
- {
- lambdaAttrs = checksumAttr;
- }
- else
- {
- lambdaAttrs.AddLast(checksumAttr);
- }
- }
-
- // this is ugly, the output will depend on hashing order
- var subst = new Dictionary<Variable, Expr>();
- var substFnAttrs = new Dictionary<Variable, Expr>();
- var formals = new List<Variable>();
- var callArgs = new List<Expr>();
- var axCallArgs = new List<Expr>();
- var dummies = new List<Variable>(lambda.Dummies);
- var freeTypeVars = new List<TypeVariable>();
- var fnTypeVarActuals = new List<Type/*!*/>();
- var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition
-
- // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body
- Set freeVars = new Set();
- BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, lambdaAttrs, freeVars);
-
- foreach (object o in freeVars) {
- // 'o' is either a Variable or a TypeVariable.
- if (o is Variable) {
- var v = o as Variable;
- var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type);
- var f = new Formal(v.tok, ti, true);
- formals.Add(f);
- substFnAttrs.Add(v, new IdentifierExpr(f.tok, f));
- var b = new BoundVariable(v.tok, ti);
- dummies.Add(b);
- if (callOldMapping.ContainsKey(v)) {
- callArgs.Add(callOldMapping[v]);
- } else {
- callArgs.Add(new IdentifierExpr(v.tok, v));
- }
- Expr id = new IdentifierExpr(b.tok, b);
- subst.Add(v, id);
- axCallArgs.Add(id);
- } else {
- var tv = (TypeVariable)o;
- freeTypeVars.Add(tv);
- fnTypeVarActuals.Add(tv);
- freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name));
- }
- }
-
- var sw = new System.IO.StringWriter();
- var wr = new TokenTextWriter(sw, true);
- lambda.Emit(wr);
- string lam_str = sw.ToString();
-
- FunctionCall fcall;
- IToken tok = lambda.tok;
- Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false);
-
- if (liftedLambdas.TryGetValue(lambda, out fcall)) {
- if (CommandLineOptions.Clo.TraceVerify) {
- Console.WriteLine("Old lambda: {0}", lam_str);
- }
- } else {
- if (CommandLineOptions.Clo.TraceVerify) {
- Console.WriteLine("New lambda: {0}", lam_str);
- }
- Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function",
- Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs));
-
- fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name));
- fcall.Func = fn; // resolve here
- liftedLambdas[lambda] = fcall;
-
- List<Expr/*!*/> selectArgs = new List<Expr/*!*/>();
- foreach (Variable/*!*/ v in lambda.Dummies) {
- Contract.Assert(v != null);
- selectArgs.Add(new IdentifierExpr(v.tok, v));
- }
- NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs);
- axcall.Type = res.TypedIdent.Type;
- axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals);
- NAryExpr select = Expr.Select(axcall, selectArgs);
- select.Type = lambdaBody.Type;
- List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>();
- List<TypeVariable> forallTypeVariables = new List<TypeVariable>();
- foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) {
- Contract.Assert(tp != null);
- selectTypeParamActuals.Add(tp);
- forallTypeVariables.Add(tp);
- }
- forallTypeVariables.AddRange(freeTypeVars);
- select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals);
-
- Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody);
- NAryExpr body = Expr.Eq(select, bb);
- body.Type = Type.Bool;
- body.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- Trigger trig = new Trigger(select.tok, true, new List<Expr> { select });
-
- lambdaFunctions.Add(fn);
- lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies,
- Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs),
- trig, body));
- }
-
- NAryExpr call = new NAryExpr(tok, fcall, callArgs);
- call.Type = res.TypedIdent.Type;
- call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals);
-
- return call;
- }
- public override Cmd VisitCallCmd(CallCmd node) {
- var baseResult = base.VisitCallCmd(node);
- node = baseResult as CallCmd;
- if (node == null) {
- return baseResult; // apparently, the base visitor already turned the lambda into something else
- }
- // also visit the desugaring (which the StandardVisitor does not do)
- node.VisitDesugaring(this);
- return node;
- }
- }
- }
-
- class OldFinder : ReadOnlyVisitor
- {
- public readonly GSet<Variable> FreeOldVars = new GSet<Variable>();
- public override Expr VisitOldExpr(OldExpr node) {
- Set freeVars = new Set();
- node.Expr.ComputeFreeVariables(freeVars);
- foreach (var v in freeVars) {
- // Note, "v" is either a Variable or a TypeVariable
- if (v is Variable) {
- FreeOldVars.Add((Variable)v);
- }
- }
- return node; // don't visit subexpressions, since ComputeFreeVariables has already gone through those
- }
- public override BinderExpr VisitBinderExpr(BinderExpr node) {
- base.VisitBinderExpr(node);
- // visit attributes, even though StandardVisitor does not do that (but maybe it should?)
- if (node.Attributes != null) {
- this.Visit(node.Attributes);
- }
- return node;
- }
- }
-
-} // end namespace \ No newline at end of file
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using Set = GSet<object>; // for the purposes here, "object" really means "either Variable or TypeVariable"
+
+ public static class LambdaHelper {
+ public static Program Desugar(Program program, out List<Expr/*!*/>/*!*/ axioms, out List<Function/*!*/>/*!*/ functions) {
+ Contract.Requires(program != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out functions)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out axioms)));
+ Contract.Ensures(Contract.Result<Program>() != null);
+ LambdaVisitor v = new LambdaVisitor();
+ program = v.VisitProgram(program);
+ axioms = v.lambdaAxioms;
+ functions = v.lambdaFunctions;
+ if (CommandLineOptions.Clo.TraceVerify) {
+ Console.WriteLine("Desugaring of lambda expressions produced {0} functions and {1} axioms:", functions.Count, axioms.Count);
+ TokenTextWriter wr = new TokenTextWriter("<console>", Console.Out, /*pretty=*/ false);
+ foreach (Function f in functions) {
+ f.Emit(wr, 0);
+ }
+ foreach (Expr ax in axioms) {
+ ax.Emit(wr);
+ Console.WriteLine();
+ }
+ }
+ return program;
+ }
+
+ public static void ExpandLambdas(Program prog) {
+ Contract.Requires(prog != null);
+ List<Expr/*!*/>/*!*/ axioms;
+ List<Function/*!*/>/*!*/ functions;
+
+ Desugar(prog, out axioms, out functions);
+ foreach (var f in functions) {
+ prog.AddTopLevelDeclaration(f);
+ }
+ foreach (var a in axioms) {
+ prog.AddTopLevelDeclaration(new Axiom(a.tok, a));
+ }
+ }
+
+ private class LambdaVisitor : StandardVisitor {
+ private readonly Dictionary<Expr, FunctionCall> liftedLambdas =
+ new Dictionary<Expr, FunctionCall>(new AlphaEquality());
+
+ internal List<Expr/*!*/>/*!*/ lambdaAxioms = new List<Expr/*!*/>();
+ internal List<Function/*!*/>/*!*/ lambdaFunctions = new List<Function/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(lambdaAxioms));
+ Contract.Invariant(cce.NonNullElements(lambdaFunctions));
+ }
+
+ int lambdaid = 0;
+
+ string FreshLambdaFunctionName()
+ {
+ return string.Format("lambda#{0}", lambdaid++);
+ }
+
+ public override Expr VisitLambdaExpr(LambdaExpr lambda) {
+ var baseResult = base.VisitLambdaExpr(lambda);
+ lambda = baseResult as LambdaExpr;
+ if (lambda == null) {
+ return baseResult; // apparently, the base visitor already turned the lambda into something else
+ }
+
+ // We start by getting rid of any use of "old" inside the lambda. This is done as follows.
+ // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og".
+ // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers.
+ var oldFinder = new OldFinder();
+ oldFinder.Visit(lambda);
+ var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0
+ var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g)
+ foreach (var v in oldFinder.FreeOldVars) {
+ var g = v as GlobalVariable;
+ if (g != null) {
+ var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type));
+ oldSubst.Add(g, new IdentifierExpr(g0.tok, g0));
+ callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g)));
+ }
+ }
+ var lambdaBody = Substituter.ApplyReplacingOldExprs(
+ Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()),
+ Substituter.SubstitutionFromHashtable(oldSubst),
+ lambda.Body);
+ var lambdaAttrs = Substituter.ApplyReplacingOldExprs(
+ Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()),
+ Substituter.SubstitutionFromHashtable(oldSubst),
+ lambda.Attributes);
+
+ if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null)
+ {
+ // Attach a dummy checksum to avoid issues in the dependency analysis.
+ var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> { "lambda expression" }, null);
+ if (lambdaAttrs == null)
+ {
+ lambdaAttrs = checksumAttr;
+ }
+ else
+ {
+ lambdaAttrs.AddLast(checksumAttr);
+ }
+ }
+
+ // this is ugly, the output will depend on hashing order
+ var subst = new Dictionary<Variable, Expr>();
+ var substFnAttrs = new Dictionary<Variable, Expr>();
+ var formals = new List<Variable>();
+ var callArgs = new List<Expr>();
+ var axCallArgs = new List<Expr>();
+ var dummies = new List<Variable>(lambda.Dummies);
+ var freeTypeVars = new List<TypeVariable>();
+ var fnTypeVarActuals = new List<Type/*!*/>();
+ var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition
+
+ // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body
+ Set freeVars = new Set();
+ BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, lambdaAttrs, freeVars);
+
+ foreach (object o in freeVars) {
+ // 'o' is either a Variable or a TypeVariable.
+ if (o is Variable) {
+ var v = o as Variable;
+ var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type);
+ var f = new Formal(v.tok, ti, true);
+ formals.Add(f);
+ substFnAttrs.Add(v, new IdentifierExpr(f.tok, f));
+ var b = new BoundVariable(v.tok, ti);
+ dummies.Add(b);
+ if (callOldMapping.ContainsKey(v)) {
+ callArgs.Add(callOldMapping[v]);
+ } else {
+ callArgs.Add(new IdentifierExpr(v.tok, v));
+ }
+ Expr id = new IdentifierExpr(b.tok, b);
+ subst.Add(v, id);
+ axCallArgs.Add(id);
+ } else {
+ var tv = (TypeVariable)o;
+ freeTypeVars.Add(tv);
+ fnTypeVarActuals.Add(tv);
+ freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name));
+ }
+ }
+
+ var sw = new System.IO.StringWriter();
+ var wr = new TokenTextWriter(sw, true);
+ lambda.Emit(wr);
+ string lam_str = sw.ToString();
+
+ FunctionCall fcall;
+ IToken tok = lambda.tok;
+ Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false);
+
+ if (liftedLambdas.TryGetValue(lambda, out fcall)) {
+ if (CommandLineOptions.Clo.TraceVerify) {
+ Console.WriteLine("Old lambda: {0}", lam_str);
+ }
+ } else {
+ if (CommandLineOptions.Clo.TraceVerify) {
+ Console.WriteLine("New lambda: {0}", lam_str);
+ }
+ Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function",
+ Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs));
+ fn.OriginalLambdaExprAsString = lam_str;
+
+ fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name));
+ fcall.Func = fn; // resolve here
+ liftedLambdas[lambda] = fcall;
+
+ List<Expr/*!*/> selectArgs = new List<Expr/*!*/>();
+ foreach (Variable/*!*/ v in lambda.Dummies) {
+ Contract.Assert(v != null);
+ selectArgs.Add(new IdentifierExpr(v.tok, v));
+ }
+ NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs);
+ axcall.Type = res.TypedIdent.Type;
+ axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals);
+ NAryExpr select = Expr.Select(axcall, selectArgs);
+ select.Type = lambdaBody.Type;
+ List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>();
+ List<TypeVariable> forallTypeVariables = new List<TypeVariable>();
+ foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) {
+ Contract.Assert(tp != null);
+ selectTypeParamActuals.Add(tp);
+ forallTypeVariables.Add(tp);
+ }
+ forallTypeVariables.AddRange(freeTypeVars);
+ select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals);
+
+ Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody);
+ NAryExpr body = Expr.Eq(select, bb);
+ body.Type = Type.Bool;
+ body.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ Trigger trig = new Trigger(select.tok, true, new List<Expr> { select });
+
+ lambdaFunctions.Add(fn);
+ lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies,
+ Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs),
+ trig, body));
+ }
+
+ NAryExpr call = new NAryExpr(tok, fcall, callArgs);
+ call.Type = res.TypedIdent.Type;
+ call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals);
+
+ return call;
+ }
+ public override Cmd VisitCallCmd(CallCmd node) {
+ var baseResult = base.VisitCallCmd(node);
+ node = baseResult as CallCmd;
+ if (node == null) {
+ return baseResult; // apparently, the base visitor already turned the lambda into something else
+ }
+ // also visit the desugaring (which the StandardVisitor does not do)
+ node.VisitDesugaring(this);
+ return node;
+ }
+ }
+ }
+
+ class OldFinder : ReadOnlyVisitor
+ {
+ public readonly GSet<Variable> FreeOldVars = new GSet<Variable>();
+ public override Expr VisitOldExpr(OldExpr node) {
+ Set freeVars = new Set();
+ node.Expr.ComputeFreeVariables(freeVars);
+ foreach (var v in freeVars) {
+ // Note, "v" is either a Variable or a TypeVariable
+ if (v is Variable) {
+ FreeOldVars.Add((Variable)v);
+ }
+ }
+ return node; // don't visit subexpressions, since ComputeFreeVariables has already gone through those
+ }
+ public override BinderExpr VisitBinderExpr(BinderExpr node) {
+ base.VisitBinderExpr(node);
+ // visit attributes, even though StandardVisitor does not do that (but maybe it should?)
+ if (node.Attributes != null) {
+ this.Visit(node.Attributes);
+ }
+ return node;
+ }
+ }
+
+} // end namespace
diff --git a/Source/Core/LoopUnroll.cs b/Source/Core/LoopUnroll.cs
index df1be84c..036d5f73 100644
--- a/Source/Core/LoopUnroll.cs
+++ b/Source/Core/LoopUnroll.cs
@@ -1,286 +1,286 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Diagnostics.Contracts;
-using System.Collections.Generic;
-using Bpl = Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie {
- public class LoopUnroll {
- public static List<Block/*!*/>/*!*/ UnrollLoops(Block start, int unrollMaxDepth, bool soundLoopUnrolling) {
- Contract.Requires(start != null);
-
- Contract.Requires(0 <= unrollMaxDepth);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- Dictionary<Block, GraphNode/*!*/> gd = new Dictionary<Block, GraphNode/*!*/>();
- HashSet<Block> beingVisited = new HashSet<Block>();
- GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited);
-
- // Compute SCCs
- StronglyConnectedComponents<GraphNode/*!*/> sccs =
- new StronglyConnectedComponents<GraphNode/*!*/>(gd.Values, Preds, Succs);
- Contract.Assert(sccs != null);
- sccs.Compute();
- Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> containingSCC = new Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>();
- foreach (SCC<GraphNode/*!*/> scc in sccs) {
- foreach (GraphNode/*!*/ n in scc) {
- Contract.Assert(n != null);
- containingSCC[n] = scc;
- }
- }
-
- LoopUnroll lu = new LoopUnroll(unrollMaxDepth, soundLoopUnrolling, containingSCC, new List<Block/*!*/>());
- lu.Visit(gStart);
- lu.newBlockSeqGlobal.Reverse();
- return lu.newBlockSeqGlobal;
- }
-
- // This is supposed to "undo" to effect of loop unrolling
- // on block labels. It essentially removes the "#num" from the end
- // of lab, if there is something like this
- public static string sanitizeLabel(string lab)
- {
- if (!lab.Contains("#"))
- return lab;
-
- // Find the last occurrance of "#"
- int pos = lab.LastIndexOf('#');
-
- return lab.Substring(0, pos);
- }
-
- private static System.Collections.IEnumerable/*<GraphNode/*!>/*!*/ Succs(GraphNode n) {
- Contract.Requires(n != null);
- Contract.Ensures(Contract.Result<System.Collections.IEnumerable>() != null);
-
- List<GraphNode/*!*/>/*!*/ AllEdges = new List<GraphNode/*!*/>();
- AllEdges.AddRange(n.ForwardEdges);
- AllEdges.AddRange(n.BackEdges);
- return AllEdges;
- }
- private static System.Collections.IEnumerable/*<GraphNode!>*//*!*/ Preds(GraphNode n) {
- Contract.Requires(n != null);
- Contract.Ensures(Contract.Result<System.Collections.IEnumerable>() != null);
-
- return n.Predecessors;
- }
-
- class GraphNode {
- public readonly Block/*!*/ Block;
- public readonly List<Cmd>/*!*/ Body;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Block != null);
- Contract.Invariant(Body != null);
- Contract.Invariant(cce.NonNullElements(ForwardEdges));
- Contract.Invariant(cce.NonNullElements(BackEdges));
- Contract.Invariant(cce.NonNullElements(Predecessors));
- Contract.Invariant(isCutPoint == (BackEdges.Count != 0));
- }
-
- bool isCutPoint; // is set during ComputeGraphInfo
- public bool IsCutPoint {
- get {
- return isCutPoint;
- }
- }
- [Rep]
- public readonly List<GraphNode/*!*/>/*!*/ ForwardEdges = new List<GraphNode/*!*/>();
- [Rep]
- public readonly List<GraphNode/*!*/>/*!*/ BackEdges = new List<GraphNode/*!*/>();
- [Rep]
- public readonly List<GraphNode/*!*/>/*!*/ Predecessors = new List<GraphNode/*!*/>();
-
- GraphNode(Block b, List<Cmd> body) {
- Contract.Requires(body != null);
- Contract.Requires(b != null);
- this.Block = b;
- this.Body = body;
- }
-
- static List<Cmd> GetOptimizedBody(List<Cmd> cmds) {
- Contract.Requires(cmds != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- int n = 0;
- foreach (Cmd c in cmds) {
- n++;
- PredicateCmd pc = c as PredicateCmd;
- if (pc != null && pc.Expr is LiteralExpr && ((LiteralExpr)pc.Expr).IsFalse) {
- // return a sequence consisting of the commands seen so far
- Cmd[] s = new Cmd[n];
- for (int i = 0; i < n; i++) {
- s[i] = cmds[i];
- }
- return new List<Cmd>(s);
- }
- }
- return cmds;
- }
-
- public static GraphNode ComputeGraphInfo(GraphNode from, Block b, Dictionary<Block/*!*/, GraphNode/*!*/>/*!*/ gd, HashSet<Block> beingVisited) {
- Contract.Requires(beingVisited != null);
- Contract.Requires(b != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(gd));
- Contract.Ensures(Contract.Result<GraphNode>() != null);
- GraphNode g;
- if (gd.TryGetValue(b, out g)) {
- Contract.Assume(from != null);
- Contract.Assert(g != null);
- if (beingVisited.Contains(b)) {
- // it's a cut point
- g.isCutPoint = true;
- from.BackEdges.Add(g);
- g.Predecessors.Add(from);
- } else {
- from.ForwardEdges.Add(g);
- g.Predecessors.Add(from);
- }
-
- } else {
- List<Cmd> body = GetOptimizedBody(b.Cmds);
- g = new GraphNode(b, body);
- gd.Add(b, g);
- if (from != null) {
- from.ForwardEdges.Add(g);
- g.Predecessors.Add(from);
- }
-
- if (body != b.Cmds) {
- // the body was optimized -- there is no way through this block
- } else {
- beingVisited.Add(b);
-
- GotoCmd gcmd = b.TransferCmd as GotoCmd;
- if (gcmd != null) {
- Contract.Assume(gcmd.labelTargets != null);
- foreach (Block/*!*/ succ in gcmd.labelTargets) {
- Contract.Assert(succ != null);
- ComputeGraphInfo(g, succ, gd, beingVisited);
- }
- }
-
- beingVisited.Remove(b);
- }
- }
- return g;
- }
- }
-
- readonly List<Block/*!*/>/*!*/ newBlockSeqGlobal;
- readonly Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>/*!*/ containingSCC;
- readonly int c;
- readonly bool soundLoopUnrolling;
- readonly LoopUnroll next;
- readonly LoopUnroll/*!*/ head;
-
- Dictionary<Block, Block/*!*/>/*!*/ newBlocks = new Dictionary<Block, Block/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(head != null);
- Contract.Invariant(cce.NonNullElements(newBlockSeqGlobal));
- Contract.Invariant(newBlocks != null && cce.NonNullElements(newBlocks.Values));
- }
-
-
- [NotDelayed]
- private LoopUnroll(int unrollMaxDepth, bool soundLoopUnrolling, Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>/*!*/ scc, List<Block/*!*/>/*!*/ newBlockSeqGlobal)
- : base() {
- Contract.Requires(cce.NonNullElements(newBlockSeqGlobal));
- Contract.Requires(cce.NonNullDictionaryAndValues(scc) && Contract.ForAll(scc.Values, v => cce.NonNullElements(v)));
- Contract.Requires(0 <= unrollMaxDepth);
- this.newBlockSeqGlobal = newBlockSeqGlobal;
- this.c = unrollMaxDepth;
- this.containingSCC = scc;
- this.head = this;
- if (unrollMaxDepth != 0) {
- next = new LoopUnroll(unrollMaxDepth - 1, soundLoopUnrolling, scc, newBlockSeqGlobal, this);
- }
- }
-
- private LoopUnroll(int unrollMaxDepth, bool soundLoopUnrolling, Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> scc, List<Block/*!*/>/*!*/ newBlockSeqGlobal, LoopUnroll head) {
- Contract.Requires(head != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(scc));
- Contract.Requires(cce.NonNullElements(newBlockSeqGlobal));
- Contract.Requires(0 <= unrollMaxDepth);
- this.newBlockSeqGlobal = newBlockSeqGlobal;
- this.c = unrollMaxDepth;
- this.soundLoopUnrolling = soundLoopUnrolling;
- this.containingSCC = scc;
- this.head = head;
- if (unrollMaxDepth != 0) {
- next = new LoopUnroll(unrollMaxDepth - 1, soundLoopUnrolling, scc, newBlockSeqGlobal, head);
- }
- }
-
- Block Visit(GraphNode node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Block>() != null);
- Block orig = node.Block;
- Block nw;
- if (newBlocks.TryGetValue(orig, out nw)) {
- Contract.Assert(nw != null);
-
- } else {
- List<Cmd> body;
- TransferCmd tcmd;
- Contract.Assert(orig.TransferCmd != null);
-
- if (next == null && node.IsCutPoint) {
- // as the body, use the assert/assume commands that make up the loop invariant
- body = new List<Cmd>();
- foreach (Cmd/*!*/ c in node.Body) {
- Contract.Assert(c != null);
- if (c is PredicateCmd || c is CommentCmd) {
- body.Add(c);
- } else {
- break;
- }
- }
- if (soundLoopUnrolling) {
- body.Add(new AssertCmd(orig.tok, Bpl.Expr.False));
- } else {
- body.Add(new AssumeCmd(orig.tok, Bpl.Expr.False));
- }
- tcmd = new ReturnCmd(orig.TransferCmd.tok);
-
- } else {
- body = node.Body;
- List<Block> newSuccs = new List<Block>();
-
- foreach (GraphNode succ in node.ForwardEdges) {
- Block s;
- if (containingSCC[node] == containingSCC[succ]) {
- s = Visit(succ);
- } else {
- Contract.Assert(head != null); // follows from object invariant
- s = head.Visit(succ);
- }
- newSuccs.Add(s);
- }
-
- Contract.Assert(next != null || node.BackEdges.Count == 0); // follows from if-else test above and the GraphNode invariant
- foreach (GraphNode succ in node.BackEdges) {
- Contract.Assert(next != null); // since if we get here, node.BackEdges.Count != 0
- Block s = next.Visit(succ);
- newSuccs.Add(s);
- }
-
- if (newSuccs.Count == 0) {
- tcmd = new ReturnCmd(orig.TransferCmd.tok);
- } else {
- tcmd = new GotoCmd(orig.TransferCmd.tok, newSuccs);
- }
- }
-
- nw = new Block(orig.tok, orig.Label + "#" + this.c, body, tcmd);
- newBlocks.Add(orig, nw);
- newBlockSeqGlobal.Add(nw);
- }
-
- return nw;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+using Bpl = Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie {
+ public class LoopUnroll {
+ public static List<Block/*!*/>/*!*/ UnrollLoops(Block start, int unrollMaxDepth, bool soundLoopUnrolling) {
+ Contract.Requires(start != null);
+
+ Contract.Requires(0 <= unrollMaxDepth);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+ Dictionary<Block, GraphNode/*!*/> gd = new Dictionary<Block, GraphNode/*!*/>();
+ HashSet<Block> beingVisited = new HashSet<Block>();
+ GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited);
+
+ // Compute SCCs
+ StronglyConnectedComponents<GraphNode/*!*/> sccs =
+ new StronglyConnectedComponents<GraphNode/*!*/>(gd.Values, Preds, Succs);
+ Contract.Assert(sccs != null);
+ sccs.Compute();
+ Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> containingSCC = new Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>();
+ foreach (SCC<GraphNode/*!*/> scc in sccs) {
+ foreach (GraphNode/*!*/ n in scc) {
+ Contract.Assert(n != null);
+ containingSCC[n] = scc;
+ }
+ }
+
+ LoopUnroll lu = new LoopUnroll(unrollMaxDepth, soundLoopUnrolling, containingSCC, new List<Block/*!*/>());
+ lu.Visit(gStart);
+ lu.newBlockSeqGlobal.Reverse();
+ return lu.newBlockSeqGlobal;
+ }
+
+ // This is supposed to "undo" to effect of loop unrolling
+ // on block labels. It essentially removes the "#num" from the end
+ // of lab, if there is something like this
+ public static string sanitizeLabel(string lab)
+ {
+ if (!lab.Contains("#"))
+ return lab;
+
+ // Find the last occurrance of "#"
+ int pos = lab.LastIndexOf('#');
+
+ return lab.Substring(0, pos);
+ }
+
+ private static System.Collections.IEnumerable/*<GraphNode/*!>/*!*/ Succs(GraphNode n) {
+ Contract.Requires(n != null);
+ Contract.Ensures(Contract.Result<System.Collections.IEnumerable>() != null);
+
+ List<GraphNode/*!*/>/*!*/ AllEdges = new List<GraphNode/*!*/>();
+ AllEdges.AddRange(n.ForwardEdges);
+ AllEdges.AddRange(n.BackEdges);
+ return AllEdges;
+ }
+ private static System.Collections.IEnumerable/*<GraphNode!>*//*!*/ Preds(GraphNode n) {
+ Contract.Requires(n != null);
+ Contract.Ensures(Contract.Result<System.Collections.IEnumerable>() != null);
+
+ return n.Predecessors;
+ }
+
+ class GraphNode {
+ public readonly Block/*!*/ Block;
+ public readonly List<Cmd>/*!*/ Body;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Block != null);
+ Contract.Invariant(Body != null);
+ Contract.Invariant(cce.NonNullElements(ForwardEdges));
+ Contract.Invariant(cce.NonNullElements(BackEdges));
+ Contract.Invariant(cce.NonNullElements(Predecessors));
+ Contract.Invariant(isCutPoint == (BackEdges.Count != 0));
+ }
+
+ bool isCutPoint; // is set during ComputeGraphInfo
+ public bool IsCutPoint {
+ get {
+ return isCutPoint;
+ }
+ }
+ [Rep]
+ public readonly List<GraphNode/*!*/>/*!*/ ForwardEdges = new List<GraphNode/*!*/>();
+ [Rep]
+ public readonly List<GraphNode/*!*/>/*!*/ BackEdges = new List<GraphNode/*!*/>();
+ [Rep]
+ public readonly List<GraphNode/*!*/>/*!*/ Predecessors = new List<GraphNode/*!*/>();
+
+ GraphNode(Block b, List<Cmd> body) {
+ Contract.Requires(body != null);
+ Contract.Requires(b != null);
+ this.Block = b;
+ this.Body = body;
+ }
+
+ static List<Cmd> GetOptimizedBody(List<Cmd> cmds) {
+ Contract.Requires(cmds != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ int n = 0;
+ foreach (Cmd c in cmds) {
+ n++;
+ PredicateCmd pc = c as PredicateCmd;
+ if (pc != null && pc.Expr is LiteralExpr && ((LiteralExpr)pc.Expr).IsFalse) {
+ // return a sequence consisting of the commands seen so far
+ Cmd[] s = new Cmd[n];
+ for (int i = 0; i < n; i++) {
+ s[i] = cmds[i];
+ }
+ return new List<Cmd>(s);
+ }
+ }
+ return cmds;
+ }
+
+ public static GraphNode ComputeGraphInfo(GraphNode from, Block b, Dictionary<Block/*!*/, GraphNode/*!*/>/*!*/ gd, HashSet<Block> beingVisited) {
+ Contract.Requires(beingVisited != null);
+ Contract.Requires(b != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(gd));
+ Contract.Ensures(Contract.Result<GraphNode>() != null);
+ GraphNode g;
+ if (gd.TryGetValue(b, out g)) {
+ Contract.Assume(from != null);
+ Contract.Assert(g != null);
+ if (beingVisited.Contains(b)) {
+ // it's a cut point
+ g.isCutPoint = true;
+ from.BackEdges.Add(g);
+ g.Predecessors.Add(from);
+ } else {
+ from.ForwardEdges.Add(g);
+ g.Predecessors.Add(from);
+ }
+
+ } else {
+ List<Cmd> body = GetOptimizedBody(b.Cmds);
+ g = new GraphNode(b, body);
+ gd.Add(b, g);
+ if (from != null) {
+ from.ForwardEdges.Add(g);
+ g.Predecessors.Add(from);
+ }
+
+ if (body != b.Cmds) {
+ // the body was optimized -- there is no way through this block
+ } else {
+ beingVisited.Add(b);
+
+ GotoCmd gcmd = b.TransferCmd as GotoCmd;
+ if (gcmd != null) {
+ Contract.Assume(gcmd.labelTargets != null);
+ foreach (Block/*!*/ succ in gcmd.labelTargets) {
+ Contract.Assert(succ != null);
+ ComputeGraphInfo(g, succ, gd, beingVisited);
+ }
+ }
+
+ beingVisited.Remove(b);
+ }
+ }
+ return g;
+ }
+ }
+
+ readonly List<Block/*!*/>/*!*/ newBlockSeqGlobal;
+ readonly Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>/*!*/ containingSCC;
+ readonly int c;
+ readonly bool soundLoopUnrolling;
+ readonly LoopUnroll next;
+ readonly LoopUnroll/*!*/ head;
+
+ Dictionary<Block, Block/*!*/>/*!*/ newBlocks = new Dictionary<Block, Block/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(head != null);
+ Contract.Invariant(cce.NonNullElements(newBlockSeqGlobal));
+ Contract.Invariant(newBlocks != null && cce.NonNullElements(newBlocks.Values));
+ }
+
+
+ [NotDelayed]
+ private LoopUnroll(int unrollMaxDepth, bool soundLoopUnrolling, Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>/*!*/ scc, List<Block/*!*/>/*!*/ newBlockSeqGlobal)
+ : base() {
+ Contract.Requires(cce.NonNullElements(newBlockSeqGlobal));
+ Contract.Requires(cce.NonNullDictionaryAndValues(scc) && Contract.ForAll(scc.Values, v => cce.NonNullElements(v)));
+ Contract.Requires(0 <= unrollMaxDepth);
+ this.newBlockSeqGlobal = newBlockSeqGlobal;
+ this.c = unrollMaxDepth;
+ this.containingSCC = scc;
+ this.head = this;
+ if (unrollMaxDepth != 0) {
+ next = new LoopUnroll(unrollMaxDepth - 1, soundLoopUnrolling, scc, newBlockSeqGlobal, this);
+ }
+ }
+
+ private LoopUnroll(int unrollMaxDepth, bool soundLoopUnrolling, Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> scc, List<Block/*!*/>/*!*/ newBlockSeqGlobal, LoopUnroll head) {
+ Contract.Requires(head != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(scc));
+ Contract.Requires(cce.NonNullElements(newBlockSeqGlobal));
+ Contract.Requires(0 <= unrollMaxDepth);
+ this.newBlockSeqGlobal = newBlockSeqGlobal;
+ this.c = unrollMaxDepth;
+ this.soundLoopUnrolling = soundLoopUnrolling;
+ this.containingSCC = scc;
+ this.head = head;
+ if (unrollMaxDepth != 0) {
+ next = new LoopUnroll(unrollMaxDepth - 1, soundLoopUnrolling, scc, newBlockSeqGlobal, head);
+ }
+ }
+
+ Block Visit(GraphNode node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+ Block orig = node.Block;
+ Block nw;
+ if (newBlocks.TryGetValue(orig, out nw)) {
+ Contract.Assert(nw != null);
+
+ } else {
+ List<Cmd> body;
+ TransferCmd tcmd;
+ Contract.Assert(orig.TransferCmd != null);
+
+ if (next == null && node.IsCutPoint) {
+ // as the body, use the assert/assume commands that make up the loop invariant
+ body = new List<Cmd>();
+ foreach (Cmd/*!*/ c in node.Body) {
+ Contract.Assert(c != null);
+ if (c is PredicateCmd || c is CommentCmd) {
+ body.Add(c);
+ } else {
+ break;
+ }
+ }
+ if (soundLoopUnrolling) {
+ body.Add(new AssertCmd(orig.tok, Bpl.Expr.False));
+ } else {
+ body.Add(new AssumeCmd(orig.tok, Bpl.Expr.False));
+ }
+ tcmd = new ReturnCmd(orig.TransferCmd.tok);
+
+ } else {
+ body = node.Body;
+ List<Block> newSuccs = new List<Block>();
+
+ foreach (GraphNode succ in node.ForwardEdges) {
+ Block s;
+ if (containingSCC[node] == containingSCC[succ]) {
+ s = Visit(succ);
+ } else {
+ Contract.Assert(head != null); // follows from object invariant
+ s = head.Visit(succ);
+ }
+ newSuccs.Add(s);
+ }
+
+ Contract.Assert(next != null || node.BackEdges.Count == 0); // follows from if-else test above and the GraphNode invariant
+ foreach (GraphNode succ in node.BackEdges) {
+ Contract.Assert(next != null); // since if we get here, node.BackEdges.Count != 0
+ Block s = next.Visit(succ);
+ newSuccs.Add(s);
+ }
+
+ if (newSuccs.Count == 0) {
+ tcmd = new ReturnCmd(orig.TransferCmd.tok);
+ } else {
+ tcmd = new GotoCmd(orig.TransferCmd.tok, newSuccs);
+ }
+ }
+
+ nw = new Block(orig.tok, orig.Label + "#" + this.c, body, tcmd);
+ newBlocks.Add(orig, nw);
+ newBlockSeqGlobal.Add(nw);
+ }
+
+ return nw;
+ }
+ }
+}
diff --git a/Source/Core/Makefile b/Source/Core/Makefile
index 4d3f433a..2b0cf4e6 100644
--- a/Source/Core/Makefile
+++ b/Source/Core/Makefile
@@ -1,20 +1,20 @@
-COCO = Coco.exe
-
-# ###############################################################################
-# The frame files are no longer in this directory. They must be downloaded
-# from http://boogiepartners.codeplex.com/. Update the FRAME_DIR variable to
-# point to whatever directory you install that into.
-# ###############################################################################
-FRAME_DIR = ..\..\..\boogiepartners\CocoR\Modified
-
-# "all" depends on 2 files, really (Parser.cs and Scanner.cs), but they
-# are both generated in one go and I don't know a better way to tell
-# nmake that. --KRML
-all: Parser.cs
-
-Parser.cs: $(FRAME_DIR)\Scanner.frame $(FRAME_DIR)\Parser.frame BoogiePL.atg
- $(COCO) BoogiePL.atg -namespace Microsoft.Boogie -frames $(FRAME_DIR)
-
-clean:
- if exist Scanner.cs del Scanner.cs
- if exist Parser.cs del Parser.cs
+COCO = Coco.exe
+
+# ###############################################################################
+# The frame files are no longer in this directory. They must be downloaded
+# from https://github.com/boogie-org/boogie-partners . Update the FRAME_DIR variable to
+# point to whatever directory you install that into.
+# ###############################################################################
+FRAME_DIR = ..\..\..\boogiepartners\CocoR\Modified
+
+# "all" depends on 2 files, really (Parser.cs and Scanner.cs), but they
+# are both generated in one go and I don't know a better way to tell
+# nmake that. --KRML
+all: Parser.cs
+
+Parser.cs: $(FRAME_DIR)\Scanner.frame $(FRAME_DIR)\Parser.frame BoogiePL.atg
+ $(COCO) BoogiePL.atg -namespace Microsoft.Boogie -frames $(FRAME_DIR)
+
+clean:
+ if exist Scanner.cs del Scanner.cs
+ if exist Parser.cs del Parser.cs
diff --git a/Source/Core/OOLongUtil.cs b/Source/Core/OOLongUtil.cs
index 0d7bfc35..767b64a1 100644
--- a/Source/Core/OOLongUtil.cs
+++ b/Source/Core/OOLongUtil.cs
@@ -1,210 +1,210 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Diagnostics.Contracts;
-
-namespace Boogie.Util {
- public class TeeWriter : TextWriter {
- readonly TextWriter/*!*/ a;
- readonly TextWriter/*!*/ b;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(a != null);
- Contract.Invariant(b != null);
- }
-
-
- public TeeWriter(TextWriter a, TextWriter b) {
- Contract.Requires(b != null);
- Contract.Requires(a != null);
- this.a = a;
- this.b = b;
- }
-
- public override System.Text.Encoding Encoding {
- get {
- return a.Encoding;
- }
- }
-
- public override void Close() {
- a.Close();
- b.Close();
- }
-
- public override void Flush() {
- a.Flush();
- b.Flush();
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "<TeeWriter: " + a.ToString() + ", " + b.ToString() + ">";
- }
-
- public override void Write(char ch) {
- a.Write(ch);
- b.Write(ch);
- }
-
- public override void Write(string s) {
- a.Write(s);
- b.Write(s);
- }
- }
-
- /// <summary>
- /// A LineReader is a class that allows further subclasses to just override the ReadLine() method.
- /// It simply reads from the given "reader".
- /// </summary>
- public class LineReader : TextReader {
- [Rep]
- readonly TextReader/*!*/ reader;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(reader != null);
- Contract.Invariant(readAhead == null || (0 <= readAheadConsumed && readAheadConsumed < readAhead.Length));
- }
-
- string readAhead;
- int readAheadConsumed;
-
-
- public LineReader([Captured] TextReader reader) {
- Contract.Requires(reader != null);
- this.reader = reader;
- }
- public override void Close() {
- cce.BeginExpose(this);
- {
- reader.Close();
- }
- cce.EndExpose();
- }
- public override int Read() {
- cce.BeginExpose(this);
- try {
- while (readAhead == null) {
- readAhead = reader.ReadLine();
- if (readAhead == null) {
- // we're at EOF
- return -1;
- } else if (readAhead.Length > 0) {
- readAheadConsumed = 0;
- break;
- }
- }
- int res = readAhead[readAheadConsumed++];
- if (readAheadConsumed == readAhead.Length) {
- readAhead = null;
- }
- return res;
- } finally {
- cce.EndExpose();
- }
- }
- public override int Read(char[] buffer, int index, int count) {
-
- int n = 0;
- for (; n < count; n++) {
- int ch = Read();
- if (ch == -1) {
- break;
- }
- buffer[index + n] = (char)ch;
- }
- return n;
- }
- public override string ReadLine() {
- string res;
- if (readAhead != null) {
- cce.BeginExpose(this);
- {
- res = readAhead.Substring(readAheadConsumed);
- readAhead = null;
- }
- cce.EndExpose();
- } else {
- res = reader.ReadLine();
- }
- return res;
- }
- }
-
- public class IfdefReader : LineReader {
- [Rep]
- readonly List<string/*!*/>/*!*/ defines;
- [Rep]
- readonly List<bool>/*!*/ readState = new List<bool>();
- int ignoreCutoff = 0; // 0 means we're not ignoring
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(readState != null);
- Contract.Invariant(cce.NonNullElements(defines));
- Contract.Invariant(0 <= ignoreCutoff && ignoreCutoff <= readState.Count);
- }
-
-
-
- public IfdefReader([Captured] TextReader reader, [Captured] List<string/*!*/>/*!*/ defines)
- : base(reader) {
- Contract.Requires(reader != null);
- Contract.Requires(cce.NonNullElements(defines));
- this.defines = defines;
- }
-
- public override string ReadLine() {
- while (true) {
- string s = base.ReadLine();
- if (s == null) {
- return s;
- }
- string t = s.Trim();
- if (t.StartsWith("#if")) {
- string arg = t.Substring(3).TrimStart();
- bool sense = true;
- while (t.StartsWith("!")) {
- sense = !sense;
- t = t.Substring(1).TrimStart();
- }
- // push "true", since we're in a "then" branch
- readState.Add(true);
- if (ignoreCutoff == 0 && defines.Contains(arg) != sense) {
- ignoreCutoff = readState.Count; // start ignoring
- }
- } else if (t == "#else") {
- if (readState.Count == 0 || !readState[readState.Count - 1]) {
- return s; // malformed input; return the read line as if it were not special
- }
- // change the "true" to a "false" on top of the state, since we're now going into the "else" branch
- readState[readState.Count - 1] = false;
- if (ignoreCutoff == 0) {
- // the "then" branch had been included, so we'll ignore the "else" branch
- ignoreCutoff = readState.Count;
- } else if (ignoreCutoff == readState.Count) {
- // we had ignored the "then" branch, so we'll include the "else" branch
- ignoreCutoff = 0;
- }
- } else if (t == "#endif") {
- if (readState.Count == 0) {
- return s; // malformed input; return the read line as if it were not special
- }
- if (ignoreCutoff == readState.Count) {
- // we had ignored the branch that ends here; so, now we start including again
- ignoreCutoff = 0;
- }
- // pop
- readState.RemoveAt(readState.Count - 1);
- } else if (ignoreCutoff == 0) {
- return s;
- }
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Diagnostics.Contracts;
+
+namespace Boogie.Util {
+ public class TeeWriter : TextWriter {
+ readonly TextWriter/*!*/ a;
+ readonly TextWriter/*!*/ b;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(a != null);
+ Contract.Invariant(b != null);
+ }
+
+
+ public TeeWriter(TextWriter a, TextWriter b) {
+ Contract.Requires(b != null);
+ Contract.Requires(a != null);
+ this.a = a;
+ this.b = b;
+ }
+
+ public override System.Text.Encoding Encoding {
+ get {
+ return a.Encoding;
+ }
+ }
+
+ public override void Close() {
+ a.Close();
+ b.Close();
+ }
+
+ public override void Flush() {
+ a.Flush();
+ b.Flush();
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "<TeeWriter: " + a.ToString() + ", " + b.ToString() + ">";
+ }
+
+ public override void Write(char ch) {
+ a.Write(ch);
+ b.Write(ch);
+ }
+
+ public override void Write(string s) {
+ a.Write(s);
+ b.Write(s);
+ }
+ }
+
+ /// <summary>
+ /// A LineReader is a class that allows further subclasses to just override the ReadLine() method.
+ /// It simply reads from the given "reader".
+ /// </summary>
+ public class LineReader : TextReader {
+ [Rep]
+ readonly TextReader/*!*/ reader;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(reader != null);
+ Contract.Invariant(readAhead == null || (0 <= readAheadConsumed && readAheadConsumed < readAhead.Length));
+ }
+
+ string readAhead;
+ int readAheadConsumed;
+
+
+ public LineReader([Captured] TextReader reader) {
+ Contract.Requires(reader != null);
+ this.reader = reader;
+ }
+ public override void Close() {
+ cce.BeginExpose(this);
+ {
+ reader.Close();
+ }
+ cce.EndExpose();
+ }
+ public override int Read() {
+ cce.BeginExpose(this);
+ try {
+ while (readAhead == null) {
+ readAhead = reader.ReadLine();
+ if (readAhead == null) {
+ // we're at EOF
+ return -1;
+ } else if (readAhead.Length > 0) {
+ readAheadConsumed = 0;
+ break;
+ }
+ }
+ int res = readAhead[readAheadConsumed++];
+ if (readAheadConsumed == readAhead.Length) {
+ readAhead = null;
+ }
+ return res;
+ } finally {
+ cce.EndExpose();
+ }
+ }
+ public override int Read(char[] buffer, int index, int count) {
+
+ int n = 0;
+ for (; n < count; n++) {
+ int ch = Read();
+ if (ch == -1) {
+ break;
+ }
+ buffer[index + n] = (char)ch;
+ }
+ return n;
+ }
+ public override string ReadLine() {
+ string res;
+ if (readAhead != null) {
+ cce.BeginExpose(this);
+ {
+ res = readAhead.Substring(readAheadConsumed);
+ readAhead = null;
+ }
+ cce.EndExpose();
+ } else {
+ res = reader.ReadLine();
+ }
+ return res;
+ }
+ }
+
+ public class IfdefReader : LineReader {
+ [Rep]
+ readonly List<string/*!*/>/*!*/ defines;
+ [Rep]
+ readonly List<bool>/*!*/ readState = new List<bool>();
+ int ignoreCutoff = 0; // 0 means we're not ignoring
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(readState != null);
+ Contract.Invariant(cce.NonNullElements(defines));
+ Contract.Invariant(0 <= ignoreCutoff && ignoreCutoff <= readState.Count);
+ }
+
+
+
+ public IfdefReader([Captured] TextReader reader, [Captured] List<string/*!*/>/*!*/ defines)
+ : base(reader) {
+ Contract.Requires(reader != null);
+ Contract.Requires(cce.NonNullElements(defines));
+ this.defines = defines;
+ }
+
+ public override string ReadLine() {
+ while (true) {
+ string s = base.ReadLine();
+ if (s == null) {
+ return s;
+ }
+ string t = s.Trim();
+ if (t.StartsWith("#if")) {
+ string arg = t.Substring(3).TrimStart();
+ bool sense = true;
+ while (t.StartsWith("!")) {
+ sense = !sense;
+ t = t.Substring(1).TrimStart();
+ }
+ // push "true", since we're in a "then" branch
+ readState.Add(true);
+ if (ignoreCutoff == 0 && defines.Contains(arg) != sense) {
+ ignoreCutoff = readState.Count; // start ignoring
+ }
+ } else if (t == "#else") {
+ if (readState.Count == 0 || !readState[readState.Count - 1]) {
+ return s; // malformed input; return the read line as if it were not special
+ }
+ // change the "true" to a "false" on top of the state, since we're now going into the "else" branch
+ readState[readState.Count - 1] = false;
+ if (ignoreCutoff == 0) {
+ // the "then" branch had been included, so we'll ignore the "else" branch
+ ignoreCutoff = readState.Count;
+ } else if (ignoreCutoff == readState.Count) {
+ // we had ignored the "then" branch, so we'll include the "else" branch
+ ignoreCutoff = 0;
+ }
+ } else if (t == "#endif") {
+ if (readState.Count == 0) {
+ return s; // malformed input; return the read line as if it were not special
+ }
+ if (ignoreCutoff == readState.Count) {
+ // we had ignored the branch that ends here; so, now we start including again
+ ignoreCutoff = 0;
+ }
+ // pop
+ readState.RemoveAt(readState.Count - 1);
+ } else if (ignoreCutoff == 0) {
+ return s;
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs
index 7982f594..1f8d17d6 100644
--- a/Source/Core/Parser.cs
+++ b/Source/Core/Parser.cs
@@ -1,2425 +1,2425 @@
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using Bpl = Microsoft.Boogie;
-
-
-
-
-using System;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie {
-
-
-
-public class Parser {
- public const int _EOF = 0;
- public const int _ident = 1;
- public const int _bvlit = 2;
- public const int _digits = 3;
- public const int _string = 4;
- public const int _decimal = 5;
- public const int _float = 6;
- public const int _fp = 97;
- public const int maxT = 98;
-
- const bool T = true;
- const bool x = false;
- const int minErrDist = 2;
-
- public Scanner/*!*/ scanner;
- public Errors/*!*/ errors;
-
- public Token/*!*/ t; // last recognized token
- public Token/*!*/ la; // lookahead token
- int errDist = minErrDist;
-
-readonly Program/*!*/ Pgm;
-
-readonly Expr/*!*/ dummyExpr;
-readonly Cmd/*!*/ dummyCmd;
-readonly Block/*!*/ dummyBlock;
-readonly Bpl.Type/*!*/ dummyType;
-readonly List<Expr>/*!*/ dummyExprSeq;
-readonly TransferCmd/*!*/ dummyTransferCmd;
-readonly StructuredCmd/*!*/ dummyStructuredCmd;
-
-///<summary>
-///Returns the number of parsing errors encountered. If 0, "program" returns as
-///the parsed program.
-///</summary>
-public static int Parse (string/*!*/ filename, /*maybe null*/ List<string/*!*/> defines, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
- Contract.Requires(filename != null);
- Contract.Requires(cce.NonNullElements(defines,true));
-
- if (defines == null) {
- defines = new List<string/*!*/>();
- }
-
- if (filename == "stdin.bpl") {
- var s = ParserHelper.Fill(Console.In, defines);
- return Parse(s, filename, out program, useBaseName);
- } else {
- FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
- var s = ParserHelper.Fill(stream, defines);
- var ret = Parse(s, filename, out program, useBaseName);
- stream.Close();
- return ret;
- }
-}
-
-
-public static int Parse (string s, string/*!*/ filename, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
- Contract.Requires(s != null);
- Contract.Requires(filename != null);
-
- byte[]/*!*/ buffer = cce.NonNull(UTF8Encoding.Default.GetBytes(s));
- MemoryStream ms = new MemoryStream(buffer,false);
- Errors errors = new Errors();
- Scanner scanner = new Scanner(ms, errors, filename, useBaseName);
-
- Parser parser = new Parser(scanner, errors, false);
- parser.Parse();
- if (parser.errors.count == 0)
- {
- program = parser.Pgm;
- program.ProcessDatatypeConstructors();
- return 0;
- }
- else
- {
- program = null;
- return parser.errors.count;
- }
-}
-
-public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, bool disambiguation)
- : this(scanner, errors)
-{
- // initialize readonly fields
- Pgm = new Program();
- dummyExpr = new LiteralExpr(Token.NoToken, false);
- dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
- dummyBlock = new Block(Token.NoToken, "dummyBlock", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
- dummyExprSeq = new List<Expr> ();
- dummyTransferCmd = new ReturnCmd(Token.NoToken);
- dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
-}
-
-// Class to represent the bounds of a bitvector expression t[a:b].
-// Objects of this class only exist during parsing and are directly
-// turned into BvExtract before they get anywhere else
-private class BvBounds : Expr {
- public BigNum Lower;
- public BigNum Upper;
- public BvBounds(IToken/*!*/ tok, BigNum lower, BigNum upper)
- : base(tok, /*immutable=*/ false) {
- Contract.Requires(tok != null);
- this.Lower = lower;
- this.Upper = upper;
- }
- public override Bpl.Type/*!*/ ShallowType { get {Contract.Ensures(Contract.Result<Bpl.Type>() != null); return Bpl.Type.Int; } }
- public override void Resolve(ResolutionContext/*!*/ rc) {
- // Contract.Requires(rc != null);
- rc.Error(this, "bitvector bounds in illegal position");
- }
- public override void Emit(TokenTextWriter/*!*/ stream,
- int contextBindingStrength, bool fragileContext) {
- Contract.Assert(false);throw new cce.UnreachableException();
- }
- public override void ComputeFreeVariables(GSet<object>/*!*/ freeVars) { Contract.Assert(false);throw new cce.UnreachableException(); }
- public override int ComputeHashCode() {
- return base.GetHashCode();
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-
- public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors) {
- this.scanner = scanner;
- this.errors = errors;
- Token/*!*/ tok = new Token();
- tok.val = "";
- this.la = tok;
- this.t = new Token(); // just to satisfy its non-null constraint
- }
-
- void SynErr (int n) {
- if (errDist >= minErrDist) errors.SynErr(la.filename, la.line, la.col, n);
- errDist = 0;
- }
-
- public void SemErr (string/*!*/ msg) {
- Contract.Requires(msg != null);
- if (errDist >= minErrDist) errors.SemErr(t, msg);
- errDist = 0;
- }
-
- public void SemErr(IToken/*!*/ tok, string/*!*/ msg) {
- Contract.Requires(tok != null);
- Contract.Requires(msg != null);
- errors.SemErr(tok, msg);
- }
-
- void Get () {
- for (;;) {
- t = la;
- la = scanner.Scan();
- if (la.kind <= maxT) { ++errDist; break; }
-
- la = t;
- }
- }
-
- void Expect (int n) {
- if (la.kind==n) Get(); else { SynErr(n); }
- }
-
- bool StartOf (int s) {
- return set[s, la.kind];
- }
-
- void ExpectWeak (int n, int follow) {
- if (la.kind == n) Get();
- else {
- SynErr(n);
- while (!StartOf(follow)) Get();
- }
- }
-
-
- bool WeakSeparator(int n, int syFol, int repFol) {
- int kind = la.kind;
- if (kind == n) {Get(); return true;}
- else if (StartOf(repFol)) {return false;}
- else {
- SynErr(n);
- while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
- Get();
- kind = la.kind;
- }
- return StartOf(syFol);
- }
- }
-
-
- void BoogiePL() {
- List<Variable>/*!*/ vs;
- List<Declaration>/*!*/ ds;
- Axiom/*!*/ ax;
- List<Declaration/*!*/>/*!*/ ts;
- Procedure/*!*/ pr;
- Implementation im;
- Implementation/*!*/ nnim;
-
- while (StartOf(1)) {
- switch (la.kind) {
- case 21: {
- Consts(out vs);
- foreach(Bpl.Variable/*!*/ v in vs){
- Contract.Assert(v != null);
- Pgm.AddTopLevelDeclaration(v);
- }
-
- break;
- }
- case 25: {
- Function(out ds);
- foreach(Bpl.Declaration/*!*/ d in ds){
- Contract.Assert(d != null);
- Pgm.AddTopLevelDeclaration(d);
- }
-
- break;
- }
- case 29: {
- Axiom(out ax);
- Pgm.AddTopLevelDeclaration(ax);
- break;
- }
- case 30: {
- UserDefinedTypes(out ts);
- foreach(Declaration/*!*/ td in ts){
- Contract.Assert(td != null);
- Pgm.AddTopLevelDeclaration(td);
- }
-
- break;
- }
- case 7: {
- GlobalVars(out vs);
- foreach(Bpl.Variable/*!*/ v in vs){
- Contract.Assert(v != null);
- Pgm.AddTopLevelDeclaration(v);
- }
-
- break;
- }
- case 32: {
- Procedure(out pr, out im);
- Pgm.AddTopLevelDeclaration(pr);
- if (im != null) {
- Pgm.AddTopLevelDeclaration(im);
- }
-
- break;
- }
- case 33: {
- Implementation(out nnim);
- Pgm.AddTopLevelDeclaration(nnim);
- break;
- }
- }
- }
- Expect(0);
- }
-
- void Consts(out List<Variable>/*!*/ ds) {
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null); IToken/*!*/ y; List<TypedIdent>/*!*/ xs;
- ds = new List<Variable>();
- bool u = false; QKeyValue kv = null;
- bool ChildrenComplete = false;
- List<ConstantParent/*!*/> Parents = null;
- Expect(21);
- y = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- if (la.kind == 22) {
- Get();
- u = true;
- }
- IdsType(out xs);
- if (la.kind == 23) {
- OrderSpec(out ChildrenComplete, out Parents);
- }
- bool makeClone = false;
- foreach(TypedIdent/*!*/ x in xs){
- Contract.Assert(x != null);
-
- // ensure that no sharing is introduced
- List<ConstantParent/*!*/> ParentsClone;
- if (makeClone && Parents != null) {
- ParentsClone = new List<ConstantParent/*!*/> ();
- foreach (ConstantParent/*!*/ p in Parents){
- Contract.Assert(p != null);
- ParentsClone.Add(new ConstantParent (
- new IdentifierExpr (p.Parent.tok, p.Parent.Name),
- p.Unique));}
- } else {
- ParentsClone = Parents;
- }
- makeClone = true;
-
- ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
- }
-
- Expect(8);
- }
-
- void Function(out List<Declaration>/*!*/ ds) {
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- ds = new List<Declaration>(); IToken/*!*/ z;
- IToken/*!*/ typeParamTok;
- var typeParams = new List<TypeVariable>();
- var arguments = new List<Variable>();
- TypedIdent/*!*/ tyd;
- TypedIdent retTyd = null;
- Bpl.Type/*!*/ retTy;
- QKeyValue argKv = null;
- QKeyValue kv = null;
- Expr definition = null;
- Expr/*!*/ tmp;
-
- Expect(25);
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Ident(out z);
- if (la.kind == 19) {
- TypeParams(out typeParamTok, out typeParams);
- }
- Expect(9);
- if (StartOf(2)) {
- VarOrType(out tyd, out argKv);
- arguments.Add(new Formal(tyd.tok, tyd, true, argKv));
- while (la.kind == 12) {
- Get();
- VarOrType(out tyd, out argKv);
- arguments.Add(new Formal(tyd.tok, tyd, true, argKv));
- }
- }
- Expect(10);
- argKv = null;
- if (la.kind == 26) {
- Get();
- Expect(9);
- VarOrType(out retTyd, out argKv);
- Expect(10);
- } else if (la.kind == 11) {
- Get();
- Type(out retTy);
- retTyd = new TypedIdent(retTy.tok, TypedIdent.NoName, retTy);
- } else SynErr(99);
- if (la.kind == 27) {
- Get();
- Expression(out tmp);
- definition = tmp;
- Expect(28);
- } else if (la.kind == 8) {
- Get();
- } else SynErr(100);
- if (retTyd == null) {
- // construct a dummy type for the case of syntax error
- retTyd = new TypedIdent(t, TypedIdent.NoName, new BasicType(t, SimpleType.Int));
- }
- Function/*!*/ func = new Function(z, z.val, typeParams, arguments,
- new Formal(retTyd.tok, retTyd, false, argKv), null, kv);
- Contract.Assert(func != null);
- ds.Add(func);
- bool allUnnamed = true;
- foreach(Formal/*!*/ f in arguments){
- Contract.Assert(f != null);
- if (f.TypedIdent.HasName) {
- allUnnamed = false;
- break;
- }
- }
- if (!allUnnamed) {
- Bpl.Type prevType = null;
- for (int i = arguments.Count; 0 <= --i; ) {
- TypedIdent/*!*/ curr = cce.NonNull(arguments[i]).TypedIdent;
- if (curr.HasName) {
- // the argument was given as both an identifier and a type
- prevType = curr.Type;
- } else {
- // the argument was given as just one "thing", which syntactically parsed as a type
- if (prevType == null) {
- this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
- break;
- }
- Bpl.Type ty = curr.Type;
- var uti = ty as UnresolvedTypeIdentifier;
- if (uti != null && uti.Arguments.Count == 0) {
- // the given "thing" was just an identifier, so let's use it as the name of the parameter
- curr.Name = uti.Name;
- curr.Type = prevType;
- } else {
- this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
- }
- }
- }
- }
- if (definition != null) {
- // generate either an axiom or a function body
- if (QKeyValue.FindBoolAttribute(kv, "inline")) {
- func.Body = definition;
- } else {
- ds.Add(func.CreateDefinitionAxiom(definition, kv));
- }
- }
-
- }
-
- void Axiom(out Axiom/*!*/ m) {
- Contract.Ensures(Contract.ValueAtReturn(out m) != null); Expr/*!*/ e; QKeyValue kv = null;
- Expect(29);
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- IToken/*!*/ x = t;
- Proposition(out e);
- Expect(8);
- m = new Axiom(x,e, null, kv);
- }
-
- void UserDefinedTypes(out List<Declaration/*!*/>/*!*/ ts) {
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out ts))); Declaration/*!*/ decl; QKeyValue kv = null; ts = new List<Declaration/*!*/> ();
- Expect(30);
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- UserDefinedType(out decl, kv);
- ts.Add(decl);
- while (la.kind == 12) {
- Get();
- UserDefinedType(out decl, kv);
- ts.Add(decl);
- }
- Expect(8);
- }
-
- void GlobalVars(out List<Variable>/*!*/ ds) {
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- QKeyValue kv = null;
- ds = new List<Variable>();
- var dsx = ds;
-
- Expect(7);
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- IdsTypeWheres(true, "global variables", delegate(TypedIdent tyd) { dsx.Add(new GlobalVariable(tyd.tok, tyd, kv)); } );
- Expect(8);
- }
-
- void Procedure(out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl) {
- Contract.Ensures(Contract.ValueAtReturn(out proc) != null); IToken/*!*/ x;
- List<TypeVariable>/*!*/ typeParams;
- List<Variable>/*!*/ ins, outs;
- List<Requires>/*!*/ pre = new List<Requires>();
- List<IdentifierExpr>/*!*/ mods = new List<IdentifierExpr>();
- List<Ensures>/*!*/ post = new List<Ensures>();
-
- List<Variable>/*!*/ locals = new List<Variable>();
- StmtList/*!*/ stmtList;
- QKeyValue kv = null;
- impl = null;
-
- Expect(32);
- ProcSignature(true, out x, out typeParams, out ins, out outs, out kv);
- if (la.kind == 8) {
- Get();
- while (StartOf(3)) {
- Spec(pre, mods, post);
- }
- } else if (StartOf(4)) {
- while (StartOf(3)) {
- Spec(pre, mods, post);
- }
- ImplBody(out locals, out stmtList);
- impl = new Implementation(x, x.val, typeParams,
- Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors);
-
- } else SynErr(99);
- proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv);
- }
-
- void Implementation(out Implementation/*!*/ impl) {
- Contract.Ensures(Contract.ValueAtReturn(out impl) != null); IToken/*!*/ x;
- List<TypeVariable>/*!*/ typeParams;
- List<Variable>/*!*/ ins, outs;
- List<Variable>/*!*/ locals;
- StmtList/*!*/ stmtList;
- QKeyValue kv;
-
- Expect(33);
- ProcSignature(false, out x, out typeParams, out ins, out outs, out kv);
- ImplBody(out locals, out stmtList);
- impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors);
- }
-
- void Attribute(ref QKeyValue kv) {
- Trigger trig = null;
- AttributeOrTrigger(ref kv, ref trig);
- if (trig != null) this.SemErr("only attributes, not triggers, allowed here");
- }
-
- void IdsTypeWheres(bool allowWhereClauses, string context, System.Action<TypedIdent> action ) {
- IdsTypeWhere(allowWhereClauses, context, action);
- while (la.kind == 12) {
- Get();
- IdsTypeWhere(allowWhereClauses, context, action);
- }
- }
-
- void LocalVars(List<Variable>/*!*/ ds) {
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- QKeyValue kv = null;
-
- Expect(7);
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- IdsTypeWheres(true, "local variables", delegate(TypedIdent tyd) { ds.Add(new LocalVariable(tyd.tok, tyd, kv)); } );
- Expect(8);
- }
-
- void ProcFormals(bool incoming, bool allowWhereClauses, out List<Variable>/*!*/ ds) {
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- ds = new List<Variable>();
- var dsx = ds;
- var context = allowWhereClauses ? "procedure formals" : "the 'implementation' copies of formals";
-
- Expect(9);
- if (la.kind == 1 || la.kind == 27) {
- AttrsIdsTypeWheres(allowWhereClauses, allowWhereClauses, context, delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new Formal(tyd.tok, tyd, incoming, kv)); });
- }
- Expect(10);
- }
-
- void AttrsIdsTypeWheres(bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action ) {
- AttributesIdsTypeWhere(allowAttributes, allowWhereClauses, context, action);
- while (la.kind == 12) {
- Get();
- AttributesIdsTypeWhere(allowAttributes, allowWhereClauses, context, action);
- }
- }
-
- void BoundVars(IToken/*!*/ x, out List<Variable>/*!*/ ds) {
- Contract.Requires(x != null);
- Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
- List<TypedIdent>/*!*/ tyds = new List<TypedIdent>();
- ds = new List<Variable>();
- var dsx = ds;
-
- AttrsIdsTypeWheres(true, false, "bound variables", delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new BoundVariable(tyd.tok, tyd, kv)); } );
- }
-
- void IdsType(out List<TypedIdent>/*!*/ tyds) {
- Contract.Ensures(Contract.ValueAtReturn(out tyds) != null); List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty;
- Idents(out ids);
- Expect(11);
- Type(out ty);
- tyds = new List<TypedIdent>();
- foreach(Token/*!*/ id in ids){
- Contract.Assert(id != null);
- tyds.Add(new TypedIdent(id, id.val, ty, null));
- }
-
- }
-
- void Idents(out List<IToken>/*!*/ xs) {
- Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>();
- Ident(out id);
- xs.Add(id);
- while (la.kind == 12) {
- Get();
- Ident(out id);
- xs.Add(id);
- }
- }
-
- void Type(out Bpl.Type/*!*/ ty) {
- Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; ty = dummyType;
- if (StartOf(5)) {
- TypeAtom(out ty);
- } else if (la.kind == 1) {
- Ident(out tok);
- List<Bpl.Type>/*!*/ args = new List<Bpl.Type> ();
- if (StartOf(6)) {
- TypeArgs(args);
- }
- ty = new UnresolvedTypeIdentifier (tok, tok.val, args);
- } else if (la.kind == 17 || la.kind == 19) {
- MapType(out ty);
- } else SynErr(100);
- }
-
- void AttributesIdsTypeWhere(bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action ) {
- QKeyValue kv = null;
- while (la.kind == 27) {
- Attribute(ref kv);
- if (!allowAttributes) {
- kv = null;
- this.SemErr("attributes are not allowed on " + context);
- }
-
- }
- IdsTypeWhere(allowWhereClauses, context, delegate(TypedIdent tyd) { action(tyd, kv); });
- }
-
- void IdsTypeWhere(bool allowWhereClauses, string context, System.Action<TypedIdent> action ) {
- List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty; Expr wh = null; Expr/*!*/ nne;
- Idents(out ids);
- Expect(11);
- Type(out ty);
- if (la.kind == 13) {
- Get();
- Expression(out nne);
- if (!allowWhereClauses) {
- this.SemErr("where clause not allowed on " + context);
- } else {
- wh = nne;
- }
-
- }
- foreach(Token/*!*/ id in ids){
- Contract.Assert(id != null);
- action(new TypedIdent(id, id.val, ty, wh));
- }
-
- }
-
- void Expression(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
- ImpliesExpression(false, out e0);
- while (la.kind == 55 || la.kind == 56) {
- EquivOp();
- x = t;
- ImpliesExpression(false, out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1);
- }
- }
-
- void TypeAtom(out Bpl.Type/*!*/ ty) {
- Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType;
- if (la.kind == 14) {
- Get();
- ty = new BasicType(t, SimpleType.Int);
- } else if (la.kind == 15) {
- Get();
- ty = new BasicType(t, SimpleType.Real);
- } else if (la.kind == 98) {
- Get();
- ty = FType();
- } else if (la.kind == 16) {
- Get();
- ty = new BasicType(t, SimpleType.Bool);
- } else if (la.kind == 9) {
- Get();
- Type(out ty);
- Expect(10);
- } else SynErr(101);
- }
-
- FloatType FType() {
- if (t.val.Length > 5) {
- switch (Int32.Parse(t.val.Substring(5))) {
- case 16:
- return new FloatType(t, 5, 11);
- case 32:
- return new FloatType(t, 8, 24);
- case 64:
- return new FloatType(t, 11, 53);
- case 128:
- return new FloatType(t, 15, 113);
- default:
- SynErr(3);
- return new FloatType(t, 0, 0);
- }
- }
- else {
- try {
- Expect(19); //<
- Expect(3); //int
- int exp = Int32.Parse(t.val);
- Expect(12); //,
- Expect(3); //int
- int man = Int32.Parse(t.val);
- Expect(20); //>
- return new FloatType(t, exp, man);
- }
- catch (Exception) {
- return new FloatType(t, 0, 0);
- }
- }
- }
-
- void Ident(out IToken/*!*/ x) {
- Contract.Ensures(Contract.ValueAtReturn(out x) != null);
- Expect(1);
- x = t;
- if (x.val.StartsWith("\\"))
- x.val = x.val.Substring(1);
-
- }
-
- void TypeArgs(List<Bpl.Type>/*!*/ ts) {
- Contract.Requires(ts != null); IToken/*!*/ tok; Bpl.Type/*!*/ ty;
- if (StartOf(5)) {
- TypeAtom(out ty);
- ts.Add(ty);
- if (StartOf(6)) {
- TypeArgs(ts);
- }
- } else if (la.kind == 1) {
- Ident(out tok);
- List<Bpl.Type>/*!*/ args = new List<Bpl.Type> ();
- ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args));
- if (StartOf(6)) {
- TypeArgs(ts);
- }
- } else if (la.kind == 17 || la.kind == 19) {
- MapType(out ty);
- ts.Add(ty);
- } else SynErr(102);
- }
-
- void MapType(out Bpl.Type/*!*/ ty) {
- Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken tok = null;
- IToken/*!*/ nnTok;
- List<Bpl.Type>/*!*/ arguments = new List<Bpl.Type>();
- Bpl.Type/*!*/ result;
- List<TypeVariable>/*!*/ typeParameters = new List<TypeVariable>();
-
- if (la.kind == 19) {
- TypeParams(out nnTok, out typeParameters);
- tok = nnTok;
- }
- Expect(17);
- if (tok == null) tok = t;
- if (StartOf(6)) {
- Types(arguments);
- }
- Expect(18);
- Type(out result);
- ty = new MapType(tok, typeParameters, arguments, result);
-
- }
-
- void TypeParams(out IToken/*!*/ tok, out List<TypeVariable>/*!*/ typeParams) {
- Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); List<IToken>/*!*/ typeParamToks;
- Expect(19);
- tok = t;
- Idents(out typeParamToks);
- Expect(20);
- typeParams = new List<TypeVariable> ();
- foreach(Token/*!*/ id in typeParamToks){
- Contract.Assert(id != null);
- typeParams.Add(new TypeVariable(id, id.val));}
-
- }
-
- void Types(List<Bpl.Type>/*!*/ ts) {
- Contract.Requires(ts != null); Bpl.Type/*!*/ ty;
- Type(out ty);
- ts.Add(ty);
- while (la.kind == 12) {
- Get();
- Type(out ty);
- ts.Add(ty);
- }
- }
-
- void OrderSpec(out bool ChildrenComplete, out List<ConstantParent/*!*/> Parents) {
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out Parents),true)); ChildrenComplete = false;
- Parents = null;
- bool u;
- IToken/*!*/ parent;
- Expect(23);
- Parents = new List<ConstantParent/*!*/> ();
- u = false;
- if (la.kind == 1 || la.kind == 22) {
- if (la.kind == 22) {
- Get();
- u = true;
- }
- Ident(out parent);
- Parents.Add(new ConstantParent (
- new IdentifierExpr(parent, parent.val), u));
- while (la.kind == 12) {
- Get();
- u = false;
- if (la.kind == 22) {
- Get();
- u = true;
- }
- Ident(out parent);
- Parents.Add(new ConstantParent (
- new IdentifierExpr(parent, parent.val), u));
- }
- }
- if (la.kind == 24) {
- Get();
- ChildrenComplete = true;
- }
- }
-
- void VarOrType(out TypedIdent/*!*/ tyd, out QKeyValue kv) {
- Contract.Ensures(Contract.ValueAtReturn(out tyd) != null);
- string/*!*/ varName = TypedIdent.NoName;
- Bpl.Type/*!*/ ty;
- IToken/*!*/ tok;
- kv = null;
-
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Type(out ty);
- tok = ty.tok;
- if (la.kind == 11) {
- Get();
- var uti = ty as UnresolvedTypeIdentifier;
- if (uti != null && uti.Arguments.Count == 0) {
- varName = uti.Name;
- } else {
- this.SemErr("expected identifier before ':'");
- }
-
- Type(out ty);
- }
- tyd = new TypedIdent(tok, varName, ty);
- }
-
- void Proposition(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null);
- Expression(out e);
- }
-
- void UserDefinedType(out Declaration/*!*/ decl, QKeyValue kv) {
- Contract.Ensures(Contract.ValueAtReturn(out decl) != null); IToken/*!*/ id; List<IToken>/*!*/ paramTokens = new List<IToken> ();
- Bpl.Type/*!*/ body = dummyType; bool synonym = false;
- Ident(out id);
- if (la.kind == 1) {
- WhiteSpaceIdents(out paramTokens);
- }
- if (la.kind == 31) {
- Get();
- Type(out body);
- synonym = true;
- }
- if (synonym) {
- List<TypeVariable>/*!*/ typeParams = new List<TypeVariable>();
- foreach(Token/*!*/ t in paramTokens){
- Contract.Assert(t != null);
- typeParams.Add(new TypeVariable(t, t.val));}
- decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
- } else {
- decl = new TypeCtorDecl(id, id.val, paramTokens.Count, kv);
- }
-
- }
-
- void WhiteSpaceIdents(out List<IToken>/*!*/ xs) {
- Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>();
- Ident(out id);
- xs.Add(id);
- while (la.kind == 1) {
- Ident(out id);
- xs.Add(id);
- }
- }
-
- void ProcSignature(bool allowWhereClausesOnFormals, out IToken/*!*/ name, out List<TypeVariable>/*!*/ typeParams,
-out List<Variable>/*!*/ ins, out List<Variable>/*!*/ outs, out QKeyValue kv) {
- Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null);
- IToken/*!*/ typeParamTok; typeParams = new List<TypeVariable>();
- outs = new List<Variable>(); kv = null;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Ident(out name);
- if (la.kind == 19) {
- TypeParams(out typeParamTok, out typeParams);
- }
- ProcFormals(true, allowWhereClausesOnFormals, out ins);
- if (la.kind == 26) {
- Get();
- ProcFormals(false, allowWhereClausesOnFormals, out outs);
- }
- }
-
- void Spec(List<Requires>/*!*/ pre, List<IdentifierExpr>/*!*/ mods, List<Ensures>/*!*/ post) {
- Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); List<IToken>/*!*/ ms;
- if (la.kind == 34) {
- Get();
- if (la.kind == 1) {
- Idents(out ms);
- foreach(IToken/*!*/ m in ms){
- Contract.Assert(m != null);
- mods.Add(new IdentifierExpr(m, m.val));
- }
-
- }
- Expect(8);
- } else if (la.kind == 35) {
- Get();
- SpecPrePost(true, pre, post);
- } else if (la.kind == 36 || la.kind == 37) {
- SpecPrePost(false, pre, post);
- } else SynErr(103);
- }
-
- void ImplBody(out List<Variable>/*!*/ locals, out StmtList/*!*/ stmtList) {
- Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List<Variable>();
- Expect(27);
- while (la.kind == 7) {
- LocalVars(locals);
- }
- StmtList(out stmtList);
- }
-
- void SpecPrePost(bool free, List<Requires>/*!*/ pre, List<Ensures>/*!*/ post) {
- Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null;
- if (la.kind == 36) {
- Get();
- tok = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Proposition(out e);
- Expect(8);
- pre.Add(new Requires(tok, free, e, null, kv));
- } else if (la.kind == 37) {
- Get();
- tok = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Proposition(out e);
- Expect(8);
- post.Add(new Ensures(tok, free, e, null, kv));
- } else SynErr(104);
- }
-
- void StmtList(out StmtList/*!*/ stmtList) {
- Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List<BigBlock/*!*/> bigblocks = new List<BigBlock/*!*/>();
- /* built-up state for the current BigBlock: */
- IToken startToken = null; string currentLabel = null;
- List<Cmd> cs = null; /* invariant: startToken != null ==> cs != null */
- /* temporary variables: */
- IToken label; Cmd c; BigBlock b;
- StructuredCmd ec = null; StructuredCmd/*!*/ ecn;
- TransferCmd tc = null; TransferCmd/*!*/ tcn;
-
- while (StartOf(7)) {
- if (StartOf(8)) {
- LabelOrCmd(out c, out label);
- if (c != null) {
- // LabelOrCmd read a Cmd
- Contract.Assert(label == null);
- if (startToken == null) { startToken = c.tok; cs = new List<Cmd>(); }
- Contract.Assert(cs != null);
- cs.Add(c);
- } else {
- // LabelOrCmd read a label
- Contract.Assert(label != null);
- if (startToken != null) {
- Contract.Assert(cs != null);
- // dump the built-up state into a BigBlock
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- cs = null;
- }
- startToken = label;
- currentLabel = label.val;
- cs = new List<Cmd>();
- }
-
- } else if (la.kind == 40 || la.kind == 42 || la.kind == 45) {
- StructuredCmd(out ecn);
- ec = ecn;
- if (startToken == null) { startToken = ec.tok; cs = new List<Cmd>(); }
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, ec, null);
- bigblocks.Add(b);
- startToken = null; currentLabel = null; cs = null;
-
- } else {
- TransferCmd(out tcn);
- tc = tcn;
- if (startToken == null) { startToken = tc.tok; cs = new List<Cmd>(); }
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, null, tc);
- bigblocks.Add(b);
- startToken = null; currentLabel = null; cs = null;
-
- }
- }
- Expect(28);
- IToken/*!*/ endCurly = t;
- if (startToken == null && bigblocks.Count == 0) {
- startToken = t; cs = new List<Cmd>();
- }
- if (startToken != null) {
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- }
-
- stmtList = new StmtList(bigblocks, endCurly);
-
- }
-
- void LabelOrCmd(out Cmd c, out IToken label) {
- IToken/*!*/ x; Expr/*!*/ e;
- List<IToken>/*!*/ xs;
- List<IdentifierExpr> ids;
- c = dummyCmd; label = null;
- Cmd/*!*/ cn;
- QKeyValue kv = null;
-
- switch (la.kind) {
- case 1: {
- LabelOrAssign(out c, out label);
- break;
- }
- case 46: {
- Get();
- x = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Proposition(out e);
- c = new AssertCmd(x, e, kv);
- Expect(8);
- break;
- }
- case 47: {
- Get();
- x = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Proposition(out e);
- c = new AssumeCmd(x, e, kv);
- Expect(8);
- break;
- }
- case 48: {
- Get();
- x = t;
- Idents(out xs);
- Expect(8);
- ids = new List<IdentifierExpr>();
- foreach(IToken/*!*/ y in xs){
- Contract.Assert(y != null);
- ids.Add(new IdentifierExpr(y, y.val));
- }
- c = new HavocCmd(x,ids);
-
- break;
- }
- case 35: case 51: case 52: {
- CallCmd(out cn);
- Expect(8);
- c = cn;
- break;
- }
- case 53: {
- ParCallCmd(out cn);
- c = cn;
- break;
- }
- case 49: {
- Get();
- x = t;
- Expect(8);
- c = new YieldCmd(x);
- break;
- }
- default: SynErr(105); break;
- }
- }
-
- void StructuredCmd(out StructuredCmd/*!*/ ec) {
- Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec));
- IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd;
-
- if (la.kind == 40) {
- IfCmd(out ifcmd);
- ec = ifcmd;
- } else if (la.kind == 42) {
- WhileCmd(out wcmd);
- ec = wcmd;
- } else if (la.kind == 45) {
- BreakCmd(out bcmd);
- ec = bcmd;
- } else SynErr(106);
- }
-
- void TransferCmd(out TransferCmd/*!*/ tc) {
- Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
- Token y; List<IToken>/*!*/ xs;
- List<String> ss = new List<String>();
-
- if (la.kind == 38) {
- Get();
- y = t;
- Idents(out xs);
- foreach(IToken/*!*/ s in xs){
- Contract.Assert(s != null);
- ss.Add(s.val); }
- tc = new GotoCmd(y, ss);
-
- } else if (la.kind == 39) {
- Get();
- tc = new ReturnCmd(t);
- } else SynErr(107);
- Expect(8);
- }
-
- void IfCmd(out IfCmd/*!*/ ifcmd) {
- Contract.Ensures(Contract.ValueAtReturn(out ifcmd) != null); IToken/*!*/ x;
- Expr guard;
- StmtList/*!*/ thn;
- IfCmd/*!*/ elseIf; IfCmd elseIfOption = null;
- StmtList/*!*/ els; StmtList elseOption = null;
-
- Expect(40);
- x = t;
- Guard(out guard);
- Expect(27);
- StmtList(out thn);
- if (la.kind == 41) {
- Get();
- if (la.kind == 40) {
- IfCmd(out elseIf);
- elseIfOption = elseIf;
- } else if (la.kind == 27) {
- Get();
- StmtList(out els);
- elseOption = els;
- } else SynErr(108);
- }
- ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption);
- }
-
- void WhileCmd(out WhileCmd/*!*/ wcmd) {
- Contract.Ensures(Contract.ValueAtReturn(out wcmd) != null); IToken/*!*/ x; Token z;
- Expr guard; Expr/*!*/ e; bool isFree;
- List<PredicateCmd/*!*/> invariants = new List<PredicateCmd/*!*/>();
- StmtList/*!*/ body;
- QKeyValue kv = null;
-
- Expect(42);
- x = t;
- Guard(out guard);
- Contract.Assume(guard == null || cce.Owner.None(guard));
- while (la.kind == 35 || la.kind == 43) {
- isFree = false; z = la/*lookahead token*/;
- if (la.kind == 35) {
- Get();
- isFree = true;
- }
- Expect(43);
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- Expression(out e);
- if (isFree) {
- invariants.Add(new AssumeCmd(z, e, kv));
- } else {
- invariants.Add(new AssertCmd(z, e, kv));
- }
- kv = null;
-
- Expect(8);
- }
- Expect(27);
- StmtList(out body);
- wcmd = new WhileCmd(x, guard, invariants, body);
- }
-
- void BreakCmd(out BreakCmd/*!*/ bcmd) {
- Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y;
- string breakLabel = null;
-
- Expect(45);
- x = t;
- if (la.kind == 1) {
- Ident(out y);
- breakLabel = y.val;
- }
- Expect(8);
- bcmd = new BreakCmd(x, breakLabel);
- }
-
- void Guard(out Expr e) {
- Expr/*!*/ ee; e = null;
- Expect(9);
- if (la.kind == 44) {
- Get();
- e = null;
- } else if (StartOf(9)) {
- Expression(out ee);
- e = ee;
- } else SynErr(109);
- Expect(10);
- }
-
- void LabelOrAssign(out Cmd c, out IToken label) {
- IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0;
- c = dummyCmd; label = null;
- AssignLhs/*!*/ lhs;
- List<AssignLhs/*!*/>/*!*/ lhss;
- List<Expr/*!*/>/*!*/ rhss;
- List<Expr/*!*/>/*!*/ indexes;
-
- Ident(out id);
- x = t;
- if (la.kind == 11) {
- Get();
- c = null; label = x;
- } else if (la.kind == 12 || la.kind == 17 || la.kind == 50) {
- lhss = new List<AssignLhs/*!*/>();
- lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
- while (la.kind == 17) {
- MapAssignIndex(out y, out indexes);
- lhs = new MapAssignLhs(y, lhs, indexes);
- }
- lhss.Add(lhs);
- while (la.kind == 12) {
- Get();
- Ident(out id);
- lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
- while (la.kind == 17) {
- MapAssignIndex(out y, out indexes);
- lhs = new MapAssignLhs(y, lhs, indexes);
- }
- lhss.Add(lhs);
- }
- Expect(50);
- x = t; /* use location of := */
- Expression(out e0);
- rhss = new List<Expr/*!*/> ();
- rhss.Add(e0);
- while (la.kind == 12) {
- Get();
- Expression(out e0);
- rhss.Add(e0);
- }
- Expect(8);
- c = new AssignCmd(x, lhss, rhss);
- } else SynErr(110);
- }
-
- void CallCmd(out Cmd c) {
- Contract.Ensures(Contract.ValueAtReturn(out c) != null);
- IToken x;
- bool isAsync = false;
- bool isFree = false;
- QKeyValue kv = null;
- c = null;
-
- if (la.kind == 51) {
- Get();
- isAsync = true;
- }
- if (la.kind == 35) {
- Get();
- isFree = true;
- }
- Expect(52);
- x = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- CallParams(isAsync, isFree, kv, x, out c);
-
- }
-
- void ParCallCmd(out Cmd d) {
- Contract.Ensures(Contract.ValueAtReturn(out d) != null);
- IToken x;
- QKeyValue kv = null;
- Cmd c = null;
- List<CallCmd> callCmds = new List<CallCmd>();
-
- Expect(53);
- x = t;
- while (la.kind == 27) {
- Attribute(ref kv);
- }
- CallParams(false, false, kv, x, out c);
- callCmds.Add((CallCmd)c);
- while (la.kind == 54) {
- Get();
- CallParams(false, false, kv, x, out c);
- callCmds.Add((CallCmd)c);
- }
- Expect(8);
- d = new ParCallCmd(x, callCmds, kv);
- }
-
- void MapAssignIndex(out IToken/*!*/ x, out List<Expr/*!*/>/*!*/ indexes) {
- Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List<Expr/*!*/> ();
- Expr/*!*/ e;
-
- Expect(17);
- x = t;
- if (StartOf(9)) {
- Expression(out e);
- indexes.Add(e);
- while (la.kind == 12) {
- Get();
- Expression(out e);
- indexes.Add(e);
- }
- }
- Expect(18);
- }
-
- void CallParams(bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c) {
- List<IdentifierExpr> ids = new List<IdentifierExpr>();
- List<Expr> es = new List<Expr>();
- Expr en;
- IToken first;
- IToken p;
- c = null;
-
- Ident(out first);
- if (la.kind == 9) {
- Get();
- if (StartOf(9)) {
- Expression(out en);
- es.Add(en);
- while (la.kind == 12) {
- Get();
- Expression(out en);
- es.Add(en);
- }
- }
- Expect(10);
- c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync;
- } else if (la.kind == 12 || la.kind == 50) {
- ids.Add(new IdentifierExpr(first, first.val));
- if (la.kind == 12) {
- Get();
- Ident(out p);
- ids.Add(new IdentifierExpr(p, p.val));
- while (la.kind == 12) {
- Get();
- Ident(out p);
- ids.Add(new IdentifierExpr(p, p.val));
- }
- }
- Expect(50);
- Ident(out first);
- Expect(9);
- if (StartOf(9)) {
- Expression(out en);
- es.Add(en);
- while (la.kind == 12) {
- Get();
- Expression(out en);
- es.Add(en);
- }
- }
- Expect(10);
- c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync;
- } else SynErr(111);
- }
-
- void Expressions(out List<Expr>/*!*/ es) {
- Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new List<Expr>();
- Expression(out e);
- es.Add(e);
- while (la.kind == 12) {
- Get();
- Expression(out e);
- es.Add(e);
- }
- }
-
- void ImpliesExpression(bool noExplies, out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
- LogicalExpression(out e0);
- if (StartOf(10)) {
- if (la.kind == 57 || la.kind == 58) {
- ImpliesOp();
- x = t;
- ImpliesExpression(true, out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1);
- } else {
- ExpliesOp();
- if (noExplies)
- this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
- x = t;
- LogicalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
- while (la.kind == 59 || la.kind == 60) {
- ExpliesOp();
- x = t;
- LogicalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
- }
- }
- }
- }
-
- void EquivOp() {
- if (la.kind == 55) {
- Get();
- } else if (la.kind == 56) {
- Get();
- } else SynErr(112);
- }
-
- void LogicalExpression(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
- RelationalExpression(out e0);
- if (StartOf(11)) {
- if (la.kind == 61 || la.kind == 62) {
- AndOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
- while (la.kind == 61 || la.kind == 62) {
- AndOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
- }
- } else {
- OrOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
- while (la.kind == 63 || la.kind == 64) {
- OrOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
- }
- }
- }
- }
-
- void ImpliesOp() {
- if (la.kind == 57) {
- Get();
- } else if (la.kind == 58) {
- Get();
- } else SynErr(113);
- }
-
- void ExpliesOp() {
- if (la.kind == 59) {
- Get();
- } else if (la.kind == 60) {
- Get();
- } else SynErr(114);
- }
-
- void RelationalExpression(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
- BvTerm(out e0);
- if (StartOf(12)) {
- RelOp(out x, out op);
- BvTerm(out e1);
- e0 = Expr.Binary(x, op, e0, e1);
- }
- }
-
- void AndOp() {
- if (la.kind == 61) {
- Get();
- } else if (la.kind == 62) {
- Get();
- } else SynErr(115);
- }
-
- void OrOp() {
- if (la.kind == 63) {
- Get();
- } else if (la.kind == 64) {
- Get();
- } else SynErr(116);
- }
-
- void BvTerm(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
- Term(out e0);
- while (la.kind == 73) {
- Get();
- x = t;
- Term(out e1);
- e0 = new BvConcatExpr(x, e0, e1);
- }
- }
-
- void RelOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
- Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- switch (la.kind) {
- case 65: {
- Get();
- x = t; op=BinaryOperator.Opcode.Eq;
- break;
- }
- case 19: {
- Get();
- x = t; op=BinaryOperator.Opcode.Lt;
- break;
- }
- case 20: {
- Get();
- x = t; op=BinaryOperator.Opcode.Gt;
- break;
- }
- case 66: {
- Get();
- x = t; op=BinaryOperator.Opcode.Le;
- break;
- }
- case 67: {
- Get();
- x = t; op=BinaryOperator.Opcode.Ge;
- break;
- }
- case 68: {
- Get();
- x = t; op=BinaryOperator.Opcode.Neq;
- break;
- }
- case 69: {
- Get();
- x = t; op=BinaryOperator.Opcode.Subtype;
- break;
- }
- case 70: {
- Get();
- x = t; op=BinaryOperator.Opcode.Neq;
- break;
- }
- case 71: {
- Get();
- x = t; op=BinaryOperator.Opcode.Le;
- break;
- }
- case 72: {
- Get();
- x = t; op=BinaryOperator.Opcode.Ge;
- break;
- }
- default: SynErr(117); break;
- }
- }
-
- void Term(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
- Factor(out e0);
- while (la.kind == 74 || la.kind == 75) {
- AddOp(out x, out op);
- Factor(out e1);
- e0 = Expr.Binary(x, op, e0, e1);
- }
- }
-
- void Factor(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
- Power(out e0);
- while (StartOf(13)) {
- MulOp(out x, out op);
- Power(out e1);
- e0 = Expr.Binary(x, op, e0, e1);
- }
- }
-
- void AddOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
- Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- if (la.kind == 74) {
- Get();
- x = t; op=BinaryOperator.Opcode.Add;
- } else if (la.kind == 75) {
- Get();
- x = t; op=BinaryOperator.Opcode.Sub;
- } else SynErr(118);
- }
-
- void Power(out Expr/*!*/ e0) {
- Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
- UnaryExpression(out e0);
- if (la.kind == 79) {
- Get();
- x = t;
- Power(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Pow, e0, e1);
- }
- }
-
- void MulOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
- Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- if (la.kind == 44) {
- Get();
- x = t; op=BinaryOperator.Opcode.Mul;
- } else if (la.kind == 76) {
- Get();
- x = t; op=BinaryOperator.Opcode.Div;
- } else if (la.kind == 77) {
- Get();
- x = t; op=BinaryOperator.Opcode.Mod;
- } else if (la.kind == 78) {
- Get();
- x = t; op=BinaryOperator.Opcode.RealDiv;
- } else SynErr(119);
- }
-
- void UnaryExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- e = dummyExpr;
-
- if (la.kind == 75) {
- Get();
- x = t;
- UnaryExpression(out e);
- e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e);
- } else if (la.kind == 80 || la.kind == 81) {
- NegOp();
- x = t;
- UnaryExpression(out e);
- e = Expr.Unary(x, UnaryOperator.Opcode.Not, e);
- } else if (StartOf(14)) {
- CoercionExpression(out e);
- } else SynErr(120);
- }
-
- void NegOp() {
- if (la.kind == 80) {
- Get();
- } else if (la.kind == 81) {
- Get();
- } else SynErr(123);
- }
-
- void CoercionExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- Bpl.Type/*!*/ coercedTo;
- BigNum bn;
-
- ArrayExpression(out e);
- while (la.kind == 11) {
- Get();
- x = t;
- if (StartOf(6)) {
- Type(out coercedTo);
- e = Expr.CoerceType(x, e, coercedTo);
- } else if (la.kind == 3) {
- Nat(out bn);
- if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
- this.SemErr("arguments of extract need to be integer literals");
- e = new BvBounds(x, bn, BigNum.ZERO);
- } else {
- e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
- }
-
- } else SynErr(124);
- }
- }
-
- void ArrayExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
- Expr/*!*/ index0 = dummyExpr; Expr/*!*/ e1;
- bool store; bool bvExtract;
- List<Expr>/*!*/ allArgs = dummyExprSeq;
-
- AtomExpression(out e);
- while (la.kind == 17) {
- Get();
- x = t; allArgs = new List<Expr> ();
- allArgs.Add(e);
- store = false; bvExtract = false;
- if (StartOf(15)) {
- if (StartOf(9)) {
- Expression(out index0);
- if (index0 is BvBounds)
- bvExtract = true;
- else
- allArgs.Add(index0);
-
- while (la.kind == 12) {
- Get();
- Expression(out e1);
- if (bvExtract || e1 is BvBounds)
- this.SemErr("bitvectors only have one dimension");
- allArgs.Add(e1);
-
- }
- if (la.kind == 50) {
- Get();
- Expression(out e1);
- if (bvExtract || e1 is BvBounds)
- this.SemErr("assignment to bitvectors is not possible");
- allArgs.Add(e1); store = true;
-
- }
- } else {
- Get();
- Expression(out e1);
- allArgs.Add(e1); store = true;
- }
- }
- Expect(18);
- if (store)
- e = new NAryExpr(x, new MapStore(x, allArgs.Count - 2), allArgs);
- else if (bvExtract)
- e = new BvExtractExpr(x, e,
- ((BvBounds)index0).Upper.ToIntSafe,
- ((BvBounds)index0).Lower.ToIntSafe);
- else
- e = new NAryExpr(x, new MapSelect(x, allArgs.Count - 1), allArgs);
-
- }
- }
-
- void Nat(out BigNum n) {
- Expect(3);
- try {
- n = BigNum.FromString(t.val);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted number");
- n = BigNum.ZERO;
- }
-
- }
-
- void AtomExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; BigFloat fp;
- List<Expr>/*!*/ es; List<Variable>/*!*/ ds; Trigger trig;
- List<TypeVariable>/*!*/ typeParams;
- IdentifierExpr/*!*/ id;
- QKeyValue kv;
- e = dummyExpr;
- List<Variable>/*!*/ locals;
- List<Block/*!*/>/*!*/ blocks;
-
- switch (la.kind) {
- case 82: {
- Get();
- e = new LiteralExpr(t, false);
- break;
- }
- case 83: {
- Get();
- e = new LiteralExpr(t, true);
- break;
- }
- case 3: {
- Nat(out bn);
- e = new LiteralExpr(t, bn);
- break;
- }
- case 5: case 6: {
- Dec(out bd);
- e = new LiteralExpr(t, bd);
- break;
- }
- case 97: {
- Float(out fp);
- e = new LiteralExpr(t, fp);
- break;
- }
- case 2: {
- BvLit(out bn, out n);
- e = new LiteralExpr(t, bn, n);
- break;
- }
- case 1: {
- Ident(out x);
- id = new IdentifierExpr(x, x.val); e = id;
- if (la.kind == 9) {
- Get();
- if (StartOf(9)) {
- Expressions(out es);
- e = new NAryExpr(x, new FunctionCall(id), es);
- } else if (la.kind == 10) {
- e = new NAryExpr(x, new FunctionCall(id), new List<Expr>());
- } else SynErr(125);
- Expect(10);
- }
- break;
- }
- case 84: {
- Get();
- x = t;
- Expect(9);
- Expression(out e);
- Expect(10);
- e = new OldExpr(x, e);
- break;
- }
- case 14: {
- Get();
- x = t;
- Expect(9);
- Expression(out e);
- Expect(10);
- e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new List<Expr>{ e });
- break;
- }
- case 15: {
- Get();
- x = t;
- Expect(9);
- Expression(out e);
- Expect(10);
- e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new List<Expr>{ e });
- break;
- }
- case 98: {
- Get();
- x = t;
- Expect(19);
- Expression(out e);
- Expect(20);
- e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToFloat), new List<Expr> { e });
- break;
- }
- case 9: {
- Get();
- if (StartOf(9)) {
- Expression(out e);
- if (e is BvBounds)
- this.SemErr("parentheses around bitvector bounds " +
- "are not allowed");
- } else if (la.kind == 88 || la.kind == 89) {
- Forall();
- x = t;
- QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
- if (typeParams.Count + ds.Count > 0)
- e = new ForallExpr(x, typeParams, ds, kv, trig, e);
- } else if (la.kind == 90 || la.kind == 91) {
- Exists();
- x = t;
- QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
- if (typeParams.Count + ds.Count > 0)
- e = new ExistsExpr(x, typeParams, ds, kv, trig, e);
- } else if (la.kind == 92 || la.kind == 93) {
- Lambda();
- x = t;
- QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
- if (trig != null)
- SemErr("triggers not allowed in lambda expressions");
- if (typeParams.Count + ds.Count > 0)
- e = new LambdaExpr(x, typeParams, ds, kv, e);
- } else SynErr(126);
- Expect(10);
- break;
- }
- case 40: {
- IfThenElseExpression(out e);
- break;
- }
- case 85: {
- CodeExpression(out locals, out blocks);
- e = new CodeExpr(locals, blocks);
- break;
- }
- default: SynErr(127); break;
- }
- }
-
- void Dec(out BigDec n) {
- string s = "";
- if (la.kind == 5) {
- Get();
- s = t.val;
- } else if (la.kind == 6) {
- Get();
- s = t.val;
- } else SynErr(128);
- try {
- n = BigDec.FromString(s);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted number");
- n = BigDec.ZERO;
- }
-
- }
-
- /// <summary>
- /// Creates a floating point from the current token value
- /// </summary>
- /// <param name="n"></param>
- void Float(out BigFloat n)
- {
- try
- {
- if (la.kind == 97) {
- bool negative = false;
- int exp, sig, size;
- BigNum exp_val, sig_val, value;
- //Expected format = float(sign exp_val sig_val) || float<exp sig>(value)
- Get(); //Skip the float token
- if (la.val == "(") {
- Get();
- if (la.val == "false")
- negative = false;
- else if (la.val == "true")
- negative = true;
- else
- throw new FormatException();
- Get();
- Expect(12); //,
- BvLit(out exp_val, out exp);
- Expect(12);
- BvLit(out sig_val, out sig);
- n = new BigFloat(negative, exp_val, sig_val, exp, sig);
- Expect(10); //)
- }
- else if (la.val == "<") {
- Get();
- Expect(3);
- exp = Int32.Parse(t.val);
- Expect(12);
- Expect(3);
- sig = Int32.Parse(t.val);
- Expect(20); //>
- Expect(9); //(
- if (la.kind == 1) { //NaN
- Get();
- n = new BigFloat(t.val, exp, sig);
- }
- else if (la.kind == 74 || la.kind == 75) { //+ or -
- Get();
- String s = t.val;
- Get();
- n = new BigFloat(s + t.val, exp, sig);
- }
- else {
- BvLit(out value, out size);
- n = new BigFloat(value.ToString(), exp, sig);
- }
- Expect(10); //)
- }
- else {
- throw new FormatException();
- }
- }
- else {
- n = BigFloat.ZERO(8, 24);
- SynErr(137);
- }
- }
- catch (FormatException)
- {
- this.SemErr("incorrectly formatted floating point");
- n = BigFloat.ZERO(8, 24);
- }
- }
-
- void BvLit(out BigNum n, out int m) {
- Expect(2);
- int pos = t.val.IndexOf("bv");
- string a = t.val.Substring(0, pos);
- string b = t.val.Substring(pos + 2);
- try {
- n = BigNum.FromString(a);
- m = Convert.ToInt32(b);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted bitvector");
- n = BigNum.ZERO;
- m = 0;
- }
-
- }
-
- void Forall() {
- if (la.kind == 88) {
- Get();
- } else if (la.kind == 89) {
- Get();
- } else SynErr(129);
- }
-
- void QuantifierBody(IToken/*!*/ q, out List<TypeVariable>/*!*/ typeParams, out List<Variable>/*!*/ ds,
-out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
- Contract.Requires(q != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ds) != null); Contract.Ensures(Contract.ValueAtReturn(out body) != null);
- trig = null; typeParams = new List<TypeVariable> ();
- IToken/*!*/ tok;
- kv = null;
- ds = new List<Variable> ();
-
- if (la.kind == 19) {
- TypeParams(out tok, out typeParams);
- if (la.kind == 1 || la.kind == 27) {
- BoundVars(q, out ds);
- }
- } else if (la.kind == 1 || la.kind == 27) {
- BoundVars(q, out ds);
- } else SynErr(130);
- QSep();
- while (la.kind == 27) {
- AttributeOrTrigger(ref kv, ref trig);
- }
- Expression(out body);
- }
-
- void Exists() {
- if (la.kind == 90) {
- Get();
- } else if (la.kind == 91) {
- Get();
- } else SynErr(131);
- }
-
- void Lambda() {
- if (la.kind == 92) {
- Get();
- } else if (la.kind == 93) {
- Get();
- } else SynErr(132);
- }
-
- void IfThenElseExpression(out Expr/*!*/ e) {
- Contract.Ensures(Contract.ValueAtReturn(out e) != null);
- IToken/*!*/ tok;
- Expr/*!*/ e0, e1, e2;
- e = dummyExpr;
- Expect(40);
- tok = t;
- Expression(out e0);
- Expect(87);
- Expression(out e1);
- Expect(41);
- Expression(out e2);
- e = new NAryExpr(tok, new IfThenElse(tok), new List<Expr>{ e0, e1, e2 });
- }
-
- void CodeExpression(out List<Variable>/*!*/ locals, out List<Block/*!*/>/*!*/ blocks) {
- Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new List<Variable>(); Block/*!*/ b;
- blocks = new List<Block/*!*/>();
-
- Expect(85);
- while (la.kind == 7) {
- LocalVars(locals);
- }
- SpecBlock(out b);
- blocks.Add(b);
- while (la.kind == 1) {
- SpecBlock(out b);
- blocks.Add(b);
- }
- Expect(86);
- }
-
- void SpecBlock(out Block/*!*/ b) {
- Contract.Ensures(Contract.ValueAtReturn(out b) != null); IToken/*!*/ x; IToken/*!*/ y;
- Cmd c; IToken label;
- List<Cmd> cs = new List<Cmd>();
- List<IToken>/*!*/ xs;
- List<String> ss = new List<String>();
- b = dummyBlock;
- Expr/*!*/ e;
-
- Ident(out x);
- Expect(11);
- while (StartOf(8)) {
- LabelOrCmd(out c, out label);
- if (c != null) {
- Contract.Assert(label == null);
- cs.Add(c);
- } else {
- Contract.Assert(label != null);
- SemErr("SpecBlock's can only have one label");
- }
-
- }
- if (la.kind == 38) {
- Get();
- y = t;
- Idents(out xs);
- foreach(IToken/*!*/ s in xs){
- Contract.Assert(s != null);
- ss.Add(s.val); }
- b = new Block(x,x.val,cs,new GotoCmd(y,ss));
-
- } else if (la.kind == 39) {
- Get();
- Expression(out e);
- b = new Block(x,x.val,cs,new ReturnExprCmd(t,e));
- } else SynErr(133);
- Expect(8);
- }
-
- void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) {
- IToken/*!*/ tok; Expr/*!*/ e; List<Expr>/*!*/ es;
- string key;
- List<object/*!*/> parameters; object/*!*/ param;
-
- Expect(27);
- tok = t;
- if (la.kind == 11) {
- Get();
- Expect(1);
- key = t.val; parameters = new List<object/*!*/>();
- if (StartOf(16)) {
- AttributeParameter(out param);
- parameters.Add(param);
- while (la.kind == 12) {
- Get();
- AttributeParameter(out param);
- parameters.Add(param);
- }
- }
- if (key == "nopats") {
- if (parameters.Count == 1 && parameters[0] is Expr) {
- e = (Expr)parameters[0];
- if(trig==null){
- trig = new Trigger(tok, false, new List<Expr> { e }, null);
- } else {
- trig.AddLast(new Trigger(tok, false, new List<Expr> { e }, null));
- }
- } else {
- this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
- }
- } else {
- if (kv==null) {
- kv = new QKeyValue(tok, key, parameters, null);
- } else {
- kv.AddLast(new QKeyValue(tok, key, parameters, null));
- }
- }
-
- } else if (StartOf(9)) {
- Expression(out e);
- es = new List<Expr> { e };
- while (la.kind == 12) {
- Get();
- Expression(out e);
- es.Add(e);
- }
- if (trig==null) {
- trig = new Trigger(tok, true, es, null);
- } else {
- trig.AddLast(new Trigger(tok, true, es, null));
- }
-
- } else SynErr(134);
- Expect(28);
- }
-
- void AttributeParameter(out object/*!*/ o) {
- Contract.Ensures(Contract.ValueAtReturn(out o) != null);
- o = "error";
- Expr/*!*/ e;
-
- if (la.kind == 4) {
- Get();
- o = t.val.Substring(1, t.val.Length-2);
- } else if (StartOf(9)) {
- Expression(out e);
- o = e;
- } else SynErr(135);
- }
-
- void QSep() {
- if (la.kind == 94) {
- Get();
- } else if (la.kind == 95) {
- Get();
- } else SynErr(136);
- }
-
-
-
- public void Parse() {
- la = new Token();
- la.val = "";
- Get();
- BoogiePL();
- Expect(0);
-
- Expect(0);
- }
-
- static readonly bool[,]/*!*/ set = { //grid is 17 x 100
- {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,x,x, x,T,T,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x},
- {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, T,x,T,x, x,T,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x},
- {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,T,T, T,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x}
-
- };
-} // end Parser
-
-
-public class Errors {
- public int count = 0; // number of errors detected
- public System.IO.TextWriter/*!*/ errorStream = Console.Out; // error messages go to this stream
- public string errMsgFormat = "{0}({1},{2}): error: {3}"; // 0=filename, 1=line, 2=column, 3=text
- public string warningMsgFormat = "{0}({1},{2}): warning: {3}"; // 0=filename, 1=line, 2=column, 3=text
-
- public void SynErr(string filename, int line, int col, int n) {
- SynErr(filename, line, col, GetSyntaxErrorString(n));
- }
-
- public virtual void SynErr(string filename, int line, int col, string/*!*/ msg) {
- Contract.Requires(msg != null);
- errorStream.WriteLine(errMsgFormat, filename, line, col, msg);
- count++;
- }
-
- /// <summary>
- /// Returns a string corresponding to the syntax error of the given type
- /// Note that many of these errors (0-98) correspond to token types (e.g. the la token)
- /// </summary>
- /// <param name="n"></param>
- /// <returns></returns>
- string GetSyntaxErrorString(int n) {
- string s;
- switch (n) {
- case 0: s = "EOF expected"; break;
- case 1: s = "ident expected"; break;
- case 2: s = "bvlit expected"; break;
- case 3: s = "digits expected"; break;
- case 4: s = "string expected"; break;
- case 5: s = "decimal expected"; break;
- case 6: s = "float expected"; break;
- case 7: s = "\"var\" expected"; break;
- case 8: s = "\";\" expected"; break;
- case 9: s = "\"(\" expected"; break;
- case 10: s = "\")\" expected"; break;
- case 11: s = "\":\" expected"; break;
- case 12: s = "\",\" expected"; break;
- case 13: s = "\"where\" expected"; break;
- case 14: s = "\"int\" expected"; break;
- case 15: s = "\"real\" expected"; break;
- case 16: s = "\"bool\" expected"; break;
- case 17: s = "\"[\" expected"; break;
- case 18: s = "\"]\" expected"; break;
- case 19: s = "\"<\" expected"; break;
- case 20: s = "\">\" expected"; break;
- case 21: s = "\"const\" expected"; break;
- case 22: s = "\"unique\" expected"; break;
- case 23: s = "\"extends\" expected"; break;
- case 24: s = "\"complete\" expected"; break;
- case 25: s = "\"function\" expected"; break;
- case 26: s = "\"returns\" expected"; break;
- case 27: s = "\"{\" expected"; break;
- case 28: s = "\"}\" expected"; break;
- case 29: s = "\"axiom\" expected"; break;
- case 30: s = "\"type\" expected"; break;
- case 31: s = "\"=\" expected"; break;
- case 32: s = "\"procedure\" expected"; break;
- case 33: s = "\"implementation\" expected"; break;
- case 34: s = "\"modifies\" expected"; break;
- case 35: s = "\"free\" expected"; break;
- case 36: s = "\"requires\" expected"; break;
- case 37: s = "\"ensures\" expected"; break;
- case 38: s = "\"goto\" expected"; break;
- case 39: s = "\"return\" expected"; break;
- case 40: s = "\"if\" expected"; break;
- case 41: s = "\"else\" expected"; break;
- case 42: s = "\"while\" expected"; break;
- case 43: s = "\"invariant\" expected"; break;
- case 44: s = "\"*\" expected"; break;
- case 45: s = "\"break\" expected"; break;
- case 46: s = "\"assert\" expected"; break;
- case 47: s = "\"assume\" expected"; break;
- case 48: s = "\"havoc\" expected"; break;
- case 49: s = "\"yield\" expected"; break;
- case 50: s = "\":=\" expected"; break;
- case 51: s = "\"async\" expected"; break;
- case 52: s = "\"call\" expected"; break;
- case 53: s = "\"par\" expected"; break;
- case 54: s = "\"|\" expected"; break;
- case 55: s = "\"<==>\" expected"; break;
- case 56: s = "\"\\u21d4\" expected"; break;
- case 57: s = "\"==>\" expected"; break;
- case 58: s = "\"\\u21d2\" expected"; break;
- case 59: s = "\"<==\" expected"; break;
- case 60: s = "\"\\u21d0\" expected"; break;
- case 61: s = "\"&&\" expected"; break;
- case 62: s = "\"\\u2227\" expected"; break;
- case 63: s = "\"||\" expected"; break;
- case 64: s = "\"\\u2228\" expected"; break;
- case 65: s = "\"==\" expected"; break;
- case 66: s = "\"<=\" expected"; break;
- case 67: s = "\">=\" expected"; break;
- case 68: s = "\"!=\" expected"; break;
- case 69: s = "\"<:\" expected"; break;
- case 70: s = "\"\\u2260\" expected"; break;
- case 71: s = "\"\\u2264\" expected"; break;
- case 72: s = "\"\\u2265\" expected"; break;
- case 73: s = "\"++\" expected"; break;
- case 74: s = "\"+\" expected"; break;
- case 75: s = "\"-\" expected"; break;
- case 76: s = "\"div\" expected"; break;
- case 77: s = "\"mod\" expected"; break;
- case 78: s = "\"/\" expected"; break;
- case 79: s = "\"**\" expected"; break;
- case 80: s = "\"!\" expected"; break;
- case 81: s = "\"\\u00ac\" expected"; break;
- case 82: s = "\"false\" expected"; break;
- case 83: s = "\"true\" expected"; break;
- case 84: s = "\"old\" expected"; break;
- case 85: s = "\"|{\" expected"; break;
- case 86: s = "\"}|\" expected"; break;
- case 87: s = "\"then\" expected"; break;
- case 88: s = "\"forall\" expected"; break;
- case 89: s = "\"\\u2200\" expected"; break;
- case 90: s = "\"exists\" expected"; break;
- case 91: s = "\"\\u2203\" expected"; break;
- case 92: s = "\"lambda\" expected"; break;
- case 93: s = "\"\\u03bb\" expected"; break;
- case 94: s = "\"::\" expected"; break;
- case 95: s = "\"\\u2022\" expected"; break;
- case 96: s = "??? expected"; break;
- case 97: s = "fp expected"; break;
- case 98: s = "\"float\" expected"; break;
- case 99: s = "invalid Function"; break;
- case 100: s = "invalid Function"; break;
- case 101: s = "invalid Procedure"; break;
- case 102: s = "invalid Type"; break;
- case 103: s = "invalid TypeAtom"; break;
- case 104: s = "invalid TypeArgs"; break;
- case 105: s = "invalid Spec"; break;
- case 106: s = "invalid SpecPrePost"; break;
- case 107: s = "invalid LabelOrCmd"; break;
- case 108: s = "invalid StructuredCmd"; break;
- case 109: s = "invalid TransferCmd"; break;
- case 110: s = "invalid IfCmd"; break;
- case 111: s = "invalid Guard"; break;
- case 112: s = "invalid LabelOrAssign"; break;
- case 113: s = "invalid CallParams"; break;
- case 114: s = "invalid EquivOp"; break;
- case 115: s = "invalid ImpliesOp"; break;
- case 116: s = "invalid ExpliesOp"; break;
- case 117: s = "invalid AndOp"; break;
- case 118: s = "invalid OrOp"; break;
- case 119: s = "invalid RelOp"; break;
- case 120: s = "invalid AddOp"; break;
- case 121: s = "invalid MulOp"; break;
- case 122: s = "invalid UnaryExpression"; break;
- case 123: s = "invalid NegOp"; break;
- case 124: s = "invalid CoercionExpression"; break;
- case 125: s = "invalid AtomExpression"; break;
- case 126: s = "invalid AtomExpression"; break;
- case 127: s = "invalid AtomExpression"; break;
- case 128: s = "invalid Dec"; break;
- case 129: s = "invalid Forall"; break;
- case 130: s = "invalid QuantifierBody"; break;
- case 131: s = "invalid Exists"; break;
- case 132: s = "invalid Lambda"; break;
- case 133: s = "invalid SpecBlock"; break;
- case 134: s = "invalid AttributeOrTrigger"; break;
- case 135: s = "invalid AttributeParameter"; break;
- case 136: s = "invalid QSep"; break;
- case 137: s = "invalid Float"; break;
-
- default: s = "error " + n; break;
- }
- return s;
- }
-
- public void SemErr(IToken/*!*/ tok, string/*!*/ msg) { // semantic errors
- Contract.Requires(tok != null);
- Contract.Requires(msg != null);
- SemErr(tok.filename, tok.line, tok.col, msg);
- }
-
- public virtual void SemErr(string filename, int line, int col, string/*!*/ msg) {
- Contract.Requires(msg != null);
- errorStream.WriteLine(errMsgFormat, filename, line, col, msg);
- count++;
- }
-
- public void Warning(IToken/*!*/ tok, string/*!*/ msg) { // warnings
- Contract.Requires(tok != null);
- Contract.Requires(msg != null);
- Warning(tok.filename, tok.line, tok.col, msg);
- }
-
- public virtual void Warning(string filename, int line, int col, string msg) {
- Contract.Requires(msg != null);
- errorStream.WriteLine(warningMsgFormat, filename, line, col, msg);
- }
-} // Errors
-
-
-public class FatalError: Exception {
- public FatalError(string m): base(m) {}
-}
-
-
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using Bpl = Microsoft.Boogie;
+
+
+
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie {
+
+
+
+public class Parser {
+ public const int _EOF = 0;
+ public const int _ident = 1;
+ public const int _bvlit = 2;
+ public const int _digits = 3;
+ public const int _string = 4;
+ public const int _decimal = 5;
+ public const int _float = 6;
+ public const int _fp = 97;
+ public const int maxT = 98;
+
+ const bool T = true;
+ const bool x = false;
+ const int minErrDist = 2;
+
+ public Scanner/*!*/ scanner;
+ public Errors/*!*/ errors;
+
+ public Token/*!*/ t; // last recognized token
+ public Token/*!*/ la; // lookahead token
+ int errDist = minErrDist;
+
+readonly Program/*!*/ Pgm;
+
+readonly Expr/*!*/ dummyExpr;
+readonly Cmd/*!*/ dummyCmd;
+readonly Block/*!*/ dummyBlock;
+readonly Bpl.Type/*!*/ dummyType;
+readonly List<Expr>/*!*/ dummyExprSeq;
+readonly TransferCmd/*!*/ dummyTransferCmd;
+readonly StructuredCmd/*!*/ dummyStructuredCmd;
+
+///<summary>
+///Returns the number of parsing errors encountered. If 0, "program" returns as
+///the parsed program.
+///</summary>
+public static int Parse (string/*!*/ filename, /*maybe null*/ List<string/*!*/> defines, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
+ Contract.Requires(filename != null);
+ Contract.Requires(cce.NonNullElements(defines,true));
+
+ if (defines == null) {
+ defines = new List<string/*!*/>();
+ }
+
+ if (filename == "stdin.bpl") {
+ var s = ParserHelper.Fill(Console.In, defines);
+ return Parse(s, filename, out program, useBaseName);
+ } else {
+ FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+ var s = ParserHelper.Fill(stream, defines);
+ var ret = Parse(s, filename, out program, useBaseName);
+ stream.Close();
+ return ret;
+ }
+}
+
+
+public static int Parse (string s, string/*!*/ filename, out /*maybe null*/ Program program, bool useBaseName=false) /* throws System.IO.IOException */ {
+ Contract.Requires(s != null);
+ Contract.Requires(filename != null);
+
+ byte[]/*!*/ buffer = cce.NonNull(UTF8Encoding.Default.GetBytes(s));
+ MemoryStream ms = new MemoryStream(buffer,false);
+ Errors errors = new Errors();
+ Scanner scanner = new Scanner(ms, errors, filename, useBaseName);
+
+ Parser parser = new Parser(scanner, errors, false);
+ parser.Parse();
+ if (parser.errors.count == 0)
+ {
+ program = parser.Pgm;
+ program.ProcessDatatypeConstructors();
+ return 0;
+ }
+ else
+ {
+ program = null;
+ return parser.errors.count;
+ }
+}
+
+public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, bool disambiguation)
+ : this(scanner, errors)
+{
+ // initialize readonly fields
+ Pgm = new Program();
+ dummyExpr = new LiteralExpr(Token.NoToken, false);
+ dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
+ dummyBlock = new Block(Token.NoToken, "dummyBlock", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
+ dummyExprSeq = new List<Expr> ();
+ dummyTransferCmd = new ReturnCmd(Token.NoToken);
+ dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
+}
+
+// Class to represent the bounds of a bitvector expression t[a:b].
+// Objects of this class only exist during parsing and are directly
+// turned into BvExtract before they get anywhere else
+private class BvBounds : Expr {
+ public BigNum Lower;
+ public BigNum Upper;
+ public BvBounds(IToken/*!*/ tok, BigNum lower, BigNum upper)
+ : base(tok, /*immutable=*/ false) {
+ Contract.Requires(tok != null);
+ this.Lower = lower;
+ this.Upper = upper;
+ }
+ public override Bpl.Type/*!*/ ShallowType { get {Contract.Ensures(Contract.Result<Bpl.Type>() != null); return Bpl.Type.Int; } }
+ public override void Resolve(ResolutionContext/*!*/ rc) {
+ // Contract.Requires(rc != null);
+ rc.Error(this, "bitvector bounds in illegal position");
+ }
+ public override void Emit(TokenTextWriter/*!*/ stream,
+ int contextBindingStrength, bool fragileContext) {
+ Contract.Assert(false);throw new cce.UnreachableException();
+ }
+ public override void ComputeFreeVariables(GSet<object>/*!*/ freeVars) { Contract.Assert(false);throw new cce.UnreachableException(); }
+ public override int ComputeHashCode() {
+ return base.GetHashCode();
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+ public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors) {
+ this.scanner = scanner;
+ this.errors = errors;
+ Token/*!*/ tok = new Token();
+ tok.val = "";
+ this.la = tok;
+ this.t = new Token(); // just to satisfy its non-null constraint
+ }
+
+ void SynErr (int n) {
+ if (errDist >= minErrDist) errors.SynErr(la.filename, la.line, la.col, n);
+ errDist = 0;
+ }
+
+ public void SemErr (string/*!*/ msg) {
+ Contract.Requires(msg != null);
+ if (errDist >= minErrDist) errors.SemErr(t, msg);
+ errDist = 0;
+ }
+
+ public void SemErr(IToken/*!*/ tok, string/*!*/ msg) {
+ Contract.Requires(tok != null);
+ Contract.Requires(msg != null);
+ errors.SemErr(tok, msg);
+ }
+
+ void Get () {
+ for (;;) {
+ t = la;
+ la = scanner.Scan();
+ if (la.kind <= maxT) { ++errDist; break; }
+
+ la = t;
+ }
+ }
+
+ void Expect (int n) {
+ if (la.kind==n) Get(); else { SynErr(n); }
+ }
+
+ bool StartOf (int s) {
+ return set[s, la.kind];
+ }
+
+ void ExpectWeak (int n, int follow) {
+ if (la.kind == n) Get();
+ else {
+ SynErr(n);
+ while (!StartOf(follow)) Get();
+ }
+ }
+
+
+ bool WeakSeparator(int n, int syFol, int repFol) {
+ int kind = la.kind;
+ if (kind == n) {Get(); return true;}
+ else if (StartOf(repFol)) {return false;}
+ else {
+ SynErr(n);
+ while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
+ Get();
+ kind = la.kind;
+ }
+ return StartOf(syFol);
+ }
+ }
+
+
+ void BoogiePL() {
+ List<Variable>/*!*/ vs;
+ List<Declaration>/*!*/ ds;
+ Axiom/*!*/ ax;
+ List<Declaration/*!*/>/*!*/ ts;
+ Procedure/*!*/ pr;
+ Implementation im;
+ Implementation/*!*/ nnim;
+
+ while (StartOf(1)) {
+ switch (la.kind) {
+ case 21: {
+ Consts(out vs);
+ foreach(Bpl.Variable/*!*/ v in vs){
+ Contract.Assert(v != null);
+ Pgm.AddTopLevelDeclaration(v);
+ }
+
+ break;
+ }
+ case 25: {
+ Function(out ds);
+ foreach(Bpl.Declaration/*!*/ d in ds){
+ Contract.Assert(d != null);
+ Pgm.AddTopLevelDeclaration(d);
+ }
+
+ break;
+ }
+ case 29: {
+ Axiom(out ax);
+ Pgm.AddTopLevelDeclaration(ax);
+ break;
+ }
+ case 30: {
+ UserDefinedTypes(out ts);
+ foreach(Declaration/*!*/ td in ts){
+ Contract.Assert(td != null);
+ Pgm.AddTopLevelDeclaration(td);
+ }
+
+ break;
+ }
+ case 7: {
+ GlobalVars(out vs);
+ foreach(Bpl.Variable/*!*/ v in vs){
+ Contract.Assert(v != null);
+ Pgm.AddTopLevelDeclaration(v);
+ }
+
+ break;
+ }
+ case 32: {
+ Procedure(out pr, out im);
+ Pgm.AddTopLevelDeclaration(pr);
+ if (im != null) {
+ Pgm.AddTopLevelDeclaration(im);
+ }
+
+ break;
+ }
+ case 33: {
+ Implementation(out nnim);
+ Pgm.AddTopLevelDeclaration(nnim);
+ break;
+ }
+ }
+ }
+ Expect(0);
+ }
+
+ void Consts(out List<Variable>/*!*/ ds) {
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null); IToken/*!*/ y; List<TypedIdent>/*!*/ xs;
+ ds = new List<Variable>();
+ bool u = false; QKeyValue kv = null;
+ bool ChildrenComplete = false;
+ List<ConstantParent/*!*/> Parents = null;
+ Expect(21);
+ y = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ if (la.kind == 22) {
+ Get();
+ u = true;
+ }
+ IdsType(out xs);
+ if (la.kind == 23) {
+ OrderSpec(out ChildrenComplete, out Parents);
+ }
+ bool makeClone = false;
+ foreach(TypedIdent/*!*/ x in xs){
+ Contract.Assert(x != null);
+
+ // ensure that no sharing is introduced
+ List<ConstantParent/*!*/> ParentsClone;
+ if (makeClone && Parents != null) {
+ ParentsClone = new List<ConstantParent/*!*/> ();
+ foreach (ConstantParent/*!*/ p in Parents){
+ Contract.Assert(p != null);
+ ParentsClone.Add(new ConstantParent (
+ new IdentifierExpr (p.Parent.tok, p.Parent.Name),
+ p.Unique));}
+ } else {
+ ParentsClone = Parents;
+ }
+ makeClone = true;
+
+ ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
+ }
+
+ Expect(8);
+ }
+
+ void Function(out List<Declaration>/*!*/ ds) {
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ ds = new List<Declaration>(); IToken/*!*/ z;
+ IToken/*!*/ typeParamTok;
+ var typeParams = new List<TypeVariable>();
+ var arguments = new List<Variable>();
+ TypedIdent/*!*/ tyd;
+ TypedIdent retTyd = null;
+ Bpl.Type/*!*/ retTy;
+ QKeyValue argKv = null;
+ QKeyValue kv = null;
+ Expr definition = null;
+ Expr/*!*/ tmp;
+
+ Expect(25);
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Ident(out z);
+ if (la.kind == 19) {
+ TypeParams(out typeParamTok, out typeParams);
+ }
+ Expect(9);
+ if (StartOf(2)) {
+ VarOrType(out tyd, out argKv);
+ arguments.Add(new Formal(tyd.tok, tyd, true, argKv));
+ while (la.kind == 12) {
+ Get();
+ VarOrType(out tyd, out argKv);
+ arguments.Add(new Formal(tyd.tok, tyd, true, argKv));
+ }
+ }
+ Expect(10);
+ argKv = null;
+ if (la.kind == 26) {
+ Get();
+ Expect(9);
+ VarOrType(out retTyd, out argKv);
+ Expect(10);
+ } else if (la.kind == 11) {
+ Get();
+ Type(out retTy);
+ retTyd = new TypedIdent(retTy.tok, TypedIdent.NoName, retTy);
+ } else SynErr(99);
+ if (la.kind == 27) {
+ Get();
+ Expression(out tmp);
+ definition = tmp;
+ Expect(28);
+ } else if (la.kind == 8) {
+ Get();
+ } else SynErr(100);
+ if (retTyd == null) {
+ // construct a dummy type for the case of syntax error
+ retTyd = new TypedIdent(t, TypedIdent.NoName, new BasicType(t, SimpleType.Int));
+ }
+ Function/*!*/ func = new Function(z, z.val, typeParams, arguments,
+ new Formal(retTyd.tok, retTyd, false, argKv), null, kv);
+ Contract.Assert(func != null);
+ ds.Add(func);
+ bool allUnnamed = true;
+ foreach(Formal/*!*/ f in arguments){
+ Contract.Assert(f != null);
+ if (f.TypedIdent.HasName) {
+ allUnnamed = false;
+ break;
+ }
+ }
+ if (!allUnnamed) {
+ Bpl.Type prevType = null;
+ for (int i = arguments.Count; 0 <= --i; ) {
+ TypedIdent/*!*/ curr = cce.NonNull(arguments[i]).TypedIdent;
+ if (curr.HasName) {
+ // the argument was given as both an identifier and a type
+ prevType = curr.Type;
+ } else {
+ // the argument was given as just one "thing", which syntactically parsed as a type
+ if (prevType == null) {
+ this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
+ break;
+ }
+ Bpl.Type ty = curr.Type;
+ var uti = ty as UnresolvedTypeIdentifier;
+ if (uti != null && uti.Arguments.Count == 0) {
+ // the given "thing" was just an identifier, so let's use it as the name of the parameter
+ curr.Name = uti.Name;
+ curr.Type = prevType;
+ } else {
+ this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
+ }
+ }
+ }
+ }
+ if (definition != null) {
+ // generate either an axiom or a function body
+ if (QKeyValue.FindBoolAttribute(kv, "inline")) {
+ func.Body = definition;
+ } else {
+ ds.Add(func.CreateDefinitionAxiom(definition, kv));
+ }
+ }
+
+ }
+
+ void Axiom(out Axiom/*!*/ m) {
+ Contract.Ensures(Contract.ValueAtReturn(out m) != null); Expr/*!*/ e; QKeyValue kv = null;
+ Expect(29);
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ IToken/*!*/ x = t;
+ Proposition(out e);
+ Expect(8);
+ m = new Axiom(x,e, null, kv);
+ }
+
+ void UserDefinedTypes(out List<Declaration/*!*/>/*!*/ ts) {
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out ts))); Declaration/*!*/ decl; QKeyValue kv = null; ts = new List<Declaration/*!*/> ();
+ Expect(30);
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ UserDefinedType(out decl, kv);
+ ts.Add(decl);
+ while (la.kind == 12) {
+ Get();
+ UserDefinedType(out decl, kv);
+ ts.Add(decl);
+ }
+ Expect(8);
+ }
+
+ void GlobalVars(out List<Variable>/*!*/ ds) {
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ QKeyValue kv = null;
+ ds = new List<Variable>();
+ var dsx = ds;
+
+ Expect(7);
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ IdsTypeWheres(true, "global variables", delegate(TypedIdent tyd) { dsx.Add(new GlobalVariable(tyd.tok, tyd, kv)); } );
+ Expect(8);
+ }
+
+ void Procedure(out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl) {
+ Contract.Ensures(Contract.ValueAtReturn(out proc) != null); IToken/*!*/ x;
+ List<TypeVariable>/*!*/ typeParams;
+ List<Variable>/*!*/ ins, outs;
+ List<Requires>/*!*/ pre = new List<Requires>();
+ List<IdentifierExpr>/*!*/ mods = new List<IdentifierExpr>();
+ List<Ensures>/*!*/ post = new List<Ensures>();
+
+ List<Variable>/*!*/ locals = new List<Variable>();
+ StmtList/*!*/ stmtList;
+ QKeyValue kv = null;
+ impl = null;
+
+ Expect(32);
+ ProcSignature(true, out x, out typeParams, out ins, out outs, out kv);
+ if (la.kind == 8) {
+ Get();
+ while (StartOf(3)) {
+ Spec(pre, mods, post);
+ }
+ } else if (StartOf(4)) {
+ while (StartOf(3)) {
+ Spec(pre, mods, post);
+ }
+ ImplBody(out locals, out stmtList);
+ impl = new Implementation(x, x.val, typeParams,
+ Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors);
+
+ } else SynErr(99);
+ proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv);
+ }
+
+ void Implementation(out Implementation/*!*/ impl) {
+ Contract.Ensures(Contract.ValueAtReturn(out impl) != null); IToken/*!*/ x;
+ List<TypeVariable>/*!*/ typeParams;
+ List<Variable>/*!*/ ins, outs;
+ List<Variable>/*!*/ locals;
+ StmtList/*!*/ stmtList;
+ QKeyValue kv;
+
+ Expect(33);
+ ProcSignature(false, out x, out typeParams, out ins, out outs, out kv);
+ ImplBody(out locals, out stmtList);
+ impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors);
+ }
+
+ void Attribute(ref QKeyValue kv) {
+ Trigger trig = null;
+ AttributeOrTrigger(ref kv, ref trig);
+ if (trig != null) this.SemErr("only attributes, not triggers, allowed here");
+ }
+
+ void IdsTypeWheres(bool allowWhereClauses, string context, System.Action<TypedIdent> action ) {
+ IdsTypeWhere(allowWhereClauses, context, action);
+ while (la.kind == 12) {
+ Get();
+ IdsTypeWhere(allowWhereClauses, context, action);
+ }
+ }
+
+ void LocalVars(List<Variable>/*!*/ ds) {
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ QKeyValue kv = null;
+
+ Expect(7);
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ IdsTypeWheres(true, "local variables", delegate(TypedIdent tyd) { ds.Add(new LocalVariable(tyd.tok, tyd, kv)); } );
+ Expect(8);
+ }
+
+ void ProcFormals(bool incoming, bool allowWhereClauses, out List<Variable>/*!*/ ds) {
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ ds = new List<Variable>();
+ var dsx = ds;
+ var context = allowWhereClauses ? "procedure formals" : "the 'implementation' copies of formals";
+
+ Expect(9);
+ if (la.kind == 1 || la.kind == 27) {
+ AttrsIdsTypeWheres(allowWhereClauses, allowWhereClauses, context, delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new Formal(tyd.tok, tyd, incoming, kv)); });
+ }
+ Expect(10);
+ }
+
+ void AttrsIdsTypeWheres(bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action ) {
+ AttributesIdsTypeWhere(allowAttributes, allowWhereClauses, context, action);
+ while (la.kind == 12) {
+ Get();
+ AttributesIdsTypeWhere(allowAttributes, allowWhereClauses, context, action);
+ }
+ }
+
+ void BoundVars(IToken/*!*/ x, out List<Variable>/*!*/ ds) {
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
+ List<TypedIdent>/*!*/ tyds = new List<TypedIdent>();
+ ds = new List<Variable>();
+ var dsx = ds;
+
+ AttrsIdsTypeWheres(true, false, "bound variables", delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new BoundVariable(tyd.tok, tyd, kv)); } );
+ }
+
+ void IdsType(out List<TypedIdent>/*!*/ tyds) {
+ Contract.Ensures(Contract.ValueAtReturn(out tyds) != null); List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty;
+ Idents(out ids);
+ Expect(11);
+ Type(out ty);
+ tyds = new List<TypedIdent>();
+ foreach(Token/*!*/ id in ids){
+ Contract.Assert(id != null);
+ tyds.Add(new TypedIdent(id, id.val, ty, null));
+ }
+
+ }
+
+ void Idents(out List<IToken>/*!*/ xs) {
+ Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>();
+ Ident(out id);
+ xs.Add(id);
+ while (la.kind == 12) {
+ Get();
+ Ident(out id);
+ xs.Add(id);
+ }
+ }
+
+ void Type(out Bpl.Type/*!*/ ty) {
+ Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; ty = dummyType;
+ if (StartOf(5)) {
+ TypeAtom(out ty);
+ } else if (la.kind == 1) {
+ Ident(out tok);
+ List<Bpl.Type>/*!*/ args = new List<Bpl.Type> ();
+ if (StartOf(6)) {
+ TypeArgs(args);
+ }
+ ty = new UnresolvedTypeIdentifier (tok, tok.val, args);
+ } else if (la.kind == 17 || la.kind == 19) {
+ MapType(out ty);
+ } else SynErr(100);
+ }
+
+ void AttributesIdsTypeWhere(bool allowAttributes, bool allowWhereClauses, string context, System.Action<TypedIdent, QKeyValue> action ) {
+ QKeyValue kv = null;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ if (!allowAttributes) {
+ kv = null;
+ this.SemErr("attributes are not allowed on " + context);
+ }
+
+ }
+ IdsTypeWhere(allowWhereClauses, context, delegate(TypedIdent tyd) { action(tyd, kv); });
+ }
+
+ void IdsTypeWhere(bool allowWhereClauses, string context, System.Action<TypedIdent> action ) {
+ List<IToken>/*!*/ ids; Bpl.Type/*!*/ ty; Expr wh = null; Expr/*!*/ nne;
+ Idents(out ids);
+ Expect(11);
+ Type(out ty);
+ if (la.kind == 13) {
+ Get();
+ Expression(out nne);
+ if (!allowWhereClauses) {
+ this.SemErr("where clause not allowed on " + context);
+ } else {
+ wh = nne;
+ }
+
+ }
+ foreach(Token/*!*/ id in ids){
+ Contract.Assert(id != null);
+ action(new TypedIdent(id, id.val, ty, wh));
+ }
+
+ }
+
+ void Expression(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
+ ImpliesExpression(false, out e0);
+ while (la.kind == 55 || la.kind == 56) {
+ EquivOp();
+ x = t;
+ ImpliesExpression(false, out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1);
+ }
+ }
+
+ void TypeAtom(out Bpl.Type/*!*/ ty) {
+ Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType;
+ if (la.kind == 14) {
+ Get();
+ ty = new BasicType(t, SimpleType.Int);
+ } else if (la.kind == 15) {
+ Get();
+ ty = new BasicType(t, SimpleType.Real);
+ } else if (la.kind == 98) {
+ Get();
+ ty = FType();
+ } else if (la.kind == 16) {
+ Get();
+ ty = new BasicType(t, SimpleType.Bool);
+ } else if (la.kind == 9) {
+ Get();
+ Type(out ty);
+ Expect(10);
+ } else SynErr(101);
+ }
+
+ FloatType FType() {
+ if (t.val.Length > 5) {
+ switch (Int32.Parse(t.val.Substring(5))) {
+ case 16:
+ return new FloatType(t, 5, 11);
+ case 32:
+ return new FloatType(t, 8, 24);
+ case 64:
+ return new FloatType(t, 11, 53);
+ case 128:
+ return new FloatType(t, 15, 113);
+ default:
+ SynErr(3);
+ return new FloatType(t, 0, 0);
+ }
+ }
+ else {
+ try {
+ Expect(19); //<
+ Expect(3); //int
+ int exp = Int32.Parse(t.val);
+ Expect(12); //,
+ Expect(3); //int
+ int man = Int32.Parse(t.val);
+ Expect(20); //>
+ return new FloatType(t, exp, man);
+ }
+ catch (Exception) {
+ return new FloatType(t, 0, 0);
+ }
+ }
+ }
+
+ void Ident(out IToken/*!*/ x) {
+ Contract.Ensures(Contract.ValueAtReturn(out x) != null);
+ Expect(1);
+ x = t;
+ if (x.val.StartsWith("\\"))
+ x.val = x.val.Substring(1);
+
+ }
+
+ void TypeArgs(List<Bpl.Type>/*!*/ ts) {
+ Contract.Requires(ts != null); IToken/*!*/ tok; Bpl.Type/*!*/ ty;
+ if (StartOf(5)) {
+ TypeAtom(out ty);
+ ts.Add(ty);
+ if (StartOf(6)) {
+ TypeArgs(ts);
+ }
+ } else if (la.kind == 1) {
+ Ident(out tok);
+ List<Bpl.Type>/*!*/ args = new List<Bpl.Type> ();
+ ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args));
+ if (StartOf(6)) {
+ TypeArgs(ts);
+ }
+ } else if (la.kind == 17 || la.kind == 19) {
+ MapType(out ty);
+ ts.Add(ty);
+ } else SynErr(102);
+ }
+
+ void MapType(out Bpl.Type/*!*/ ty) {
+ Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken tok = null;
+ IToken/*!*/ nnTok;
+ List<Bpl.Type>/*!*/ arguments = new List<Bpl.Type>();
+ Bpl.Type/*!*/ result;
+ List<TypeVariable>/*!*/ typeParameters = new List<TypeVariable>();
+
+ if (la.kind == 19) {
+ TypeParams(out nnTok, out typeParameters);
+ tok = nnTok;
+ }
+ Expect(17);
+ if (tok == null) tok = t;
+ if (StartOf(6)) {
+ Types(arguments);
+ }
+ Expect(18);
+ Type(out result);
+ ty = new MapType(tok, typeParameters, arguments, result);
+
+ }
+
+ void TypeParams(out IToken/*!*/ tok, out List<TypeVariable>/*!*/ typeParams) {
+ Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); List<IToken>/*!*/ typeParamToks;
+ Expect(19);
+ tok = t;
+ Idents(out typeParamToks);
+ Expect(20);
+ typeParams = new List<TypeVariable> ();
+ foreach(Token/*!*/ id in typeParamToks){
+ Contract.Assert(id != null);
+ typeParams.Add(new TypeVariable(id, id.val));}
+
+ }
+
+ void Types(List<Bpl.Type>/*!*/ ts) {
+ Contract.Requires(ts != null); Bpl.Type/*!*/ ty;
+ Type(out ty);
+ ts.Add(ty);
+ while (la.kind == 12) {
+ Get();
+ Type(out ty);
+ ts.Add(ty);
+ }
+ }
+
+ void OrderSpec(out bool ChildrenComplete, out List<ConstantParent/*!*/> Parents) {
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out Parents),true)); ChildrenComplete = false;
+ Parents = null;
+ bool u;
+ IToken/*!*/ parent;
+ Expect(23);
+ Parents = new List<ConstantParent/*!*/> ();
+ u = false;
+ if (la.kind == 1 || la.kind == 22) {
+ if (la.kind == 22) {
+ Get();
+ u = true;
+ }
+ Ident(out parent);
+ Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u));
+ while (la.kind == 12) {
+ Get();
+ u = false;
+ if (la.kind == 22) {
+ Get();
+ u = true;
+ }
+ Ident(out parent);
+ Parents.Add(new ConstantParent (
+ new IdentifierExpr(parent, parent.val), u));
+ }
+ }
+ if (la.kind == 24) {
+ Get();
+ ChildrenComplete = true;
+ }
+ }
+
+ void VarOrType(out TypedIdent/*!*/ tyd, out QKeyValue kv) {
+ Contract.Ensures(Contract.ValueAtReturn(out tyd) != null);
+ string/*!*/ varName = TypedIdent.NoName;
+ Bpl.Type/*!*/ ty;
+ IToken/*!*/ tok;
+ kv = null;
+
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Type(out ty);
+ tok = ty.tok;
+ if (la.kind == 11) {
+ Get();
+ var uti = ty as UnresolvedTypeIdentifier;
+ if (uti != null && uti.Arguments.Count == 0) {
+ varName = uti.Name;
+ } else {
+ this.SemErr("expected identifier before ':'");
+ }
+
+ Type(out ty);
+ }
+ tyd = new TypedIdent(tok, varName, ty);
+ }
+
+ void Proposition(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null);
+ Expression(out e);
+ }
+
+ void UserDefinedType(out Declaration/*!*/ decl, QKeyValue kv) {
+ Contract.Ensures(Contract.ValueAtReturn(out decl) != null); IToken/*!*/ id; List<IToken>/*!*/ paramTokens = new List<IToken> ();
+ Bpl.Type/*!*/ body = dummyType; bool synonym = false;
+ Ident(out id);
+ if (la.kind == 1) {
+ WhiteSpaceIdents(out paramTokens);
+ }
+ if (la.kind == 31) {
+ Get();
+ Type(out body);
+ synonym = true;
+ }
+ if (synonym) {
+ List<TypeVariable>/*!*/ typeParams = new List<TypeVariable>();
+ foreach(Token/*!*/ t in paramTokens){
+ Contract.Assert(t != null);
+ typeParams.Add(new TypeVariable(t, t.val));}
+ decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
+ } else {
+ decl = new TypeCtorDecl(id, id.val, paramTokens.Count, kv);
+ }
+
+ }
+
+ void WhiteSpaceIdents(out List<IToken>/*!*/ xs) {
+ Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List<IToken>();
+ Ident(out id);
+ xs.Add(id);
+ while (la.kind == 1) {
+ Ident(out id);
+ xs.Add(id);
+ }
+ }
+
+ void ProcSignature(bool allowWhereClausesOnFormals, out IToken/*!*/ name, out List<TypeVariable>/*!*/ typeParams,
+out List<Variable>/*!*/ ins, out List<Variable>/*!*/ outs, out QKeyValue kv) {
+ Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null);
+ IToken/*!*/ typeParamTok; typeParams = new List<TypeVariable>();
+ outs = new List<Variable>(); kv = null;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Ident(out name);
+ if (la.kind == 19) {
+ TypeParams(out typeParamTok, out typeParams);
+ }
+ ProcFormals(true, allowWhereClausesOnFormals, out ins);
+ if (la.kind == 26) {
+ Get();
+ ProcFormals(false, allowWhereClausesOnFormals, out outs);
+ }
+ }
+
+ void Spec(List<Requires>/*!*/ pre, List<IdentifierExpr>/*!*/ mods, List<Ensures>/*!*/ post) {
+ Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); List<IToken>/*!*/ ms;
+ if (la.kind == 34) {
+ Get();
+ if (la.kind == 1) {
+ Idents(out ms);
+ foreach(IToken/*!*/ m in ms){
+ Contract.Assert(m != null);
+ mods.Add(new IdentifierExpr(m, m.val));
+ }
+
+ }
+ Expect(8);
+ } else if (la.kind == 35) {
+ Get();
+ SpecPrePost(true, pre, post);
+ } else if (la.kind == 36 || la.kind == 37) {
+ SpecPrePost(false, pre, post);
+ } else SynErr(103);
+ }
+
+ void ImplBody(out List<Variable>/*!*/ locals, out StmtList/*!*/ stmtList) {
+ Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List<Variable>();
+ Expect(27);
+ while (la.kind == 7) {
+ LocalVars(locals);
+ }
+ StmtList(out stmtList);
+ }
+
+ void SpecPrePost(bool free, List<Requires>/*!*/ pre, List<Ensures>/*!*/ post) {
+ Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null;
+ if (la.kind == 36) {
+ Get();
+ tok = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Proposition(out e);
+ Expect(8);
+ pre.Add(new Requires(tok, free, e, null, kv));
+ } else if (la.kind == 37) {
+ Get();
+ tok = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Proposition(out e);
+ Expect(8);
+ post.Add(new Ensures(tok, free, e, null, kv));
+ } else SynErr(104);
+ }
+
+ void StmtList(out StmtList/*!*/ stmtList) {
+ Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List<BigBlock/*!*/> bigblocks = new List<BigBlock/*!*/>();
+ /* built-up state for the current BigBlock: */
+ IToken startToken = null; string currentLabel = null;
+ List<Cmd> cs = null; /* invariant: startToken != null ==> cs != null */
+ /* temporary variables: */
+ IToken label; Cmd c; BigBlock b;
+ StructuredCmd ec = null; StructuredCmd/*!*/ ecn;
+ TransferCmd tc = null; TransferCmd/*!*/ tcn;
+
+ while (StartOf(7)) {
+ if (StartOf(8)) {
+ LabelOrCmd(out c, out label);
+ if (c != null) {
+ // LabelOrCmd read a Cmd
+ Contract.Assert(label == null);
+ if (startToken == null) { startToken = c.tok; cs = new List<Cmd>(); }
+ Contract.Assert(cs != null);
+ cs.Add(c);
+ } else {
+ // LabelOrCmd read a label
+ Contract.Assert(label != null);
+ if (startToken != null) {
+ Contract.Assert(cs != null);
+ // dump the built-up state into a BigBlock
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ cs = null;
+ }
+ startToken = label;
+ currentLabel = label.val;
+ cs = new List<Cmd>();
+ }
+
+ } else if (la.kind == 40 || la.kind == 42 || la.kind == 45) {
+ StructuredCmd(out ecn);
+ ec = ecn;
+ if (startToken == null) { startToken = ec.tok; cs = new List<Cmd>(); }
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, ec, null);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+
+ } else {
+ TransferCmd(out tcn);
+ tc = tcn;
+ if (startToken == null) { startToken = tc.tok; cs = new List<Cmd>(); }
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, null, tc);
+ bigblocks.Add(b);
+ startToken = null; currentLabel = null; cs = null;
+
+ }
+ }
+ Expect(28);
+ IToken/*!*/ endCurly = t;
+ if (startToken == null && bigblocks.Count == 0) {
+ startToken = t; cs = new List<Cmd>();
+ }
+ if (startToken != null) {
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ }
+
+ stmtList = new StmtList(bigblocks, endCurly);
+
+ }
+
+ void LabelOrCmd(out Cmd c, out IToken label) {
+ IToken/*!*/ x; Expr/*!*/ e;
+ List<IToken>/*!*/ xs;
+ List<IdentifierExpr> ids;
+ c = dummyCmd; label = null;
+ Cmd/*!*/ cn;
+ QKeyValue kv = null;
+
+ switch (la.kind) {
+ case 1: {
+ LabelOrAssign(out c, out label);
+ break;
+ }
+ case 46: {
+ Get();
+ x = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Proposition(out e);
+ c = new AssertCmd(x, e, kv);
+ Expect(8);
+ break;
+ }
+ case 47: {
+ Get();
+ x = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Proposition(out e);
+ c = new AssumeCmd(x, e, kv);
+ Expect(8);
+ break;
+ }
+ case 48: {
+ Get();
+ x = t;
+ Idents(out xs);
+ Expect(8);
+ ids = new List<IdentifierExpr>();
+ foreach(IToken/*!*/ y in xs){
+ Contract.Assert(y != null);
+ ids.Add(new IdentifierExpr(y, y.val));
+ }
+ c = new HavocCmd(x,ids);
+
+ break;
+ }
+ case 35: case 51: case 52: {
+ CallCmd(out cn);
+ Expect(8);
+ c = cn;
+ break;
+ }
+ case 53: {
+ ParCallCmd(out cn);
+ c = cn;
+ break;
+ }
+ case 49: {
+ Get();
+ x = t;
+ Expect(8);
+ c = new YieldCmd(x);
+ break;
+ }
+ default: SynErr(105); break;
+ }
+ }
+
+ void StructuredCmd(out StructuredCmd/*!*/ ec) {
+ Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec));
+ IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd;
+
+ if (la.kind == 40) {
+ IfCmd(out ifcmd);
+ ec = ifcmd;
+ } else if (la.kind == 42) {
+ WhileCmd(out wcmd);
+ ec = wcmd;
+ } else if (la.kind == 45) {
+ BreakCmd(out bcmd);
+ ec = bcmd;
+ } else SynErr(106);
+ }
+
+ void TransferCmd(out TransferCmd/*!*/ tc) {
+ Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
+ Token y; List<IToken>/*!*/ xs;
+ List<String> ss = new List<String>();
+
+ if (la.kind == 38) {
+ Get();
+ y = t;
+ Idents(out xs);
+ foreach(IToken/*!*/ s in xs){
+ Contract.Assert(s != null);
+ ss.Add(s.val); }
+ tc = new GotoCmd(y, ss);
+
+ } else if (la.kind == 39) {
+ Get();
+ tc = new ReturnCmd(t);
+ } else SynErr(107);
+ Expect(8);
+ }
+
+ void IfCmd(out IfCmd/*!*/ ifcmd) {
+ Contract.Ensures(Contract.ValueAtReturn(out ifcmd) != null); IToken/*!*/ x;
+ Expr guard;
+ StmtList/*!*/ thn;
+ IfCmd/*!*/ elseIf; IfCmd elseIfOption = null;
+ StmtList/*!*/ els; StmtList elseOption = null;
+
+ Expect(40);
+ x = t;
+ Guard(out guard);
+ Expect(27);
+ StmtList(out thn);
+ if (la.kind == 41) {
+ Get();
+ if (la.kind == 40) {
+ IfCmd(out elseIf);
+ elseIfOption = elseIf;
+ } else if (la.kind == 27) {
+ Get();
+ StmtList(out els);
+ elseOption = els;
+ } else SynErr(108);
+ }
+ ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption);
+ }
+
+ void WhileCmd(out WhileCmd/*!*/ wcmd) {
+ Contract.Ensures(Contract.ValueAtReturn(out wcmd) != null); IToken/*!*/ x; Token z;
+ Expr guard; Expr/*!*/ e; bool isFree;
+ List<PredicateCmd/*!*/> invariants = new List<PredicateCmd/*!*/>();
+ StmtList/*!*/ body;
+ QKeyValue kv = null;
+
+ Expect(42);
+ x = t;
+ Guard(out guard);
+ Contract.Assume(guard == null || cce.Owner.None(guard));
+ while (la.kind == 35 || la.kind == 43) {
+ isFree = false; z = la/*lookahead token*/;
+ if (la.kind == 35) {
+ Get();
+ isFree = true;
+ }
+ Expect(43);
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ Expression(out e);
+ if (isFree) {
+ invariants.Add(new AssumeCmd(z, e, kv));
+ } else {
+ invariants.Add(new AssertCmd(z, e, kv));
+ }
+ kv = null;
+
+ Expect(8);
+ }
+ Expect(27);
+ StmtList(out body);
+ wcmd = new WhileCmd(x, guard, invariants, body);
+ }
+
+ void BreakCmd(out BreakCmd/*!*/ bcmd) {
+ Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y;
+ string breakLabel = null;
+
+ Expect(45);
+ x = t;
+ if (la.kind == 1) {
+ Ident(out y);
+ breakLabel = y.val;
+ }
+ Expect(8);
+ bcmd = new BreakCmd(x, breakLabel);
+ }
+
+ void Guard(out Expr e) {
+ Expr/*!*/ ee; e = null;
+ Expect(9);
+ if (la.kind == 44) {
+ Get();
+ e = null;
+ } else if (StartOf(9)) {
+ Expression(out ee);
+ e = ee;
+ } else SynErr(109);
+ Expect(10);
+ }
+
+ void LabelOrAssign(out Cmd c, out IToken label) {
+ IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0;
+ c = dummyCmd; label = null;
+ AssignLhs/*!*/ lhs;
+ List<AssignLhs/*!*/>/*!*/ lhss;
+ List<Expr/*!*/>/*!*/ rhss;
+ List<Expr/*!*/>/*!*/ indexes;
+
+ Ident(out id);
+ x = t;
+ if (la.kind == 11) {
+ Get();
+ c = null; label = x;
+ } else if (la.kind == 12 || la.kind == 17 || la.kind == 50) {
+ lhss = new List<AssignLhs/*!*/>();
+ lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
+ while (la.kind == 17) {
+ MapAssignIndex(out y, out indexes);
+ lhs = new MapAssignLhs(y, lhs, indexes);
+ }
+ lhss.Add(lhs);
+ while (la.kind == 12) {
+ Get();
+ Ident(out id);
+ lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
+ while (la.kind == 17) {
+ MapAssignIndex(out y, out indexes);
+ lhs = new MapAssignLhs(y, lhs, indexes);
+ }
+ lhss.Add(lhs);
+ }
+ Expect(50);
+ x = t; /* use location of := */
+ Expression(out e0);
+ rhss = new List<Expr/*!*/> ();
+ rhss.Add(e0);
+ while (la.kind == 12) {
+ Get();
+ Expression(out e0);
+ rhss.Add(e0);
+ }
+ Expect(8);
+ c = new AssignCmd(x, lhss, rhss);
+ } else SynErr(110);
+ }
+
+ void CallCmd(out Cmd c) {
+ Contract.Ensures(Contract.ValueAtReturn(out c) != null);
+ IToken x;
+ bool isAsync = false;
+ bool isFree = false;
+ QKeyValue kv = null;
+ c = null;
+
+ if (la.kind == 51) {
+ Get();
+ isAsync = true;
+ }
+ if (la.kind == 35) {
+ Get();
+ isFree = true;
+ }
+ Expect(52);
+ x = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ CallParams(isAsync, isFree, kv, x, out c);
+
+ }
+
+ void ParCallCmd(out Cmd d) {
+ Contract.Ensures(Contract.ValueAtReturn(out d) != null);
+ IToken x;
+ QKeyValue kv = null;
+ Cmd c = null;
+ List<CallCmd> callCmds = new List<CallCmd>();
+
+ Expect(53);
+ x = t;
+ while (la.kind == 27) {
+ Attribute(ref kv);
+ }
+ CallParams(false, false, kv, x, out c);
+ callCmds.Add((CallCmd)c);
+ while (la.kind == 54) {
+ Get();
+ CallParams(false, false, kv, x, out c);
+ callCmds.Add((CallCmd)c);
+ }
+ Expect(8);
+ d = new ParCallCmd(x, callCmds, kv);
+ }
+
+ void MapAssignIndex(out IToken/*!*/ x, out List<Expr/*!*/>/*!*/ indexes) {
+ Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List<Expr/*!*/> ();
+ Expr/*!*/ e;
+
+ Expect(17);
+ x = t;
+ if (StartOf(9)) {
+ Expression(out e);
+ indexes.Add(e);
+ while (la.kind == 12) {
+ Get();
+ Expression(out e);
+ indexes.Add(e);
+ }
+ }
+ Expect(18);
+ }
+
+ void CallParams(bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c) {
+ List<IdentifierExpr> ids = new List<IdentifierExpr>();
+ List<Expr> es = new List<Expr>();
+ Expr en;
+ IToken first;
+ IToken p;
+ c = null;
+
+ Ident(out first);
+ if (la.kind == 9) {
+ Get();
+ if (StartOf(9)) {
+ Expression(out en);
+ es.Add(en);
+ while (la.kind == 12) {
+ Get();
+ Expression(out en);
+ es.Add(en);
+ }
+ }
+ Expect(10);
+ c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync;
+ } else if (la.kind == 12 || la.kind == 50) {
+ ids.Add(new IdentifierExpr(first, first.val));
+ if (la.kind == 12) {
+ Get();
+ Ident(out p);
+ ids.Add(new IdentifierExpr(p, p.val));
+ while (la.kind == 12) {
+ Get();
+ Ident(out p);
+ ids.Add(new IdentifierExpr(p, p.val));
+ }
+ }
+ Expect(50);
+ Ident(out first);
+ Expect(9);
+ if (StartOf(9)) {
+ Expression(out en);
+ es.Add(en);
+ while (la.kind == 12) {
+ Get();
+ Expression(out en);
+ es.Add(en);
+ }
+ }
+ Expect(10);
+ c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync;
+ } else SynErr(111);
+ }
+
+ void Expressions(out List<Expr>/*!*/ es) {
+ Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new List<Expr>();
+ Expression(out e);
+ es.Add(e);
+ while (la.kind == 12) {
+ Get();
+ Expression(out e);
+ es.Add(e);
+ }
+ }
+
+ void ImpliesExpression(bool noExplies, out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
+ LogicalExpression(out e0);
+ if (StartOf(10)) {
+ if (la.kind == 57 || la.kind == 58) {
+ ImpliesOp();
+ x = t;
+ ImpliesExpression(true, out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1);
+ } else {
+ ExpliesOp();
+ if (noExplies)
+ this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
+ x = t;
+ LogicalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
+ while (la.kind == 59 || la.kind == 60) {
+ ExpliesOp();
+ x = t;
+ LogicalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
+ }
+ }
+ }
+ }
+
+ void EquivOp() {
+ if (la.kind == 55) {
+ Get();
+ } else if (la.kind == 56) {
+ Get();
+ } else SynErr(112);
+ }
+
+ void LogicalExpression(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
+ RelationalExpression(out e0);
+ if (StartOf(11)) {
+ if (la.kind == 61 || la.kind == 62) {
+ AndOp();
+ x = t;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
+ while (la.kind == 61 || la.kind == 62) {
+ AndOp();
+ x = t;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
+ }
+ } else {
+ OrOp();
+ x = t;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
+ while (la.kind == 63 || la.kind == 64) {
+ OrOp();
+ x = t;
+ RelationalExpression(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
+ }
+ }
+ }
+ }
+
+ void ImpliesOp() {
+ if (la.kind == 57) {
+ Get();
+ } else if (la.kind == 58) {
+ Get();
+ } else SynErr(113);
+ }
+
+ void ExpliesOp() {
+ if (la.kind == 59) {
+ Get();
+ } else if (la.kind == 60) {
+ Get();
+ } else SynErr(114);
+ }
+
+ void RelationalExpression(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
+ BvTerm(out e0);
+ if (StartOf(12)) {
+ RelOp(out x, out op);
+ BvTerm(out e1);
+ e0 = Expr.Binary(x, op, e0, e1);
+ }
+ }
+
+ void AndOp() {
+ if (la.kind == 61) {
+ Get();
+ } else if (la.kind == 62) {
+ Get();
+ } else SynErr(115);
+ }
+
+ void OrOp() {
+ if (la.kind == 63) {
+ Get();
+ } else if (la.kind == 64) {
+ Get();
+ } else SynErr(116);
+ }
+
+ void BvTerm(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
+ Term(out e0);
+ while (la.kind == 73) {
+ Get();
+ x = t;
+ Term(out e1);
+ e0 = new BvConcatExpr(x, e0, e1);
+ }
+ }
+
+ void RelOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
+ Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
+ switch (la.kind) {
+ case 65: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Eq;
+ break;
+ }
+ case 19: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Lt;
+ break;
+ }
+ case 20: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Gt;
+ break;
+ }
+ case 66: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Le;
+ break;
+ }
+ case 67: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Ge;
+ break;
+ }
+ case 68: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Neq;
+ break;
+ }
+ case 69: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Subtype;
+ break;
+ }
+ case 70: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Neq;
+ break;
+ }
+ case 71: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Le;
+ break;
+ }
+ case 72: {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Ge;
+ break;
+ }
+ default: SynErr(117); break;
+ }
+ }
+
+ void Term(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
+ Factor(out e0);
+ while (la.kind == 74 || la.kind == 75) {
+ AddOp(out x, out op);
+ Factor(out e1);
+ e0 = Expr.Binary(x, op, e0, e1);
+ }
+ }
+
+ void Factor(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op;
+ Power(out e0);
+ while (StartOf(13)) {
+ MulOp(out x, out op);
+ Power(out e1);
+ e0 = Expr.Binary(x, op, e0, e1);
+ }
+ }
+
+ void AddOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
+ Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
+ if (la.kind == 74) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Add;
+ } else if (la.kind == 75) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Sub;
+ } else SynErr(118);
+ }
+
+ void Power(out Expr/*!*/ e0) {
+ Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1;
+ UnaryExpression(out e0);
+ if (la.kind == 79) {
+ Get();
+ x = t;
+ Power(out e1);
+ e0 = Expr.Binary(x, BinaryOperator.Opcode.Pow, e0, e1);
+ }
+ }
+
+ void MulOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) {
+ Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
+ if (la.kind == 44) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Mul;
+ } else if (la.kind == 76) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Div;
+ } else if (la.kind == 77) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.Mod;
+ } else if (la.kind == 78) {
+ Get();
+ x = t; op=BinaryOperator.Opcode.RealDiv;
+ } else SynErr(119);
+ }
+
+ void UnaryExpression(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ e = dummyExpr;
+
+ if (la.kind == 75) {
+ Get();
+ x = t;
+ UnaryExpression(out e);
+ e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e);
+ } else if (la.kind == 80 || la.kind == 81) {
+ NegOp();
+ x = t;
+ UnaryExpression(out e);
+ e = Expr.Unary(x, UnaryOperator.Opcode.Not, e);
+ } else if (StartOf(14)) {
+ CoercionExpression(out e);
+ } else SynErr(120);
+ }
+
+ void NegOp() {
+ if (la.kind == 80) {
+ Get();
+ } else if (la.kind == 81) {
+ Get();
+ } else SynErr(123);
+ }
+
+ void CoercionExpression(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ Bpl.Type/*!*/ coercedTo;
+ BigNum bn;
+
+ ArrayExpression(out e);
+ while (la.kind == 11) {
+ Get();
+ x = t;
+ if (StartOf(6)) {
+ Type(out coercedTo);
+ e = Expr.CoerceType(x, e, coercedTo);
+ } else if (la.kind == 3) {
+ Nat(out bn);
+ if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
+ this.SemErr("arguments of extract need to be integer literals");
+ e = new BvBounds(x, bn, BigNum.ZERO);
+ } else {
+ e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
+ }
+
+ } else SynErr(124);
+ }
+ }
+
+ void ArrayExpression(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
+ Expr/*!*/ index0 = dummyExpr; Expr/*!*/ e1;
+ bool store; bool bvExtract;
+ List<Expr>/*!*/ allArgs = dummyExprSeq;
+
+ AtomExpression(out e);
+ while (la.kind == 17) {
+ Get();
+ x = t; allArgs = new List<Expr> ();
+ allArgs.Add(e);
+ store = false; bvExtract = false;
+ if (StartOf(15)) {
+ if (StartOf(9)) {
+ Expression(out index0);
+ if (index0 is BvBounds)
+ bvExtract = true;
+ else
+ allArgs.Add(index0);
+
+ while (la.kind == 12) {
+ Get();
+ Expression(out e1);
+ if (bvExtract || e1 is BvBounds)
+ this.SemErr("bitvectors only have one dimension");
+ allArgs.Add(e1);
+
+ }
+ if (la.kind == 50) {
+ Get();
+ Expression(out e1);
+ if (bvExtract || e1 is BvBounds)
+ this.SemErr("assignment to bitvectors is not possible");
+ allArgs.Add(e1); store = true;
+
+ }
+ } else {
+ Get();
+ Expression(out e1);
+ allArgs.Add(e1); store = true;
+ }
+ }
+ Expect(18);
+ if (store)
+ e = new NAryExpr(x, new MapStore(x, allArgs.Count - 2), allArgs);
+ else if (bvExtract)
+ e = new BvExtractExpr(x, e,
+ ((BvBounds)index0).Upper.ToIntSafe,
+ ((BvBounds)index0).Lower.ToIntSafe);
+ else
+ e = new NAryExpr(x, new MapSelect(x, allArgs.Count - 1), allArgs);
+
+ }
+ }
+
+ void Nat(out BigNum n) {
+ Expect(3);
+ try {
+ n = BigNum.FromString(t.val);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted number");
+ n = BigNum.ZERO;
+ }
+
+ }
+
+ void AtomExpression(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; BigFloat fp;
+ List<Expr>/*!*/ es; List<Variable>/*!*/ ds; Trigger trig;
+ List<TypeVariable>/*!*/ typeParams;
+ IdentifierExpr/*!*/ id;
+ QKeyValue kv;
+ e = dummyExpr;
+ List<Variable>/*!*/ locals;
+ List<Block/*!*/>/*!*/ blocks;
+
+ switch (la.kind) {
+ case 82: {
+ Get();
+ e = new LiteralExpr(t, false);
+ break;
+ }
+ case 83: {
+ Get();
+ e = new LiteralExpr(t, true);
+ break;
+ }
+ case 3: {
+ Nat(out bn);
+ e = new LiteralExpr(t, bn);
+ break;
+ }
+ case 5: case 6: {
+ Dec(out bd);
+ e = new LiteralExpr(t, bd);
+ break;
+ }
+ case 97: {
+ Float(out fp);
+ e = new LiteralExpr(t, fp);
+ break;
+ }
+ case 2: {
+ BvLit(out bn, out n);
+ e = new LiteralExpr(t, bn, n);
+ break;
+ }
+ case 1: {
+ Ident(out x);
+ id = new IdentifierExpr(x, x.val); e = id;
+ if (la.kind == 9) {
+ Get();
+ if (StartOf(9)) {
+ Expressions(out es);
+ e = new NAryExpr(x, new FunctionCall(id), es);
+ } else if (la.kind == 10) {
+ e = new NAryExpr(x, new FunctionCall(id), new List<Expr>());
+ } else SynErr(125);
+ Expect(10);
+ }
+ break;
+ }
+ case 84: {
+ Get();
+ x = t;
+ Expect(9);
+ Expression(out e);
+ Expect(10);
+ e = new OldExpr(x, e);
+ break;
+ }
+ case 14: {
+ Get();
+ x = t;
+ Expect(9);
+ Expression(out e);
+ Expect(10);
+ e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new List<Expr>{ e });
+ break;
+ }
+ case 15: {
+ Get();
+ x = t;
+ Expect(9);
+ Expression(out e);
+ Expect(10);
+ e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new List<Expr>{ e });
+ break;
+ }
+ case 98: {
+ Get();
+ x = t;
+ Expect(19);
+ Expression(out e);
+ Expect(20);
+ e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToFloat), new List<Expr> { e });
+ break;
+ }
+ case 9: {
+ Get();
+ if (StartOf(9)) {
+ Expression(out e);
+ if (e is BvBounds)
+ this.SemErr("parentheses around bitvector bounds " +
+ "are not allowed");
+ } else if (la.kind == 88 || la.kind == 89) {
+ Forall();
+ x = t;
+ QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
+ if (typeParams.Count + ds.Count > 0)
+ e = new ForallExpr(x, typeParams, ds, kv, trig, e);
+ } else if (la.kind == 90 || la.kind == 91) {
+ Exists();
+ x = t;
+ QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
+ if (typeParams.Count + ds.Count > 0)
+ e = new ExistsExpr(x, typeParams, ds, kv, trig, e);
+ } else if (la.kind == 92 || la.kind == 93) {
+ Lambda();
+ x = t;
+ QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
+ if (trig != null)
+ SemErr("triggers not allowed in lambda expressions");
+ if (typeParams.Count + ds.Count > 0)
+ e = new LambdaExpr(x, typeParams, ds, kv, e);
+ } else SynErr(126);
+ Expect(10);
+ break;
+ }
+ case 40: {
+ IfThenElseExpression(out e);
+ break;
+ }
+ case 85: {
+ CodeExpression(out locals, out blocks);
+ e = new CodeExpr(locals, blocks);
+ break;
+ }
+ default: SynErr(127); break;
+ }
+ }
+
+ void Dec(out BigDec n) {
+ string s = "";
+ if (la.kind == 5) {
+ Get();
+ s = t.val;
+ } else if (la.kind == 6) {
+ Get();
+ s = t.val;
+ } else SynErr(128);
+ try {
+ n = BigDec.FromString(s);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted number");
+ n = BigDec.ZERO;
+ }
+
+ }
+
+ /// <summary>
+ /// Creates a floating point from the current token value
+ /// </summary>
+ /// <param name="n"></param>
+ void Float(out BigFloat n)
+ {
+ try
+ {
+ if (la.kind == 97) {
+ bool negative = false;
+ int exp, sig, size;
+ BigNum exp_val, sig_val, value;
+ //Expected format = float(sign exp_val sig_val) || float<exp sig>(value)
+ Get(); //Skip the float token
+ if (la.val == "(") {
+ Get();
+ if (la.val == "false")
+ negative = false;
+ else if (la.val == "true")
+ negative = true;
+ else
+ throw new FormatException();
+ Get();
+ Expect(12); //,
+ BvLit(out exp_val, out exp);
+ Expect(12);
+ BvLit(out sig_val, out sig);
+ n = new BigFloat(negative, exp_val, sig_val, exp, sig);
+ Expect(10); //)
+ }
+ else if (la.val == "<") {
+ Get();
+ Expect(3);
+ exp = Int32.Parse(t.val);
+ Expect(12);
+ Expect(3);
+ sig = Int32.Parse(t.val);
+ Expect(20); //>
+ Expect(9); //(
+ if (la.kind == 1) { //NaN
+ Get();
+ n = new BigFloat(t.val, exp, sig);
+ }
+ else if (la.kind == 74 || la.kind == 75) { //+ or -
+ Get();
+ String s = t.val;
+ Get();
+ n = new BigFloat(s + t.val, exp, sig);
+ }
+ else {
+ BvLit(out value, out size);
+ n = new BigFloat(value.ToString(), exp, sig);
+ }
+ Expect(10); //)
+ }
+ else {
+ throw new FormatException();
+ }
+ }
+ else {
+ n = BigFloat.ZERO(8, 24);
+ SynErr(137);
+ }
+ }
+ catch (FormatException)
+ {
+ this.SemErr("incorrectly formatted floating point");
+ n = BigFloat.ZERO(8, 24);
+ }
+ }
+
+ void BvLit(out BigNum n, out int m) {
+ Expect(2);
+ int pos = t.val.IndexOf("bv");
+ string a = t.val.Substring(0, pos);
+ string b = t.val.Substring(pos + 2);
+ try {
+ n = BigNum.FromString(a);
+ m = Convert.ToInt32(b);
+ } catch (FormatException) {
+ this.SemErr("incorrectly formatted bitvector");
+ n = BigNum.ZERO;
+ m = 0;
+ }
+
+ }
+
+ void Forall() {
+ if (la.kind == 88) {
+ Get();
+ } else if (la.kind == 89) {
+ Get();
+ } else SynErr(129);
+ }
+
+ void QuantifierBody(IToken/*!*/ q, out List<TypeVariable>/*!*/ typeParams, out List<Variable>/*!*/ ds,
+out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
+ Contract.Requires(q != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ds) != null); Contract.Ensures(Contract.ValueAtReturn(out body) != null);
+ trig = null; typeParams = new List<TypeVariable> ();
+ IToken/*!*/ tok;
+ kv = null;
+ ds = new List<Variable> ();
+
+ if (la.kind == 19) {
+ TypeParams(out tok, out typeParams);
+ if (la.kind == 1 || la.kind == 27) {
+ BoundVars(q, out ds);
+ }
+ } else if (la.kind == 1 || la.kind == 27) {
+ BoundVars(q, out ds);
+ } else SynErr(130);
+ QSep();
+ while (la.kind == 27) {
+ AttributeOrTrigger(ref kv, ref trig);
+ }
+ Expression(out body);
+ }
+
+ void Exists() {
+ if (la.kind == 90) {
+ Get();
+ } else if (la.kind == 91) {
+ Get();
+ } else SynErr(131);
+ }
+
+ void Lambda() {
+ if (la.kind == 92) {
+ Get();
+ } else if (la.kind == 93) {
+ Get();
+ } else SynErr(132);
+ }
+
+ void IfThenElseExpression(out Expr/*!*/ e) {
+ Contract.Ensures(Contract.ValueAtReturn(out e) != null);
+ IToken/*!*/ tok;
+ Expr/*!*/ e0, e1, e2;
+ e = dummyExpr;
+ Expect(40);
+ tok = t;
+ Expression(out e0);
+ Expect(87);
+ Expression(out e1);
+ Expect(41);
+ Expression(out e2);
+ e = new NAryExpr(tok, new IfThenElse(tok), new List<Expr>{ e0, e1, e2 });
+ }
+
+ void CodeExpression(out List<Variable>/*!*/ locals, out List<Block/*!*/>/*!*/ blocks) {
+ Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new List<Variable>(); Block/*!*/ b;
+ blocks = new List<Block/*!*/>();
+
+ Expect(85);
+ while (la.kind == 7) {
+ LocalVars(locals);
+ }
+ SpecBlock(out b);
+ blocks.Add(b);
+ while (la.kind == 1) {
+ SpecBlock(out b);
+ blocks.Add(b);
+ }
+ Expect(86);
+ }
+
+ void SpecBlock(out Block/*!*/ b) {
+ Contract.Ensures(Contract.ValueAtReturn(out b) != null); IToken/*!*/ x; IToken/*!*/ y;
+ Cmd c; IToken label;
+ List<Cmd> cs = new List<Cmd>();
+ List<IToken>/*!*/ xs;
+ List<String> ss = new List<String>();
+ b = dummyBlock;
+ Expr/*!*/ e;
+
+ Ident(out x);
+ Expect(11);
+ while (StartOf(8)) {
+ LabelOrCmd(out c, out label);
+ if (c != null) {
+ Contract.Assert(label == null);
+ cs.Add(c);
+ } else {
+ Contract.Assert(label != null);
+ SemErr("SpecBlock's can only have one label");
+ }
+
+ }
+ if (la.kind == 38) {
+ Get();
+ y = t;
+ Idents(out xs);
+ foreach(IToken/*!*/ s in xs){
+ Contract.Assert(s != null);
+ ss.Add(s.val); }
+ b = new Block(x,x.val,cs,new GotoCmd(y,ss));
+
+ } else if (la.kind == 39) {
+ Get();
+ Expression(out e);
+ b = new Block(x,x.val,cs,new ReturnExprCmd(t,e));
+ } else SynErr(133);
+ Expect(8);
+ }
+
+ void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) {
+ IToken/*!*/ tok; Expr/*!*/ e; List<Expr>/*!*/ es;
+ string key;
+ List<object/*!*/> parameters; object/*!*/ param;
+
+ Expect(27);
+ tok = t;
+ if (la.kind == 11) {
+ Get();
+ Expect(1);
+ key = t.val; parameters = new List<object/*!*/>();
+ if (StartOf(16)) {
+ AttributeParameter(out param);
+ parameters.Add(param);
+ while (la.kind == 12) {
+ Get();
+ AttributeParameter(out param);
+ parameters.Add(param);
+ }
+ }
+ if (key == "nopats") {
+ if (parameters.Count == 1 && parameters[0] is Expr) {
+ e = (Expr)parameters[0];
+ if(trig==null){
+ trig = new Trigger(tok, false, new List<Expr> { e }, null);
+ } else {
+ trig.AddLast(new Trigger(tok, false, new List<Expr> { e }, null));
+ }
+ } else {
+ this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
+ }
+ } else {
+ if (kv==null) {
+ kv = new QKeyValue(tok, key, parameters, null);
+ } else {
+ kv.AddLast(new QKeyValue(tok, key, parameters, null));
+ }
+ }
+
+ } else if (StartOf(9)) {
+ Expression(out e);
+ es = new List<Expr> { e };
+ while (la.kind == 12) {
+ Get();
+ Expression(out e);
+ es.Add(e);
+ }
+ if (trig==null) {
+ trig = new Trigger(tok, true, es, null);
+ } else {
+ trig.AddLast(new Trigger(tok, true, es, null));
+ }
+
+ } else SynErr(134);
+ Expect(28);
+ }
+
+ void AttributeParameter(out object/*!*/ o) {
+ Contract.Ensures(Contract.ValueAtReturn(out o) != null);
+ o = "error";
+ Expr/*!*/ e;
+
+ if (la.kind == 4) {
+ Get();
+ o = t.val.Substring(1, t.val.Length-2);
+ } else if (StartOf(9)) {
+ Expression(out e);
+ o = e;
+ } else SynErr(135);
+ }
+
+ void QSep() {
+ if (la.kind == 94) {
+ Get();
+ } else if (la.kind == 95) {
+ Get();
+ } else SynErr(136);
+ }
+
+
+
+ public void Parse() {
+ la = new Token();
+ la.val = "";
+ Get();
+ BoogiePL();
+ Expect(0);
+
+ Expect(0);
+ }
+
+ static readonly bool[,]/*!*/ set = { //grid is 17 x 100
+ {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,x,x, x,T,T,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x},
+ {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x},
+ {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, T,x,T,x, x,T,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x},
+ {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,T,T,T, T,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x}
+
+ };
+} // end Parser
+
+
+public class Errors {
+ public int count = 0; // number of errors detected
+ public System.IO.TextWriter/*!*/ errorStream = Console.Out; // error messages go to this stream
+ public string errMsgFormat = "{0}({1},{2}): error: {3}"; // 0=filename, 1=line, 2=column, 3=text
+ public string warningMsgFormat = "{0}({1},{2}): warning: {3}"; // 0=filename, 1=line, 2=column, 3=text
+
+ public void SynErr(string filename, int line, int col, int n) {
+ SynErr(filename, line, col, GetSyntaxErrorString(n));
+ }
+
+ public virtual void SynErr(string filename, int line, int col, string/*!*/ msg) {
+ Contract.Requires(msg != null);
+ errorStream.WriteLine(errMsgFormat, filename, line, col, msg);
+ count++;
+ }
+
+ /// <summary>
+ /// Returns a string corresponding to the syntax error of the given type
+ /// Note that many of these errors (0-98) correspond to token types (e.g. the la token)
+ /// </summary>
+ /// <param name="n"></param>
+ /// <returns></returns>
+ string GetSyntaxErrorString(int n) {
+ string s;
+ switch (n) {
+ case 0: s = "EOF expected"; break;
+ case 1: s = "ident expected"; break;
+ case 2: s = "bvlit expected"; break;
+ case 3: s = "digits expected"; break;
+ case 4: s = "string expected"; break;
+ case 5: s = "decimal expected"; break;
+ case 6: s = "float expected"; break;
+ case 7: s = "\"var\" expected"; break;
+ case 8: s = "\";\" expected"; break;
+ case 9: s = "\"(\" expected"; break;
+ case 10: s = "\")\" expected"; break;
+ case 11: s = "\":\" expected"; break;
+ case 12: s = "\",\" expected"; break;
+ case 13: s = "\"where\" expected"; break;
+ case 14: s = "\"int\" expected"; break;
+ case 15: s = "\"real\" expected"; break;
+ case 16: s = "\"bool\" expected"; break;
+ case 17: s = "\"[\" expected"; break;
+ case 18: s = "\"]\" expected"; break;
+ case 19: s = "\"<\" expected"; break;
+ case 20: s = "\">\" expected"; break;
+ case 21: s = "\"const\" expected"; break;
+ case 22: s = "\"unique\" expected"; break;
+ case 23: s = "\"extends\" expected"; break;
+ case 24: s = "\"complete\" expected"; break;
+ case 25: s = "\"function\" expected"; break;
+ case 26: s = "\"returns\" expected"; break;
+ case 27: s = "\"{\" expected"; break;
+ case 28: s = "\"}\" expected"; break;
+ case 29: s = "\"axiom\" expected"; break;
+ case 30: s = "\"type\" expected"; break;
+ case 31: s = "\"=\" expected"; break;
+ case 32: s = "\"procedure\" expected"; break;
+ case 33: s = "\"implementation\" expected"; break;
+ case 34: s = "\"modifies\" expected"; break;
+ case 35: s = "\"free\" expected"; break;
+ case 36: s = "\"requires\" expected"; break;
+ case 37: s = "\"ensures\" expected"; break;
+ case 38: s = "\"goto\" expected"; break;
+ case 39: s = "\"return\" expected"; break;
+ case 40: s = "\"if\" expected"; break;
+ case 41: s = "\"else\" expected"; break;
+ case 42: s = "\"while\" expected"; break;
+ case 43: s = "\"invariant\" expected"; break;
+ case 44: s = "\"*\" expected"; break;
+ case 45: s = "\"break\" expected"; break;
+ case 46: s = "\"assert\" expected"; break;
+ case 47: s = "\"assume\" expected"; break;
+ case 48: s = "\"havoc\" expected"; break;
+ case 49: s = "\"yield\" expected"; break;
+ case 50: s = "\":=\" expected"; break;
+ case 51: s = "\"async\" expected"; break;
+ case 52: s = "\"call\" expected"; break;
+ case 53: s = "\"par\" expected"; break;
+ case 54: s = "\"|\" expected"; break;
+ case 55: s = "\"<==>\" expected"; break;
+ case 56: s = "\"\\u21d4\" expected"; break;
+ case 57: s = "\"==>\" expected"; break;
+ case 58: s = "\"\\u21d2\" expected"; break;
+ case 59: s = "\"<==\" expected"; break;
+ case 60: s = "\"\\u21d0\" expected"; break;
+ case 61: s = "\"&&\" expected"; break;
+ case 62: s = "\"\\u2227\" expected"; break;
+ case 63: s = "\"||\" expected"; break;
+ case 64: s = "\"\\u2228\" expected"; break;
+ case 65: s = "\"==\" expected"; break;
+ case 66: s = "\"<=\" expected"; break;
+ case 67: s = "\">=\" expected"; break;
+ case 68: s = "\"!=\" expected"; break;
+ case 69: s = "\"<:\" expected"; break;
+ case 70: s = "\"\\u2260\" expected"; break;
+ case 71: s = "\"\\u2264\" expected"; break;
+ case 72: s = "\"\\u2265\" expected"; break;
+ case 73: s = "\"++\" expected"; break;
+ case 74: s = "\"+\" expected"; break;
+ case 75: s = "\"-\" expected"; break;
+ case 76: s = "\"div\" expected"; break;
+ case 77: s = "\"mod\" expected"; break;
+ case 78: s = "\"/\" expected"; break;
+ case 79: s = "\"**\" expected"; break;
+ case 80: s = "\"!\" expected"; break;
+ case 81: s = "\"\\u00ac\" expected"; break;
+ case 82: s = "\"false\" expected"; break;
+ case 83: s = "\"true\" expected"; break;
+ case 84: s = "\"old\" expected"; break;
+ case 85: s = "\"|{\" expected"; break;
+ case 86: s = "\"}|\" expected"; break;
+ case 87: s = "\"then\" expected"; break;
+ case 88: s = "\"forall\" expected"; break;
+ case 89: s = "\"\\u2200\" expected"; break;
+ case 90: s = "\"exists\" expected"; break;
+ case 91: s = "\"\\u2203\" expected"; break;
+ case 92: s = "\"lambda\" expected"; break;
+ case 93: s = "\"\\u03bb\" expected"; break;
+ case 94: s = "\"::\" expected"; break;
+ case 95: s = "\"\\u2022\" expected"; break;
+ case 96: s = "??? expected"; break;
+ case 97: s = "fp expected"; break;
+ case 98: s = "\"float\" expected"; break;
+ case 99: s = "invalid Function"; break;
+ case 100: s = "invalid Function"; break;
+ case 101: s = "invalid Procedure"; break;
+ case 102: s = "invalid Type"; break;
+ case 103: s = "invalid TypeAtom"; break;
+ case 104: s = "invalid TypeArgs"; break;
+ case 105: s = "invalid Spec"; break;
+ case 106: s = "invalid SpecPrePost"; break;
+ case 107: s = "invalid LabelOrCmd"; break;
+ case 108: s = "invalid StructuredCmd"; break;
+ case 109: s = "invalid TransferCmd"; break;
+ case 110: s = "invalid IfCmd"; break;
+ case 111: s = "invalid Guard"; break;
+ case 112: s = "invalid LabelOrAssign"; break;
+ case 113: s = "invalid CallParams"; break;
+ case 114: s = "invalid EquivOp"; break;
+ case 115: s = "invalid ImpliesOp"; break;
+ case 116: s = "invalid ExpliesOp"; break;
+ case 117: s = "invalid AndOp"; break;
+ case 118: s = "invalid OrOp"; break;
+ case 119: s = "invalid RelOp"; break;
+ case 120: s = "invalid AddOp"; break;
+ case 121: s = "invalid MulOp"; break;
+ case 122: s = "invalid UnaryExpression"; break;
+ case 123: s = "invalid NegOp"; break;
+ case 124: s = "invalid CoercionExpression"; break;
+ case 125: s = "invalid AtomExpression"; break;
+ case 126: s = "invalid AtomExpression"; break;
+ case 127: s = "invalid AtomExpression"; break;
+ case 128: s = "invalid Dec"; break;
+ case 129: s = "invalid Forall"; break;
+ case 130: s = "invalid QuantifierBody"; break;
+ case 131: s = "invalid Exists"; break;
+ case 132: s = "invalid Lambda"; break;
+ case 133: s = "invalid SpecBlock"; break;
+ case 134: s = "invalid AttributeOrTrigger"; break;
+ case 135: s = "invalid AttributeParameter"; break;
+ case 136: s = "invalid QSep"; break;
+ case 137: s = "invalid Float"; break;
+
+ default: s = "error " + n; break;
+ }
+ return s;
+ }
+
+ public void SemErr(IToken/*!*/ tok, string/*!*/ msg) { // semantic errors
+ Contract.Requires(tok != null);
+ Contract.Requires(msg != null);
+ SemErr(tok.filename, tok.line, tok.col, msg);
+ }
+
+ public virtual void SemErr(string filename, int line, int col, string/*!*/ msg) {
+ Contract.Requires(msg != null);
+ errorStream.WriteLine(errMsgFormat, filename, line, col, msg);
+ count++;
+ }
+
+ public void Warning(IToken/*!*/ tok, string/*!*/ msg) { // warnings
+ Contract.Requires(tok != null);
+ Contract.Requires(msg != null);
+ Warning(tok.filename, tok.line, tok.col, msg);
+ }
+
+ public virtual void Warning(string filename, int line, int col, string msg) {
+ Contract.Requires(msg != null);
+ errorStream.WriteLine(warningMsgFormat, filename, line, col, msg);
+ }
+} // Errors
+
+
+public class FatalError: Exception {
+ public FatalError(string m): base(m) {}
+}
+
+
} \ No newline at end of file
diff --git a/Source/Core/Readme.txt b/Source/Core/Readme.txt
index 1b0606a6..dfdd8050 100644
--- a/Source/Core/Readme.txt
+++ b/Source/Core/Readme.txt
@@ -1,61 +1,61 @@
-// ----------------------------------------------------------------------------
-// Boogie-PL
-//
-// Readme
-// ws 5/9/03
-// ----------------------------------------------------------------------------
-
-
-This directory cointains the Boogie Procedural Language (BoogiePL)
-implementataion and "1" sample program.
-
-
-Scanner and parser are generated with Coco (ann LL1 parser generator for EBNFs)
-(see http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/CSharp/)
-
- The input file is
- BoogiePL.atg
- then simply call
- ..\Coco\bin\Debug\Coco.exe BoogiePL.atg
- it then uses (as input)
- Scanner.frame
- Parser.frame
- as templates to generate an LL1 parser into
- Scanner.cs
- Parser.cs
- as output
-
-The Csharp excutable then contains
-
- BoogiePL.cs -- main program
- Absy -- abstract syntax for BoogiePL
- Error.cs -- error handling (contains still some oldstuff)
- Parser.cs -- generated parser
- Scanner.cs -- generated scanner
- PureCollections.cs -- sets/maps/tuples/ (contains still some oldstuff)
-
-The directory Samples contains one parsing example
- Parsing1.pl
-Please check it for the syntax, alternatively consult BoogiePL.atg
-
-Here is its output:
- C:\Boogie> bin\debug\Boogiepl.exe samples\Parsing1.pl
-
- Boogie Procedural Language Version 0.1 Copyright (c) Microsoft 2003
- Parsing samples\Parsing1.pl <<<=== here is what is does
- 0 errors detected
-
-Things left to do:
-
- BoogiePL needs a tiny context analysis
- checking names, updates, arities, OLD, etc.
- (ws will do until 5/8)
-
- BoogiePL Absy might be too flexible
- simplify (if one things so..) (Mike/Rustan will do)
-
- BoogiePL needs more examples/experiences
- (all of us..)
-
-
-
+// ----------------------------------------------------------------------------
+// Boogie-PL
+//
+// Readme
+// ws 5/9/03
+// ----------------------------------------------------------------------------
+
+
+This directory cointains the Boogie Procedural Language (BoogiePL)
+implementataion and "1" sample program.
+
+
+Scanner and parser are generated with Coco (ann LL1 parser generator for EBNFs)
+(see http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/CSharp/)
+
+ The input file is
+ BoogiePL.atg
+ then simply call
+ ..\Coco\bin\Debug\Coco.exe BoogiePL.atg
+ it then uses (as input)
+ Scanner.frame
+ Parser.frame
+ as templates to generate an LL1 parser into
+ Scanner.cs
+ Parser.cs
+ as output
+
+The Csharp excutable then contains
+
+ BoogiePL.cs -- main program
+ Absy -- abstract syntax for BoogiePL
+ Error.cs -- error handling (contains still some oldstuff)
+ Parser.cs -- generated parser
+ Scanner.cs -- generated scanner
+ PureCollections.cs -- sets/maps/tuples/ (contains still some oldstuff)
+
+The directory Samples contains one parsing example
+ Parsing1.pl
+Please check it for the syntax, alternatively consult BoogiePL.atg
+
+Here is its output:
+ C:\Boogie> bin\debug\Boogiepl.exe samples\Parsing1.pl
+
+ Boogie Procedural Language Version 0.1 Copyright (c) Microsoft 2003
+ Parsing samples\Parsing1.pl <<<=== here is what is does
+ 0 errors detected
+
+Things left to do:
+
+ BoogiePL needs a tiny context analysis
+ checking names, updates, arities, OLD, etc.
+ (ws will do until 5/8)
+
+ BoogiePL Absy might be too flexible
+ simplify (if one things so..) (Mike/Rustan will do)
+
+ BoogiePL needs more examples/experiences
+ (all of us..)
+
+
+
diff --git a/Source/Core/ResolutionContext.cs b/Source/Core/ResolutionContext.cs
index bf1a5629..279e00bf 100644
--- a/Source/Core/ResolutionContext.cs
+++ b/Source/Core/ResolutionContext.cs
@@ -1,629 +1,641 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
- using System.Collections;
- using System.Collections.Generic;
- using System;
- using System.Linq;
- using System.Diagnostics.Contracts;
-
- [ContractClass(typeof(IErrorSinkContracts))]
- public interface IErrorSink {
- void Error(IToken/*!*/ tok, string/*!*/ msg);
- }
- [ContractClassFor(typeof(IErrorSink))]
- public abstract class IErrorSinkContracts : IErrorSink {
- #region IErrorSink Members
- public void Error(IToken tok, string msg) {
- Contract.Requires(tok != null);
- Contract.Requires(msg != null);
- throw new NotImplementedException();
- }
- #endregion
- }
-
- public class CheckingContext {
- // ------------------------------ Error counting ------------------------------
-
- IErrorSink errorSink;
- int errors;
-
- public CheckingContext(IErrorSink errorSink) {
- this.errorSink = errorSink;
- }
-
- public int ErrorCount {
- get {
- return errors;
- }
- set {
- errors = value;
- }
- }
-
- public void Error(Absy subject, string msg, params object[] args) {
- Contract.Requires(args != null);
- Contract.Requires(msg != null);
- Contract.Requires(subject != null);
- Error(subject.tok, msg, args);
- }
-
- public virtual void Error(IToken tok, string msg) {
- Contract.Requires(msg != null);
- Contract.Requires(tok != null);
- errors++;
- if (errorSink == null) {
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine("{0}({1},{2}): Error: {3}",
- tok.filename, tok.line, tok.col - 1,
- msg);
- Console.ForegroundColor = col;
- } else {
- errorSink.Error(tok, msg);
- }
- }
-
- private string Format(string msg, params object[] args) {
- Contract.Requires(msg != null);
- Contract.Ensures(Contract.Result<string>() != null);
- if (System.Type.GetType("Mono.Runtime") != null) { // MONO
- // something in mono seems to be broken so that calling
- // NamedDeclarations.ToString (and similar ToString methods)
- // causes a stack overflow. We therefore convert those to
- // strings by hand
- object[] fixedArgs = new object[cce.NonNull(args).Length];
- for (int i = 0; i < args.Length; ++i) {
- if (args[i] is NamedDeclaration) {
- fixedArgs[i] = cce.NonNull((NamedDeclaration)args[i]).Name;
- } else if (args[i] is Type) {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
- cce.NonNull((Type)args[i]).Emit(stream);
- }
- fixedArgs[i] = buffer.ToString();
- } else if (args[i] is Expr) {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
- cce.NonNull((Expr/*!*/)args[i]).Emit(stream, 0, false);
- }
- fixedArgs[i] = buffer.ToString();
- } else {
- fixedArgs[i] = args[i];
- }
- }
- args = fixedArgs;
- }
- return string.Format(msg, args);
- }
-
- public void Error(IToken tok, string msg, params object[] args) {
- Contract.Requires(msg != null);
- Contract.Requires(tok != null);
- Error(tok, Format(msg, args));
- }
-
- public void Warning(Absy subject, string msg, params object[] args) {
- Contract.Requires(args != null);
- Contract.Requires(msg != null);
- Contract.Requires(subject != null);
- Warning(subject.tok, msg, args);
- }
-
- public virtual void Warning(IToken tok, string msg) {
- Contract.Requires(msg != null);
- Contract.Requires(tok != null);
- // warnings are currently always written to the console
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- Console.WriteLine("{0}({1},{2}): Warning: {3}",
- tok.filename, tok.line, tok.col - 1,
- msg);
- Console.ForegroundColor = col;
- }
-
- public void Warning(IToken tok, string msg, params object[] args) {
- Contract.Requires(msg != null);
- Contract.Requires(tok != null);
- Warning(tok, Format(msg, args));
- }
- }
-
- public class ResolutionContext : CheckingContext {
- public ResolutionContext(IErrorSink errorSink)
- : base(errorSink) {
- }
-
- // ------------------------------ Boogie 2 Types -------------------------
-
- // user-defined types, which can be either TypeCtorDecl or TypeSynonymDecl
- Hashtable /*string->NamedDeclaration*//*!*/ types = new Hashtable /*string->NamedDeclaration*/ ();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(types != null);
- Contract.Invariant(cce.NonNullElements(typeBinders));
- Contract.Invariant(varContext != null);
- Contract.Invariant(funcdures != null);
- }
-
-
- /// <summary>
- /// Checks if name coincides with the name of a bitvector type. If so, reports an error and
- /// returns true; otherwise, returns false.
- /// </summary>
- private bool CheckBvNameClashes(Absy absy, string name) {
- Contract.Requires(name != null);
- Contract.Requires(absy != null);
- if (name.StartsWith("bv") && name.Length > 2) {
- for (int i = 2; i < name.Length; ++i)
- if (!char.IsDigit(name[i]))
- return false;
- Error(absy, "type name: {0} is registered for bitvectors", name);
- return true;
- }
- return false;
- }
-
- public void AddType(NamedDeclaration td) {
- Contract.Requires(td != null);
- Contract.Requires((td is TypeCtorDecl) || (td is TypeSynonymDecl));
- Contract.Requires(td.Name != null);
-
- string name = td.Name;
- if (CheckBvNameClashes(td, name))
- return; // error has already been reported
-
- var previous = (NamedDeclaration)types[name];
- if (previous == null) {
- types.Add(name, td);
- } else {
- var r = (NamedDeclaration)SelectNonExtern(td, previous);
- if (r == null) {
- Error(td, "more than one declaration of type name: {0}", name);
- } else {
- types[name] = r;
- }
- }
- }
-
- /// <summary>
- /// Returns the declaration of the named type, or null if
- /// no such type is declared. Also return null if the type
- /// declared with the given name is not a constructor but a
- /// type synonym
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public TypeCtorDecl LookUpType(string name) {
- Contract.Requires(name != null);
- return types[name] as TypeCtorDecl;
- }
-
- public TypeSynonymDecl LookUpTypeSynonym(string name) {
- Contract.Requires(name != null);
- return types[name] as TypeSynonymDecl;
- }
-
- // ------------------------------ Boogie 2 Type Binders ------------------------------
-
- List<TypeVariable/*!*/>/*!*/ typeBinders = new List<TypeVariable/*!*/>(5);
-
- public void AddTypeBinder(TypeVariable td) {
- Contract.Requires(td != null);
- if (CheckBvNameClashes(td, td.Name)) {
- return;
- }
- if (types.ContainsKey(td.Name)) {
- Error(td, "name is already reserved for type constructor: {0}", td.Name);
- return;
- }
- for (int i = 0; i < typeBinders.Count; i++) {
- if (typeBinders[i].Name == td.Name) {
- Error(td, "more than one declaration of type variable: {0}", td.Name);
- return;
- }
- }
- typeBinders.Add(td);
- }
-
- public int TypeBinderState {
- get {
- return typeBinders.Count;
- }
- set {
- typeBinders.RemoveRange(value, typeBinders.Count - value);
- }
- }
-
- /// <summary>
- /// Returns the declaration of the named type binder, or null if
- /// no such binder is declared.
- /// </summary>
- public TypeVariable LookUpTypeBinder(string name) {
- Contract.Requires(name != null);
- for (int i = typeBinders.Count; 0 <= --i; ) {
- TypeVariable/*!*/ td = typeBinders[i];
- Contract.Assert(td != null);
- if (td.Name == name) {
- return td;
- }
- }
- return null; // not present
- }
-
- // ------------------------------ Variables ------------------------------
-
- class VarContextNode {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(VarSymbols != null);
- }
-
- public readonly Hashtable /*string->Variable*//*!*/ VarSymbols = new Hashtable /*string->Variable*/();
- public /*maybe null*/ VarContextNode ParentContext;
- public readonly bool Opaque;
- readonly ISet<string> assignedAssumptionVariables = new HashSet<string>();
-
- public bool HasVariableBeenAssigned(string name)
- {
- Contract.Requires(name != null);
-
- if (assignedAssumptionVariables.Contains(name))
- {
- return true;
- }
- else if (ParentContext != null)
- {
- return ParentContext.HasVariableBeenAssigned(name);
- }
- else
- {
- return false;
- }
- }
-
- public bool MarkVariableAsAssigned(string name)
- {
- Contract.Requires(name != null);
-
- if (VarSymbols.Contains(name))
- {
- if (assignedAssumptionVariables.Contains(name))
- {
- return false;
- }
- assignedAssumptionVariables.Add(name);
- return true;
- }
- else if (ParentContext != null)
- {
- return ParentContext.MarkVariableAsAssigned(name);
- }
- else
- {
- return false;
- }
- }
-
- public VarContextNode(/*maybe null*/ VarContextNode parentContext, bool opaque) {
- ParentContext = parentContext;
- Opaque = opaque;
- }
- }
-
- // symbolic constants, global variables, local variables, formals, expression-bound variables
- VarContextNode/*!*/ varContext = new VarContextNode(null, false);
-
- /// <summary>
- /// Adds a variable context.
- /// </summary>
- public void PushVarContext() {
- varContext = new VarContextNode(varContext, false);
- }
-
- /// <summary>
- /// Adds an opaque variable context, that is, one that blocks all previously pushed contexts.
- /// </summary>
- public void PushOpaqueVarContext() {
- varContext = new VarContextNode(varContext, true);
- }
-
- /// <summary>
- /// Requires there to be more than one variable context.
- /// </summary>
- public void PopVarContext() {
- Contract.Assert(varContext.ParentContext != null);
- varContext = varContext.ParentContext;
- }
-
- public void AddVariable(Variable var, bool global) {
- Contract.Requires(var != null);
- var previous = FindVariable(cce.NonNull(var.Name), !global);
- if (previous == null) {
- varContext.VarSymbols.Add(var.Name, var);
- } else {
- var r = (Variable)SelectNonExtern(var, previous);
- if (r == null) {
- Error(var, "more than one declaration of variable name: {0}", var.Name);
- } else {
- varContext.VarSymbols[var.Name] = r;
- }
- }
- }
-
- /// <summary>
- /// Returns the declaration of the named variable, or null if
- /// no such variable is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public Variable LookUpVariable(string name) {
- Contract.Requires(name != null);
- return FindVariable(name, false);
- }
-
- Variable FindVariable(string name, bool ignoreTopLevelVars) {
- Contract.Requires(name != null);
- VarContextNode c = varContext;
- bool lookOnlyForConstants = false;
- do {
- if (ignoreTopLevelVars && c.ParentContext == null) {
- // this is the top level and we're asked to ignore the top level; hence, we're done
- break;
- }
-
- Variable var = (Variable)c.VarSymbols[name];
- if (var != null && (!lookOnlyForConstants || var is Constant)) {
- return var;
- }
- // not at this level
-
- if (c.Opaque) {
- // from here on, only constants can be looked up
- lookOnlyForConstants = true;
- }
- c = c.ParentContext;
- } while (c != null);
-
- // not present in the relevant levels
- return null;
- }
-
- public bool HasVariableBeenAssigned(string name)
- {
- Contract.Requires(name != null);
-
- return varContext.HasVariableBeenAssigned(name);
- }
-
- public void MarkVariableAsAssigned(string name)
- {
- Contract.Requires(name != null);
-
- var success = varContext.MarkVariableAsAssigned(name);
- Contract.Assume(success);
- }
-
- Hashtable axioms = new Hashtable();
-
- public void AddAxiom(Axiom axiom) {
- string axiomName = QKeyValue.FindStringAttribute(axiom.Attributes, "name");
- if (axiomName == null)
- return;
- var previous = (Axiom)axioms[axiomName];
- if (previous == null) {
- axioms.Add(axiomName, axiom);
- }
- else {
- var r = (Axiom)SelectNonExtern(axiom, previous);
- if (r == null) {
- Error(axiom, "more than one declaration of axiom name: {0}", axiomName);
- }
- else {
- axioms[axiomName] = r;
- }
- }
- }
-
- // ------------------------------ Functions/Procedures ------------------------------
-
- // uninterpreted function symbols, procedures
- Hashtable /*string->DeclWithFormals*//*!*/ funcdures = new Hashtable /*string->DeclWithFormals*/ ();
-
- public void AddProcedure(DeclWithFormals proc) {
- Contract.Requires(proc != null);
- Contract.Requires(proc.Name != null);
-
- string name = proc.Name;
- var previous = (DeclWithFormals)funcdures[name];
- if (previous == null) {
- funcdures.Add(name, proc);
- } else {
- var r = (DeclWithFormals)SelectNonExtern(proc, previous);
- if (r == null) {
- Error(proc, "more than one declaration of function/procedure name: {0}", name);
- } else {
- funcdures[name] = r;
- }
- }
- }
-
- /// <summary>
- /// If both "a" and "b" have an ":extern" attribute, returns either one.
- /// If one of "a" and "b" has an ":extern" attribute, returns that one.
- /// If neither of "a" and "b" has an ":extern" attribute, returns null.
- /// If a non-value value is returned, this method also adds the ":ignore"
- /// attribute to the declaration NOT returned.
- /// </summary>
- Declaration SelectNonExtern(Declaration a, Declaration b) {
- Contract.Requires(a != null);
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<Declaration>() == null || Contract.Result<Declaration>() == a || Contract.Result<Declaration>() == b);
-
- Declaration ignore, keep;
- if (QKeyValue.FindBoolAttribute(a.Attributes, "extern")) {
- ignore = a;
- keep = b;
- } else if (QKeyValue.FindBoolAttribute(b.Attributes, "extern")) {
- ignore = b;
- keep = a;
- } else {
- return null;
- }
- // prepend :ignore attribute
- ignore.Attributes = new QKeyValue(ignore.tok, "ignore", new List<object/*!*/>(), ignore.Attributes);
- return keep;
- }
-
- /// <summary>
- /// Returns the declaration of the named function/procedure, or null if
- /// no such function or procedure is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public DeclWithFormals LookUpProcedure(string name) {
- Contract.Requires(name != null);
- return (DeclWithFormals)funcdures[name];
- }
-
- // ------------------------------ Blocks ------------------------------
-
- class ProcedureContext {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Blocks != null);
- }
-
- public readonly Hashtable/*!*/ /*string->Block!*/ Blocks;
- public readonly ProcedureContext Next;
- public ProcedureContext(ProcedureContext next) {
- Blocks = new Hashtable /*string->Block!*/ ();
- Next = next;
- }
- }
- /*maybe null*/
- ProcedureContext procedureContext; // stack of procedure contexts
- public bool HasProcedureContext {
- get {
- return procedureContext != null;
- }
- }
-
- /// <summary>
- /// Pushes a new procedure context.
- /// </summary>
- public void PushProcedureContext() {
- Contract.Ensures(HasProcedureContext);
- procedureContext = new ProcedureContext(procedureContext);
- }
-
- /// <summary>
- /// Requires there to be a procedure context. Pops it.
- /// </summary>
- public void PopProcedureContext() {
- Contract.Requires(HasProcedureContext);
- Contract.Assert(procedureContext != null); // follows from precondition
- procedureContext = procedureContext.Next;
- }
-
- /// <summary>
- /// Requires there to be a procedure context.
- /// </summary>
- /// <param name="block"></param>
- public void AddBlock(Block block) {
- Contract.Requires(block != null);
- Contract.Requires(HasProcedureContext);
- Contract.Assert(procedureContext != null); // follows from precondition
- Hashtable/*!*/ /*string->Block!*/ blocks = procedureContext.Blocks;
- Contract.Assert(blocks != null);
- if (blocks[block.Label] != null) {
- Error(block, "more than one declaration of block name: {0}", block.Label);
- } else {
- blocks.Add(block.Label, block);
- }
- }
-
- /// <summary>
- /// Requires there to be a procedure context.
- /// Returns the declaration of the named block, or null if
- /// no such block is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public Block LookUpBlock(string name) {
- Contract.Requires(name != null);
- Contract.Requires(HasProcedureContext);
- Contract.Assert(procedureContext != null); // follows from precondition
- Hashtable/*!*/ /*string->Block!*/ blocks = procedureContext.Blocks;
- Contract.Assert(blocks != null);
- return (Block)blocks[name];
- }
-
- // ------------------------------ Flags ------------------------------
-
- public enum State {
- StateLess,
- Single,
- Two
- }
- State stateMode = State.Single;
-
- /// <summary>
- /// To increase our confidence in that the caller knows what it's doing, we only allow
- /// the state mode to be changed in and out of the State.Single mode.
- /// </summary>
- public State StateMode {
- get {
- return stateMode;
- }
- set {
- Contract.Assert(value != stateMode);
- Contract.Assert(stateMode == State.Single || value == State.Single);
- cce.BeginExpose(this);
- {
- stateMode = value;
- }
- cce.EndExpose();
- }
- }
-
- bool triggerMode = false;
-
- /// <summary>
- /// Setting TriggerMode is allowed only if the setting has the effect of toggling the
- /// boolean. That is, TriggerMode can be set to true only if it previously was false,
- /// and TriggerMode can be set to false only if it previously was true.
- /// </summary>
- public bool TriggerMode {
- get {
- return triggerMode;
- }
- set {
- Contract.Assert(triggerMode != value);
- cce.BeginExpose(this);
- {
- triggerMode = value;
- }
- cce.EndExpose();
- }
- }
- }
-
- public class TypecheckingContext : CheckingContext {
- public List<IdentifierExpr> Frame; // used in checking the assignment targets of implementation bodies
- public bool Yields;
-
- public TypecheckingContext(IErrorSink errorSink)
- : base(errorSink) {
- }
-
- public bool InFrame(Variable v) {
- Contract.Requires(v != null);
- Contract.Requires(Frame != null);
- return Frame.Any(f => f.Decl == v);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+ using System.Collections;
+ using System.Collections.Generic;
+ using System;
+ using System.Linq;
+ using System.Diagnostics.Contracts;
+
+ [ContractClass(typeof(IErrorSinkContracts))]
+ public interface IErrorSink {
+ void Error(IToken/*!*/ tok, string/*!*/ msg);
+ }
+ [ContractClassFor(typeof(IErrorSink))]
+ public abstract class IErrorSinkContracts : IErrorSink {
+ #region IErrorSink Members
+ public void Error(IToken tok, string msg) {
+ Contract.Requires(tok != null);
+ Contract.Requires(msg != null);
+ throw new NotImplementedException();
+ }
+ #endregion
+ }
+
+ public class CheckingContext {
+ // ------------------------------ Error counting ------------------------------
+
+ IErrorSink errorSink;
+ int errors;
+
+ public CheckingContext(IErrorSink errorSink) {
+ this.errorSink = errorSink;
+ }
+
+ public int ErrorCount {
+ get {
+ return errors;
+ }
+ set {
+ errors = value;
+ }
+ }
+
+ public void Error(Absy subject, string msg, params object[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(msg != null);
+ Contract.Requires(subject != null);
+ Error(subject.tok, msg, args);
+ }
+
+ public virtual void Error(IToken tok, string msg) {
+ Contract.Requires(msg != null);
+ Contract.Requires(tok != null);
+ errors++;
+ if (errorSink == null) {
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("{0}({1},{2}): Error: {3}",
+ tok.filename, tok.line, tok.col - 1,
+ msg);
+ Console.ForegroundColor = col;
+ } else {
+ errorSink.Error(tok, msg);
+ }
+ }
+
+ private string Format(string msg, params object[] args) {
+ Contract.Requires(msg != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ if (System.Type.GetType("Mono.Runtime") != null) { // MONO
+ // something in mono seems to be broken so that calling
+ // NamedDeclarations.ToString (and similar ToString methods)
+ // causes a stack overflow. We therefore convert those to
+ // strings by hand
+ object[] fixedArgs = new object[cce.NonNull(args).Length];
+ for (int i = 0; i < args.Length; ++i) {
+ if (args[i] is NamedDeclaration) {
+ fixedArgs[i] = cce.NonNull((NamedDeclaration)args[i]).Name;
+ } else if (args[i] is Type) {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
+ cce.NonNull((Type)args[i]).Emit(stream);
+ }
+ fixedArgs[i] = buffer.ToString();
+ } else if (args[i] is Expr) {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
+ cce.NonNull((Expr/*!*/)args[i]).Emit(stream, 0, false);
+ }
+ fixedArgs[i] = buffer.ToString();
+ } else {
+ fixedArgs[i] = args[i];
+ }
+ }
+ args = fixedArgs;
+ }
+ return string.Format(msg, args);
+ }
+
+ public void Error(IToken tok, string msg, params object[] args) {
+ Contract.Requires(msg != null);
+ Contract.Requires(tok != null);
+ Error(tok, Format(msg, args));
+ }
+
+ public void Warning(Absy subject, string msg, params object[] args) {
+ Contract.Requires(args != null);
+ Contract.Requires(msg != null);
+ Contract.Requires(subject != null);
+ Warning(subject.tok, msg, args);
+ }
+
+ public virtual void Warning(IToken tok, string msg) {
+ Contract.Requires(msg != null);
+ Contract.Requires(tok != null);
+ // warnings are currently always written to the console
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ Console.WriteLine("{0}({1},{2}): Warning: {3}",
+ tok.filename, tok.line, tok.col - 1,
+ msg);
+ Console.ForegroundColor = col;
+ }
+
+ public void Warning(IToken tok, string msg, params object[] args) {
+ Contract.Requires(msg != null);
+ Contract.Requires(tok != null);
+ Warning(tok, Format(msg, args));
+ }
+ }
+
+ public class ResolutionContext : CheckingContext {
+ public ResolutionContext(IErrorSink errorSink)
+ : base(errorSink) {
+ }
+
+ // ------------------------------ Boogie 2 Types -------------------------
+
+ // user-defined types, which can be either TypeCtorDecl or TypeSynonymDecl
+ Hashtable /*string->NamedDeclaration*//*!*/ types = new Hashtable /*string->NamedDeclaration*/ ();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(types != null);
+ Contract.Invariant(cce.NonNullElements(typeBinders));
+ Contract.Invariant(varContext != null);
+ Contract.Invariant(funcdures != null);
+ }
+
+
+ /// <summary>
+ /// Checks if name coincides with the name of a bitvector type. If so, reports an error and
+ /// returns true; otherwise, returns false.
+ /// </summary>
+ private bool CheckBvNameClashes(Absy absy, string name) {
+ Contract.Requires(name != null);
+ Contract.Requires(absy != null);
+ if (name.StartsWith("bv") && name.Length > 2) {
+ for (int i = 2; i < name.Length; ++i)
+ if (!char.IsDigit(name[i]))
+ return false;
+ Error(absy, "type name: {0} is registered for bitvectors", name);
+ return true;
+ }
+ return false;
+ }
+
+ public void AddType(NamedDeclaration td) {
+ Contract.Requires(td != null);
+ Contract.Requires((td is TypeCtorDecl) || (td is TypeSynonymDecl));
+ Contract.Requires(td.Name != null);
+
+ string name = td.Name;
+ if (CheckBvNameClashes(td, name))
+ return; // error has already been reported
+
+ var previous = (NamedDeclaration)types[name];
+ if (previous == null) {
+ types.Add(name, td);
+ } else {
+ var r = (NamedDeclaration)SelectNonExtern(td, previous);
+ if (r == null) {
+ Error(td, "more than one declaration of type name: {0}", name);
+ } else {
+ types[name] = r;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named type, or null if
+ /// no such type is declared. Also return null if the type
+ /// declared with the given name is not a constructor but a
+ /// type synonym
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public TypeCtorDecl LookUpType(string name) {
+ Contract.Requires(name != null);
+ return types[name] as TypeCtorDecl;
+ }
+
+ public TypeSynonymDecl LookUpTypeSynonym(string name) {
+ Contract.Requires(name != null);
+ return types[name] as TypeSynonymDecl;
+ }
+
+ // ------------------------------ Boogie 2 Type Binders ------------------------------
+
+ List<TypeVariable/*!*/>/*!*/ typeBinders = new List<TypeVariable/*!*/>(5);
+
+ public void AddTypeBinder(TypeVariable td) {
+ Contract.Requires(td != null);
+ if (CheckBvNameClashes(td, td.Name)) {
+ return;
+ }
+ if (types.ContainsKey(td.Name)) {
+ Error(td, "name is already reserved for type constructor: {0}", td.Name);
+ return;
+ }
+ for (int i = 0; i < typeBinders.Count; i++) {
+ if (typeBinders[i].Name == td.Name) {
+ Error(td, "more than one declaration of type variable: {0}", td.Name);
+ return;
+ }
+ }
+ typeBinders.Add(td);
+ }
+
+ public int TypeBinderState {
+ get {
+ return typeBinders.Count;
+ }
+ set {
+ typeBinders.RemoveRange(value, typeBinders.Count - value);
+ }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named type binder, or null if
+ /// no such binder is declared.
+ /// </summary>
+ public TypeVariable LookUpTypeBinder(string name) {
+ Contract.Requires(name != null);
+ for (int i = typeBinders.Count; 0 <= --i; ) {
+ TypeVariable/*!*/ td = typeBinders[i];
+ Contract.Assert(td != null);
+ if (td.Name == name) {
+ return td;
+ }
+ }
+ return null; // not present
+ }
+
+ // ------------------------------ Variables ------------------------------
+
+ class VarContextNode {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(VarSymbols != null);
+ }
+
+ public readonly Hashtable /*string->Variable*//*!*/ VarSymbols = new Hashtable /*string->Variable*/();
+ public /*maybe null*/ VarContextNode ParentContext;
+ public readonly bool Opaque;
+ readonly ISet<string> assignedAssumptionVariables = new HashSet<string>();
+
+ public bool HasVariableBeenAssigned(string name)
+ {
+ Contract.Requires(name != null);
+
+ if (assignedAssumptionVariables.Contains(name))
+ {
+ return true;
+ }
+ else if (ParentContext != null)
+ {
+ return ParentContext.HasVariableBeenAssigned(name);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public bool MarkVariableAsAssigned(string name)
+ {
+ Contract.Requires(name != null);
+
+ if (VarSymbols.Contains(name))
+ {
+ if (assignedAssumptionVariables.Contains(name))
+ {
+ return false;
+ }
+ assignedAssumptionVariables.Add(name);
+ return true;
+ }
+ else if (ParentContext != null)
+ {
+ return ParentContext.MarkVariableAsAssigned(name);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public VarContextNode(/*maybe null*/ VarContextNode parentContext, bool opaque) {
+ ParentContext = parentContext;
+ Opaque = opaque;
+ }
+ }
+
+ // symbolic constants, global variables, local variables, formals, expression-bound variables
+ VarContextNode/*!*/ varContext = new VarContextNode(null, false);
+
+ /// <summary>
+ /// Adds a variable context.
+ /// </summary>
+ public void PushVarContext() {
+ varContext = new VarContextNode(varContext, false);
+ }
+
+ /// <summary>
+ /// Adds an opaque variable context, that is, one that blocks all previously pushed contexts.
+ /// </summary>
+ public void PushOpaqueVarContext() {
+ varContext = new VarContextNode(varContext, true);
+ }
+
+ /// <summary>
+ /// Requires there to be more than one variable context.
+ /// </summary>
+ public void PopVarContext() {
+ Contract.Assert(varContext.ParentContext != null);
+ varContext = varContext.ParentContext;
+ }
+
+ public readonly ISet<string> StatementIds = new HashSet<string>();
+
+ public void AddStatementId(IToken tok, string name)
+ {
+ if (StatementIds.Contains(name))
+ {
+ Error(tok, "more than one statement with same id: " + name);
+ return;
+ }
+ StatementIds.Add(name);
+ }
+
+ public void AddVariable(Variable var, bool global) {
+ Contract.Requires(var != null);
+ var previous = FindVariable(cce.NonNull(var.Name), !global);
+ if (previous == null) {
+ varContext.VarSymbols.Add(var.Name, var);
+ } else {
+ var r = (Variable)SelectNonExtern(var, previous);
+ if (r == null) {
+ Error(var, "more than one declaration of variable name: {0}", var.Name);
+ } else {
+ varContext.VarSymbols[var.Name] = r;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named variable, or null if
+ /// no such variable is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public Variable LookUpVariable(string name) {
+ Contract.Requires(name != null);
+ return FindVariable(name, false);
+ }
+
+ Variable FindVariable(string name, bool ignoreTopLevelVars) {
+ Contract.Requires(name != null);
+ VarContextNode c = varContext;
+ bool lookOnlyForConstants = false;
+ do {
+ if (ignoreTopLevelVars && c.ParentContext == null) {
+ // this is the top level and we're asked to ignore the top level; hence, we're done
+ break;
+ }
+
+ Variable var = (Variable)c.VarSymbols[name];
+ if (var != null && (!lookOnlyForConstants || var is Constant)) {
+ return var;
+ }
+ // not at this level
+
+ if (c.Opaque) {
+ // from here on, only constants can be looked up
+ lookOnlyForConstants = true;
+ }
+ c = c.ParentContext;
+ } while (c != null);
+
+ // not present in the relevant levels
+ return null;
+ }
+
+ public bool HasVariableBeenAssigned(string name)
+ {
+ Contract.Requires(name != null);
+
+ return varContext.HasVariableBeenAssigned(name);
+ }
+
+ public void MarkVariableAsAssigned(string name)
+ {
+ Contract.Requires(name != null);
+
+ var success = varContext.MarkVariableAsAssigned(name);
+ Contract.Assume(success);
+ }
+
+ Hashtable axioms = new Hashtable();
+
+ public void AddAxiom(Axiom axiom) {
+ string axiomName = QKeyValue.FindStringAttribute(axiom.Attributes, "name");
+ if (axiomName == null)
+ return;
+ var previous = (Axiom)axioms[axiomName];
+ if (previous == null) {
+ axioms.Add(axiomName, axiom);
+ }
+ else {
+ var r = (Axiom)SelectNonExtern(axiom, previous);
+ if (r == null) {
+ Error(axiom, "more than one declaration of axiom name: {0}", axiomName);
+ }
+ else {
+ axioms[axiomName] = r;
+ }
+ }
+ }
+
+ // ------------------------------ Functions/Procedures ------------------------------
+
+ // uninterpreted function symbols, procedures
+ Hashtable /*string->DeclWithFormals*//*!*/ funcdures = new Hashtable /*string->DeclWithFormals*/ ();
+
+ public void AddProcedure(DeclWithFormals proc) {
+ Contract.Requires(proc != null);
+ Contract.Requires(proc.Name != null);
+
+ string name = proc.Name;
+ var previous = (DeclWithFormals)funcdures[name];
+ if (previous == null) {
+ funcdures.Add(name, proc);
+ } else {
+ var r = (DeclWithFormals)SelectNonExtern(proc, previous);
+ if (r == null) {
+ Error(proc, "more than one declaration of function/procedure name: {0}", name);
+ } else {
+ funcdures[name] = r;
+ }
+ }
+ }
+
+ /// <summary>
+ /// If both "a" and "b" have an ":extern" attribute, returns either one.
+ /// If one of "a" and "b" has an ":extern" attribute, returns that one.
+ /// If neither of "a" and "b" has an ":extern" attribute, returns null.
+ /// If a non-value value is returned, this method also adds the ":ignore"
+ /// attribute to the declaration NOT returned.
+ /// </summary>
+ Declaration SelectNonExtern(Declaration a, Declaration b) {
+ Contract.Requires(a != null);
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<Declaration>() == null || Contract.Result<Declaration>() == a || Contract.Result<Declaration>() == b);
+
+ Declaration ignore, keep;
+ if (QKeyValue.FindBoolAttribute(a.Attributes, "extern")) {
+ ignore = a;
+ keep = b;
+ } else if (QKeyValue.FindBoolAttribute(b.Attributes, "extern")) {
+ ignore = b;
+ keep = a;
+ } else {
+ return null;
+ }
+ // prepend :ignore attribute
+ ignore.Attributes = new QKeyValue(ignore.tok, "ignore", new List<object/*!*/>(), ignore.Attributes);
+ return keep;
+ }
+
+ /// <summary>
+ /// Returns the declaration of the named function/procedure, or null if
+ /// no such function or procedure is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public DeclWithFormals LookUpProcedure(string name) {
+ Contract.Requires(name != null);
+ return (DeclWithFormals)funcdures[name];
+ }
+
+ // ------------------------------ Blocks ------------------------------
+
+ class ProcedureContext {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Blocks != null);
+ }
+
+ public readonly Hashtable/*!*/ /*string->Block!*/ Blocks;
+ public readonly ProcedureContext Next;
+ public ProcedureContext(ProcedureContext next) {
+ Blocks = new Hashtable /*string->Block!*/ ();
+ Next = next;
+ }
+ }
+ /*maybe null*/
+ ProcedureContext procedureContext; // stack of procedure contexts
+ public bool HasProcedureContext {
+ get {
+ return procedureContext != null;
+ }
+ }
+
+ /// <summary>
+ /// Pushes a new procedure context.
+ /// </summary>
+ public void PushProcedureContext() {
+ Contract.Ensures(HasProcedureContext);
+ procedureContext = new ProcedureContext(procedureContext);
+ }
+
+ /// <summary>
+ /// Requires there to be a procedure context. Pops it.
+ /// </summary>
+ public void PopProcedureContext() {
+ Contract.Requires(HasProcedureContext);
+ Contract.Assert(procedureContext != null); // follows from precondition
+ procedureContext = procedureContext.Next;
+ }
+
+ /// <summary>
+ /// Requires there to be a procedure context.
+ /// </summary>
+ /// <param name="block"></param>
+ public void AddBlock(Block block) {
+ Contract.Requires(block != null);
+ Contract.Requires(HasProcedureContext);
+ Contract.Assert(procedureContext != null); // follows from precondition
+ Hashtable/*!*/ /*string->Block!*/ blocks = procedureContext.Blocks;
+ Contract.Assert(blocks != null);
+ if (blocks[block.Label] != null) {
+ Error(block, "more than one declaration of block name: {0}", block.Label);
+ } else {
+ blocks.Add(block.Label, block);
+ }
+ }
+
+ /// <summary>
+ /// Requires there to be a procedure context.
+ /// Returns the declaration of the named block, or null if
+ /// no such block is declared.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public Block LookUpBlock(string name) {
+ Contract.Requires(name != null);
+ Contract.Requires(HasProcedureContext);
+ Contract.Assert(procedureContext != null); // follows from precondition
+ Hashtable/*!*/ /*string->Block!*/ blocks = procedureContext.Blocks;
+ Contract.Assert(blocks != null);
+ return (Block)blocks[name];
+ }
+
+ // ------------------------------ Flags ------------------------------
+
+ public enum State {
+ StateLess,
+ Single,
+ Two
+ }
+ State stateMode = State.Single;
+
+ /// <summary>
+ /// To increase our confidence in that the caller knows what it's doing, we only allow
+ /// the state mode to be changed in and out of the State.Single mode.
+ /// </summary>
+ public State StateMode {
+ get {
+ return stateMode;
+ }
+ set {
+ Contract.Assert(value != stateMode);
+ Contract.Assert(stateMode == State.Single || value == State.Single);
+ cce.BeginExpose(this);
+ {
+ stateMode = value;
+ }
+ cce.EndExpose();
+ }
+ }
+
+ bool triggerMode = false;
+
+ /// <summary>
+ /// Setting TriggerMode is allowed only if the setting has the effect of toggling the
+ /// boolean. That is, TriggerMode can be set to true only if it previously was false,
+ /// and TriggerMode can be set to false only if it previously was true.
+ /// </summary>
+ public bool TriggerMode {
+ get {
+ return triggerMode;
+ }
+ set {
+ Contract.Assert(triggerMode != value);
+ cce.BeginExpose(this);
+ {
+ triggerMode = value;
+ }
+ cce.EndExpose();
+ }
+ }
+ }
+
+ public class TypecheckingContext : CheckingContext {
+ public List<IdentifierExpr> Frame; // used in checking the assignment targets of implementation bodies
+ public bool Yields;
+
+ public TypecheckingContext(IErrorSink errorSink)
+ : base(errorSink) {
+ }
+
+ public bool InFrame(Variable v) {
+ Contract.Requires(v != null);
+ Contract.Requires(Frame != null);
+ return Frame.Any(f => f.Decl == v);
+ }
+ }
+}
diff --git a/Source/Core/Scanner.cs b/Source/Core/Scanner.cs
index ca7db1e1..69023555 100644
--- a/Source/Core/Scanner.cs
+++ b/Source/Core/Scanner.cs
@@ -1,823 +1,823 @@
-
-using System;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-
-
-namespace Microsoft.Boogie {
-
-//-----------------------------------------------------------------------------------
-// Buffer
-//-----------------------------------------------------------------------------------
-public class Buffer {
- // This Buffer supports the following cases:
- // 1) seekable stream (file)
- // a) whole stream in buffer
- // b) part of stream in buffer
- // 2) non seekable stream (network, console)
-
- public const int EOF = 65535 + 1; // char.MaxValue + 1;
- const int MIN_BUFFER_LENGTH = 1024; // 1KB
- const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
- byte[]/*!*/ buf; // input buffer
- int bufStart; // position of first byte in buffer relative to input stream
- int bufLen; // length of buffer
- int fileLen; // length of input stream (may change if the stream is no file)
- int bufPos; // current position in buffer
- Stream/*!*/ stream; // input stream (seekable)
- bool isUserStream; // was the stream opened by the user?
-
- [ContractInvariantMethod]
- void ObjectInvariant(){
- Contract.Invariant(buf != null);
- Contract.Invariant(stream != null);
- }
-
-// [NotDelayed]
- public Buffer (Stream/*!*/ s, bool isUserStream) : base() {
- Contract.Requires(s != null);
- stream = s; this.isUserStream = isUserStream;
-
- int fl, bl;
- if (s.CanSeek) {
- fl = (int) s.Length;
- bl = fl < MAX_BUFFER_LENGTH ? fl : MAX_BUFFER_LENGTH; // Math.Min(fileLen, MAX_BUFFER_LENGTH);
- bufStart = Int32.MaxValue; // nothing in the buffer so far
- } else {
- fl = bl = bufStart = 0;
- }
-
- buf = new byte[(bl>0) ? bl : MIN_BUFFER_LENGTH];
- fileLen = fl; bufLen = bl;
-
- if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
- else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
- if (bufLen == fileLen && s.CanSeek) Close();
- }
-
- protected Buffer(Buffer/*!*/ b) { // called in UTF8Buffer constructor
- Contract.Requires(b != null);
- buf = b.buf;
- bufStart = b.bufStart;
- bufLen = b.bufLen;
- fileLen = b.fileLen;
- bufPos = b.bufPos;
- stream = b.stream;
- // keep destructor from closing the stream
- //b.stream = null;
- isUserStream = b.isUserStream;
- // keep destructor from closing the stream
- b.isUserStream = true;
- }
-
- ~Buffer() { Close(); }
-
- protected void Close() {
- if (!isUserStream && stream != null) {
- stream.Close();
- //stream = null;
- }
- }
-
- public virtual int Read () {
- if (bufPos < bufLen) {
- return buf[bufPos++];
- } else if (Pos < fileLen) {
- Pos = Pos; // shift buffer start to Pos
- return buf[bufPos++];
- } else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
- return buf[bufPos++];
- } else {
- return EOF;
- }
- }
-
- public int Peek () {
- int curPos = Pos;
- int ch = Read();
- Pos = curPos;
- return ch;
- }
-
- public string/*!*/ GetString (int beg, int end) {
- Contract.Ensures(Contract.Result<string>() != null);
- int len = 0;
- char[] buf = new char[end - beg];
- int oldPos = Pos;
- Pos = beg;
- while (Pos < end) buf[len++] = (char) Read();
- Pos = oldPos;
- return new String(buf, 0, len);
- }
-
- public int Pos {
- get { return bufPos + bufStart; }
- set {
- if (value >= fileLen && stream != null && !stream.CanSeek) {
- // Wanted position is after buffer and the stream
- // is not seek-able e.g. network or console,
- // thus we have to read the stream manually till
- // the wanted position is in sight.
- while (value >= fileLen && ReadNextStreamChunk() > 0);
- }
-
- if (value < 0 || value > fileLen) {
- throw new FatalError("buffer out of bounds access, position: " + value);
- }
-
- if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
- bufPos = value - bufStart;
- } else if (stream != null) { // must be swapped in
- stream.Seek(value, SeekOrigin.Begin);
- bufLen = stream.Read(buf, 0, buf.Length);
- bufStart = value; bufPos = 0;
- } else {
- // set the position to the end of the file, Pos will return fileLen.
- bufPos = fileLen - bufStart;
- }
- }
- }
-
- // Read the next chunk of bytes from the stream, increases the buffer
- // if needed and updates the fields fileLen and bufLen.
- // Returns the number of bytes read.
- private int ReadNextStreamChunk() {
- int free = buf.Length - bufLen;
- if (free == 0) {
- // in the case of a growing input stream
- // we can neither seek in the stream, nor can we
- // foresee the maximum length, thus we must adapt
- // the buffer size on demand.
- byte[] newBuf = new byte[bufLen * 2];
- Array.Copy(buf, newBuf, bufLen);
- buf = newBuf;
- free = bufLen;
- }
- int read = stream.Read(buf, bufLen, free);
- if (read > 0) {
- fileLen = bufLen = (bufLen + read);
- return read;
- }
- // end of stream reached
- return 0;
- }
-}
-
-//-----------------------------------------------------------------------------------
-// UTF8Buffer
-//-----------------------------------------------------------------------------------
-public class UTF8Buffer: Buffer {
- public UTF8Buffer(Buffer/*!*/ b): base(b) {Contract.Requires(b != null);}
-
- public override int Read() {
- int ch;
- do {
- ch = base.Read();
- // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
- } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
- if (ch < 128 || ch == EOF) {
- // nothing to do, first 127 chars are the same in ascii and utf8
- // 0xxxxxxx or end of file character
- } else if ((ch & 0xF0) == 0xF0) {
- // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- int c1 = ch & 0x07; ch = base.Read();
- int c2 = ch & 0x3F; ch = base.Read();
- int c3 = ch & 0x3F; ch = base.Read();
- int c4 = ch & 0x3F;
- ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
- } else if ((ch & 0xE0) == 0xE0) {
- // 1110xxxx 10xxxxxx 10xxxxxx
- int c1 = ch & 0x0F; ch = base.Read();
- int c2 = ch & 0x3F; ch = base.Read();
- int c3 = ch & 0x3F;
- ch = (((c1 << 6) | c2) << 6) | c3;
- } else if ((ch & 0xC0) == 0xC0) {
- // 110xxxxx 10xxxxxx
- int c1 = ch & 0x1F; ch = base.Read();
- int c2 = ch & 0x3F;
- ch = (c1 << 6) | c2;
- }
- return ch;
- }
-}
-
-//-----------------------------------------------------------------------------------
-// Scanner
-//-----------------------------------------------------------------------------------
-public class Scanner {
- const char EOL = '\n';
- const int eofSym = 0; /* pdt */
- const int maxT = 96;
- const int noSym = 96;
-
-
- [ContractInvariantMethod]
- void objectInvariant(){
- Contract.Invariant(this._buffer != null);
- Contract.Invariant(t != null);
- Contract.Invariant(start != null);
- Contract.Invariant(tokens != null);
- Contract.Invariant(pt != null);
- Contract.Invariant(tval != null);
- Contract.Invariant(Filename != null);
- Contract.Invariant(errorHandler != null);
- }
-
- private Buffer/*!*/ _buffer; // scanner buffer
-
- public Buffer/*!*/ buffer {
- get {
- Contract.Ensures(Contract.Result<Buffer>() != null);
- return this._buffer;
- }
- set {
- Contract.Requires(value != null);
- this._buffer = value;
- }
- }
-
- Token/*!*/ t; // current token
- int ch; // current input character
- int pos; // byte position of current character
- int charPos;
- int col; // column number of current character
- int line; // line number of current character
- int oldEols; // EOLs that appeared in a comment;
- static readonly Hashtable/*!*/ start; // maps first token character to start state
-
- Token/*!*/ tokens; // list of tokens already peeked (first token is a dummy)
- Token/*!*/ pt; // current peek token
-
- char[]/*!*/ tval = new char[128]; // text of current token
- int tlen; // length of current token
-
- private string/*!*/ Filename;
- private Errors/*!*/ errorHandler;
-
- static Scanner() {
- start = new Hashtable(128);
- for (int i = 35; i <= 36; ++i) start[i] = 2;
- for (int i = 39; i <= 39; ++i) start[i] = 2;
- for (int i = 46; i <= 46; ++i) start[i] = 2;
- for (int i = 63; i <= 63; ++i) start[i] = 2;
- for (int i = 65; i <= 90; ++i) start[i] = 2;
- for (int i = 94; i <= 122; ++i) start[i] = 2;
- for (int i = 126; i <= 126; ++i) start[i] = 2;
- for (int i = 48; i <= 57; ++i) start[i] = 16;
- for (int i = 34; i <= 34; ++i) start[i] = 6;
- start[92] = 1;
- start[59] = 19;
- start[40] = 20;
- start[41] = 21;
- start[58] = 55;
- start[44] = 22;
- start[91] = 23;
- start[93] = 24;
- start[60] = 56;
- start[62] = 57;
- start[123] = 25;
- start[125] = 58;
- start[61] = 59;
- start[42] = 60;
- start[124] = 61;
- start[8660] = 28;
- start[8658] = 30;
- start[8656] = 31;
- start[38] = 32;
- start[8743] = 34;
- start[8744] = 36;
- start[33] = 62;
- start[8800] = 40;
- start[8804] = 41;
- start[8805] = 42;
- start[43] = 63;
- start[45] = 44;
- start[47] = 45;
- start[172] = 47;
- start[8704] = 50;
- start[8707] = 51;
- start[955] = 52;
- start[8226] = 54;
- start[Buffer.EOF] = -1;
-
- }
-
-// [NotDelayed]
- public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler, bool useBaseName = false) : base() {
- Contract.Requires(fileName != null);
- Contract.Requires(errorHandler != null);
- this.errorHandler = errorHandler;
- pt = tokens = new Token(); // first token is a dummy
- t = new Token(); // dummy because t is a non-null field
- try {
- Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
- this._buffer = new Buffer(stream, false);
- Filename = useBaseName? GetBaseName(fileName): fileName;
- Init();
- } catch (IOException) {
- throw new FatalError("Cannot open file " + fileName);
- }
- }
-
-// [NotDelayed]
- public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName, bool useBaseName = false) : base() {
- Contract.Requires(s != null);
- Contract.Requires(errorHandler != null);
- Contract.Requires(fileName != null);
- pt = tokens = new Token(); // first token is a dummy
- t = new Token(); // dummy because t is a non-null field
- this._buffer = new Buffer(s, true);
- this.errorHandler = errorHandler;
- this.Filename = useBaseName? GetBaseName(fileName) : fileName;
- Init();
- }
-
- string GetBaseName(string fileName) {
- return System.IO.Path.GetFileName(fileName); // Return basename
- }
-
- void Init() {
- pos = -1; line = 1; col = 0;
- oldEols = 0;
- NextCh();
- if (ch == 0xEF) { // check optional byte order mark for UTF-8
- NextCh(); int ch1 = ch;
- NextCh(); int ch2 = ch;
- if (ch1 != 0xBB || ch2 != 0xBF) {
- throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
- }
- buffer = new UTF8Buffer(buffer); col = 0;
- NextCh();
- }
- pt = tokens = new Token(); // first token is a dummy
- }
-
- string/*!*/ ReadToEOL(){
- Contract.Ensures(Contract.Result<string>() != null);
- int p = buffer.Pos;
- int ch = buffer.Read();
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
- while (ch != EOL && ch != Buffer.EOF){
- ch = buffer.Read();
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
- }
- string/*!*/ s = buffer.GetString(p, buffer.Pos);
- Contract.Assert(s!=null);
- return s;
- }
-
- void NextCh() {
- if (oldEols > 0) { ch = EOL; oldEols--; }
- else {
-// pos = buffer.Pos;
-// ch = buffer.Read(); col++;
-// // replace isolated '\r' by '\n' in order to make
-// // eol handling uniform across Windows, Unix and Mac
-// if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
-// if (ch == EOL) { line++; col = 0; }
-
- while (true) {
- pos = buffer.Pos;
- ch = buffer.Read(); col++;
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
- if (ch == EOL) {
- line++; col = 0;
- } else if (ch == '#' && col == 1) {
- int prLine = line;
- int prColumn = 0;
-
- string/*!*/ hashLine = ReadToEOL();
- Contract.Assert(hashLine!=null);
- col = 0;
- line++;
-
- hashLine = hashLine.TrimEnd(null);
- if (hashLine.StartsWith("line ") || hashLine == "line") {
- // parse #line pragma: #line num [filename]
- string h = hashLine.Substring(4).TrimStart(null);
- int x = h.IndexOf(' ');
- if (x == -1) {
- x = h.Length; // this will be convenient below when we look for a filename
- }
- try {
- int li = int.Parse(h.Substring(0, x));
-
- h = h.Substring(x).Trim();
-
- // act on #line
- line = li;
- if (h.Length != 0) {
- // a filename was specified
- Filename = h;
- }
- continue; // successfully parsed and acted on the #line pragma
-
- } catch (FormatException) {
- // just fall down through to produce an error message
- }
- this.errorHandler.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
- continue;
- }
-
- this.errorHandler.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
- continue;
- }
- return;
- }
-
-
- }
-
- }
-
- void AddCh() {
- if (tlen >= tval.Length) {
- char[] newBuf = new char[2 * tval.Length];
- Array.Copy(tval, 0, newBuf, 0, tval.Length);
- tval = newBuf;
- }
- if (ch != Buffer.EOF) {
- tval[tlen++] = (char) ch;
- NextCh();
- }
- }
-
-
-
- bool Comment0() {
- int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
- NextCh();
- if (ch == '/') {
- NextCh();
- for(;;) {
- if (ch == 10) {
- level--;
- if (level == 0) { oldEols = line - line0; NextCh(); return true; }
- NextCh();
- } else if (ch == Buffer.EOF) return false;
- else NextCh();
- }
- } else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
- }
- return false;
- }
-
- bool Comment1() {
- int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
- NextCh();
- if (ch == '*') {
- NextCh();
- for(;;) {
- if (ch == '*') {
- NextCh();
- if (ch == '/') {
- level--;
- if (level == 0) { oldEols = line - line0; NextCh(); return true; }
- NextCh();
- }
- } else if (ch == '/') {
- NextCh();
- if (ch == '*') {
- level++; NextCh();
- }
- } else if (ch == Buffer.EOF) return false;
- else NextCh();
- }
- } else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
- }
- return false;
- }
-
-
- void CheckLiteral() {
- switch (t.val) {
- case "var": t.kind = 7; break;
- case "where": t.kind = 13; break;
- case "int": t.kind = 14; break;
- case "real": t.kind = 15; break;
- case "bool": t.kind = 16; break;
- case "fp": t.kind = 97; break;
- case "float": case "float16": case "float32": case "float64": case "float128": t.kind = 98; break;
- case "const": t.kind = 21; break;
- case "unique": t.kind = 22; break;
- case "extends": t.kind = 23; break;
- case "complete": t.kind = 24; break;
- case "function": t.kind = 25; break;
- case "returns": t.kind = 26; break;
- case "axiom": t.kind = 29; break;
- case "type": t.kind = 30; break;
- case "procedure": t.kind = 32; break;
- case "implementation": t.kind = 33; break;
- case "modifies": t.kind = 34; break;
- case "free": t.kind = 35; break;
- case "requires": t.kind = 36; break;
- case "ensures": t.kind = 37; break;
- case "goto": t.kind = 38; break;
- case "return": t.kind = 39; break;
- case "if": t.kind = 40; break;
- case "else": t.kind = 41; break;
- case "while": t.kind = 42; break;
- case "invariant": t.kind = 43; break;
- case "break": t.kind = 45; break;
- case "assert": t.kind = 46; break;
- case "assume": t.kind = 47; break;
- case "havoc": t.kind = 48; break;
- case "yield": t.kind = 49; break;
- case "async": t.kind = 51; break;
- case "call": t.kind = 52; break;
- case "par": t.kind = 53; break;
- case "div": t.kind = 76; break;
- case "mod": t.kind = 77; break;
- case "false": t.kind = 82; break;
- case "true": t.kind = 83; break;
- case "old": t.kind = 84; break;
- case "then": t.kind = 87; break;
- case "forall": t.kind = 88; break;
- case "exists": t.kind = 90; break;
- case "lambda": t.kind = 92; break;
- default: break;
- }
- }
-
- Token/*!*/ NextToken() {
- Contract.Ensures(Contract.Result<Token>() != null);
- while (ch == ' ' ||
- ch >= 9 && ch <= 10 || ch == 13
- ) NextCh();
- if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
- int recKind = noSym;
- int recEnd = pos;
- t = new Token();
- t.pos = pos; t.col = col; t.line = line;
- t.filename = this.Filename;
- int state;
- if (start.ContainsKey(ch)) {
- Contract.Assert(start[ch] != null);
- state = (int) start[ch];
- }
- else { state = 0; }
- tlen = 0; AddCh();
-
- switch (state) {
- case -1: { t.kind = eofSym; break; } // NextCh already done
- case 0: {
- if (recKind != noSym) {
- tlen = recEnd - t.pos;
- SetScannerBehindT();
- }
- t.kind = recKind; break;
- } // NextCh already done
- case 1:
- if (ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~') {AddCh(); goto case 2;}
- else {goto case 0;}
- case 2:
- recEnd = pos; recKind = 1;
- if (ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~') {AddCh(); goto case 2;}
- else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 3:
- if (ch == 'v') {AddCh(); goto case 4;}
- else {goto case 0;}
- case 4:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 5;}
- else {goto case 0;}
- case 5:
- recEnd = pos; recKind = 2;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 5;}
- else {t.kind = 2; break;}
- case 6:
- if (ch == '"') {AddCh(); goto case 7;}
- else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
- else if (ch == 92) {AddCh(); goto case 17;}
- else {goto case 0;}
- case 7:
- {t.kind = 4; break;}
- case 8:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
- else if (ch == '-') {AddCh(); goto case 9;}
- else {goto case 0;}
- case 9:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
- else {goto case 0;}
- case 10:
- recEnd = pos; recKind = 5;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
- else {t.kind = 5; break;}
- case 11:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;}
- else {goto case 0;}
- case 12:
- recEnd = pos; recKind = 6;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;}
- else if (ch == 'e') {AddCh(); goto case 13;}
- else {t.kind = 6; break;}
- case 13:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
- else if (ch == '-') {AddCh(); goto case 14;}
- else {goto case 0;}
- case 14:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
- else {goto case 0;}
- case 15:
- recEnd = pos; recKind = 6;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
- else {t.kind = 6; break;}
- case 16:
- recEnd = pos; recKind = 3;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 16;}
- else if (ch == 'b') {AddCh(); goto case 3;}
- else if (ch == 'e') {AddCh(); goto case 8;}
- else if (ch == '.') {AddCh(); goto case 11;}
- else {t.kind = 3; break;}
- case 17:
- if (ch == '"') {AddCh(); goto case 18;}
- else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
- else if (ch == 92) {AddCh(); goto case 17;}
- else {goto case 0;}
- case 18:
- recEnd = pos; recKind = 4;
- if (ch == '"') {AddCh(); goto case 7;}
- else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
- else if (ch == 92) {AddCh(); goto case 17;}
- else {t.kind = 4; break;}
- case 19:
- {t.kind = 8; break;}
- case 20:
- {t.kind = 9; break;}
- case 21:
- {t.kind = 10; break;}
- case 22:
- {t.kind = 12; break;}
- case 23:
- {t.kind = 17; break;}
- case 24:
- {t.kind = 18; break;}
- case 25:
- {t.kind = 27; break;}
- case 26:
- {t.kind = 50; break;}
- case 27:
- {t.kind = 55; break;}
- case 28:
- {t.kind = 56; break;}
- case 29:
- {t.kind = 57; break;}
- case 30:
- {t.kind = 58; break;}
- case 31:
- {t.kind = 60; break;}
- case 32:
- if (ch == '&') {AddCh(); goto case 33;}
- else {goto case 0;}
- case 33:
- {t.kind = 61; break;}
- case 34:
- {t.kind = 62; break;}
- case 35:
- {t.kind = 63; break;}
- case 36:
- {t.kind = 64; break;}
- case 37:
- {t.kind = 67; break;}
- case 38:
- {t.kind = 68; break;}
- case 39:
- {t.kind = 69; break;}
- case 40:
- {t.kind = 70; break;}
- case 41:
- {t.kind = 71; break;}
- case 42:
- {t.kind = 72; break;}
- case 43:
- {t.kind = 73; break;}
- case 44:
- {t.kind = 75; break;}
- case 45:
- {t.kind = 78; break;}
- case 46:
- {t.kind = 79; break;}
- case 47:
- {t.kind = 81; break;}
- case 48:
- {t.kind = 85; break;}
- case 49:
- {t.kind = 86; break;}
- case 50:
- {t.kind = 89; break;}
- case 51:
- {t.kind = 91; break;}
- case 52:
- {t.kind = 93; break;}
- case 53:
- {t.kind = 94; break;}
- case 54:
- {t.kind = 95; break;}
- case 55:
- recEnd = pos; recKind = 11;
- if (ch == '=') {AddCh(); goto case 26;}
- else if (ch == ':') {AddCh(); goto case 53;}
- else {t.kind = 11; break;}
- case 56:
- recEnd = pos; recKind = 19;
- if (ch == '=') {AddCh(); goto case 64;}
- else if (ch == ':') {AddCh(); goto case 39;}
- else {t.kind = 19; break;}
- case 57:
- recEnd = pos; recKind = 20;
- if (ch == '=') {AddCh(); goto case 37;}
- else {t.kind = 20; break;}
- case 58:
- recEnd = pos; recKind = 28;
- if (ch == '|') {AddCh(); goto case 49;}
- else {t.kind = 28; break;}
- case 59:
- recEnd = pos; recKind = 31;
- if (ch == '=') {AddCh(); goto case 65;}
- else {t.kind = 31; break;}
- case 60:
- recEnd = pos; recKind = 44;
- if (ch == '*') {AddCh(); goto case 46;}
- else {t.kind = 44; break;}
- case 61:
- recEnd = pos; recKind = 54;
- if (ch == '|') {AddCh(); goto case 35;}
- else if (ch == '{') {AddCh(); goto case 48;}
- else {t.kind = 54; break;}
- case 62:
- recEnd = pos; recKind = 80;
- if (ch == '=') {AddCh(); goto case 38;}
- else {t.kind = 80; break;}
- case 63:
- recEnd = pos; recKind = 74;
- if (ch == '+') {AddCh(); goto case 43;}
- else {t.kind = 74; break;}
- case 64:
- recEnd = pos; recKind = 66;
- if (ch == '=') {AddCh(); goto case 66;}
- else {t.kind = 66; break;}
- case 65:
- recEnd = pos; recKind = 65;
- if (ch == '>') {AddCh(); goto case 29;}
- else {t.kind = 65; break;}
- case 66:
- recEnd = pos; recKind = 59;
- if (ch == '>') {AddCh(); goto case 27;}
- else {t.kind = 59; break;}
-
- }
- t.val = new String(tval, 0, tlen);
- return t;
- }
-
- private void SetScannerBehindT() {
- buffer.Pos = t.pos;
- NextCh();
- line = t.line; col = t.col;
- for (int i = 0; i < tlen; i++) NextCh();
- }
-
- // get the next token (possibly a token already seen during peeking)
- public Token/*!*/ Scan () {
- Contract.Ensures(Contract.Result<Token>() != null);
- if (tokens.next == null) {
- return NextToken();
- } else {
- pt = tokens = tokens.next;
- return tokens;
- }
- }
-
- // peek for the next token, ignore pragmas
- public Token/*!*/ Peek () {
- Contract.Ensures(Contract.Result<Token>() != null);
- do {
- if (pt.next == null) {
- pt.next = NextToken();
- }
- pt = pt.next;
- } while (pt.kind > maxT); // skip pragmas
-
- return pt;
- }
-
- // make sure that peeking starts at the current scan position
- public void ResetPeek () { pt = tokens; }
-
-} // end Scanner
-
-public delegate void ErrorProc(int n, string filename, int line, int col);
-
-
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+
+
+namespace Microsoft.Boogie {
+
+//-----------------------------------------------------------------------------------
+// Buffer
+//-----------------------------------------------------------------------------------
+public class Buffer {
+ // This Buffer supports the following cases:
+ // 1) seekable stream (file)
+ // a) whole stream in buffer
+ // b) part of stream in buffer
+ // 2) non seekable stream (network, console)
+
+ public const int EOF = 65535 + 1; // char.MaxValue + 1;
+ const int MIN_BUFFER_LENGTH = 1024; // 1KB
+ const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+ byte[]/*!*/ buf; // input buffer
+ int bufStart; // position of first byte in buffer relative to input stream
+ int bufLen; // length of buffer
+ int fileLen; // length of input stream (may change if the stream is no file)
+ int bufPos; // current position in buffer
+ Stream/*!*/ stream; // input stream (seekable)
+ bool isUserStream; // was the stream opened by the user?
+
+ [ContractInvariantMethod]
+ void ObjectInvariant(){
+ Contract.Invariant(buf != null);
+ Contract.Invariant(stream != null);
+ }
+
+// [NotDelayed]
+ public Buffer (Stream/*!*/ s, bool isUserStream) : base() {
+ Contract.Requires(s != null);
+ stream = s; this.isUserStream = isUserStream;
+
+ int fl, bl;
+ if (s.CanSeek) {
+ fl = (int) s.Length;
+ bl = fl < MAX_BUFFER_LENGTH ? fl : MAX_BUFFER_LENGTH; // Math.Min(fileLen, MAX_BUFFER_LENGTH);
+ bufStart = Int32.MaxValue; // nothing in the buffer so far
+ } else {
+ fl = bl = bufStart = 0;
+ }
+
+ buf = new byte[(bl>0) ? bl : MIN_BUFFER_LENGTH];
+ fileLen = fl; bufLen = bl;
+
+ if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
+ else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
+ if (bufLen == fileLen && s.CanSeek) Close();
+ }
+
+ protected Buffer(Buffer/*!*/ b) { // called in UTF8Buffer constructor
+ Contract.Requires(b != null);
+ buf = b.buf;
+ bufStart = b.bufStart;
+ bufLen = b.bufLen;
+ fileLen = b.fileLen;
+ bufPos = b.bufPos;
+ stream = b.stream;
+ // keep destructor from closing the stream
+ //b.stream = null;
+ isUserStream = b.isUserStream;
+ // keep destructor from closing the stream
+ b.isUserStream = true;
+ }
+
+ ~Buffer() { Close(); }
+
+ protected void Close() {
+ if (!isUserStream && stream != null) {
+ stream.Close();
+ //stream = null;
+ }
+ }
+
+ public virtual int Read () {
+ if (bufPos < bufLen) {
+ return buf[bufPos++];
+ } else if (Pos < fileLen) {
+ Pos = Pos; // shift buffer start to Pos
+ return buf[bufPos++];
+ } else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
+ return buf[bufPos++];
+ } else {
+ return EOF;
+ }
+ }
+
+ public int Peek () {
+ int curPos = Pos;
+ int ch = Read();
+ Pos = curPos;
+ return ch;
+ }
+
+ public string/*!*/ GetString (int beg, int end) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ int len = 0;
+ char[] buf = new char[end - beg];
+ int oldPos = Pos;
+ Pos = beg;
+ while (Pos < end) buf[len++] = (char) Read();
+ Pos = oldPos;
+ return new String(buf, 0, len);
+ }
+
+ public int Pos {
+ get { return bufPos + bufStart; }
+ set {
+ if (value >= fileLen && stream != null && !stream.CanSeek) {
+ // Wanted position is after buffer and the stream
+ // is not seek-able e.g. network or console,
+ // thus we have to read the stream manually till
+ // the wanted position is in sight.
+ while (value >= fileLen && ReadNextStreamChunk() > 0);
+ }
+
+ if (value < 0 || value > fileLen) {
+ throw new FatalError("buffer out of bounds access, position: " + value);
+ }
+
+ if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+ bufPos = value - bufStart;
+ } else if (stream != null) { // must be swapped in
+ stream.Seek(value, SeekOrigin.Begin);
+ bufLen = stream.Read(buf, 0, buf.Length);
+ bufStart = value; bufPos = 0;
+ } else {
+ // set the position to the end of the file, Pos will return fileLen.
+ bufPos = fileLen - bufStart;
+ }
+ }
+ }
+
+ // Read the next chunk of bytes from the stream, increases the buffer
+ // if needed and updates the fields fileLen and bufLen.
+ // Returns the number of bytes read.
+ private int ReadNextStreamChunk() {
+ int free = buf.Length - bufLen;
+ if (free == 0) {
+ // in the case of a growing input stream
+ // we can neither seek in the stream, nor can we
+ // foresee the maximum length, thus we must adapt
+ // the buffer size on demand.
+ byte[] newBuf = new byte[bufLen * 2];
+ Array.Copy(buf, newBuf, bufLen);
+ buf = newBuf;
+ free = bufLen;
+ }
+ int read = stream.Read(buf, bufLen, free);
+ if (read > 0) {
+ fileLen = bufLen = (bufLen + read);
+ return read;
+ }
+ // end of stream reached
+ return 0;
+ }
+}
+
+//-----------------------------------------------------------------------------------
+// UTF8Buffer
+//-----------------------------------------------------------------------------------
+public class UTF8Buffer: Buffer {
+ public UTF8Buffer(Buffer/*!*/ b): base(b) {Contract.Requires(b != null);}
+
+ public override int Read() {
+ int ch;
+ do {
+ ch = base.Read();
+ // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+ } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+ if (ch < 128 || ch == EOF) {
+ // nothing to do, first 127 chars are the same in ascii and utf8
+ // 0xxxxxxx or end of file character
+ } else if ((ch & 0xF0) == 0xF0) {
+ // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ int c1 = ch & 0x07; ch = base.Read();
+ int c2 = ch & 0x3F; ch = base.Read();
+ int c3 = ch & 0x3F; ch = base.Read();
+ int c4 = ch & 0x3F;
+ ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+ } else if ((ch & 0xE0) == 0xE0) {
+ // 1110xxxx 10xxxxxx 10xxxxxx
+ int c1 = ch & 0x0F; ch = base.Read();
+ int c2 = ch & 0x3F; ch = base.Read();
+ int c3 = ch & 0x3F;
+ ch = (((c1 << 6) | c2) << 6) | c3;
+ } else if ((ch & 0xC0) == 0xC0) {
+ // 110xxxxx 10xxxxxx
+ int c1 = ch & 0x1F; ch = base.Read();
+ int c2 = ch & 0x3F;
+ ch = (c1 << 6) | c2;
+ }
+ return ch;
+ }
+}
+
+//-----------------------------------------------------------------------------------
+// Scanner
+//-----------------------------------------------------------------------------------
+public class Scanner {
+ const char EOL = '\n';
+ const int eofSym = 0; /* pdt */
+ const int maxT = 96;
+ const int noSym = 96;
+
+
+ [ContractInvariantMethod]
+ void objectInvariant(){
+ Contract.Invariant(this._buffer != null);
+ Contract.Invariant(t != null);
+ Contract.Invariant(start != null);
+ Contract.Invariant(tokens != null);
+ Contract.Invariant(pt != null);
+ Contract.Invariant(tval != null);
+ Contract.Invariant(Filename != null);
+ Contract.Invariant(errorHandler != null);
+ }
+
+ private Buffer/*!*/ _buffer; // scanner buffer
+
+ public Buffer/*!*/ buffer {
+ get {
+ Contract.Ensures(Contract.Result<Buffer>() != null);
+ return this._buffer;
+ }
+ set {
+ Contract.Requires(value != null);
+ this._buffer = value;
+ }
+ }
+
+ Token/*!*/ t; // current token
+ int ch; // current input character
+ int pos; // byte position of current character
+ int charPos;
+ int col; // column number of current character
+ int line; // line number of current character
+ int oldEols; // EOLs that appeared in a comment;
+ static readonly Hashtable/*!*/ start; // maps first token character to start state
+
+ Token/*!*/ tokens; // list of tokens already peeked (first token is a dummy)
+ Token/*!*/ pt; // current peek token
+
+ char[]/*!*/ tval = new char[128]; // text of current token
+ int tlen; // length of current token
+
+ private string/*!*/ Filename;
+ private Errors/*!*/ errorHandler;
+
+ static Scanner() {
+ start = new Hashtable(128);
+ for (int i = 35; i <= 36; ++i) start[i] = 2;
+ for (int i = 39; i <= 39; ++i) start[i] = 2;
+ for (int i = 46; i <= 46; ++i) start[i] = 2;
+ for (int i = 63; i <= 63; ++i) start[i] = 2;
+ for (int i = 65; i <= 90; ++i) start[i] = 2;
+ for (int i = 94; i <= 122; ++i) start[i] = 2;
+ for (int i = 126; i <= 126; ++i) start[i] = 2;
+ for (int i = 48; i <= 57; ++i) start[i] = 16;
+ for (int i = 34; i <= 34; ++i) start[i] = 6;
+ start[92] = 1;
+ start[59] = 19;
+ start[40] = 20;
+ start[41] = 21;
+ start[58] = 55;
+ start[44] = 22;
+ start[91] = 23;
+ start[93] = 24;
+ start[60] = 56;
+ start[62] = 57;
+ start[123] = 25;
+ start[125] = 58;
+ start[61] = 59;
+ start[42] = 60;
+ start[124] = 61;
+ start[8660] = 28;
+ start[8658] = 30;
+ start[8656] = 31;
+ start[38] = 32;
+ start[8743] = 34;
+ start[8744] = 36;
+ start[33] = 62;
+ start[8800] = 40;
+ start[8804] = 41;
+ start[8805] = 42;
+ start[43] = 63;
+ start[45] = 44;
+ start[47] = 45;
+ start[172] = 47;
+ start[8704] = 50;
+ start[8707] = 51;
+ start[955] = 52;
+ start[8226] = 54;
+ start[Buffer.EOF] = -1;
+
+ }
+
+// [NotDelayed]
+ public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler, bool useBaseName = false) : base() {
+ Contract.Requires(fileName != null);
+ Contract.Requires(errorHandler != null);
+ this.errorHandler = errorHandler;
+ pt = tokens = new Token(); // first token is a dummy
+ t = new Token(); // dummy because t is a non-null field
+ try {
+ Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
+ this._buffer = new Buffer(stream, false);
+ Filename = useBaseName? GetBaseName(fileName): fileName;
+ Init();
+ } catch (IOException) {
+ throw new FatalError("Cannot open file " + fileName);
+ }
+ }
+
+// [NotDelayed]
+ public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName, bool useBaseName = false) : base() {
+ Contract.Requires(s != null);
+ Contract.Requires(errorHandler != null);
+ Contract.Requires(fileName != null);
+ pt = tokens = new Token(); // first token is a dummy
+ t = new Token(); // dummy because t is a non-null field
+ this._buffer = new Buffer(s, true);
+ this.errorHandler = errorHandler;
+ this.Filename = useBaseName? GetBaseName(fileName) : fileName;
+ Init();
+ }
+
+ string GetBaseName(string fileName) {
+ return System.IO.Path.GetFileName(fileName); // Return basename
+ }
+
+ void Init() {
+ pos = -1; line = 1; col = 0;
+ oldEols = 0;
+ NextCh();
+ if (ch == 0xEF) { // check optional byte order mark for UTF-8
+ NextCh(); int ch1 = ch;
+ NextCh(); int ch2 = ch;
+ if (ch1 != 0xBB || ch2 != 0xBF) {
+ throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
+ }
+ buffer = new UTF8Buffer(buffer); col = 0;
+ NextCh();
+ }
+ pt = tokens = new Token(); // first token is a dummy
+ }
+
+ string/*!*/ ReadToEOL(){
+ Contract.Ensures(Contract.Result<string>() != null);
+ int p = buffer.Pos;
+ int ch = buffer.Read();
+ // replace isolated '\r' by '\n' in order to make
+ // eol handling uniform across Windows, Unix and Mac
+ if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
+ while (ch != EOL && ch != Buffer.EOF){
+ ch = buffer.Read();
+ // replace isolated '\r' by '\n' in order to make
+ // eol handling uniform across Windows, Unix and Mac
+ if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
+ }
+ string/*!*/ s = buffer.GetString(p, buffer.Pos);
+ Contract.Assert(s!=null);
+ return s;
+ }
+
+ void NextCh() {
+ if (oldEols > 0) { ch = EOL; oldEols--; }
+ else {
+// pos = buffer.Pos;
+// ch = buffer.Read(); col++;
+// // replace isolated '\r' by '\n' in order to make
+// // eol handling uniform across Windows, Unix and Mac
+// if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
+// if (ch == EOL) { line++; col = 0; }
+
+ while (true) {
+ pos = buffer.Pos;
+ ch = buffer.Read(); col++;
+ // replace isolated '\r' by '\n' in order to make
+ // eol handling uniform across Windows, Unix and Mac
+ if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
+ if (ch == EOL) {
+ line++; col = 0;
+ } else if (ch == '#' && col == 1) {
+ int prLine = line;
+ int prColumn = 0;
+
+ string/*!*/ hashLine = ReadToEOL();
+ Contract.Assert(hashLine!=null);
+ col = 0;
+ line++;
+
+ hashLine = hashLine.TrimEnd(null);
+ if (hashLine.StartsWith("line ") || hashLine == "line") {
+ // parse #line pragma: #line num [filename]
+ string h = hashLine.Substring(4).TrimStart(null);
+ int x = h.IndexOf(' ');
+ if (x == -1) {
+ x = h.Length; // this will be convenient below when we look for a filename
+ }
+ try {
+ int li = int.Parse(h.Substring(0, x));
+
+ h = h.Substring(x).Trim();
+
+ // act on #line
+ line = li;
+ if (h.Length != 0) {
+ // a filename was specified
+ Filename = h;
+ }
+ continue; // successfully parsed and acted on the #line pragma
+
+ } catch (FormatException) {
+ // just fall down through to produce an error message
+ }
+ this.errorHandler.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
+ continue;
+ }
+
+ this.errorHandler.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
+ continue;
+ }
+ return;
+ }
+
+
+ }
+
+ }
+
+ void AddCh() {
+ if (tlen >= tval.Length) {
+ char[] newBuf = new char[2 * tval.Length];
+ Array.Copy(tval, 0, newBuf, 0, tval.Length);
+ tval = newBuf;
+ }
+ if (ch != Buffer.EOF) {
+ tval[tlen++] = (char) ch;
+ NextCh();
+ }
+ }
+
+
+
+ bool Comment0() {
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+ NextCh();
+ if (ch == '/') {
+ NextCh();
+ for(;;) {
+ if (ch == 10) {
+ level--;
+ if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+ NextCh();
+ } else if (ch == Buffer.EOF) return false;
+ else NextCh();
+ }
+ } else {
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
+ }
+ return false;
+ }
+
+ bool Comment1() {
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+ NextCh();
+ if (ch == '*') {
+ NextCh();
+ for(;;) {
+ if (ch == '*') {
+ NextCh();
+ if (ch == '/') {
+ level--;
+ if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+ NextCh();
+ }
+ } else if (ch == '/') {
+ NextCh();
+ if (ch == '*') {
+ level++; NextCh();
+ }
+ } else if (ch == Buffer.EOF) return false;
+ else NextCh();
+ }
+ } else {
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
+ }
+ return false;
+ }
+
+
+ void CheckLiteral() {
+ switch (t.val) {
+ case "var": t.kind = 7; break;
+ case "where": t.kind = 13; break;
+ case "int": t.kind = 14; break;
+ case "real": t.kind = 15; break;
+ case "bool": t.kind = 16; break;
+ case "fp": t.kind = 97; break;
+ case "float": case "float16": case "float32": case "float64": case "float128": t.kind = 98; break;
+ case "const": t.kind = 21; break;
+ case "unique": t.kind = 22; break;
+ case "extends": t.kind = 23; break;
+ case "complete": t.kind = 24; break;
+ case "function": t.kind = 25; break;
+ case "returns": t.kind = 26; break;
+ case "axiom": t.kind = 29; break;
+ case "type": t.kind = 30; break;
+ case "procedure": t.kind = 32; break;
+ case "implementation": t.kind = 33; break;
+ case "modifies": t.kind = 34; break;
+ case "free": t.kind = 35; break;
+ case "requires": t.kind = 36; break;
+ case "ensures": t.kind = 37; break;
+ case "goto": t.kind = 38; break;
+ case "return": t.kind = 39; break;
+ case "if": t.kind = 40; break;
+ case "else": t.kind = 41; break;
+ case "while": t.kind = 42; break;
+ case "invariant": t.kind = 43; break;
+ case "break": t.kind = 45; break;
+ case "assert": t.kind = 46; break;
+ case "assume": t.kind = 47; break;
+ case "havoc": t.kind = 48; break;
+ case "yield": t.kind = 49; break;
+ case "async": t.kind = 51; break;
+ case "call": t.kind = 52; break;
+ case "par": t.kind = 53; break;
+ case "div": t.kind = 76; break;
+ case "mod": t.kind = 77; break;
+ case "false": t.kind = 82; break;
+ case "true": t.kind = 83; break;
+ case "old": t.kind = 84; break;
+ case "then": t.kind = 87; break;
+ case "forall": t.kind = 88; break;
+ case "exists": t.kind = 90; break;
+ case "lambda": t.kind = 92; break;
+ default: break;
+ }
+ }
+
+ Token/*!*/ NextToken() {
+ Contract.Ensures(Contract.Result<Token>() != null);
+ while (ch == ' ' ||
+ ch >= 9 && ch <= 10 || ch == 13
+ ) NextCh();
+ if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
+ int recKind = noSym;
+ int recEnd = pos;
+ t = new Token();
+ t.pos = pos; t.col = col; t.line = line;
+ t.filename = this.Filename;
+ int state;
+ if (start.ContainsKey(ch)) {
+ Contract.Assert(start[ch] != null);
+ state = (int) start[ch];
+ }
+ else { state = 0; }
+ tlen = 0; AddCh();
+
+ switch (state) {
+ case -1: { t.kind = eofSym; break; } // NextCh already done
+ case 0: {
+ if (recKind != noSym) {
+ tlen = recEnd - t.pos;
+ SetScannerBehindT();
+ }
+ t.kind = recKind; break;
+ } // NextCh already done
+ case 1:
+ if (ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~') {AddCh(); goto case 2;}
+ else {goto case 0;}
+ case 2:
+ recEnd = pos; recKind = 1;
+ if (ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~') {AddCh(); goto case 2;}
+ else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
+ case 3:
+ if (ch == 'v') {AddCh(); goto case 4;}
+ else {goto case 0;}
+ case 4:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 5;}
+ else {goto case 0;}
+ case 5:
+ recEnd = pos; recKind = 2;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 5;}
+ else {t.kind = 2; break;}
+ case 6:
+ if (ch == '"') {AddCh(); goto case 7;}
+ else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
+ else if (ch == 92) {AddCh(); goto case 17;}
+ else {goto case 0;}
+ case 7:
+ {t.kind = 4; break;}
+ case 8:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
+ else if (ch == '-') {AddCh(); goto case 9;}
+ else {goto case 0;}
+ case 9:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
+ else {goto case 0;}
+ case 10:
+ recEnd = pos; recKind = 5;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
+ else {t.kind = 5; break;}
+ case 11:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;}
+ else {goto case 0;}
+ case 12:
+ recEnd = pos; recKind = 6;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;}
+ else if (ch == 'e') {AddCh(); goto case 13;}
+ else {t.kind = 6; break;}
+ case 13:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
+ else if (ch == '-') {AddCh(); goto case 14;}
+ else {goto case 0;}
+ case 14:
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
+ else {goto case 0;}
+ case 15:
+ recEnd = pos; recKind = 6;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;}
+ else {t.kind = 6; break;}
+ case 16:
+ recEnd = pos; recKind = 3;
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 16;}
+ else if (ch == 'b') {AddCh(); goto case 3;}
+ else if (ch == 'e') {AddCh(); goto case 8;}
+ else if (ch == '.') {AddCh(); goto case 11;}
+ else {t.kind = 3; break;}
+ case 17:
+ if (ch == '"') {AddCh(); goto case 18;}
+ else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
+ else if (ch == 92) {AddCh(); goto case 17;}
+ else {goto case 0;}
+ case 18:
+ recEnd = pos; recKind = 4;
+ if (ch == '"') {AddCh(); goto case 7;}
+ else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;}
+ else if (ch == 92) {AddCh(); goto case 17;}
+ else {t.kind = 4; break;}
+ case 19:
+ {t.kind = 8; break;}
+ case 20:
+ {t.kind = 9; break;}
+ case 21:
+ {t.kind = 10; break;}
+ case 22:
+ {t.kind = 12; break;}
+ case 23:
+ {t.kind = 17; break;}
+ case 24:
+ {t.kind = 18; break;}
+ case 25:
+ {t.kind = 27; break;}
+ case 26:
+ {t.kind = 50; break;}
+ case 27:
+ {t.kind = 55; break;}
+ case 28:
+ {t.kind = 56; break;}
+ case 29:
+ {t.kind = 57; break;}
+ case 30:
+ {t.kind = 58; break;}
+ case 31:
+ {t.kind = 60; break;}
+ case 32:
+ if (ch == '&') {AddCh(); goto case 33;}
+ else {goto case 0;}
+ case 33:
+ {t.kind = 61; break;}
+ case 34:
+ {t.kind = 62; break;}
+ case 35:
+ {t.kind = 63; break;}
+ case 36:
+ {t.kind = 64; break;}
+ case 37:
+ {t.kind = 67; break;}
+ case 38:
+ {t.kind = 68; break;}
+ case 39:
+ {t.kind = 69; break;}
+ case 40:
+ {t.kind = 70; break;}
+ case 41:
+ {t.kind = 71; break;}
+ case 42:
+ {t.kind = 72; break;}
+ case 43:
+ {t.kind = 73; break;}
+ case 44:
+ {t.kind = 75; break;}
+ case 45:
+ {t.kind = 78; break;}
+ case 46:
+ {t.kind = 79; break;}
+ case 47:
+ {t.kind = 81; break;}
+ case 48:
+ {t.kind = 85; break;}
+ case 49:
+ {t.kind = 86; break;}
+ case 50:
+ {t.kind = 89; break;}
+ case 51:
+ {t.kind = 91; break;}
+ case 52:
+ {t.kind = 93; break;}
+ case 53:
+ {t.kind = 94; break;}
+ case 54:
+ {t.kind = 95; break;}
+ case 55:
+ recEnd = pos; recKind = 11;
+ if (ch == '=') {AddCh(); goto case 26;}
+ else if (ch == ':') {AddCh(); goto case 53;}
+ else {t.kind = 11; break;}
+ case 56:
+ recEnd = pos; recKind = 19;
+ if (ch == '=') {AddCh(); goto case 64;}
+ else if (ch == ':') {AddCh(); goto case 39;}
+ else {t.kind = 19; break;}
+ case 57:
+ recEnd = pos; recKind = 20;
+ if (ch == '=') {AddCh(); goto case 37;}
+ else {t.kind = 20; break;}
+ case 58:
+ recEnd = pos; recKind = 28;
+ if (ch == '|') {AddCh(); goto case 49;}
+ else {t.kind = 28; break;}
+ case 59:
+ recEnd = pos; recKind = 31;
+ if (ch == '=') {AddCh(); goto case 65;}
+ else {t.kind = 31; break;}
+ case 60:
+ recEnd = pos; recKind = 44;
+ if (ch == '*') {AddCh(); goto case 46;}
+ else {t.kind = 44; break;}
+ case 61:
+ recEnd = pos; recKind = 54;
+ if (ch == '|') {AddCh(); goto case 35;}
+ else if (ch == '{') {AddCh(); goto case 48;}
+ else {t.kind = 54; break;}
+ case 62:
+ recEnd = pos; recKind = 80;
+ if (ch == '=') {AddCh(); goto case 38;}
+ else {t.kind = 80; break;}
+ case 63:
+ recEnd = pos; recKind = 74;
+ if (ch == '+') {AddCh(); goto case 43;}
+ else {t.kind = 74; break;}
+ case 64:
+ recEnd = pos; recKind = 66;
+ if (ch == '=') {AddCh(); goto case 66;}
+ else {t.kind = 66; break;}
+ case 65:
+ recEnd = pos; recKind = 65;
+ if (ch == '>') {AddCh(); goto case 29;}
+ else {t.kind = 65; break;}
+ case 66:
+ recEnd = pos; recKind = 59;
+ if (ch == '>') {AddCh(); goto case 27;}
+ else {t.kind = 59; break;}
+
+ }
+ t.val = new String(tval, 0, tlen);
+ return t;
+ }
+
+ private void SetScannerBehindT() {
+ buffer.Pos = t.pos;
+ NextCh();
+ line = t.line; col = t.col;
+ for (int i = 0; i < tlen; i++) NextCh();
+ }
+
+ // get the next token (possibly a token already seen during peeking)
+ public Token/*!*/ Scan () {
+ Contract.Ensures(Contract.Result<Token>() != null);
+ if (tokens.next == null) {
+ return NextToken();
+ } else {
+ pt = tokens = tokens.next;
+ return tokens;
+ }
+ }
+
+ // peek for the next token, ignore pragmas
+ public Token/*!*/ Peek () {
+ Contract.Ensures(Contract.Result<Token>() != null);
+ do {
+ if (pt.next == null) {
+ pt.next = NextToken();
+ }
+ pt = pt.next;
+ } while (pt.kind > maxT); // skip pragmas
+
+ return pt;
+ }
+
+ // make sure that peeking starts at the current scan position
+ public void ResetPeek () { pt = tokens; }
+
+} // end Scanner
+
+public delegate void ErrorProc(int n, string filename, int line, int col);
+
+
} \ No newline at end of file
diff --git a/Source/Core/StandardVisitor.cs b/Source/Core/StandardVisitor.cs
index 97215cfb..c3d8a672 100644
--- a/Source/Core/StandardVisitor.cs
+++ b/Source/Core/StandardVisitor.cs
@@ -1,1167 +1,1167 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - StandardVisitor.cs
-//---------------------------------------------------------------------------------------------
-
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-
-namespace Microsoft.Boogie {
- [ContractClass(typeof(VisitorContracts))]
- /// <summary>
- /// Base for all classes that process the Absy using the visitor pattern.
- /// </summary>
- public abstract class Visitor {
- /// <summary>
- /// Switches on node.NodeType to call a visitor method that has been specialized for node.
- /// </summary>
- /// <param name="a">The Absy node to be visited.</param>
- /// <returns> Returns null if node is null. Otherwise returns an updated node (possibly a different object).</returns>
- public abstract Absy/*!*/ Visit(Absy/*!*/ node);
-
- /// <summary>
- /// Transfers the state from one visitor to another. This enables separate visitor instances to cooperative process a single IR.
- /// </summary>
- public virtual void TransferStateTo(Visitor targetVisitor) {
- }
-
- public virtual IList<Expr> VisitExprSeq(IList<Expr> list) {
- Contract.Requires(list != null);
- Contract.Ensures(Contract.Result<IList<Expr>>() != null);
- lock (list)
- {
- for (int i = 0, n = list.Count; i < n; i++)
- list[i] = (Expr)this.Visit(cce.NonNull(list[i]));
- }
- return list;
- }
- }
- [ContractClassFor(typeof(Visitor))]
- abstract class VisitorContracts : Visitor {
- public override Absy Visit(Absy node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- throw new System.NotImplementedException();
- }
- }
-
- /// <summary>
- /// Walks an IR, mutating it into a new form. (For a subclass that does not mutate the IR, see ReadOnlyVisitor.)
- /// </summary>
- public abstract class StandardVisitor : Visitor {
- public Visitor callingVisitor;
-
- public StandardVisitor() {
- }
- public StandardVisitor(Visitor callingVisitor) {
- this.callingVisitor = callingVisitor;
- }
- public override Absy Visit(Absy node) {
- return node.StdDispatch(this);
- }
- public virtual Cmd VisitAssertCmd(AssertCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Cmd VisitAssignCmd(AssignCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- for (int i = 0; i < node.Lhss.Count; ++i) {
- node.SetLhs(i, cce.NonNull((AssignLhs)this.Visit(node.Lhss[i])));
- node.SetRhs(i, cce.NonNull((Expr/*!*/)this.Visit(node.Rhss[i])));
- }
- return node;
- }
- public virtual Cmd VisitAssumeCmd(AssumeCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual AtomicRE VisitAtomicRE(AtomicRE node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AtomicRE>() != null);
- node.b = this.VisitBlock(node.b);
- return node;
- }
- public virtual Axiom VisitAxiom(Axiom node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Axiom>() != null);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Type VisitBasicType(BasicType node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.VisitType(node);
- }
- public virtual Type VisitFloatType(FloatType node)
- {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.VisitType(node);
- }
- public virtual Expr VisitBvConcatExpr(BvConcatExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node.E0 = this.VisitExpr(node.E0);
- node.E1 = this.VisitExpr(node.E1);
- return node;
- }
- public virtual Type VisitBvType(BvType node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.VisitType(node);
- }
- public virtual Type VisitBvTypeProxy(BvTypeProxy node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- return (Type)this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
- public virtual Block VisitBlock(Block node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Block>() != null);
- node.Cmds = this.VisitCmdSeq(node.Cmds);
- node.TransferCmd = (TransferCmd)this.Visit(cce.NonNull(node.TransferCmd));
- return node;
- }
- public virtual Expr VisitCodeExpr(CodeExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node.LocVars = this.VisitVariableSeq(node.LocVars);
- node.Blocks = this.VisitBlockList(node.Blocks);
- return node;
- }
- public virtual List<Block> VisitBlockSeq(List<Block> blockSeq) {
- Contract.Requires(blockSeq != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
- lock (blockSeq)
- {
- for (int i = 0, n = blockSeq.Count; i < n; i++)
- blockSeq[i] = this.VisitBlock(cce.NonNull(blockSeq[i]));
- }
- return blockSeq;
- }
- public virtual List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
- Contract.Requires(blocks != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
- for (int i = 0, n = blocks.Count; i < n; i++) {
- blocks[i] = this.VisitBlock(blocks[i]);
- }
- return blocks;
- }
- public virtual BoundVariable VisitBoundVariable(BoundVariable node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<BoundVariable>() != null);
- node = (BoundVariable)this.VisitVariable(node);
- return node;
- }
- public virtual Cmd VisitCallCmd(CallCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- for (int i = 0; i < node.Ins.Count; ++i)
- if (node.Ins[i] != null)
- node.Ins[i] = this.VisitExpr(cce.NonNull(node.Ins[i]));
- for (int i = 0; i < node.Outs.Count; ++i)
- if (node.Outs[i] != null)
- node.Outs[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(node.Outs[i]));
- return node;
- }
- public virtual Cmd VisitParCallCmd(ParCallCmd node)
- {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- for (int i = 0; i < node.CallCmds.Count; i++)
- {
- if (node.CallCmds[i] != null)
- node.CallCmds[i] = (CallCmd)this.VisitCallCmd(node.CallCmds[i]);
- }
- return node;
- }
- public virtual List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
- Contract.Requires(cmdSeq != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- lock (cmdSeq)
- {
- for (int i = 0, n = cmdSeq.Count; i < n; i++)
- cmdSeq[i] = (Cmd)this.Visit(cce.NonNull(cmdSeq[i])); // call general Visit so subtypes of Cmd get visited by their particular visitor
- }
- return cmdSeq;
- }
- public virtual Choice VisitChoice(Choice node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Choice>() != null);
- node.rs = this.VisitRESeq(node.rs);
- return node;
- }
- public virtual Cmd VisitCommentCmd(CommentCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return node;
- }
- public virtual Constant VisitConstant(Constant node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Constant>() != null);
- return node;
- }
- public virtual CtorType VisitCtorType(CtorType node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<CtorType>() != null);
- lock (node)
- {
- for (int i = 0; i < node.Arguments.Count; ++i)
- node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
- }
- return node;
- }
- public virtual Declaration VisitDeclaration(Declaration node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Declaration>() != null);
- return node;
- }
- public virtual List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
- Contract.Requires(declarationList != null);
- Contract.Ensures(Contract.Result<List<Declaration>>() != null);
- for (int i = 0, n = declarationList.Count; i < n; i++)
- declarationList[i] = cce.NonNull((Declaration/*!*/)this.Visit(declarationList[i]));
- return declarationList;
- }
- public virtual DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
- node.InParams = this.VisitVariableSeq(node.InParams);
- node.OutParams = this.VisitVariableSeq(node.OutParams);
- return node;
- }
- public virtual Expr VisitExistsExpr(ExistsExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (ExistsExpr)this.VisitQuantifierExpr(node);
- return node;
- }
- public virtual Expr VisitBvExtractExpr(BvExtractExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node.Bitvector = this.VisitExpr(node.Bitvector);
- return node;
- }
- public virtual Expr VisitExpr(Expr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Expr e = (Expr)this.Visit(node);
- return e;
- }
- public override IList<Expr> VisitExprSeq(IList<Expr> exprSeq) {
- //Contract.Requires(exprSeq != null);
- Contract.Ensures(Contract.Result<IList<Expr>>() != null);
- for (int i = 0, n = exprSeq.Count; i < n; i++)
- exprSeq[i] = this.VisitExpr(cce.NonNull(exprSeq[i]));
- return exprSeq;
- }
- public virtual Requires VisitRequires(Requires @requires) {
- Contract.Requires(@requires != null);
- Contract.Ensures(Contract.Result<Requires>() != null);
- @requires.Condition = this.VisitExpr(@requires.Condition);
- return @requires;
- }
- public virtual List<Requires> VisitRequiresSeq(List<Requires> requiresSeq) {
- Contract.Requires(requiresSeq != null);
- Contract.Ensures(Contract.Result<List<Requires>>() != null);
- for (int i = 0, n = requiresSeq.Count; i < n; i++)
- requiresSeq[i] = this.VisitRequires(requiresSeq[i]);
- return requiresSeq;
- }
- public virtual Ensures VisitEnsures(Ensures @ensures) {
- Contract.Requires(@ensures != null);
- Contract.Ensures(Contract.Result<Ensures>() != null);
- @ensures.Condition = this.VisitExpr(@ensures.Condition);
- return @ensures;
- }
- public virtual List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq) {
- Contract.Requires(ensuresSeq != null);
- Contract.Ensures(Contract.Result<List<Ensures>>() != null);
- for (int i = 0, n = ensuresSeq.Count; i < n; i++)
- ensuresSeq[i] = this.VisitEnsures(ensuresSeq[i]);
- return ensuresSeq;
- }
- public virtual Expr VisitForallExpr(ForallExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (ForallExpr)this.VisitQuantifierExpr(node);
- return node;
- }
- public virtual Expr VisitLambdaExpr(LambdaExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (LambdaExpr)this.VisitBinderExpr(node);
- return node;
- }
- public virtual Formal VisitFormal(Formal node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Formal>() != null);
- return node;
- }
- public virtual Function VisitFunction(Function node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- node = (Function)this.VisitDeclWithFormals(node);
- if (node.Body != null)
- node.Body = this.VisitExpr(node.Body);
- return node;
- }
- public virtual GlobalVariable VisitGlobalVariable(GlobalVariable node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GlobalVariable>() != null);
- node = (GlobalVariable)this.VisitVariable(node);
- return node;
- }
- public virtual GotoCmd VisitGotoCmd(GotoCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GotoCmd>() != null);
- // do not visit the labelTargets, or control-flow loops will lead to a looping visitor
- return node;
- }
- public virtual Cmd VisitHavocCmd(HavocCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- node.Vars = this.VisitIdentifierExprSeq(node.Vars);
- return node;
- }
- public virtual Expr VisitIdentifierExpr(IdentifierExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- if (node.Decl != null)
- node.Decl = this.VisitVariable(node.Decl);
- return node;
- }
- public virtual List<IdentifierExpr> VisitIdentifierExprSeq(List<IdentifierExpr> identifierExprSeq) {
- Contract.Requires(identifierExprSeq != null);
- Contract.Ensures(Contract.Result<List<IdentifierExpr>>() != null);
- lock (identifierExprSeq)
- {
- for (int i = 0, n = identifierExprSeq.Count; i < n; i++)
- identifierExprSeq[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(identifierExprSeq[i]));
- }
- return identifierExprSeq;
- }
- public virtual Implementation VisitImplementation(Implementation node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- node.LocVars = this.VisitVariableSeq(node.LocVars);
- node.Blocks = this.VisitBlockList(node.Blocks);
- node.Proc = this.VisitProcedure(cce.NonNull(node.Proc));
- node = (Implementation)this.VisitDeclWithFormals(node); // do this first or last?
- return node;
- }
- public virtual Expr VisitLiteralExpr(LiteralExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- return node;
- }
-
- public virtual LocalVariable VisitLocalVariable(LocalVariable node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<LocalVariable>() != null);
- return node;
- }
-
- public virtual AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- node.Map = cce.NonNull((AssignLhs)this.Visit(node.Map));
- for (int i = 0; i < node.Indexes.Count; ++i)
- node.Indexes[i] = cce.NonNull((Expr)this.Visit(node.Indexes[i]));
- return node;
- }
- public virtual MapType VisitMapType(MapType node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<MapType>() != null);
- // not doing anything about the bound variables ... maybe
- // these should be visited as well ...
- //
- // NOTE: when overriding this method, you have to make sure that
- // the bound variables of the map type are updated correctly
- lock (node.Arguments)
- {
- for (int i = 0; i < node.Arguments.Count; ++i)
- node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
- }
- node.Result = cce.NonNull((Type/*!*/)this.Visit(node.Result));
- return node;
- }
- public virtual Type VisitMapTypeProxy(MapTypeProxy node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- return (Type)this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
-
- public virtual Expr VisitNAryExpr(NAryExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node.Args = this.VisitExprSeq(node.Args);
- return node;
- }
- public virtual Expr VisitOldExpr(OldExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Procedure VisitProcedure(Procedure node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Procedure>() != null);
- node.Ensures = this.VisitEnsuresSeq(node.Ensures);
- node.InParams = this.VisitVariableSeq(node.InParams);
- node.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
- node.OutParams = this.VisitVariableSeq(node.OutParams);
- node.Requires = this.VisitRequiresSeq(node.Requires);
- return node;
- }
- public virtual Program VisitProgram(Program node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Program>() != null);
- var decls = node.TopLevelDeclarations.ToList();
- node.ClearTopLevelDeclarations();
- node.AddTopLevelDeclarations(this.VisitDeclarationList(decls));
- return node;
- }
- public virtual QKeyValue VisitQKeyValue(QKeyValue node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<QKeyValue>() != null);
- var newParams = new List<object>();
- for (int i = 0, n = node.Params.Count; i < n; i++) {
- var e = node.Params[i] as Expr;
- newParams.Add(e != null ? this.Visit(e) : node.Params[i]);
- }
- node.ClearParams();
- node.AddParams(newParams);
- if (node.Next != null) {
- node.Next = (QKeyValue)this.Visit(node.Next);
- }
- return node;
- }
- public virtual BinderExpr VisitBinderExpr(BinderExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<BinderExpr>() != null);
- node.Body = this.VisitExpr(node.Body);
- node.Dummies = this.VisitVariableSeq(node.Dummies);
- //node.Type = this.VisitType(node.Type);
- return node;
- }
- public virtual QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<QuantifierExpr>() != null);
- node = cce.NonNull((QuantifierExpr)this.VisitBinderExpr(node));
- if (node.Triggers != null) {
- node.Triggers = this.VisitTrigger(node.Triggers);
- }
- return node;
- }
- public virtual Cmd VisitRE(RE node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- return (Cmd)this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
- }
- public virtual List<RE> VisitRESeq(List<RE> reSeq) {
- Contract.Requires(reSeq != null);
- Contract.Ensures(Contract.Result<List<RE>>() != null);
- for (int i = 0, n = reSeq.Count; i < n; i++)
- reSeq[i] = (RE)this.VisitRE(cce.NonNull(reSeq[i]));
- return reSeq;
- }
- public virtual ReturnCmd VisitReturnCmd(ReturnCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnCmd>() != null);
- return (ReturnCmd)this.VisitTransferCmd(node);
- }
- public virtual ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Sequential VisitSequential(Sequential node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Sequential>() != null);
- node.first = (RE)this.VisitRE(node.first);
- node.second = (RE)this.VisitRE(node.second);
- return node;
- }
- public virtual AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- node.AssignedVariable =
- (IdentifierExpr)this.VisitIdentifierExpr(node.AssignedVariable);
- return node;
- }
- public virtual Cmd VisitStateCmd(StateCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- node.Locals = this.VisitVariableSeq(node.Locals);
- node.Cmds = this.VisitCmdSeq(node.Cmds);
- return node;
- }
- public virtual TransferCmd VisitTransferCmd(TransferCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TransferCmd>() != null);
- return node;
- }
- public virtual Trigger VisitTrigger(Trigger node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Trigger>() != null);
- Trigger origNext = node.Next;
- if (origNext != null) {
- Trigger newNext = this.VisitTrigger(origNext);
- if (newNext != origNext) {
- node = new Trigger(node.tok, node.Pos, node.Tr.ToList());
- node.Next = newNext;
- }
- }
- node.Tr = this.VisitExprSeq(node.Tr.ToList());
- return node;
- }
- // called by default for all nullary type constructors and type variables
- public virtual Type VisitType(Type node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return node;
- }
- public virtual TypedIdent VisitTypedIdent(TypedIdent node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TypedIdent>() != null);
- node.Type = (Type)this.Visit(node.Type);
- return node;
- }
- public virtual Declaration VisitTypeCtorDecl(TypeCtorDecl node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Declaration>() != null);
- return this.VisitDeclaration(node);
- }
- public virtual Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- node.ExpandedType = cce.NonNull((Type/*!*/)this.Visit(node.ExpandedType));
- lock (node.Arguments)
- {
- for (int i = 0; i < node.Arguments.Count; ++i)
- node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
- }
- return node;
- }
- public virtual Declaration VisitTypeSynonymDecl(TypeSynonymDecl node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Declaration>() != null);
- return this.VisitDeclaration(node);
- }
- public virtual Type VisitTypeVariable(TypeVariable node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.VisitType(node);
- }
- public virtual Type VisitTypeProxy(TypeProxy node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- return cce.NonNull((Type/*!*/)this.Visit(node.ProxyFor));
- return this.VisitType(node);
- }
- public virtual Type VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- return this.VisitType(node);
- }
- public virtual Variable VisitVariable(Variable node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
- node.TypedIdent = this.VisitTypedIdent(node.TypedIdent);
- return node;
- }
- public virtual List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
- Contract.Requires(variableSeq != null);
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- lock (variableSeq)
- {
- for (int i = 0, n = variableSeq.Count; i < n; i++)
- variableSeq[i] = this.VisitVariable(cce.NonNull(variableSeq[i]));
- }
- return variableSeq;
- }
- public virtual YieldCmd VisitYieldCmd(YieldCmd node)
- {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<YieldCmd>() != null);
- return node;
- }
- public virtual Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- node.Ensures = this.VisitEnsures(node.Ensures);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- node.Requires = this.VisitRequires(node.Requires);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- }
-
- /// <summary>
- /// A ReadOnlyVisitor visits all the nodes of a given Absy. The visitor may collect information from
- /// the nodes, may change fields contained in the data structure, but may not replace any nodes in the
- /// data structure. To enforce this, all Visit...(node) methods have a postcondition that says that
- /// the return value is equal to the given "node".
- /// </summary>
- public abstract class ReadOnlyVisitor : StandardVisitor
- {
- public ReadOnlyVisitor()
- {
- }
- public ReadOnlyVisitor(Visitor callingVisitor)
- {
- this.callingVisitor = callingVisitor;
- }
- public override Absy Visit(Absy node)
- {
- Contract.Ensures(Contract.Result<Absy>() == node);
- return node.StdDispatch(this);
- }
- public override Cmd VisitAssertCmd(AssertCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- this.VisitExpr(node.Expr);
- return node;
- }
- public override Cmd VisitAssignCmd(AssignCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- for (int i = 0; i < node.Lhss.Count; ++i)
- {
- this.Visit(node.Lhss[i]);
- this.Visit(node.Rhss[i]);
- }
- return node;
- }
- public override Cmd VisitAssumeCmd(AssumeCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- this.VisitExpr(node.Expr);
- return node;
- }
- public override AtomicRE VisitAtomicRE(AtomicRE node)
- {
- Contract.Ensures(Contract.Result<AtomicRE>() == node);
- this.VisitBlock(node.b);
- return node;
- }
- public override Axiom VisitAxiom(Axiom node)
- {
- Contract.Ensures(Contract.Result<Axiom>() == node);
- this.VisitExpr(node.Expr);
- return node;
- }
- public override Type VisitBasicType(BasicType node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- return this.VisitType(node);
- }
- public override Expr VisitBvConcatExpr(BvConcatExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- this.VisitExpr(node.E0);
- this.VisitExpr(node.E1);
- return node;
- }
- public override Type VisitBvType(BvType node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- return this.VisitType(node);
- }
- public override Type VisitBvTypeProxy(BvTypeProxy node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
- public override Block VisitBlock(Block node)
- {
- Contract.Ensures(Contract.Result<Block>() == node);
- this.VisitCmdSeq(node.Cmds);
- this.Visit(cce.NonNull(node.TransferCmd));
- return node;
- }
- public override Expr VisitCodeExpr(CodeExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- this.VisitVariableSeq(node.LocVars);
- this.VisitBlockList(node.Blocks);
- return node;
- }
- public override List<Block> VisitBlockSeq(List<Block> blockSeq)
- {
- Contract.Ensures(Contract.Result<List<Block>>() == blockSeq);
- for (int i = 0, n = blockSeq.Count; i < n; i++)
- this.VisitBlock(cce.NonNull(blockSeq[i]));
- return blockSeq;
- }
- public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks)
- {
- Contract.Ensures(Contract.Result<List<Block>>() == blocks);
- for (int i = 0, n = blocks.Count; i < n; i++)
- {
- this.VisitBlock(blocks[i]);
- }
- return blocks;
- }
- public override BoundVariable VisitBoundVariable(BoundVariable node)
- {
- Contract.Ensures(Contract.Result<BoundVariable>() == node);
- return (BoundVariable)this.VisitVariable(node);
- }
- public override Cmd VisitCallCmd(CallCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- for (int i = 0; i < node.Ins.Count; ++i)
- if (node.Ins[i] != null)
- this.VisitExpr(node.Ins[i]);
- for (int i = 0; i < node.Outs.Count; ++i)
- if (node.Outs[i] != null)
- this.VisitIdentifierExpr(node.Outs[i]);
- return node;
- }
- public override Cmd VisitParCallCmd(ParCallCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- for (int i = 0; i < node.CallCmds.Count; i++)
- {
- if (node.CallCmds[i] != null)
- this.VisitCallCmd(node.CallCmds[i]);
- }
- return node;
- }
- public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq)
- {
- Contract.Ensures(Contract.Result<List<Cmd>>() == cmdSeq);
- for (int i = 0, n = cmdSeq.Count; i < n; i++)
- this.Visit(cce.NonNull(cmdSeq[i])); // call general Visit so subtypes of Cmd get visited by their particular visitor
- return cmdSeq;
- }
- public override Choice VisitChoice(Choice node)
- {
- Contract.Ensures(Contract.Result<Choice>() == node);
- this.VisitRESeq(node.rs);
- return node;
- }
- public override Cmd VisitCommentCmd(CommentCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- return node;
- }
- public override Constant VisitConstant(Constant node)
- {
- Contract.Ensures(Contract.Result<Constant>() == node);
- return node;
- }
- public override CtorType VisitCtorType(CtorType node)
- {
- Contract.Ensures(Contract.Result<CtorType>() == node);
- for (int i = 0; i < node.Arguments.Count; ++i)
- this.Visit(node.Arguments[i]);
- return node;
- }
- public override Declaration VisitDeclaration(Declaration node)
- {
- Contract.Ensures(Contract.Result<Declaration>() == node);
- return node;
- }
- public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList)
- {
- Contract.Ensures(Contract.Result<List<Declaration>>() == declarationList);
- for (int i = 0, n = declarationList.Count; i < n; i++)
- this.Visit(declarationList[i]);
- return declarationList;
- }
- public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node)
- {
- Contract.Ensures(Contract.Result<DeclWithFormals>() == node);
- this.VisitVariableSeq(node.InParams);
- this.VisitVariableSeq(node.OutParams);
- return node;
- }
- public override Expr VisitExistsExpr(ExistsExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- return (ExistsExpr)this.VisitQuantifierExpr(node);
- }
- public override Expr VisitBvExtractExpr(BvExtractExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- this.VisitExpr(node.Bitvector);
- return node;
- }
- public override Expr VisitExpr(Expr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- return (Expr)this.Visit(node);
- }
- public override IList<Expr> VisitExprSeq(IList<Expr> exprSeq)
- {
- Contract.Ensures(Contract.Result<IList<Expr>>() == exprSeq);
- for (int i = 0, n = exprSeq.Count; i < n; i++)
- this.VisitExpr(cce.NonNull(exprSeq[i]));
- return exprSeq;
- }
- public override Requires VisitRequires(Requires requires)
- {
- Contract.Ensures(Contract.Result<Requires>() == requires);
- this.VisitExpr(requires.Condition);
- return requires;
- }
- public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq)
- {
- Contract.Ensures(Contract.Result<List<Requires>>() == requiresSeq);
- for (int i = 0, n = requiresSeq.Count; i < n; i++)
- this.VisitRequires(requiresSeq[i]);
- return requiresSeq;
- }
- public override Ensures VisitEnsures(Ensures ensures)
- {
- Contract.Ensures(Contract.Result<Ensures>() == ensures);
- this.VisitExpr(ensures.Condition);
- return ensures;
- }
- public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq)
- {
- Contract.Ensures(Contract.Result<List<Ensures>>() == ensuresSeq);
- for (int i = 0, n = ensuresSeq.Count; i < n; i++)
- this.VisitEnsures(ensuresSeq[i]);
- return ensuresSeq;
- }
- public override Expr VisitForallExpr(ForallExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- return (ForallExpr)this.VisitQuantifierExpr(node);
- }
- public override Expr VisitLambdaExpr(LambdaExpr node) {
- Contract.Ensures(Contract.Result<Expr>() == node);
- return this.VisitBinderExpr(node);
- }
- public override Formal VisitFormal(Formal node)
- {
- Contract.Ensures(Contract.Result<Formal>() == node);
- return node;
- }
- public override Function VisitFunction(Function node)
- {
- Contract.Ensures(Contract.Result<Function>() == node);
- node = (Function)this.VisitDeclWithFormals(node);
- if (node.Body != null)
- this.VisitExpr(node.Body);
- return node;
- }
- public override GlobalVariable VisitGlobalVariable(GlobalVariable node)
- {
- Contract.Ensures(Contract.Result<GlobalVariable>() == node);
- return (GlobalVariable)this.VisitVariable(node);
- }
- public override GotoCmd VisitGotoCmd(GotoCmd node)
- {
- Contract.Ensures(Contract.Result<GotoCmd>() == node);
- // do not visit the labelTargets, or control-flow loops will lead to a looping visitor
- return node;
- }
- public override Cmd VisitHavocCmd(HavocCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- this.VisitIdentifierExprSeq(node.Vars);
- return node;
- }
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- if (node.Decl != null)
- this.VisitVariable(node.Decl);
- return node;
- }
- public override List<IdentifierExpr> VisitIdentifierExprSeq(List<IdentifierExpr> identifierExprSeq)
- {
- Contract.Ensures(Contract.Result<List<IdentifierExpr>>() == identifierExprSeq);
- for (int i = 0, n = identifierExprSeq.Count; i < n; i++)
- this.VisitIdentifierExpr(cce.NonNull(identifierExprSeq[i]));
- return identifierExprSeq;
- }
- public override Implementation VisitImplementation(Implementation node)
- {
- Contract.Ensures(Contract.Result<Implementation>() == node);
- this.VisitVariableSeq(node.LocVars);
- this.VisitBlockList(node.Blocks);
- this.VisitProcedure(cce.NonNull(node.Proc));
- return (Implementation)this.VisitDeclWithFormals(node); // do this first or last?
- }
- public override Expr VisitLiteralExpr(LiteralExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- return node;
- }
-
- public override LocalVariable VisitLocalVariable(LocalVariable node)
- {
- Contract.Ensures(Contract.Result<LocalVariable>() == node);
- return node;
- }
-
- public override AssignLhs VisitMapAssignLhs(MapAssignLhs node)
- {
- Contract.Ensures(Contract.Result<AssignLhs>() == node);
- this.Visit(node.Map);
- for (int i = 0; i < node.Indexes.Count; ++i)
- this.Visit(node.Indexes[i]);
- return node;
- }
- public override MapType VisitMapType(MapType node)
- {
- Contract.Ensures(Contract.Result<MapType>() == node);
- // not doing anything about the bound variables ... maybe
- // these should be visited as well ...
- //
- // NOTE: when overriding this method, you have to make sure that
- // the bound variables of the map type are updated correctly
- for (int i = 0; i < node.Arguments.Count; ++i)
- this.Visit(node.Arguments[i]);
- this.Visit(node.Result);
- return node;
- }
- public override Type VisitMapTypeProxy(MapTypeProxy node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- this.VisitExprSeq(node.Args);
- return node;
- }
- public override Expr VisitOldExpr(OldExpr node)
- {
- Contract.Ensures(Contract.Result<Expr>() == node);
- this.VisitExpr(node.Expr);
- return node;
- }
- public override Procedure VisitProcedure(Procedure node)
- {
- Contract.Ensures(Contract.Result<Procedure>() == node);
- this.VisitEnsuresSeq(node.Ensures);
- this.VisitVariableSeq(node.InParams);
- this.VisitIdentifierExprSeq(node.Modifies);
- this.VisitVariableSeq(node.OutParams);
- this.VisitRequiresSeq(node.Requires);
- return node;
- }
- public override Program VisitProgram(Program node)
- {
- Contract.Ensures(Contract.Result<Program>() == node);
- this.VisitDeclarationList(node.TopLevelDeclarations.ToList());
- return node;
- }
- public override QKeyValue VisitQKeyValue(QKeyValue node) {
- Contract.Ensures(Contract.Result<QKeyValue>() == node);
- for (int i = 0, n = node.Params.Count; i < n; i++) {
- var e = node.Params[i] as Expr;
- if (e != null) {
- this.Visit(e);
- }
- }
- if (node.Next != null) {
- this.Visit(node.Next);
- }
- return node;
- }
- public override BinderExpr VisitBinderExpr(BinderExpr node)
- {
- Contract.Ensures(Contract.Result<BinderExpr>() == node);
- this.VisitExpr(node.Body);
- this.VisitVariableSeq(node.Dummies);
- // this.VisitType(node.Type);
- return node;
- }
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
- {
- Contract.Ensures(Contract.Result<QuantifierExpr>() == node);
- this.VisitBinderExpr(node);
- if (node.Triggers != null)
- {
- this.VisitTrigger(node.Triggers);
- }
- return node;
- }
- public override Cmd VisitRE(RE node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- return (Cmd)this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
- }
- public override List<RE> VisitRESeq(List<RE> reSeq)
- {
- Contract.Ensures(Contract.Result<List<RE>>() == reSeq);
- for (int i = 0, n = reSeq.Count; i < n; i++)
- this.VisitRE(cce.NonNull(reSeq[i]));
- return reSeq;
- }
- public override ReturnCmd VisitReturnCmd(ReturnCmd node)
- {
- Contract.Ensures(Contract.Result<ReturnCmd>() == node);
- return (ReturnCmd)this.VisitTransferCmd(node);
- }
- public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node)
- {
- Contract.Ensures(Contract.Result<ReturnExprCmd>() == node);
- this.VisitExpr(node.Expr);
- return node;
- }
- public override Sequential VisitSequential(Sequential node)
- {
- Contract.Ensures(Contract.Result<Sequential>() == node);
- this.VisitRE(node.first);
- this.VisitRE(node.second);
- return node;
- }
- public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node)
- {
- Contract.Ensures(Contract.Result<AssignLhs>() == node);
- this.VisitIdentifierExpr(node.AssignedVariable);
- return node;
- }
- public override Cmd VisitStateCmd(StateCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- this.VisitVariableSeq(node.Locals);
- this.VisitCmdSeq(node.Cmds);
- return node;
- }
- public override TransferCmd VisitTransferCmd(TransferCmd node)
- {
- Contract.Ensures(Contract.Result<TransferCmd>() == node);
- return node;
- }
- public override Trigger VisitTrigger(Trigger node)
- {
- Contract.Ensures(Contract.Result<Trigger>() == node);
- Trigger origNext = node.Next;
- if (origNext != null)
- {
- this.VisitTrigger(origNext);
- }
- this.VisitExprSeq(node.Tr.ToList());
- return node;
- }
- // called by default for all nullary type constructors and type variables
- public override Type VisitType(Type node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- return node;
- }
- public override TypedIdent VisitTypedIdent(TypedIdent node)
- {
- Contract.Ensures(Contract.Result<TypedIdent>() == node);
- this.Visit(node.Type);
- return node;
- }
- public override Declaration VisitTypeCtorDecl(TypeCtorDecl node)
- {
- Contract.Ensures(Contract.Result<Declaration>() == node);
- return this.VisitDeclaration(node);
- }
- public override Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- node.ExpandedType = cce.NonNull((Type/*!*/)this.Visit(node.ExpandedType));
- for (int i = 0; i < node.Arguments.Count; ++i)
- this.Visit(node.Arguments[i]);
- return node;
- }
- public override Declaration VisitTypeSynonymDecl(TypeSynonymDecl node)
- {
- Contract.Ensures(Contract.Result<Declaration>() == node);
- return this.VisitDeclaration(node);
- }
- public override Type VisitTypeVariable(TypeVariable node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- return this.VisitType(node);
- }
- public override Type VisitTypeProxy(TypeProxy node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
- public override Type VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier node)
- {
- Contract.Ensures(Contract.Result<Type>() == node);
- return this.VisitType(node);
- }
- public override Variable VisitVariable(Variable node)
- {
- Contract.Ensures(Contract.Result<Variable>() == node);
- this.VisitTypedIdent(node.TypedIdent);
- return node;
- }
- public override List<Variable> VisitVariableSeq(List<Variable> variableSeq)
- {
- Contract.Ensures(Contract.Result<List<Variable>>() == variableSeq);
- for (int i = 0, n = variableSeq.Count; i < n; i++)
- this.VisitVariable(cce.NonNull(variableSeq[i]));
- return variableSeq;
- }
- public override YieldCmd VisitYieldCmd(YieldCmd node)
- {
- Contract.Ensures(Contract.Result<YieldCmd>() == node);
- return node;
- }
- public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- this.VisitEnsures(node.Ensures);
- this.VisitExpr(node.Expr);
- return node;
- }
- public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node)
- {
- Contract.Ensures(Contract.Result<Cmd>() == node);
- this.VisitRequires(node.Requires);
- this.VisitExpr(node.Expr);
- return node;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+// BoogiePL - StandardVisitor.cs
+//---------------------------------------------------------------------------------------------
+
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+
+namespace Microsoft.Boogie {
+ [ContractClass(typeof(VisitorContracts))]
+ /// <summary>
+ /// Base for all classes that process the Absy using the visitor pattern.
+ /// </summary>
+ public abstract class Visitor {
+ /// <summary>
+ /// Switches on node.NodeType to call a visitor method that has been specialized for node.
+ /// </summary>
+ /// <param name="a">The Absy node to be visited.</param>
+ /// <returns> Returns null if node is null. Otherwise returns an updated node (possibly a different object).</returns>
+ public abstract Absy/*!*/ Visit(Absy/*!*/ node);
+
+ /// <summary>
+ /// Transfers the state from one visitor to another. This enables separate visitor instances to cooperative process a single IR.
+ /// </summary>
+ public virtual void TransferStateTo(Visitor targetVisitor) {
+ }
+
+ public virtual IList<Expr> VisitExprSeq(IList<Expr> list) {
+ Contract.Requires(list != null);
+ Contract.Ensures(Contract.Result<IList<Expr>>() != null);
+ lock (list)
+ {
+ for (int i = 0, n = list.Count; i < n; i++)
+ list[i] = (Expr)this.Visit(cce.NonNull(list[i]));
+ }
+ return list;
+ }
+ }
+ [ContractClassFor(typeof(Visitor))]
+ abstract class VisitorContracts : Visitor {
+ public override Absy Visit(Absy node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ throw new System.NotImplementedException();
+ }
+ }
+
+ /// <summary>
+ /// Walks an IR, mutating it into a new form. (For a subclass that does not mutate the IR, see ReadOnlyVisitor.)
+ /// </summary>
+ public abstract class StandardVisitor : Visitor {
+ public Visitor callingVisitor;
+
+ public StandardVisitor() {
+ }
+ public StandardVisitor(Visitor callingVisitor) {
+ this.callingVisitor = callingVisitor;
+ }
+ public override Absy Visit(Absy node) {
+ return node.StdDispatch(this);
+ }
+ public virtual Cmd VisitAssertCmd(AssertCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Cmd VisitAssignCmd(AssignCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ for (int i = 0; i < node.Lhss.Count; ++i) {
+ node.SetLhs(i, cce.NonNull((AssignLhs)this.Visit(node.Lhss[i])));
+ node.SetRhs(i, cce.NonNull((Expr/*!*/)this.Visit(node.Rhss[i])));
+ }
+ return node;
+ }
+ public virtual Cmd VisitAssumeCmd(AssumeCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual AtomicRE VisitAtomicRE(AtomicRE node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AtomicRE>() != null);
+ node.b = this.VisitBlock(node.b);
+ return node;
+ }
+ public virtual Axiom VisitAxiom(Axiom node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Axiom>() != null);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Type VisitBasicType(BasicType node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.VisitType(node);
+ }
+ public virtual Type VisitFloatType(FloatType node)
+ {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.VisitType(node);
+ }
+ public virtual Expr VisitBvConcatExpr(BvConcatExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node.E0 = this.VisitExpr(node.E0);
+ node.E1 = this.VisitExpr(node.E1);
+ return node;
+ }
+ public virtual Type VisitBvType(BvType node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.VisitType(node);
+ }
+ public virtual Type VisitBvTypeProxy(BvTypeProxy node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ return (Type)this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+ public virtual Block VisitBlock(Block node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+ node.Cmds = this.VisitCmdSeq(node.Cmds);
+ node.TransferCmd = (TransferCmd)this.Visit(cce.NonNull(node.TransferCmd));
+ return node;
+ }
+ public virtual Expr VisitCodeExpr(CodeExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node.LocVars = this.VisitVariableSeq(node.LocVars);
+ node.Blocks = this.VisitBlockList(node.Blocks);
+ return node;
+ }
+ public virtual List<Block> VisitBlockSeq(List<Block> blockSeq) {
+ Contract.Requires(blockSeq != null);
+ Contract.Ensures(Contract.Result<List<Block>>() != null);
+ lock (blockSeq)
+ {
+ for (int i = 0, n = blockSeq.Count; i < n; i++)
+ blockSeq[i] = this.VisitBlock(cce.NonNull(blockSeq[i]));
+ }
+ return blockSeq;
+ }
+ public virtual List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
+ Contract.Requires(blocks != null);
+ Contract.Ensures(Contract.Result<List<Block>>() != null);
+ for (int i = 0, n = blocks.Count; i < n; i++) {
+ blocks[i] = this.VisitBlock(blocks[i]);
+ }
+ return blocks;
+ }
+ public virtual BoundVariable VisitBoundVariable(BoundVariable node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<BoundVariable>() != null);
+ node = (BoundVariable)this.VisitVariable(node);
+ return node;
+ }
+ public virtual Cmd VisitCallCmd(CallCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ for (int i = 0; i < node.Ins.Count; ++i)
+ if (node.Ins[i] != null)
+ node.Ins[i] = this.VisitExpr(cce.NonNull(node.Ins[i]));
+ for (int i = 0; i < node.Outs.Count; ++i)
+ if (node.Outs[i] != null)
+ node.Outs[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(node.Outs[i]));
+ return node;
+ }
+ public virtual Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ for (int i = 0; i < node.CallCmds.Count; i++)
+ {
+ if (node.CallCmds[i] != null)
+ node.CallCmds[i] = (CallCmd)this.VisitCallCmd(node.CallCmds[i]);
+ }
+ return node;
+ }
+ public virtual List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
+ Contract.Requires(cmdSeq != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ lock (cmdSeq)
+ {
+ for (int i = 0, n = cmdSeq.Count; i < n; i++)
+ cmdSeq[i] = (Cmd)this.Visit(cce.NonNull(cmdSeq[i])); // call general Visit so subtypes of Cmd get visited by their particular visitor
+ }
+ return cmdSeq;
+ }
+ public virtual Choice VisitChoice(Choice node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Choice>() != null);
+ node.rs = this.VisitRESeq(node.rs);
+ return node;
+ }
+ public virtual Cmd VisitCommentCmd(CommentCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return node;
+ }
+ public virtual Constant VisitConstant(Constant node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Constant>() != null);
+ return node;
+ }
+ public virtual CtorType VisitCtorType(CtorType node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+ lock (node)
+ {
+ for (int i = 0; i < node.Arguments.Count; ++i)
+ node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
+ }
+ return node;
+ }
+ public virtual Declaration VisitDeclaration(Declaration node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Declaration>() != null);
+ return node;
+ }
+ public virtual List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
+ Contract.Requires(declarationList != null);
+ Contract.Ensures(Contract.Result<List<Declaration>>() != null);
+ for (int i = 0, n = declarationList.Count; i < n; i++)
+ declarationList[i] = cce.NonNull((Declaration/*!*/)this.Visit(declarationList[i]));
+ return declarationList;
+ }
+ public virtual DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
+ node.InParams = this.VisitVariableSeq(node.InParams);
+ node.OutParams = this.VisitVariableSeq(node.OutParams);
+ return node;
+ }
+ public virtual Expr VisitExistsExpr(ExistsExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node = (ExistsExpr)this.VisitQuantifierExpr(node);
+ return node;
+ }
+ public virtual Expr VisitBvExtractExpr(BvExtractExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node.Bitvector = this.VisitExpr(node.Bitvector);
+ return node;
+ }
+ public virtual Expr VisitExpr(Expr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Expr e = (Expr)this.Visit(node);
+ return e;
+ }
+ public override IList<Expr> VisitExprSeq(IList<Expr> exprSeq) {
+ //Contract.Requires(exprSeq != null);
+ Contract.Ensures(Contract.Result<IList<Expr>>() != null);
+ for (int i = 0, n = exprSeq.Count; i < n; i++)
+ exprSeq[i] = this.VisitExpr(cce.NonNull(exprSeq[i]));
+ return exprSeq;
+ }
+ public virtual Requires VisitRequires(Requires @requires) {
+ Contract.Requires(@requires != null);
+ Contract.Ensures(Contract.Result<Requires>() != null);
+ @requires.Condition = this.VisitExpr(@requires.Condition);
+ return @requires;
+ }
+ public virtual List<Requires> VisitRequiresSeq(List<Requires> requiresSeq) {
+ Contract.Requires(requiresSeq != null);
+ Contract.Ensures(Contract.Result<List<Requires>>() != null);
+ for (int i = 0, n = requiresSeq.Count; i < n; i++)
+ requiresSeq[i] = this.VisitRequires(requiresSeq[i]);
+ return requiresSeq;
+ }
+ public virtual Ensures VisitEnsures(Ensures @ensures) {
+ Contract.Requires(@ensures != null);
+ Contract.Ensures(Contract.Result<Ensures>() != null);
+ @ensures.Condition = this.VisitExpr(@ensures.Condition);
+ return @ensures;
+ }
+ public virtual List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq) {
+ Contract.Requires(ensuresSeq != null);
+ Contract.Ensures(Contract.Result<List<Ensures>>() != null);
+ for (int i = 0, n = ensuresSeq.Count; i < n; i++)
+ ensuresSeq[i] = this.VisitEnsures(ensuresSeq[i]);
+ return ensuresSeq;
+ }
+ public virtual Expr VisitForallExpr(ForallExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node = (ForallExpr)this.VisitQuantifierExpr(node);
+ return node;
+ }
+ public virtual Expr VisitLambdaExpr(LambdaExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node = (LambdaExpr)this.VisitBinderExpr(node);
+ return node;
+ }
+ public virtual Formal VisitFormal(Formal node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Formal>() != null);
+ return node;
+ }
+ public virtual Function VisitFunction(Function node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ node = (Function)this.VisitDeclWithFormals(node);
+ if (node.Body != null)
+ node.Body = this.VisitExpr(node.Body);
+ return node;
+ }
+ public virtual GlobalVariable VisitGlobalVariable(GlobalVariable node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<GlobalVariable>() != null);
+ node = (GlobalVariable)this.VisitVariable(node);
+ return node;
+ }
+ public virtual GotoCmd VisitGotoCmd(GotoCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<GotoCmd>() != null);
+ // do not visit the labelTargets, or control-flow loops will lead to a looping visitor
+ return node;
+ }
+ public virtual Cmd VisitHavocCmd(HavocCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ node.Vars = this.VisitIdentifierExprSeq(node.Vars);
+ return node;
+ }
+ public virtual Expr VisitIdentifierExpr(IdentifierExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ if (node.Decl != null)
+ node.Decl = this.VisitVariable(node.Decl);
+ return node;
+ }
+ public virtual List<IdentifierExpr> VisitIdentifierExprSeq(List<IdentifierExpr> identifierExprSeq) {
+ Contract.Requires(identifierExprSeq != null);
+ Contract.Ensures(Contract.Result<List<IdentifierExpr>>() != null);
+ lock (identifierExprSeq)
+ {
+ for (int i = 0, n = identifierExprSeq.Count; i < n; i++)
+ identifierExprSeq[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(identifierExprSeq[i]));
+ }
+ return identifierExprSeq;
+ }
+ public virtual Implementation VisitImplementation(Implementation node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Implementation>() != null);
+ node.LocVars = this.VisitVariableSeq(node.LocVars);
+ node.Blocks = this.VisitBlockList(node.Blocks);
+ node.Proc = this.VisitProcedure(cce.NonNull(node.Proc));
+ node = (Implementation)this.VisitDeclWithFormals(node); // do this first or last?
+ return node;
+ }
+ public virtual Expr VisitLiteralExpr(LiteralExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ return node;
+ }
+
+ public virtual LocalVariable VisitLocalVariable(LocalVariable node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<LocalVariable>() != null);
+ return node;
+ }
+
+ public virtual AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ node.Map = cce.NonNull((AssignLhs)this.Visit(node.Map));
+ for (int i = 0; i < node.Indexes.Count; ++i)
+ node.Indexes[i] = cce.NonNull((Expr)this.Visit(node.Indexes[i]));
+ return node;
+ }
+ public virtual MapType VisitMapType(MapType node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<MapType>() != null);
+ // not doing anything about the bound variables ... maybe
+ // these should be visited as well ...
+ //
+ // NOTE: when overriding this method, you have to make sure that
+ // the bound variables of the map type are updated correctly
+ lock (node.Arguments)
+ {
+ for (int i = 0; i < node.Arguments.Count; ++i)
+ node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
+ }
+ node.Result = cce.NonNull((Type/*!*/)this.Visit(node.Result));
+ return node;
+ }
+ public virtual Type VisitMapTypeProxy(MapTypeProxy node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ return (Type)this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+
+ public virtual Expr VisitNAryExpr(NAryExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node.Args = this.VisitExprSeq(node.Args);
+ return node;
+ }
+ public virtual Expr VisitOldExpr(OldExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Procedure VisitProcedure(Procedure node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Procedure>() != null);
+ node.Ensures = this.VisitEnsuresSeq(node.Ensures);
+ node.InParams = this.VisitVariableSeq(node.InParams);
+ node.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
+ node.OutParams = this.VisitVariableSeq(node.OutParams);
+ node.Requires = this.VisitRequiresSeq(node.Requires);
+ return node;
+ }
+ public virtual Program VisitProgram(Program node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Program>() != null);
+ var decls = node.TopLevelDeclarations.ToList();
+ node.ClearTopLevelDeclarations();
+ node.AddTopLevelDeclarations(this.VisitDeclarationList(decls));
+ return node;
+ }
+ public virtual QKeyValue VisitQKeyValue(QKeyValue node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<QKeyValue>() != null);
+ var newParams = new List<object>();
+ for (int i = 0, n = node.Params.Count; i < n; i++) {
+ var e = node.Params[i] as Expr;
+ newParams.Add(e != null ? this.Visit(e) : node.Params[i]);
+ }
+ node.ClearParams();
+ node.AddParams(newParams);
+ if (node.Next != null) {
+ node.Next = (QKeyValue)this.Visit(node.Next);
+ }
+ return node;
+ }
+ public virtual BinderExpr VisitBinderExpr(BinderExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<BinderExpr>() != null);
+ node.Body = this.VisitExpr(node.Body);
+ node.Dummies = this.VisitVariableSeq(node.Dummies);
+ //node.Type = this.VisitType(node.Type);
+ return node;
+ }
+ public virtual QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<QuantifierExpr>() != null);
+ node = cce.NonNull((QuantifierExpr)this.VisitBinderExpr(node));
+ if (node.Triggers != null) {
+ node.Triggers = this.VisitTrigger(node.Triggers);
+ }
+ return node;
+ }
+ public virtual Cmd VisitRE(RE node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ return (Cmd)this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
+ }
+ public virtual List<RE> VisitRESeq(List<RE> reSeq) {
+ Contract.Requires(reSeq != null);
+ Contract.Ensures(Contract.Result<List<RE>>() != null);
+ for (int i = 0, n = reSeq.Count; i < n; i++)
+ reSeq[i] = (RE)this.VisitRE(cce.NonNull(reSeq[i]));
+ return reSeq;
+ }
+ public virtual ReturnCmd VisitReturnCmd(ReturnCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<ReturnCmd>() != null);
+ return (ReturnCmd)this.VisitTransferCmd(node);
+ }
+ public virtual ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Sequential VisitSequential(Sequential node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Sequential>() != null);
+ node.first = (RE)this.VisitRE(node.first);
+ node.second = (RE)this.VisitRE(node.second);
+ return node;
+ }
+ public virtual AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ node.AssignedVariable =
+ (IdentifierExpr)this.VisitIdentifierExpr(node.AssignedVariable);
+ return node;
+ }
+ public virtual Cmd VisitStateCmd(StateCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ node.Locals = this.VisitVariableSeq(node.Locals);
+ node.Cmds = this.VisitCmdSeq(node.Cmds);
+ return node;
+ }
+ public virtual TransferCmd VisitTransferCmd(TransferCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<TransferCmd>() != null);
+ return node;
+ }
+ public virtual Trigger VisitTrigger(Trigger node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Trigger>() != null);
+ Trigger origNext = node.Next;
+ if (origNext != null) {
+ Trigger newNext = this.VisitTrigger(origNext);
+ if (newNext != origNext) {
+ node = new Trigger(node.tok, node.Pos, node.Tr.ToList());
+ node.Next = newNext;
+ }
+ }
+ node.Tr = this.VisitExprSeq(node.Tr.ToList());
+ return node;
+ }
+ // called by default for all nullary type constructors and type variables
+ public virtual Type VisitType(Type node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return node;
+ }
+ public virtual TypedIdent VisitTypedIdent(TypedIdent node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<TypedIdent>() != null);
+ node.Type = (Type)this.Visit(node.Type);
+ return node;
+ }
+ public virtual Declaration VisitTypeCtorDecl(TypeCtorDecl node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Declaration>() != null);
+ return this.VisitDeclaration(node);
+ }
+ public virtual Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ node.ExpandedType = cce.NonNull((Type/*!*/)this.Visit(node.ExpandedType));
+ lock (node.Arguments)
+ {
+ for (int i = 0; i < node.Arguments.Count; ++i)
+ node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
+ }
+ return node;
+ }
+ public virtual Declaration VisitTypeSynonymDecl(TypeSynonymDecl node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Declaration>() != null);
+ return this.VisitDeclaration(node);
+ }
+ public virtual Type VisitTypeVariable(TypeVariable node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.VisitType(node);
+ }
+ public virtual Type VisitTypeProxy(TypeProxy node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ return cce.NonNull((Type/*!*/)this.Visit(node.ProxyFor));
+ return this.VisitType(node);
+ }
+ public virtual Type VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return this.VisitType(node);
+ }
+ public virtual Variable VisitVariable(Variable node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Variable>() != null);
+ node.TypedIdent = this.VisitTypedIdent(node.TypedIdent);
+ return node;
+ }
+ public virtual List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
+ Contract.Requires(variableSeq != null);
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ lock (variableSeq)
+ {
+ for (int i = 0, n = variableSeq.Count; i < n; i++)
+ variableSeq[i] = this.VisitVariable(cce.NonNull(variableSeq[i]));
+ }
+ return variableSeq;
+ }
+ public virtual YieldCmd VisitYieldCmd(YieldCmd node)
+ {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<YieldCmd>() != null);
+ return node;
+ }
+ public virtual Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ node.Ensures = this.VisitEnsures(node.Ensures);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ public virtual Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ node.Requires = this.VisitRequires(node.Requires);
+ node.Expr = this.VisitExpr(node.Expr);
+ return node;
+ }
+ }
+
+ /// <summary>
+ /// A ReadOnlyVisitor visits all the nodes of a given Absy. The visitor may collect information from
+ /// the nodes, may change fields contained in the data structure, but may not replace any nodes in the
+ /// data structure. To enforce this, all Visit...(node) methods have a postcondition that says that
+ /// the return value is equal to the given "node".
+ /// </summary>
+ public abstract class ReadOnlyVisitor : StandardVisitor
+ {
+ public ReadOnlyVisitor()
+ {
+ }
+ public ReadOnlyVisitor(Visitor callingVisitor)
+ {
+ this.callingVisitor = callingVisitor;
+ }
+ public override Absy Visit(Absy node)
+ {
+ Contract.Ensures(Contract.Result<Absy>() == node);
+ return node.StdDispatch(this);
+ }
+ public override Cmd VisitAssertCmd(AssertCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ public override Cmd VisitAssignCmd(AssignCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ for (int i = 0; i < node.Lhss.Count; ++i)
+ {
+ this.Visit(node.Lhss[i]);
+ this.Visit(node.Rhss[i]);
+ }
+ return node;
+ }
+ public override Cmd VisitAssumeCmd(AssumeCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ public override AtomicRE VisitAtomicRE(AtomicRE node)
+ {
+ Contract.Ensures(Contract.Result<AtomicRE>() == node);
+ this.VisitBlock(node.b);
+ return node;
+ }
+ public override Axiom VisitAxiom(Axiom node)
+ {
+ Contract.Ensures(Contract.Result<Axiom>() == node);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ public override Type VisitBasicType(BasicType node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ return this.VisitType(node);
+ }
+ public override Expr VisitBvConcatExpr(BvConcatExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ this.VisitExpr(node.E0);
+ this.VisitExpr(node.E1);
+ return node;
+ }
+ public override Type VisitBvType(BvType node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ return this.VisitType(node);
+ }
+ public override Type VisitBvTypeProxy(BvTypeProxy node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+ public override Block VisitBlock(Block node)
+ {
+ Contract.Ensures(Contract.Result<Block>() == node);
+ this.VisitCmdSeq(node.Cmds);
+ this.Visit(cce.NonNull(node.TransferCmd));
+ return node;
+ }
+ public override Expr VisitCodeExpr(CodeExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ this.VisitVariableSeq(node.LocVars);
+ this.VisitBlockList(node.Blocks);
+ return node;
+ }
+ public override List<Block> VisitBlockSeq(List<Block> blockSeq)
+ {
+ Contract.Ensures(Contract.Result<List<Block>>() == blockSeq);
+ for (int i = 0, n = blockSeq.Count; i < n; i++)
+ this.VisitBlock(cce.NonNull(blockSeq[i]));
+ return blockSeq;
+ }
+ public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks)
+ {
+ Contract.Ensures(Contract.Result<List<Block>>() == blocks);
+ for (int i = 0, n = blocks.Count; i < n; i++)
+ {
+ this.VisitBlock(blocks[i]);
+ }
+ return blocks;
+ }
+ public override BoundVariable VisitBoundVariable(BoundVariable node)
+ {
+ Contract.Ensures(Contract.Result<BoundVariable>() == node);
+ return (BoundVariable)this.VisitVariable(node);
+ }
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ for (int i = 0; i < node.Ins.Count; ++i)
+ if (node.Ins[i] != null)
+ this.VisitExpr(node.Ins[i]);
+ for (int i = 0; i < node.Outs.Count; ++i)
+ if (node.Outs[i] != null)
+ this.VisitIdentifierExpr(node.Outs[i]);
+ return node;
+ }
+ public override Cmd VisitParCallCmd(ParCallCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ for (int i = 0; i < node.CallCmds.Count; i++)
+ {
+ if (node.CallCmds[i] != null)
+ this.VisitCallCmd(node.CallCmds[i]);
+ }
+ return node;
+ }
+ public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq)
+ {
+ Contract.Ensures(Contract.Result<List<Cmd>>() == cmdSeq);
+ for (int i = 0, n = cmdSeq.Count; i < n; i++)
+ this.Visit(cce.NonNull(cmdSeq[i])); // call general Visit so subtypes of Cmd get visited by their particular visitor
+ return cmdSeq;
+ }
+ public override Choice VisitChoice(Choice node)
+ {
+ Contract.Ensures(Contract.Result<Choice>() == node);
+ this.VisitRESeq(node.rs);
+ return node;
+ }
+ public override Cmd VisitCommentCmd(CommentCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ return node;
+ }
+ public override Constant VisitConstant(Constant node)
+ {
+ Contract.Ensures(Contract.Result<Constant>() == node);
+ return node;
+ }
+ public override CtorType VisitCtorType(CtorType node)
+ {
+ Contract.Ensures(Contract.Result<CtorType>() == node);
+ for (int i = 0; i < node.Arguments.Count; ++i)
+ this.Visit(node.Arguments[i]);
+ return node;
+ }
+ public override Declaration VisitDeclaration(Declaration node)
+ {
+ Contract.Ensures(Contract.Result<Declaration>() == node);
+ return node;
+ }
+ public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList)
+ {
+ Contract.Ensures(Contract.Result<List<Declaration>>() == declarationList);
+ for (int i = 0, n = declarationList.Count; i < n; i++)
+ this.Visit(declarationList[i]);
+ return declarationList;
+ }
+ public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node)
+ {
+ Contract.Ensures(Contract.Result<DeclWithFormals>() == node);
+ this.VisitVariableSeq(node.InParams);
+ this.VisitVariableSeq(node.OutParams);
+ return node;
+ }
+ public override Expr VisitExistsExpr(ExistsExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ return (ExistsExpr)this.VisitQuantifierExpr(node);
+ }
+ public override Expr VisitBvExtractExpr(BvExtractExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ this.VisitExpr(node.Bitvector);
+ return node;
+ }
+ public override Expr VisitExpr(Expr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ return (Expr)this.Visit(node);
+ }
+ public override IList<Expr> VisitExprSeq(IList<Expr> exprSeq)
+ {
+ Contract.Ensures(Contract.Result<IList<Expr>>() == exprSeq);
+ for (int i = 0, n = exprSeq.Count; i < n; i++)
+ this.VisitExpr(cce.NonNull(exprSeq[i]));
+ return exprSeq;
+ }
+ public override Requires VisitRequires(Requires requires)
+ {
+ Contract.Ensures(Contract.Result<Requires>() == requires);
+ this.VisitExpr(requires.Condition);
+ return requires;
+ }
+ public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq)
+ {
+ Contract.Ensures(Contract.Result<List<Requires>>() == requiresSeq);
+ for (int i = 0, n = requiresSeq.Count; i < n; i++)
+ this.VisitRequires(requiresSeq[i]);
+ return requiresSeq;
+ }
+ public override Ensures VisitEnsures(Ensures ensures)
+ {
+ Contract.Ensures(Contract.Result<Ensures>() == ensures);
+ this.VisitExpr(ensures.Condition);
+ return ensures;
+ }
+ public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq)
+ {
+ Contract.Ensures(Contract.Result<List<Ensures>>() == ensuresSeq);
+ for (int i = 0, n = ensuresSeq.Count; i < n; i++)
+ this.VisitEnsures(ensuresSeq[i]);
+ return ensuresSeq;
+ }
+ public override Expr VisitForallExpr(ForallExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ return (ForallExpr)this.VisitQuantifierExpr(node);
+ }
+ public override Expr VisitLambdaExpr(LambdaExpr node) {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ return this.VisitBinderExpr(node);
+ }
+ public override Formal VisitFormal(Formal node)
+ {
+ Contract.Ensures(Contract.Result<Formal>() == node);
+ return node;
+ }
+ public override Function VisitFunction(Function node)
+ {
+ Contract.Ensures(Contract.Result<Function>() == node);
+ node = (Function)this.VisitDeclWithFormals(node);
+ if (node.Body != null)
+ this.VisitExpr(node.Body);
+ return node;
+ }
+ public override GlobalVariable VisitGlobalVariable(GlobalVariable node)
+ {
+ Contract.Ensures(Contract.Result<GlobalVariable>() == node);
+ return (GlobalVariable)this.VisitVariable(node);
+ }
+ public override GotoCmd VisitGotoCmd(GotoCmd node)
+ {
+ Contract.Ensures(Contract.Result<GotoCmd>() == node);
+ // do not visit the labelTargets, or control-flow loops will lead to a looping visitor
+ return node;
+ }
+ public override Cmd VisitHavocCmd(HavocCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ this.VisitIdentifierExprSeq(node.Vars);
+ return node;
+ }
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ if (node.Decl != null)
+ this.VisitVariable(node.Decl);
+ return node;
+ }
+ public override List<IdentifierExpr> VisitIdentifierExprSeq(List<IdentifierExpr> identifierExprSeq)
+ {
+ Contract.Ensures(Contract.Result<List<IdentifierExpr>>() == identifierExprSeq);
+ for (int i = 0, n = identifierExprSeq.Count; i < n; i++)
+ this.VisitIdentifierExpr(cce.NonNull(identifierExprSeq[i]));
+ return identifierExprSeq;
+ }
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ Contract.Ensures(Contract.Result<Implementation>() == node);
+ this.VisitVariableSeq(node.LocVars);
+ this.VisitBlockList(node.Blocks);
+ this.VisitProcedure(cce.NonNull(node.Proc));
+ return (Implementation)this.VisitDeclWithFormals(node); // do this first or last?
+ }
+ public override Expr VisitLiteralExpr(LiteralExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ return node;
+ }
+
+ public override LocalVariable VisitLocalVariable(LocalVariable node)
+ {
+ Contract.Ensures(Contract.Result<LocalVariable>() == node);
+ return node;
+ }
+
+ public override AssignLhs VisitMapAssignLhs(MapAssignLhs node)
+ {
+ Contract.Ensures(Contract.Result<AssignLhs>() == node);
+ this.Visit(node.Map);
+ for (int i = 0; i < node.Indexes.Count; ++i)
+ this.Visit(node.Indexes[i]);
+ return node;
+ }
+ public override MapType VisitMapType(MapType node)
+ {
+ Contract.Ensures(Contract.Result<MapType>() == node);
+ // not doing anything about the bound variables ... maybe
+ // these should be visited as well ...
+ //
+ // NOTE: when overriding this method, you have to make sure that
+ // the bound variables of the map type are updated correctly
+ for (int i = 0; i < node.Arguments.Count; ++i)
+ this.Visit(node.Arguments[i]);
+ this.Visit(node.Result);
+ return node;
+ }
+ public override Type VisitMapTypeProxy(MapTypeProxy node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ this.VisitExprSeq(node.Args);
+ return node;
+ }
+ public override Expr VisitOldExpr(OldExpr node)
+ {
+ Contract.Ensures(Contract.Result<Expr>() == node);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ public override Procedure VisitProcedure(Procedure node)
+ {
+ Contract.Ensures(Contract.Result<Procedure>() == node);
+ this.VisitEnsuresSeq(node.Ensures);
+ this.VisitVariableSeq(node.InParams);
+ this.VisitIdentifierExprSeq(node.Modifies);
+ this.VisitVariableSeq(node.OutParams);
+ this.VisitRequiresSeq(node.Requires);
+ return node;
+ }
+ public override Program VisitProgram(Program node)
+ {
+ Contract.Ensures(Contract.Result<Program>() == node);
+ this.VisitDeclarationList(node.TopLevelDeclarations.ToList());
+ return node;
+ }
+ public override QKeyValue VisitQKeyValue(QKeyValue node) {
+ Contract.Ensures(Contract.Result<QKeyValue>() == node);
+ for (int i = 0, n = node.Params.Count; i < n; i++) {
+ var e = node.Params[i] as Expr;
+ if (e != null) {
+ this.Visit(e);
+ }
+ }
+ if (node.Next != null) {
+ this.Visit(node.Next);
+ }
+ return node;
+ }
+ public override BinderExpr VisitBinderExpr(BinderExpr node)
+ {
+ Contract.Ensures(Contract.Result<BinderExpr>() == node);
+ this.VisitExpr(node.Body);
+ this.VisitVariableSeq(node.Dummies);
+ // this.VisitType(node.Type);
+ return node;
+ }
+ public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
+ {
+ Contract.Ensures(Contract.Result<QuantifierExpr>() == node);
+ this.VisitBinderExpr(node);
+ if (node.Triggers != null)
+ {
+ this.VisitTrigger(node.Triggers);
+ }
+ return node;
+ }
+ public override Cmd VisitRE(RE node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ return (Cmd)this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
+ }
+ public override List<RE> VisitRESeq(List<RE> reSeq)
+ {
+ Contract.Ensures(Contract.Result<List<RE>>() == reSeq);
+ for (int i = 0, n = reSeq.Count; i < n; i++)
+ this.VisitRE(cce.NonNull(reSeq[i]));
+ return reSeq;
+ }
+ public override ReturnCmd VisitReturnCmd(ReturnCmd node)
+ {
+ Contract.Ensures(Contract.Result<ReturnCmd>() == node);
+ return (ReturnCmd)this.VisitTransferCmd(node);
+ }
+ public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node)
+ {
+ Contract.Ensures(Contract.Result<ReturnExprCmd>() == node);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ public override Sequential VisitSequential(Sequential node)
+ {
+ Contract.Ensures(Contract.Result<Sequential>() == node);
+ this.VisitRE(node.first);
+ this.VisitRE(node.second);
+ return node;
+ }
+ public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node)
+ {
+ Contract.Ensures(Contract.Result<AssignLhs>() == node);
+ this.VisitIdentifierExpr(node.AssignedVariable);
+ return node;
+ }
+ public override Cmd VisitStateCmd(StateCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ this.VisitVariableSeq(node.Locals);
+ this.VisitCmdSeq(node.Cmds);
+ return node;
+ }
+ public override TransferCmd VisitTransferCmd(TransferCmd node)
+ {
+ Contract.Ensures(Contract.Result<TransferCmd>() == node);
+ return node;
+ }
+ public override Trigger VisitTrigger(Trigger node)
+ {
+ Contract.Ensures(Contract.Result<Trigger>() == node);
+ Trigger origNext = node.Next;
+ if (origNext != null)
+ {
+ this.VisitTrigger(origNext);
+ }
+ this.VisitExprSeq(node.Tr.ToList());
+ return node;
+ }
+ // called by default for all nullary type constructors and type variables
+ public override Type VisitType(Type node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ return node;
+ }
+ public override TypedIdent VisitTypedIdent(TypedIdent node)
+ {
+ Contract.Ensures(Contract.Result<TypedIdent>() == node);
+ this.Visit(node.Type);
+ return node;
+ }
+ public override Declaration VisitTypeCtorDecl(TypeCtorDecl node)
+ {
+ Contract.Ensures(Contract.Result<Declaration>() == node);
+ return this.VisitDeclaration(node);
+ }
+ public override Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ node.ExpandedType = cce.NonNull((Type/*!*/)this.Visit(node.ExpandedType));
+ for (int i = 0; i < node.Arguments.Count; ++i)
+ this.Visit(node.Arguments[i]);
+ return node;
+ }
+ public override Declaration VisitTypeSynonymDecl(TypeSynonymDecl node)
+ {
+ Contract.Ensures(Contract.Result<Declaration>() == node);
+ return this.VisitDeclaration(node);
+ }
+ public override Type VisitTypeVariable(TypeVariable node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ return this.VisitType(node);
+ }
+ public override Type VisitTypeProxy(TypeProxy node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ // if the type proxy is instantiated with some more
+ // specific type, we visit the instantiation
+ if (node.ProxyFor != null)
+ this.Visit(node.ProxyFor);
+ return this.VisitType(node);
+ }
+ public override Type VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier node)
+ {
+ Contract.Ensures(Contract.Result<Type>() == node);
+ return this.VisitType(node);
+ }
+ public override Variable VisitVariable(Variable node)
+ {
+ Contract.Ensures(Contract.Result<Variable>() == node);
+ this.VisitTypedIdent(node.TypedIdent);
+ return node;
+ }
+ public override List<Variable> VisitVariableSeq(List<Variable> variableSeq)
+ {
+ Contract.Ensures(Contract.Result<List<Variable>>() == variableSeq);
+ for (int i = 0, n = variableSeq.Count; i < n; i++)
+ this.VisitVariable(cce.NonNull(variableSeq[i]));
+ return variableSeq;
+ }
+ public override YieldCmd VisitYieldCmd(YieldCmd node)
+ {
+ Contract.Ensures(Contract.Result<YieldCmd>() == node);
+ return node;
+ }
+ public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ this.VisitEnsures(node.Ensures);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node)
+ {
+ Contract.Ensures(Contract.Result<Cmd>() == node);
+ this.VisitRequires(node.Requires);
+ this.VisitExpr(node.Expr);
+ return node;
+ }
+ }
+}
diff --git a/Source/Core/TypeAmbiguitySeeker.cs b/Source/Core/TypeAmbiguitySeeker.cs
index 753385a1..6f57ad43 100644
--- a/Source/Core/TypeAmbiguitySeeker.cs
+++ b/Source/Core/TypeAmbiguitySeeker.cs
@@ -1,123 +1,123 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Diagnostics.Contracts;
-using System.Collections.Generic;
-
-// Visitor to search for types proxies that could not completely be
-// determined by type inference. If this happens, a warning is
-// generated and the proxies are instantiated in a more or less arbitrary
-// fashion.
-
-namespace Microsoft.Boogie {
-
- public class TypeAmbiguitySeeker : ReadOnlyVisitor {
-
- private readonly InTypeSeeker/*!*/ inTypeSeeker = new InTypeSeeker();
- private readonly TypecheckingContext/*!*/ TC;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(inTypeSeeker != null);
- Contract.Invariant(TC != null);
- }
-
-
- public TypeAmbiguitySeeker(TypecheckingContext tc) {
- Contract.Requires(tc != null);
- TC = tc;
- }
-
- private void CheckTypeParams(Absy node, TypeParamInstantiation insts) {
- Contract.Requires(insts != null);
- Contract.Requires(node != null);
- foreach (TypeVariable/*!*/ var in insts.FormalTypeParams) {
- Contract.Assert(var != null);
- Type/*!*/ inst = insts[var];
- Contract.Assert(inst != null);
-
- inTypeSeeker.FoundAmbiguity = false;
- inTypeSeeker.Visit(inst);
- if (inTypeSeeker.FoundAmbiguity)
- TC.Warning(node,
- "type parameter {0} is ambiguous, instantiating to {1}",
- var, inst);
- }
- }
-
- public override Expr VisitNAryExpr(NAryExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- CheckTypeParams(node, cce.NonNull(node.TypeParameters));
- return base.VisitNAryExpr(node);
- }
-
- public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- CheckTypeParams(node, cce.NonNull(node.TypeParameters));
- return base.VisitMapAssignLhs(node);
- }
- }
-
- internal class InTypeSeeker : ReadOnlyVisitor {
-
- internal bool FoundAmbiguity = false;
-
- // called when an uninstantiated proxy was found
- private Type Instantiate(Type node, Type inst) {
- Contract.Requires(inst != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() == node);
- FoundAmbiguity = true;
- bool success = node.Unify(inst);
- Contract.Assert(success);
- return node;
- }
-
- public override Type VisitTypeProxy(TypeProxy node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- if (node.ProxyFor != null)
- return base.VisitTypeProxy(node);
-
- return Instantiate(node, Type.Int);
- }
-
- public override Type VisitMapTypeProxy(MapTypeProxy node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- if (node.ProxyFor != null)
- return base.VisitMapTypeProxy(node);
-
- List<TypeVariable>/*!*/ typeParams = new List<TypeVariable>();
- List<Type>/*!*/ arguments = new List<Type>();
- for (int i = 0; i < node.Arity; ++i) {
- TypeVariable/*!*/ param = new TypeVariable(Token.NoToken, "arg" + i);
- Contract.Assert(param != null);
- typeParams.Add(param);
- arguments.Add(param);
- }
- TypeVariable/*!*/ result = new TypeVariable(Token.NoToken, "res");
- Contract.Assert(result != null);
- typeParams.Add(result);
-
- Type/*!*/ instantiation = new MapType(Token.NoToken, typeParams, arguments, result);
- Contract.Assert(instantiation != null);
-
- return Instantiate(node, instantiation);
- }
-
- public override Type VisitBvTypeProxy(BvTypeProxy node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- if (node.ProxyFor != null)
- return base.VisitBvTypeProxy(node);
-
- return Instantiate(node, new BvType(node.MinBits));
- }
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+
+// Visitor to search for types proxies that could not completely be
+// determined by type inference. If this happens, a warning is
+// generated and the proxies are instantiated in a more or less arbitrary
+// fashion.
+
+namespace Microsoft.Boogie {
+
+ public class TypeAmbiguitySeeker : ReadOnlyVisitor {
+
+ private readonly InTypeSeeker/*!*/ inTypeSeeker = new InTypeSeeker();
+ private readonly TypecheckingContext/*!*/ TC;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(inTypeSeeker != null);
+ Contract.Invariant(TC != null);
+ }
+
+
+ public TypeAmbiguitySeeker(TypecheckingContext tc) {
+ Contract.Requires(tc != null);
+ TC = tc;
+ }
+
+ private void CheckTypeParams(Absy node, TypeParamInstantiation insts) {
+ Contract.Requires(insts != null);
+ Contract.Requires(node != null);
+ foreach (TypeVariable/*!*/ var in insts.FormalTypeParams) {
+ Contract.Assert(var != null);
+ Type/*!*/ inst = insts[var];
+ Contract.Assert(inst != null);
+
+ inTypeSeeker.FoundAmbiguity = false;
+ inTypeSeeker.Visit(inst);
+ if (inTypeSeeker.FoundAmbiguity)
+ TC.Warning(node,
+ "type parameter {0} is ambiguous, instantiating to {1}",
+ var, inst);
+ }
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ CheckTypeParams(node, cce.NonNull(node.TypeParameters));
+ return base.VisitNAryExpr(node);
+ }
+
+ public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ CheckTypeParams(node, cce.NonNull(node.TypeParameters));
+ return base.VisitMapAssignLhs(node);
+ }
+ }
+
+ internal class InTypeSeeker : ReadOnlyVisitor {
+
+ internal bool FoundAmbiguity = false;
+
+ // called when an uninstantiated proxy was found
+ private Type Instantiate(Type node, Type inst) {
+ Contract.Requires(inst != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() == node);
+ FoundAmbiguity = true;
+ bool success = node.Unify(inst);
+ Contract.Assert(success);
+ return node;
+ }
+
+ public override Type VisitTypeProxy(TypeProxy node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (node.ProxyFor != null)
+ return base.VisitTypeProxy(node);
+
+ return Instantiate(node, Type.Int);
+ }
+
+ public override Type VisitMapTypeProxy(MapTypeProxy node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (node.ProxyFor != null)
+ return base.VisitMapTypeProxy(node);
+
+ List<TypeVariable>/*!*/ typeParams = new List<TypeVariable>();
+ List<Type>/*!*/ arguments = new List<Type>();
+ for (int i = 0; i < node.Arity; ++i) {
+ TypeVariable/*!*/ param = new TypeVariable(Token.NoToken, "arg" + i);
+ Contract.Assert(param != null);
+ typeParams.Add(param);
+ arguments.Add(param);
+ }
+ TypeVariable/*!*/ result = new TypeVariable(Token.NoToken, "res");
+ Contract.Assert(result != null);
+ typeParams.Add(result);
+
+ Type/*!*/ instantiation = new MapType(Token.NoToken, typeParams, arguments, result);
+ Contract.Assert(instantiation != null);
+
+ return Instantiate(node, instantiation);
+ }
+
+ public override Type VisitBvTypeProxy(BvTypeProxy node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (node.ProxyFor != null)
+ return base.VisitBvTypeProxy(node);
+
+ return Instantiate(node, new BvType(node.MinBits));
+ }
+ }
+
} \ No newline at end of file
diff --git a/Source/Core/Util.cs b/Source/Core/Util.cs
index 3b8412b9..f201aef8 100644
--- a/Source/Core/Util.cs
+++ b/Source/Core/Util.cs
@@ -1,688 +1,688 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
- using System;
- using System.IO;
- using System.Collections;
- using System.Diagnostics.Contracts;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
-
- public static class LinqExtender
- {
- public static string Concat(this IEnumerable<string> strings, string separator)
- {
- var sb = new StringBuilder();
- var first = true;
- foreach (var s in strings) {
- if (!first)
- sb.Append(separator);
- first = false;
- sb.Append(s);
- }
- return sb.ToString();
- }
-
- public static IEnumerable<T> Concat1<T>(this IEnumerable<T> objects, T final)
- {
- foreach (var s in objects) {
- yield return s;
- }
- yield return final;
- }
-
- public static string MapConcat<T>(this IEnumerable<T> objects, Func<T,string> toString, string separator)
- {
- var sb = new StringBuilder();
- var first = true;
- foreach (var s in objects) {
- if (!first)
- sb.Append(separator);
- first = false;
- sb.Append(toString(s));
- }
- return sb.ToString();
- }
-
- public static IEnumerable<T> SkipEnd<T>(this IEnumerable<T> source, int count)
- {
- var l = source.ToList();
- if (count >= l.Count)
- return Enumerable.Empty<T>();
- l.RemoveRange(l.Count - count, count);
- return l;
- }
-
- public static void Iter<T>(this IEnumerable<T> coll, Action<T> fn)
- {
- foreach (var e in coll) fn(e);
- }
-
- public static IEnumerable<Tuple<TSource1, TSource2>> Zip<TSource1, TSource2>(this IEnumerable<TSource1> source1, IEnumerable<TSource2> source2)
- {
- return source1.Zip(source2, (e1, e2) => new Tuple<TSource1, TSource2>(e1, e2));
- }
- }
-
- public class TokenTextWriter : IDisposable {
- string/*!*/ filename;
- TextWriter/*!*/ writer;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(filename != null);
- Contract.Invariant(writer != null);
- }
-
- bool setTokens = true;
- int line = 1;
- int col;
- public bool UseForComputingChecksums;
-
- private const int indent_size = 2;
- protected static string Indent(int level) {
- Contract.Ensures(Contract.Result<string>() != null);
- return new string(' ', (indent_size * level));
- }
-
-
- // Keywords, this array *must* be sorted
- public static readonly string[]/*!*/ BplKeywords =
- {
- "assert",
- "assume",
- "axiom",
- "bool",
- "break",
- "call",
- "cast",
- "const",
- "else",
- "ensures",
- "exists",
- "false",
- "forall",
- "free",
- "function",
- "goto",
- "havoc",
- "if",
- "implementation",
- "int",
- "invariant",
- "modifies",
- "old",
- "procedure",
- "public",
- "requires",
- "return",
- "returns",
- "true",
- "type",
- "unique",
- "var",
- "where",
- "while",
- };
-
- // "Pretty" printing: not very efficient, and not necessarily very pretty, but helps a bit
- private readonly bool pretty;
-
- // The stack of writers in a current separator-block.
- // The string is an optional identifier that allows you
- // to not start a new indentation for e.g. "&&" in "a && b && c".
- // When the pretty printing is finished, this should be empty.
- Stack<KeyValuePair<string, List<TextWriter>>> wstk;
-
- // The original writer: where everything should finally end up.
- TextWriter actual_writer;
-
- public bool push(string type = null) {
- if (pretty) {
- if (wstk == null) {
- wstk = new Stack<KeyValuePair<string, List<TextWriter>>>();
- actual_writer = writer;
- }
- if (wstk.Count > 0 && wstk.Peek().Key == type && type != null) {
- sep();
- return false; // don't actually pop this thing (send this bool to pop)
- } else {
- wstk.Push(new KeyValuePair<string, List<TextWriter>>(type, new List<TextWriter> { }));
- sep();
- return true; // this needs to be popped
- }
- } else {
- return false;
- }
- }
-
- public void pop(bool do_it = true) {
- if (pretty) {
- if (do_it) {
- List<TextWriter> ws = wstk.Pop().Value;
- // try to figure out if you should insert line breaks between
- // them or print them on one single line
- // this breaks down when there are newlines inserted
- List<String> ss = new List<String>();
- int len = 0;
- foreach (TextWriter w in ws) {
- foreach (String s in w.ToString().Split(new String[] { "\r\n", "\n" }, StringSplitOptions.None)) {
- if (s.Length > 0) {
- ss.Add(s);
- len += s.Length;
- // len = Math.Max(len, s.Length);
- }
- }
- }
- // figure out which is the next writer to use
- List<TextWriter> tw = wstk.Count > 0 ? wstk.Peek().Value : null;
- if (tw == null) {
- writer = actual_writer;
- } else {
- writer = tw.Last();
- }
- // write the strings (we would like to know WHERE we are in the document here)
- if (len > 80 /* - wstk.Count * 2 */) {
- for (int i = 0; i < ss.Count; i++) {
- if (i != ss.Count - 1) {
- writer.WriteLine(ss[i]);
- writer.Write(" ");
- } else {
- writer.Write(ss[i]);
- }
- }
- } else {
- foreach (String s in ss) {
- writer.Write(s);
- }
- }
- }
- }
- }
-
- public void sep() {
- if (pretty) {
- List<TextWriter> ws = wstk.Peek().Value;
-
- writer = new StringWriter();
- wstk.Peek().Value.Add(writer);
- }
- }
-
- private IToken/*!*/ CurrentToken {
- get {
- Contract.Ensures(Contract.Result<IToken>() != null);
-
- Token token = new Token();
- token.filename = filename;
- token.line = line;
- token.col = col;
- return token;
- }
- }
-
- public void SetToken(Absy absy) {
- Contract.Requires(absy != null);
- this.SetToken(t => absy.tok = t);
- }
-
- public void SetToken(IfThenElse expr)
- {
- Contract.Requires(expr != null);
- this.SetToken(t => expr.tok = t);
- }
-
- public void SetToken(Action<IToken> setter) {
- Contract.Requires(setter != null);
- if (this.setTokens) {
- setter(this.CurrentToken);
- }
- }
-
- public void SetToken(ref IToken tok) {
- Contract.Requires(tok != null);
- if (this.setTokens) {
- tok = this.CurrentToken;
- }
- }
-
- public static string SanitizeIdentifier(string name) {
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<string>() != null);
- int index = Array.BinarySearch(TokenTextWriter.BplKeywords, name);
- if (index >= 0) {
- return "\\" + name;
- } else if (name.Length > 2 && name[0] == 'b' && name[1] == 'v') {
- int dummy;
- return int.TryParse(name.Substring(2), out dummy) ? "\\" + name : name;
- } else if (name.Contains('@')) {
- return SanitizeIdentifier(name.Replace("@", "#AT#"));
- } else {
- return name;
- }
- }
-
- public TokenTextWriter(string filename)
- : this(filename, false)
- {
- }
-
- public TokenTextWriter(string filename, bool pretty)
- : base() {
- Contract.Requires(filename != null);
- this.pretty = pretty;
- this.filename = filename;
- this.writer = new StreamWriter(filename);
- }
-
- public TokenTextWriter(string filename, bool setTokens, bool pretty)
- : base() {
- Contract.Requires(filename != null);
- this.pretty = pretty;
- this.filename = filename;
- this.writer = new StreamWriter(filename);
- this.setTokens = setTokens;
- }
-
- public TokenTextWriter(string filename, TextWriter writer, bool setTokens, bool pretty)
- : base() {
- Contract.Requires(writer != null);
- Contract.Requires(filename != null);
- this.pretty = pretty;
- this.filename = filename;
- this.writer = writer;
- this.setTokens = setTokens;
- }
-
- public TokenTextWriter(string filename, TextWriter writer, bool pretty)
- : base() {
- Contract.Requires(writer != null);
- Contract.Requires(filename != null);
- this.pretty = pretty;
- this.filename = filename;
- this.writer = writer;
- }
-
- public TokenTextWriter(TextWriter writer)
- : this(writer, false)
- {
- }
-
- public TokenTextWriter(TextWriter writer, bool pretty)
- : base() {
- Contract.Requires(writer != null);
- this.pretty = pretty;
- this.filename = "<no file>";
- this.writer = writer;
- }
-
- public void Write(string text) {
- Contract.Requires(text != null);
- this.writer.Write(text);
- this.col += text.Length;
- }
-
- public void WriteIndent(int level) {
- if (!UseForComputingChecksums)
- {
- this.Write(Indent(level));
- }
- }
-
- public void Write(string text, params object[] args) {
- Contract.Requires(text != null);
- this.Write(string.Format(text, args));
- }
-
- public void Write(int level, string text) {
- Contract.Requires(text != null);
- this.WriteIndent(level);
- this.Write(text);
- }
-
- public void Write(int level, string text, params object[] args) {
- Contract.Requires(text != null);
- this.WriteIndent(level);
- this.Write(text, args);
- }
-
- public void Write(Absy node, string text) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.SetToken(node);
- this.Write(text);
- }
-
- public void Write(Absy node, string text, params string[] args) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.SetToken(node);
- this.Write(text, args);
- }
-
- public void Write(Absy node, int level, string text) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.WriteIndent(level);
- this.SetToken(node);
- this.Write(text);
- }
-
- public void Write(Absy node, int level, string text, params object[] args) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.WriteIndent(level);
- this.SetToken(node);
- this.Write(text, args);
- }
-
- public void WriteLine() {
- this.writer.WriteLine();
- this.line++;
- this.col = 0;
- }
-
- public void WriteLine(string text) {
- Contract.Requires(text != null);
- this.writer.WriteLine(text);
- this.line++;
- this.col = 0;
- }
-
- public void WriteText(string text) {
- Contract.Requires(text != null);
- int processed = 0;
- while (true) {
- int n = text.IndexOf('\n', processed);
- if (n == -1) {
- this.writer.Write(text);
- this.col += text.Length - processed;
- return;
- }
- processed = n + 1;
- this.line++;
- this.col = 0;
- }
- }
-
- public void WriteLine(string text, params object[] args) {
- Contract.Requires(text != null);
- this.WriteLine(string.Format(text, args));
- }
-
- public void WriteLine(int level, string text) {
- Contract.Requires(text != null);
- this.WriteIndent(level);
- this.WriteLine(text);
- }
-
- public void WriteLine(int level, string text, params object[] args) {
- Contract.Requires(text != null);
- this.WriteIndent(level);
- this.WriteLine(text, args);
- }
-
- public void WriteLine(Absy node, string text) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.SetToken(node);
- this.WriteLine(text);
- }
-
- public void WriteLine(Absy node, int level, string text) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.SetToken(node);
- this.WriteLine(level, text);
- }
-
- public void WriteLine(Absy node, int level, string text, params object[] args) {
- Contract.Requires(text != null);
- Contract.Requires(node != null);
- this.SetToken(node);
- this.WriteLine(level, text, args);
- }
-
- public void Close() {
- this.writer.Close();
- }
-
- public void Dispose() {
- this.Close();
- }
- }
-
- public class Helpers {
- public static string BeautifyBplString(string s) {
- Contract.Requires(s != null);
- Contract.Ensures(Contract.Result<string>() != null);
- // strip "^" if it is the first character, change "$result" to "result"
- if (s.StartsWith("^") || s == "$result") {
- s = s.Substring(1);
- } else if (s.StartsWith("call")) {
- s = s.Substring(s.IndexOf('@') + 1);
- if (s.StartsWith("formal@")) {
- s = "(value of formal parameter: " + s.Substring(7) + ")";
- }
- }
- // strip "$in" from the end of identifier names
- if (s.EndsWith("$in")) {
- return "(initial value of: " + s.Substring(0, s.Length - 3) + ")";
- } else {
- return s;
- }
- }
- public static string PrettyPrintBplExpr(Expr e) {
- Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<string>() != null);
- // anything that is unknown will just be printed via ToString
- // OldExpr and QuantifierExpr, BvExtractExpr, BvConcatExpr are ignored for now
- // LiteralExpr is printed as itself by ToString
- if (e is IdentifierExpr) {
- string s = e.ToString();
- return Helpers.BeautifyBplString(s);
- } else if (e is NAryExpr) {
- NAryExpr ne = (NAryExpr)e;
- IAppliable fun = ne.Fun;
- var eSeq = ne.Args;
- if (fun != null) {
- if ((fun.FunctionName == "$Length" || fun.FunctionName == "$StringLength") && eSeq.Count == 1) {
- Expr e0 = eSeq[0];
- if (e0 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- return s0 + ".Length";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "$typeof" && eSeq.Count == 1) {
- Expr e0 = eSeq[0];
- if (e0 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- return "(the dynamic type of: " + s0 + ")";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "IntArrayGet" && eSeq.Count == 2) {
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- return s0 + "[" + s1 + "]";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "$Is" && eSeq.Count == 2) {
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- return "(" + s0 + " == null || (" + s0 + " is " + s1 + "))";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "$IsNotNull" && eSeq.Count == 2) {
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- return "(" + s0 + " is " + s1 + ")";
- }
- //unexpected, just fall outside to the default
- } else if (fun is MapSelect && eSeq.Count <= 3) {
- // only maps with up to two arguments are supported right now (here)
- if (cce.NonNull(eSeq[0]).ToString() == "$Heap") {
- //print Index0.Index1, unless Index1 is "$elements", then just print Index0
- string s0 = PrettyPrintBplExpr(cce.NonNull(eSeq[1]));
- if (eSeq.Count > 2) {
- string s1 = PrettyPrintBplExpr(cce.NonNull(eSeq[2]));
- if (s1 == "$elements") {
- return s0;
- } else {
- if (eSeq[2] is IdentifierExpr) {
- // strip the class name out of a fieldname
- s1 = s1.Substring(s1.LastIndexOf('.') + 1);
- }
- return s0 + "." + s1;
- }
- }
- }
- //unexpected, just fall outside to the default
- } else if (fun is Microsoft.Boogie.BinaryOperator && eSeq.Count == 2) {
- Microsoft.Boogie.BinaryOperator f = (Microsoft.Boogie.BinaryOperator)fun;
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- string op = "";
- switch (f.Op) {
- case Microsoft.Boogie.BinaryOperator.Opcode.Add:
- op = " + ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.And:
- op = " && ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Div:
- op = " div ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Eq:
- op = " == ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Ge:
- op = " >= ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Gt:
- op = " > ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Iff:
- op = " <==> ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Imp:
- op = " ==> ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Le:
- op = " <= ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Lt:
- op = " < ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Mod:
- op = " mod ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Mul:
- op = " * ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Neq:
- op = " != ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Or:
- op = " || ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Pow:
- op = " ** ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.RealDiv:
- op = " / ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Sub:
- op = " - ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Subtype:
- op = " <: ";
- break;
- default:
- op = " ";
- break;
- }
- return "(" + s0 + op + s1 + ")";
- }
- //unexpected, just fall outside to the default
- } else {
- string s = fun.FunctionName + "(";
- for (int i = 0; i < eSeq.Count; i++) {
- Expr ex = eSeq[i];
- Contract.Assume(ex != null);
- if (i > 0) {
- s += ", ";
- }
- string t = PrettyPrintBplExpr(ex);
- if (t.StartsWith("(") && t.EndsWith(")")) {
- t = t.Substring(1, t.Length - 2);
- }
- s += t;
- }
- s += ")";
- return s;
- //unexpected, just fall outside to the default
- }
- }
- }
-
- return e.ToString();
- }
-
- private static readonly DateTime StartUp = DateTime.UtcNow;
-
- public static void ExtraTraceInformation(string point) {
- Contract.Requires(point != null);
- if (CommandLineOptions.Clo.TraceTimes) {
- DateTime now = DateTime.UtcNow;
- TimeSpan timeSinceStartUp = now - StartUp;
- Console.WriteLine(">>> {0} [{1} s]", point, timeSinceStartUp.TotalSeconds);
- }
- }
-
- // Substitute @PROC@ in a filename with the given descName
- public static string SubstituteAtPROC(string descName, string fileName) {
- Contract.Requires(fileName != null);
- Contract.Requires(descName != null);
- Contract.Ensures(Contract.Result<string>() != null);
- System.Text.StringBuilder/*!*/ sb =
- new System.Text.StringBuilder(descName.Length);
- // quote the name, characters like ^ cause trouble in CMD
- // while $ could cause trouble in SH
- foreach (char c in descName) {
- if (Char.IsLetterOrDigit(c) || c == '.') {
- sb.Append(c);
- } else {
- sb.Append('_');
- }
- }
- string pn = sb.ToString();
- // We attempt to avoid filenames that are too long, but we only
- // do it by truncating the @PROC@ replacement, which leaves unchanged
- // any filename extension specified by the user. We base our
- // calculations on that there is at most one occurrence of @PROC@.
- if (180 <= fileName.Length - 6 + pn.Length) {
- pn = pn.Substring(0, Math.Max(180 - (fileName.Length - 6), 0)) + "-n" + System.Threading.Interlocked.Increment(ref sequenceId);
- }
-
- return fileName.Replace("@PROC@", pn);
- }
-
- private static int sequenceId = -1;
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+namespace Microsoft.Boogie {
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Diagnostics.Contracts;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ public static class LinqExtender
+ {
+ public static string Concat(this IEnumerable<string> strings, string separator)
+ {
+ var sb = new StringBuilder();
+ var first = true;
+ foreach (var s in strings) {
+ if (!first)
+ sb.Append(separator);
+ first = false;
+ sb.Append(s);
+ }
+ return sb.ToString();
+ }
+
+ public static IEnumerable<T> Concat1<T>(this IEnumerable<T> objects, T final)
+ {
+ foreach (var s in objects) {
+ yield return s;
+ }
+ yield return final;
+ }
+
+ public static string MapConcat<T>(this IEnumerable<T> objects, Func<T,string> toString, string separator)
+ {
+ var sb = new StringBuilder();
+ var first = true;
+ foreach (var s in objects) {
+ if (!first)
+ sb.Append(separator);
+ first = false;
+ sb.Append(toString(s));
+ }
+ return sb.ToString();
+ }
+
+ public static IEnumerable<T> SkipEnd<T>(this IEnumerable<T> source, int count)
+ {
+ var l = source.ToList();
+ if (count >= l.Count)
+ return Enumerable.Empty<T>();
+ l.RemoveRange(l.Count - count, count);
+ return l;
+ }
+
+ public static void Iter<T>(this IEnumerable<T> coll, Action<T> fn)
+ {
+ foreach (var e in coll) fn(e);
+ }
+
+ public static IEnumerable<Tuple<TSource1, TSource2>> Zip<TSource1, TSource2>(this IEnumerable<TSource1> source1, IEnumerable<TSource2> source2)
+ {
+ return source1.Zip(source2, (e1, e2) => new Tuple<TSource1, TSource2>(e1, e2));
+ }
+ }
+
+ public class TokenTextWriter : IDisposable {
+ string/*!*/ filename;
+ TextWriter/*!*/ writer;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(filename != null);
+ Contract.Invariant(writer != null);
+ }
+
+ bool setTokens = true;
+ int line = 1;
+ int col;
+ public bool UseForComputingChecksums;
+
+ private const int indent_size = 2;
+ protected static string Indent(int level) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return new string(' ', (indent_size * level));
+ }
+
+
+ // Keywords, this array *must* be sorted
+ public static readonly string[]/*!*/ BplKeywords =
+ {
+ "assert",
+ "assume",
+ "axiom",
+ "bool",
+ "break",
+ "call",
+ "cast",
+ "const",
+ "else",
+ "ensures",
+ "exists",
+ "false",
+ "forall",
+ "free",
+ "function",
+ "goto",
+ "havoc",
+ "if",
+ "implementation",
+ "int",
+ "invariant",
+ "modifies",
+ "old",
+ "procedure",
+ "public",
+ "requires",
+ "return",
+ "returns",
+ "true",
+ "type",
+ "unique",
+ "var",
+ "where",
+ "while",
+ };
+
+ // "Pretty" printing: not very efficient, and not necessarily very pretty, but helps a bit
+ private readonly bool pretty;
+
+ // The stack of writers in a current separator-block.
+ // The string is an optional identifier that allows you
+ // to not start a new indentation for e.g. "&&" in "a && b && c".
+ // When the pretty printing is finished, this should be empty.
+ Stack<KeyValuePair<string, List<TextWriter>>> wstk;
+
+ // The original writer: where everything should finally end up.
+ TextWriter actual_writer;
+
+ public bool push(string type = null) {
+ if (pretty) {
+ if (wstk == null) {
+ wstk = new Stack<KeyValuePair<string, List<TextWriter>>>();
+ actual_writer = writer;
+ }
+ if (wstk.Count > 0 && wstk.Peek().Key == type && type != null) {
+ sep();
+ return false; // don't actually pop this thing (send this bool to pop)
+ } else {
+ wstk.Push(new KeyValuePair<string, List<TextWriter>>(type, new List<TextWriter> { }));
+ sep();
+ return true; // this needs to be popped
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public void pop(bool do_it = true) {
+ if (pretty) {
+ if (do_it) {
+ List<TextWriter> ws = wstk.Pop().Value;
+ // try to figure out if you should insert line breaks between
+ // them or print them on one single line
+ // this breaks down when there are newlines inserted
+ List<String> ss = new List<String>();
+ int len = 0;
+ foreach (TextWriter w in ws) {
+ foreach (String s in w.ToString().Split(new String[] { "\r\n", "\n" }, StringSplitOptions.None)) {
+ if (s.Length > 0) {
+ ss.Add(s);
+ len += s.Length;
+ // len = Math.Max(len, s.Length);
+ }
+ }
+ }
+ // figure out which is the next writer to use
+ List<TextWriter> tw = wstk.Count > 0 ? wstk.Peek().Value : null;
+ if (tw == null) {
+ writer = actual_writer;
+ } else {
+ writer = tw.Last();
+ }
+ // write the strings (we would like to know WHERE we are in the document here)
+ if (len > 80 /* - wstk.Count * 2 */) {
+ for (int i = 0; i < ss.Count; i++) {
+ if (i != ss.Count - 1) {
+ writer.WriteLine(ss[i]);
+ writer.Write(" ");
+ } else {
+ writer.Write(ss[i]);
+ }
+ }
+ } else {
+ foreach (String s in ss) {
+ writer.Write(s);
+ }
+ }
+ }
+ }
+ }
+
+ public void sep() {
+ if (pretty) {
+ List<TextWriter> ws = wstk.Peek().Value;
+
+ writer = new StringWriter();
+ wstk.Peek().Value.Add(writer);
+ }
+ }
+
+ private IToken/*!*/ CurrentToken {
+ get {
+ Contract.Ensures(Contract.Result<IToken>() != null);
+
+ Token token = new Token();
+ token.filename = filename;
+ token.line = line;
+ token.col = col;
+ return token;
+ }
+ }
+
+ public void SetToken(Absy absy) {
+ Contract.Requires(absy != null);
+ this.SetToken(t => absy.tok = t);
+ }
+
+ public void SetToken(IfThenElse expr)
+ {
+ Contract.Requires(expr != null);
+ this.SetToken(t => expr.tok = t);
+ }
+
+ public void SetToken(Action<IToken> setter) {
+ Contract.Requires(setter != null);
+ if (this.setTokens) {
+ setter(this.CurrentToken);
+ }
+ }
+
+ public void SetToken(ref IToken tok) {
+ Contract.Requires(tok != null);
+ if (this.setTokens) {
+ tok = this.CurrentToken;
+ }
+ }
+
+ public static string SanitizeIdentifier(string name) {
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ int index = Array.BinarySearch(TokenTextWriter.BplKeywords, name);
+ if (index >= 0) {
+ return "\\" + name;
+ } else if (name.Length > 2 && name[0] == 'b' && name[1] == 'v') {
+ int dummy;
+ return int.TryParse(name.Substring(2), out dummy) ? "\\" + name : name;
+ } else if (name.Contains('@')) {
+ return SanitizeIdentifier(name.Replace("@", "#AT#"));
+ } else {
+ return name;
+ }
+ }
+
+ public TokenTextWriter(string filename)
+ : this(filename, false)
+ {
+ }
+
+ public TokenTextWriter(string filename, bool pretty)
+ : base() {
+ Contract.Requires(filename != null);
+ this.pretty = pretty;
+ this.filename = filename;
+ this.writer = new StreamWriter(filename);
+ }
+
+ public TokenTextWriter(string filename, bool setTokens, bool pretty)
+ : base() {
+ Contract.Requires(filename != null);
+ this.pretty = pretty;
+ this.filename = filename;
+ this.writer = new StreamWriter(filename);
+ this.setTokens = setTokens;
+ }
+
+ public TokenTextWriter(string filename, TextWriter writer, bool setTokens, bool pretty)
+ : base() {
+ Contract.Requires(writer != null);
+ Contract.Requires(filename != null);
+ this.pretty = pretty;
+ this.filename = filename;
+ this.writer = writer;
+ this.setTokens = setTokens;
+ }
+
+ public TokenTextWriter(string filename, TextWriter writer, bool pretty)
+ : base() {
+ Contract.Requires(writer != null);
+ Contract.Requires(filename != null);
+ this.pretty = pretty;
+ this.filename = filename;
+ this.writer = writer;
+ }
+
+ public TokenTextWriter(TextWriter writer)
+ : this(writer, false)
+ {
+ }
+
+ public TokenTextWriter(TextWriter writer, bool pretty)
+ : base() {
+ Contract.Requires(writer != null);
+ this.pretty = pretty;
+ this.filename = "<no file>";
+ this.writer = writer;
+ }
+
+ public void Write(string text) {
+ Contract.Requires(text != null);
+ this.writer.Write(text);
+ this.col += text.Length;
+ }
+
+ public void WriteIndent(int level) {
+ if (!UseForComputingChecksums)
+ {
+ this.Write(Indent(level));
+ }
+ }
+
+ public void Write(string text, params object[] args) {
+ Contract.Requires(text != null);
+ this.Write(string.Format(text, args));
+ }
+
+ public void Write(int level, string text) {
+ Contract.Requires(text != null);
+ this.WriteIndent(level);
+ this.Write(text);
+ }
+
+ public void Write(int level, string text, params object[] args) {
+ Contract.Requires(text != null);
+ this.WriteIndent(level);
+ this.Write(text, args);
+ }
+
+ public void Write(Absy node, string text) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.SetToken(node);
+ this.Write(text);
+ }
+
+ public void Write(Absy node, string text, params string[] args) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.SetToken(node);
+ this.Write(text, args);
+ }
+
+ public void Write(Absy node, int level, string text) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.WriteIndent(level);
+ this.SetToken(node);
+ this.Write(text);
+ }
+
+ public void Write(Absy node, int level, string text, params object[] args) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.WriteIndent(level);
+ this.SetToken(node);
+ this.Write(text, args);
+ }
+
+ public void WriteLine() {
+ this.writer.WriteLine();
+ this.line++;
+ this.col = 0;
+ }
+
+ public void WriteLine(string text) {
+ Contract.Requires(text != null);
+ this.writer.WriteLine(text);
+ this.line++;
+ this.col = 0;
+ }
+
+ public void WriteText(string text) {
+ Contract.Requires(text != null);
+ int processed = 0;
+ while (true) {
+ int n = text.IndexOf('\n', processed);
+ if (n == -1) {
+ this.writer.Write(text);
+ this.col += text.Length - processed;
+ return;
+ }
+ processed = n + 1;
+ this.line++;
+ this.col = 0;
+ }
+ }
+
+ public void WriteLine(string text, params object[] args) {
+ Contract.Requires(text != null);
+ this.WriteLine(string.Format(text, args));
+ }
+
+ public void WriteLine(int level, string text) {
+ Contract.Requires(text != null);
+ this.WriteIndent(level);
+ this.WriteLine(text);
+ }
+
+ public void WriteLine(int level, string text, params object[] args) {
+ Contract.Requires(text != null);
+ this.WriteIndent(level);
+ this.WriteLine(text, args);
+ }
+
+ public void WriteLine(Absy node, string text) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.SetToken(node);
+ this.WriteLine(text);
+ }
+
+ public void WriteLine(Absy node, int level, string text) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.SetToken(node);
+ this.WriteLine(level, text);
+ }
+
+ public void WriteLine(Absy node, int level, string text, params object[] args) {
+ Contract.Requires(text != null);
+ Contract.Requires(node != null);
+ this.SetToken(node);
+ this.WriteLine(level, text, args);
+ }
+
+ public void Close() {
+ this.writer.Close();
+ }
+
+ public void Dispose() {
+ this.Close();
+ }
+ }
+
+ public class Helpers {
+ public static string BeautifyBplString(string s) {
+ Contract.Requires(s != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ // strip "^" if it is the first character, change "$result" to "result"
+ if (s.StartsWith("^") || s == "$result") {
+ s = s.Substring(1);
+ } else if (s.StartsWith("call")) {
+ s = s.Substring(s.IndexOf('@') + 1);
+ if (s.StartsWith("formal@")) {
+ s = "(value of formal parameter: " + s.Substring(7) + ")";
+ }
+ }
+ // strip "$in" from the end of identifier names
+ if (s.EndsWith("$in")) {
+ return "(initial value of: " + s.Substring(0, s.Length - 3) + ")";
+ } else {
+ return s;
+ }
+ }
+ public static string PrettyPrintBplExpr(Expr e) {
+ Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ // anything that is unknown will just be printed via ToString
+ // OldExpr and QuantifierExpr, BvExtractExpr, BvConcatExpr are ignored for now
+ // LiteralExpr is printed as itself by ToString
+ if (e is IdentifierExpr) {
+ string s = e.ToString();
+ return Helpers.BeautifyBplString(s);
+ } else if (e is NAryExpr) {
+ NAryExpr ne = (NAryExpr)e;
+ IAppliable fun = ne.Fun;
+ var eSeq = ne.Args;
+ if (fun != null) {
+ if ((fun.FunctionName == "$Length" || fun.FunctionName == "$StringLength") && eSeq.Count == 1) {
+ Expr e0 = eSeq[0];
+ if (e0 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ return s0 + ".Length";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "$typeof" && eSeq.Count == 1) {
+ Expr e0 = eSeq[0];
+ if (e0 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ return "(the dynamic type of: " + s0 + ")";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "IntArrayGet" && eSeq.Count == 2) {
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ return s0 + "[" + s1 + "]";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "$Is" && eSeq.Count == 2) {
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ return "(" + s0 + " == null || (" + s0 + " is " + s1 + "))";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun.FunctionName == "$IsNotNull" && eSeq.Count == 2) {
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ return "(" + s0 + " is " + s1 + ")";
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun is MapSelect && eSeq.Count <= 3) {
+ // only maps with up to two arguments are supported right now (here)
+ if (cce.NonNull(eSeq[0]).ToString() == "$Heap") {
+ //print Index0.Index1, unless Index1 is "$elements", then just print Index0
+ string s0 = PrettyPrintBplExpr(cce.NonNull(eSeq[1]));
+ if (eSeq.Count > 2) {
+ string s1 = PrettyPrintBplExpr(cce.NonNull(eSeq[2]));
+ if (s1 == "$elements") {
+ return s0;
+ } else {
+ if (eSeq[2] is IdentifierExpr) {
+ // strip the class name out of a fieldname
+ s1 = s1.Substring(s1.LastIndexOf('.') + 1);
+ }
+ return s0 + "." + s1;
+ }
+ }
+ }
+ //unexpected, just fall outside to the default
+ } else if (fun is Microsoft.Boogie.BinaryOperator && eSeq.Count == 2) {
+ Microsoft.Boogie.BinaryOperator f = (Microsoft.Boogie.BinaryOperator)fun;
+ Expr e0 = eSeq[0];
+ Expr e1 = eSeq[1];
+ if (e0 != null && e1 != null) {
+ string s0 = PrettyPrintBplExpr(e0);
+ string s1 = PrettyPrintBplExpr(e1);
+ string op = "";
+ switch (f.Op) {
+ case Microsoft.Boogie.BinaryOperator.Opcode.Add:
+ op = " + ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.And:
+ op = " && ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Div:
+ op = " div ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Eq:
+ op = " == ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Ge:
+ op = " >= ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Gt:
+ op = " > ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Iff:
+ op = " <==> ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Imp:
+ op = " ==> ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Le:
+ op = " <= ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Lt:
+ op = " < ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Mod:
+ op = " mod ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Mul:
+ op = " * ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Neq:
+ op = " != ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Or:
+ op = " || ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Pow:
+ op = " ** ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.RealDiv:
+ op = " / ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Sub:
+ op = " - ";
+ break;
+ case Microsoft.Boogie.BinaryOperator.Opcode.Subtype:
+ op = " <: ";
+ break;
+ default:
+ op = " ";
+ break;
+ }
+ return "(" + s0 + op + s1 + ")";
+ }
+ //unexpected, just fall outside to the default
+ } else {
+ string s = fun.FunctionName + "(";
+ for (int i = 0; i < eSeq.Count; i++) {
+ Expr ex = eSeq[i];
+ Contract.Assume(ex != null);
+ if (i > 0) {
+ s += ", ";
+ }
+ string t = PrettyPrintBplExpr(ex);
+ if (t.StartsWith("(") && t.EndsWith(")")) {
+ t = t.Substring(1, t.Length - 2);
+ }
+ s += t;
+ }
+ s += ")";
+ return s;
+ //unexpected, just fall outside to the default
+ }
+ }
+ }
+
+ return e.ToString();
+ }
+
+ private static readonly DateTime StartUp = DateTime.UtcNow;
+
+ public static void ExtraTraceInformation(string point) {
+ Contract.Requires(point != null);
+ if (CommandLineOptions.Clo.TraceTimes) {
+ DateTime now = DateTime.UtcNow;
+ TimeSpan timeSinceStartUp = now - StartUp;
+ Console.WriteLine(">>> {0} [{1} s]", point, timeSinceStartUp.TotalSeconds);
+ }
+ }
+
+ // Substitute @PROC@ in a filename with the given descName
+ public static string SubstituteAtPROC(string descName, string fileName) {
+ Contract.Requires(fileName != null);
+ Contract.Requires(descName != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ System.Text.StringBuilder/*!*/ sb =
+ new System.Text.StringBuilder(descName.Length);
+ // quote the name, characters like ^ cause trouble in CMD
+ // while $ could cause trouble in SH
+ foreach (char c in descName) {
+ if (Char.IsLetterOrDigit(c) || c == '.') {
+ sb.Append(c);
+ } else {
+ sb.Append('_');
+ }
+ }
+ string pn = sb.ToString();
+ // We attempt to avoid filenames that are too long, but we only
+ // do it by truncating the @PROC@ replacement, which leaves unchanged
+ // any filename extension specified by the user. We base our
+ // calculations on that there is at most one occurrence of @PROC@.
+ if (180 <= fileName.Length - 6 + pn.Length) {
+ pn = pn.Substring(0, Math.Max(180 - (fileName.Length - 6), 0)) + "-n" + System.Threading.Interlocked.Increment(ref sequenceId);
+ }
+
+ return fileName.Replace("@PROC@", pn);
+ }
+
+ private static int sequenceId = -1;
+
+ }
+}
diff --git a/Source/Core/VCExp.cs b/Source/Core/VCExp.cs
index 87b8f3e6..63dca024 100644
--- a/Source/Core/VCExp.cs
+++ b/Source/Core/VCExp.cs
@@ -1,238 +1,238 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Text;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-namespace Microsoft.Boogie {
-
- public class ProverOptions {
- public class OptionException : Exception {
- public OptionException(string msg)
- : base(msg) {
- Contract.Requires(msg != null);
- }
- }
-
- public string/*?*/ LogFilename = null;
- public bool AppendLogFile = false;
- public bool SeparateLogFiles = false;
- // Say (DBG_WAS_VALID) or (DBG_WAS_INVALID) after query
- public bool ForceLogStatus = false;
- public int TimeLimit = 0;
- public int MemoryLimit = 0;
- public int Verbosity = 0;
- public string ProverPath;
-
- private string/*!*/ stringRepr = "";
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(stringRepr != null);
- }
-
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return stringRepr;
- }
-
- // The usual thing to override.
- protected virtual bool Parse(string opt) {
- Contract.Requires(opt != null);
- return ParseString(opt, "LOG_FILE", ref LogFilename) ||
- ParseBool(opt, "APPEND_LOG_FILE", ref AppendLogFile) ||
- ParseBool(opt, "FORCE_LOG_STATUS", ref ForceLogStatus) ||
- ParseInt(opt, "MEMORY_LIMIT", ref MemoryLimit) ||
- ParseInt(opt, "VERBOSITY", ref Verbosity) ||
- ParseInt(opt, "TIME_LIMIT", ref TimeLimit) ||
- ParseString(opt, "PROVER_PATH", ref ProverPath);
- // || base.Parse(opt)
- }
-
- public virtual string Help
- {
- get
- {
- return
-@"
-Generic prover options :
-~~~~~~~~~~~~~~~~~~~~~~~
-LOG_FILE=<string> Log input for the theorem prover. The string @PROC@ in the filename
- causes there to be one prover log file per verification condition,
- and is expanded to the name of the procedure that the verification
- condition is for.
-APPEND_LOG_FILE=<bool> Append, rather than overwrite the log file.
-MEMORY_LIMIT=<int> Memory limit of the prover in megabytes.
-VERBOSITY=<int> The higher, the more verbose.
-TIME_LIMIT=<int> Time limit per verification condition in miliseconds.
-PROVER_PATH=<string> Path to the prover to use.
-
-The generic options may or may not be used by the prover plugin.
-";
-
- }
- }
-
- public virtual void Parse(IEnumerable<string/*!*/>/*!*/ opts) {
- Contract.Requires(cce.NonNullElements(opts));
- StringBuilder sb = new StringBuilder(stringRepr);
- Contract.Assert(sb != null);
- foreach (string/*!*/ opt in opts) {
- Contract.Assert(opt != null);
- if (!Parse(opt)) {
- ReportError("Unrecognised prover option: " + opt);
- }
- sb.Append(opt).Append(" ");
- }
- stringRepr = sb.ToString();
- PostParse();
- }
-
- public virtual void PostParse() {
- if (LogFilename != null && LogFilename.Contains("@PROC@")) {
- SeparateLogFiles = true;
- }
- }
-
- protected void ReportError(string msg) {
- Contract.Requires(msg != null);
- throw new OptionException(msg + "\n\n" + Help);
- }
-
- protected virtual bool ParseString(string opt, string name, ref string field) {
- Contract.Requires(name != null);
- Contract.Requires(opt != null);
- if (opt.Length >= name.Length && opt.StartsWith(name)) {
- if (opt.Length == name.Length) {
- field = "";
- return true;
- } else if (opt[name.Length] == '=' || opt[name.Length] == ':') {
- field = opt.Substring(name.Length + 1);
- return true;
- }
- }
- return false;
- }
-
- protected virtual bool ParseBool(string opt, string name, ref bool field) {
- Contract.Requires(name != null);
- Contract.Requires(opt != null);
- string tmp = null;
- if (ParseString(opt, name, ref tmp))
- switch (cce.NonNull(tmp).ToLower()) {
- case "1":
- case "true":
- case "":
- field = true;
- return true;
- case "0":
- case "false":
- field = false;
- return true;
- default:
- ReportError("Invalid Boolean option \"" + opt + "\"");
- return false;
- }
- return false;
- }
-
- protected virtual bool ParseInt(string opt, string name, ref int field) {
- Contract.Requires(name != null);
- Contract.Requires(opt != null);
- string tmp = null;
- int t2;
- if (ParseString(opt, name, ref tmp)) {
- if (int.TryParse(cce.NonNull(tmp), out t2)) {
- field = t2;
- return true;
- } else {
- ReportError("Invalid integer option \"" + opt + "\"");
- }
- }
- return false;
- }
-
- public virtual TextWriter OpenLog(string/*?*/ descName) {
- if (LogFilename != null) {
- string filename = LogFilename;
- Contract.Assert(filename != null);
- if (descName != null)
- filename = Helpers.SubstituteAtPROC(descName, filename);
- return new StreamWriter(filename, AppendLogFile);
- } else {
- return null;
- }
- }
- }
-
- [ContractClass(typeof(ProverFactoryContracts))]
- public abstract class ProverFactory {
- // Really returns ProverInterface.
- //public abstract object! SpawnProver(ProverOptions! options, object! ctxt);
- public abstract object SpawnProver(ProverOptions options, object ctxt);
-
- // Really returns ProverContext
- public abstract object/*!*/ NewProverContext(ProverOptions/*!*/ options);
-
- public virtual ProverOptions BlankProverOptions() {
- Contract.Ensures(Contract.Result<ProverOptions>() != null);
- return new ProverOptions();
- }
-
- // return true if the prover supports DAG AST as opposed to LET AST
- public virtual bool SupportsDags {
- get {
- return false;
- }
- }
-
- public virtual CommandLineOptions.VCVariety DefaultVCVariety {
- get {
- Contract.Ensures(Contract.Result<CommandLineOptions.VCVariety>() != CommandLineOptions.VCVariety.Unspecified);
- return CommandLineOptions.VCVariety.DagIterative;
- }
- }
-
- public virtual bool SupportsLabels(ProverOptions options) {
- return true;
- }
-
- public virtual void Close() {
- }
-
- public static ProverFactory Load(string proverName) {
- Contract.Requires(proverName != null);
- Contract.Ensures(Contract.Result<ProverFactory>() != null);
- Contract.Ensures(cce.IsNew(Contract.Result<ProverFactory>()) && cce.Owner.New(Contract.Result<ProverFactory>()));
- string/*!*/ path;
- if (proverName.IndexOf("/") > 0 || proverName.IndexOf("\\") > 0) {
- path = proverName;
- } else {
- string codebase = cce.NonNull(System.IO.Path.GetDirectoryName(
- cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
- path = System.IO.Path.Combine(codebase, "Provers." + proverName + ".dll");
- }
- Assembly asm = cce.NonNull(Assembly.LoadFrom(path));
- string name = cce.NonNull(asm.GetName().Name);
- System.Type factoryType = cce.NonNull(asm.GetType("Microsoft.Boogie." + name.Replace("Provers.", "") + ".Factory"));
- return cce.NonNull((ProverFactory/*!*/)Activator.CreateInstance(factoryType));
- }
- }
- [ContractClassFor(typeof(ProverFactory))]
- public abstract class ProverFactoryContracts : ProverFactory {
- public override object NewProverContext(ProverOptions options) {
- Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- throw new NotImplementedException();
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+namespace Microsoft.Boogie {
+
+ public class ProverOptions {
+ public class OptionException : Exception {
+ public OptionException(string msg)
+ : base(msg) {
+ Contract.Requires(msg != null);
+ }
+ }
+
+ public string/*?*/ LogFilename = null;
+ public bool AppendLogFile = false;
+ public bool SeparateLogFiles = false;
+ // Say (DBG_WAS_VALID) or (DBG_WAS_INVALID) after query
+ public bool ForceLogStatus = false;
+ public int TimeLimit = 0;
+ public int MemoryLimit = 0;
+ public int Verbosity = 0;
+ public string ProverPath;
+
+ private string/*!*/ stringRepr = "";
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(stringRepr != null);
+ }
+
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return stringRepr;
+ }
+
+ // The usual thing to override.
+ protected virtual bool Parse(string opt) {
+ Contract.Requires(opt != null);
+ return ParseString(opt, "LOG_FILE", ref LogFilename) ||
+ ParseBool(opt, "APPEND_LOG_FILE", ref AppendLogFile) ||
+ ParseBool(opt, "FORCE_LOG_STATUS", ref ForceLogStatus) ||
+ ParseInt(opt, "MEMORY_LIMIT", ref MemoryLimit) ||
+ ParseInt(opt, "VERBOSITY", ref Verbosity) ||
+ ParseInt(opt, "TIME_LIMIT", ref TimeLimit) ||
+ ParseString(opt, "PROVER_PATH", ref ProverPath);
+ // || base.Parse(opt)
+ }
+
+ public virtual string Help
+ {
+ get
+ {
+ return
+@"
+Generic prover options :
+~~~~~~~~~~~~~~~~~~~~~~~
+LOG_FILE=<string> Log input for the theorem prover. The string @PROC@ in the filename
+ causes there to be one prover log file per verification condition,
+ and is expanded to the name of the procedure that the verification
+ condition is for.
+APPEND_LOG_FILE=<bool> Append, rather than overwrite the log file.
+MEMORY_LIMIT=<int> Memory limit of the prover in megabytes.
+VERBOSITY=<int> The higher, the more verbose.
+TIME_LIMIT=<int> Time limit per verification condition in miliseconds.
+PROVER_PATH=<string> Path to the prover to use.
+
+The generic options may or may not be used by the prover plugin.
+";
+
+ }
+ }
+
+ public virtual void Parse(IEnumerable<string/*!*/>/*!*/ opts) {
+ Contract.Requires(cce.NonNullElements(opts));
+ StringBuilder sb = new StringBuilder(stringRepr);
+ Contract.Assert(sb != null);
+ foreach (string/*!*/ opt in opts) {
+ Contract.Assert(opt != null);
+ if (!Parse(opt)) {
+ ReportError("Unrecognised prover option: " + opt);
+ }
+ sb.Append(opt).Append(" ");
+ }
+ stringRepr = sb.ToString();
+ PostParse();
+ }
+
+ public virtual void PostParse() {
+ if (LogFilename != null && LogFilename.Contains("@PROC@")) {
+ SeparateLogFiles = true;
+ }
+ }
+
+ protected void ReportError(string msg) {
+ Contract.Requires(msg != null);
+ throw new OptionException(msg + "\n\n" + Help);
+ }
+
+ protected virtual bool ParseString(string opt, string name, ref string field) {
+ Contract.Requires(name != null);
+ Contract.Requires(opt != null);
+ if (opt.Length >= name.Length && opt.StartsWith(name)) {
+ if (opt.Length == name.Length) {
+ field = "";
+ return true;
+ } else if (opt[name.Length] == '=' || opt[name.Length] == ':') {
+ field = opt.Substring(name.Length + 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected virtual bool ParseBool(string opt, string name, ref bool field) {
+ Contract.Requires(name != null);
+ Contract.Requires(opt != null);
+ string tmp = null;
+ if (ParseString(opt, name, ref tmp))
+ switch (cce.NonNull(tmp).ToLower()) {
+ case "1":
+ case "true":
+ case "":
+ field = true;
+ return true;
+ case "0":
+ case "false":
+ field = false;
+ return true;
+ default:
+ ReportError("Invalid Boolean option \"" + opt + "\"");
+ return false;
+ }
+ return false;
+ }
+
+ protected virtual bool ParseInt(string opt, string name, ref int field) {
+ Contract.Requires(name != null);
+ Contract.Requires(opt != null);
+ string tmp = null;
+ int t2;
+ if (ParseString(opt, name, ref tmp)) {
+ if (int.TryParse(cce.NonNull(tmp), out t2)) {
+ field = t2;
+ return true;
+ } else {
+ ReportError("Invalid integer option \"" + opt + "\"");
+ }
+ }
+ return false;
+ }
+
+ public virtual TextWriter OpenLog(string/*?*/ descName) {
+ if (LogFilename != null) {
+ string filename = LogFilename;
+ Contract.Assert(filename != null);
+ if (descName != null)
+ filename = Helpers.SubstituteAtPROC(descName, filename);
+ return new StreamWriter(filename, AppendLogFile);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ [ContractClass(typeof(ProverFactoryContracts))]
+ public abstract class ProverFactory {
+ // Really returns ProverInterface.
+ //public abstract object! SpawnProver(ProverOptions! options, object! ctxt);
+ public abstract object SpawnProver(ProverOptions options, object ctxt);
+
+ // Really returns ProverContext
+ public abstract object/*!*/ NewProverContext(ProverOptions/*!*/ options);
+
+ public virtual ProverOptions BlankProverOptions() {
+ Contract.Ensures(Contract.Result<ProverOptions>() != null);
+ return new ProverOptions();
+ }
+
+ // return true if the prover supports DAG AST as opposed to LET AST
+ public virtual bool SupportsDags {
+ get {
+ return false;
+ }
+ }
+
+ public virtual CommandLineOptions.VCVariety DefaultVCVariety {
+ get {
+ Contract.Ensures(Contract.Result<CommandLineOptions.VCVariety>() != CommandLineOptions.VCVariety.Unspecified);
+ return CommandLineOptions.VCVariety.DagIterative;
+ }
+ }
+
+ public virtual bool SupportsLabels(ProverOptions options) {
+ return true;
+ }
+
+ public virtual void Close() {
+ }
+
+ public static ProverFactory Load(string proverName) {
+ Contract.Requires(proverName != null);
+ Contract.Ensures(Contract.Result<ProverFactory>() != null);
+ Contract.Ensures(cce.IsNew(Contract.Result<ProverFactory>()) && cce.Owner.New(Contract.Result<ProverFactory>()));
+ string/*!*/ path;
+ if (proverName.IndexOf("/") > 0 || proverName.IndexOf("\\") > 0) {
+ path = proverName;
+ } else {
+ string codebase = cce.NonNull(System.IO.Path.GetDirectoryName(
+ cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
+ path = System.IO.Path.Combine(codebase, "Provers." + proverName + ".dll");
+ }
+ Assembly asm = cce.NonNull(Assembly.LoadFrom(path));
+ string name = cce.NonNull(asm.GetName().Name);
+ System.Type factoryType = cce.NonNull(asm.GetType("Microsoft.Boogie." + name.Replace("Provers.", "") + ".Factory"));
+ return cce.NonNull((ProverFactory/*!*/)Activator.CreateInstance(factoryType));
+ }
+ }
+ [ContractClassFor(typeof(ProverFactory))]
+ public abstract class ProverFactoryContracts : ProverFactory {
+ public override object NewProverContext(ProverOptions options) {
+ Contract.Requires(options != null);
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Source/Core/VariableDependenceAnalyser.cs b/Source/Core/VariableDependenceAnalyser.cs
index ab12a47e..30e1dbf3 100644
--- a/Source/Core/VariableDependenceAnalyser.cs
+++ b/Source/Core/VariableDependenceAnalyser.cs
@@ -1,646 +1,646 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-
-
-namespace Microsoft.Boogie {
-
- public interface IVariableDependenceAnalyser {
-
- void Analyse();
- VariableDescriptor MakeDescriptor(string proc, Variable v);
- HashSet<VariableDescriptor> DependsOn(VariableDescriptor v);
- void dump();
- void ShowDependencyChain(VariableDescriptor source, VariableDescriptor target);
- bool VariableRelevantToAnalysis(Variable v, string proc);
- bool Ignoring(Variable v, string proc);
-
- }
-
- public abstract class VariableDescriptor : IComparable {
- internal readonly string Name;
- internal VariableDescriptor(string Name) {
- this.Name = Name;
- }
-
- public override string ToString() {
- return Name;
- }
-
- public override bool Equals(object that) {
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- }
-
- VariableDescriptor thatDescriptor = that as VariableDescriptor;
-
- if (thatDescriptor == null) {
- return false;
- }
-
- return this.Name.Equals(thatDescriptor.Name);
- }
-
- public override int GetHashCode() {
- return Name.GetHashCode();
- }
-
- public int CompareTo(object that) {
- return this.ToString().CompareTo(that.ToString());
- }
-
- }
-
- public class LocalDescriptor : VariableDescriptor {
- internal readonly string Proc;
- public LocalDescriptor(string Proc, string Name)
- : base(Name) {
- this.Proc = Proc;
- }
-
- public override string ToString() {
- return Proc + "." + base.ToString();
- }
-
- public override bool Equals(object that) {
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- }
-
- LocalDescriptor thatDescriptor = that as LocalDescriptor;
-
- if (thatDescriptor == null) {
- return false;
- }
-
- return base.Equals(thatDescriptor) &&
- this.Proc.Equals(thatDescriptor.Proc);
-
- }
-
- public override int GetHashCode() {
- return (33 * base.GetHashCode())
- + this.Proc.GetHashCode();
- }
-
- }
-
- public class GlobalDescriptor : VariableDescriptor {
- public GlobalDescriptor(string name) : base(name) { }
-
- public override bool Equals(object that) {
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- }
-
- GlobalDescriptor thatDescriptor = that as GlobalDescriptor;
-
- if (thatDescriptor == null) {
- return false;
- }
-
- return base.Equals(thatDescriptor);
-
- }
-
- public override int GetHashCode() {
- return base.GetHashCode();
- }
-
- }
-
- /// <summary>
- /// Given a Boogie program, computes a graph that over-approximates dependences
- /// between program variables.
- /// </summary>
- public class VariableDependenceAnalyser : IVariableDependenceAnalyser {
-
- private Graph<VariableDescriptor> dependsOnNonTransitive;
- private Program prog;
- private Dictionary<Block, HashSet<Block>> BlockToControllingBlocks;
- private Dictionary<Block, HashSet<VariableDescriptor>> ControllingBlockToVariables;
-
- public VariableDependenceAnalyser(Program prog) {
- this.prog = prog;
- dependsOnNonTransitive = new Graph<VariableDescriptor>();
- }
-
-
- private void Initialise() {
- foreach (var descriptor in
- prog.Variables.Where(Item => VariableRelevantToAnalysis(Item, null)).
- Select(Variable => Variable.Name).
- Select(Name => new GlobalDescriptor(Name))) {
- dependsOnNonTransitive.AddEdge(descriptor, descriptor);
- }
-
- foreach (var Proc in prog.NonInlinedProcedures()) {
-
- List<Variable> parameters = new List<Variable>();
- parameters.AddRange(Proc.InParams);
- parameters.AddRange(Proc.OutParams);
- foreach (var descriptor in
- parameters.Select(Variable => Variable.Name).Select(Name => new LocalDescriptor(Proc.Name, Name))) {
- dependsOnNonTransitive.AddEdge(descriptor, descriptor);
- }
- }
-
- foreach (var Impl in prog.NonInlinedImplementations()) {
-
- List<Variable> locals = new List<Variable>();
- locals.AddRange(Impl.LocVars);
- foreach (var descriptor in
- locals.Select(Variable => Variable.Name).Select(Name => new LocalDescriptor(Impl.Name, Name))) {
- dependsOnNonTransitive.AddEdge(descriptor, descriptor);
- }
- }
- }
-
- private List<VariableDescriptor> ComputeDependencyChain(VariableDescriptor source, VariableDescriptor target, HashSet<VariableDescriptor> visited) {
- if(source.Equals(target)) {
- return new List<VariableDescriptor> { target };
- }
-
- visited.Add(source);
-
- foreach(var w in dependsOnNonTransitive.Successors(source)) {
- if(visited.Contains(w)) {
- continue;
- }
- var result = ComputeDependencyChain(w, target, visited);
- if(result != null) {
- result.Insert(0, source);
- return result;
- }
- }
-
- return null;
-
- }
-
- public void ShowDependencyChain(VariableDescriptor source, VariableDescriptor target) {
- var chain = ComputeDependencyChain(source, target, new HashSet<VariableDescriptor>());
- if(chain == null) {
- Console.WriteLine("No chain between " + source + " and " + target);
- } else {
- bool first = true;
- foreach(var v in chain) {
- if(first) {
- first = false;
- } else {
- Console.Write(" -> ");
- }
- Console.Write(v);
- }
- }
- Console.WriteLine(); Console.WriteLine();
- }
-
- public void Analyse() {
-
- /* The algorithm is as follows:
- *
- * 1. Build global control dependence graph. First build control dependence graph for each procedure,
- * and union them. Then examine each procedure. If block B is control-dependent on block C, make
- * every block that can be indirectly reached via a call from B control-dependent on C.
- *
- * 2. Take transitive closure of global control dependence graph.
- *
- * 3. For every block B such that some other block is control-dependent on B, determine those variables
- * which B tests. If B tests v, and C is control-depdendent on B, we say that v "controls" the
- * statements appearing in C.
- *
- * 4. Consider each statement to work out variable dependences. v may depend on u if:
- * - there is a statement v := e where u appears in e
- * - there is a statement call ... := foo(..., e, ...) where v is formal in parameter of foo
- * corresponding to e and u appears in e
- * - there is a statement call ..., v, ... := foo(...) where u is formal out parameter of foo
- * correspondnig to v
- * - there is a statement v := ... controlled by u
- * - there is a statement call ... := foo(...) controlled by u where v is a formal in parameter
- * of foo
- * - there is a statement call ..., v, ... := foo(...) controlled by u
- *
- * 5. Finialise variable dependence graph by taking its transitive closure.
- *
- */
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Variable dependence analysis: Initialising");
- }
-
- Initialise();
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Variable dependence analysis: Computing control dependence info");
- }
-
- BlockToControllingBlocks = ComputeGlobalControlDependences();
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Variable dependence analysis: Computing control dependence variables");
- }
-
- ControllingBlockToVariables = ComputeControllingVariables(BlockToControllingBlocks);
- foreach (var Impl in prog.NonInlinedImplementations()) {
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Variable dependence analysis: Analysing " + Impl.Name);
- }
-
- Analyse(Impl);
- }
- }
-
- private void Analyse(Implementation Impl) {
- string proc = Impl.Name;
- foreach (Block b in Impl.Blocks) {
- Analyse(proc, b);
- }
- }
-
- private void Analyse(string proc, Block b) {
- foreach (Cmd cmd in b.Cmds) {
- AssignCmd assign = cmd as AssignCmd;
- if (assign != null) {
- HandleAssign(proc, b, assign);
- }
- CallCmd call = cmd as CallCmd;
- if (call != null) {
- HandleCall(proc, b, call);
- }
- }
- }
-
- private void HandleCall(string proc, Block b, CallCmd call) {
- foreach (var formalActualPair in call.Proc.InParams.Zip(call.Ins)) {
- var formalIn = MakeDescriptor(call.callee, formalActualPair.Item1);
- AddDependences(formalIn, GetReferencedVariables(formalActualPair.Item2, proc),
- "referenced in in-param in call to " + proc, call.tok);
- AddControlDependences(b, formalIn, " in param assigned under control dependence in call to " + proc, call.tok);
- }
-
- foreach (var formalActualPair in call.Proc.OutParams.Zip(call.Outs)) {
- var actualOut = MakeDescriptor(proc, formalActualPair.Item2.Decl);
- AddDependences(actualOut, GetReferencedVariables(new IdentifierExpr(Token.NoToken, formalActualPair.Item1), call.callee),
- "receiving variable for out-param in call to " + proc, call.tok);
- AddControlDependences(b, actualOut, " receiving variable assigned under control dependence in call to " + proc, call.tok);
- }
-
- }
-
- private void HandleAssign(string proc, Block b, AssignCmd assign) {
- foreach (var assignPair in assign.Lhss.Zip(assign.Rhss).Where
- (Item => VariableRelevantToAnalysis(Item.Item1.DeepAssignedVariable, proc))) {
- VariableDescriptor assignedVariable = MakeDescriptor(proc, assignPair.Item1.DeepAssignedVariable);
- AddDependences(assignedVariable, GetReferencedVariables(assignPair.Item1, proc),
- "LHS of assignment", assign.tok);
- AddDependences(assignedVariable, GetReferencedVariables(assignPair.Item2, proc),
- "RHS of assignment", assign.tok);
- AddControlDependences(b, assignedVariable, "Variable assigned under control dependence", assign.tok);
- }
- }
-
- private void AddControlDependences(Block b, VariableDescriptor v, string reason, IToken tok) {
- if (!BlockToControllingBlocks.ContainsKey(b)) {
- return;
- }
- foreach (var controller in BlockToControllingBlocks[b]) {
- AddDependences(v, ControllingBlockToVariables[controller], reason + " controlling block at (" + controller.tok.line + ":" + controller.tok.col + ")", tok);
- }
- }
-
- private IEnumerable<VariableDescriptor> GetReferencedVariables(Absy node, string proc) {
- var VarCollector = new VariableCollector();
- VarCollector.Visit(node);
- return VarCollector.usedVars.Where(Item => VariableRelevantToAnalysis(Item, proc)).
- Select(Item => MakeDescriptor(proc, Item));
- }
-
- void AddDependences(VariableDescriptor v, IEnumerable<VariableDescriptor> vs, string reason, IToken tok) {
- foreach (var n in vs) {
- if(CommandLineOptions.Clo.DebugStagedHoudini) {
- Console.WriteLine("Adding dependence " + v + " -> " + n + ", reason: " + reason + "(" + tok.line + ":" + tok.col + ")");
- }
- dependsOnNonTransitive.AddEdge(v, n);
- }
- }
-
- private Dictionary<Block, HashSet<VariableDescriptor>> ComputeControllingVariables(Dictionary<Block, HashSet<Block>> GlobalCtrlDep) {
- Dictionary<Block, HashSet<VariableDescriptor>> result = new Dictionary<Block, HashSet<VariableDescriptor>>();
- foreach (var Impl in prog.NonInlinedImplementations()) {
- foreach (var b in Impl.Blocks) {
- result[b] = GetControlDependencyVariables(Impl.Name, b);
- }
- }
- return result;
- }
-
- private HashSet<VariableDescriptor> GetControlDependencyVariables(string proc, Block b) {
-
- // This method works under the assumption that assume statements
- // relevant to control flow between basic blocks have the "partition" attribute
-
- HashSet<VariableDescriptor> result = new HashSet<VariableDescriptor>();
- var gotoCmd = b.TransferCmd as GotoCmd;
- if (gotoCmd != null && gotoCmd.labelTargets.Count >= 2) {
- foreach (Block succ in gotoCmd.labelTargets) {
- foreach (Cmd c in succ.Cmds) {
- AssumeCmd a = c as AssumeCmd;
- if (a != null && QKeyValue.FindBoolAttribute(a.Attributes, "partition")) {
- var VarCollector = new VariableCollector();
- VarCollector.VisitExpr(a.Expr);
- result.UnionWith(VarCollector.usedVars.Where(Item => VariableRelevantToAnalysis(Item, proc)).
- Select(Item => MakeDescriptor(proc, Item)));
- }
- else {
- break;
- }
- }
- }
- }
- return result;
- }
-
- private HashSet<VariableDescriptor> IgnoredVariables = null;
-
- public bool Ignoring(Variable v, string proc) {
-
- if (IgnoredVariables == null) {
- MakeIgnoreList();
- }
-
- if(proc != null && IgnoredVariables.Contains(new LocalDescriptor(proc, v.Name))) {
- return true;
- }
-
- if(IgnoredVariables.Contains(new GlobalDescriptor(v.Name))) {
- return true;
- }
-
- return false;
-
- }
-
- public bool VariableRelevantToAnalysis(Variable v, string proc) {
- return !(v is Constant || Ignoring(v, proc));
- }
-
- private void MakeIgnoreList()
- {
- IgnoredVariables = new HashSet<VariableDescriptor>();
- if(CommandLineOptions.Clo.VariableDependenceIgnore == null) {
- return;
- }
- try {
- var file = System.IO.File.OpenText(CommandLineOptions.Clo.VariableDependenceIgnore);
- while(!file.EndOfStream) {
- string line = file.ReadLine();
- string[] tokens = line.Split(' ');
- if(tokens.Count() == 0) {
- continue;
- }
- if(tokens.Count() > 2) {
- Console.Error.WriteLine("Ignoring malformed line of ignored variables file: " + line);
- continue;
- }
- if(tokens.Count() == 1) {
- IgnoredVariables.Add(new GlobalDescriptor(tokens[0]));
- continue;
- }
- Debug.Assert(tokens.Count() == 2);
- IgnoredVariables.Add(new LocalDescriptor(tokens[0], tokens[1]));
- }
- } catch(System.IO.IOException e) {
- Console.Error.WriteLine("Error reading from ignored variables file " + CommandLineOptions.Clo.VariableDependenceIgnore + ": " + e);
- }
- }
-
- private Dictionary<Block, HashSet<Block>> ComputeGlobalControlDependences() {
-
- Dictionary<Block, HashSet<Block>> GlobalCtrlDep = new Dictionary<Block, HashSet<Block>>();
- Dictionary<Implementation, Dictionary<Block, HashSet<Block>>> LocalCtrlDeps = new Dictionary<Implementation, Dictionary<Block, HashSet<Block>>>();
-
- // Work out and union together local control dependences
- foreach (var Impl in prog.NonInlinedImplementations()) {
- Graph<Block> blockGraph = prog.ProcessLoops(Impl);
- LocalCtrlDeps[Impl] = blockGraph.ControlDependence();
- foreach (var KeyValue in LocalCtrlDeps[Impl]) {
- GlobalCtrlDep.Add(KeyValue.Key, KeyValue.Value);
- }
- }
-
- Graph<Implementation> callGraph = Program.BuildCallGraph(prog);
-
- // Add inter-procedural control dependence nodes based on calls
- foreach (var Impl in prog.NonInlinedImplementations()) {
- foreach (var b in Impl.Blocks) {
- foreach (var cmd in b.Cmds.OfType<CallCmd>()) {
- var DirectCallee = GetImplementation(cmd.callee);
- if (DirectCallee != null) {
- HashSet<Implementation> IndirectCallees = ComputeIndirectCallees(callGraph, DirectCallee);
- foreach (var control in GetControllingBlocks(b, LocalCtrlDeps[Impl])) {
- foreach (var c in IndirectCallees.Select(Item => Item.Blocks).SelectMany(Item => Item)) {
- GlobalCtrlDep[control].Add(c);
- }
- }
- }
- }
- }
- }
-
- // Compute transitive closure
- GlobalCtrlDep.TransitiveClosure();
-
- // Finally reverse the dependences
-
- Dictionary<Block, HashSet<Block>> result = new Dictionary<Block, HashSet<Block>>();
-
- foreach (var KeyValue in GlobalCtrlDep) {
- foreach (var v in KeyValue.Value) {
- if (!result.ContainsKey(v)) {
- result[v] = new HashSet<Block>();
- }
- result[v].Add(KeyValue.Key);
- }
- }
-
- return result;
- }
-
- private HashSet<Implementation> ComputeIndirectCallees(Graph<Implementation> callGraph, Implementation DirectCallee) {
- return ComputeIndirectCallees(callGraph, DirectCallee, new HashSet<Implementation>());
- }
-
- private HashSet<Implementation> ComputeIndirectCallees(Graph<Implementation> callGraph, Implementation DirectCallee, HashSet<Implementation> seen) {
- if (seen.Contains(DirectCallee)) {
- return new HashSet<Implementation>();
- }
- HashSet<Implementation> result = new HashSet<Implementation>();
- result.Add(DirectCallee);
- seen.Add(DirectCallee);
- foreach (var succ in callGraph.Successors(DirectCallee)) {
- result.UnionWith(ComputeIndirectCallees(callGraph, succ, seen));
- }
- return result;
- }
-
- private HashSet<Block> GetControllingBlocks(Block b, Dictionary<Block, HashSet<Block>> ctrlDep) {
- HashSet<Block> result = new HashSet<Block>();
- foreach (var KeyValue in ctrlDep) {
- if (KeyValue.Value.Contains(b)) {
- result.Add(KeyValue.Key);
- }
- }
- return result;
- }
-
- private Implementation GetImplementation(string proc) {
- foreach (var Impl in prog.Implementations) {
- if (Impl.Name.Equals(proc)) {
- return Impl;
- }
- }
- return null;
- }
-
- public VariableDescriptor MakeDescriptor(string proc, Variable v) {
-
- // Check whether there is an (Impl, v) match
- var MatchingLocals = dependsOnNonTransitive.Nodes.Where(Item => Item is LocalDescriptor).Select(
- Item => (LocalDescriptor)Item).Where(Item => Item.Proc.Equals(proc) &&
- Item.Name.Equals(v.Name));
- if (MatchingLocals.Count() > 0) {
- Debug.Assert(MatchingLocals.Count() == 1);
- return MatchingLocals.ToArray()[0];
- }
-
- // It must be a global with same name as v
- return dependsOnNonTransitive.Nodes.Where(Item => Item is GlobalDescriptor &&
- Item.Name.Equals(v.Name)).ToArray()[0];
- }
-
- private Dictionary<SCC<VariableDescriptor>, HashSet<VariableDescriptor>> DependsOnCache = new Dictionary<SCC<VariableDescriptor>, HashSet<VariableDescriptor>>();
-
- private Graph<SCC<VariableDescriptor>> DependsOnSCCsDAG;
- private Dictionary<VariableDescriptor, SCC<VariableDescriptor>> VariableDescriptorToSCC;
-
- public HashSet<VariableDescriptor> DependsOn(VariableDescriptor v) {
- if (DependsOnSCCsDAG == null) {
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Variable dependence: computing SCCs");
- }
- Adjacency<VariableDescriptor> next = new Adjacency<VariableDescriptor>(dependsOnNonTransitive.Successors);
- Adjacency<VariableDescriptor> prev = new Adjacency<VariableDescriptor>(dependsOnNonTransitive.Predecessors);
- StronglyConnectedComponents<VariableDescriptor> DependsOnSCCs = new StronglyConnectedComponents<VariableDescriptor>(
- dependsOnNonTransitive.Nodes, next, prev);
- DependsOnSCCs.Compute();
-
- VariableDescriptorToSCC = new Dictionary<VariableDescriptor, SCC<VariableDescriptor>>();
- foreach (var scc in DependsOnSCCs) {
- foreach (var s in scc) {
- VariableDescriptorToSCC[s] = scc;
- }
- }
-
- DependsOnSCCsDAG = new Graph<SCC<VariableDescriptor>>();
- foreach (var edge in dependsOnNonTransitive.Edges) {
- if (VariableDescriptorToSCC[edge.Item1] != VariableDescriptorToSCC[edge.Item2]) {
- DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[edge.Item1], VariableDescriptorToSCC[edge.Item2]);
- }
- }
-
- SCC<VariableDescriptor> dummy = new SCC<VariableDescriptor>();
- foreach (var n in dependsOnNonTransitive.Nodes) {
- DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[n], dummy);
- }
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Variable dependence: SCCs computed!");
- }
- }
- return DependsOn(VariableDescriptorToSCC[v]);
- }
-
- public HashSet<VariableDescriptor> DependsOn(SCC<VariableDescriptor> vSCC) {
-
- if (!DependsOnCache.ContainsKey(vSCC)) {
- HashSet<VariableDescriptor> result = new HashSet<VariableDescriptor>();
- if (vSCC.Count() > 0) {
- result.UnionWith(vSCC);
- foreach (var wSCC in DependsOnSCCsDAG.Successors(vSCC)) {
- result.UnionWith(DependsOn(wSCC));
- }
- }
- DependsOnCache[vSCC] = result;
- }
- return DependsOnCache[vSCC];
- }
-
- public void dump() {
-
- Console.WriteLine("Variable dependence information");
- Console.WriteLine("===============================");
-
- Console.WriteLine("Global variables");
- Console.WriteLine("================");
-
- foreach (var GlobalEntry in dependsOnNonTransitive.Nodes.Where(Item => Item is GlobalDescriptor)) {
- dump(GlobalEntry);
- }
-
- foreach (var proc in Procedures()) {
- Console.WriteLine("Variables of " + proc);
- Console.WriteLine("=====================");
- foreach (var LocalEntry in dependsOnNonTransitive.Nodes.Where(Item => Item is LocalDescriptor
- && ((LocalDescriptor)Item).Proc.Equals(proc))) {
- dump(LocalEntry);
- }
- }
- }
-
- private void dump(VariableDescriptor vd) {
- Console.Write(vd + " <- {");
- bool first = true;
-
- var SortedDependents = DependsOn(vd).ToList();
- SortedDependents.Sort();
- foreach (var Descriptor in SortedDependents) {
- Console.Write((first ? "" : ",") + "\n " + Descriptor);
- if (first) {
- first = false;
- }
- }
- Debug.Assert(!first);
- Console.WriteLine("\n}\n");
- }
-
- private HashSet<string> Procedures() {
- return new HashSet<string>(dependsOnNonTransitive.Nodes.Where(Item =>
- Item is LocalDescriptor).Select(Item => ((LocalDescriptor)Item).Proc));
- }
-
- }
-
- public static class Helper {
-
- public static IEnumerable<Procedure> NonInlinedProcedures(this Program prog) {
- return prog.Procedures.
- Where(Item => QKeyValue.FindIntAttribute(Item.Attributes, "inline", -1) == -1);
- }
-
- public static IEnumerable<Implementation> NonInlinedImplementations(this Program prog) {
- return prog.Implementations.
- Where(Item => QKeyValue.FindIntAttribute(Item.Proc.Attributes, "inline", -1) == -1);
- }
-
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+
+
+namespace Microsoft.Boogie {
+
+ public interface IVariableDependenceAnalyser {
+
+ void Analyse();
+ VariableDescriptor MakeDescriptor(string proc, Variable v);
+ HashSet<VariableDescriptor> DependsOn(VariableDescriptor v);
+ void dump();
+ void ShowDependencyChain(VariableDescriptor source, VariableDescriptor target);
+ bool VariableRelevantToAnalysis(Variable v, string proc);
+ bool Ignoring(Variable v, string proc);
+
+ }
+
+ public abstract class VariableDescriptor : IComparable {
+ internal readonly string Name;
+ internal VariableDescriptor(string Name) {
+ this.Name = Name;
+ }
+
+ public override string ToString() {
+ return Name;
+ }
+
+ public override bool Equals(object that) {
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ }
+
+ VariableDescriptor thatDescriptor = that as VariableDescriptor;
+
+ if (thatDescriptor == null) {
+ return false;
+ }
+
+ return this.Name.Equals(thatDescriptor.Name);
+ }
+
+ public override int GetHashCode() {
+ return Name.GetHashCode();
+ }
+
+ public int CompareTo(object that) {
+ return this.ToString().CompareTo(that.ToString());
+ }
+
+ }
+
+ public class LocalDescriptor : VariableDescriptor {
+ internal readonly string Proc;
+ public LocalDescriptor(string Proc, string Name)
+ : base(Name) {
+ this.Proc = Proc;
+ }
+
+ public override string ToString() {
+ return Proc + "." + base.ToString();
+ }
+
+ public override bool Equals(object that) {
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ }
+
+ LocalDescriptor thatDescriptor = that as LocalDescriptor;
+
+ if (thatDescriptor == null) {
+ return false;
+ }
+
+ return base.Equals(thatDescriptor) &&
+ this.Proc.Equals(thatDescriptor.Proc);
+
+ }
+
+ public override int GetHashCode() {
+ return (33 * base.GetHashCode())
+ + this.Proc.GetHashCode();
+ }
+
+ }
+
+ public class GlobalDescriptor : VariableDescriptor {
+ public GlobalDescriptor(string name) : base(name) { }
+
+ public override bool Equals(object that) {
+
+ if (object.ReferenceEquals(this, that)) {
+ return true;
+ }
+
+ GlobalDescriptor thatDescriptor = that as GlobalDescriptor;
+
+ if (thatDescriptor == null) {
+ return false;
+ }
+
+ return base.Equals(thatDescriptor);
+
+ }
+
+ public override int GetHashCode() {
+ return base.GetHashCode();
+ }
+
+ }
+
+ /// <summary>
+ /// Given a Boogie program, computes a graph that over-approximates dependences
+ /// between program variables.
+ /// </summary>
+ public class VariableDependenceAnalyser : IVariableDependenceAnalyser {
+
+ private Graph<VariableDescriptor> dependsOnNonTransitive;
+ private Program prog;
+ private Dictionary<Block, HashSet<Block>> BlockToControllingBlocks;
+ private Dictionary<Block, HashSet<VariableDescriptor>> ControllingBlockToVariables;
+
+ public VariableDependenceAnalyser(Program prog) {
+ this.prog = prog;
+ dependsOnNonTransitive = new Graph<VariableDescriptor>();
+ }
+
+
+ private void Initialise() {
+ foreach (var descriptor in
+ prog.Variables.Where(Item => VariableRelevantToAnalysis(Item, null)).
+ Select(Variable => Variable.Name).
+ Select(Name => new GlobalDescriptor(Name))) {
+ dependsOnNonTransitive.AddEdge(descriptor, descriptor);
+ }
+
+ foreach (var Proc in prog.NonInlinedProcedures()) {
+
+ List<Variable> parameters = new List<Variable>();
+ parameters.AddRange(Proc.InParams);
+ parameters.AddRange(Proc.OutParams);
+ foreach (var descriptor in
+ parameters.Select(Variable => Variable.Name).Select(Name => new LocalDescriptor(Proc.Name, Name))) {
+ dependsOnNonTransitive.AddEdge(descriptor, descriptor);
+ }
+ }
+
+ foreach (var Impl in prog.NonInlinedImplementations()) {
+
+ List<Variable> locals = new List<Variable>();
+ locals.AddRange(Impl.LocVars);
+ foreach (var descriptor in
+ locals.Select(Variable => Variable.Name).Select(Name => new LocalDescriptor(Impl.Name, Name))) {
+ dependsOnNonTransitive.AddEdge(descriptor, descriptor);
+ }
+ }
+ }
+
+ private List<VariableDescriptor> ComputeDependencyChain(VariableDescriptor source, VariableDescriptor target, HashSet<VariableDescriptor> visited) {
+ if(source.Equals(target)) {
+ return new List<VariableDescriptor> { target };
+ }
+
+ visited.Add(source);
+
+ foreach(var w in dependsOnNonTransitive.Successors(source)) {
+ if(visited.Contains(w)) {
+ continue;
+ }
+ var result = ComputeDependencyChain(w, target, visited);
+ if(result != null) {
+ result.Insert(0, source);
+ return result;
+ }
+ }
+
+ return null;
+
+ }
+
+ public void ShowDependencyChain(VariableDescriptor source, VariableDescriptor target) {
+ var chain = ComputeDependencyChain(source, target, new HashSet<VariableDescriptor>());
+ if(chain == null) {
+ Console.WriteLine("No chain between " + source + " and " + target);
+ } else {
+ bool first = true;
+ foreach(var v in chain) {
+ if(first) {
+ first = false;
+ } else {
+ Console.Write(" -> ");
+ }
+ Console.Write(v);
+ }
+ }
+ Console.WriteLine(); Console.WriteLine();
+ }
+
+ public void Analyse() {
+
+ /* The algorithm is as follows:
+ *
+ * 1. Build global control dependence graph. First build control dependence graph for each procedure,
+ * and union them. Then examine each procedure. If block B is control-dependent on block C, make
+ * every block that can be indirectly reached via a call from B control-dependent on C.
+ *
+ * 2. Take transitive closure of global control dependence graph.
+ *
+ * 3. For every block B such that some other block is control-dependent on B, determine those variables
+ * which B tests. If B tests v, and C is control-depdendent on B, we say that v "controls" the
+ * statements appearing in C.
+ *
+ * 4. Consider each statement to work out variable dependences. v may depend on u if:
+ * - there is a statement v := e where u appears in e
+ * - there is a statement call ... := foo(..., e, ...) where v is formal in parameter of foo
+ * corresponding to e and u appears in e
+ * - there is a statement call ..., v, ... := foo(...) where u is formal out parameter of foo
+ * correspondnig to v
+ * - there is a statement v := ... controlled by u
+ * - there is a statement call ... := foo(...) controlled by u where v is a formal in parameter
+ * of foo
+ * - there is a statement call ..., v, ... := foo(...) controlled by u
+ *
+ * 5. Finialise variable dependence graph by taking its transitive closure.
+ *
+ */
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Variable dependence analysis: Initialising");
+ }
+
+ Initialise();
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Variable dependence analysis: Computing control dependence info");
+ }
+
+ BlockToControllingBlocks = ComputeGlobalControlDependences();
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Variable dependence analysis: Computing control dependence variables");
+ }
+
+ ControllingBlockToVariables = ComputeControllingVariables(BlockToControllingBlocks);
+ foreach (var Impl in prog.NonInlinedImplementations()) {
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Variable dependence analysis: Analysing " + Impl.Name);
+ }
+
+ Analyse(Impl);
+ }
+ }
+
+ private void Analyse(Implementation Impl) {
+ string proc = Impl.Name;
+ foreach (Block b in Impl.Blocks) {
+ Analyse(proc, b);
+ }
+ }
+
+ private void Analyse(string proc, Block b) {
+ foreach (Cmd cmd in b.Cmds) {
+ AssignCmd assign = cmd as AssignCmd;
+ if (assign != null) {
+ HandleAssign(proc, b, assign);
+ }
+ CallCmd call = cmd as CallCmd;
+ if (call != null) {
+ HandleCall(proc, b, call);
+ }
+ }
+ }
+
+ private void HandleCall(string proc, Block b, CallCmd call) {
+ foreach (var formalActualPair in call.Proc.InParams.Zip(call.Ins)) {
+ var formalIn = MakeDescriptor(call.callee, formalActualPair.Item1);
+ AddDependences(formalIn, GetReferencedVariables(formalActualPair.Item2, proc),
+ "referenced in in-param in call to " + proc, call.tok);
+ AddControlDependences(b, formalIn, " in param assigned under control dependence in call to " + proc, call.tok);
+ }
+
+ foreach (var formalActualPair in call.Proc.OutParams.Zip(call.Outs)) {
+ var actualOut = MakeDescriptor(proc, formalActualPair.Item2.Decl);
+ AddDependences(actualOut, GetReferencedVariables(new IdentifierExpr(Token.NoToken, formalActualPair.Item1), call.callee),
+ "receiving variable for out-param in call to " + proc, call.tok);
+ AddControlDependences(b, actualOut, " receiving variable assigned under control dependence in call to " + proc, call.tok);
+ }
+
+ }
+
+ private void HandleAssign(string proc, Block b, AssignCmd assign) {
+ foreach (var assignPair in assign.Lhss.Zip(assign.Rhss).Where
+ (Item => VariableRelevantToAnalysis(Item.Item1.DeepAssignedVariable, proc))) {
+ VariableDescriptor assignedVariable = MakeDescriptor(proc, assignPair.Item1.DeepAssignedVariable);
+ AddDependences(assignedVariable, GetReferencedVariables(assignPair.Item1, proc),
+ "LHS of assignment", assign.tok);
+ AddDependences(assignedVariable, GetReferencedVariables(assignPair.Item2, proc),
+ "RHS of assignment", assign.tok);
+ AddControlDependences(b, assignedVariable, "Variable assigned under control dependence", assign.tok);
+ }
+ }
+
+ private void AddControlDependences(Block b, VariableDescriptor v, string reason, IToken tok) {
+ if (!BlockToControllingBlocks.ContainsKey(b)) {
+ return;
+ }
+ foreach (var controller in BlockToControllingBlocks[b]) {
+ AddDependences(v, ControllingBlockToVariables[controller], reason + " controlling block at (" + controller.tok.line + ":" + controller.tok.col + ")", tok);
+ }
+ }
+
+ private IEnumerable<VariableDescriptor> GetReferencedVariables(Absy node, string proc) {
+ var VarCollector = new VariableCollector();
+ VarCollector.Visit(node);
+ return VarCollector.usedVars.Where(Item => VariableRelevantToAnalysis(Item, proc)).
+ Select(Item => MakeDescriptor(proc, Item));
+ }
+
+ void AddDependences(VariableDescriptor v, IEnumerable<VariableDescriptor> vs, string reason, IToken tok) {
+ foreach (var n in vs) {
+ if(CommandLineOptions.Clo.DebugStagedHoudini) {
+ Console.WriteLine("Adding dependence " + v + " -> " + n + ", reason: " + reason + "(" + tok.line + ":" + tok.col + ")");
+ }
+ dependsOnNonTransitive.AddEdge(v, n);
+ }
+ }
+
+ private Dictionary<Block, HashSet<VariableDescriptor>> ComputeControllingVariables(Dictionary<Block, HashSet<Block>> GlobalCtrlDep) {
+ Dictionary<Block, HashSet<VariableDescriptor>> result = new Dictionary<Block, HashSet<VariableDescriptor>>();
+ foreach (var Impl in prog.NonInlinedImplementations()) {
+ foreach (var b in Impl.Blocks) {
+ result[b] = GetControlDependencyVariables(Impl.Name, b);
+ }
+ }
+ return result;
+ }
+
+ private HashSet<VariableDescriptor> GetControlDependencyVariables(string proc, Block b) {
+
+ // This method works under the assumption that assume statements
+ // relevant to control flow between basic blocks have the "partition" attribute
+
+ HashSet<VariableDescriptor> result = new HashSet<VariableDescriptor>();
+ var gotoCmd = b.TransferCmd as GotoCmd;
+ if (gotoCmd != null && gotoCmd.labelTargets.Count >= 2) {
+ foreach (Block succ in gotoCmd.labelTargets) {
+ foreach (Cmd c in succ.Cmds) {
+ AssumeCmd a = c as AssumeCmd;
+ if (a != null && QKeyValue.FindBoolAttribute(a.Attributes, "partition")) {
+ var VarCollector = new VariableCollector();
+ VarCollector.VisitExpr(a.Expr);
+ result.UnionWith(VarCollector.usedVars.Where(Item => VariableRelevantToAnalysis(Item, proc)).
+ Select(Item => MakeDescriptor(proc, Item)));
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private HashSet<VariableDescriptor> IgnoredVariables = null;
+
+ public bool Ignoring(Variable v, string proc) {
+
+ if (IgnoredVariables == null) {
+ MakeIgnoreList();
+ }
+
+ if(proc != null && IgnoredVariables.Contains(new LocalDescriptor(proc, v.Name))) {
+ return true;
+ }
+
+ if(IgnoredVariables.Contains(new GlobalDescriptor(v.Name))) {
+ return true;
+ }
+
+ return false;
+
+ }
+
+ public bool VariableRelevantToAnalysis(Variable v, string proc) {
+ return !(v is Constant || Ignoring(v, proc));
+ }
+
+ private void MakeIgnoreList()
+ {
+ IgnoredVariables = new HashSet<VariableDescriptor>();
+ if(CommandLineOptions.Clo.VariableDependenceIgnore == null) {
+ return;
+ }
+ try {
+ var file = System.IO.File.OpenText(CommandLineOptions.Clo.VariableDependenceIgnore);
+ while(!file.EndOfStream) {
+ string line = file.ReadLine();
+ string[] tokens = line.Split(' ');
+ if(tokens.Count() == 0) {
+ continue;
+ }
+ if(tokens.Count() > 2) {
+ Console.Error.WriteLine("Ignoring malformed line of ignored variables file: " + line);
+ continue;
+ }
+ if(tokens.Count() == 1) {
+ IgnoredVariables.Add(new GlobalDescriptor(tokens[0]));
+ continue;
+ }
+ Debug.Assert(tokens.Count() == 2);
+ IgnoredVariables.Add(new LocalDescriptor(tokens[0], tokens[1]));
+ }
+ } catch(System.IO.IOException e) {
+ Console.Error.WriteLine("Error reading from ignored variables file " + CommandLineOptions.Clo.VariableDependenceIgnore + ": " + e);
+ }
+ }
+
+ private Dictionary<Block, HashSet<Block>> ComputeGlobalControlDependences() {
+
+ Dictionary<Block, HashSet<Block>> GlobalCtrlDep = new Dictionary<Block, HashSet<Block>>();
+ Dictionary<Implementation, Dictionary<Block, HashSet<Block>>> LocalCtrlDeps = new Dictionary<Implementation, Dictionary<Block, HashSet<Block>>>();
+
+ // Work out and union together local control dependences
+ foreach (var Impl in prog.NonInlinedImplementations()) {
+ Graph<Block> blockGraph = prog.ProcessLoops(Impl);
+ LocalCtrlDeps[Impl] = blockGraph.ControlDependence();
+ foreach (var KeyValue in LocalCtrlDeps[Impl]) {
+ GlobalCtrlDep.Add(KeyValue.Key, KeyValue.Value);
+ }
+ }
+
+ Graph<Implementation> callGraph = Program.BuildCallGraph(prog);
+
+ // Add inter-procedural control dependence nodes based on calls
+ foreach (var Impl in prog.NonInlinedImplementations()) {
+ foreach (var b in Impl.Blocks) {
+ foreach (var cmd in b.Cmds.OfType<CallCmd>()) {
+ var DirectCallee = GetImplementation(cmd.callee);
+ if (DirectCallee != null) {
+ HashSet<Implementation> IndirectCallees = ComputeIndirectCallees(callGraph, DirectCallee);
+ foreach (var control in GetControllingBlocks(b, LocalCtrlDeps[Impl])) {
+ foreach (var c in IndirectCallees.Select(Item => Item.Blocks).SelectMany(Item => Item)) {
+ GlobalCtrlDep[control].Add(c);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Compute transitive closure
+ GlobalCtrlDep.TransitiveClosure();
+
+ // Finally reverse the dependences
+
+ Dictionary<Block, HashSet<Block>> result = new Dictionary<Block, HashSet<Block>>();
+
+ foreach (var KeyValue in GlobalCtrlDep) {
+ foreach (var v in KeyValue.Value) {
+ if (!result.ContainsKey(v)) {
+ result[v] = new HashSet<Block>();
+ }
+ result[v].Add(KeyValue.Key);
+ }
+ }
+
+ return result;
+ }
+
+ private HashSet<Implementation> ComputeIndirectCallees(Graph<Implementation> callGraph, Implementation DirectCallee) {
+ return ComputeIndirectCallees(callGraph, DirectCallee, new HashSet<Implementation>());
+ }
+
+ private HashSet<Implementation> ComputeIndirectCallees(Graph<Implementation> callGraph, Implementation DirectCallee, HashSet<Implementation> seen) {
+ if (seen.Contains(DirectCallee)) {
+ return new HashSet<Implementation>();
+ }
+ HashSet<Implementation> result = new HashSet<Implementation>();
+ result.Add(DirectCallee);
+ seen.Add(DirectCallee);
+ foreach (var succ in callGraph.Successors(DirectCallee)) {
+ result.UnionWith(ComputeIndirectCallees(callGraph, succ, seen));
+ }
+ return result;
+ }
+
+ private HashSet<Block> GetControllingBlocks(Block b, Dictionary<Block, HashSet<Block>> ctrlDep) {
+ HashSet<Block> result = new HashSet<Block>();
+ foreach (var KeyValue in ctrlDep) {
+ if (KeyValue.Value.Contains(b)) {
+ result.Add(KeyValue.Key);
+ }
+ }
+ return result;
+ }
+
+ private Implementation GetImplementation(string proc) {
+ foreach (var Impl in prog.Implementations) {
+ if (Impl.Name.Equals(proc)) {
+ return Impl;
+ }
+ }
+ return null;
+ }
+
+ public VariableDescriptor MakeDescriptor(string proc, Variable v) {
+
+ // Check whether there is an (Impl, v) match
+ var MatchingLocals = dependsOnNonTransitive.Nodes.Where(Item => Item is LocalDescriptor).Select(
+ Item => (LocalDescriptor)Item).Where(Item => Item.Proc.Equals(proc) &&
+ Item.Name.Equals(v.Name));
+ if (MatchingLocals.Count() > 0) {
+ Debug.Assert(MatchingLocals.Count() == 1);
+ return MatchingLocals.ToArray()[0];
+ }
+
+ // It must be a global with same name as v
+ return dependsOnNonTransitive.Nodes.Where(Item => Item is GlobalDescriptor &&
+ Item.Name.Equals(v.Name)).ToArray()[0];
+ }
+
+ private Dictionary<SCC<VariableDescriptor>, HashSet<VariableDescriptor>> DependsOnCache = new Dictionary<SCC<VariableDescriptor>, HashSet<VariableDescriptor>>();
+
+ private Graph<SCC<VariableDescriptor>> DependsOnSCCsDAG;
+ private Dictionary<VariableDescriptor, SCC<VariableDescriptor>> VariableDescriptorToSCC;
+
+ public HashSet<VariableDescriptor> DependsOn(VariableDescriptor v) {
+ if (DependsOnSCCsDAG == null) {
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Variable dependence: computing SCCs");
+ }
+ Adjacency<VariableDescriptor> next = new Adjacency<VariableDescriptor>(dependsOnNonTransitive.Successors);
+ Adjacency<VariableDescriptor> prev = new Adjacency<VariableDescriptor>(dependsOnNonTransitive.Predecessors);
+ StronglyConnectedComponents<VariableDescriptor> DependsOnSCCs = new StronglyConnectedComponents<VariableDescriptor>(
+ dependsOnNonTransitive.Nodes, next, prev);
+ DependsOnSCCs.Compute();
+
+ VariableDescriptorToSCC = new Dictionary<VariableDescriptor, SCC<VariableDescriptor>>();
+ foreach (var scc in DependsOnSCCs) {
+ foreach (var s in scc) {
+ VariableDescriptorToSCC[s] = scc;
+ }
+ }
+
+ DependsOnSCCsDAG = new Graph<SCC<VariableDescriptor>>();
+ foreach (var edge in dependsOnNonTransitive.Edges) {
+ if (VariableDescriptorToSCC[edge.Item1] != VariableDescriptorToSCC[edge.Item2]) {
+ DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[edge.Item1], VariableDescriptorToSCC[edge.Item2]);
+ }
+ }
+
+ SCC<VariableDescriptor> dummy = new SCC<VariableDescriptor>();
+ foreach (var n in dependsOnNonTransitive.Nodes) {
+ DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[n], dummy);
+ }
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Variable dependence: SCCs computed!");
+ }
+ }
+ return DependsOn(VariableDescriptorToSCC[v]);
+ }
+
+ public HashSet<VariableDescriptor> DependsOn(SCC<VariableDescriptor> vSCC) {
+
+ if (!DependsOnCache.ContainsKey(vSCC)) {
+ HashSet<VariableDescriptor> result = new HashSet<VariableDescriptor>();
+ if (vSCC.Count() > 0) {
+ result.UnionWith(vSCC);
+ foreach (var wSCC in DependsOnSCCsDAG.Successors(vSCC)) {
+ result.UnionWith(DependsOn(wSCC));
+ }
+ }
+ DependsOnCache[vSCC] = result;
+ }
+ return DependsOnCache[vSCC];
+ }
+
+ public void dump() {
+
+ Console.WriteLine("Variable dependence information");
+ Console.WriteLine("===============================");
+
+ Console.WriteLine("Global variables");
+ Console.WriteLine("================");
+
+ foreach (var GlobalEntry in dependsOnNonTransitive.Nodes.Where(Item => Item is GlobalDescriptor)) {
+ dump(GlobalEntry);
+ }
+
+ foreach (var proc in Procedures()) {
+ Console.WriteLine("Variables of " + proc);
+ Console.WriteLine("=====================");
+ foreach (var LocalEntry in dependsOnNonTransitive.Nodes.Where(Item => Item is LocalDescriptor
+ && ((LocalDescriptor)Item).Proc.Equals(proc))) {
+ dump(LocalEntry);
+ }
+ }
+ }
+
+ private void dump(VariableDescriptor vd) {
+ Console.Write(vd + " <- {");
+ bool first = true;
+
+ var SortedDependents = DependsOn(vd).ToList();
+ SortedDependents.Sort();
+ foreach (var Descriptor in SortedDependents) {
+ Console.Write((first ? "" : ",") + "\n " + Descriptor);
+ if (first) {
+ first = false;
+ }
+ }
+ Debug.Assert(!first);
+ Console.WriteLine("\n}\n");
+ }
+
+ private HashSet<string> Procedures() {
+ return new HashSet<string>(dependsOnNonTransitive.Nodes.Where(Item =>
+ Item is LocalDescriptor).Select(Item => ((LocalDescriptor)Item).Proc));
+ }
+
+ }
+
+ public static class Helper {
+
+ public static IEnumerable<Procedure> NonInlinedProcedures(this Program prog) {
+ return prog.Procedures.
+ Where(Item => QKeyValue.FindIntAttribute(Item.Attributes, "inline", -1) == -1);
+ }
+
+ public static IEnumerable<Implementation> NonInlinedImplementations(this Program prog) {
+ return prog.Implementations.
+ Where(Item => QKeyValue.FindIntAttribute(Item.Proc.Attributes, "inline", -1) == -1);
+ }
+
+ }
+
+}
diff --git a/Source/Core/Xml.cs b/Source/Core/Xml.cs
index dcc19b34..58a2c5b0 100644
--- a/Source/Core/Xml.cs
+++ b/Source/Core/Xml.cs
@@ -1,316 +1,316 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Xml;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-namespace Microsoft.Boogie {
-
- public class XmlSink {
- string/*!*/ filename;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(filename != null);
- }
-
- [Rep]
- XmlWriter wr;
- public bool IsOpen {
- get {
- return wr != null;
- }
- }
-
- public XmlSink(string filename) {
- Contract.Requires(filename != null);
- this.filename = filename;
- }
-
- /// <summary>
- /// Returns null on success, in which case the caller should eventually invoke Close.
- /// Returns an error string on failure.
- /// </summary>
- public string Open() {
- //modifies this.*;
- Contract.Ensures(IsOpen);
- if (wr != null) {
- Close();
- }
- cce.BeginExpose(this);
- {
- XmlWriterSettings settings = new XmlWriterSettings();
- settings.Indent = true;
- wr = XmlWriter.Create(filename, settings);
- wr.WriteStartDocument();
- wr.WriteStartElement("boogie");
- wr.WriteAttributeString("version", CommandLineOptions.Clo.VersionNumber);
- wr.WriteAttributeString("commandLine", Environment.CommandLine);
- }
- cce.EndExpose();
- return null; // success
- }
-
- public void Close() {
- //modifies this.*;
- if (wr != null) {
- cce.BeginExpose(this);
- {
- wr.WriteEndDocument();
- wr.Close();
- wr = null;
- }
- cce.EndExpose();
- }
- }
-
- const string DateTimeFormatString = "u";
-
- public void WriteStartMethod(string methodName, DateTime startTime) {
- Contract.Requires(methodName != null);
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("method");
- wr.WriteAttributeString("name", methodName);
- wr.WriteAttributeString("startTime", startTime.ToString(DateTimeFormatString));
- }
- cce.EndExpose();
- }
-
- public void WriteEndMethod(string outcome, DateTime endTime, TimeSpan elapsed) {
- Contract.Requires(outcome != null);
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("conclusion");
- wr.WriteAttributeString("endTime", endTime.ToString(DateTimeFormatString));
- wr.WriteAttributeString("duration", elapsed.TotalSeconds.ToString());
- wr.WriteAttributeString("outcome", outcome);
-
- wr.WriteEndElement(); // outcome
- wr.WriteEndElement(); // method
- }
- cce.EndExpose();
- }
-
- public void WriteError(string message, IToken errorToken, IToken relatedToken, List<Block> trace) {
- Contract.Requires(errorToken != null);
- Contract.Requires(message != null);
- Contract.Requires(IsOpen && (trace == null || cce.Owner.Different(this, trace)));
- //modifies this.*, errorToken.*, relatedToken.*, trace.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("error");
- wr.WriteAttributeString("message", message);
- WriteTokenAttributes(errorToken);
- if (relatedToken != null) {
- wr.WriteStartElement("related");
- WriteTokenAttributes(relatedToken);
- wr.WriteEndElement();
- }
- if (trace != null) {
- wr.WriteStartElement("trace");
- {
- foreach (object bo in trace) {
- cce.LoopInvariant(wr != null);
- Contract.Assume(bo is Block);
- Block b = (Block)bo;
- wr.WriteStartElement("traceNode");
- {
- WriteTokenAttributes(b.tok);
- wr.WriteAttributeString("label", b.Label);
- }
- wr.WriteEndElement();
- }
- wr.WriteEndElement();
- }
- }
- wr.WriteEndElement();
- }
- cce.EndExpose();
- }
-
-#if CCI
- public void WriteError(string message, Cci.Node offendingNode, List<Block> trace) {
- Contract.Requires(offendingNode != null);
- Contract.Requires(message != null);
- Contract.Requires(IsOpen && cce.Owner.Different(this, offendingNode));
- Contract.Requires(trace == null || cce.Owner.Different(this, trace));
- //modifies this.*, offendingNode.*, trace.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("error");
- wr.WriteAttributeString("message", message);
- WriteTokenAttributes(offendingNode);
- if (trace != null) {
- wr.WriteStartElement("trace");
- {
- foreach (object bo in trace) {
- cce.LoopInvariant(wr != null);
- Contract.Assume(bo is Block);
- Block b = (Block)bo;
- wr.WriteStartElement("traceNode");
- {
- this.WriteTokenAttributes(b.tok);
- wr.WriteAttributeString("label", b.Label);
- }
- wr.WriteEndElement();
- }
- wr.WriteEndElement();
- }
- }
- wr.WriteEndElement();
- }
- cce.EndExpose();
- }
-#endif
-
- [Inside]
- private void WriteTokenAttributes(IToken tok) {
- Contract.Requires(wr != null && cce.IsPeerConsistent(wr));
- //modifies this.0, wr.*;
- if (tok != null && tok.filename != null) {
- wr.WriteAttributeString("file", tok.filename);
- wr.WriteAttributeString("line", tok.line.ToString());
- wr.WriteAttributeString("column", tok.col.ToString());
- }
- }
-
-#if CCI
- [Inside]
- private void WriteTokenAttributes(Cci.Node node) {
- Contract.Requires(node != null);
- Contract.Requires(wr != null && cce.IsPeerConsistent(wr));
- //modifies this.0, wr.*;
- Contract.Assert(wr != null);
- if (node.SourceContext.Document != null) {
- wr.WriteAttributeString("file", node.SourceContext.Document.Name);
- wr.WriteAttributeString("line", node.SourceContext.StartLine.ToString());
- wr.WriteAttributeString("column", node.SourceContext.StartColumn.ToString());
- }
- }
-#endif
-
- public void WriteStartInference(string inferenceName) {
- Contract.Requires(inferenceName != null);
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("inference");
- wr.WriteAttributeString("name", inferenceName);
- }
- cce.EndExpose();
- }
-
- public void WriteEndInference() {
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteEndElement(); // inference
- }
- cce.EndExpose();
- }
-
- public void WriteContractParaAssignment(string varName, string val) {
- Contract.Requires(varName != null);
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("assignment");
- wr.WriteAttributeString("name", varName);
- wr.WriteAttributeString("value", val);
- wr.WriteEndElement();
- }
- cce.EndExpose();
- }
-
- public void WriteStartFile(string filename) {
- Contract.Requires(filename != null);
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("file");
- wr.WriteAttributeString("name", filename);
- }
- cce.EndExpose();
- }
-
- public void WriteEndFile() {
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteEndElement();
- }
- cce.EndExpose();
- }
-
- public void WriteFileFragment(string fragment) {
- Contract.Requires(fragment != null);
- Contract.Requires(IsOpen);
- //modifies this.*;
- Contract.Ensures(IsOpen);
- Contract.Assert(wr != null);
- cce.BeginExpose(this);
- {
- wr.WriteStartElement("fileFragment");
- wr.WriteAttributeString("name", fragment);
- wr.WriteEndElement();
- }
- cce.EndExpose();
- }
- }
-
- public class XmlFileScope : IDisposable {
- [Peer]
- [SpecPublic]
- XmlSink sink;
-
- [Captured]
- public XmlFileScope(XmlSink sink, string filename) {
- Contract.Requires(filename != null);
- Contract.Requires(sink == null || sink.IsOpen);
- //modifies sink.*;
- if (sink != null) {
- sink.WriteStartFile(filename); // invoke this method while "sink" is still peer consistent
- cce.Owner.AssignSame(this, sink);
- this.sink = sink;
- }
- }
-
- public void Dispose() {
- if (sink != null) {
- Contract.Assume(sink.IsOpen);
- sink.WriteEndFile();
- }
- }
- }
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Xml;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+namespace Microsoft.Boogie {
+
+ public class XmlSink {
+ string/*!*/ filename;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(filename != null);
+ }
+
+ [Rep]
+ XmlWriter wr;
+ public bool IsOpen {
+ get {
+ return wr != null;
+ }
+ }
+
+ public XmlSink(string filename) {
+ Contract.Requires(filename != null);
+ this.filename = filename;
+ }
+
+ /// <summary>
+ /// Returns null on success, in which case the caller should eventually invoke Close.
+ /// Returns an error string on failure.
+ /// </summary>
+ public string Open() {
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ if (wr != null) {
+ Close();
+ }
+ cce.BeginExpose(this);
+ {
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Indent = true;
+ wr = XmlWriter.Create(filename, settings);
+ wr.WriteStartDocument();
+ wr.WriteStartElement("boogie");
+ wr.WriteAttributeString("version", CommandLineOptions.Clo.VersionNumber);
+ wr.WriteAttributeString("commandLine", Environment.CommandLine);
+ }
+ cce.EndExpose();
+ return null; // success
+ }
+
+ public void Close() {
+ //modifies this.*;
+ if (wr != null) {
+ cce.BeginExpose(this);
+ {
+ wr.WriteEndDocument();
+ wr.Close();
+ wr = null;
+ }
+ cce.EndExpose();
+ }
+ }
+
+ const string DateTimeFormatString = "u";
+
+ public void WriteStartMethod(string methodName, DateTime startTime) {
+ Contract.Requires(methodName != null);
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("method");
+ wr.WriteAttributeString("name", methodName);
+ wr.WriteAttributeString("startTime", startTime.ToString(DateTimeFormatString));
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteEndMethod(string outcome, DateTime endTime, TimeSpan elapsed) {
+ Contract.Requires(outcome != null);
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("conclusion");
+ wr.WriteAttributeString("endTime", endTime.ToString(DateTimeFormatString));
+ wr.WriteAttributeString("duration", elapsed.TotalSeconds.ToString());
+ wr.WriteAttributeString("outcome", outcome);
+
+ wr.WriteEndElement(); // outcome
+ wr.WriteEndElement(); // method
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteError(string message, IToken errorToken, IToken relatedToken, List<Block> trace) {
+ Contract.Requires(errorToken != null);
+ Contract.Requires(message != null);
+ Contract.Requires(IsOpen && (trace == null || cce.Owner.Different(this, trace)));
+ //modifies this.*, errorToken.*, relatedToken.*, trace.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("error");
+ wr.WriteAttributeString("message", message);
+ WriteTokenAttributes(errorToken);
+ if (relatedToken != null) {
+ wr.WriteStartElement("related");
+ WriteTokenAttributes(relatedToken);
+ wr.WriteEndElement();
+ }
+ if (trace != null) {
+ wr.WriteStartElement("trace");
+ {
+ foreach (object bo in trace) {
+ cce.LoopInvariant(wr != null);
+ Contract.Assume(bo is Block);
+ Block b = (Block)bo;
+ wr.WriteStartElement("traceNode");
+ {
+ WriteTokenAttributes(b.tok);
+ wr.WriteAttributeString("label", b.Label);
+ }
+ wr.WriteEndElement();
+ }
+ wr.WriteEndElement();
+ }
+ }
+ wr.WriteEndElement();
+ }
+ cce.EndExpose();
+ }
+
+#if CCI
+ public void WriteError(string message, Cci.Node offendingNode, List<Block> trace) {
+ Contract.Requires(offendingNode != null);
+ Contract.Requires(message != null);
+ Contract.Requires(IsOpen && cce.Owner.Different(this, offendingNode));
+ Contract.Requires(trace == null || cce.Owner.Different(this, trace));
+ //modifies this.*, offendingNode.*, trace.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("error");
+ wr.WriteAttributeString("message", message);
+ WriteTokenAttributes(offendingNode);
+ if (trace != null) {
+ wr.WriteStartElement("trace");
+ {
+ foreach (object bo in trace) {
+ cce.LoopInvariant(wr != null);
+ Contract.Assume(bo is Block);
+ Block b = (Block)bo;
+ wr.WriteStartElement("traceNode");
+ {
+ this.WriteTokenAttributes(b.tok);
+ wr.WriteAttributeString("label", b.Label);
+ }
+ wr.WriteEndElement();
+ }
+ wr.WriteEndElement();
+ }
+ }
+ wr.WriteEndElement();
+ }
+ cce.EndExpose();
+ }
+#endif
+
+ [Inside]
+ private void WriteTokenAttributes(IToken tok) {
+ Contract.Requires(wr != null && cce.IsPeerConsistent(wr));
+ //modifies this.0, wr.*;
+ if (tok != null && tok.filename != null) {
+ wr.WriteAttributeString("file", tok.filename);
+ wr.WriteAttributeString("line", tok.line.ToString());
+ wr.WriteAttributeString("column", tok.col.ToString());
+ }
+ }
+
+#if CCI
+ [Inside]
+ private void WriteTokenAttributes(Cci.Node node) {
+ Contract.Requires(node != null);
+ Contract.Requires(wr != null && cce.IsPeerConsistent(wr));
+ //modifies this.0, wr.*;
+ Contract.Assert(wr != null);
+ if (node.SourceContext.Document != null) {
+ wr.WriteAttributeString("file", node.SourceContext.Document.Name);
+ wr.WriteAttributeString("line", node.SourceContext.StartLine.ToString());
+ wr.WriteAttributeString("column", node.SourceContext.StartColumn.ToString());
+ }
+ }
+#endif
+
+ public void WriteStartInference(string inferenceName) {
+ Contract.Requires(inferenceName != null);
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("inference");
+ wr.WriteAttributeString("name", inferenceName);
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteEndInference() {
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteEndElement(); // inference
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteContractParaAssignment(string varName, string val) {
+ Contract.Requires(varName != null);
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("assignment");
+ wr.WriteAttributeString("name", varName);
+ wr.WriteAttributeString("value", val);
+ wr.WriteEndElement();
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteStartFile(string filename) {
+ Contract.Requires(filename != null);
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("file");
+ wr.WriteAttributeString("name", filename);
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteEndFile() {
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteEndElement();
+ }
+ cce.EndExpose();
+ }
+
+ public void WriteFileFragment(string fragment) {
+ Contract.Requires(fragment != null);
+ Contract.Requires(IsOpen);
+ //modifies this.*;
+ Contract.Ensures(IsOpen);
+ Contract.Assert(wr != null);
+ cce.BeginExpose(this);
+ {
+ wr.WriteStartElement("fileFragment");
+ wr.WriteAttributeString("name", fragment);
+ wr.WriteEndElement();
+ }
+ cce.EndExpose();
+ }
+ }
+
+ public class XmlFileScope : IDisposable {
+ [Peer]
+ [SpecPublic]
+ XmlSink sink;
+
+ [Captured]
+ public XmlFileScope(XmlSink sink, string filename) {
+ Contract.Requires(filename != null);
+ Contract.Requires(sink == null || sink.IsOpen);
+ //modifies sink.*;
+ if (sink != null) {
+ sink.WriteStartFile(filename); // invoke this method while "sink" is still peer consistent
+ cce.Owner.AssignSame(this, sink);
+ this.sink = sink;
+ }
+ }
+
+ public void Dispose() {
+ if (sink != null) {
+ Contract.Assume(sink.IsOpen);
+ sink.WriteEndFile();
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Core/cce.cs b/Source/Core/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/Core/cce.cs
+++ b/Source/Core/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/Doomed/DoomCheck.cs b/Source/Doomed/DoomCheck.cs
index 83de03ff..c1d6736f 100644
--- a/Source/Doomed/DoomCheck.cs
+++ b/Source/Doomed/DoomCheck.cs
@@ -1,407 +1,407 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC
-{
- internal class Evc {
-
- public DoomErrorHandler ErrorHandler {
- set {
- m_ErrorHandler = value;
- }
- }
-
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(m_Checker!=null);
-}
-
- private Checker m_Checker;
- private DoomErrorHandler m_ErrorHandler;
-
- [NotDelayed]
- public Evc(Checker check) {
- Contract.Requires(check != null);
- m_Checker = check;
-
- }
-
- public void Initialize(VCExpr evc) {
- Contract.Requires(evc != null);
- m_Checker.PushVCExpr(evc);
- }
-
-
- public bool CheckReachvar(List<Variable> lv,Dictionary<Expr, int> finalreachvars,
- int k, int l, bool usenew , out ProverInterface.Outcome outcome) {
- Contract.Requires(lv != null);
-
- VCExpr vc = VCExpressionGenerator.False;
- if (usenew )
- {
- foreach (Variable v in lv)
- {
-
- vc = m_Checker.VCExprGen.Or(
- m_Checker.VCExprGen.Neq(
- m_Checker.VCExprGen.Integer(BigNum.ZERO),
- m_Checker.TheoremProver.Context.BoogieExprTranslator.LookupVariable(v)),
- vc);
- }
- //Console.WriteLine("TPQuery k={0}, l={1}, |Sp|={2}", k, l, finalreachvars.Count);
-
- VCExpr vc21 = m_Checker.VCExprGen.Integer(BigNum.ZERO); // Ask: is the necessary or can we use the same instance term in two inequalities?
- VCExpr vc22 = m_Checker.VCExprGen.Integer(BigNum.ZERO);
-
- foreach (KeyValuePair<Expr, int> kvp in finalreachvars)
- {
-
- vc21 = m_Checker.VCExprGen.Add(vc21, m_Checker.TheoremProver.Context.BoogieExprTranslator.Translate(kvp.Key));
- vc22 = m_Checker.VCExprGen.Add(vc22, m_Checker.TheoremProver.Context.BoogieExprTranslator.Translate(kvp.Key));
- }
-
- VCExpr post = m_Checker.VCExprGen.Gt(m_Checker.VCExprGen.Integer(BigNum.FromInt(l)), vc21);
-
- if (k != -1)
- {
- post = m_Checker.VCExprGen.Or(
- post, m_Checker.VCExprGen.Gt(vc22, m_Checker.VCExprGen.Integer(BigNum.FromInt(k)))
- );
- }
- vc = (m_Checker.VCExprGen.Or(vc, (post) ));
-
- }
- else
- {
-
- foreach (Variable v in lv)
- {
-
- vc = m_Checker.VCExprGen.Or(
- m_Checker.VCExprGen.Eq(
- m_Checker.VCExprGen.Integer(BigNum.ONE),
- m_Checker.TheoremProver.Context.BoogieExprTranslator.LookupVariable(v)),
- vc);
- }
- Contract.Assert(vc != null);
-
- // Add the desired outcome of the reachability variables
- foreach (KeyValuePair<Expr, int> kvp in finalreachvars)
- {
- vc = m_Checker.VCExprGen.Or(
- m_Checker.VCExprGen.Neq(
- m_Checker.VCExprGen.Integer(BigNum.FromInt(kvp.Value)),
- m_Checker.TheoremProver.Context.BoogieExprTranslator.Translate(kvp.Key)),
- vc);
- }
-
- }
-
- // Todo: Check if vc is trivial true or false
- outcome = ProverInterface.Outcome.Undetermined;
- Contract.Assert(m_ErrorHandler != null);
- try
- {
- m_Checker.BeginCheck(lv[0].Name, vc, m_ErrorHandler);
- m_Checker.ProverTask.Wait();
- outcome = m_Checker.ReadOutcome();
- }
- catch (UnexpectedProverOutputException e)
- {
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("Prover is unable to check {0}! Reason:", lv[0].Name);
- Console.WriteLine(e.ToString());
- }
- return false;
- }
- finally
- {
- m_Checker.GoBackToIdle();
- }
- return true;
- }
- }
-
- internal class DoomCheck {
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Label2Absy!=null);
- Contract.Invariant(m_Check != null);
- Contract.Invariant(m_Evc != null);
- Contract.Invariant(m_Order != null);
- }
-
- #region Attributes
- public Dictionary<int, Absy> Label2Absy;
- public DoomErrorHandler ErrorHandler {
- set {
- m_ErrHandler = value;
- m_Evc.ErrorHandler = value;
- }
-
- get {
- return m_ErrHandler;
- }
- }
-
- private DoomErrorHandler m_ErrHandler;
- private Checker m_Check;
- private DoomDetectionStrategy m_Order;
- private Evc m_Evc;
- #endregion
-
- public void __DEBUG_PrintStatistics()
- {
- Console.WriteLine("Checked/Total: Bl {0} / {1} EQ {2} / {3} {4} Tr {5} {6} / {7}", m_Order.__DEBUG_BlocksChecked, m_Order.__DEBUG_BlocksTotal, m_Order.__DEBUG_EQCChecked, m_Order.__DEBUG_EQCTotal, m_Order.__DEBUG_EQCLeaf, m_Order.__DEBUG_TracesChecked, m_Order.__DEBUG_InfeasibleTraces, m_Order.__DEBUG_TracesTotal);
- }
-
- [NotDelayed]
- public DoomCheck (Implementation passive_impl, Block unifiedExit, Checker check, List<Block> uncheckable, out int assertionCount) {
- Contract.Requires(passive_impl != null);
- Contract.Requires(check != null);
- Contract.Requires(uncheckable != null);
- m_Check = check;
-
- int replaceThisByCmdLineOption = CommandLineOptions.Clo.DoomStrategy ;
- if (CommandLineOptions.Clo.DoomStrategy!=-1) Console.Write("Running experiments using {0} /", replaceThisByCmdLineOption);
- switch (replaceThisByCmdLineOption)
- {
- default:
- {
- if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("Path Cover specialK Strategy");
- m_Order = new PathCoverStrategyK(passive_impl, unifiedExit, uncheckable);
- break;
- }
- case 1:
- {
- if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("Path Cover L Strategy");
- m_Order = new PathCoverStrategy(passive_impl, unifiedExit, uncheckable);
- break;
- }
- case 2:
- {
- if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("hasse strategy");
- m_Order = new HierachyStrategy(passive_impl, unifiedExit, uncheckable);
-
- break;
- }
- case 3:
- {
- if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("hasse+ce strategy");
- m_Order = new HierachyCEStrategy(passive_impl, unifiedExit, uncheckable);
- break;
- }
- case 4:
- {
- if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("no strategy");
- m_Order = new NoStrategy(passive_impl, unifiedExit, uncheckable);
- break;
- }
-
- }
-
- Label2Absy = new Dictionary<int, Absy>(); // This is only a dummy
- m_Evc = new Evc(check);
- Dictionary<int, Absy> l2a = null;
- VCExpr vce = this.GenerateEVC(passive_impl, out l2a, check, out assertionCount);
- Contract.Assert(vce != null);
- Contract.Assert( l2a!=null);
- Label2Absy = l2a;
-
- m_Evc.Initialize(vce);
- }
-
-
- public void RespawnChecker(Implementation passive_impl, Checker check)
- {
- Contract.Requires(check != null);
- m_Check = check;
- Label2Absy = new Dictionary<int, Absy>(); // This is only a dummy
- m_Evc = new Evc(check);
- Dictionary<int, Absy> l2a = null;
- int assertionCount; // compute and then ignore
- VCExpr vce = this.GenerateEVC(passive_impl, out l2a, check, out assertionCount);
- Contract.Assert(vce != null);
- Contract.Assert(l2a != null);
- Label2Absy = l2a;
-
- m_Evc.Initialize(vce);
- }
-
- /* - Set b to the next block that needs to be checked.
- - Returns false and set b to null if all blocks are checked.
- - Has to be alternated with CheckLabel; might crash otherwise
- */
- public bool GetNextBlock(out List<Block> lb)
- {
- return m_Order.GetNextBlock(out lb);
- }
-
- public Stopwatch DEBUG_ProverTime = new Stopwatch();
-
- /* - Checking a label means to ask the prover if |= ( rvar=false -> vc ) holds.
- - outcome is set to Outcome.Invalid if the Block denoted by reachvar is doomed.
- - returns false if the theorem prover throws an exception, otherwise true.
- */
- public bool CheckLabel(List<Variable> lv,Dictionary<Expr, int> finalreachvars, out ProverInterface.Outcome outcome) {
- Contract.Requires(lv != null);
- outcome = ProverInterface.Outcome.Undetermined;
- DEBUG_ProverTime.Reset();
- DEBUG_ProverTime.Start();
- if (m_Evc.CheckReachvar(lv,finalreachvars,m_Order.MaxBlocks,m_Order.MinBlocks,m_Order.HACK_NewCheck, out outcome) ) {
- DEBUG_ProverTime.Stop();
- if (!m_Order.SetCurrentResult(lv, outcome, m_ErrHandler)) {
- outcome = ProverInterface.Outcome.Undetermined;
- }
- return true;
- } else {
- DEBUG_ProverTime.Stop();
- Console.WriteLine(outcome);
- m_Order.SetCurrentResult(lv, ProverInterface.Outcome.Undetermined, m_ErrHandler);
- return false;
- }
- }
-
- public List<List<Block/*!>!>!*/>> DoomedSequences {
- get {
- Contract.Ensures(Contract.ForAll(Contract.Result<List<List<Block>>>(), i=> cce.NonNullElements(i)));
-
- return m_Order.DetectedBlock;
- }
- }
-
-
- #region Error Verification Condition Generation
- /*
- #region _TESTING_NEW_STUFF_
- CommandLineOptions.Clo.vcVariety = CommandLineOptions.VCVariety.Block;
- //VCExpr wp = Wlp.Block(block, SuccCorrect, context); // Computes wp.S.true
-
- CommandLineOptions.Clo.vcVariety = CommandLineOptions.VCVariety.Doomed;
- #endregion
-
- */
-
- VCExpr GenerateEVC(Implementation impl, out Dictionary<int, Absy> label2absy, Checker ch, out int assertionCount) {
- Contract.Requires(impl != null);
- Contract.Requires(ch != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- TypecheckingContext tc = new TypecheckingContext(null);
- impl.Typecheck(tc);
- label2absy = new Dictionary<int, Absy>();
- VCExpr vc;
- switch (CommandLineOptions.Clo.vcVariety) {
- case CommandLineOptions.VCVariety.Doomed:
- vc = LetVC(cce.NonNull(impl.Blocks[0]), label2absy, ch.TheoremProver.Context, out assertionCount);
- break;
-
- default:
- Contract.Assert(false); throw new cce.UnreachableException(); // unexpected enumeration value
- }
- return vc;
- }
-
- public VCExpr LetVC(Block startBlock,
- Dictionary<int, Absy> label2absy,
- ProverContext proverCtxt,
- out int assertionCount)
- {
- Contract.Requires(startBlock != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(proverCtxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
- List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
- VCExpr startCorrect = LetVC(startBlock, label2absy, blockVariables, bindings, proverCtxt, out assertionCount);
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
- return proverCtxt.ExprGen.Let(bindings, proverCtxt.ExprGen.Not(startCorrect) );
- } else {
- return proverCtxt.ExprGen.Let(bindings, startCorrect );
- }
- }
-
- VCExpr LetVC(Block block,
- Dictionary<int, Absy> label2absy,
- Hashtable/*<Block, VCExprVar!>*/ blockVariables,
- List<VCExprLetBinding> bindings,
- ProverContext proverCtxt,
- out int assertionCount)
- {
- Contract.Requires(label2absy != null);
- Contract.Requires(blockVariables != null);
- Contract.Requires(proverCtxt != null);
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- assertionCount = 0;
- VCExpressionGenerator gen = proverCtxt.ExprGen;
- Contract.Assert(gen != null);
- VCExprVar v = (VCExprVar)blockVariables[block];
- if (v == null) {
- /*
- * For block A (= block), generate:
- * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct))
- * with the side effect of adding the let bindings to "bindings" for any
- * successor not yet visited.
- */
- VCExpr SuccCorrect;
- GotoCmd gotocmd = block.TransferCmd as GotoCmd;
- if (gotocmd == null) {
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
- SuccCorrect = VCExpressionGenerator.False;
- } else {
- SuccCorrect = VCExpressionGenerator.True;
- }
- } else {
- Contract.Assert( gotocmd.labelTargets != null);
- List<VCExpr> SuccCorrectVars = new List<VCExpr>(gotocmd.labelTargets.Count);
- foreach (Block successor in gotocmd.labelTargets) {
- Contract.Assert(successor != null);
- int ac;
- VCExpr s = LetVC(successor, label2absy, blockVariables, bindings, proverCtxt, out ac);
- assertionCount += ac;
- SuccCorrectVars.Add(s);
- }
- SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
- }
-
- VCContext context = new VCContext(label2absy, proverCtxt);
- // m_Context = context;
-
- VCExpr vc = Wlp.Block(block, SuccCorrect, context);
- assertionCount += context.AssertionCount;
- v = gen.Variable(block.Label + "_correct", Microsoft.Boogie.Type.Bool);
-
- bindings.Add(gen.LetBinding(v, vc));
- blockVariables.Add(block, v);
- }
- return v;
- }
-
-
- #endregion
-
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC
+{
+ internal class Evc {
+
+ public DoomErrorHandler ErrorHandler {
+ set {
+ m_ErrorHandler = value;
+ }
+ }
+
+ [ContractInvariantMethod]
+void ObjectInvariant()
+{
+ Contract.Invariant(m_Checker!=null);
+}
+
+ private Checker m_Checker;
+ private DoomErrorHandler m_ErrorHandler;
+
+ [NotDelayed]
+ public Evc(Checker check) {
+ Contract.Requires(check != null);
+ m_Checker = check;
+
+ }
+
+ public void Initialize(VCExpr evc) {
+ Contract.Requires(evc != null);
+ m_Checker.PushVCExpr(evc);
+ }
+
+
+ public bool CheckReachvar(List<Variable> lv,Dictionary<Expr, int> finalreachvars,
+ int k, int l, bool usenew , out ProverInterface.Outcome outcome) {
+ Contract.Requires(lv != null);
+
+ VCExpr vc = VCExpressionGenerator.False;
+ if (usenew )
+ {
+ foreach (Variable v in lv)
+ {
+
+ vc = m_Checker.VCExprGen.Or(
+ m_Checker.VCExprGen.Neq(
+ m_Checker.VCExprGen.Integer(BigNum.ZERO),
+ m_Checker.TheoremProver.Context.BoogieExprTranslator.LookupVariable(v)),
+ vc);
+ }
+ //Console.WriteLine("TPQuery k={0}, l={1}, |Sp|={2}", k, l, finalreachvars.Count);
+
+ VCExpr vc21 = m_Checker.VCExprGen.Integer(BigNum.ZERO); // Ask: is the necessary or can we use the same instance term in two inequalities?
+ VCExpr vc22 = m_Checker.VCExprGen.Integer(BigNum.ZERO);
+
+ foreach (KeyValuePair<Expr, int> kvp in finalreachvars)
+ {
+
+ vc21 = m_Checker.VCExprGen.Add(vc21, m_Checker.TheoremProver.Context.BoogieExprTranslator.Translate(kvp.Key));
+ vc22 = m_Checker.VCExprGen.Add(vc22, m_Checker.TheoremProver.Context.BoogieExprTranslator.Translate(kvp.Key));
+ }
+
+ VCExpr post = m_Checker.VCExprGen.Gt(m_Checker.VCExprGen.Integer(BigNum.FromInt(l)), vc21);
+
+ if (k != -1)
+ {
+ post = m_Checker.VCExprGen.Or(
+ post, m_Checker.VCExprGen.Gt(vc22, m_Checker.VCExprGen.Integer(BigNum.FromInt(k)))
+ );
+ }
+ vc = (m_Checker.VCExprGen.Or(vc, (post) ));
+
+ }
+ else
+ {
+
+ foreach (Variable v in lv)
+ {
+
+ vc = m_Checker.VCExprGen.Or(
+ m_Checker.VCExprGen.Eq(
+ m_Checker.VCExprGen.Integer(BigNum.ONE),
+ m_Checker.TheoremProver.Context.BoogieExprTranslator.LookupVariable(v)),
+ vc);
+ }
+ Contract.Assert(vc != null);
+
+ // Add the desired outcome of the reachability variables
+ foreach (KeyValuePair<Expr, int> kvp in finalreachvars)
+ {
+ vc = m_Checker.VCExprGen.Or(
+ m_Checker.VCExprGen.Neq(
+ m_Checker.VCExprGen.Integer(BigNum.FromInt(kvp.Value)),
+ m_Checker.TheoremProver.Context.BoogieExprTranslator.Translate(kvp.Key)),
+ vc);
+ }
+
+ }
+
+ // Todo: Check if vc is trivial true or false
+ outcome = ProverInterface.Outcome.Undetermined;
+ Contract.Assert(m_ErrorHandler != null);
+ try
+ {
+ m_Checker.BeginCheck(lv[0].Name, vc, m_ErrorHandler);
+ m_Checker.ProverTask.Wait();
+ outcome = m_Checker.ReadOutcome();
+ }
+ catch (UnexpectedProverOutputException e)
+ {
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("Prover is unable to check {0}! Reason:", lv[0].Name);
+ Console.WriteLine(e.ToString());
+ }
+ return false;
+ }
+ finally
+ {
+ m_Checker.GoBackToIdle();
+ }
+ return true;
+ }
+ }
+
+ internal class DoomCheck {
+
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(Label2Absy!=null);
+ Contract.Invariant(m_Check != null);
+ Contract.Invariant(m_Evc != null);
+ Contract.Invariant(m_Order != null);
+ }
+
+ #region Attributes
+ public Dictionary<int, Absy> Label2Absy;
+ public DoomErrorHandler ErrorHandler {
+ set {
+ m_ErrHandler = value;
+ m_Evc.ErrorHandler = value;
+ }
+
+ get {
+ return m_ErrHandler;
+ }
+ }
+
+ private DoomErrorHandler m_ErrHandler;
+ private Checker m_Check;
+ private DoomDetectionStrategy m_Order;
+ private Evc m_Evc;
+ #endregion
+
+ public void __DEBUG_PrintStatistics()
+ {
+ Console.WriteLine("Checked/Total: Bl {0} / {1} EQ {2} / {3} {4} Tr {5} {6} / {7}", m_Order.__DEBUG_BlocksChecked, m_Order.__DEBUG_BlocksTotal, m_Order.__DEBUG_EQCChecked, m_Order.__DEBUG_EQCTotal, m_Order.__DEBUG_EQCLeaf, m_Order.__DEBUG_TracesChecked, m_Order.__DEBUG_InfeasibleTraces, m_Order.__DEBUG_TracesTotal);
+ }
+
+ [NotDelayed]
+ public DoomCheck (Implementation passive_impl, Block unifiedExit, Checker check, List<Block> uncheckable, out int assertionCount) {
+ Contract.Requires(passive_impl != null);
+ Contract.Requires(check != null);
+ Contract.Requires(uncheckable != null);
+ m_Check = check;
+
+ int replaceThisByCmdLineOption = CommandLineOptions.Clo.DoomStrategy ;
+ if (CommandLineOptions.Clo.DoomStrategy!=-1) Console.Write("Running experiments using {0} /", replaceThisByCmdLineOption);
+ switch (replaceThisByCmdLineOption)
+ {
+ default:
+ {
+ if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("Path Cover specialK Strategy");
+ m_Order = new PathCoverStrategyK(passive_impl, unifiedExit, uncheckable);
+ break;
+ }
+ case 1:
+ {
+ if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("Path Cover L Strategy");
+ m_Order = new PathCoverStrategy(passive_impl, unifiedExit, uncheckable);
+ break;
+ }
+ case 2:
+ {
+ if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("hasse strategy");
+ m_Order = new HierachyStrategy(passive_impl, unifiedExit, uncheckable);
+
+ break;
+ }
+ case 3:
+ {
+ if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("hasse+ce strategy");
+ m_Order = new HierachyCEStrategy(passive_impl, unifiedExit, uncheckable);
+ break;
+ }
+ case 4:
+ {
+ if (CommandLineOptions.Clo.DoomStrategy != -1) Console.WriteLine("no strategy");
+ m_Order = new NoStrategy(passive_impl, unifiedExit, uncheckable);
+ break;
+ }
+
+ }
+
+ Label2Absy = new Dictionary<int, Absy>(); // This is only a dummy
+ m_Evc = new Evc(check);
+ Dictionary<int, Absy> l2a = null;
+ VCExpr vce = this.GenerateEVC(passive_impl, out l2a, check, out assertionCount);
+ Contract.Assert(vce != null);
+ Contract.Assert( l2a!=null);
+ Label2Absy = l2a;
+
+ m_Evc.Initialize(vce);
+ }
+
+
+ public void RespawnChecker(Implementation passive_impl, Checker check)
+ {
+ Contract.Requires(check != null);
+ m_Check = check;
+ Label2Absy = new Dictionary<int, Absy>(); // This is only a dummy
+ m_Evc = new Evc(check);
+ Dictionary<int, Absy> l2a = null;
+ int assertionCount; // compute and then ignore
+ VCExpr vce = this.GenerateEVC(passive_impl, out l2a, check, out assertionCount);
+ Contract.Assert(vce != null);
+ Contract.Assert(l2a != null);
+ Label2Absy = l2a;
+
+ m_Evc.Initialize(vce);
+ }
+
+ /* - Set b to the next block that needs to be checked.
+ - Returns false and set b to null if all blocks are checked.
+ - Has to be alternated with CheckLabel; might crash otherwise
+ */
+ public bool GetNextBlock(out List<Block> lb)
+ {
+ return m_Order.GetNextBlock(out lb);
+ }
+
+ public Stopwatch DEBUG_ProverTime = new Stopwatch();
+
+ /* - Checking a label means to ask the prover if |= ( rvar=false -> vc ) holds.
+ - outcome is set to Outcome.Invalid if the Block denoted by reachvar is doomed.
+ - returns false if the theorem prover throws an exception, otherwise true.
+ */
+ public bool CheckLabel(List<Variable> lv,Dictionary<Expr, int> finalreachvars, out ProverInterface.Outcome outcome) {
+ Contract.Requires(lv != null);
+ outcome = ProverInterface.Outcome.Undetermined;
+ DEBUG_ProverTime.Reset();
+ DEBUG_ProverTime.Start();
+ if (m_Evc.CheckReachvar(lv,finalreachvars,m_Order.MaxBlocks,m_Order.MinBlocks,m_Order.HACK_NewCheck, out outcome) ) {
+ DEBUG_ProverTime.Stop();
+ if (!m_Order.SetCurrentResult(lv, outcome, m_ErrHandler)) {
+ outcome = ProverInterface.Outcome.Undetermined;
+ }
+ return true;
+ } else {
+ DEBUG_ProverTime.Stop();
+ Console.WriteLine(outcome);
+ m_Order.SetCurrentResult(lv, ProverInterface.Outcome.Undetermined, m_ErrHandler);
+ return false;
+ }
+ }
+
+ public List<List<Block/*!>!>!*/>> DoomedSequences {
+ get {
+ Contract.Ensures(Contract.ForAll(Contract.Result<List<List<Block>>>(), i=> cce.NonNullElements(i)));
+
+ return m_Order.DetectedBlock;
+ }
+ }
+
+
+ #region Error Verification Condition Generation
+ /*
+ #region _TESTING_NEW_STUFF_
+ CommandLineOptions.Clo.vcVariety = CommandLineOptions.VCVariety.Block;
+ //VCExpr wp = Wlp.Block(block, SuccCorrect, context); // Computes wp.S.true
+
+ CommandLineOptions.Clo.vcVariety = CommandLineOptions.VCVariety.Doomed;
+ #endregion
+
+ */
+
+ VCExpr GenerateEVC(Implementation impl, out Dictionary<int, Absy> label2absy, Checker ch, out int assertionCount) {
+ Contract.Requires(impl != null);
+ Contract.Requires(ch != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ TypecheckingContext tc = new TypecheckingContext(null);
+ impl.Typecheck(tc);
+ label2absy = new Dictionary<int, Absy>();
+ VCExpr vc;
+ switch (CommandLineOptions.Clo.vcVariety) {
+ case CommandLineOptions.VCVariety.Doomed:
+ vc = LetVC(cce.NonNull(impl.Blocks[0]), label2absy, ch.TheoremProver.Context, out assertionCount);
+ break;
+
+ default:
+ Contract.Assert(false); throw new cce.UnreachableException(); // unexpected enumeration value
+ }
+ return vc;
+ }
+
+ public VCExpr LetVC(Block startBlock,
+ Dictionary<int, Absy> label2absy,
+ ProverContext proverCtxt,
+ out int assertionCount)
+ {
+ Contract.Requires(startBlock != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
+ List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
+ VCExpr startCorrect = LetVC(startBlock, label2absy, blockVariables, bindings, proverCtxt, out assertionCount);
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ return proverCtxt.ExprGen.Let(bindings, proverCtxt.ExprGen.Not(startCorrect) );
+ } else {
+ return proverCtxt.ExprGen.Let(bindings, startCorrect );
+ }
+ }
+
+ VCExpr LetVC(Block block,
+ Dictionary<int, Absy> label2absy,
+ Hashtable/*<Block, VCExprVar!>*/ blockVariables,
+ List<VCExprLetBinding> bindings,
+ ProverContext proverCtxt,
+ out int assertionCount)
+ {
+ Contract.Requires(label2absy != null);
+ Contract.Requires(blockVariables != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ assertionCount = 0;
+ VCExpressionGenerator gen = proverCtxt.ExprGen;
+ Contract.Assert(gen != null);
+ VCExprVar v = (VCExprVar)blockVariables[block];
+ if (v == null) {
+ /*
+ * For block A (= block), generate:
+ * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct))
+ * with the side effect of adding the let bindings to "bindings" for any
+ * successor not yet visited.
+ */
+ VCExpr SuccCorrect;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd == null) {
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ SuccCorrect = VCExpressionGenerator.False;
+ } else {
+ SuccCorrect = VCExpressionGenerator.True;
+ }
+ } else {
+ Contract.Assert( gotocmd.labelTargets != null);
+ List<VCExpr> SuccCorrectVars = new List<VCExpr>(gotocmd.labelTargets.Count);
+ foreach (Block successor in gotocmd.labelTargets) {
+ Contract.Assert(successor != null);
+ int ac;
+ VCExpr s = LetVC(successor, label2absy, blockVariables, bindings, proverCtxt, out ac);
+ assertionCount += ac;
+ SuccCorrectVars.Add(s);
+ }
+ SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt);
+ // m_Context = context;
+
+ VCExpr vc = Wlp.Block(block, SuccCorrect, context);
+ assertionCount += context.AssertionCount;
+ v = gen.Variable(block.Label + "_correct", Microsoft.Boogie.Type.Bool);
+
+ bindings.Add(gen.LetBinding(v, vc));
+ blockVariables.Add(block, v);
+ }
+ return v;
+ }
+
+
+ #endregion
+
+ }
+
+}
diff --git a/Source/Doomed/DoomErrorHandler.cs b/Source/Doomed/DoomErrorHandler.cs
index 8d89bae3..ce14ff73 100644
--- a/Source/Doomed/DoomErrorHandler.cs
+++ b/Source/Doomed/DoomErrorHandler.cs
@@ -1,86 +1,86 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC
-{
- internal class DoomErrorHandler : ProverInterface.ErrorHandler
- {
-
- protected Dictionary<int, Absy> label2Absy;
- protected VerifierCallback callback;
- private List<Block> m_CurrentTrace = new List<Block>();
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(label2Absy != null);
- Contract.Invariant(callback != null);
- Contract.Invariant(cce.NonNullElements(m_CurrentTrace));
- }
-
-
- public DoomErrorHandler(Dictionary<int, Absy> label2Absy, VerifierCallback callback)
- {
- Contract.Requires(label2Absy != null);
- Contract.Requires(callback != null);
- this.label2Absy = label2Absy;
- this.callback = callback;
- }
-
- public override Absy Label2Absy(string label)
- {
- //Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- int id = int.Parse(label);
- return cce.NonNull((Absy)label2Absy[id]);
- }
-
- public override void OnProverWarning(string msg)
- {
- //Contract.Requires(msg != null);
- this.callback.OnWarning(msg);
- }
-
-
- public List<Block>/*!>!*/ TraceNodes
- {
- get
- {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
-
- return m_CurrentTrace;
- }
- }
-
- public override void OnModel(IList<string>/*!>!*/ labels, Model model, ProverInterface.Outcome proverOutcome)
- {
- // TODO: it would be better to check which reachability variables are actually set to one!
- List<Block> traceNodes = new List<Block>();
- List<AssertCmd> assertNodes = new List<AssertCmd>();
- foreach (string s in labels)
- {
- Contract.Assert(s != null);
- Absy node = Label2Absy(s);
- if (node is Block)
- {
- Block b = (Block)node;
- traceNodes.Add(b);
- //Console.Write("{0}, ", b.Label);
- }
- }
- m_CurrentTrace.AddRange(traceNodes);
- }
-
- }
-
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC
+{
+ internal class DoomErrorHandler : ProverInterface.ErrorHandler
+ {
+
+ protected Dictionary<int, Absy> label2Absy;
+ protected VerifierCallback callback;
+ private List<Block> m_CurrentTrace = new List<Block>();
+
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(label2Absy != null);
+ Contract.Invariant(callback != null);
+ Contract.Invariant(cce.NonNullElements(m_CurrentTrace));
+ }
+
+
+ public DoomErrorHandler(Dictionary<int, Absy> label2Absy, VerifierCallback callback)
+ {
+ Contract.Requires(label2Absy != null);
+ Contract.Requires(callback != null);
+ this.label2Absy = label2Absy;
+ this.callback = callback;
+ }
+
+ public override Absy Label2Absy(string label)
+ {
+ //Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ int id = int.Parse(label);
+ return cce.NonNull((Absy)label2Absy[id]);
+ }
+
+ public override void OnProverWarning(string msg)
+ {
+ //Contract.Requires(msg != null);
+ this.callback.OnWarning(msg);
+ }
+
+
+ public List<Block>/*!>!*/ TraceNodes
+ {
+ get
+ {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+
+ return m_CurrentTrace;
+ }
+ }
+
+ public override void OnModel(IList<string>/*!>!*/ labels, Model model, ProverInterface.Outcome proverOutcome)
+ {
+ // TODO: it would be better to check which reachability variables are actually set to one!
+ List<Block> traceNodes = new List<Block>();
+ List<AssertCmd> assertNodes = new List<AssertCmd>();
+ foreach (string s in labels)
+ {
+ Contract.Assert(s != null);
+ Absy node = Label2Absy(s);
+ if (node is Block)
+ {
+ Block b = (Block)node;
+ traceNodes.Add(b);
+ //Console.Write("{0}, ", b.Label);
+ }
+ }
+ m_CurrentTrace.AddRange(traceNodes);
+ }
+
+ }
+
} \ No newline at end of file
diff --git a/Source/Doomed/Doomed.csproj b/Source/Doomed/Doomed.csproj
index 77713080..f055d2c9 100644
--- a/Source/Doomed/Doomed.csproj
+++ b/Source/Doomed/Doomed.csproj
@@ -1,190 +1,190 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{884386A3-58E9-40BB-A273-B24976775553}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Doomed</RootNamespace>
- <AssemblyName>Doomed</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
- <ProductVersion>12.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </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>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
- <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
- <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
- <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
- <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
- <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
- <CodeContractsInferRequires>True</CodeContractsInferRequires>
- <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
- <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
- <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
- <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
- <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
- <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
- <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
- <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
- <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsSQLServerOption />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
- <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
- <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </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>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
- <CodeContractsInferRequires>True</CodeContractsInferRequires>
- <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
- <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
- <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
- <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
- <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsSQLServerOption />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="DoomCheck.cs" />
- <Compile Include="DoomedLoopUnrolling.cs" />
- <Compile Include="DoomedStrategy.cs" />
- <Compile Include="DoomErrorHandler.cs" />
- <Compile Include="HasseDiagram.cs" />
- <Compile Include="VCDoomed.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{884386A3-58E9-40BB-A273-B24976775553}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Doomed</RootNamespace>
+ <AssemblyName>BoogieDoomed</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ <ProductVersion>12.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </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>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+ <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
+ <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
+ <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
+ <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+ <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
+ <CodeContractsInferRequires>True</CodeContractsInferRequires>
+ <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+ <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
+ <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+ <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+ <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
+ <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
+ <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
+ <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+ <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsSQLServerOption />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+ <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
+ <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+ <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </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>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+ <CodeContractsInferRequires>True</CodeContractsInferRequires>
+ <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+ <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+ <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+ <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
+ <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsSQLServerOption />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+ <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DoomCheck.cs" />
+ <Compile Include="DoomedLoopUnrolling.cs" />
+ <Compile Include="DoomedStrategy.cs" />
+ <Compile Include="DoomErrorHandler.cs" />
+ <Compile Include="HasseDiagram.cs" />
+ <Compile Include="VCDoomed.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Model\Model.csproj">
+ <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</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/Doomed/DoomedLoopUnrolling.cs b/Source/Doomed/DoomedLoopUnrolling.cs
index 38fa99ac..0905deed 100644
--- a/Source/Doomed/DoomedLoopUnrolling.cs
+++ b/Source/Doomed/DoomedLoopUnrolling.cs
@@ -1,650 +1,650 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC
-{
- #region Loop handeling for doomed code detection
-
- #region Loop Remover
- internal class LoopRemover
- {
- GraphAnalyzer m_GraphAnalyzer;
-
- public LoopRemover(GraphAnalyzer ga)
- {
- m_GraphAnalyzer = ga;
- }
-
- private void m_RemoveBackEdge(Loop l)
- {
- // first remove the backedges of the nested loops
- foreach (Loop c in l.NestedLoops) m_RemoveBackEdge(c);
- //Debugger.Break();
- GraphNode loopSkip = null;
- foreach (GraphNode gn in l.Cutpoint.Suc)
- {
- if (l.LoopExitNodes.Contains(gn))
- {
- loopSkip = gn; break;
- }
- }
- if (loopSkip == null)
- { // We didn't find a loop exit node. There must be a bug
- Debugger.Break();
- }
- foreach (GraphNode gn in l.Cutpoint.LoopingPred)
- {
- List<GraphNode> newsuc = new List<GraphNode>();
- foreach (GraphNode s in gn.Suc)
- {
- if (s == l.Cutpoint) newsuc.Add(loopSkip);
- else newsuc.Add(s);
- }
- gn.Suc = newsuc;
- }
- }
-
- private void m_AbstractLoop(Loop l)
- {
- foreach (Loop c in l.NestedLoops) m_AbstractLoop(c);
- m_HavocLoopBody(l);
- m_RemoveBackEdge(l);
- }
-
- public void AbstractLoopUnrolling()
- {
- foreach (Loop l in m_GraphAnalyzer.Graphloops)
- {
- m_MarkLoopExitUncheckable(l);
- m_AbstractLoopUnrolling(l,null, "",true);
- }
- }
-
- private void m_HavocLoopBody(Loop l)
- {
- List<Block> loopblocks = new List<Block>();
- foreach (GraphNode g in l.LoopNodes) loopblocks.Add(g.Label);
- HavocCmd hcmd = m_ComputHavocCmd(loopblocks, l.Cutpoint.Label.tok);
-
- //Add Havoc before and after the loop body
- foreach (GraphNode g in l.Cutpoint.Suc) // before
- {
- if (l.LoopNodes.Contains(g)) m_AddHavocCmdToFront(g.Label, hcmd);
- }
- foreach (GraphNode g in l.Cutpoint.Pre) // and after
- {
- if (l.LoopNodes.Contains(g)) m_AddHavocCmdToFront(g.Label, hcmd);
- }
- }
-
- private void m_AddHavocCmdToFront(Block b, HavocCmd hcmd)
- {
- List<Cmd> cs = new List<Cmd>();
- cs.Add(hcmd); cs.AddRange(b.Cmds);
- b.Cmds = cs;
- }
-
- private HavocCmd m_ComputHavocCmd(List<Block> bl, IToken tok)
- {
- Contract.Requires(bl != null);
- Contract.Requires(tok != null);
- Contract.Ensures(Contract.Result<HavocCmd>() != null);
-
- List<Variable> varsToHavoc = new List<Variable>();
- foreach (Block b in bl)
- {
- Contract.Assert(b != null);
- foreach (Cmd c in b.Cmds)
- {
- Contract.Assert(c != null);
- c.AddAssignedVariables(varsToHavoc);
- }
- }
- List<IdentifierExpr> havocExprs = new List<IdentifierExpr>();
- foreach (Variable v in varsToHavoc)
- {
- Contract.Assert(v != null);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
- if (!havocExprs.Contains(ie))
- havocExprs.Add(ie);
- }
- // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
- // the source location for this later on
- return new HavocCmd(tok, havocExprs);
- }
-
- private void m_AbstractLoopUnrolling(Loop l, Loop parent, string prefix, bool unfold)
- {
- //Debugger.Break();
- if (unfold)
- {
-
- Loop first = new Loop(l, m_GraphAnalyzer,prefix+"FI_");
- Loop last = new Loop(l, m_GraphAnalyzer,prefix+"LA_");
- Loop abs = new Loop(l, m_GraphAnalyzer, prefix + "AB_");
- foreach (Loop c in first.NestedLoops) m_AbstractLoopUnrolling(c, first, prefix + "FI_", false);
- foreach (Loop c in last.NestedLoops) m_AbstractLoopUnrolling(c, last, prefix + "LA_", false);
- foreach (Loop c in abs.NestedLoops) m_AbstractLoopUnrolling(c, abs, prefix + "AB_", true);
-
- //Debugger.Break();
-
- if (parent != null)
- {
- foreach (GraphNode gn in l.LoopNodes)
- {
- if (parent.LoopNodes.Contains(gn)) parent.LoopNodes.Remove(gn);
- }
- foreach (GraphNode gn in abs.LoopNodes)
- {
- if (!parent.LoopNodes.Contains(gn)) parent.LoopNodes.Add(gn);
- }
- foreach (GraphNode gn in first.LoopNodes)
- {
- if (!parent.LoopNodes.Contains(gn)) parent.LoopNodes.Add(gn);
- }
- foreach (GraphNode gn in last.LoopNodes)
- {
- if (!parent.LoopNodes.Contains(gn)) parent.LoopNodes.Add(gn);
- }
- }
-
- m_HavocLoopBody(abs);
- List<GraphNode> backupPre = new List<GraphNode>();
- backupPre.AddRange(l.Cutpoint.Pre);
- foreach (GraphNode pre in backupPre)
- {
- if (!l.Cutpoint.LoopingPred.Contains(pre))
- {
- pre.RemoveEdgeTo(l.Cutpoint);
- pre.RemoveEdgeTo(abs.Cutpoint);
- pre.AddEdgeTo(first.Cutpoint);
- }
- }
-
- m_RemoveRegularLoopExit(last);
- m_RemoveRegularLoopExit(abs);
-
- m_ReplaceBackEdge(first, abs.Cutpoint);
- m_ReplaceBackEdge(abs, last.Cutpoint);
- foreach (GraphNode gn in first.Cutpoint.Suc)
- {
- if (!first.LoopNodes.Contains(gn))
- {
- m_ReplaceBackEdge(last, gn);
- break;
- }
- }
-
- // Remove all remaining connections to the original loop
- foreach (GraphNode gn in l.LoopExitNodes)
- {
- List<GraphNode> tmp = new List<GraphNode>();
- tmp.AddRange(gn.Pre);
- foreach (GraphNode g in tmp)
- {
- if (l.LoopNodes.Contains(g))
- {
- //Debugger.Break();
- g.RemoveEdgeTo(gn);
- }
- }
- }
- foreach (GraphNode gn in l.LoopNodes)
- {
- m_GraphAnalyzer.DeleteGraphNode(gn);
- }
- foreach (GraphNode gn in first.LoopNodes)
- {
- if (gn != first.Cutpoint && !m_GraphAnalyzer.UncheckableNodes.Contains(gn) )
- m_GraphAnalyzer.UncheckableNodes.Add(gn);
- }
- foreach (GraphNode gn in last.LoopNodes)
- {
- if (gn != last.Cutpoint && !m_GraphAnalyzer.UncheckableNodes.Contains(gn))
- m_GraphAnalyzer.UncheckableNodes.Add(gn);
- }
- MakeLoopExitUncheckable(last.LoopExitNodes);
- }
- else
- {
- foreach (Loop c in l.NestedLoops) m_AbstractLoopUnrolling(c, l, prefix, false);
- m_AbstractLoop(l);
- //MakeLoopExitUncheckable(l.LoopExitNodes);
- }
- }
-
- // the loop exit has to be marked uncheckable because otherwise
- // while(true) would report unreachable code.
- private void m_MarkLoopExitUncheckable(Loop l)
- {
-
- foreach (GraphNode g in l.Cutpoint.Suc)
- {
- if (!l.LoopNodes.Contains(g))
- {
- foreach (GraphNode g_ in m_MarkLoopExitUncheckable(g, l))
- {
- if (!m_GraphAnalyzer.UncheckableNodes.Contains(g_))
- m_GraphAnalyzer.UncheckableNodes.Add(g_);
- }
- }
- }
- }
-
- private List<GraphNode> m_MarkLoopExitUncheckable(GraphNode g, Loop l)
- {
- List<GraphNode> ret = new List<GraphNode>();
-
- if (g.Pre.Count > 1) return ret;
- ret.Add(g);
- foreach (GraphNode gn in g.Suc)
- {
- ret.AddRange(m_MarkLoopExitUncheckable(gn, l));
- }
-
- return ret;
- }
-
- // to avoid problems with unreachable code after while(true) {}, try to make the loopexit nodes uncheckable.
- private void MakeLoopExitUncheckable(List<GraphNode> le)
- {
- foreach (GraphNode gn in le)
- {
- if (gn.Suc.Count==1) m_GraphAnalyzer.UncheckableNodes.Add(gn);
- }
- }
-
- private void m_RemoveRegularLoopExit(Loop l)
- {
- List<GraphNode> lg = new List<GraphNode>();
- lg.AddRange( l.Cutpoint.Suc );
- foreach (GraphNode gn in lg)
- {
- if (l.LoopExitNodes.Contains(gn))
- {
- l.Cutpoint.RemoveEdgeTo(gn);
- l.LoopExitNodes.Remove(gn);
- }
- }
- }
-
- private void m_ReplaceBackEdge(Loop l, GraphNode loopSkip)
- {
-
- foreach (GraphNode gn in l.Cutpoint.LoopingPred)
- {
- List<GraphNode> newsuc = new List<GraphNode>();
- foreach (GraphNode s in gn.Suc)
- {
- if (s == l.Cutpoint) newsuc.Add(loopSkip);
- else newsuc.Add(s);
- }
- gn.Suc = newsuc;
- }
- }
-
-
- }
- #endregion
-
- #region Graph Analyzer
- internal class GraphAnalyzer
- {
- public List<GraphNode> UncheckableNodes = new List<GraphNode>();
-
- public Dictionary<Block, GraphNode> GraphMap = new Dictionary<Block, GraphNode>();
-
- public List<Loop> Graphloops = null;
-
- public GraphAnalyzer(List<Block> blocks)
- {
- //ExitBlock = dedicatedExitBlock;
- if (blocks.Count < 1) return;
- foreach (Block b in blocks) GraphMap[b] = new GraphNode(b);
- foreach (Block b in blocks)
- {
- foreach (Block pre in b.Predecessors) GraphMap[b].Pre.Add(GraphMap[pre]);
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (gc != null)
- {
- foreach (Block suc in gc.labelTargets) GraphMap[b].Suc.Add(GraphMap[suc]);
- }
- }
-
-
- m_DetectCutPoints(GraphMap[blocks[0]]);
-
- //m_DetectCutPoints(GraphMap[blocks[0]], null, new List<GraphNode>());
- Graphloops = m_CollectLoops(GraphMap[blocks[0]], null);
-
- }
-
- public List<Block> ToImplementation(out List<Block> uncheckables)
- {
- List<Block> blocks = new List<Block>();
- uncheckables = new List<Block>();
-
- foreach (KeyValuePair<Block, GraphNode> kvp in GraphMap)
- {
- Block b = kvp.Key;
- if (UncheckableNodes.Contains(GraphMap[b])) uncheckables.Add(b);
- blocks.Add(b);
- b.Predecessors = new List<Block>();
- foreach (GraphNode p in kvp.Value.Pre) b.Predecessors.Add(p.Label);
- if (kvp.Value.Suc.Count > 0)
- {
- List<Block> bs = new List<Block>();
- foreach (GraphNode s in kvp.Value.Suc) bs.Add(s.Label);
- b.TransferCmd = new GotoCmd(b.tok, bs);
- }
- else
- {
- b.TransferCmd = new ReturnCmd(b.tok);
- }
- }
-
- return blocks;
- }
-
- public GraphNode CloneGraphNode(GraphNode gn, string prefix)
- {
- List<Cmd> cmds = new List<Cmd>(gn.Label.Cmds);
-
- Block b = new Block(gn.Label.tok, prefix+gn.Label.Label, cmds, gn.Label.TransferCmd);
- GraphNode clone = new GraphNode(b);
- clone.IsCutpoint = gn.IsCutpoint;
- clone.Suc.AddRange(gn.Suc);
- clone.Pre.AddRange(gn.Pre);
- clone.LoopingPred.AddRange(gn.LoopingPred);
- GraphMap[b] = clone;
- //if (gn.Label == ExitBlock) ExitBlock = b;
- return clone;
- }
-
- public void DeleteGraphNode(GraphNode gn)
- {
- List<Block> affected = new List<Block>();
-
- foreach (KeyValuePair<Block, GraphNode> kvp in GraphMap)
- {
- if (kvp.Value == gn && !affected.Contains(kvp.Key)) affected.Add(kvp.Key);
- }
- foreach (Block b in affected)
- {
- GraphMap.Remove(b);
- }
- }
-/*
- private void m_DetectCutPoints(GraphNode gn, GraphNode pred, List<GraphNode> visited )
- {
- if (visited.Contains(gn) )
- {
- if (pred != null && !gn.LoopingPred.Contains(pred)) gn.LoopingPred.Add(pred);
- gn.IsCutpoint = true;
- Console.WriteLine("Normal RootNode {0}", gn.Label.Label);
- return;
- }
- else
- {
- List<GraphNode> visited_ = new List<GraphNode>();
- visited_.AddRange(visited);
- visited_.Add(gn);
- foreach (GraphNode next in gn.Suc)
- {
- m_DetectCutPoints(next,gn,visited_);
- }
- }
-
- }
-*/
-
-
- private void m_DetectCutPoints(GraphNode gn)
- {
- List<GraphNode> todo = new List<GraphNode>();
- List<GraphNode> done = new List<GraphNode>();
- todo.Add(gn);
-
- GraphNode current = null;
- todo[0].Index = 0;
-
- while (todo.Count > 0)
- {
- current = todo[0];
- todo.Remove(current);
-
- bool ready = true;
- foreach (GraphNode p in current.Pre)
- {
- if (!done.Contains(p) )
- {
- _loopbacktracking.Clear();
- if (!m_isLoop(current, p, todo, done))
- {
- todo.Add(current);
- ready = false;
- break;
- }
- else
- {
- if (!current.LoopingPred.Contains(p)) current.LoopingPred.Add(p);
- current.IsCutpoint = true;
- }
- }
- }
- if (!ready) continue;
- done.Add(current);
- foreach (GraphNode s in current.Suc)
- {
- if (!todo.Contains(s) && !done.Contains(s)) todo.Add(s);
- }
- }
-
- }
-
- List<GraphNode> _loopbacktracking = new List<GraphNode>();
- private bool m_isLoop(GraphNode loophead, GraphNode gn, List<GraphNode> l1, List<GraphNode> l2)
- {
- if (loophead == gn) return true;
- if (l1.Contains(gn) || l2.Contains(gn) || _loopbacktracking.Contains(gn)) return false;
- _loopbacktracking.Add(gn);
- foreach (GraphNode p in gn.Pre)
- {
- if (m_isLoop(loophead, p, l1, l2)) return true;
- }
- return false;
- }
-
- private List<Loop> m_CollectLoops(GraphNode gn, Loop lastLoop)
- {
- List<Loop> ret = new List<Loop>();
- if (gn.Visited) return ret;
- gn.Visited = true;
- List<GraphNode> loopingSucs = new List<GraphNode>();
- if (gn.IsCutpoint)
- {
- Loop l = new Loop(gn);
- if (lastLoop != null)
- {
- lastLoop.SucLoops.Add(l);
- l.PreLoops.Add(lastLoop);
- }
- loopingSucs = l.LoopNodes;
- lastLoop = l;
- ret.Add(lastLoop);
- }
- foreach (GraphNode suc in gn.Suc)
- {
- if (!loopingSucs.Contains(suc)) ret.AddRange(m_CollectLoops(suc, lastLoop));
- }
- //Debugger.Break();
- return ret;
- }
- }
- #endregion
-
- #region GraphNodeStructure
- internal class GraphNode
- {
- public int Index = -1; // Used for scc detection
- public int LowLink = -1; // Used for scc detection
-
- public GraphNode(Block b)
- {
- Label = b; IsCutpoint = false;
- }
- public Block Label;
- public List<GraphNode> Pre = new List<GraphNode>();
- public List<GraphNode> Suc = new List<GraphNode>();
- public bool IsCutpoint;
- public bool Visited = false;
- public List<GraphNode> LoopingPred = new List<GraphNode>();
-
- public void AddEdgeTo(GraphNode other)
- {
- if (!this.Suc.Contains(other)) this.Suc.Add(other);
- if (!other.Pre.Contains(this)) other.Pre.Add(this);
- }
-
- public void RemoveEdgeTo(GraphNode other)
- {
- if (this.Suc.Contains(other)) this.Suc.Remove(other);
- if (other.Pre.Contains(this)) other.Pre.Remove(this);
- }
-
- }
- #endregion
-
- #region LoopStructure
- internal class Loop
- {
- public Loop(GraphNode cutpoint)
- {
- if (!cutpoint.IsCutpoint)
- {
- Debugger.Break();
- }
- Cutpoint = cutpoint;
- LoopNodes.Add(Cutpoint);
- foreach (GraphNode gn in Cutpoint.LoopingPred)
- {
- CollectLoopBody(gn);
- }
- CollectLoopExitNodes();
- }
-
- // Copy Constructor
- public Loop(Loop l, GraphAnalyzer ga, string prefix)
- {
-
- Dictionary<GraphNode, GraphNode> clonemap = new Dictionary<GraphNode, GraphNode>();
- GraphNode clonecutpoint = null;
- foreach (GraphNode gn in l.LoopNodes)
- {
- clonemap[gn] = ga.CloneGraphNode(gn, prefix);
- if (gn == l.Cutpoint) clonecutpoint = clonemap[gn];
- }
-
- if (clonecutpoint == null)
- {
- Debugger.Break();
- return;
- }
- // Replace the pre and post nodes by the corresponding clone
- foreach (GraphNode gn in l.LoopNodes)
- {
- List<GraphNode> newl = new List<GraphNode>();
- foreach (GraphNode g in clonemap[gn].Pre)
- {
- if (clonemap.ContainsKey(g)) newl.Add(clonemap[g]);
- else newl.Add(g);
- }
- clonemap[gn].Pre = newl;
- newl = new List<GraphNode>();
- foreach (GraphNode g in clonemap[gn].Suc)
- {
- if (clonemap.ContainsKey(g)) newl.Add(clonemap[g]);
- else newl.Add(g);
- }
- clonemap[gn].Suc = newl;
- newl = new List<GraphNode>();
- foreach (GraphNode g in clonemap[gn].LoopingPred)
- {
- if (clonemap.ContainsKey(g)) newl.Add(clonemap[g]);
- else newl.Add(g);
- }
- clonemap[gn].LoopingPred = newl;
- }
-
- foreach (GraphNode gn in l.Cutpoint.LoopingPred)
- {
- clonecutpoint.LoopingPred.Remove(gn);
- clonecutpoint.LoopingPred.Add(clonemap[gn]);
- }
-
-
-
- SucLoops.AddRange(l.SucLoops);
- PreLoops.AddRange(l.PreLoops);
- Cutpoint = clonecutpoint;
- LoopNodes.Add(Cutpoint);
- foreach (GraphNode gn in Cutpoint.LoopingPred)
- {
- CollectLoopBody(gn);
- }
- CollectLoopExitNodes();
- }
-
- private void CollectLoopBody(GraphNode gn)
- {
- if (gn == Cutpoint) return;
- if (!LoopNodes.Contains(gn))
- {
- if (gn.IsCutpoint) // nested loop found
- {
- Loop lo = new Loop(gn);
- foreach (GraphNode lgn in lo.LoopNodes)
- {
- if (!LoopNodes.Contains(lgn)) LoopNodes.Add(lgn);
- }
- NestedLoops.Add(lo);
- }
- else
- {
- LoopNodes.Add(gn);
- }
- foreach (GraphNode pre in gn.Pre) if (!gn.LoopingPred.Contains(pre)) CollectLoopBody(pre);
- }
- }
-
- private void CollectLoopExitNodes()
- {
- foreach (GraphNode gn in LoopNodes)
- {
- foreach (GraphNode gn_ in gn.Suc)
- {
- if (!LoopNodes.Contains(gn_) && !LoopExitNodes.Contains(gn_)) LoopExitNodes.Add(gn_);
- }
- }
- }
-
- public GraphNode Cutpoint;
- public List<GraphNode> LoopExitNodes = new List<GraphNode>();
- public List<Loop> NestedLoops = new List<Loop>();
- public List<Loop> SucLoops = new List<Loop>();
- public List<Loop> PreLoops = new List<Loop>();
- public List<GraphNode> LoopNodes = new List<GraphNode>();
- }
- #endregion
-
- #endregion
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC
+{
+ #region Loop handeling for doomed code detection
+
+ #region Loop Remover
+ internal class LoopRemover
+ {
+ GraphAnalyzer m_GraphAnalyzer;
+
+ public LoopRemover(GraphAnalyzer ga)
+ {
+ m_GraphAnalyzer = ga;
+ }
+
+ private void m_RemoveBackEdge(Loop l)
+ {
+ // first remove the backedges of the nested loops
+ foreach (Loop c in l.NestedLoops) m_RemoveBackEdge(c);
+ //Debugger.Break();
+ GraphNode loopSkip = null;
+ foreach (GraphNode gn in l.Cutpoint.Suc)
+ {
+ if (l.LoopExitNodes.Contains(gn))
+ {
+ loopSkip = gn; break;
+ }
+ }
+ if (loopSkip == null)
+ { // We didn't find a loop exit node. There must be a bug
+ Debugger.Break();
+ }
+ foreach (GraphNode gn in l.Cutpoint.LoopingPred)
+ {
+ List<GraphNode> newsuc = new List<GraphNode>();
+ foreach (GraphNode s in gn.Suc)
+ {
+ if (s == l.Cutpoint) newsuc.Add(loopSkip);
+ else newsuc.Add(s);
+ }
+ gn.Suc = newsuc;
+ }
+ }
+
+ private void m_AbstractLoop(Loop l)
+ {
+ foreach (Loop c in l.NestedLoops) m_AbstractLoop(c);
+ m_HavocLoopBody(l);
+ m_RemoveBackEdge(l);
+ }
+
+ public void AbstractLoopUnrolling()
+ {
+ foreach (Loop l in m_GraphAnalyzer.Graphloops)
+ {
+ m_MarkLoopExitUncheckable(l);
+ m_AbstractLoopUnrolling(l,null, "",true);
+ }
+ }
+
+ private void m_HavocLoopBody(Loop l)
+ {
+ List<Block> loopblocks = new List<Block>();
+ foreach (GraphNode g in l.LoopNodes) loopblocks.Add(g.Label);
+ HavocCmd hcmd = m_ComputHavocCmd(loopblocks, l.Cutpoint.Label.tok);
+
+ //Add Havoc before and after the loop body
+ foreach (GraphNode g in l.Cutpoint.Suc) // before
+ {
+ if (l.LoopNodes.Contains(g)) m_AddHavocCmdToFront(g.Label, hcmd);
+ }
+ foreach (GraphNode g in l.Cutpoint.Pre) // and after
+ {
+ if (l.LoopNodes.Contains(g)) m_AddHavocCmdToFront(g.Label, hcmd);
+ }
+ }
+
+ private void m_AddHavocCmdToFront(Block b, HavocCmd hcmd)
+ {
+ List<Cmd> cs = new List<Cmd>();
+ cs.Add(hcmd); cs.AddRange(b.Cmds);
+ b.Cmds = cs;
+ }
+
+ private HavocCmd m_ComputHavocCmd(List<Block> bl, IToken tok)
+ {
+ Contract.Requires(bl != null);
+ Contract.Requires(tok != null);
+ Contract.Ensures(Contract.Result<HavocCmd>() != null);
+
+ List<Variable> varsToHavoc = new List<Variable>();
+ foreach (Block b in bl)
+ {
+ Contract.Assert(b != null);
+ foreach (Cmd c in b.Cmds)
+ {
+ Contract.Assert(c != null);
+ c.AddAssignedVariables(varsToHavoc);
+ }
+ }
+ List<IdentifierExpr> havocExprs = new List<IdentifierExpr>();
+ foreach (Variable v in varsToHavoc)
+ {
+ Contract.Assert(v != null);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
+ if (!havocExprs.Contains(ie))
+ havocExprs.Add(ie);
+ }
+ // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
+ // the source location for this later on
+ return new HavocCmd(tok, havocExprs);
+ }
+
+ private void m_AbstractLoopUnrolling(Loop l, Loop parent, string prefix, bool unfold)
+ {
+ //Debugger.Break();
+ if (unfold)
+ {
+
+ Loop first = new Loop(l, m_GraphAnalyzer,prefix+"FI_");
+ Loop last = new Loop(l, m_GraphAnalyzer,prefix+"LA_");
+ Loop abs = new Loop(l, m_GraphAnalyzer, prefix + "AB_");
+ foreach (Loop c in first.NestedLoops) m_AbstractLoopUnrolling(c, first, prefix + "FI_", false);
+ foreach (Loop c in last.NestedLoops) m_AbstractLoopUnrolling(c, last, prefix + "LA_", false);
+ foreach (Loop c in abs.NestedLoops) m_AbstractLoopUnrolling(c, abs, prefix + "AB_", true);
+
+ //Debugger.Break();
+
+ if (parent != null)
+ {
+ foreach (GraphNode gn in l.LoopNodes)
+ {
+ if (parent.LoopNodes.Contains(gn)) parent.LoopNodes.Remove(gn);
+ }
+ foreach (GraphNode gn in abs.LoopNodes)
+ {
+ if (!parent.LoopNodes.Contains(gn)) parent.LoopNodes.Add(gn);
+ }
+ foreach (GraphNode gn in first.LoopNodes)
+ {
+ if (!parent.LoopNodes.Contains(gn)) parent.LoopNodes.Add(gn);
+ }
+ foreach (GraphNode gn in last.LoopNodes)
+ {
+ if (!parent.LoopNodes.Contains(gn)) parent.LoopNodes.Add(gn);
+ }
+ }
+
+ m_HavocLoopBody(abs);
+ List<GraphNode> backupPre = new List<GraphNode>();
+ backupPre.AddRange(l.Cutpoint.Pre);
+ foreach (GraphNode pre in backupPre)
+ {
+ if (!l.Cutpoint.LoopingPred.Contains(pre))
+ {
+ pre.RemoveEdgeTo(l.Cutpoint);
+ pre.RemoveEdgeTo(abs.Cutpoint);
+ pre.AddEdgeTo(first.Cutpoint);
+ }
+ }
+
+ m_RemoveRegularLoopExit(last);
+ m_RemoveRegularLoopExit(abs);
+
+ m_ReplaceBackEdge(first, abs.Cutpoint);
+ m_ReplaceBackEdge(abs, last.Cutpoint);
+ foreach (GraphNode gn in first.Cutpoint.Suc)
+ {
+ if (!first.LoopNodes.Contains(gn))
+ {
+ m_ReplaceBackEdge(last, gn);
+ break;
+ }
+ }
+
+ // Remove all remaining connections to the original loop
+ foreach (GraphNode gn in l.LoopExitNodes)
+ {
+ List<GraphNode> tmp = new List<GraphNode>();
+ tmp.AddRange(gn.Pre);
+ foreach (GraphNode g in tmp)
+ {
+ if (l.LoopNodes.Contains(g))
+ {
+ //Debugger.Break();
+ g.RemoveEdgeTo(gn);
+ }
+ }
+ }
+ foreach (GraphNode gn in l.LoopNodes)
+ {
+ m_GraphAnalyzer.DeleteGraphNode(gn);
+ }
+ foreach (GraphNode gn in first.LoopNodes)
+ {
+ if (gn != first.Cutpoint && !m_GraphAnalyzer.UncheckableNodes.Contains(gn) )
+ m_GraphAnalyzer.UncheckableNodes.Add(gn);
+ }
+ foreach (GraphNode gn in last.LoopNodes)
+ {
+ if (gn != last.Cutpoint && !m_GraphAnalyzer.UncheckableNodes.Contains(gn))
+ m_GraphAnalyzer.UncheckableNodes.Add(gn);
+ }
+ MakeLoopExitUncheckable(last.LoopExitNodes);
+ }
+ else
+ {
+ foreach (Loop c in l.NestedLoops) m_AbstractLoopUnrolling(c, l, prefix, false);
+ m_AbstractLoop(l);
+ //MakeLoopExitUncheckable(l.LoopExitNodes);
+ }
+ }
+
+ // the loop exit has to be marked uncheckable because otherwise
+ // while(true) would report unreachable code.
+ private void m_MarkLoopExitUncheckable(Loop l)
+ {
+
+ foreach (GraphNode g in l.Cutpoint.Suc)
+ {
+ if (!l.LoopNodes.Contains(g))
+ {
+ foreach (GraphNode g_ in m_MarkLoopExitUncheckable(g, l))
+ {
+ if (!m_GraphAnalyzer.UncheckableNodes.Contains(g_))
+ m_GraphAnalyzer.UncheckableNodes.Add(g_);
+ }
+ }
+ }
+ }
+
+ private List<GraphNode> m_MarkLoopExitUncheckable(GraphNode g, Loop l)
+ {
+ List<GraphNode> ret = new List<GraphNode>();
+
+ if (g.Pre.Count > 1) return ret;
+ ret.Add(g);
+ foreach (GraphNode gn in g.Suc)
+ {
+ ret.AddRange(m_MarkLoopExitUncheckable(gn, l));
+ }
+
+ return ret;
+ }
+
+ // to avoid problems with unreachable code after while(true) {}, try to make the loopexit nodes uncheckable.
+ private void MakeLoopExitUncheckable(List<GraphNode> le)
+ {
+ foreach (GraphNode gn in le)
+ {
+ if (gn.Suc.Count==1) m_GraphAnalyzer.UncheckableNodes.Add(gn);
+ }
+ }
+
+ private void m_RemoveRegularLoopExit(Loop l)
+ {
+ List<GraphNode> lg = new List<GraphNode>();
+ lg.AddRange( l.Cutpoint.Suc );
+ foreach (GraphNode gn in lg)
+ {
+ if (l.LoopExitNodes.Contains(gn))
+ {
+ l.Cutpoint.RemoveEdgeTo(gn);
+ l.LoopExitNodes.Remove(gn);
+ }
+ }
+ }
+
+ private void m_ReplaceBackEdge(Loop l, GraphNode loopSkip)
+ {
+
+ foreach (GraphNode gn in l.Cutpoint.LoopingPred)
+ {
+ List<GraphNode> newsuc = new List<GraphNode>();
+ foreach (GraphNode s in gn.Suc)
+ {
+ if (s == l.Cutpoint) newsuc.Add(loopSkip);
+ else newsuc.Add(s);
+ }
+ gn.Suc = newsuc;
+ }
+ }
+
+
+ }
+ #endregion
+
+ #region Graph Analyzer
+ internal class GraphAnalyzer
+ {
+ public List<GraphNode> UncheckableNodes = new List<GraphNode>();
+
+ public Dictionary<Block, GraphNode> GraphMap = new Dictionary<Block, GraphNode>();
+
+ public List<Loop> Graphloops = null;
+
+ public GraphAnalyzer(List<Block> blocks)
+ {
+ //ExitBlock = dedicatedExitBlock;
+ if (blocks.Count < 1) return;
+ foreach (Block b in blocks) GraphMap[b] = new GraphNode(b);
+ foreach (Block b in blocks)
+ {
+ foreach (Block pre in b.Predecessors) GraphMap[b].Pre.Add(GraphMap[pre]);
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ foreach (Block suc in gc.labelTargets) GraphMap[b].Suc.Add(GraphMap[suc]);
+ }
+ }
+
+
+ m_DetectCutPoints(GraphMap[blocks[0]]);
+
+ //m_DetectCutPoints(GraphMap[blocks[0]], null, new List<GraphNode>());
+ Graphloops = m_CollectLoops(GraphMap[blocks[0]], null);
+
+ }
+
+ public List<Block> ToImplementation(out List<Block> uncheckables)
+ {
+ List<Block> blocks = new List<Block>();
+ uncheckables = new List<Block>();
+
+ foreach (KeyValuePair<Block, GraphNode> kvp in GraphMap)
+ {
+ Block b = kvp.Key;
+ if (UncheckableNodes.Contains(GraphMap[b])) uncheckables.Add(b);
+ blocks.Add(b);
+ b.Predecessors = new List<Block>();
+ foreach (GraphNode p in kvp.Value.Pre) b.Predecessors.Add(p.Label);
+ if (kvp.Value.Suc.Count > 0)
+ {
+ List<Block> bs = new List<Block>();
+ foreach (GraphNode s in kvp.Value.Suc) bs.Add(s.Label);
+ b.TransferCmd = new GotoCmd(b.tok, bs);
+ }
+ else
+ {
+ b.TransferCmd = new ReturnCmd(b.tok);
+ }
+ }
+
+ return blocks;
+ }
+
+ public GraphNode CloneGraphNode(GraphNode gn, string prefix)
+ {
+ List<Cmd> cmds = new List<Cmd>(gn.Label.Cmds);
+
+ Block b = new Block(gn.Label.tok, prefix+gn.Label.Label, cmds, gn.Label.TransferCmd);
+ GraphNode clone = new GraphNode(b);
+ clone.IsCutpoint = gn.IsCutpoint;
+ clone.Suc.AddRange(gn.Suc);
+ clone.Pre.AddRange(gn.Pre);
+ clone.LoopingPred.AddRange(gn.LoopingPred);
+ GraphMap[b] = clone;
+ //if (gn.Label == ExitBlock) ExitBlock = b;
+ return clone;
+ }
+
+ public void DeleteGraphNode(GraphNode gn)
+ {
+ List<Block> affected = new List<Block>();
+
+ foreach (KeyValuePair<Block, GraphNode> kvp in GraphMap)
+ {
+ if (kvp.Value == gn && !affected.Contains(kvp.Key)) affected.Add(kvp.Key);
+ }
+ foreach (Block b in affected)
+ {
+ GraphMap.Remove(b);
+ }
+ }
+/*
+ private void m_DetectCutPoints(GraphNode gn, GraphNode pred, List<GraphNode> visited )
+ {
+ if (visited.Contains(gn) )
+ {
+ if (pred != null && !gn.LoopingPred.Contains(pred)) gn.LoopingPred.Add(pred);
+ gn.IsCutpoint = true;
+ Console.WriteLine("Normal RootNode {0}", gn.Label.Label);
+ return;
+ }
+ else
+ {
+ List<GraphNode> visited_ = new List<GraphNode>();
+ visited_.AddRange(visited);
+ visited_.Add(gn);
+ foreach (GraphNode next in gn.Suc)
+ {
+ m_DetectCutPoints(next,gn,visited_);
+ }
+ }
+
+ }
+*/
+
+
+ private void m_DetectCutPoints(GraphNode gn)
+ {
+ List<GraphNode> todo = new List<GraphNode>();
+ List<GraphNode> done = new List<GraphNode>();
+ todo.Add(gn);
+
+ GraphNode current = null;
+ todo[0].Index = 0;
+
+ while (todo.Count > 0)
+ {
+ current = todo[0];
+ todo.Remove(current);
+
+ bool ready = true;
+ foreach (GraphNode p in current.Pre)
+ {
+ if (!done.Contains(p) )
+ {
+ _loopbacktracking.Clear();
+ if (!m_isLoop(current, p, todo, done))
+ {
+ todo.Add(current);
+ ready = false;
+ break;
+ }
+ else
+ {
+ if (!current.LoopingPred.Contains(p)) current.LoopingPred.Add(p);
+ current.IsCutpoint = true;
+ }
+ }
+ }
+ if (!ready) continue;
+ done.Add(current);
+ foreach (GraphNode s in current.Suc)
+ {
+ if (!todo.Contains(s) && !done.Contains(s)) todo.Add(s);
+ }
+ }
+
+ }
+
+ List<GraphNode> _loopbacktracking = new List<GraphNode>();
+ private bool m_isLoop(GraphNode loophead, GraphNode gn, List<GraphNode> l1, List<GraphNode> l2)
+ {
+ if (loophead == gn) return true;
+ if (l1.Contains(gn) || l2.Contains(gn) || _loopbacktracking.Contains(gn)) return false;
+ _loopbacktracking.Add(gn);
+ foreach (GraphNode p in gn.Pre)
+ {
+ if (m_isLoop(loophead, p, l1, l2)) return true;
+ }
+ return false;
+ }
+
+ private List<Loop> m_CollectLoops(GraphNode gn, Loop lastLoop)
+ {
+ List<Loop> ret = new List<Loop>();
+ if (gn.Visited) return ret;
+ gn.Visited = true;
+ List<GraphNode> loopingSucs = new List<GraphNode>();
+ if (gn.IsCutpoint)
+ {
+ Loop l = new Loop(gn);
+ if (lastLoop != null)
+ {
+ lastLoop.SucLoops.Add(l);
+ l.PreLoops.Add(lastLoop);
+ }
+ loopingSucs = l.LoopNodes;
+ lastLoop = l;
+ ret.Add(lastLoop);
+ }
+ foreach (GraphNode suc in gn.Suc)
+ {
+ if (!loopingSucs.Contains(suc)) ret.AddRange(m_CollectLoops(suc, lastLoop));
+ }
+ //Debugger.Break();
+ return ret;
+ }
+ }
+ #endregion
+
+ #region GraphNodeStructure
+ internal class GraphNode
+ {
+ public int Index = -1; // Used for scc detection
+ public int LowLink = -1; // Used for scc detection
+
+ public GraphNode(Block b)
+ {
+ Label = b; IsCutpoint = false;
+ }
+ public Block Label;
+ public List<GraphNode> Pre = new List<GraphNode>();
+ public List<GraphNode> Suc = new List<GraphNode>();
+ public bool IsCutpoint;
+ public bool Visited = false;
+ public List<GraphNode> LoopingPred = new List<GraphNode>();
+
+ public void AddEdgeTo(GraphNode other)
+ {
+ if (!this.Suc.Contains(other)) this.Suc.Add(other);
+ if (!other.Pre.Contains(this)) other.Pre.Add(this);
+ }
+
+ public void RemoveEdgeTo(GraphNode other)
+ {
+ if (this.Suc.Contains(other)) this.Suc.Remove(other);
+ if (other.Pre.Contains(this)) other.Pre.Remove(this);
+ }
+
+ }
+ #endregion
+
+ #region LoopStructure
+ internal class Loop
+ {
+ public Loop(GraphNode cutpoint)
+ {
+ if (!cutpoint.IsCutpoint)
+ {
+ Debugger.Break();
+ }
+ Cutpoint = cutpoint;
+ LoopNodes.Add(Cutpoint);
+ foreach (GraphNode gn in Cutpoint.LoopingPred)
+ {
+ CollectLoopBody(gn);
+ }
+ CollectLoopExitNodes();
+ }
+
+ // Copy Constructor
+ public Loop(Loop l, GraphAnalyzer ga, string prefix)
+ {
+
+ Dictionary<GraphNode, GraphNode> clonemap = new Dictionary<GraphNode, GraphNode>();
+ GraphNode clonecutpoint = null;
+ foreach (GraphNode gn in l.LoopNodes)
+ {
+ clonemap[gn] = ga.CloneGraphNode(gn, prefix);
+ if (gn == l.Cutpoint) clonecutpoint = clonemap[gn];
+ }
+
+ if (clonecutpoint == null)
+ {
+ Debugger.Break();
+ return;
+ }
+ // Replace the pre and post nodes by the corresponding clone
+ foreach (GraphNode gn in l.LoopNodes)
+ {
+ List<GraphNode> newl = new List<GraphNode>();
+ foreach (GraphNode g in clonemap[gn].Pre)
+ {
+ if (clonemap.ContainsKey(g)) newl.Add(clonemap[g]);
+ else newl.Add(g);
+ }
+ clonemap[gn].Pre = newl;
+ newl = new List<GraphNode>();
+ foreach (GraphNode g in clonemap[gn].Suc)
+ {
+ if (clonemap.ContainsKey(g)) newl.Add(clonemap[g]);
+ else newl.Add(g);
+ }
+ clonemap[gn].Suc = newl;
+ newl = new List<GraphNode>();
+ foreach (GraphNode g in clonemap[gn].LoopingPred)
+ {
+ if (clonemap.ContainsKey(g)) newl.Add(clonemap[g]);
+ else newl.Add(g);
+ }
+ clonemap[gn].LoopingPred = newl;
+ }
+
+ foreach (GraphNode gn in l.Cutpoint.LoopingPred)
+ {
+ clonecutpoint.LoopingPred.Remove(gn);
+ clonecutpoint.LoopingPred.Add(clonemap[gn]);
+ }
+
+
+
+ SucLoops.AddRange(l.SucLoops);
+ PreLoops.AddRange(l.PreLoops);
+ Cutpoint = clonecutpoint;
+ LoopNodes.Add(Cutpoint);
+ foreach (GraphNode gn in Cutpoint.LoopingPred)
+ {
+ CollectLoopBody(gn);
+ }
+ CollectLoopExitNodes();
+ }
+
+ private void CollectLoopBody(GraphNode gn)
+ {
+ if (gn == Cutpoint) return;
+ if (!LoopNodes.Contains(gn))
+ {
+ if (gn.IsCutpoint) // nested loop found
+ {
+ Loop lo = new Loop(gn);
+ foreach (GraphNode lgn in lo.LoopNodes)
+ {
+ if (!LoopNodes.Contains(lgn)) LoopNodes.Add(lgn);
+ }
+ NestedLoops.Add(lo);
+ }
+ else
+ {
+ LoopNodes.Add(gn);
+ }
+ foreach (GraphNode pre in gn.Pre) if (!gn.LoopingPred.Contains(pre)) CollectLoopBody(pre);
+ }
+ }
+
+ private void CollectLoopExitNodes()
+ {
+ foreach (GraphNode gn in LoopNodes)
+ {
+ foreach (GraphNode gn_ in gn.Suc)
+ {
+ if (!LoopNodes.Contains(gn_) && !LoopExitNodes.Contains(gn_)) LoopExitNodes.Add(gn_);
+ }
+ }
+ }
+
+ public GraphNode Cutpoint;
+ public List<GraphNode> LoopExitNodes = new List<GraphNode>();
+ public List<Loop> NestedLoops = new List<Loop>();
+ public List<Loop> SucLoops = new List<Loop>();
+ public List<Loop> PreLoops = new List<Loop>();
+ public List<GraphNode> LoopNodes = new List<GraphNode>();
+ }
+ #endregion
+
+ #endregion
} \ No newline at end of file
diff --git a/Source/Doomed/DoomedStrategy.cs b/Source/Doomed/DoomedStrategy.cs
index 9e280873..76261827 100644
--- a/Source/Doomed/DoomedStrategy.cs
+++ b/Source/Doomed/DoomedStrategy.cs
@@ -1,528 +1,528 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC
-{
- #region SuperClass for different doomed code detection strategies
- abstract internal class DoomDetectionStrategy
- {
- public int __DEBUG_BlocksChecked = 0;
- public int __DEBUG_BlocksTotal = 0;
- public int __DEBUG_InfeasibleTraces = 0;
- public int __DEBUG_TracesChecked = 0;
- public int __DEBUG_TracesTotal = 0;
- public int __DEBUG_EQCTotal = 0;
- public int __DEBUG_EQCLeaf = 0;
- public int __DEBUG_EQCChecked = 0;
-
- //Please use this one to toggle your Debug output
- protected bool __DEBUGOUT = CommandLineOptions.Clo.DoomStrategy != -1;
-
- protected Implementation impl;
- protected BlockHierachy m_BlockH = null;
-
- protected int m_MaxBranchingDepth = 0;
- protected int m_MaxK = 0;
-
- protected Stopwatch sw = new Stopwatch();
-
-
- // This is the List with all detected doomed program points. This List is used by VCDoomed.cs to
- // create an error message
- public List<List<Block/*!*/>/*!*/>/*!*/ DetectedBlock = new List<List<Block/*!*/>/*!*/>();
-
- private List<Block> __DEBUG_minelements = new List<Block>();
-
- // There is no default constructor, because these parameters are needed for most subclasses
- public DoomDetectionStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
- {
- m_BlockH = new BlockHierachy(imp, unifiedexit);
- __DEBUG_EQCLeaf = m_BlockH.Leaves.Count;
-
- //foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
- //{
- // if (bhn.Content.Count > 0) __DEBUG_minelements.Add(bhn.Content[0]);
- //}
- //if (imp.Blocks.Count>0) m_GatherInfo(imp.Blocks[0], 0, 0,0);
-
-
- if (__DEBUGOUT)
- {
- Console.WriteLine("MaBranchingDepth {0} MaxMinPP {1} ", m_MaxBranchingDepth, m_MaxK);
-
- Console.WriteLine("AvgLeaverPerPath {0} AvgPLen {1}", 0, 0);
- }
-
- MaxBlocks = imp.Blocks.Count;
- MinBlocks = imp.Blocks.Count;
- HACK_NewCheck = false;
- __DEBUG_BlocksTotal = imp.Blocks.Count;
- }
-
- public int MaxBlocks, MinBlocks;
- public bool HACK_NewCheck;
-
- // This method is called by the prover while it returns true. The prover checks for each
- // List lb if
- // |= !lb_1 /\ ... /\ !lb_n => wlp(Program, false)
- // and passes the result to SetCurrentResult
- abstract public bool GetNextBlock(out List<Block> passBlock);
-
- // This method is called to inform about the prover outcome for the previous GetNextBlock call.
- abstract public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb);
-
- protected List<Block> m_GetErrorTraceFromCE(DoomErrorHandler cb)
- {
- BlockHierachyNode tn=null;
- List<Block> errortrace = new List<Block>();
- foreach (Block b in cb.TraceNodes)
- {
- if (errortrace.Contains(b)) continue;
- if (m_BlockH.BlockToHierachyMap.TryGetValue(b, out tn))
- {
- foreach (Block b_ in tn.Unavoidable)
- {
- if (!errortrace.Contains(b_)) errortrace.Add(b_);
- }
- foreach (Block b_ in tn.Content)
- {
- if (!errortrace.Contains(b_)) errortrace.Add(b_);
- }
- }
- }
- return errortrace;
- }
-
- private List<int> __pathLength = new List<int>();
- private List<int> __leavespp = new List<int>();
- protected void m_GatherInfo(Block b, int branchingdepth, int leavespp, int plen)
- {
- if (b.Predecessors.Count > 1) branchingdepth--;
-
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (__DEBUG_minelements.Contains(b)) leavespp++;
- plen++;
- if (gc != null && gc.labelTargets.Count>0)
- {
- if (gc.labelTargets.Count > 1) branchingdepth++;
- m_MaxBranchingDepth = (branchingdepth > m_MaxBranchingDepth) ? branchingdepth : m_MaxBranchingDepth;
- foreach (Block s in gc.labelTargets)
- {
- m_GatherInfo(s, branchingdepth, leavespp,plen);
- }
- }
- else
- {
- __pathLength.Add(plen);
- __leavespp.Add(leavespp);
- m_MaxK = (m_MaxK > leavespp) ? m_MaxK : leavespp;
- }
- }
-
-
-
- }
- #endregion
-
- #region BruteForce Strategy
- internal class NoStrategy : DoomDetectionStrategy
- {
- private List<Block> m_Blocks = new List<Block>();
- private int m_Current = 0;
-
- public NoStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
- : base(imp, unifiedexit, unreach)
- {
- m_Blocks = imp.Blocks;
- }
-
- override public bool GetNextBlock(out List<Block> lb)
- {
- if (m_Current < m_Blocks.Count)
- {
- lb = new List<Block>();
- lb.Add(m_Blocks[m_Current]);
- m_Current++;
- return true;
- }
- lb = null;
- return false;
- }
-
- // This method is called to inform about the prover outcome for the previous GetNextBlock call.
- override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
- {
- this.__DEBUG_BlocksChecked++;
- // outcome==Valid means that there is no feasible execution for the current block/path (i.e., might be doomed)
- if (outcome == ProverInterface.Outcome.Valid && m_Current <= m_Blocks.Count)
- {
- List<Block> lb = new List<Block>();
- lb.Add(m_Blocks[m_Current - 1]);
- DetectedBlock.Add(lb);
- }
- return true;
- }
- }
- #endregion
-
- #region Only check the minimal elements of the Hasse diagram
- internal class HierachyStrategy : DoomDetectionStrategy
- {
- private List<Block> m_Blocks = new List<Block>();
- private List<Block> m_doomedBlocks = new List<Block>();
- private int m_Current = 0;
-
- public HierachyStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
- : base(imp, unifiedexit, unreach)
- {
- foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
- {
- if (bhn.Content.Count > 0)
- {
- m_Blocks.Add(bhn.Content[0]);
- }
- }
- }
-
- override public bool GetNextBlock(out List<Block> lb)
- {
- sw.Start();
- if (m_Current < m_Blocks.Count)
- {
- lb = new List<Block>();
- lb.Add(m_Blocks[m_Current]);
- m_Current++;
- return true;
- }
- else
- {
- DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_doomedBlocks));
- }
- lb = null;
- return false;
- }
-
- // This method is called to inform about the prover outcome for the previous GetNextBlock call.
- override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
- {
- this.__DEBUG_BlocksChecked++;
- // outcome==Valid means that there is no feasible execution for the current block/path (i.e., might be doomed)
- if (outcome == ProverInterface.Outcome.Valid && m_Current <= m_Blocks.Count)
- {
- m_doomedBlocks.Add(m_Blocks[m_Current - 1]);
- }
- if (__DEBUGOUT) Console.WriteLine("K := {0,3} , out {1,8}, time {2,12}", MaxBlocks, outcome, sw.ElapsedTicks);
- sw.Stop();
- sw.Reset();
-
- return true;
- }
- }
- #endregion
-
- #region Only check the minimal elements of the Hasse diagram and use CEs
- internal class HierachyCEStrategy : DoomDetectionStrategy
- {
- private List<Block> m_Blocks = new List<Block>();
- private List<Block> m_doomedBlocks = new List<Block>();
- private Block m_Current = null;
-
- public HierachyCEStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
- : base(imp, unifiedexit, unreach)
- {
- foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
- {
- if (bhn.Content.Count > 0)
- {
- m_Blocks.Add(bhn.Content[0]);
- }
- }
- }
-
- override public bool GetNextBlock(out List<Block> lb)
- {
- m_Current = null;
- if (m_Blocks.Count > 0)
- {
- m_Current = m_Blocks[0];
- m_Blocks.Remove(m_Current);
- lb = new List<Block>();
- lb.Add(m_Current);
- return true;
- }
- else
- {
- DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_doomedBlocks));
- }
- lb = null;
- return false;
- }
-
- // This method is called to inform about the prover outcome for the previous GetNextBlock call.
- override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
- {
- this.__DEBUG_BlocksChecked++;
- // outcome==Valid means that there is no feasible execution for the current block/path (i.e., might be doomed)
- if (outcome == ProverInterface.Outcome.Valid && m_Current != null)
- {
- m_doomedBlocks.Add(m_Current);
- }
- else if (outcome == ProverInterface.Outcome.Invalid)
- {
- List<Block> errortrace = m_GetErrorTraceFromCE(cb);
- foreach (Block b in errortrace)
- {
- if (m_Blocks.Contains(b))
- {
- m_Blocks.Remove(b);
- }
- }
- cb.TraceNodes.Clear();
- }
- return true;
- }
- }
- #endregion
-
- #region Path Cover Optimization with L
- internal class PathCoverStrategy : DoomDetectionStrategy
- {
- List<Block> m_Uncheckedlocks = new List<Block>();
- List<Block> m_Ignore = new List<Block>();
-
- Random m_Random = new Random();
- bool m_NoMoreMoves = false;
-
- private List<Block> m_foundBlock = new List<Block>();
-
- public PathCoverStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
- : base(imp, unifiedexit, unreach)
- {
- m_Ignore = unreach;
- HACK_NewCheck = true;
- impl = imp;
- foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
- {
- if (bhn.Content.Count > 0)
- {
- m_Uncheckedlocks.Add(bhn.Content[0]);
- }
-
- }
- m_MaxK = m_BlockH.GetMaxK(m_Uncheckedlocks);
- MinBlocks = m_MaxK / 2 + (m_MaxK % 2 > 0 ? 1 : 0);
- MaxBlocks = -1;
- }
-
- override public bool GetNextBlock(out List<Block> lb)
- {
- sw.Start();
-
- lb = new List<Block>();
-
- if (m_Uncheckedlocks.Count == 0 || m_NoMoreMoves)
- {
- if (m_Uncheckedlocks.Count > 0)
- {
- DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_Uncheckedlocks));
- }
-
- return false;
- }
-
- lb.AddRange(m_Uncheckedlocks);
-
- return true;
- }
-
- override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
- {
- this.__DEBUG_BlocksChecked++;
- // Valid means infeasible...
- int oldl = MinBlocks;
- int oldsize = m_Uncheckedlocks.Count;
-
-
- if (outcome == ProverInterface.Outcome.Valid)
- {
- this.__DEBUG_InfeasibleTraces++;
- if (MinBlocks == 1)
- {
- m_NoMoreMoves = true;
- }
- else
- {
- MinBlocks = 1;
- }
- }
- else if (outcome == ProverInterface.Outcome.Invalid)
- {
- this.__DEBUG_TracesChecked++;
-
- List<Block> errortrace = m_GetErrorTraceFromCE(cb);
- foreach (Block b in errortrace)
- {
- if (m_Uncheckedlocks.Contains(b))
- {
- m_Uncheckedlocks.Remove(b);
- }
- }
- cb.TraceNodes.Clear();
- m_MaxK = m_BlockH.GetMaxK(m_Uncheckedlocks);
- if (m_MaxK < 1)
- {
- m_NoMoreMoves = true; m_Uncheckedlocks.Clear();
- }
- MinBlocks = m_MaxK / 2 + (m_MaxK % 2 > 0 ? 1 : 0);
- //if (MinBlocks > m_MaxK) MinBlocks = m_MaxK;
-
- }
- else
- {
- m_NoMoreMoves = true; m_Uncheckedlocks.Clear();
- }
- if (__DEBUGOUT)
- Console.WriteLine("K := {0,3}, L := {1,3}, deltaSp {2,3}, out {3,8}, time {4,8}", MaxBlocks, oldl, (oldsize - m_Uncheckedlocks.Count), outcome, sw.ElapsedTicks);
- sw.Stop();
- sw.Reset();
- return true;
- }
-
-
- }
- #endregion
-
- #region Path Cover Optimization with K
- internal class PathCoverStrategyK : DoomDetectionStrategy
- {
- List<Block> m_Uncheckedlocks = new List<Block>();
- List<Block> m_Ignore = new List<Block>();
-
- Random m_Random = new Random();
- bool m_NoMoreMoves = false;
-
- private List<Block> m_foundBlock = new List<Block>();
-
- public PathCoverStrategyK(Implementation imp, Block unifiedexit, List<Block> unreach)
- : base(imp, unifiedexit, unreach)
- {
- m_Ignore = unreach;
- HACK_NewCheck = true;
- impl = imp;
- foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
- {
- if (bhn.Content.Count > 0)
- {
- m_Uncheckedlocks.Add(bhn.Content[0]);
- }
-
- }
-
- m_MaxK = m_BlockH.GetMaxK(m_Uncheckedlocks);
-
- MaxBlocks = m_Uncheckedlocks.Count;
- if (m_MaxK < m_Uncheckedlocks.Count && m_MaxK > 0)
- {
- MaxBlocks = m_MaxK;
- }
- else if (m_MaxK >= m_Uncheckedlocks.Count)
- {
- MaxBlocks = m_Uncheckedlocks.Count;
- }
- else
- {
- MaxBlocks = 1;
- }
- //Console.WriteLine("InitK {0}, Max {1}", m_MaxK, MaxBlocks);
- }
-
- override public bool GetNextBlock(out List<Block> lb)
- {
- sw.Start();
-
- lb = new List<Block>();
-
- if (m_Uncheckedlocks.Count == 0 || m_NoMoreMoves)
- {
- if (m_Uncheckedlocks.Count > 0)
- {
- DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_Uncheckedlocks));
- }
-
- return false;
- }
-
- lb.AddRange(m_Uncheckedlocks);
-
- MaxBlocks = MaxBlocks > m_Uncheckedlocks.Count ? m_Uncheckedlocks.Count : MaxBlocks;
- MinBlocks = MaxBlocks / 2 + (MaxBlocks % 2 > 0 ? 1 : 0);
- return true;
- }
-
- override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
- {
- this.__DEBUG_BlocksChecked++;
- // Valid means infeasible...
- int oldk = MaxBlocks;
- int oldl = MinBlocks;
- int oldsize = m_Uncheckedlocks.Count;
-
- if (outcome == ProverInterface.Outcome.Valid)
- {
- this.__DEBUG_InfeasibleTraces++;
- if (MaxBlocks == 1)
- {
- m_NoMoreMoves = true;
- }
- else
- {
- MaxBlocks /= 2;
- }
- }
- else if (outcome == ProverInterface.Outcome.Invalid)
- {
- this.__DEBUG_TracesChecked++;
-
- List<Block> errortrace = m_GetErrorTraceFromCE(cb);
- foreach (Block b in errortrace)
- {
- if (m_Uncheckedlocks.Contains(b))
- {
- m_Uncheckedlocks.Remove(b);
- }
- }
- cb.TraceNodes.Clear();
-
- int k = m_BlockH.GetMaxK(m_Uncheckedlocks);
- MaxBlocks = (k > MaxBlocks) ? MaxBlocks : k;
- }
- else
- {
- m_NoMoreMoves = true; m_Uncheckedlocks.Clear();
- }
- if (__DEBUGOUT)
- Console.WriteLine("K := {0,3}, L := {1,3}, deltaSp {2,3}, out {3,8}, time {4,8}", oldk, oldl, (oldsize - m_Uncheckedlocks.Count), outcome, sw.ElapsedTicks);
- sw.Stop();
- sw.Reset();
- return true;
- }
-
-
- }
- #endregion
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC
+{
+ #region SuperClass for different doomed code detection strategies
+ abstract internal class DoomDetectionStrategy
+ {
+ public int __DEBUG_BlocksChecked = 0;
+ public int __DEBUG_BlocksTotal = 0;
+ public int __DEBUG_InfeasibleTraces = 0;
+ public int __DEBUG_TracesChecked = 0;
+ public int __DEBUG_TracesTotal = 0;
+ public int __DEBUG_EQCTotal = 0;
+ public int __DEBUG_EQCLeaf = 0;
+ public int __DEBUG_EQCChecked = 0;
+
+ //Please use this one to toggle your Debug output
+ protected bool __DEBUGOUT = CommandLineOptions.Clo.DoomStrategy != -1;
+
+ protected Implementation impl;
+ protected BlockHierachy m_BlockH = null;
+
+ protected int m_MaxBranchingDepth = 0;
+ protected int m_MaxK = 0;
+
+ protected Stopwatch sw = new Stopwatch();
+
+
+ // This is the List with all detected doomed program points. This List is used by VCDoomed.cs to
+ // create an error message
+ public List<List<Block/*!*/>/*!*/>/*!*/ DetectedBlock = new List<List<Block/*!*/>/*!*/>();
+
+ private List<Block> __DEBUG_minelements = new List<Block>();
+
+ // There is no default constructor, because these parameters are needed for most subclasses
+ public DoomDetectionStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
+ {
+ m_BlockH = new BlockHierachy(imp, unifiedexit);
+ __DEBUG_EQCLeaf = m_BlockH.Leaves.Count;
+
+ //foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
+ //{
+ // if (bhn.Content.Count > 0) __DEBUG_minelements.Add(bhn.Content[0]);
+ //}
+ //if (imp.Blocks.Count>0) m_GatherInfo(imp.Blocks[0], 0, 0,0);
+
+
+ if (__DEBUGOUT)
+ {
+ Console.WriteLine("MaBranchingDepth {0} MaxMinPP {1} ", m_MaxBranchingDepth, m_MaxK);
+
+ Console.WriteLine("AvgLeaverPerPath {0} AvgPLen {1}", 0, 0);
+ }
+
+ MaxBlocks = imp.Blocks.Count;
+ MinBlocks = imp.Blocks.Count;
+ HACK_NewCheck = false;
+ __DEBUG_BlocksTotal = imp.Blocks.Count;
+ }
+
+ public int MaxBlocks, MinBlocks;
+ public bool HACK_NewCheck;
+
+ // This method is called by the prover while it returns true. The prover checks for each
+ // List lb if
+ // |= !lb_1 /\ ... /\ !lb_n => wlp(Program, false)
+ // and passes the result to SetCurrentResult
+ abstract public bool GetNextBlock(out List<Block> passBlock);
+
+ // This method is called to inform about the prover outcome for the previous GetNextBlock call.
+ abstract public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb);
+
+ protected List<Block> m_GetErrorTraceFromCE(DoomErrorHandler cb)
+ {
+ BlockHierachyNode tn=null;
+ List<Block> errortrace = new List<Block>();
+ foreach (Block b in cb.TraceNodes)
+ {
+ if (errortrace.Contains(b)) continue;
+ if (m_BlockH.BlockToHierachyMap.TryGetValue(b, out tn))
+ {
+ foreach (Block b_ in tn.Unavoidable)
+ {
+ if (!errortrace.Contains(b_)) errortrace.Add(b_);
+ }
+ foreach (Block b_ in tn.Content)
+ {
+ if (!errortrace.Contains(b_)) errortrace.Add(b_);
+ }
+ }
+ }
+ return errortrace;
+ }
+
+ private List<int> __pathLength = new List<int>();
+ private List<int> __leavespp = new List<int>();
+ protected void m_GatherInfo(Block b, int branchingdepth, int leavespp, int plen)
+ {
+ if (b.Predecessors.Count > 1) branchingdepth--;
+
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (__DEBUG_minelements.Contains(b)) leavespp++;
+ plen++;
+ if (gc != null && gc.labelTargets.Count>0)
+ {
+ if (gc.labelTargets.Count > 1) branchingdepth++;
+ m_MaxBranchingDepth = (branchingdepth > m_MaxBranchingDepth) ? branchingdepth : m_MaxBranchingDepth;
+ foreach (Block s in gc.labelTargets)
+ {
+ m_GatherInfo(s, branchingdepth, leavespp,plen);
+ }
+ }
+ else
+ {
+ __pathLength.Add(plen);
+ __leavespp.Add(leavespp);
+ m_MaxK = (m_MaxK > leavespp) ? m_MaxK : leavespp;
+ }
+ }
+
+
+
+ }
+ #endregion
+
+ #region BruteForce Strategy
+ internal class NoStrategy : DoomDetectionStrategy
+ {
+ private List<Block> m_Blocks = new List<Block>();
+ private int m_Current = 0;
+
+ public NoStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
+ : base(imp, unifiedexit, unreach)
+ {
+ m_Blocks = imp.Blocks;
+ }
+
+ override public bool GetNextBlock(out List<Block> lb)
+ {
+ if (m_Current < m_Blocks.Count)
+ {
+ lb = new List<Block>();
+ lb.Add(m_Blocks[m_Current]);
+ m_Current++;
+ return true;
+ }
+ lb = null;
+ return false;
+ }
+
+ // This method is called to inform about the prover outcome for the previous GetNextBlock call.
+ override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
+ {
+ this.__DEBUG_BlocksChecked++;
+ // outcome==Valid means that there is no feasible execution for the current block/path (i.e., might be doomed)
+ if (outcome == ProverInterface.Outcome.Valid && m_Current <= m_Blocks.Count)
+ {
+ List<Block> lb = new List<Block>();
+ lb.Add(m_Blocks[m_Current - 1]);
+ DetectedBlock.Add(lb);
+ }
+ return true;
+ }
+ }
+ #endregion
+
+ #region Only check the minimal elements of the Hasse diagram
+ internal class HierachyStrategy : DoomDetectionStrategy
+ {
+ private List<Block> m_Blocks = new List<Block>();
+ private List<Block> m_doomedBlocks = new List<Block>();
+ private int m_Current = 0;
+
+ public HierachyStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
+ : base(imp, unifiedexit, unreach)
+ {
+ foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
+ {
+ if (bhn.Content.Count > 0)
+ {
+ m_Blocks.Add(bhn.Content[0]);
+ }
+ }
+ }
+
+ override public bool GetNextBlock(out List<Block> lb)
+ {
+ sw.Start();
+ if (m_Current < m_Blocks.Count)
+ {
+ lb = new List<Block>();
+ lb.Add(m_Blocks[m_Current]);
+ m_Current++;
+ return true;
+ }
+ else
+ {
+ DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_doomedBlocks));
+ }
+ lb = null;
+ return false;
+ }
+
+ // This method is called to inform about the prover outcome for the previous GetNextBlock call.
+ override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
+ {
+ this.__DEBUG_BlocksChecked++;
+ // outcome==Valid means that there is no feasible execution for the current block/path (i.e., might be doomed)
+ if (outcome == ProverInterface.Outcome.Valid && m_Current <= m_Blocks.Count)
+ {
+ m_doomedBlocks.Add(m_Blocks[m_Current - 1]);
+ }
+ if (__DEBUGOUT) Console.WriteLine("K := {0,3} , out {1,8}, time {2,12}", MaxBlocks, outcome, sw.ElapsedTicks);
+ sw.Stop();
+ sw.Reset();
+
+ return true;
+ }
+ }
+ #endregion
+
+ #region Only check the minimal elements of the Hasse diagram and use CEs
+ internal class HierachyCEStrategy : DoomDetectionStrategy
+ {
+ private List<Block> m_Blocks = new List<Block>();
+ private List<Block> m_doomedBlocks = new List<Block>();
+ private Block m_Current = null;
+
+ public HierachyCEStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
+ : base(imp, unifiedexit, unreach)
+ {
+ foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
+ {
+ if (bhn.Content.Count > 0)
+ {
+ m_Blocks.Add(bhn.Content[0]);
+ }
+ }
+ }
+
+ override public bool GetNextBlock(out List<Block> lb)
+ {
+ m_Current = null;
+ if (m_Blocks.Count > 0)
+ {
+ m_Current = m_Blocks[0];
+ m_Blocks.Remove(m_Current);
+ lb = new List<Block>();
+ lb.Add(m_Current);
+ return true;
+ }
+ else
+ {
+ DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_doomedBlocks));
+ }
+ lb = null;
+ return false;
+ }
+
+ // This method is called to inform about the prover outcome for the previous GetNextBlock call.
+ override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
+ {
+ this.__DEBUG_BlocksChecked++;
+ // outcome==Valid means that there is no feasible execution for the current block/path (i.e., might be doomed)
+ if (outcome == ProverInterface.Outcome.Valid && m_Current != null)
+ {
+ m_doomedBlocks.Add(m_Current);
+ }
+ else if (outcome == ProverInterface.Outcome.Invalid)
+ {
+ List<Block> errortrace = m_GetErrorTraceFromCE(cb);
+ foreach (Block b in errortrace)
+ {
+ if (m_Blocks.Contains(b))
+ {
+ m_Blocks.Remove(b);
+ }
+ }
+ cb.TraceNodes.Clear();
+ }
+ return true;
+ }
+ }
+ #endregion
+
+ #region Path Cover Optimization with L
+ internal class PathCoverStrategy : DoomDetectionStrategy
+ {
+ List<Block> m_Uncheckedlocks = new List<Block>();
+ List<Block> m_Ignore = new List<Block>();
+
+ Random m_Random = new Random();
+ bool m_NoMoreMoves = false;
+
+ private List<Block> m_foundBlock = new List<Block>();
+
+ public PathCoverStrategy(Implementation imp, Block unifiedexit, List<Block> unreach)
+ : base(imp, unifiedexit, unreach)
+ {
+ m_Ignore = unreach;
+ HACK_NewCheck = true;
+ impl = imp;
+ foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
+ {
+ if (bhn.Content.Count > 0)
+ {
+ m_Uncheckedlocks.Add(bhn.Content[0]);
+ }
+
+ }
+ m_MaxK = m_BlockH.GetMaxK(m_Uncheckedlocks);
+ MinBlocks = m_MaxK / 2 + (m_MaxK % 2 > 0 ? 1 : 0);
+ MaxBlocks = -1;
+ }
+
+ override public bool GetNextBlock(out List<Block> lb)
+ {
+ sw.Start();
+
+ lb = new List<Block>();
+
+ if (m_Uncheckedlocks.Count == 0 || m_NoMoreMoves)
+ {
+ if (m_Uncheckedlocks.Count > 0)
+ {
+ DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_Uncheckedlocks));
+ }
+
+ return false;
+ }
+
+ lb.AddRange(m_Uncheckedlocks);
+
+ return true;
+ }
+
+ override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
+ {
+ this.__DEBUG_BlocksChecked++;
+ // Valid means infeasible...
+ int oldl = MinBlocks;
+ int oldsize = m_Uncheckedlocks.Count;
+
+
+ if (outcome == ProverInterface.Outcome.Valid)
+ {
+ this.__DEBUG_InfeasibleTraces++;
+ if (MinBlocks == 1)
+ {
+ m_NoMoreMoves = true;
+ }
+ else
+ {
+ MinBlocks = 1;
+ }
+ }
+ else if (outcome == ProverInterface.Outcome.Invalid)
+ {
+ this.__DEBUG_TracesChecked++;
+
+ List<Block> errortrace = m_GetErrorTraceFromCE(cb);
+ foreach (Block b in errortrace)
+ {
+ if (m_Uncheckedlocks.Contains(b))
+ {
+ m_Uncheckedlocks.Remove(b);
+ }
+ }
+ cb.TraceNodes.Clear();
+ m_MaxK = m_BlockH.GetMaxK(m_Uncheckedlocks);
+ if (m_MaxK < 1)
+ {
+ m_NoMoreMoves = true; m_Uncheckedlocks.Clear();
+ }
+ MinBlocks = m_MaxK / 2 + (m_MaxK % 2 > 0 ? 1 : 0);
+ //if (MinBlocks > m_MaxK) MinBlocks = m_MaxK;
+
+ }
+ else
+ {
+ m_NoMoreMoves = true; m_Uncheckedlocks.Clear();
+ }
+ if (__DEBUGOUT)
+ Console.WriteLine("K := {0,3}, L := {1,3}, deltaSp {2,3}, out {3,8}, time {4,8}", MaxBlocks, oldl, (oldsize - m_Uncheckedlocks.Count), outcome, sw.ElapsedTicks);
+ sw.Stop();
+ sw.Reset();
+ return true;
+ }
+
+
+ }
+ #endregion
+
+ #region Path Cover Optimization with K
+ internal class PathCoverStrategyK : DoomDetectionStrategy
+ {
+ List<Block> m_Uncheckedlocks = new List<Block>();
+ List<Block> m_Ignore = new List<Block>();
+
+ Random m_Random = new Random();
+ bool m_NoMoreMoves = false;
+
+ private List<Block> m_foundBlock = new List<Block>();
+
+ public PathCoverStrategyK(Implementation imp, Block unifiedexit, List<Block> unreach)
+ : base(imp, unifiedexit, unreach)
+ {
+ m_Ignore = unreach;
+ HACK_NewCheck = true;
+ impl = imp;
+ foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
+ {
+ if (bhn.Content.Count > 0)
+ {
+ m_Uncheckedlocks.Add(bhn.Content[0]);
+ }
+
+ }
+
+ m_MaxK = m_BlockH.GetMaxK(m_Uncheckedlocks);
+
+ MaxBlocks = m_Uncheckedlocks.Count;
+ if (m_MaxK < m_Uncheckedlocks.Count && m_MaxK > 0)
+ {
+ MaxBlocks = m_MaxK;
+ }
+ else if (m_MaxK >= m_Uncheckedlocks.Count)
+ {
+ MaxBlocks = m_Uncheckedlocks.Count;
+ }
+ else
+ {
+ MaxBlocks = 1;
+ }
+ //Console.WriteLine("InitK {0}, Max {1}", m_MaxK, MaxBlocks);
+ }
+
+ override public bool GetNextBlock(out List<Block> lb)
+ {
+ sw.Start();
+
+ lb = new List<Block>();
+
+ if (m_Uncheckedlocks.Count == 0 || m_NoMoreMoves)
+ {
+ if (m_Uncheckedlocks.Count > 0)
+ {
+ DetectedBlock.Add(m_BlockH.GetOtherDoomedBlocks(m_Uncheckedlocks));
+ }
+
+ return false;
+ }
+
+ lb.AddRange(m_Uncheckedlocks);
+
+ MaxBlocks = MaxBlocks > m_Uncheckedlocks.Count ? m_Uncheckedlocks.Count : MaxBlocks;
+ MinBlocks = MaxBlocks / 2 + (MaxBlocks % 2 > 0 ? 1 : 0);
+ return true;
+ }
+
+ override public bool SetCurrentResult(List<Variable> reachvar, ProverInterface.Outcome outcome, DoomErrorHandler cb)
+ {
+ this.__DEBUG_BlocksChecked++;
+ // Valid means infeasible...
+ int oldk = MaxBlocks;
+ int oldl = MinBlocks;
+ int oldsize = m_Uncheckedlocks.Count;
+
+ if (outcome == ProverInterface.Outcome.Valid)
+ {
+ this.__DEBUG_InfeasibleTraces++;
+ if (MaxBlocks == 1)
+ {
+ m_NoMoreMoves = true;
+ }
+ else
+ {
+ MaxBlocks /= 2;
+ }
+ }
+ else if (outcome == ProverInterface.Outcome.Invalid)
+ {
+ this.__DEBUG_TracesChecked++;
+
+ List<Block> errortrace = m_GetErrorTraceFromCE(cb);
+ foreach (Block b in errortrace)
+ {
+ if (m_Uncheckedlocks.Contains(b))
+ {
+ m_Uncheckedlocks.Remove(b);
+ }
+ }
+ cb.TraceNodes.Clear();
+
+ int k = m_BlockH.GetMaxK(m_Uncheckedlocks);
+ MaxBlocks = (k > MaxBlocks) ? MaxBlocks : k;
+ }
+ else
+ {
+ m_NoMoreMoves = true; m_Uncheckedlocks.Clear();
+ }
+ if (__DEBUGOUT)
+ Console.WriteLine("K := {0,3}, L := {1,3}, deltaSp {2,3}, out {3,8}, time {4,8}", oldk, oldl, (oldsize - m_Uncheckedlocks.Count), outcome, sw.ElapsedTicks);
+ sw.Stop();
+ sw.Reset();
+ return true;
+ }
+
+
+ }
+ #endregion
+
} \ No newline at end of file
diff --git a/Source/Doomed/HasseDiagram.cs b/Source/Doomed/HasseDiagram.cs
index ad3d487e..c866662e 100644
--- a/Source/Doomed/HasseDiagram.cs
+++ b/Source/Doomed/HasseDiagram.cs
@@ -1,424 +1,424 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC
-{
- internal class BlockHierachyNode
- {
- public List<Block> Unavoidable;
- public List<Block> Content = new List<Block>();
- public List<BlockHierachyNode> Parents = new List<BlockHierachyNode>();
- public List<BlockHierachyNode> Children = new List<BlockHierachyNode>();
-
- public bool Checked, Doomed, DoubleChecked;
-
- public BlockHierachyNode(Block current, List<Block> unavoidable)
- {
- Checked = false; Doomed = false; DoubleChecked = false;
- Unavoidable = unavoidable;
- Content.Add(current);
- }
-
- public static bool operator <(BlockHierachyNode left, BlockHierachyNode right)
- {
- return Compare(left,right)>0;
- }
-
- public static bool operator >(BlockHierachyNode left, BlockHierachyNode right)
- {
- return Compare(left, right) < 0;
- }
-
- // Compare the unavoidable blocks of two BlockHierachyNodes.
- // returns 0 if sets have the same size, -1 if l2 has an element
- // that is not in l1, otherwise the size of the intersection.
- public static int Compare(BlockHierachyNode l1, BlockHierachyNode l2)
- {
- List<Block> tmp = new List<Block>();
- tmp.AddRange(l2.Unavoidable);
- foreach (Block b in l1.Unavoidable)
- {
- if (tmp.Contains(b)) tmp.Remove(b);
- else return -1;
- }
- return tmp.Count;
- }
- }
-
- internal class HasseDiagram
- {
- public readonly List<BlockHierachyNode> Leaves = new List<BlockHierachyNode>();
- public readonly List<BlockHierachyNode> Roots = new List<BlockHierachyNode>();
-
- public HasseDiagram(List<BlockHierachyNode> nodes)
- {
- Dictionary<BlockHierachyNode, List<BlockHierachyNode>> largerElements = new Dictionary<BlockHierachyNode, List<BlockHierachyNode>>();
- foreach (BlockHierachyNode left in nodes)
- {
- largerElements[left] = new List<BlockHierachyNode>();
- foreach (BlockHierachyNode right in nodes)
- {
- if (left != right)
- {
- if (left < right)
- {
- largerElements[left].Add(right);
- }
- }
- }
- if (largerElements[left].Count == 0) Leaves.Add(left);
- }
-
- List<BlockHierachyNode> done = new List<BlockHierachyNode>();
- List<BlockHierachyNode> lastround = null;
-
- //Debugger.Break();
-
- // Now that we have the leaves, build the Hasse diagram
- while (done.Count < nodes.Count)
- {
- List<BlockHierachyNode> maxelements = new List<BlockHierachyNode>();
- maxelements.AddRange(nodes);
- foreach (BlockHierachyNode bhn in nodes)
- {
- if (!done.Contains(bhn))
- {
- foreach (BlockHierachyNode tmp in largerElements[bhn])
- {
- if (maxelements.Contains(tmp)) maxelements.Remove(tmp);
- }
- }
- else
- {
- maxelements.Remove(bhn);
- }
- }
-
- done.AddRange(maxelements);
-
- if (lastround != null)
- {
- foreach (BlockHierachyNode tmp in lastround)
- {
- foreach (BlockHierachyNode tmp2 in maxelements)
- {
- if (largerElements[tmp].Contains(tmp2))
- {
- if (!tmp.Children.Contains(tmp2)) tmp.Children.Add(tmp2);
- if (!tmp2.Parents.Contains(tmp)) tmp2.Parents.Add(tmp);
- }
- }
- }
- }
- else
- {
- Roots.AddRange(maxelements);
- }
- lastround = maxelements;
- }
- }
-
-
- }
-
- internal class BlockHierachy
- {
- public BlockHierachyNode RootNode = null;
- readonly public Dictionary<Block, BlockHierachyNode> BlockToHierachyMap = new Dictionary<Block, BlockHierachyNode>();
- readonly public Dictionary<Block, List<Block>> Dominators = new Dictionary<Block, List<Block>>();
- readonly public Dictionary<Block, List<Block>> PostDominators = new Dictionary<Block, List<Block>>();
- readonly public List<BlockHierachyNode> Leaves = new List<BlockHierachyNode>();
-
- private Implementation m_Impl;
-
- public BlockHierachy(Implementation impl, Block unifiedExit)
- {
- m_Impl = impl;
- List<Block> blocks = impl.Blocks;
- List<BlockHierachyNode> tmp_hnodes = new List<BlockHierachyNode>();
- Dictionary<Block, List<Block>> unavoidable = new Dictionary<Block, List<Block>>();
-
- BfsTraverser(blocks[0], true, Dominators);
- BfsTraverser(unifiedExit, false, PostDominators);
-
- foreach (Block b in blocks)
- {
- List<Block> l1 = Dominators[b];
- List<Block> l2 = PostDominators[b];
- unavoidable[b] = m_MergeLists(l1, l2);
-
- BlockHierachyNode bhn = new BlockHierachyNode(b, unavoidable[b]);
- bool found = false;
- foreach (KeyValuePair<Block, BlockHierachyNode> kvp in BlockToHierachyMap)
- {
- if (BlockHierachyNode.Compare(kvp.Value, bhn) == 0) // using the overloaded compare operator
- {
- kvp.Value.Content.AddRange(bhn.Content);
- BlockToHierachyMap[b] = kvp.Value;
- found = true;
- break;
- }
- }
- if (!found)
- {
- BlockToHierachyMap[b] = bhn;
- tmp_hnodes.Add(bhn);
- }
- }
-
- HasseDiagram hd = new HasseDiagram(tmp_hnodes);
- Leaves = hd.Leaves;
- }
-
- public int GetMaxK(List<Block> blocks)
- {
- m_GetMaxK(blocks);
- return (m_MaxK>0) ? m_MaxK : 1;
- }
-
- private int m_MaxK = 0;
- private void m_GetMaxK(List<Block> blocks)
- {
- m_MaxK = 0;
- Dictionary<Block, int> kstore = new Dictionary<Block, int>();
- List<Block> todo = new List<Block>();
- List<Block> done = new List<Block>();
- todo.Add(m_Impl.Blocks[0]);
- kstore[m_Impl.Blocks[0]] = 0;
- int localmax;
- Block current = null;
- while (todo.Count > 0)
- {
- current = todo[0];
- todo.Remove(current);
- bool ready = true;
- localmax = 0;
- if (current.Predecessors!=null) {
- foreach (Block p in current.Predecessors)
- {
- if (!done.Contains(p))
- {
- ready = false; break;
- }
- else localmax = (localmax > kstore[p]) ? localmax : kstore[p];
- }
- }
- if (!ready)
- {
- todo.Add(current); continue;
- }
- done.Add(current);
- kstore[current] = (blocks.Contains(current)) ? localmax +1 : localmax;
-
- m_MaxK = (kstore[current] > m_MaxK) ? kstore[current] : m_MaxK;
-
- GotoCmd gc = current.TransferCmd as GotoCmd;
- if (gc != null)
- {
- foreach (Block s in gc.labelTargets)
- {
- if (!todo.Contains(s)) todo.Add(s);
- }
- }
- }
-
- }
-
- public List<Block> GetOtherDoomedBlocks(List<Block> doomedblocks)
- {
- List<Block> alsoDoomed = new List<Block>();
- List<BlockHierachyNode> todo = new List<BlockHierachyNode>();
- foreach (Block b in doomedblocks)
- {
- BlockToHierachyMap[b].Doomed = true;
- todo.Add(BlockToHierachyMap[b]);
- }
-
- while (todo.Count > 0)
- {
- BlockHierachyNode current = todo[0];
- todo.Remove(current);
- if (!current.Doomed && current.Children.Count > 0)
- {
- bool childrenDoomed = true;
- foreach (BlockHierachyNode c in current.Children)
- {
- if (!c.Doomed) { childrenDoomed = false; break; }
- }
- if (childrenDoomed) current.Doomed = true;
- }
-
- if (current.Doomed)
- {
- foreach (BlockHierachyNode p in current.Parents)
- {
- if (!todo.Contains(p)) todo.Add(p);
- }
- foreach (Block b in current.Content)
- {
- if (!alsoDoomed.Contains(b)) alsoDoomed.Add(b);
- }
- }
- }
-
- return alsoDoomed;
- }
-
- public void Impl2Dot(string filename)
- {
-
- Contract.Requires(filename != null);
- List<string> nodes = new List<string>();
- List<string> edges = new List<string>();
-
- string nodestyle = "[shape=box];";
-
- List<BlockHierachyNode> nl = new List<BlockHierachyNode>();
- foreach (BlockHierachyNode h in BlockToHierachyMap.Values) if (!nl.Contains(h)) nl.Add(h);
-
-
- foreach (BlockHierachyNode b in nl)
- {
- String l1 = "";
- foreach (Block bl in b.Content) l1 = String.Format("{0}_{1}", l1, bl.Label);
-
- Contract.Assert(b != null);
- nodes.Add(string.Format("\"{0}\" {1}", l1, nodestyle));
- foreach (BlockHierachyNode b_ in b.Children)
- {
-
- String l2 = "";
- foreach (Block bl in b_.Content) l2 = String.Format("{0}_{1}", l2, bl.Label);
- edges.Add(String.Format("\"{0}\" -> \"{1}\";", l1, l2));
- }
-
- }
-
- using (StreamWriter sw = new StreamWriter(filename))
- {
- sw.WriteLine(String.Format("digraph {0} {{", "DISCO"));
- // foreach (string! s in nodes) {
- // sw.WriteLine(s);
- // }
- foreach (string s in edges)
- {
- Contract.Assert(s != null);
- sw.WriteLine(s);
- }
- sw.WriteLine("}}");
- sw.Close();
- }
- }
-
- private void BfsTraverser(Block current, bool forward, Dictionary<Block, List<Block>> unavoidableBlocks)
- {
- List<Block> todo = new List<Block>();
- List<Block> done = new List<Block>();
- unavoidableBlocks[current] = new List<Block>();
- //Debugger.Break();
- todo.Add(current);
- while (todo.Count > 0)
- {
- current = todo[0];
- todo.Remove(current);
- List<Block> pre = m_Predecessors(current, forward);
- bool ready = true;
- if (pre != null)
- {
- foreach (Block bpre in pre)
- {
- if (!done.Contains(bpre))
- {
- ready = false;
- break;
- }
- }
- }
- if (!ready)
- {
- todo.Add(current);
- continue;
- }
- done.Add(current);
- unavoidableBlocks[current].Add(current);
-
- List<Block> suc = m_Succecessors(current, forward);
- if (suc == null) continue;
- foreach (Block bsuc in suc)
- {
- if (unavoidableBlocks.ContainsKey(bsuc))
- {
- unavoidableBlocks[bsuc] = m_IntersectLists(unavoidableBlocks[bsuc], unavoidableBlocks[current]);
- }
- else
- {
- todo.Add(bsuc);
- unavoidableBlocks[bsuc] = new List<Block>();
- unavoidableBlocks[bsuc].AddRange(unavoidableBlocks[current]);
- }
-
- }
- }
-
- }
-
- private List<Block> m_MergeLists(List<Block> lb1, List<Block> lb2)
- {
- List<Block> ret = new List<Block>();
- ret.AddRange(lb1);
- foreach (Block b in lb2)
- {
- if (!ret.Contains(b)) ret.Add(b);
- }
- return ret;
- }
-
- private List<Block> m_IntersectLists(List<Block> lb1, List<Block> lb2)
- {
- List<Block> ret = new List<Block>();
- ret.AddRange(lb1);
- foreach (Block b in lb2)
- {
- if (!lb1.Contains(b)) ret.Remove(b);
- }
- foreach (Block b in lb1)
- {
- if (ret.Contains(b) && !lb2.Contains(b)) ret.Remove(b);
- }
- return ret;
- }
-
- private List<Block> m_Predecessors(Block b, bool forward)
- {
- if (forward) return b.Predecessors;
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (gc != null)
- {
- return gc.labelTargets;
- }
- return null;
- }
-
- private List<Block> m_Succecessors(Block b, bool forward)
- {
- return m_Predecessors(b, !forward);
- }
-
-
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC
+{
+ internal class BlockHierachyNode
+ {
+ public List<Block> Unavoidable;
+ public List<Block> Content = new List<Block>();
+ public List<BlockHierachyNode> Parents = new List<BlockHierachyNode>();
+ public List<BlockHierachyNode> Children = new List<BlockHierachyNode>();
+
+ public bool Checked, Doomed, DoubleChecked;
+
+ public BlockHierachyNode(Block current, List<Block> unavoidable)
+ {
+ Checked = false; Doomed = false; DoubleChecked = false;
+ Unavoidable = unavoidable;
+ Content.Add(current);
+ }
+
+ public static bool operator <(BlockHierachyNode left, BlockHierachyNode right)
+ {
+ return Compare(left,right)>0;
+ }
+
+ public static bool operator >(BlockHierachyNode left, BlockHierachyNode right)
+ {
+ return Compare(left, right) < 0;
+ }
+
+ // Compare the unavoidable blocks of two BlockHierachyNodes.
+ // returns 0 if sets have the same size, -1 if l2 has an element
+ // that is not in l1, otherwise the size of the intersection.
+ public static int Compare(BlockHierachyNode l1, BlockHierachyNode l2)
+ {
+ List<Block> tmp = new List<Block>();
+ tmp.AddRange(l2.Unavoidable);
+ foreach (Block b in l1.Unavoidable)
+ {
+ if (tmp.Contains(b)) tmp.Remove(b);
+ else return -1;
+ }
+ return tmp.Count;
+ }
+ }
+
+ internal class HasseDiagram
+ {
+ public readonly List<BlockHierachyNode> Leaves = new List<BlockHierachyNode>();
+ public readonly List<BlockHierachyNode> Roots = new List<BlockHierachyNode>();
+
+ public HasseDiagram(List<BlockHierachyNode> nodes)
+ {
+ Dictionary<BlockHierachyNode, List<BlockHierachyNode>> largerElements = new Dictionary<BlockHierachyNode, List<BlockHierachyNode>>();
+ foreach (BlockHierachyNode left in nodes)
+ {
+ largerElements[left] = new List<BlockHierachyNode>();
+ foreach (BlockHierachyNode right in nodes)
+ {
+ if (left != right)
+ {
+ if (left < right)
+ {
+ largerElements[left].Add(right);
+ }
+ }
+ }
+ if (largerElements[left].Count == 0) Leaves.Add(left);
+ }
+
+ List<BlockHierachyNode> done = new List<BlockHierachyNode>();
+ List<BlockHierachyNode> lastround = null;
+
+ //Debugger.Break();
+
+ // Now that we have the leaves, build the Hasse diagram
+ while (done.Count < nodes.Count)
+ {
+ List<BlockHierachyNode> maxelements = new List<BlockHierachyNode>();
+ maxelements.AddRange(nodes);
+ foreach (BlockHierachyNode bhn in nodes)
+ {
+ if (!done.Contains(bhn))
+ {
+ foreach (BlockHierachyNode tmp in largerElements[bhn])
+ {
+ if (maxelements.Contains(tmp)) maxelements.Remove(tmp);
+ }
+ }
+ else
+ {
+ maxelements.Remove(bhn);
+ }
+ }
+
+ done.AddRange(maxelements);
+
+ if (lastround != null)
+ {
+ foreach (BlockHierachyNode tmp in lastround)
+ {
+ foreach (BlockHierachyNode tmp2 in maxelements)
+ {
+ if (largerElements[tmp].Contains(tmp2))
+ {
+ if (!tmp.Children.Contains(tmp2)) tmp.Children.Add(tmp2);
+ if (!tmp2.Parents.Contains(tmp)) tmp2.Parents.Add(tmp);
+ }
+ }
+ }
+ }
+ else
+ {
+ Roots.AddRange(maxelements);
+ }
+ lastround = maxelements;
+ }
+ }
+
+
+ }
+
+ internal class BlockHierachy
+ {
+ public BlockHierachyNode RootNode = null;
+ readonly public Dictionary<Block, BlockHierachyNode> BlockToHierachyMap = new Dictionary<Block, BlockHierachyNode>();
+ readonly public Dictionary<Block, List<Block>> Dominators = new Dictionary<Block, List<Block>>();
+ readonly public Dictionary<Block, List<Block>> PostDominators = new Dictionary<Block, List<Block>>();
+ readonly public List<BlockHierachyNode> Leaves = new List<BlockHierachyNode>();
+
+ private Implementation m_Impl;
+
+ public BlockHierachy(Implementation impl, Block unifiedExit)
+ {
+ m_Impl = impl;
+ List<Block> blocks = impl.Blocks;
+ List<BlockHierachyNode> tmp_hnodes = new List<BlockHierachyNode>();
+ Dictionary<Block, List<Block>> unavoidable = new Dictionary<Block, List<Block>>();
+
+ BfsTraverser(blocks[0], true, Dominators);
+ BfsTraverser(unifiedExit, false, PostDominators);
+
+ foreach (Block b in blocks)
+ {
+ List<Block> l1 = Dominators[b];
+ List<Block> l2 = PostDominators[b];
+ unavoidable[b] = m_MergeLists(l1, l2);
+
+ BlockHierachyNode bhn = new BlockHierachyNode(b, unavoidable[b]);
+ bool found = false;
+ foreach (KeyValuePair<Block, BlockHierachyNode> kvp in BlockToHierachyMap)
+ {
+ if (BlockHierachyNode.Compare(kvp.Value, bhn) == 0) // using the overloaded compare operator
+ {
+ kvp.Value.Content.AddRange(bhn.Content);
+ BlockToHierachyMap[b] = kvp.Value;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ BlockToHierachyMap[b] = bhn;
+ tmp_hnodes.Add(bhn);
+ }
+ }
+
+ HasseDiagram hd = new HasseDiagram(tmp_hnodes);
+ Leaves = hd.Leaves;
+ }
+
+ public int GetMaxK(List<Block> blocks)
+ {
+ m_GetMaxK(blocks);
+ return (m_MaxK>0) ? m_MaxK : 1;
+ }
+
+ private int m_MaxK = 0;
+ private void m_GetMaxK(List<Block> blocks)
+ {
+ m_MaxK = 0;
+ Dictionary<Block, int> kstore = new Dictionary<Block, int>();
+ List<Block> todo = new List<Block>();
+ List<Block> done = new List<Block>();
+ todo.Add(m_Impl.Blocks[0]);
+ kstore[m_Impl.Blocks[0]] = 0;
+ int localmax;
+ Block current = null;
+ while (todo.Count > 0)
+ {
+ current = todo[0];
+ todo.Remove(current);
+ bool ready = true;
+ localmax = 0;
+ if (current.Predecessors!=null) {
+ foreach (Block p in current.Predecessors)
+ {
+ if (!done.Contains(p))
+ {
+ ready = false; break;
+ }
+ else localmax = (localmax > kstore[p]) ? localmax : kstore[p];
+ }
+ }
+ if (!ready)
+ {
+ todo.Add(current); continue;
+ }
+ done.Add(current);
+ kstore[current] = (blocks.Contains(current)) ? localmax +1 : localmax;
+
+ m_MaxK = (kstore[current] > m_MaxK) ? kstore[current] : m_MaxK;
+
+ GotoCmd gc = current.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ foreach (Block s in gc.labelTargets)
+ {
+ if (!todo.Contains(s)) todo.Add(s);
+ }
+ }
+ }
+
+ }
+
+ public List<Block> GetOtherDoomedBlocks(List<Block> doomedblocks)
+ {
+ List<Block> alsoDoomed = new List<Block>();
+ List<BlockHierachyNode> todo = new List<BlockHierachyNode>();
+ foreach (Block b in doomedblocks)
+ {
+ BlockToHierachyMap[b].Doomed = true;
+ todo.Add(BlockToHierachyMap[b]);
+ }
+
+ while (todo.Count > 0)
+ {
+ BlockHierachyNode current = todo[0];
+ todo.Remove(current);
+ if (!current.Doomed && current.Children.Count > 0)
+ {
+ bool childrenDoomed = true;
+ foreach (BlockHierachyNode c in current.Children)
+ {
+ if (!c.Doomed) { childrenDoomed = false; break; }
+ }
+ if (childrenDoomed) current.Doomed = true;
+ }
+
+ if (current.Doomed)
+ {
+ foreach (BlockHierachyNode p in current.Parents)
+ {
+ if (!todo.Contains(p)) todo.Add(p);
+ }
+ foreach (Block b in current.Content)
+ {
+ if (!alsoDoomed.Contains(b)) alsoDoomed.Add(b);
+ }
+ }
+ }
+
+ return alsoDoomed;
+ }
+
+ public void Impl2Dot(string filename)
+ {
+
+ Contract.Requires(filename != null);
+ List<string> nodes = new List<string>();
+ List<string> edges = new List<string>();
+
+ string nodestyle = "[shape=box];";
+
+ List<BlockHierachyNode> nl = new List<BlockHierachyNode>();
+ foreach (BlockHierachyNode h in BlockToHierachyMap.Values) if (!nl.Contains(h)) nl.Add(h);
+
+
+ foreach (BlockHierachyNode b in nl)
+ {
+ String l1 = "";
+ foreach (Block bl in b.Content) l1 = String.Format("{0}_{1}", l1, bl.Label);
+
+ Contract.Assert(b != null);
+ nodes.Add(string.Format("\"{0}\" {1}", l1, nodestyle));
+ foreach (BlockHierachyNode b_ in b.Children)
+ {
+
+ String l2 = "";
+ foreach (Block bl in b_.Content) l2 = String.Format("{0}_{1}", l2, bl.Label);
+ edges.Add(String.Format("\"{0}\" -> \"{1}\";", l1, l2));
+ }
+
+ }
+
+ using (StreamWriter sw = new StreamWriter(filename))
+ {
+ sw.WriteLine(String.Format("digraph {0} {{", "DISCO"));
+ // foreach (string! s in nodes) {
+ // sw.WriteLine(s);
+ // }
+ foreach (string s in edges)
+ {
+ Contract.Assert(s != null);
+ sw.WriteLine(s);
+ }
+ sw.WriteLine("}}");
+ sw.Close();
+ }
+ }
+
+ private void BfsTraverser(Block current, bool forward, Dictionary<Block, List<Block>> unavoidableBlocks)
+ {
+ List<Block> todo = new List<Block>();
+ List<Block> done = new List<Block>();
+ unavoidableBlocks[current] = new List<Block>();
+ //Debugger.Break();
+ todo.Add(current);
+ while (todo.Count > 0)
+ {
+ current = todo[0];
+ todo.Remove(current);
+ List<Block> pre = m_Predecessors(current, forward);
+ bool ready = true;
+ if (pre != null)
+ {
+ foreach (Block bpre in pre)
+ {
+ if (!done.Contains(bpre))
+ {
+ ready = false;
+ break;
+ }
+ }
+ }
+ if (!ready)
+ {
+ todo.Add(current);
+ continue;
+ }
+ done.Add(current);
+ unavoidableBlocks[current].Add(current);
+
+ List<Block> suc = m_Succecessors(current, forward);
+ if (suc == null) continue;
+ foreach (Block bsuc in suc)
+ {
+ if (unavoidableBlocks.ContainsKey(bsuc))
+ {
+ unavoidableBlocks[bsuc] = m_IntersectLists(unavoidableBlocks[bsuc], unavoidableBlocks[current]);
+ }
+ else
+ {
+ todo.Add(bsuc);
+ unavoidableBlocks[bsuc] = new List<Block>();
+ unavoidableBlocks[bsuc].AddRange(unavoidableBlocks[current]);
+ }
+
+ }
+ }
+
+ }
+
+ private List<Block> m_MergeLists(List<Block> lb1, List<Block> lb2)
+ {
+ List<Block> ret = new List<Block>();
+ ret.AddRange(lb1);
+ foreach (Block b in lb2)
+ {
+ if (!ret.Contains(b)) ret.Add(b);
+ }
+ return ret;
+ }
+
+ private List<Block> m_IntersectLists(List<Block> lb1, List<Block> lb2)
+ {
+ List<Block> ret = new List<Block>();
+ ret.AddRange(lb1);
+ foreach (Block b in lb2)
+ {
+ if (!lb1.Contains(b)) ret.Remove(b);
+ }
+ foreach (Block b in lb1)
+ {
+ if (ret.Contains(b) && !lb2.Contains(b)) ret.Remove(b);
+ }
+ return ret;
+ }
+
+ private List<Block> m_Predecessors(Block b, bool forward)
+ {
+ if (forward) return b.Predecessors;
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ return gc.labelTargets;
+ }
+ return null;
+ }
+
+ private List<Block> m_Succecessors(Block b, bool forward)
+ {
+ return m_Predecessors(b, !forward);
+ }
+
+
+ }
+
} \ No newline at end of file
diff --git a/Source/Doomed/VCDoomed.cs b/Source/Doomed/VCDoomed.cs
index d4d4db21..822fb9c0 100644
--- a/Source/Doomed/VCDoomed.cs
+++ b/Source/Doomed/VCDoomed.cs
@@ -1,826 +1,826 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC {
- public partial class DCGen : ConditionGeneration {
- private bool _print_time = CommandLineOptions.Clo.DoomStrategy!=-1;
- #region Attributes
- static private Dictionary<Block, Variable/*!*/>/*!*/ m_BlockReachabilityMap;
- Dictionary<Block/*!*/, Block/*!*/>/*!*/ m_copiedBlocks = new Dictionary<Block/*!*/, Block/*!*/>();
- const string reachvarsuffix = "__ivebeenthere";
- List<Cmd/*!*/>/*!*/ m_doomedCmds = new List<Cmd/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
-
- }
-
- #endregion
-
-
- /// <summary>
- /// Constructor. Initializes the theorem prover.
- /// </summary>
- public DCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
- : base(program, checkers) {
- Contract.Requires(program != null);
-
- this.appendLogFile = appendLogFile;
- this.logFilePath = logFilePath;
- m_BlockReachabilityMap = new Dictionary<Block, Variable>();
- }
-
- /// <summary>
- /// Debug method that prints a dot file of the
- /// current set of blocks in impl to filename.
- /// </summary>
- private void Impl2Dot(Implementation impl, string filename) {
- Contract.Requires(impl != null);
- Contract.Requires(filename != null);
- List<string> nodes = new List<string>();
- List<string> edges = new List<string>();
-
- string nodestyle = "[shape=box];";
-
- foreach (Block b in impl.Blocks) {
- Contract.Assert(b != null);
- nodes.Add(string.Format("\"{0}\" {1}", b.Label, nodestyle));
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (gc != null)
- {
- Contract.Assert(gc.labelTargets != null);
- foreach (Block b_ in gc.labelTargets)
- {
- Contract.Assert(b_ != null);
- edges.Add(String.Format("\"{0}\" -> \"{1}\";", b.Label, b_.Label));
- }
- }
-
- //foreach (Block b_ in b.Predecessors)
- //{
- // edges.Add(String.Format("\"{0}\" -> \"{1}\";", b.Label, b_.Label));
- //}
- }
-
- using (StreamWriter sw = new StreamWriter(filename)) {
- sw.WriteLine(String.Format("digraph {0} {{", impl.Name));
- // foreach (string! s in nodes) {
- // sw.WriteLine(s);
- // }
- foreach (string s in edges) {
- Contract.Assert(s != null);
- sw.WriteLine(s);
- }
- sw.WriteLine("}}");
- sw.Close();
- }
- }
- private const string _copyPrefix = "CPY__";
-
- private List<Block> m_UncheckableBlocks = null;
-
- /// <summary>
- /// MSchaef:
- /// - remove loops and add reach variables
- /// - make it a passive program
- /// - compute the wlp for each block
- /// - check if |= (reach=false) => wlp.S.false holds for each reach
- ///
- /// </summary>
- public override Outcome VerifyImplementation(Implementation impl, VerifierCallback callback) {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- Console.WriteLine();
- Console.WriteLine("Checking function {0}", impl.Name);
- callback.OnProgress("doomdetector", 0, 0, 0);
-
- bool restartTP = CommandLineOptions.Clo.DoomRestartTP ;
-
- //Impl2Dot(impl, String.Format("c:/dot/{0}_orig.dot", impl.Name));
-
- Transform4DoomedCheck(impl);
-
- //Impl2Dot(impl, String.Format("c:/dot/{0}_fin.dot", impl.Name));
-
- Checker checker = FindCheckerFor(1000);
- Contract.Assert(checker != null);
- int assertionCount;
- DoomCheck dc = new DoomCheck(impl, this.exitBlock, checker, m_UncheckableBlocks, out assertionCount);
- CumulativeAssertionCount += assertionCount;
-
- //EmitImpl(impl, false);
-
- int _totalchecks = 0;
-
- ProverInterface.Outcome outcome;
- dc.ErrorHandler = new DoomErrorHandler(dc.Label2Absy, callback);
-
- System.TimeSpan ts = new TimeSpan();
-
- if (_print_time) Console.WriteLine("Total number of blocks {0}", impl.Blocks.Count);
-
- List<Block> lb;
- List<Variable> lv = new List<Variable>();
-
- while (dc.GetNextBlock(out lb))
- {
- Contract.Assert(lb != null);
- outcome = ProverInterface.Outcome.Undetermined;
-
- Variable v = null;
- lv.Clear();
-
- foreach (Block b_ in lb)
- {
- if (!m_BlockReachabilityMap.TryGetValue(b_, out v))
- {
- // This should cause an error
- continue;
- }
- //Console.Write("{0}, ",b_.Label);
- lv.Add(v);
- }
- //Console.WriteLine();
- Dictionary<Expr, int> finalreachvars = m_GetPostconditionVariables(impl.Blocks,lb);
- if (lv.Count < 1)
- {
-
- continue;
- }
-
- Contract.Assert(lv != null);
- _totalchecks++;
-
-
- if (!dc.CheckLabel(lv,finalreachvars, out outcome)) {
- return Outcome.Inconclusive;
- }
- ts += dc.DEBUG_ProverTime.Elapsed;
-
- if (restartTP)
- {
- checker.Close();
- checker = FindCheckerFor(1000);
- dc.RespawnChecker(impl, checker);
- dc.ErrorHandler = new DoomErrorHandler(dc.Label2Absy, callback);
- }
-
- }
- checker.Close();
-
- if (_print_time)
- {
- Console.WriteLine("Number of Checkes / #Blocks: {0} of {1}", _totalchecks, impl.Blocks.Count);
- dc.__DEBUG_PrintStatistics();
- Console.WriteLine("Total time for this method: {0}", ts.ToString());
- }
- #region Try to produce a counter example (brute force)
- if (dc.DoomedSequences.Count > 0) {
- int counter = 0;
- List<Block> _all = new List<Block>();
- foreach (List<Block> lb_ in dc.DoomedSequences)
- {
- foreach (Block b_ in lb_)
- {
- if (!_all.Contains(b_) && !m_UncheckableBlocks.Contains(b_))
- {
- _all.Add(b_); counter++;
- if (!_print_time) Console.WriteLine(b_.Label);
- }
- }
- }
- if (_all.Count > 0)
- {
- Console.WriteLine("#Dead Blocks found: {0}: ", counter);
- return Outcome.Errors;
- }
- }
- #endregion
-
-
- return Outcome.Correct;
- }
-
- private Dictionary<Expr, int> m_GetPostconditionVariables(List<Block> allblock, List<Block> passBlock)
- {
- Dictionary<Expr, int> r = new Dictionary<Expr, int>();
- foreach (Block b in allblock)
- {
- Variable v;
- if (m_BlockReachabilityMap.TryGetValue(b, out v))
- {
- if (passBlock.Contains(b)) r[m_LastReachVarIncarnation[v]] = 1;
- }
- else
- {
- Console.WriteLine("there is no reachability variable for {0}", b.Label);
- }
- }
- return r;
- }
-
-#if false
- #region Error message construction
- private void SearchCounterexample(Implementation impl, DoomErrorHandler errh, VerifierCallback callback) {
- Contract.Requires(impl != null);
- Contract.Requires(errh != null);
- Contract.Requires(callback != null);
- Contract.Requires(errh.m_Reachvar != null);
- //if (errh.m_Reachvar==null) {
- // Contract.Assert(false);throw new cce.UnreachableException();
- //}
- m_doomedCmds.Clear();
-
- Dictionary<Block, List<Cmd>> cmdbackup = new Dictionary<Block, List<Cmd>>();
-
- BruteForceCESearch(errh.m_Reachvar, impl, callback, cmdbackup, 0, impl.Blocks.Count / 2 - 1);
- BruteForceCESearch(errh.m_Reachvar, impl, callback, cmdbackup, impl.Blocks.Count / 2, impl.Blocks.Count - 1);
-
- List<Cmd> causals = CollectCausalStatements(impl.Blocks[0]);
- foreach (Cmd c in causals) {
- Contract.Assert(c != null);
- GenerateErrorMessage(c, causals);
- }
-
- #region Undo all modifications
- foreach (KeyValuePair<Block, List<Cmd>> kvp in cmdbackup) {
- Contract.Assert(kvp.Key != null);
- Contract.Assert(kvp.Value != null);
- kvp.Key.Cmds = kvp.Value;
- }
- #endregion
- }
-
- #region Causal Statement Tree
-
- private void GenerateErrorMessage(Cmd causalStatement, List<Cmd> causals) {
- Contract.Requires(causalStatement != null);
- Contract.Requires(cce.NonNullElements(causals));
- AssumeCmd uc = causalStatement as AssumeCmd;
- AssertCmd ac = causalStatement as AssertCmd;
- ConsoleColor col = Console.ForegroundColor;
-
- // Trivial case. Must be either assume or assert false
- if (m_doomedCmds.Count == 1) {
- Console.WriteLine("Found a trivial error:");
- if (uc != null) {
- Console.Write("Trivial false assumption: ");
- Console.Write("({0};{1}):", uc.tok.line, uc.tok.col);
- }
- if (ac != null) {
- Console.Write("Trivial false assertion: ");
- Console.Write("({0};{1}):", ac.tok.line, ac.tok.col);
- }
- causalStatement.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
- } else {
- // Safety error
- if (ac != null) {
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine("Safety error:");
- Console.ForegroundColor = col;
- Console.Write("This assertion is violated: ");
- Console.Write("({0};{1}):", ac.tok.line, ac.tok.col);
- ac.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
- }
- if (uc != null) {
- bool containsAssert = false;
- foreach (Cmd c in m_doomedCmds) {
- Contract.Assert(c != null);
- if (causals.Contains(c)) {
- continue;
- }
- AssertCmd asrt = c as AssertCmd;
- if (asrt != null) {
- containsAssert = true;
- break;
- }
- }
- // Plausibility error
- if (containsAssert) {
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine("Plausibility error:");
- Console.ForegroundColor = col;
- Console.Write("There is no legal exeuction passing: ");
- Console.Write("({0};{1})", uc.tok.line, uc.tok.col);
- uc.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
- } else { // Reachability error
- Console.ForegroundColor = ConsoleColor.DarkRed;
- Console.WriteLine("Reachability error:");
- Console.ForegroundColor = col;
- Console.Write("No execution can reach: ");
- Console.Write("({0};{1})", uc.tok.line, uc.tok.col);
- uc.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
- }
-
- }
-
- Console.ForegroundColor = ConsoleColor.White;
- Console.WriteLine("...on any execution passing through:");
- foreach (Cmd c in m_doomedCmds) {
- Contract.Assert(c != null);
- if (causals.Contains(c)) {
- continue;
- }
- Console.ForegroundColor = col;
- Console.Write("In ({0};{1}): ", c.tok.line, c.tok.col);
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- c.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
- }
- Console.ForegroundColor = col;
- Console.WriteLine("--");
-
- }
- }
-
- private List<Cmd> CollectCausalStatements(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Cmd>>()));
-
- Cmd lastCausal = null;
- foreach (Cmd c in b.Cmds) {
- Contract.Assert(c != null);
- AssertCmd ac = c as AssertCmd;
- AssumeCmd uc = c as AssumeCmd;
- if (ac != null && !ContainsReachVariable(ac)) {
- if (ac.Expr != Expr.True) {
- lastCausal = c;
- }
- } else if (uc != null && !ContainsReachVariable(uc)) {
- lastCausal = c;
- }
- }
-
- List<Cmd> causals = new List<Cmd>();
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (gc != null && gc.labelTargets != null) {
- List<Cmd> tmp;
- //bool allcausal = true;
- foreach (Block b_ in gc.labelTargets) {
- Contract.Assert(b_ != null);
- tmp = CollectCausalStatements(b_);
-
- foreach (Cmd cau in tmp) {
- if (!causals.Contains(cau))
- causals.Add(cau);
- }
- }
- //if (allcausal)
- if (causals.Count > 0)
- return causals;
- }
- if (lastCausal != null)
- causals.Add(lastCausal);
- return causals;
- }
-
- #endregion
-
- bool BruteForceCESearch(Variable reachvar, Implementation impl, VerifierCallback callback,
- Dictionary<Block, List<Cmd>> cmdbackup, int startidx, int endidx) {
- Contract.Requires(reachvar != null);
- Contract.Requires(impl != null);
- Contract.Requires(callback != null);
- Contract.Requires(cce.NonNullElements(cmdbackup));
- #region Modify implementation
- for (int i = startidx; i <= endidx; i++) {
- if (_copiedBlock.Contains(impl.Blocks[i]))
- continue;
- List<Cmd> cs = new List<Cmd>();
- cmdbackup.Add(impl.Blocks[i], impl.Blocks[i].Cmds);
- foreach (Cmd c in impl.Blocks[i].Cmds) {
- Contract.Assert(c != null);
- if (ContainsReachVariable(c)) {
- cs.Add(c);
- continue;
- }
- AssertCmd ac = c as AssertCmd;
- AssumeCmd uc = c as AssumeCmd;
- if (ac != null) {
- cs.Add(new AssertCmd(ac.tok, Expr.True));
- } else if (uc != null) {
- cs.Add(new AssertCmd(uc.tok, Expr.True));
- } else {
- cs.Add(c);
- }
- }
- impl.Blocks[i].Cmds = cs;
- }
- #endregion
-
- ProverInterface.Outcome outcome = ProverInterface.Outcome.Undetermined;
- if (!ReCheckImpl(reachvar, impl, callback, out outcome)) {
- UndoBlockModifications(impl, cmdbackup, startidx, endidx);
- return false;
- }
- if (outcome == ProverInterface.Outcome.Valid) {
- return true;
- } else if (outcome == ProverInterface.Outcome.Invalid) {
- UndoBlockModifications(impl, cmdbackup, startidx, endidx);
- int mid = startidx + (endidx - startidx) / 2;
- if (startidx >= endidx) {
- // Now we found an interesting Block and we have to
- // search for the interesting statements.
- int cmdcount = impl.Blocks[endidx].Cmds.Length;
- BruteForceCmd(impl.Blocks[endidx], 0, cmdcount / 2 - 1, reachvar, impl, callback);
- BruteForceCmd(impl.Blocks[endidx], cmdcount / 2, cmdcount - 1, reachvar, impl, callback);
- return true;
- } else {
- BruteForceCESearch(reachvar, impl, callback, cmdbackup, startidx, mid);
- BruteForceCESearch(reachvar, impl, callback, cmdbackup, mid + 1, endidx);
- return true;
- }
- } else {
- UndoBlockModifications(impl, cmdbackup, startidx, endidx);
- return false;
- }
- }
-
- bool BruteForceCmd(Block b, int startidx, int endidx, Variable reachvar,
- Implementation impl, VerifierCallback callback) {
- Contract.Requires(b != null);
- Contract.Requires(reachvar != null);
- Contract.Requires(impl != null);
- Contract.Requires(callback != null);
- #region Modify Cmds
- List<Cmd> backup = b.Cmds;
- Contract.Assert(backup != null);
- List<Cmd> cs = new List<Cmd>();
- for (int i = 0; i < startidx; i++) {
- cs.Add(b.Cmds[i]);
- }
- for (int i = startidx; i <= endidx; i++) {
- Cmd c = b.Cmds[i];
- if (ContainsReachVariable(c)) {
- cs.Add(c);
- continue;
- }
- cs.Add(new AssertCmd(c.tok, Expr.True));
- }
- for (int i = endidx + 1; i < b.Cmds.Length; i++) {
- cs.Add(b.Cmds[i]);
- }
-
- b.Cmds = cs;
- #endregion
-
- #region Recheck
- ProverInterface.Outcome outcome = ProverInterface.Outcome.Undetermined;
- if (!ReCheckImpl(reachvar, impl, callback, out outcome)) {
- b.Cmds = backup;
- return false;
- }
- #endregion
-
- if (outcome == ProverInterface.Outcome.Valid) {
- return true;
- } else if (outcome == ProverInterface.Outcome.Invalid) {
- b.Cmds = backup;
- if (startidx >= endidx) {
- if (!ContainsReachVariable(b.Cmds[endidx])) {
- // Console.Write(" Witness (");
- //
- // ConsoleColor col = Console.ForegroundColor;
- // Console.ForegroundColor = ConsoleColor.White;
- // Console.Write("{0};{1}", b.Cmds[endidx].tok.line, b.Cmds[endidx].tok.col );
- // Console.ForegroundColor = col;
- // Console.Write("): ");
- // Console.ForegroundColor = ConsoleColor.Yellow;
- // b.Cmds[endidx].Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
- // Console.ForegroundColor = col;
-
- m_doomedCmds.Add(b.Cmds[endidx]);
- return true;
- } else {
- return false;
- }
- } else {
- int mid = startidx + (endidx - startidx) / 2;
- BruteForceCmd(b, startidx, mid, reachvar, impl, callback);
- BruteForceCmd(b, mid + 1, endidx, reachvar, impl, callback);
- return false; // This is pure random
- }
- } else {
- b.Cmds = backup;
- return false;
- }
- }
-
- void UndoBlockModifications(Implementation impl, Dictionary<Block/*!*/, List<Cmd>/*!*/>/*!*/ cmdbackup,
- int startidx, int endidx) {
- Contract.Requires(cce.NonNullElements(cmdbackup));
- Contract.Requires(impl != null);
- for (int i = startidx; i <= endidx; i++) {
- List<Cmd> cs = null;
- if (cmdbackup.TryGetValue(impl.Blocks[i], out cs)) {
- Contract.Assert(cs != null);
- impl.Blocks[i].Cmds = cs;
- cmdbackup.Remove(impl.Blocks[i]);
- }
- }
- }
-
- bool ReCheckImpl(Variable reachvar, Implementation impl, VerifierCallback callback,
- out ProverInterface.Outcome outcome) {
- Contract.Requires(reachvar != null);
- Contract.Requires(impl != null);
- Contract.Requires(callback != null);
- Checker checker = FindCheckerFor(impl, 1000);
- Contract.Assert(checker != null);
- DoomCheck dc = new DoomCheck(impl, this.exitBlock, checker, m_UncheckableBlocks);
- dc.ErrorHandler = new DoomErrorHandler(dc.Label2Absy, callback);
- outcome = ProverInterface.Outcome.Undetermined;
- List<Variable> rv = new List<Variable>();
- rv.Add(reachvar);
- if (!dc.CheckLabel(rv,null, out outcome)) {
- checker.Close();
- return false;
- }
- checker.Close();
- return true;
- }
-
-
-
- bool ContainsReachVariable(Cmd c) {
- Contract.Requires(c != null);
- AssertCmd artc = c as AssertCmd;
- AssumeCmd amec = c as AssumeCmd;
- Expr e;
- if (artc != null) {
- e = artc.Expr;
- } else if (amec != null) {
- e = amec.Expr;
- } else {
- return false;
- }
- Set freevars = new Set();
- e.ComputeFreeVariables(freevars);
- foreach (Variable v in freevars) {
- Contract.Assert(v != null);
- if (v.Name.Contains(reachvarsuffix))
- return true;
- }
- return false;
- }
-#endregion
-#endif
-
-
- Block exitBlock;
-
- #region Program Passification
- private void GenerateHelperBlocks(Implementation impl) {
- Contract.Requires(impl != null);
- Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>();
- exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins);
- Contract.Assert(exitBlock != null);
-
- AddBlocksBetween(impl.Blocks);
-
- #region Insert pre- and post-conditions and where clauses as assume and assert statements
- {
- List<Cmd> cc = new List<Cmd>();
- // where clauses of global variables
- foreach (var gvar in program.GlobalVariables) {
- if (gvar.TypedIdent.WhereExpr != null) {
- Cmd c = new AssumeCmd(gvar.tok, gvar.TypedIdent.WhereExpr);
- cc.Add(c);
- }
- }
- // where clauses of in- and out-parameters
- cc.AddRange(GetParamWhereClauses(impl));
- // where clauses of local variables
- foreach (Variable lvar in impl.LocVars) {
- Contract.Assert(lvar != null);
- if (lvar.TypedIdent.WhereExpr != null) {
- Cmd c = new AssumeCmd(lvar.tok, lvar.TypedIdent.WhereExpr);
- cc.Add(c);
- }
- }
-
- // add cc and the preconditions to new blocks preceding impl.Blocks[0]
- InjectPreconditions(impl, cc);
-
- // append postconditions, starting in exitBlock and continuing into other blocks, if needed
- InjectPostConditions(impl, exitBlock, gotoCmdOrigins);
- }
- #endregion
- }
-
-
- private Dictionary<Variable, Expr> PassifyProgram(Implementation impl, ModelViewInfo mvInfo) {
- Contract.Requires(impl != null);
- Contract.Requires(mvInfo != null);
- Contract.Requires(this.exitBlock != null);
- Contract.Ensures(Contract.Result<Hashtable>() != null);
-
- CurrentLocalVariables = impl.LocVars;
- return Convert2PassiveCmd(impl, mvInfo);
- //return new Hashtable();
- }
-
- /// <summary>
- /// Add additional variable to allow checking as described in the paper
- /// "It's doomed; we can prove it"
- /// </summary>
- private List<Cmd> GenerateReachabilityPredicates(Implementation impl)
- {
- Contract.Requires(impl != null);
-
- foreach (Block b in impl.Blocks)
- {
- Contract.Assert(b != null);
- //if (b.Predecessors.Length==0) continue;
- //if (b.Cmds.Length == 0 ) continue;
-
- Variable v_ = new LocalVariable(Token.NoToken,
- new TypedIdent(b.tok, b.Label + reachvarsuffix, new BasicType(SimpleType.Int )));
-
- impl.LocVars.Add(v_);
-
- m_BlockReachabilityMap[b] = v_;
-
- IdentifierExpr lhs = new IdentifierExpr(b.tok, v_);
- Contract.Assert(lhs != null);
-
- impl.Proc.Modifies.Add(lhs);
-
- List<AssignLhs> lhsl = new List<AssignLhs>();
- lhsl.Add(new SimpleAssignLhs(Token.NoToken, lhs));
- List<Expr> rhsl = new List<Expr>();
- rhsl.Add(Expr.Literal(1) );
-
-
- List<Cmd> cs = new List<Cmd> { new AssignCmd(Token.NoToken, lhsl, rhsl) };
- cs.AddRange(b.Cmds);
- b.Cmds = cs;
-
- //checkBlocks.Add(new CheckableBlock(v_,b));
- }
-
- List<Cmd> incReachVars = new List<Cmd>();
- foreach (KeyValuePair<Block, Variable> kvp in m_BlockReachabilityMap)
- {
- IdentifierExpr lhs = new IdentifierExpr(Token.NoToken, kvp.Value);
- impl.Proc.Modifies.Add(lhs);
- incReachVars.Add(new AssumeCmd(Token.NoToken, Expr.Le(lhs, Expr.Literal(1))));
- }
-
- return incReachVars;
- }
-
- #endregion
-
- #region Compute loop-free approximation
-
- // this might be redundant, but I didn't find a better place to get this information.
- private Dictionary<Variable, Expr> m_LastReachVarIncarnation = new Dictionary<Variable, Expr>();
-
- private void Transform4DoomedCheck(Implementation impl)
- {
- variable2SequenceNumber = new Dictionary<Variable, int>();
- incarnationOriginMap = new Dictionary<Incarnation, Absy>();
- if (impl.Blocks.Count < 1) return;
-
- impl.PruneUnreachableBlocks();
- AddBlocksBetween(impl.Blocks);
- ResetPredecessors(impl.Blocks);
-
- GraphAnalyzer ga = new GraphAnalyzer(impl.Blocks);
- LoopRemover lr = new LoopRemover(ga);
- lr.AbstractLoopUnrolling();
-
- impl.Blocks = ga.ToImplementation(out m_UncheckableBlocks);
- ResetPredecessors(impl.Blocks);
-
- // Check for the "BlocksBetween" if all their successors are in m_UncheckableBlocks
- List<Block> oldblocks = new List<Block>();
- oldblocks.AddRange(impl.Blocks);
- GenerateHelperBlocks(impl);
- #region Check for the "BlocksBetween" if all their successors are in m_UncheckableBlocks
- foreach (Block b in impl.Blocks)
- {
- if (oldblocks.Contains(b)) continue;
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (gc != null)
- {
- bool allsuccUncheckable = true;
- foreach (Block _b in gc.labelTargets)
- {
- if (!m_UncheckableBlocks.Contains(_b))
- {
- allsuccUncheckable = false; break;
- }
- }
- if (allsuccUncheckable && !m_UncheckableBlocks.Contains(b)) m_UncheckableBlocks.Add(b);
- }
- }
- #endregion
-
- impl.Blocks = DeepCopyBlocks(impl.Blocks, m_UncheckableBlocks);
-
- m_BlockReachabilityMap = new Dictionary<Block, Variable>();
- List<Cmd> cs = GenerateReachabilityPredicates(impl);
-
- //foreach (Block test in getTheFFinalBlock(impl.Blocks[0]))
- //{
- // test.Cmds.AddRange(cs);
- //}
-
- ResetPredecessors(impl.Blocks);
- //EmitImpl(impl,false);
-
- Dictionary<Variable, Expr> var2Expr = PassifyProgram(impl, new ModelViewInfo(program, impl));
-
- // Collect the last incarnation of each reachability variable in the passive program
- foreach (KeyValuePair<Block, Variable> kvp in m_BlockReachabilityMap)
- {
- if (var2Expr.ContainsKey(kvp.Value))
- {
- m_LastReachVarIncarnation[kvp.Value] = (Expr)var2Expr[kvp.Value];
- }
- }
- }
-
-
- List<Block> getTheFFinalBlock(Block b)
- {
- List<Block> lb = new List<Block>();
- GotoCmd gc = b.TransferCmd as GotoCmd;
- if (gc == null) lb.Add(b);
- else
- {
- foreach (Block s in gc.labelTargets)
- {
- foreach (Block r in getTheFFinalBlock(s)) if (!lb.Contains(r)) lb.Add(r);
- }
- }
- return lb;
- }
-
-
- private List<Block> DeepCopyBlocks(List<Block> lb, List<Block> uncheckables)
- {
- List<Block> clones = new List<Block>();
- List<Block> uncheck_ = new List<Block>();
- Dictionary<Block, Block> clonemap = new Dictionary<Block, Block>();
-
- foreach (Block b in lb)
- {
- Block clone = CloneBlock(b);
- clones.Add(clone);
- clonemap[b] = clone;
- if (uncheckables.Contains(b)) uncheck_.Add(clone);
- }
- uncheckables.Clear();
- uncheckables.AddRange(uncheck_);
- // update the successors and predecessors
- foreach (Block b in lb)
- {
- List<Block> newpreds = new List<Block>();
- foreach (Block b_ in b.Predecessors)
- {
- newpreds.Add(clonemap[b_]);
- }
- clonemap[b].Predecessors = newpreds;
- GotoCmd gc = b.TransferCmd as GotoCmd;
- ReturnCmd rc = b.TransferCmd as ReturnCmd;
- if (gc != null)
- {
- List<String> lseq = new List<String>();
- List<Block> bseq = new List<Block>();
- foreach (string s in gc.labelNames) lseq.Add(s);
- foreach (Block b_ in gc.labelTargets) bseq.Add(clonemap[b_]);
- GotoCmd tcmd = new GotoCmd(gc.tok, lseq, bseq);
- clonemap[b].TransferCmd = tcmd;
- }
- else if (rc != null)
- {
- clonemap[b].TransferCmd = new ReturnCmd(rc.tok);
- }
- }
- return clones;
- }
-
- private Block CloneBlock(Block b)
- {
- Block clone = new Block(b.tok, b.Label, b.Cmds, b.TransferCmd);
- if (this.exitBlock == b) this.exitBlock = clone;
- return clone;
- }
- #endregion
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC {
+ public partial class DCGen : ConditionGeneration {
+ private bool _print_time = CommandLineOptions.Clo.DoomStrategy!=-1;
+ #region Attributes
+ static private Dictionary<Block, Variable/*!*/>/*!*/ m_BlockReachabilityMap;
+ Dictionary<Block/*!*/, Block/*!*/>/*!*/ m_copiedBlocks = new Dictionary<Block/*!*/, Block/*!*/>();
+ const string reachvarsuffix = "__ivebeenthere";
+ List<Cmd/*!*/>/*!*/ m_doomedCmds = new List<Cmd/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+
+ }
+
+ #endregion
+
+
+ /// <summary>
+ /// Constructor. Initializes the theorem prover.
+ /// </summary>
+ public DCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
+ : base(program, checkers) {
+ Contract.Requires(program != null);
+
+ this.appendLogFile = appendLogFile;
+ this.logFilePath = logFilePath;
+ m_BlockReachabilityMap = new Dictionary<Block, Variable>();
+ }
+
+ /// <summary>
+ /// Debug method that prints a dot file of the
+ /// current set of blocks in impl to filename.
+ /// </summary>
+ private void Impl2Dot(Implementation impl, string filename) {
+ Contract.Requires(impl != null);
+ Contract.Requires(filename != null);
+ List<string> nodes = new List<string>();
+ List<string> edges = new List<string>();
+
+ string nodestyle = "[shape=box];";
+
+ foreach (Block b in impl.Blocks) {
+ Contract.Assert(b != null);
+ nodes.Add(string.Format("\"{0}\" {1}", b.Label, nodestyle));
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ Contract.Assert(gc.labelTargets != null);
+ foreach (Block b_ in gc.labelTargets)
+ {
+ Contract.Assert(b_ != null);
+ edges.Add(String.Format("\"{0}\" -> \"{1}\";", b.Label, b_.Label));
+ }
+ }
+
+ //foreach (Block b_ in b.Predecessors)
+ //{
+ // edges.Add(String.Format("\"{0}\" -> \"{1}\";", b.Label, b_.Label));
+ //}
+ }
+
+ using (StreamWriter sw = new StreamWriter(filename)) {
+ sw.WriteLine(String.Format("digraph {0} {{", impl.Name));
+ // foreach (string! s in nodes) {
+ // sw.WriteLine(s);
+ // }
+ foreach (string s in edges) {
+ Contract.Assert(s != null);
+ sw.WriteLine(s);
+ }
+ sw.WriteLine("}}");
+ sw.Close();
+ }
+ }
+ private const string _copyPrefix = "CPY__";
+
+ private List<Block> m_UncheckableBlocks = null;
+
+ /// <summary>
+ /// MSchaef:
+ /// - remove loops and add reach variables
+ /// - make it a passive program
+ /// - compute the wlp for each block
+ /// - check if |= (reach=false) => wlp.S.false holds for each reach
+ ///
+ /// </summary>
+ public override Outcome VerifyImplementation(Implementation impl, VerifierCallback callback) {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ Console.WriteLine();
+ Console.WriteLine("Checking function {0}", impl.Name);
+ callback.OnProgress("doomdetector", 0, 0, 0);
+
+ bool restartTP = CommandLineOptions.Clo.DoomRestartTP ;
+
+ //Impl2Dot(impl, String.Format("c:/dot/{0}_orig.dot", impl.Name));
+
+ Transform4DoomedCheck(impl);
+
+ //Impl2Dot(impl, String.Format("c:/dot/{0}_fin.dot", impl.Name));
+
+ Checker checker = FindCheckerFor(1000);
+ Contract.Assert(checker != null);
+ int assertionCount;
+ DoomCheck dc = new DoomCheck(impl, this.exitBlock, checker, m_UncheckableBlocks, out assertionCount);
+ CumulativeAssertionCount += assertionCount;
+
+ //EmitImpl(impl, false);
+
+ int _totalchecks = 0;
+
+ ProverInterface.Outcome outcome;
+ dc.ErrorHandler = new DoomErrorHandler(dc.Label2Absy, callback);
+
+ System.TimeSpan ts = new TimeSpan();
+
+ if (_print_time) Console.WriteLine("Total number of blocks {0}", impl.Blocks.Count);
+
+ List<Block> lb;
+ List<Variable> lv = new List<Variable>();
+
+ while (dc.GetNextBlock(out lb))
+ {
+ Contract.Assert(lb != null);
+ outcome = ProverInterface.Outcome.Undetermined;
+
+ Variable v = null;
+ lv.Clear();
+
+ foreach (Block b_ in lb)
+ {
+ if (!m_BlockReachabilityMap.TryGetValue(b_, out v))
+ {
+ // This should cause an error
+ continue;
+ }
+ //Console.Write("{0}, ",b_.Label);
+ lv.Add(v);
+ }
+ //Console.WriteLine();
+ Dictionary<Expr, int> finalreachvars = m_GetPostconditionVariables(impl.Blocks,lb);
+ if (lv.Count < 1)
+ {
+
+ continue;
+ }
+
+ Contract.Assert(lv != null);
+ _totalchecks++;
+
+
+ if (!dc.CheckLabel(lv,finalreachvars, out outcome)) {
+ return Outcome.Inconclusive;
+ }
+ ts += dc.DEBUG_ProverTime.Elapsed;
+
+ if (restartTP)
+ {
+ checker.Close();
+ checker = FindCheckerFor(1000);
+ dc.RespawnChecker(impl, checker);
+ dc.ErrorHandler = new DoomErrorHandler(dc.Label2Absy, callback);
+ }
+
+ }
+ checker.Close();
+
+ if (_print_time)
+ {
+ Console.WriteLine("Number of Checkes / #Blocks: {0} of {1}", _totalchecks, impl.Blocks.Count);
+ dc.__DEBUG_PrintStatistics();
+ Console.WriteLine("Total time for this method: {0}", ts.ToString());
+ }
+ #region Try to produce a counter example (brute force)
+ if (dc.DoomedSequences.Count > 0) {
+ int counter = 0;
+ List<Block> _all = new List<Block>();
+ foreach (List<Block> lb_ in dc.DoomedSequences)
+ {
+ foreach (Block b_ in lb_)
+ {
+ if (!_all.Contains(b_) && !m_UncheckableBlocks.Contains(b_))
+ {
+ _all.Add(b_); counter++;
+ if (!_print_time) Console.WriteLine(b_.Label);
+ }
+ }
+ }
+ if (_all.Count > 0)
+ {
+ Console.WriteLine("#Dead Blocks found: {0}: ", counter);
+ return Outcome.Errors;
+ }
+ }
+ #endregion
+
+
+ return Outcome.Correct;
+ }
+
+ private Dictionary<Expr, int> m_GetPostconditionVariables(List<Block> allblock, List<Block> passBlock)
+ {
+ Dictionary<Expr, int> r = new Dictionary<Expr, int>();
+ foreach (Block b in allblock)
+ {
+ Variable v;
+ if (m_BlockReachabilityMap.TryGetValue(b, out v))
+ {
+ if (passBlock.Contains(b)) r[m_LastReachVarIncarnation[v]] = 1;
+ }
+ else
+ {
+ Console.WriteLine("there is no reachability variable for {0}", b.Label);
+ }
+ }
+ return r;
+ }
+
+#if false
+ #region Error message construction
+ private void SearchCounterexample(Implementation impl, DoomErrorHandler errh, VerifierCallback callback) {
+ Contract.Requires(impl != null);
+ Contract.Requires(errh != null);
+ Contract.Requires(callback != null);
+ Contract.Requires(errh.m_Reachvar != null);
+ //if (errh.m_Reachvar==null) {
+ // Contract.Assert(false);throw new cce.UnreachableException();
+ //}
+ m_doomedCmds.Clear();
+
+ Dictionary<Block, List<Cmd>> cmdbackup = new Dictionary<Block, List<Cmd>>();
+
+ BruteForceCESearch(errh.m_Reachvar, impl, callback, cmdbackup, 0, impl.Blocks.Count / 2 - 1);
+ BruteForceCESearch(errh.m_Reachvar, impl, callback, cmdbackup, impl.Blocks.Count / 2, impl.Blocks.Count - 1);
+
+ List<Cmd> causals = CollectCausalStatements(impl.Blocks[0]);
+ foreach (Cmd c in causals) {
+ Contract.Assert(c != null);
+ GenerateErrorMessage(c, causals);
+ }
+
+ #region Undo all modifications
+ foreach (KeyValuePair<Block, List<Cmd>> kvp in cmdbackup) {
+ Contract.Assert(kvp.Key != null);
+ Contract.Assert(kvp.Value != null);
+ kvp.Key.Cmds = kvp.Value;
+ }
+ #endregion
+ }
+
+ #region Causal Statement Tree
+
+ private void GenerateErrorMessage(Cmd causalStatement, List<Cmd> causals) {
+ Contract.Requires(causalStatement != null);
+ Contract.Requires(cce.NonNullElements(causals));
+ AssumeCmd uc = causalStatement as AssumeCmd;
+ AssertCmd ac = causalStatement as AssertCmd;
+ ConsoleColor col = Console.ForegroundColor;
+
+ // Trivial case. Must be either assume or assert false
+ if (m_doomedCmds.Count == 1) {
+ Console.WriteLine("Found a trivial error:");
+ if (uc != null) {
+ Console.Write("Trivial false assumption: ");
+ Console.Write("({0};{1}):", uc.tok.line, uc.tok.col);
+ }
+ if (ac != null) {
+ Console.Write("Trivial false assertion: ");
+ Console.Write("({0};{1}):", ac.tok.line, ac.tok.col);
+ }
+ causalStatement.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ } else {
+ // Safety error
+ if (ac != null) {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Safety error:");
+ Console.ForegroundColor = col;
+ Console.Write("This assertion is violated: ");
+ Console.Write("({0};{1}):", ac.tok.line, ac.tok.col);
+ ac.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ }
+ if (uc != null) {
+ bool containsAssert = false;
+ foreach (Cmd c in m_doomedCmds) {
+ Contract.Assert(c != null);
+ if (causals.Contains(c)) {
+ continue;
+ }
+ AssertCmd asrt = c as AssertCmd;
+ if (asrt != null) {
+ containsAssert = true;
+ break;
+ }
+ }
+ // Plausibility error
+ if (containsAssert) {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine("Plausibility error:");
+ Console.ForegroundColor = col;
+ Console.Write("There is no legal exeuction passing: ");
+ Console.Write("({0};{1})", uc.tok.line, uc.tok.col);
+ uc.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ } else { // Reachability error
+ Console.ForegroundColor = ConsoleColor.DarkRed;
+ Console.WriteLine("Reachability error:");
+ Console.ForegroundColor = col;
+ Console.Write("No execution can reach: ");
+ Console.Write("({0};{1})", uc.tok.line, uc.tok.col);
+ uc.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ }
+
+ }
+
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("...on any execution passing through:");
+ foreach (Cmd c in m_doomedCmds) {
+ Contract.Assert(c != null);
+ if (causals.Contains(c)) {
+ continue;
+ }
+ Console.ForegroundColor = col;
+ Console.Write("In ({0};{1}): ", c.tok.line, c.tok.col);
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ c.Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ }
+ Console.ForegroundColor = col;
+ Console.WriteLine("--");
+
+ }
+ }
+
+ private List<Cmd> CollectCausalStatements(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Cmd>>()));
+
+ Cmd lastCausal = null;
+ foreach (Cmd c in b.Cmds) {
+ Contract.Assert(c != null);
+ AssertCmd ac = c as AssertCmd;
+ AssumeCmd uc = c as AssumeCmd;
+ if (ac != null && !ContainsReachVariable(ac)) {
+ if (ac.Expr != Expr.True) {
+ lastCausal = c;
+ }
+ } else if (uc != null && !ContainsReachVariable(uc)) {
+ lastCausal = c;
+ }
+ }
+
+ List<Cmd> causals = new List<Cmd>();
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (gc != null && gc.labelTargets != null) {
+ List<Cmd> tmp;
+ //bool allcausal = true;
+ foreach (Block b_ in gc.labelTargets) {
+ Contract.Assert(b_ != null);
+ tmp = CollectCausalStatements(b_);
+
+ foreach (Cmd cau in tmp) {
+ if (!causals.Contains(cau))
+ causals.Add(cau);
+ }
+ }
+ //if (allcausal)
+ if (causals.Count > 0)
+ return causals;
+ }
+ if (lastCausal != null)
+ causals.Add(lastCausal);
+ return causals;
+ }
+
+ #endregion
+
+ bool BruteForceCESearch(Variable reachvar, Implementation impl, VerifierCallback callback,
+ Dictionary<Block, List<Cmd>> cmdbackup, int startidx, int endidx) {
+ Contract.Requires(reachvar != null);
+ Contract.Requires(impl != null);
+ Contract.Requires(callback != null);
+ Contract.Requires(cce.NonNullElements(cmdbackup));
+ #region Modify implementation
+ for (int i = startidx; i <= endidx; i++) {
+ if (_copiedBlock.Contains(impl.Blocks[i]))
+ continue;
+ List<Cmd> cs = new List<Cmd>();
+ cmdbackup.Add(impl.Blocks[i], impl.Blocks[i].Cmds);
+ foreach (Cmd c in impl.Blocks[i].Cmds) {
+ Contract.Assert(c != null);
+ if (ContainsReachVariable(c)) {
+ cs.Add(c);
+ continue;
+ }
+ AssertCmd ac = c as AssertCmd;
+ AssumeCmd uc = c as AssumeCmd;
+ if (ac != null) {
+ cs.Add(new AssertCmd(ac.tok, Expr.True));
+ } else if (uc != null) {
+ cs.Add(new AssertCmd(uc.tok, Expr.True));
+ } else {
+ cs.Add(c);
+ }
+ }
+ impl.Blocks[i].Cmds = cs;
+ }
+ #endregion
+
+ ProverInterface.Outcome outcome = ProverInterface.Outcome.Undetermined;
+ if (!ReCheckImpl(reachvar, impl, callback, out outcome)) {
+ UndoBlockModifications(impl, cmdbackup, startidx, endidx);
+ return false;
+ }
+ if (outcome == ProverInterface.Outcome.Valid) {
+ return true;
+ } else if (outcome == ProverInterface.Outcome.Invalid) {
+ UndoBlockModifications(impl, cmdbackup, startidx, endidx);
+ int mid = startidx + (endidx - startidx) / 2;
+ if (startidx >= endidx) {
+ // Now we found an interesting Block and we have to
+ // search for the interesting statements.
+ int cmdcount = impl.Blocks[endidx].Cmds.Length;
+ BruteForceCmd(impl.Blocks[endidx], 0, cmdcount / 2 - 1, reachvar, impl, callback);
+ BruteForceCmd(impl.Blocks[endidx], cmdcount / 2, cmdcount - 1, reachvar, impl, callback);
+ return true;
+ } else {
+ BruteForceCESearch(reachvar, impl, callback, cmdbackup, startidx, mid);
+ BruteForceCESearch(reachvar, impl, callback, cmdbackup, mid + 1, endidx);
+ return true;
+ }
+ } else {
+ UndoBlockModifications(impl, cmdbackup, startidx, endidx);
+ return false;
+ }
+ }
+
+ bool BruteForceCmd(Block b, int startidx, int endidx, Variable reachvar,
+ Implementation impl, VerifierCallback callback) {
+ Contract.Requires(b != null);
+ Contract.Requires(reachvar != null);
+ Contract.Requires(impl != null);
+ Contract.Requires(callback != null);
+ #region Modify Cmds
+ List<Cmd> backup = b.Cmds;
+ Contract.Assert(backup != null);
+ List<Cmd> cs = new List<Cmd>();
+ for (int i = 0; i < startidx; i++) {
+ cs.Add(b.Cmds[i]);
+ }
+ for (int i = startidx; i <= endidx; i++) {
+ Cmd c = b.Cmds[i];
+ if (ContainsReachVariable(c)) {
+ cs.Add(c);
+ continue;
+ }
+ cs.Add(new AssertCmd(c.tok, Expr.True));
+ }
+ for (int i = endidx + 1; i < b.Cmds.Length; i++) {
+ cs.Add(b.Cmds[i]);
+ }
+
+ b.Cmds = cs;
+ #endregion
+
+ #region Recheck
+ ProverInterface.Outcome outcome = ProverInterface.Outcome.Undetermined;
+ if (!ReCheckImpl(reachvar, impl, callback, out outcome)) {
+ b.Cmds = backup;
+ return false;
+ }
+ #endregion
+
+ if (outcome == ProverInterface.Outcome.Valid) {
+ return true;
+ } else if (outcome == ProverInterface.Outcome.Invalid) {
+ b.Cmds = backup;
+ if (startidx >= endidx) {
+ if (!ContainsReachVariable(b.Cmds[endidx])) {
+ // Console.Write(" Witness (");
+ //
+ // ConsoleColor col = Console.ForegroundColor;
+ // Console.ForegroundColor = ConsoleColor.White;
+ // Console.Write("{0};{1}", b.Cmds[endidx].tok.line, b.Cmds[endidx].tok.col );
+ // Console.ForegroundColor = col;
+ // Console.Write("): ");
+ // Console.ForegroundColor = ConsoleColor.Yellow;
+ // b.Cmds[endidx].Emit(new TokenTextWriter("<console>", Console.Out, false), 0);
+ // Console.ForegroundColor = col;
+
+ m_doomedCmds.Add(b.Cmds[endidx]);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ int mid = startidx + (endidx - startidx) / 2;
+ BruteForceCmd(b, startidx, mid, reachvar, impl, callback);
+ BruteForceCmd(b, mid + 1, endidx, reachvar, impl, callback);
+ return false; // This is pure random
+ }
+ } else {
+ b.Cmds = backup;
+ return false;
+ }
+ }
+
+ void UndoBlockModifications(Implementation impl, Dictionary<Block/*!*/, List<Cmd>/*!*/>/*!*/ cmdbackup,
+ int startidx, int endidx) {
+ Contract.Requires(cce.NonNullElements(cmdbackup));
+ Contract.Requires(impl != null);
+ for (int i = startidx; i <= endidx; i++) {
+ List<Cmd> cs = null;
+ if (cmdbackup.TryGetValue(impl.Blocks[i], out cs)) {
+ Contract.Assert(cs != null);
+ impl.Blocks[i].Cmds = cs;
+ cmdbackup.Remove(impl.Blocks[i]);
+ }
+ }
+ }
+
+ bool ReCheckImpl(Variable reachvar, Implementation impl, VerifierCallback callback,
+ out ProverInterface.Outcome outcome) {
+ Contract.Requires(reachvar != null);
+ Contract.Requires(impl != null);
+ Contract.Requires(callback != null);
+ Checker checker = FindCheckerFor(impl, 1000);
+ Contract.Assert(checker != null);
+ DoomCheck dc = new DoomCheck(impl, this.exitBlock, checker, m_UncheckableBlocks);
+ dc.ErrorHandler = new DoomErrorHandler(dc.Label2Absy, callback);
+ outcome = ProverInterface.Outcome.Undetermined;
+ List<Variable> rv = new List<Variable>();
+ rv.Add(reachvar);
+ if (!dc.CheckLabel(rv,null, out outcome)) {
+ checker.Close();
+ return false;
+ }
+ checker.Close();
+ return true;
+ }
+
+
+
+ bool ContainsReachVariable(Cmd c) {
+ Contract.Requires(c != null);
+ AssertCmd artc = c as AssertCmd;
+ AssumeCmd amec = c as AssumeCmd;
+ Expr e;
+ if (artc != null) {
+ e = artc.Expr;
+ } else if (amec != null) {
+ e = amec.Expr;
+ } else {
+ return false;
+ }
+ Set freevars = new Set();
+ e.ComputeFreeVariables(freevars);
+ foreach (Variable v in freevars) {
+ Contract.Assert(v != null);
+ if (v.Name.Contains(reachvarsuffix))
+ return true;
+ }
+ return false;
+ }
+#endregion
+#endif
+
+
+ Block exitBlock;
+
+ #region Program Passification
+ private void GenerateHelperBlocks(Implementation impl) {
+ Contract.Requires(impl != null);
+ Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>();
+ exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins);
+ Contract.Assert(exitBlock != null);
+
+ AddBlocksBetween(impl.Blocks);
+
+ #region Insert pre- and post-conditions and where clauses as assume and assert statements
+ {
+ List<Cmd> cc = new List<Cmd>();
+ // where clauses of global variables
+ foreach (var gvar in program.GlobalVariables) {
+ if (gvar.TypedIdent.WhereExpr != null) {
+ Cmd c = new AssumeCmd(gvar.tok, gvar.TypedIdent.WhereExpr);
+ cc.Add(c);
+ }
+ }
+ // where clauses of in- and out-parameters
+ cc.AddRange(GetParamWhereClauses(impl));
+ // where clauses of local variables
+ foreach (Variable lvar in impl.LocVars) {
+ Contract.Assert(lvar != null);
+ if (lvar.TypedIdent.WhereExpr != null) {
+ Cmd c = new AssumeCmd(lvar.tok, lvar.TypedIdent.WhereExpr);
+ cc.Add(c);
+ }
+ }
+
+ // add cc and the preconditions to new blocks preceding impl.Blocks[0]
+ InjectPreconditions(impl, cc);
+
+ // append postconditions, starting in exitBlock and continuing into other blocks, if needed
+ InjectPostConditions(impl, exitBlock, gotoCmdOrigins);
+ }
+ #endregion
+ }
+
+
+ private Dictionary<Variable, Expr> PassifyProgram(Implementation impl, ModelViewInfo mvInfo) {
+ Contract.Requires(impl != null);
+ Contract.Requires(mvInfo != null);
+ Contract.Requires(this.exitBlock != null);
+ Contract.Ensures(Contract.Result<Hashtable>() != null);
+
+ CurrentLocalVariables = impl.LocVars;
+ return Convert2PassiveCmd(impl, mvInfo);
+ //return new Hashtable();
+ }
+
+ /// <summary>
+ /// Add additional variable to allow checking as described in the paper
+ /// "It's doomed; we can prove it"
+ /// </summary>
+ private List<Cmd> GenerateReachabilityPredicates(Implementation impl)
+ {
+ Contract.Requires(impl != null);
+
+ foreach (Block b in impl.Blocks)
+ {
+ Contract.Assert(b != null);
+ //if (b.Predecessors.Length==0) continue;
+ //if (b.Cmds.Length == 0 ) continue;
+
+ Variable v_ = new LocalVariable(Token.NoToken,
+ new TypedIdent(b.tok, b.Label + reachvarsuffix, new BasicType(SimpleType.Int )));
+
+ impl.LocVars.Add(v_);
+
+ m_BlockReachabilityMap[b] = v_;
+
+ IdentifierExpr lhs = new IdentifierExpr(b.tok, v_);
+ Contract.Assert(lhs != null);
+
+ impl.Proc.Modifies.Add(lhs);
+
+ List<AssignLhs> lhsl = new List<AssignLhs>();
+ lhsl.Add(new SimpleAssignLhs(Token.NoToken, lhs));
+ List<Expr> rhsl = new List<Expr>();
+ rhsl.Add(Expr.Literal(1) );
+
+
+ List<Cmd> cs = new List<Cmd> { new AssignCmd(Token.NoToken, lhsl, rhsl) };
+ cs.AddRange(b.Cmds);
+ b.Cmds = cs;
+
+ //checkBlocks.Add(new CheckableBlock(v_,b));
+ }
+
+ List<Cmd> incReachVars = new List<Cmd>();
+ foreach (KeyValuePair<Block, Variable> kvp in m_BlockReachabilityMap)
+ {
+ IdentifierExpr lhs = new IdentifierExpr(Token.NoToken, kvp.Value);
+ impl.Proc.Modifies.Add(lhs);
+ incReachVars.Add(new AssumeCmd(Token.NoToken, Expr.Le(lhs, Expr.Literal(1))));
+ }
+
+ return incReachVars;
+ }
+
+ #endregion
+
+ #region Compute loop-free approximation
+
+ // this might be redundant, but I didn't find a better place to get this information.
+ private Dictionary<Variable, Expr> m_LastReachVarIncarnation = new Dictionary<Variable, Expr>();
+
+ private void Transform4DoomedCheck(Implementation impl)
+ {
+ variable2SequenceNumber = new Dictionary<Variable, int>();
+ incarnationOriginMap = new Dictionary<Incarnation, Absy>();
+ if (impl.Blocks.Count < 1) return;
+
+ impl.PruneUnreachableBlocks();
+ AddBlocksBetween(impl.Blocks);
+ ResetPredecessors(impl.Blocks);
+
+ GraphAnalyzer ga = new GraphAnalyzer(impl.Blocks);
+ LoopRemover lr = new LoopRemover(ga);
+ lr.AbstractLoopUnrolling();
+
+ impl.Blocks = ga.ToImplementation(out m_UncheckableBlocks);
+ ResetPredecessors(impl.Blocks);
+
+ // Check for the "BlocksBetween" if all their successors are in m_UncheckableBlocks
+ List<Block> oldblocks = new List<Block>();
+ oldblocks.AddRange(impl.Blocks);
+ GenerateHelperBlocks(impl);
+ #region Check for the "BlocksBetween" if all their successors are in m_UncheckableBlocks
+ foreach (Block b in impl.Blocks)
+ {
+ if (oldblocks.Contains(b)) continue;
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ bool allsuccUncheckable = true;
+ foreach (Block _b in gc.labelTargets)
+ {
+ if (!m_UncheckableBlocks.Contains(_b))
+ {
+ allsuccUncheckable = false; break;
+ }
+ }
+ if (allsuccUncheckable && !m_UncheckableBlocks.Contains(b)) m_UncheckableBlocks.Add(b);
+ }
+ }
+ #endregion
+
+ impl.Blocks = DeepCopyBlocks(impl.Blocks, m_UncheckableBlocks);
+
+ m_BlockReachabilityMap = new Dictionary<Block, Variable>();
+ List<Cmd> cs = GenerateReachabilityPredicates(impl);
+
+ //foreach (Block test in getTheFFinalBlock(impl.Blocks[0]))
+ //{
+ // test.Cmds.AddRange(cs);
+ //}
+
+ ResetPredecessors(impl.Blocks);
+ //EmitImpl(impl,false);
+
+ Dictionary<Variable, Expr> var2Expr = PassifyProgram(impl, new ModelViewInfo(program, impl));
+
+ // Collect the last incarnation of each reachability variable in the passive program
+ foreach (KeyValuePair<Block, Variable> kvp in m_BlockReachabilityMap)
+ {
+ if (var2Expr.ContainsKey(kvp.Value))
+ {
+ m_LastReachVarIncarnation[kvp.Value] = (Expr)var2Expr[kvp.Value];
+ }
+ }
+ }
+
+
+ List<Block> getTheFFinalBlock(Block b)
+ {
+ List<Block> lb = new List<Block>();
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ if (gc == null) lb.Add(b);
+ else
+ {
+ foreach (Block s in gc.labelTargets)
+ {
+ foreach (Block r in getTheFFinalBlock(s)) if (!lb.Contains(r)) lb.Add(r);
+ }
+ }
+ return lb;
+ }
+
+
+ private List<Block> DeepCopyBlocks(List<Block> lb, List<Block> uncheckables)
+ {
+ List<Block> clones = new List<Block>();
+ List<Block> uncheck_ = new List<Block>();
+ Dictionary<Block, Block> clonemap = new Dictionary<Block, Block>();
+
+ foreach (Block b in lb)
+ {
+ Block clone = CloneBlock(b);
+ clones.Add(clone);
+ clonemap[b] = clone;
+ if (uncheckables.Contains(b)) uncheck_.Add(clone);
+ }
+ uncheckables.Clear();
+ uncheckables.AddRange(uncheck_);
+ // update the successors and predecessors
+ foreach (Block b in lb)
+ {
+ List<Block> newpreds = new List<Block>();
+ foreach (Block b_ in b.Predecessors)
+ {
+ newpreds.Add(clonemap[b_]);
+ }
+ clonemap[b].Predecessors = newpreds;
+ GotoCmd gc = b.TransferCmd as GotoCmd;
+ ReturnCmd rc = b.TransferCmd as ReturnCmd;
+ if (gc != null)
+ {
+ List<String> lseq = new List<String>();
+ List<Block> bseq = new List<Block>();
+ foreach (string s in gc.labelNames) lseq.Add(s);
+ foreach (Block b_ in gc.labelTargets) bseq.Add(clonemap[b_]);
+ GotoCmd tcmd = new GotoCmd(gc.tok, lseq, bseq);
+ clonemap[b].TransferCmd = tcmd;
+ }
+ else if (rc != null)
+ {
+ clonemap[b].TransferCmd = new ReturnCmd(rc.tok);
+ }
+ }
+ return clones;
+ }
+
+ private Block CloneBlock(Block b)
+ {
+ Block clone = new Block(b.tok, b.Label, b.Cmds, b.TransferCmd);
+ if (this.exitBlock == b) this.exitBlock = clone;
+ return clone;
+ }
+ #endregion
+ }
+}
diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs
index 31a69c6e..9bc855be 100644
--- a/Source/ExecutionEngine/ExecutionEngine.cs
+++ b/Source/ExecutionEngine/ExecutionEngine.cs
@@ -1,1760 +1,1826 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Linq;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using VC;
-using BoogiePL = Microsoft.Boogie;
-using System.Diagnostics;
-using System.Runtime.Caching;
-
-namespace Microsoft.Boogie
-{
-
- #region Output printing
-
- public interface OutputPrinter
- {
- void ErrorWriteLine(TextWriter tw, string s);
- void ErrorWriteLine(TextWriter tw, string format, params object[] args);
- void AdvisoryWriteLine(string format, params object[] args);
- void Inform(string s, TextWriter tw);
- void WriteTrailer(PipelineStatistics stats);
- void WriteErrorInformation(ErrorInformation errorInfo, TextWriter tw, bool skipExecutionTrace = true);
- void ReportBplError(IToken tok, string message, bool error, TextWriter tw, string category = null);
- }
-
-
- public class ConsolePrinter : OutputPrinter
- {
- public void ErrorWriteLine(TextWriter tw, string s)
- {
- Contract.Requires(s != null);
- if (!s.Contains("Error: ") && !s.Contains("Error BP"))
- {
- tw.WriteLine(s);
- return;
- }
-
- // split the string up into its first line and the remaining lines
- string remaining = null;
- int i = s.IndexOf('\r');
- if (0 <= i)
- {
- remaining = s.Substring(i + 1);
- if (remaining.StartsWith("\n"))
- {
- remaining = remaining.Substring(1);
- }
- s = s.Substring(0, i);
- }
-
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Red;
- tw.WriteLine(s);
- Console.ForegroundColor = col;
-
- if (remaining != null)
- {
- tw.WriteLine(remaining);
- }
- }
-
-
- public void ErrorWriteLine(TextWriter tw, string format, params object[] args)
- {
- Contract.Requires(format != null);
- string s = string.Format(format, args);
- ErrorWriteLine(tw, s);
- }
-
-
- public void AdvisoryWriteLine(string format, params object[] args)
- {
- Contract.Requires(format != null);
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine(format, args);
- Console.ForegroundColor = col;
- }
-
-
- /// <summary>
- /// Inform the user about something and proceed with translation normally.
- /// Print newline after the message.
- /// </summary>
- public void Inform(string s, TextWriter tw)
- {
- if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.TraceProofObligations)
- {
- tw.WriteLine(s);
- }
- }
-
-
- public void WriteTrailer(PipelineStatistics stats)
- {
- Contract.Requires(stats != null);
- Contract.Requires(0 <= stats.VerifiedCount && 0 <= stats.ErrorCount && 0 <= stats.InconclusiveCount && 0 <= stats.TimeoutCount && 0 <= stats.OutOfMemoryCount);
-
- Console.WriteLine();
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
- Console.Write("{0} finished with {1} credible, {2} doomed{3}", CommandLineOptions.Clo.DescriptiveToolName, stats.VerifiedCount, stats.ErrorCount, stats.ErrorCount == 1 ? "" : "s");
- }
- else
- {
- Console.Write("{0} finished with {1} verified, {2} error{3}", CommandLineOptions.Clo.DescriptiveToolName, stats.VerifiedCount, stats.ErrorCount, stats.ErrorCount == 1 ? "" : "s");
- }
- if (stats.InconclusiveCount != 0)
- {
- Console.Write(", {0} inconclusive{1}", stats.InconclusiveCount, stats.InconclusiveCount == 1 ? "" : "s");
- }
- if (stats.TimeoutCount != 0)
- {
- Console.Write(", {0} time out{1}", stats.TimeoutCount, stats.TimeoutCount == 1 ? "" : "s");
- }
- if (stats.OutOfMemoryCount != 0)
- {
- Console.Write(", {0} out of memory", stats.OutOfMemoryCount);
- }
- Console.WriteLine();
- Console.Out.Flush();
- }
-
-
- public void WriteErrorInformation(ErrorInformation errorInfo, TextWriter tw, bool skipExecutionTrace = true)
- {
- Contract.Requires(errorInfo != null);
-
- ReportBplError(errorInfo.Tok, errorInfo.FullMsg, true, tw);
-
- foreach (var e in errorInfo.Aux)
- {
- if (!(skipExecutionTrace && e.Category.Contains("Execution trace")))
- {
- ReportBplError(e.Tok, e.FullMsg, false, tw);
- }
- }
-
- tw.Write(errorInfo.Out.ToString());
- tw.Write(errorInfo.Model.ToString());
- tw.Flush();
- }
-
-
- public virtual void ReportBplError(IToken tok, string message, bool error, TextWriter tw, string category = null)
- {
- Contract.Requires(message != null);
-
- if (category != null)
- {
- message = string.Format("{0}: {1}", category, message);
- }
- string s;
- if (tok != null)
- {
- s = string.Format("{0}({1},{2}): {3}", ExecutionEngine.GetFileNameForConsole(tok.filename), tok.line, tok.col, message);
- }
- else
- {
- s = message;
- }
- if (error)
- {
- ErrorWriteLine(tw, s);
- }
- else
- {
- tw.WriteLine(s);
- }
- }
- }
-
- #endregion
-
-
- public enum PipelineOutcome
- {
- Done,
- ResolutionError,
- TypeCheckingError,
- ResolvedAndTypeChecked,
- FatalError,
- VerificationCompleted
- }
-
-
- public class PipelineStatistics
- {
- public int ErrorCount;
- public int VerifiedCount;
- public int InconclusiveCount;
- public int TimeoutCount;
- public int OutOfMemoryCount;
- public long[] CachingActionCounts;
- public int CachedErrorCount;
- public int CachedVerifiedCount;
- public int CachedInconclusiveCount;
- public int CachedTimeoutCount;
- public int CachedOutOfMemoryCount;
- }
-
-
- #region Error reporting
-
- public delegate void ErrorReporterDelegate(ErrorInformation errInfo);
-
-
- public enum ErrorKind
- {
- Assertion,
- Precondition,
- Postcondition,
- InvariantEntry,
- InvariantMaintainance
- }
-
-
- public class ErrorInformationFactory
- {
- public virtual ErrorInformation CreateErrorInformation(IToken tok, string msg, string requestId = null, string originalRequestId = null, string category = null)
- {
- Contract.Requires(1 <= tok.line && 1 <= tok.col);
- Contract.Requires(msg != null);
-
- return ErrorInformation.CreateErrorInformation(tok, msg, requestId, originalRequestId, category);
- }
- }
-
-
- public class ErrorInformation
- {
- public readonly IToken Tok;
- public string Msg;
- public string Category { get; set; }
- public string BoogieErrorCode { get; set; }
- public readonly List<AuxErrorInfo> Aux = new List<AuxErrorInfo>();
- public string OriginalRequestId { get; set; }
- public string RequestId { get; set; }
- public ErrorKind Kind { get; set; }
- public string ImplementationName { get; set; }
- public TextWriter Out = new StringWriter();
- public TextWriter Model = new StringWriter();
-
- public string FullMsg
- {
- get
- {
- var prefix = Category;
- if (BoogieErrorCode != null)
- {
- prefix = prefix == null ? BoogieErrorCode : prefix + " " + BoogieErrorCode;
- }
- return prefix != null ? string.Format("{0}: {1}", prefix, Msg) : Msg;
- }
- }
-
- public struct AuxErrorInfo
- {
- public readonly IToken Tok;
- public readonly string Msg;
- public readonly string Category;
-
- public string FullMsg
- {
- get
- {
- return Category != null ? string.Format("{0}: {1}", Category, Msg) : Msg;
- }
- }
-
- public AuxErrorInfo(IToken tok, string msg, string category = null)
- {
- Tok = tok;
- Msg = CleanUp(msg);
- Category = category;
- }
- }
-
- protected ErrorInformation(IToken tok, string msg)
- {
- Contract.Requires(tok != null);
- Contract.Requires(1 <= tok.line && 1 <= tok.col);
- Contract.Requires(msg != null);
-
- Tok = tok;
- Msg = CleanUp(msg);
- }
-
- internal static ErrorInformation CreateErrorInformation(IToken tok, string msg, string requestId = null, string originalRequestId = null, string category = null)
- {
- var result = new ErrorInformation(tok, msg);
- result.RequestId = requestId;
- result.OriginalRequestId = originalRequestId;
- result.Category = category;
- return result;
- }
-
- public virtual void AddAuxInfo(IToken tok, string msg, string category = null)
- {
- Contract.Requires(tok != null);
- Contract.Requires(1 <= tok.line && 1 <= tok.col);
- Contract.Requires(msg != null);
- Aux.Add(new AuxErrorInfo(tok, msg, category));
- }
-
- protected static string CleanUp(string msg)
- {
- if (msg.ToLower().StartsWith("error: "))
- {
- return msg.Substring(7);
- }
- else
- {
- return msg;
- }
- }
- }
-
- #endregion
-
-
- public sealed class VerificationResult
- {
- public readonly string RequestId;
- public readonly string Checksum;
- public readonly string DependeciesChecksum;
- public readonly string ImplementationName;
- public readonly IToken ImplementationToken;
- public readonly string ProgramId;
-
- public DateTime Start { get; set; }
- public DateTime End { get; set; }
-
- public int ProofObligationCount { get { return ProofObligationCountAfter - ProofObligationCountBefore; } }
- public int ProofObligationCountBefore { get; set; }
- public int ProofObligationCountAfter { get; set; }
-
- public ConditionGeneration.Outcome Outcome { get; set; }
- public List<Counterexample> Errors;
-
- public ISet<byte[]> AssertionChecksums { get; private set; }
-
- public VerificationResult(string requestId, Implementation implementation, string programId = null)
- {
- Checksum = implementation.Checksum;
- DependeciesChecksum = implementation.DependencyChecksum;
- RequestId = requestId;
- ImplementationName = implementation.Name;
- ImplementationToken = implementation.tok;
- ProgramId = programId;
- AssertionChecksums = implementation.AssertionChecksums;
- }
- }
-
-
- public class PolymorphismChecker : ReadOnlyVisitor
- {
- bool isMonomorphic = true;
-
- public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node)
- {
- if (node.TypeParameters.Count > 0)
- isMonomorphic = false;
- return base.VisitDeclWithFormals(node);
- }
-
- public override BinderExpr VisitBinderExpr(BinderExpr node)
- {
- if (node.TypeParameters.Count > 0)
- isMonomorphic = false;
- return base.VisitBinderExpr(node);
- }
-
- public override MapType VisitMapType(MapType node)
- {
- if (node.TypeParameters.Count > 0)
- isMonomorphic = false;
- return base.VisitMapType(node);
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- BinaryOperator op = node.Fun as BinaryOperator;
- if (op != null && op.Op == BinaryOperator.Opcode.Subtype)
- isMonomorphic = false;
- return base.VisitNAryExpr(node);
- }
-
- public static bool IsMonomorphic(Program program)
- {
- var checker = new PolymorphismChecker();
- checker.VisitProgram(program);
- return checker.isMonomorphic;
- }
- }
-
- public class ExecutionEngine
- {
- public static OutputPrinter printer;
-
- public static ErrorInformationFactory errorInformationFactory = new ErrorInformationFactory();
-
- static int autoRequestIdCount;
-
- static readonly string AutoRequestIdPrefix = "auto_request_id_";
-
- public static string FreshRequestId()
- {
- var id = Interlocked.Increment(ref autoRequestIdCount);
- return AutoRequestIdPrefix + id;
- }
-
- public static int AutoRequestId(string id)
- {
- if (id.StartsWith(AutoRequestIdPrefix))
- {
- int result;
- if (int.TryParse(id.Substring(AutoRequestIdPrefix.Length), out result))
- {
- return result;
- }
- }
- return -1;
- }
-
- public readonly static VerificationResultCache Cache = new VerificationResultCache();
-
- static readonly MemoryCache programCache = new MemoryCache("ProgramCache");
- static readonly CacheItemPolicy policy = new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, 10, 0), Priority = CacheItemPriority.Default };
-
- public static Program CachedProgram(string programId)
- {
- var result = programCache.Get(programId) as Program;
- return result;
- }
-
- static List<Checker> Checkers = new List<Checker>();
-
- static DateTime FirstRequestStart;
-
- static readonly ConcurrentDictionary<string, TimeSpan> TimePerRequest = new ConcurrentDictionary<string, TimeSpan>();
- static readonly ConcurrentDictionary<string, PipelineStatistics> StatisticsPerRequest = new ConcurrentDictionary<string, PipelineStatistics>();
-
- static readonly ConcurrentDictionary<string, CancellationTokenSource> ImplIdToCancellationTokenSource = new ConcurrentDictionary<string, CancellationTokenSource>();
-
- static readonly ConcurrentDictionary<string, CancellationTokenSource> RequestIdToCancellationTokenSource = new ConcurrentDictionary<string, CancellationTokenSource>();
-
- public static void ProcessFiles(List<string> fileNames, bool lookForSnapshots = true, string programId = null)
- {
- Contract.Requires(cce.NonNullElements(fileNames));
-
- if (programId == null)
- {
- programId = "main_program_id";
- }
-
- if (CommandLineOptions.Clo.VerifySeparately && 1 < fileNames.Count)
- {
- foreach (var f in fileNames)
- {
- ProcessFiles(new List<string> { f }, lookForSnapshots, f);
- }
- return;
- }
-
- if (0 <= CommandLineOptions.Clo.VerifySnapshots && lookForSnapshots)
- {
- var snapshotsByVersion = LookForSnapshots(fileNames);
- foreach (var s in snapshotsByVersion)
- {
- ProcessFiles(new List<string>(s), false, programId);
- }
- return;
- }
-
- using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count - 1]))
- {
- Program program = ParseBoogieProgram(fileNames, false);
- if (program == null)
- return;
- if (CommandLineOptions.Clo.PrintFile != null)
- {
- PrintBplFile(CommandLineOptions.Clo.PrintFile, program, false, true, CommandLineOptions.Clo.PrettyPrint);
- }
-
- LinearTypeChecker linearTypeChecker;
- MoverTypeChecker moverTypeChecker;
- PipelineOutcome oc = ResolveAndTypecheck(program, fileNames[fileNames.Count - 1], out linearTypeChecker, out moverTypeChecker);
- if (oc != PipelineOutcome.ResolvedAndTypeChecked)
- return;
-
- if (CommandLineOptions.Clo.PrintCFGPrefix != null)
- {
- foreach (var impl in program.Implementations)
- {
- using (StreamWriter sw = new StreamWriter(CommandLineOptions.Clo.PrintCFGPrefix + "." + impl.Name + ".dot"))
- {
- sw.Write(program.ProcessLoops(impl).ToDot());
- }
- }
- }
-
- if (CommandLineOptions.Clo.StratifiedInlining == 0)
- {
- Concurrency.Transform(linearTypeChecker, moverTypeChecker);
- (new LinearEraser()).VisitProgram(program);
- if (CommandLineOptions.Clo.OwickiGriesDesugaredOutputFile != null)
- {
- int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
- CommandLineOptions.Clo.PrintUnstructured = 1;
- PrintBplFile(CommandLineOptions.Clo.OwickiGriesDesugaredOutputFile, program, false, false, CommandLineOptions.Clo.PrettyPrint);
- CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
- }
- }
-
- EliminateDeadVariables(program);
-
- CoalesceBlocks(program);
-
- Inline(program);
-
- var stats = new PipelineStatistics();
- oc = InferAndVerify(program, stats, 1 < CommandLineOptions.Clo.VerifySnapshots ? programId : null);
- switch (oc)
- {
- case PipelineOutcome.Done:
- case PipelineOutcome.VerificationCompleted:
- printer.WriteTrailer(stats);
- break;
- default:
- break;
- }
- }
- }
-
- public static IList<IList<string>> LookForSnapshots(IList<string> fileNames)
- {
- Contract.Requires(fileNames != null);
-
- var result = new List<IList<string>>();
- for (int version = 0; true; version++)
- {
- var nextSnapshot = new List<string>();
- foreach (var name in fileNames)
- {
- var versionedName = name.Replace(Path.GetExtension(name), ".v" + version + Path.GetExtension(name));
- if (File.Exists(versionedName))
- {
- nextSnapshot.Add(versionedName);
- }
- }
- if (nextSnapshot.Any())
- {
- result.Add(nextSnapshot);
- }
- else
- {
- break;
- }
- }
- return result;
- }
-
-
- public static void CoalesceBlocks(Program program)
- {
- if (CommandLineOptions.Clo.CoalesceBlocks)
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Coalescing blocks...");
- Microsoft.Boogie.BlockCoalescer.CoalesceBlocks(program);
- }
- }
-
-
- public static void CollectModSets(Program program)
- {
- if (CommandLineOptions.Clo.DoModSetAnalysis)
- {
- new ModSetCollector().DoModSetAnalysis(program);
- }
- }
-
-
- public static void EliminateDeadVariables(Program program)
- {
- Microsoft.Boogie.UnusedVarEliminator.Eliminate(program);
- }
-
-
- public static void PrintBplFile(string filename, Program program, bool allowPrintDesugaring, bool setTokens = true, bool pretty = false)
- {
- Contract.Requires(program != null);
- Contract.Requires(filename != null);
- bool oldPrintDesugaring = CommandLineOptions.Clo.PrintDesugarings;
- if (!allowPrintDesugaring)
- {
- CommandLineOptions.Clo.PrintDesugarings = false;
- }
- using (TokenTextWriter writer = filename == "-" ?
- new TokenTextWriter("<console>", Console.Out, setTokens, pretty) :
- new TokenTextWriter(filename, setTokens, pretty))
- {
- if (CommandLineOptions.Clo.ShowEnv != CommandLineOptions.ShowEnvironment.Never)
- {
- writer.WriteLine("// " + CommandLineOptions.Clo.Version);
- writer.WriteLine("// " + CommandLineOptions.Clo.Environment);
- }
- writer.WriteLine();
- program.Emit(writer);
- }
- CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaring;
- }
-
-
- /// <summary>
- /// Parse the given files into one Boogie program. If an I/O or parse error occurs, an error will be printed
- /// and null will be returned. On success, a non-null program is returned.
- /// </summary>
- public static Program ParseBoogieProgram(List<string> fileNames, bool suppressTraceOutput)
- {
- Contract.Requires(cce.NonNullElements(fileNames));
-
- Program program = null;
- bool okay = true;
- for (int fileId = 0; fileId < fileNames.Count; fileId++)
- {
- string bplFileName = fileNames[fileId];
- if (!suppressTraceOutput)
- {
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteFileFragment(bplFileName);
- }
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Parsing " + GetFileNameForConsole(bplFileName));
- }
- }
-
- Program programSnippet;
- int errorCount;
- try
- {
- var defines = new List<string>() { "FILE_" + fileId };
- errorCount = Parser.Parse(bplFileName, defines, out programSnippet, CommandLineOptions.Clo.UseBaseNameForFileName);
- if (programSnippet == null || errorCount != 0)
- {
- Console.WriteLine("{0} parse errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName));
- okay = false;
- continue;
- }
- }
- catch (IOException e)
- {
- printer.ErrorWriteLine(Console.Out, "Error opening file \"{0}\": {1}", GetFileNameForConsole(bplFileName), e.Message);
- okay = false;
- continue;
- }
- if (program == null)
- {
- program = programSnippet;
- }
- else if (programSnippet != null)
- {
- program.AddTopLevelDeclarations(programSnippet.TopLevelDeclarations);
- }
- }
- if (!okay)
- {
- return null;
- }
- else if (program == null)
- {
- return new Program();
- }
- else
- {
- return program;
- }
- }
-
- internal static string GetFileNameForConsole(string filename)
- {
- return (CommandLineOptions.Clo.UseBaseNameForFileName && !string.IsNullOrEmpty(filename) && filename != "<console>") ? System.IO.Path.GetFileName(filename) : filename;
- }
-
-
- /// <summary>
- /// Resolves and type checks the given Boogie program. Any errors are reported to the
- /// console. Returns:
- /// - Done if no errors occurred, and command line specified no resolution or no type checking.
- /// - ResolutionError if a resolution error occurred
- /// - TypeCheckingError if a type checking error occurred
- /// - ResolvedAndTypeChecked if both resolution and type checking succeeded
- /// </summary>
- public static PipelineOutcome ResolveAndTypecheck(Program program, string bplFileName, out LinearTypeChecker linearTypeChecker, out MoverTypeChecker moverTypeChecker)
- {
- Contract.Requires(program != null);
- Contract.Requires(bplFileName != null);
-
- linearTypeChecker = null;
- moverTypeChecker = null;
-
- // ---------- Resolve ------------------------------------------------------------
-
- if (CommandLineOptions.Clo.NoResolve)
- {
- return PipelineOutcome.Done;
- }
-
- int errorCount = program.Resolve();
- if (errorCount != 0)
- {
- Console.WriteLine("{0} name resolution errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName));
- return PipelineOutcome.ResolutionError;
- }
-
- // ---------- Type check ------------------------------------------------------------
-
- if (CommandLineOptions.Clo.NoTypecheck)
- {
- return PipelineOutcome.Done;
- }
-
- errorCount = program.Typecheck();
- if (errorCount != 0)
- {
- Console.WriteLine("{0} type checking errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName));
- return PipelineOutcome.TypeCheckingError;
- }
-
- if (PolymorphismChecker.IsMonomorphic(program))
- {
- CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic;
- }
-
- CollectModSets(program);
-
- moverTypeChecker = new MoverTypeChecker(program);
- moverTypeChecker.TypeCheck();
- if (moverTypeChecker.errorCount != 0)
- {
- Console.WriteLine("{0} type checking errors detected in {1}", moverTypeChecker.errorCount, GetFileNameForConsole(bplFileName));
- return PipelineOutcome.TypeCheckingError;
- }
-
- linearTypeChecker = new LinearTypeChecker(program);
- linearTypeChecker.TypeCheck();
- if (linearTypeChecker.errorCount == 0)
- {
- linearTypeChecker.Transform();
- }
- else
- {
- Console.WriteLine("{0} type checking errors detected in {1}", linearTypeChecker.errorCount, GetFileNameForConsole(bplFileName));
- return PipelineOutcome.TypeCheckingError;
- }
-
- if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings)
- {
- // if PrintDesugaring option is engaged, print the file here, after resolution and type checking
- PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true, true, CommandLineOptions.Clo.PrettyPrint);
- }
-
- return PipelineOutcome.ResolvedAndTypeChecked;
- }
-
-
- public static void Inline(Program program)
- {
- Contract.Requires(program != null);
-
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Inlining...");
-
- // Inline
- var TopLevelDeclarations = cce.NonNull(program.TopLevelDeclarations);
-
- if (CommandLineOptions.Clo.ProcedureInlining != CommandLineOptions.Inlining.None)
- {
- bool inline = false;
- foreach (var d in TopLevelDeclarations)
- {
- if ((d is Procedure || d is Implementation) && d.FindExprAttribute("inline") != null)
- {
- inline = true;
- }
- }
- if (inline)
- {
- foreach (var impl in TopLevelDeclarations.OfType<Implementation>())
- {
- impl.OriginalBlocks = impl.Blocks;
- impl.OriginalLocVars = impl.LocVars;
- }
- foreach (var impl in TopLevelDeclarations.OfType<Implementation>())
- {
- if (CommandLineOptions.Clo.UserWantsToCheckRoutine(impl.Name) && !impl.SkipVerification)
- {
- Inliner.ProcessImplementation(program, impl);
- }
- }
- foreach (var impl in TopLevelDeclarations.OfType<Implementation>())
- {
- impl.OriginalBlocks = null;
- impl.OriginalLocVars = null;
- }
- }
- }
- }
-
-
- /// <summary>
- /// Given a resolved and type checked Boogie program, infers invariants for the program
- /// and then attempts to verify it. Returns:
- /// - Done if command line specified no verification
- /// - FatalError if a fatal error occurred, in which case an error has been printed to console
- /// - VerificationCompleted if inference and verification completed, in which the out
- /// parameters contain meaningful values
- /// </summary>
- public static PipelineOutcome InferAndVerify(Program program,
- PipelineStatistics stats,
- string programId = null,
- ErrorReporterDelegate er = null, string requestId = null)
- {
- Contract.Requires(program != null);
- Contract.Requires(stats != null);
- Contract.Ensures(0 <= Contract.ValueAtReturn(out stats.InconclusiveCount) && 0 <= Contract.ValueAtReturn(out stats.TimeoutCount));
-
- if (requestId == null)
- {
- requestId = FreshRequestId();
- }
-
- var start = DateTime.UtcNow;
-
- #region Do some pre-abstract-interpretation preprocessing on the program
- // Doing lambda expansion before abstract interpretation means that the abstract interpreter
- // never needs to see any lambda expressions. (On the other hand, if it were useful for it
- // to see lambdas, then it would be better to more lambda expansion until after infererence.)
- if (CommandLineOptions.Clo.ExpandLambdas) {
- LambdaHelper.ExpandLambdas(program);
- //PrintBplFile ("-", program, true);
- }
- #endregion
-
- #region Infer invariants using Abstract Interpretation
-
- // Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
- if (CommandLineOptions.Clo.UseAbstractInterpretation)
- {
- if (!CommandLineOptions.Clo.Ai.J_Intervals && !CommandLineOptions.Clo.Ai.J_Trivial)
- {
- // use /infer:j as the default
- CommandLineOptions.Clo.Ai.J_Intervals = true;
- }
- }
- Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
-
- #endregion
-
- #region Do some post-abstract-interpretation preprocessing on the program (e.g., loop unrolling)
-
- if (CommandLineOptions.Clo.LoopUnrollCount != -1)
- {
- program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount, CommandLineOptions.Clo.SoundLoopUnrolling);
- }
-
- Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo = null;
- if (CommandLineOptions.Clo.ExtractLoops)
- {
- extractLoopMappingInfo = program.ExtractLoops();
- }
-
- if (CommandLineOptions.Clo.PrintInstrumented)
- {
- program.Emit(new TokenTextWriter(Console.Out, CommandLineOptions.Clo.PrettyPrint));
- }
- #endregion
-
- if (!CommandLineOptions.Clo.Verify)
- {
- return PipelineOutcome.Done;
- }
-
- #region Run Houdini and verify
- if (CommandLineOptions.Clo.ContractInfer)
- {
- return RunHoudini(program, stats, er);
- }
- #endregion
-
- #region Select and prioritize implementations that should be verified
-
- var impls = program.Implementations.Where(
- impl => impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine(cce.NonNull(impl.Name)) && !impl.SkipVerification);
-
- // operate on a stable copy, in case it gets updated while we're running
- Implementation[] stablePrioritizedImpls = null;
- if (0 < CommandLineOptions.Clo.VerifySnapshots)
- {
- OtherDefinitionAxiomsCollector.Collect(program.Axioms);
- DependencyCollector.Collect(program);
- stablePrioritizedImpls = impls.OrderByDescending(
- impl => impl.Priority != 1 ? impl.Priority : Cache.VerificationPriority(impl)).ToArray();
- }
- else
- {
- stablePrioritizedImpls = impls.OrderByDescending(impl => impl.Priority).ToArray();
- }
-
- #endregion
-
- if (1 < CommandLineOptions.Clo.VerifySnapshots)
- {
- CachedVerificationResultInjector.Inject(program, stablePrioritizedImpls, requestId, programId, out stats.CachingActionCounts);
- }
-
- #region Verify each implementation
-
- var outputCollector = new OutputCollector(stablePrioritizedImpls);
- var outcome = PipelineOutcome.VerificationCompleted;
-
- try
- {
- var cts = new CancellationTokenSource();
- RequestIdToCancellationTokenSource.AddOrUpdate(requestId, cts, (k, ov) => cts);
-
- var tasks = new Task[stablePrioritizedImpls.Length];
- // We use this semaphore to limit the number of tasks that are currently executing.
- var semaphore = new SemaphoreSlim(CommandLineOptions.Clo.VcsCores);
-
- // Create a task per implementation.
- for (int i = 0; i < stablePrioritizedImpls.Length; i++)
- {
- var taskIndex = i;
- var id = stablePrioritizedImpls[taskIndex].Id;
-
- CancellationTokenSource old;
- if (ImplIdToCancellationTokenSource.TryGetValue(id, out old))
- {
- old.Cancel();
- }
- ImplIdToCancellationTokenSource.AddOrUpdate(id, cts, (k, ov) => cts);
-
- var t = new Task((dummy) =>
- {
- try
- {
- if (outcome == PipelineOutcome.FatalError)
- {
- return;
- }
- if (cts.Token.IsCancellationRequested)
- {
- cts.Token.ThrowIfCancellationRequested();
- }
- VerifyImplementation(program, stats, er, requestId, extractLoopMappingInfo, stablePrioritizedImpls, taskIndex, outputCollector, Checkers, programId);
- ImplIdToCancellationTokenSource.TryRemove(id, out old);
- }
- finally
- {
- semaphore.Release();
- }
- }, cts.Token, TaskCreationOptions.LongRunning);
- tasks[taskIndex] = t;
- }
-
- // Execute the tasks.
- int j = 0;
- for (; j < stablePrioritizedImpls.Length && outcome != PipelineOutcome.FatalError; j++)
- {
- try
- {
- semaphore.Wait(cts.Token);
- }
- catch (OperationCanceledException)
- {
- break;
- }
- tasks[j].Start(TaskScheduler.Default);
- }
-
- // Don't wait for tasks that haven't been started yet.
- tasks = tasks.Take(j).ToArray();
- Task.WaitAll(tasks);
- }
- catch (AggregateException ae)
- {
- ae.Handle(e =>
- {
- var pe = e as ProverException;
- if (pe != null)
- {
- printer.ErrorWriteLine(Console.Out, "Fatal Error: ProverException: {0}", e);
- outcome = PipelineOutcome.FatalError;
- return true;
- }
- var oce = e as OperationCanceledException;
- if (oce != null)
- {
- return true;
- }
- return false;
- });
- }
- finally
- {
- CleanupCheckers(requestId);
- }
-
- cce.NonNull(CommandLineOptions.Clo.TheProverFactory).Close();
-
- outputCollector.WriteMoreOutput();
-
- if (1 < CommandLineOptions.Clo.VerifySnapshots && programId != null)
- {
- program.FreezeTopLevelDeclarations();
- programCache.Set(programId, program, policy);
- }
-
- if (0 <= CommandLineOptions.Clo.VerifySnapshots && CommandLineOptions.Clo.TraceCachingForBenchmarking)
- {
- var end = DateTime.UtcNow;
- if (TimePerRequest.Count == 0)
- {
- FirstRequestStart = start;
- }
- TimePerRequest[requestId] = end.Subtract(start);
- StatisticsPerRequest[requestId] = stats;
-
- var printTimes = true;
-
- Console.Out.WriteLine(CachedVerificationResultInjector.Statistics.Output(printTimes));
-
- Console.Out.WriteLine("Statistics per request as CSV:");
- var actions = string.Join(", ", Enum.GetNames(typeof(VC.ConditionGeneration.CachingAction)));
- Console.Out.WriteLine("Request ID{0}, Error, E (C), Inconclusive, I (C), Out of Memory, OoM (C), Timeout, T (C), Verified, V (C), {1}", printTimes ? ", Time (ms)" : "", actions);
- foreach (var kv in TimePerRequest.OrderBy(kv => ExecutionEngine.AutoRequestId(kv.Key)))
- {
- var s = StatisticsPerRequest[kv.Key];
- var cacs = s.CachingActionCounts;
- var c = cacs != null ? ", " + cacs.Select(ac => string.Format("{0,3}", ac)).Concat(", ") : "";
- var t = printTimes ? string.Format(", {0,8:F0}", kv.Value.TotalMilliseconds) : "";
- Console.Out.WriteLine("{0,-19}{1}, {2,2}, {3,2}, {4,2}, {5,2}, {6,2}, {7,2}, {8,2}, {9,2}, {10,2}, {11,2}{12}", kv.Key, t, s.ErrorCount, s.CachedErrorCount, s.InconclusiveCount, s.CachedInconclusiveCount, s.OutOfMemoryCount, s.CachedOutOfMemoryCount, s.TimeoutCount, s.CachedTimeoutCount, s.VerifiedCount, s.CachedVerifiedCount, c);
- }
-
- if (printTimes)
- {
- Console.Out.WriteLine();
- Console.Out.WriteLine("Total time (ms) since first request: {0:F0}", end.Subtract(FirstRequestStart).TotalMilliseconds);
- }
- }
-
- #endregion
-
- if (SecureVCGen.outfile != null)
- SecureVCGen.outfile.Close();
-
- return outcome;
- }
-
- public static void CancelRequest(string requestId)
- {
- Contract.Requires(requestId != null);
-
- CancellationTokenSource cts;
- if (RequestIdToCancellationTokenSource.TryGetValue(requestId, out cts))
- {
- cts.Cancel();
-
- CleanupCheckers(requestId);
- }
- }
-
-
- private static void CleanupCheckers(string requestId)
- {
- if (requestId != null)
- {
- CancellationTokenSource old;
- RequestIdToCancellationTokenSource.TryRemove(requestId, out old);
- }
- lock (RequestIdToCancellationTokenSource)
- {
- if (RequestIdToCancellationTokenSource.IsEmpty)
- {
- lock (Checkers)
- {
- foreach (Checker checker in Checkers)
- {
- Contract.Assert(checker != null);
- checker.Close();
- }
- }
- }
- }
- }
-
-
- private static void VerifyImplementation(Program program, PipelineStatistics stats, ErrorReporterDelegate er, string requestId, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo, Implementation[] stablePrioritizedImpls, int index, OutputCollector outputCollector, List<Checker> checkers, string programId)
- {
- Implementation impl = stablePrioritizedImpls[index];
- VerificationResult verificationResult = null;
- var output = new StringWriter();
-
- printer.Inform("", output); // newline
- printer.Inform(string.Format("Verifying {0} ...", impl.Name), output);
-
- int priority = 0;
- if (0 < CommandLineOptions.Clo.VerifySnapshots)
- {
- verificationResult = Cache.Lookup(impl, out priority);
- }
-
- var wasCached = false;
- if (verificationResult != null && priority == Priority.SKIP)
- {
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, verificationResult.Start);
- }
-
- printer.Inform(string.Format("Retrieving cached verification result for implementation {0}...", impl.Name), output);
- wasCached = true;
- }
- else
- {
- #region Verify the implementation
-
- verificationResult = new VerificationResult(requestId, impl, programId);
-
- using (var vcgen = CreateVCGen(program, checkers))
- {
- vcgen.CachingActionCounts = stats.CachingActionCounts;
- verificationResult.ProofObligationCountBefore = vcgen.CumulativeAssertionCount;
- verificationResult.Start = DateTime.UtcNow;
-
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, verificationResult.Start);
- }
- try
- {
- if (CommandLineOptions.Clo.inferLeastForUnsat != null)
- {
- var svcgen = vcgen as VC.StratifiedVCGen;
- Contract.Assert(svcgen != null);
- var ss = new HashSet<string>();
- foreach (var c in program.Constants)
- {
- if (!c.Name.StartsWith(CommandLineOptions.Clo.inferLeastForUnsat)) continue;
- ss.Add(c.Name);
- }
- verificationResult.Outcome = svcgen.FindLeastToVerify(impl, ref ss);
- verificationResult.Errors = new List<Counterexample>();
- output.WriteLine("Result: {0}", string.Join(" ", ss));
- }
- else
- {
- verificationResult.Outcome = vcgen.VerifyImplementation(impl, out verificationResult.Errors, requestId);
- if (CommandLineOptions.Clo.ExtractLoops && verificationResult.Errors != null)
- {
- var vcg = vcgen as VCGen;
- if (vcg != null)
- {
- for (int i = 0; i < verificationResult.Errors.Count; i++)
- {
- verificationResult.Errors[i] = vcg.extractLoopTrace(verificationResult.Errors[i], impl.Name, program, extractLoopMappingInfo);
- }
- }
- }
- }
- }
- catch (VCGenException e)
- {
- var errorInfo = errorInformationFactory.CreateErrorInformation(impl.tok, String.Format("{0} (encountered in implementation {1}).", e.Message, impl.Name), requestId, "Error");
- errorInfo.BoogieErrorCode = "BP5010";
- errorInfo.ImplementationName = impl.Name;
- printer.WriteErrorInformation(errorInfo, output);
- if (er != null)
- {
- lock (er)
- {
- er(errorInfo);
- }
- }
- verificationResult.Errors = null;
- verificationResult.Outcome = VCGen.Outcome.Inconclusive;
- }
- catch (UnexpectedProverOutputException upo)
- {
- printer.AdvisoryWriteLine("Advisory: {0} SKIPPED because of internal error: unexpected prover output: {1}", impl.Name, upo.Message);
- verificationResult.Errors = null;
- verificationResult.Outcome = VCGen.Outcome.Inconclusive;
- }
-
- verificationResult.ProofObligationCountAfter = vcgen.CumulativeAssertionCount;
- verificationResult.End = DateTime.UtcNow;
- }
-
- #endregion
-
- #region Cache the verification result
-
- if (0 < CommandLineOptions.Clo.VerifySnapshots && !string.IsNullOrEmpty(impl.Checksum))
- {
- Cache.Insert(impl, verificationResult);
- }
-
- #endregion
- }
-
- #region Process the verification results and statistics
-
- ProcessOutcome(verificationResult.Outcome, verificationResult.Errors, TimeIndication(verificationResult), stats, output, impl.TimeLimit, er, verificationResult.ImplementationName, verificationResult.ImplementationToken, verificationResult.RequestId, wasCached);
-
- ProcessErrors(verificationResult.Errors, verificationResult.Outcome, output, er, impl);
-
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- CommandLineOptions.Clo.XmlSink.WriteEndMethod(verificationResult.Outcome.ToString().ToLowerInvariant(), verificationResult.End, verificationResult.End - verificationResult.Start);
- }
-
- outputCollector.Add(index, output);
-
- outputCollector.WriteMoreOutput();
-
- if (verificationResult.Outcome == VCGen.Outcome.Errors || CommandLineOptions.Clo.Trace)
- {
- Console.Out.Flush();
- }
-
- #endregion
- }
-
-
- class OutputCollector
- {
- StringWriter[] outputs;
-
- int nextPrintableIndex = 0;
-
- public OutputCollector(Implementation[] implementations)
- {
- outputs = new StringWriter[implementations.Length];
- }
-
- public void WriteMoreOutput()
- {
- lock (outputs)
- {
- for (; nextPrintableIndex < outputs.Length && outputs[nextPrintableIndex] != null; nextPrintableIndex++)
- {
- Console.Write(outputs[nextPrintableIndex].ToString());
- outputs[nextPrintableIndex] = null;
- Console.Out.Flush();
- }
- }
- }
-
- public void Add(int index, StringWriter output)
- {
- Contract.Requires(0 <= index && index < outputs.Length);
- Contract.Requires(output != null);
-
- lock (this)
- {
- outputs[index] = output;
- }
- }
- }
-
-
- private static ConditionGeneration CreateVCGen(Program program, List<Checker> checkers)
- {
- ConditionGeneration vcgen = null;
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
- vcgen = new DCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
- }
- else if (CommandLineOptions.Clo.FixedPointEngine != null)
- {
- vcgen = new FixedpointVC(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
- }
- else if (CommandLineOptions.Clo.StratifiedInlining > 0)
- {
- vcgen = new StratifiedVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
- }
- else if (CommandLineOptions.Clo.SecureVcGen != null)
- {
- vcgen = new SecureVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
- }
- else
- {
- vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
- }
- return vcgen;
- }
-
-
- #region Houdini
-
- private static PipelineOutcome RunHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er)
- {
- Contract.Requires(stats != null);
-
- if (CommandLineOptions.Clo.AbstractHoudini != null)
- {
- return RunAbstractHoudini(program, stats, er);
- }
-
- if (CommandLineOptions.Clo.StagedHoudini != null)
- {
- return RunStagedHoudini(program, stats, er);
- }
-
- Houdini.HoudiniSession.HoudiniStatistics houdiniStats = new Houdini.HoudiniSession.HoudiniStatistics();
- Houdini.Houdini houdini = new Houdini.Houdini(program, houdiniStats);
- Houdini.HoudiniOutcome outcome = houdini.PerformHoudiniInference();
- houdini.Close();
-
- if (CommandLineOptions.Clo.PrintAssignment)
- {
- Console.WriteLine("Assignment computed by Houdini:");
- foreach (var x in outcome.assignment)
- {
- Console.WriteLine(x.Key + " = " + x.Value);
- }
- }
-
- if (CommandLineOptions.Clo.Trace)
- {
- int numTrueAssigns = 0;
- foreach (var x in outcome.assignment)
- {
- if (x.Value)
- numTrueAssigns++;
- }
- Console.WriteLine("Number of true assignments = " + numTrueAssigns);
- Console.WriteLine("Number of false assignments = " + (outcome.assignment.Count - numTrueAssigns));
- Console.WriteLine("Prover time = " + houdiniStats.proverTime.ToString("F2"));
- Console.WriteLine("Unsat core prover time = " + houdiniStats.unsatCoreProverTime.ToString("F2"));
- Console.WriteLine("Number of prover queries = " + houdiniStats.numProverQueries);
- Console.WriteLine("Number of unsat core prover queries = " + houdiniStats.numUnsatCoreProverQueries);
- Console.WriteLine("Number of unsat core prunings = " + houdiniStats.numUnsatCorePrunings);
- }
-
- foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values)
- {
- ProcessOutcome(x.outcome, x.errors, "", stats, Console.Out, CommandLineOptions.Clo.ProverKillTime, er);
- ProcessErrors(x.errors, x.outcome, Console.Out, er);
- }
-
- return PipelineOutcome.Done;
- }
-
- public static Program ProgramFromFile(string filename) {
- Program p = ParseBoogieProgram(new List<string> { filename }, false);
- System.Diagnostics.Debug.Assert(p != null);
- LinearTypeChecker linearTypeChecker;
- MoverTypeChecker moverTypeChecker;
- PipelineOutcome oc = ExecutionEngine.ResolveAndTypecheck(p, filename, out linearTypeChecker, out moverTypeChecker);
- System.Diagnostics.Debug.Assert(oc == PipelineOutcome.ResolvedAndTypeChecked);
- return p;
- }
-
- private static PipelineOutcome RunStagedHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er)
- {
- Houdini.HoudiniSession.HoudiniStatistics houdiniStats = new Houdini.HoudiniSession.HoudiniStatistics();
- Houdini.StagedHoudini stagedHoudini = new Houdini.StagedHoudini(program, houdiniStats, ProgramFromFile);
- Houdini.HoudiniOutcome outcome = stagedHoudini.PerformStagedHoudiniInference();
-
- if (CommandLineOptions.Clo.PrintAssignment)
- {
- Console.WriteLine("Assignment computed by Houdini:");
- foreach (var x in outcome.assignment)
- {
- Console.WriteLine(x.Key + " = " + x.Value);
- }
- }
-
- if (CommandLineOptions.Clo.Trace)
- {
- int numTrueAssigns = 0;
- foreach (var x in outcome.assignment)
- {
- if (x.Value)
- numTrueAssigns++;
- }
- Console.WriteLine("Number of true assignments = " + numTrueAssigns);
- Console.WriteLine("Number of false assignments = " + (outcome.assignment.Count - numTrueAssigns));
- Console.WriteLine("Prover time = " + houdiniStats.proverTime.ToString("F2"));
- Console.WriteLine("Unsat core prover time = " + houdiniStats.unsatCoreProverTime.ToString("F2"));
- Console.WriteLine("Number of prover queries = " + houdiniStats.numProverQueries);
- Console.WriteLine("Number of unsat core prover queries = " + houdiniStats.numUnsatCoreProverQueries);
- Console.WriteLine("Number of unsat core prunings = " + houdiniStats.numUnsatCorePrunings);
- }
-
- foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values)
- {
- ProcessOutcome(x.outcome, x.errors, "", stats, Console.Out, CommandLineOptions.Clo.ProverKillTime, er);
- ProcessErrors(x.errors, x.outcome, Console.Out, er);
- }
-
- return PipelineOutcome.Done;
-
- }
-
-
- private static PipelineOutcome RunAbstractHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er)
- {
- Contract.Requires(stats != null);
-
- //CommandLineOptions.Clo.PrintErrorModel = 1;
- CommandLineOptions.Clo.UseProverEvaluate = true;
- CommandLineOptions.Clo.ModelViewFile = "z3model";
- CommandLineOptions.Clo.UseArrayTheory = true;
- CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic;
- Houdini.AbstractDomainFactory.Initialize(program);
- var domain = Houdini.AbstractDomainFactory.GetInstance(CommandLineOptions.Clo.AbstractHoudini);
-
- // Run Abstract Houdini
- var abs = new Houdini.AbsHoudini(program, domain);
- var absout = abs.ComputeSummaries();
- ProcessOutcome(absout.outcome, absout.errors, "", stats, Console.Out, CommandLineOptions.Clo.ProverKillTime, er);
- ProcessErrors(absout.errors, absout.outcome, Console.Out, er);
-
- //Houdini.PredicateAbs.Initialize(program);
- //var abs = new Houdini.AbstractHoudini(program);
- //abs.computeSummaries(new Houdini.PredicateAbs(program.TopLevelDeclarations.OfType<Implementation>().First().Name));
-
- return PipelineOutcome.Done;
- }
-
- #endregion
-
-
- private static string TimeIndication(VerificationResult verificationResult)
- {
- var result = "";
- if (CommandLineOptions.Clo.Trace)
- {
- result = string.Format(" [{0:F3} s, {1} proof obligation{2}] ", (verificationResult.End - verificationResult.Start).TotalSeconds, verificationResult.ProofObligationCount, verificationResult.ProofObligationCount == 1 ? "" : "s");
- }
- else if (CommandLineOptions.Clo.TraceProofObligations)
- {
- result = string.Format(" [{0} proof obligation{1}] ", verificationResult.ProofObligationCount, verificationResult.ProofObligationCount == 1 ? "" : "s");
- }
- return result;
- }
-
-
- private static void ProcessOutcome(VC.VCGen.Outcome outcome, List<Counterexample> errors, string timeIndication,
- PipelineStatistics stats, TextWriter tw, int timeLimit, ErrorReporterDelegate er = null, string implName = null, IToken implTok = null, string requestId = null, bool wasCached = false)
- {
- Contract.Requires(stats != null);
-
- UpdateStatistics(stats, outcome, errors, wasCached);
-
- printer.Inform(timeIndication + OutcomeIndication(outcome, errors), tw);
-
- ReportOutcome(outcome, er, implName, implTok, requestId, tw, timeLimit);
- }
-
-
- private static void ReportOutcome(VC.VCGen.Outcome outcome, ErrorReporterDelegate er, string implName, IToken implTok, string requestId, TextWriter tw, int timeLimit)
- {
- ErrorInformation errorInfo = null;
-
- switch (outcome)
- {
- case VCGen.Outcome.ReachedBound:
- tw.WriteLine(string.Format("Stratified Inlining: Reached recursion bound of {0}", CommandLineOptions.Clo.RecursionBound));
- break;
- case VCGen.Outcome.TimedOut:
- if (implName != null && implTok != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(implTok, string.Format("Verification timed out after {0} seconds ({1})", timeLimit, implName), requestId);
- }
- break;
- case VCGen.Outcome.OutOfMemory:
- if (implName != null && implTok != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(implTok, "Verification out of memory (" + implName + ")", requestId);
- }
- break;
- case VCGen.Outcome.Inconclusive:
- if (implName != null && implTok != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(implTok, "Verification inconclusive (" + implName + ")", requestId);
- }
- break;
- }
-
- if (errorInfo != null)
- {
- errorInfo.ImplementationName = implName;
- if (er != null)
- {
- lock (er)
- {
- er(errorInfo);
- }
- }
- }
- }
-
-
- private static string OutcomeIndication(VC.VCGen.Outcome outcome, List<Counterexample> errors)
- {
- string traceOutput = "";
- switch (outcome)
- {
- default:
- Contract.Assert(false); // unexpected outcome
- throw new cce.UnreachableException();
- case VCGen.Outcome.ReachedBound:
- traceOutput = "verified";
- break;
- case VCGen.Outcome.Correct:
- traceOutput = (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed ? "credible" : "verified");
- break;
- case VCGen.Outcome.TimedOut:
- traceOutput = "timed out";
- break;
- case VCGen.Outcome.OutOfMemory:
- traceOutput = "out of memory";
- break;
- case VCGen.Outcome.Inconclusive:
- traceOutput = "inconclusive";
- break;
- case VCGen.Outcome.Errors:
- Contract.Assert(errors != null);
- traceOutput = (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed ? "doomed" : string.Format("error{0}", errors.Count == 1 ? "" : "s"));
- break;
- }
- return traceOutput;
- }
-
-
- private static void UpdateStatistics(PipelineStatistics stats, VC.VCGen.Outcome outcome, List<Counterexample> errors, bool wasCached)
- {
- Contract.Requires(stats != null);
-
- switch (outcome)
- {
- default:
- Contract.Assert(false); // unexpected outcome
- throw new cce.UnreachableException();
- case VCGen.Outcome.ReachedBound:
- Interlocked.Increment(ref stats.VerifiedCount);
- if (wasCached) { Interlocked.Increment(ref stats.CachedVerifiedCount); }
- break;
- case VCGen.Outcome.Correct:
- Interlocked.Increment(ref stats.VerifiedCount);
- if (wasCached) { Interlocked.Increment(ref stats.CachedVerifiedCount); }
- break;
- case VCGen.Outcome.TimedOut:
- Interlocked.Increment(ref stats.TimeoutCount);
- if (wasCached) { Interlocked.Increment(ref stats.CachedTimeoutCount); }
- break;
- case VCGen.Outcome.OutOfMemory:
- Interlocked.Increment(ref stats.OutOfMemoryCount);
- if (wasCached) { Interlocked.Increment(ref stats.CachedOutOfMemoryCount); }
- break;
- case VCGen.Outcome.Inconclusive:
- Interlocked.Increment(ref stats.InconclusiveCount);
- if (wasCached) { Interlocked.Increment(ref stats.CachedInconclusiveCount); }
- break;
- case VCGen.Outcome.Errors:
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
- {
- Interlocked.Increment(ref stats.ErrorCount);
- if (wasCached) { Interlocked.Increment(ref stats.CachedErrorCount); }
- }
- else
- {
- Interlocked.Add(ref stats.ErrorCount, errors.Count);
- if (wasCached) { Interlocked.Add(ref stats.CachedErrorCount, errors.Count); }
- }
- break;
- }
- }
-
-
- private static void ProcessErrors(List<Counterexample> errors, VC.VCGen.Outcome outcome, TextWriter tw, ErrorReporterDelegate er, Implementation impl = null)
- {
- var implName = impl != null ? impl.Name : null;
-
- if (errors != null)
- {
- errors.Sort(new CounterexampleComparer());
- foreach (Counterexample error in errors)
- {
- var errorInfo = CreateErrorInformation(error, outcome);
- errorInfo.ImplementationName = implName;
-
- if (CommandLineOptions.Clo.XmlSink != null)
- {
- WriteErrorInformationToXmlSink(errorInfo, error.Trace);
- }
-
- if (CommandLineOptions.Clo.EnhancedErrorMessages == 1)
- {
- foreach (string info in error.relatedInformation)
- {
- Contract.Assert(info != null);
- errorInfo.Out.WriteLine(" " + info);
- }
- }
- if (CommandLineOptions.Clo.ErrorTrace > 0)
- {
- errorInfo.Out.WriteLine("Execution trace:");
- error.Print(4, errorInfo.Out, b => { errorInfo.AddAuxInfo(b.tok, b.Label, "Execution trace"); });
- }
- if (CommandLineOptions.Clo.ModelViewFile != null)
- {
- error.PrintModel(errorInfo.Model);
- }
-
- printer.WriteErrorInformation(errorInfo, tw);
-
- if (er != null)
- {
- lock (er)
- {
- er(errorInfo);
- }
- }
- }
- }
- }
-
-
- private static ErrorInformation CreateErrorInformation(Counterexample error, VC.VCGen.Outcome outcome)
- {
- // BP1xxx: Parsing errors
- // BP2xxx: Name resolution errors
- // BP3xxx: Typechecking errors
- // BP4xxx: Abstract interpretation errors (Is there such a thing?)
- // BP5xxx: Verification errors
-
- ErrorInformation errorInfo;
- var cause = "Error";
- if (outcome == VCGen.Outcome.TimedOut)
- {
- cause = "Timed out on";
- }
- else if (outcome == VCGen.Outcome.OutOfMemory)
- {
- cause = "Out of memory on";
- }
-
- var callError = error as CallCounterexample;
- var returnError = error as ReturnCounterexample;
- var assertError = error as AssertCounterexample;
- if (callError != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(callError.FailingCall.tok, callError.FailingCall.ErrorData as string ?? "A precondition for this call might not hold.", callError.RequestId, callError.OriginalRequestId, cause);
- errorInfo.BoogieErrorCode = "BP5002";
- errorInfo.Kind = ErrorKind.Precondition;
- errorInfo.AddAuxInfo(callError.FailingRequires.tok, callError.FailingRequires.ErrorData as string ?? "This is the precondition that might not hold.", "Related location");
-
- if (!CommandLineOptions.Clo.ForceBplErrors && callError.FailingRequires.ErrorMessage != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(null, callError.FailingRequires.ErrorMessage, callError.RequestId, callError.OriginalRequestId, cause);
- }
- }
- else if (returnError != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(returnError.FailingReturn.tok, "A postcondition might not hold on this return path.", returnError.RequestId, returnError.OriginalRequestId, cause);
- errorInfo.BoogieErrorCode = "BP5003";
- errorInfo.Kind = ErrorKind.Postcondition;
- errorInfo.AddAuxInfo(returnError.FailingEnsures.tok, returnError.FailingEnsures.ErrorData as string ?? "This is the postcondition that might not hold.", "Related location");
-
- if (!CommandLineOptions.Clo.ForceBplErrors && returnError.FailingEnsures.ErrorMessage != null)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(null, returnError.FailingEnsures.ErrorMessage, returnError.RequestId, returnError.OriginalRequestId, cause);
- }
- }
- else // error is AssertCounterexample
- {
- if (assertError.FailingAssert is LoopInitAssertCmd)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(assertError.FailingAssert.tok, "This loop invariant might not hold on entry.", assertError.RequestId, assertError.OriginalRequestId, cause);
- errorInfo.BoogieErrorCode = "BP5004";
- errorInfo.Kind = ErrorKind.InvariantEntry;
- }
- else if (assertError.FailingAssert is LoopInvMaintainedAssertCmd)
- {
- errorInfo = errorInformationFactory.CreateErrorInformation(assertError.FailingAssert.tok, "This loop invariant might not be maintained by the loop.", assertError.RequestId, assertError.OriginalRequestId, cause);
- errorInfo.BoogieErrorCode = "BP5005";
- errorInfo.Kind = ErrorKind.InvariantMaintainance;
- }
- else
- {
- var msg = assertError.FailingAssert.ErrorData as string;
- var tok = assertError.FailingAssert.tok;
- if (!CommandLineOptions.Clo.ForceBplErrors && assertError.FailingAssert.ErrorMessage != null)
- {
- msg = assertError.FailingAssert.ErrorMessage;
- tok = null;
- if (cause == "Error")
- {
- cause = null;
- }
- }
- string bec = null;
- if (msg == null)
- {
- msg = "This assertion might not hold.";
- bec = "BP5001";
- }
-
- errorInfo = errorInformationFactory.CreateErrorInformation(tok, msg, assertError.RequestId, assertError.OriginalRequestId, cause);
- errorInfo.BoogieErrorCode = bec;
- errorInfo.Kind = ErrorKind.Assertion;
- }
- }
-
- return errorInfo;
- }
-
-
- private static void WriteErrorInformationToXmlSink(ErrorInformation errorInfo, List<Block> trace)
- {
- var msg = "assertion violation";
- switch (errorInfo.Kind)
- {
- case ErrorKind.Precondition:
- msg = "precondition violation";
- break;
-
- case ErrorKind.Postcondition:
- msg = "postcondition violation";
- break;
-
- case ErrorKind.InvariantEntry:
- msg = "loop invariant entry violation";
- break;
-
- case ErrorKind.InvariantMaintainance:
- msg = "loop invariant maintenance violation";
- break;
- }
-
- var relatedError = errorInfo.Aux.FirstOrDefault();
- CommandLineOptions.Clo.XmlSink.WriteError(msg, errorInfo.Tok, relatedError.Tok, trace);
- }
-
- }
-
-}
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using VC;
+using BoogiePL = Microsoft.Boogie;
+using System.Diagnostics;
+using System.Runtime.Caching;
+
+namespace Microsoft.Boogie
+{
+
+ #region Output printing
+
+ public interface OutputPrinter
+ {
+ void ErrorWriteLine(TextWriter tw, string s);
+ void ErrorWriteLine(TextWriter tw, string format, params object[] args);
+ void AdvisoryWriteLine(string format, params object[] args);
+ void Inform(string s, TextWriter tw);
+ void WriteTrailer(PipelineStatistics stats);
+ void WriteErrorInformation(ErrorInformation errorInfo, TextWriter tw, bool skipExecutionTrace = true);
+ void ReportBplError(IToken tok, string message, bool error, TextWriter tw, string category = null);
+ }
+
+
+ public class ConsolePrinter : OutputPrinter
+ {
+ public void ErrorWriteLine(TextWriter tw, string s)
+ {
+ Contract.Requires(s != null);
+ if (!s.Contains("Error: ") && !s.Contains("Error BP"))
+ {
+ tw.WriteLine(s);
+ return;
+ }
+
+ // split the string up into its first line and the remaining lines
+ string remaining = null;
+ int i = s.IndexOf('\r');
+ if (0 <= i)
+ {
+ remaining = s.Substring(i + 1);
+ if (remaining.StartsWith("\n"))
+ {
+ remaining = remaining.Substring(1);
+ }
+ s = s.Substring(0, i);
+ }
+
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ tw.WriteLine(s);
+ Console.ForegroundColor = col;
+
+ if (remaining != null)
+ {
+ tw.WriteLine(remaining);
+ }
+ }
+
+
+ public void ErrorWriteLine(TextWriter tw, string format, params object[] args)
+ {
+ Contract.Requires(format != null);
+ string s = string.Format(format, args);
+ ErrorWriteLine(tw, s);
+ }
+
+
+ public void AdvisoryWriteLine(string format, params object[] args)
+ {
+ Contract.Requires(format != null);
+ ConsoleColor col = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine(format, args);
+ Console.ForegroundColor = col;
+ }
+
+
+ /// <summary>
+ /// Inform the user about something and proceed with translation normally.
+ /// Print newline after the message.
+ /// </summary>
+ public void Inform(string s, TextWriter tw)
+ {
+ if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.TraceProofObligations)
+ {
+ tw.WriteLine(s);
+ }
+ }
+
+
+ public void WriteTrailer(PipelineStatistics stats)
+ {
+ Contract.Requires(stats != null);
+ Contract.Requires(0 <= stats.VerifiedCount && 0 <= stats.ErrorCount && 0 <= stats.InconclusiveCount && 0 <= stats.TimeoutCount && 0 <= stats.OutOfMemoryCount);
+
+ Console.WriteLine();
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
+ {
+ Console.Write("{0} finished with {1} credible, {2} doomed{3}", CommandLineOptions.Clo.DescriptiveToolName, stats.VerifiedCount, stats.ErrorCount, stats.ErrorCount == 1 ? "" : "s");
+ }
+ else
+ {
+ Console.Write("{0} finished with {1} verified, {2} error{3}", CommandLineOptions.Clo.DescriptiveToolName, stats.VerifiedCount, stats.ErrorCount, stats.ErrorCount == 1 ? "" : "s");
+ }
+ if (stats.InconclusiveCount != 0)
+ {
+ Console.Write(", {0} inconclusive{1}", stats.InconclusiveCount, stats.InconclusiveCount == 1 ? "" : "s");
+ }
+ if (stats.TimeoutCount != 0)
+ {
+ Console.Write(", {0} time out{1}", stats.TimeoutCount, stats.TimeoutCount == 1 ? "" : "s");
+ }
+ if (stats.OutOfMemoryCount != 0)
+ {
+ Console.Write(", {0} out of memory", stats.OutOfMemoryCount);
+ }
+ Console.WriteLine();
+ Console.Out.Flush();
+ }
+
+
+ public void WriteErrorInformation(ErrorInformation errorInfo, TextWriter tw, bool skipExecutionTrace = true)
+ {
+ Contract.Requires(errorInfo != null);
+
+ ReportBplError(errorInfo.Tok, errorInfo.FullMsg, true, tw);
+
+ foreach (var e in errorInfo.Aux)
+ {
+ if (!(skipExecutionTrace && e.Category != null && e.Category.Contains("Execution trace")))
+ {
+ ReportBplError(e.Tok, e.FullMsg, false, tw);
+ }
+ }
+
+ tw.Write(errorInfo.Out.ToString());
+ tw.Write(errorInfo.Model.ToString());
+ tw.Flush();
+ }
+
+
+ public virtual void ReportBplError(IToken tok, string message, bool error, TextWriter tw, string category = null)
+ {
+ Contract.Requires(message != null);
+
+ if (category != null) {
+ message = string.Format("{0}: {1}", category, message);
+ }
+ string s;
+ if (tok != null) {
+ s = string.Format("{0}({1},{2}): {3}", ExecutionEngine.GetFileNameForConsole(tok.filename), tok.line, tok.col, message);
+ } else {
+ s = message;
+ }
+ if (error) {
+ ErrorWriteLine(tw, s);
+ } else {
+ tw.WriteLine(s);
+ }
+ }
+ }
+
+ #endregion
+
+
+ public enum PipelineOutcome
+ {
+ Done,
+ ResolutionError,
+ TypeCheckingError,
+ ResolvedAndTypeChecked,
+ FatalError,
+ VerificationCompleted
+ }
+
+
+ public class PipelineStatistics
+ {
+ public int ErrorCount;
+ public int VerifiedCount;
+ public int InconclusiveCount;
+ public int TimeoutCount;
+ public int OutOfMemoryCount;
+ public long[] CachingActionCounts;
+ public int CachedErrorCount;
+ public int CachedVerifiedCount;
+ public int CachedInconclusiveCount;
+ public int CachedTimeoutCount;
+ public int CachedOutOfMemoryCount;
+ }
+
+
+ #region Error reporting
+
+ public delegate void ErrorReporterDelegate(ErrorInformation errInfo);
+
+
+ public enum ErrorKind
+ {
+ Assertion,
+ Precondition,
+ Postcondition,
+ InvariantEntry,
+ InvariantMaintainance
+ }
+
+
+ public class ErrorInformationFactory
+ {
+ public virtual ErrorInformation CreateErrorInformation(IToken tok, string msg, string requestId = null, string originalRequestId = null, string category = null)
+ {
+ Contract.Requires(1 <= tok.line && 1 <= tok.col);
+ Contract.Requires(msg != null);
+
+ return ErrorInformation.CreateErrorInformation(tok, msg, requestId, originalRequestId, category);
+ }
+ }
+
+
+ public class ErrorInformation
+ {
+ public readonly IToken Tok;
+ public string Msg;
+ public string Category { get; set; }
+ public string BoogieErrorCode { get; set; }
+ public readonly List<AuxErrorInfo> Aux = new List<AuxErrorInfo>();
+ public string OriginalRequestId { get; set; }
+ public string RequestId { get; set; }
+ public ErrorKind Kind { get; set; }
+ public string ImplementationName { get; set; }
+ public TextWriter Out = new StringWriter();
+ public TextWriter Model = new StringWriter();
+
+ public string FullMsg
+ {
+ get
+ {
+ var prefix = Category;
+ if (BoogieErrorCode != null)
+ {
+ prefix = prefix == null ? BoogieErrorCode : prefix + " " + BoogieErrorCode;
+ }
+ return prefix != null ? string.Format("{0}: {1}", prefix, Msg) : Msg;
+ }
+ }
+
+ public struct AuxErrorInfo
+ {
+ public readonly IToken Tok;
+ public readonly string Msg;
+ public readonly string Category;
+
+ public string FullMsg
+ {
+ get
+ {
+ return Category != null ? string.Format("{0}: {1}", Category, Msg) : Msg;
+ }
+ }
+
+ public AuxErrorInfo(IToken tok, string msg, string category = null)
+ {
+ Tok = tok;
+ Msg = CleanUp(msg);
+ Category = category;
+ }
+ }
+
+ protected ErrorInformation(IToken tok, string msg)
+ {
+ Contract.Requires(tok != null);
+ Contract.Requires(1 <= tok.line && 1 <= tok.col);
+ Contract.Requires(msg != null);
+
+ Tok = tok;
+ Msg = CleanUp(msg);
+ }
+
+ internal static ErrorInformation CreateErrorInformation(IToken tok, string msg, string requestId = null, string originalRequestId = null, string category = null)
+ {
+ var result = new ErrorInformation(tok, msg);
+ result.RequestId = requestId;
+ result.OriginalRequestId = originalRequestId;
+ result.Category = category;
+ return result;
+ }
+
+ public virtual void AddAuxInfo(IToken tok, string msg, string category = null)
+ {
+ Contract.Requires(tok != null);
+ Contract.Requires(1 <= tok.line && 1 <= tok.col);
+ Contract.Requires(msg != null);
+ Aux.Add(new AuxErrorInfo(tok, msg, category));
+ }
+
+ protected static string CleanUp(string msg)
+ {
+ if (msg.ToLower().StartsWith("error: "))
+ {
+ return msg.Substring(7);
+ }
+ else
+ {
+ return msg;
+ }
+ }
+ }
+
+ #endregion
+
+
+ public sealed class VerificationResult
+ {
+ public readonly string RequestId;
+ public readonly string Checksum;
+ public readonly string DependeciesChecksum;
+ public readonly string ImplementationName;
+ public readonly IToken ImplementationToken;
+ public readonly string ProgramId;
+
+ public DateTime Start { get; set; }
+ public DateTime End { get; set; }
+
+ public int ProofObligationCount { get { return ProofObligationCountAfter - ProofObligationCountBefore; } }
+ public int ProofObligationCountBefore { get; set; }
+ public int ProofObligationCountAfter { get; set; }
+
+ public ConditionGeneration.Outcome Outcome { get; set; }
+ public List<Counterexample> Errors;
+
+ public ISet<byte[]> AssertionChecksums { get; private set; }
+
+ public VerificationResult(string requestId, Implementation implementation, string programId = null)
+ {
+ Checksum = implementation.Checksum;
+ DependeciesChecksum = implementation.DependencyChecksum;
+ RequestId = requestId;
+ ImplementationName = implementation.Name;
+ ImplementationToken = implementation.tok;
+ ProgramId = programId;
+ AssertionChecksums = implementation.AssertionChecksums;
+ }
+ }
+
+
+ public class PolymorphismChecker : ReadOnlyVisitor
+ {
+ bool isMonomorphic = true;
+
+ public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node)
+ {
+ if (node.TypeParameters.Count > 0)
+ isMonomorphic = false;
+ return base.VisitDeclWithFormals(node);
+ }
+
+ public override BinderExpr VisitBinderExpr(BinderExpr node)
+ {
+ if (node.TypeParameters.Count > 0)
+ isMonomorphic = false;
+ return base.VisitBinderExpr(node);
+ }
+
+ public override MapType VisitMapType(MapType node)
+ {
+ if (node.TypeParameters.Count > 0)
+ isMonomorphic = false;
+ return base.VisitMapType(node);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ BinaryOperator op = node.Fun as BinaryOperator;
+ if (op != null && op.Op == BinaryOperator.Opcode.Subtype)
+ isMonomorphic = false;
+ return base.VisitNAryExpr(node);
+ }
+
+ public static bool IsMonomorphic(Program program)
+ {
+ var checker = new PolymorphismChecker();
+ checker.VisitProgram(program);
+ return checker.isMonomorphic;
+ }
+ }
+
+ public class ExecutionEngine
+ {
+ public static OutputPrinter printer;
+
+ public static ErrorInformationFactory errorInformationFactory = new ErrorInformationFactory();
+
+ static int autoRequestIdCount;
+
+ static readonly string AutoRequestIdPrefix = "auto_request_id_";
+
+ public static string FreshRequestId()
+ {
+ var id = Interlocked.Increment(ref autoRequestIdCount);
+ return AutoRequestIdPrefix + id;
+ }
+
+ public static int AutoRequestId(string id)
+ {
+ if (id.StartsWith(AutoRequestIdPrefix))
+ {
+ int result;
+ if (int.TryParse(id.Substring(AutoRequestIdPrefix.Length), out result))
+ {
+ return result;
+ }
+ }
+ return -1;
+ }
+
+ public readonly static VerificationResultCache Cache = new VerificationResultCache();
+
+ static readonly MemoryCache programCache = new MemoryCache("ProgramCache");
+ static readonly CacheItemPolicy policy = new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, 10, 0), Priority = CacheItemPriority.Default };
+
+ public static Program CachedProgram(string programId)
+ {
+ var result = programCache.Get(programId) as Program;
+ return result;
+ }
+
+ static List<Checker> Checkers = new List<Checker>();
+
+ static DateTime FirstRequestStart;
+
+ static readonly ConcurrentDictionary<string, TimeSpan> TimePerRequest = new ConcurrentDictionary<string, TimeSpan>();
+ static readonly ConcurrentDictionary<string, PipelineStatistics> StatisticsPerRequest = new ConcurrentDictionary<string, PipelineStatistics>();
+
+ static readonly ConcurrentDictionary<string, CancellationTokenSource> ImplIdToCancellationTokenSource = new ConcurrentDictionary<string, CancellationTokenSource>();
+
+ static readonly ConcurrentDictionary<string, CancellationTokenSource> RequestIdToCancellationTokenSource = new ConcurrentDictionary<string, CancellationTokenSource>();
+
+ public static void ProcessFiles(List<string> fileNames, bool lookForSnapshots = true, string programId = null)
+ {
+ Contract.Requires(cce.NonNullElements(fileNames));
+
+ if (programId == null)
+ {
+ programId = "main_program_id";
+ }
+
+ if (CommandLineOptions.Clo.VerifySeparately && 1 < fileNames.Count)
+ {
+ foreach (var f in fileNames)
+ {
+ ProcessFiles(new List<string> { f }, lookForSnapshots, f);
+ }
+ return;
+ }
+
+ if (0 <= CommandLineOptions.Clo.VerifySnapshots && lookForSnapshots)
+ {
+ var snapshotsByVersion = LookForSnapshots(fileNames);
+ foreach (var s in snapshotsByVersion)
+ {
+ ProcessFiles(new List<string>(s), false, programId);
+ }
+ return;
+ }
+
+ using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count - 1]))
+ {
+ Program program = ParseBoogieProgram(fileNames, false);
+ if (program == null)
+ return;
+ if (CommandLineOptions.Clo.PrintFile != null)
+ {
+ PrintBplFile(CommandLineOptions.Clo.PrintFile, program, false, true, CommandLineOptions.Clo.PrettyPrint);
+ }
+
+ LinearTypeChecker linearTypeChecker;
+ CivlTypeChecker civlTypeChecker;
+ PipelineOutcome oc = ResolveAndTypecheck(program, fileNames[fileNames.Count - 1], out linearTypeChecker, out civlTypeChecker);
+ if (oc != PipelineOutcome.ResolvedAndTypeChecked)
+ return;
+
+ if (CommandLineOptions.Clo.PrintCFGPrefix != null)
+ {
+ foreach (var impl in program.Implementations)
+ {
+ using (StreamWriter sw = new StreamWriter(CommandLineOptions.Clo.PrintCFGPrefix + "." + impl.Name + ".dot"))
+ {
+ sw.Write(program.ProcessLoops(impl).ToDot());
+ }
+ }
+ }
+
+ if (CommandLineOptions.Clo.StratifiedInlining == 0)
+ {
+ Concurrency.Transform(linearTypeChecker, civlTypeChecker);
+ (new LinearEraser()).VisitProgram(program);
+ if (CommandLineOptions.Clo.CivlDesugaredFile != null)
+ {
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 1;
+ PrintBplFile(CommandLineOptions.Clo.CivlDesugaredFile, program, false, false, CommandLineOptions.Clo.PrettyPrint);
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+ }
+
+ EliminateDeadVariables(program);
+
+ CoalesceBlocks(program);
+
+ Inline(program);
+
+ var stats = new PipelineStatistics();
+ oc = InferAndVerify(program, stats, 1 < CommandLineOptions.Clo.VerifySnapshots ? programId : null);
+ switch (oc)
+ {
+ case PipelineOutcome.Done:
+ case PipelineOutcome.VerificationCompleted:
+ printer.WriteTrailer(stats);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ public static IList<IList<string>> LookForSnapshots(IList<string> fileNames)
+ {
+ Contract.Requires(fileNames != null);
+
+ var result = new List<IList<string>>();
+ for (int version = 0; true; version++)
+ {
+ var nextSnapshot = new List<string>();
+ foreach (var name in fileNames)
+ {
+ var versionedName = name.Replace(Path.GetExtension(name), ".v" + version + Path.GetExtension(name));
+ if (File.Exists(versionedName))
+ {
+ nextSnapshot.Add(versionedName);
+ }
+ }
+ if (nextSnapshot.Any())
+ {
+ result.Add(nextSnapshot);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ public static void CoalesceBlocks(Program program)
+ {
+ if (CommandLineOptions.Clo.CoalesceBlocks)
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Coalescing blocks...");
+ Microsoft.Boogie.BlockCoalescer.CoalesceBlocks(program);
+ }
+ }
+
+
+ public static void CollectModSets(Program program)
+ {
+ if (CommandLineOptions.Clo.DoModSetAnalysis)
+ {
+ new ModSetCollector().DoModSetAnalysis(program);
+ }
+ }
+
+
+ public static void EliminateDeadVariables(Program program)
+ {
+ Microsoft.Boogie.UnusedVarEliminator.Eliminate(program);
+ }
+
+
+ public static void PrintBplFile(string filename, Program program, bool allowPrintDesugaring, bool setTokens = true, bool pretty = false)
+ {
+ Contract.Requires(program != null);
+ Contract.Requires(filename != null);
+ bool oldPrintDesugaring = CommandLineOptions.Clo.PrintDesugarings;
+ if (!allowPrintDesugaring)
+ {
+ CommandLineOptions.Clo.PrintDesugarings = false;
+ }
+ using (TokenTextWriter writer = filename == "-" ?
+ new TokenTextWriter("<console>", Console.Out, setTokens, pretty) :
+ new TokenTextWriter(filename, setTokens, pretty))
+ {
+ if (CommandLineOptions.Clo.ShowEnv != CommandLineOptions.ShowEnvironment.Never)
+ {
+ writer.WriteLine("// " + CommandLineOptions.Clo.Version);
+ writer.WriteLine("// " + CommandLineOptions.Clo.Environment);
+ }
+ writer.WriteLine();
+ program.Emit(writer);
+ }
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaring;
+ }
+
+
+ /// <summary>
+ /// Parse the given files into one Boogie program. If an I/O or parse error occurs, an error will be printed
+ /// and null will be returned. On success, a non-null program is returned.
+ /// </summary>
+ public static Program ParseBoogieProgram(List<string> fileNames, bool suppressTraceOutput)
+ {
+ Contract.Requires(cce.NonNullElements(fileNames));
+
+ Program program = null;
+ bool okay = true;
+ for (int fileId = 0; fileId < fileNames.Count; fileId++)
+ {
+ string bplFileName = fileNames[fileId];
+ if (!suppressTraceOutput)
+ {
+ if (CommandLineOptions.Clo.XmlSink != null)
+ {
+ CommandLineOptions.Clo.XmlSink.WriteFileFragment(bplFileName);
+ }
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Parsing " + GetFileNameForConsole(bplFileName));
+ }
+ }
+
+ Program programSnippet;
+ int errorCount;
+ try
+ {
+ var defines = new List<string>() { "FILE_" + fileId };
+ errorCount = Parser.Parse(bplFileName, defines, out programSnippet, CommandLineOptions.Clo.UseBaseNameForFileName);
+ if (programSnippet == null || errorCount != 0)
+ {
+ Console.WriteLine("{0} parse errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName));
+ okay = false;
+ continue;
+ }
+ }
+ catch (IOException e)
+ {
+ printer.ErrorWriteLine(Console.Out, "Error opening file \"{0}\": {1}", GetFileNameForConsole(bplFileName), e.Message);
+ okay = false;
+ continue;
+ }
+ if (program == null)
+ {
+ program = programSnippet;
+ }
+ else if (programSnippet != null)
+ {
+ program.AddTopLevelDeclarations(programSnippet.TopLevelDeclarations);
+ }
+ }
+ if (!okay)
+ {
+ return null;
+ }
+ else if (program == null)
+ {
+ return new Program();
+ }
+ else
+ {
+ return program;
+ }
+ }
+
+ internal static string GetFileNameForConsole(string filename)
+ {
+ return (CommandLineOptions.Clo.UseBaseNameForFileName && !string.IsNullOrEmpty(filename) && filename != "<console>") ? System.IO.Path.GetFileName(filename) : filename;
+ }
+
+
+ /// <summary>
+ /// Resolves and type checks the given Boogie program. Any errors are reported to the
+ /// console. Returns:
+ /// - Done if no errors occurred, and command line specified no resolution or no type checking.
+ /// - ResolutionError if a resolution error occurred
+ /// - TypeCheckingError if a type checking error occurred
+ /// - ResolvedAndTypeChecked if both resolution and type checking succeeded
+ /// </summary>
+ public static PipelineOutcome ResolveAndTypecheck(Program program, string bplFileName, out LinearTypeChecker linearTypeChecker, out CivlTypeChecker civlTypeChecker)
+ {
+ Contract.Requires(program != null);
+ Contract.Requires(bplFileName != null);
+
+ linearTypeChecker = null;
+ civlTypeChecker = null;
+
+ // ---------- Resolve ------------------------------------------------------------
+
+ if (CommandLineOptions.Clo.NoResolve)
+ {
+ return PipelineOutcome.Done;
+ }
+
+ int errorCount = program.Resolve();
+ if (errorCount != 0)
+ {
+ Console.WriteLine("{0} name resolution errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName));
+ return PipelineOutcome.ResolutionError;
+ }
+
+ // ---------- Type check ------------------------------------------------------------
+
+ if (CommandLineOptions.Clo.NoTypecheck)
+ {
+ return PipelineOutcome.Done;
+ }
+
+ errorCount = program.Typecheck();
+ if (errorCount != 0)
+ {
+ Console.WriteLine("{0} type checking errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName));
+ return PipelineOutcome.TypeCheckingError;
+ }
+
+ if (PolymorphismChecker.IsMonomorphic(program))
+ {
+ CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic;
+ }
+
+ CollectModSets(program);
+
+ civlTypeChecker = new CivlTypeChecker(program);
+ civlTypeChecker.TypeCheck();
+ if (civlTypeChecker.errorCount != 0)
+ {
+ Console.WriteLine("{0} type checking errors detected in {1}", civlTypeChecker.errorCount, GetFileNameForConsole(bplFileName));
+ return PipelineOutcome.TypeCheckingError;
+ }
+
+ linearTypeChecker = new LinearTypeChecker(program);
+ linearTypeChecker.TypeCheck();
+ if (linearTypeChecker.errorCount == 0)
+ {
+ linearTypeChecker.Transform();
+ }
+ else
+ {
+ Console.WriteLine("{0} type checking errors detected in {1}", linearTypeChecker.errorCount, GetFileNameForConsole(bplFileName));
+ return PipelineOutcome.TypeCheckingError;
+ }
+
+ if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings)
+ {
+ // if PrintDesugaring option is engaged, print the file here, after resolution and type checking
+ PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true, true, CommandLineOptions.Clo.PrettyPrint);
+ }
+
+ return PipelineOutcome.ResolvedAndTypeChecked;
+ }
+
+
+ public static void Inline(Program program)
+ {
+ Contract.Requires(program != null);
+
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Inlining...");
+
+ // Inline
+ var TopLevelDeclarations = cce.NonNull(program.TopLevelDeclarations);
+
+ if (CommandLineOptions.Clo.ProcedureInlining != CommandLineOptions.Inlining.None)
+ {
+ bool inline = false;
+ foreach (var d in TopLevelDeclarations)
+ {
+ if ((d is Procedure || d is Implementation) && d.FindExprAttribute("inline") != null)
+ {
+ inline = true;
+ }
+ }
+ if (inline)
+ {
+ foreach (var impl in TopLevelDeclarations.OfType<Implementation>())
+ {
+ impl.OriginalBlocks = impl.Blocks;
+ impl.OriginalLocVars = impl.LocVars;
+ }
+ foreach (var impl in TopLevelDeclarations.OfType<Implementation>())
+ {
+ if (CommandLineOptions.Clo.UserWantsToCheckRoutine(impl.Name) && !impl.SkipVerification)
+ {
+ Inliner.ProcessImplementation(program, impl);
+ }
+ }
+ foreach (var impl in TopLevelDeclarations.OfType<Implementation>())
+ {
+ impl.OriginalBlocks = null;
+ impl.OriginalLocVars = null;
+ }
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Given a resolved and type checked Boogie program, infers invariants for the program
+ /// and then attempts to verify it. Returns:
+ /// - Done if command line specified no verification
+ /// - FatalError if a fatal error occurred, in which case an error has been printed to console
+ /// - VerificationCompleted if inference and verification completed, in which the out
+ /// parameters contain meaningful values
+ /// </summary>
+ public static PipelineOutcome InferAndVerify(Program program,
+ PipelineStatistics stats,
+ string programId = null,
+ ErrorReporterDelegate er = null, string requestId = null)
+ {
+ Contract.Requires(program != null);
+ Contract.Requires(stats != null);
+ Contract.Ensures(0 <= Contract.ValueAtReturn(out stats.InconclusiveCount) && 0 <= Contract.ValueAtReturn(out stats.TimeoutCount));
+
+ if (requestId == null)
+ {
+ requestId = FreshRequestId();
+ }
+
+ var start = DateTime.UtcNow;
+
+ #region Do some pre-abstract-interpretation preprocessing on the program
+ // Doing lambda expansion before abstract interpretation means that the abstract interpreter
+ // never needs to see any lambda expressions. (On the other hand, if it were useful for it
+ // to see lambdas, then it would be better to more lambda expansion until after infererence.)
+ if (CommandLineOptions.Clo.ExpandLambdas) {
+ LambdaHelper.ExpandLambdas(program);
+ //PrintBplFile ("-", program, true);
+ }
+ #endregion
+
+ #region Infer invariants using Abstract Interpretation
+
+ // Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
+ if (CommandLineOptions.Clo.UseAbstractInterpretation)
+ {
+ if (!CommandLineOptions.Clo.Ai.J_Intervals && !CommandLineOptions.Clo.Ai.J_Trivial)
+ {
+ // use /infer:j as the default
+ CommandLineOptions.Clo.Ai.J_Intervals = true;
+ }
+ }
+ Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program);
+
+ #endregion
+
+ #region Do some post-abstract-interpretation preprocessing on the program (e.g., loop unrolling)
+
+ if (CommandLineOptions.Clo.LoopUnrollCount != -1)
+ {
+ program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount, CommandLineOptions.Clo.SoundLoopUnrolling);
+ }
+
+ Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo = null;
+ if (CommandLineOptions.Clo.ExtractLoops)
+ {
+ extractLoopMappingInfo = program.ExtractLoops();
+ }
+
+ if (CommandLineOptions.Clo.PrintInstrumented)
+ {
+ program.Emit(new TokenTextWriter(Console.Out, CommandLineOptions.Clo.PrettyPrint));
+ }
+ #endregion
+
+ if (!CommandLineOptions.Clo.Verify)
+ {
+ return PipelineOutcome.Done;
+ }
+
+ #region Run Houdini and verify
+ if (CommandLineOptions.Clo.ContractInfer)
+ {
+ return RunHoudini(program, stats, er);
+ }
+ #endregion
+
+ #region Select and prioritize implementations that should be verified
+
+ var impls = program.Implementations.Where(
+ impl => impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine(cce.NonNull(impl.Name)) && !impl.SkipVerification);
+
+ // operate on a stable copy, in case it gets updated while we're running
+ Implementation[] stablePrioritizedImpls = null;
+ if (0 < CommandLineOptions.Clo.VerifySnapshots)
+ {
+ OtherDefinitionAxiomsCollector.Collect(program.Axioms);
+ DependencyCollector.Collect(program);
+ stablePrioritizedImpls = impls.OrderByDescending(
+ impl => impl.Priority != 1 ? impl.Priority : Cache.VerificationPriority(impl)).ToArray();
+ }
+ else
+ {
+ stablePrioritizedImpls = impls.OrderByDescending(impl => impl.Priority).ToArray();
+ }
+
+ #endregion
+
+ if (1 < CommandLineOptions.Clo.VerifySnapshots)
+ {
+ CachedVerificationResultInjector.Inject(program, stablePrioritizedImpls, requestId, programId, out stats.CachingActionCounts);
+ }
+
+ #region Verify each implementation
+
+ var outputCollector = new OutputCollector(stablePrioritizedImpls);
+ var outcome = PipelineOutcome.VerificationCompleted;
+
+ try
+ {
+ var cts = new CancellationTokenSource();
+ RequestIdToCancellationTokenSource.AddOrUpdate(requestId, cts, (k, ov) => cts);
+
+ var tasks = new Task[stablePrioritizedImpls.Length];
+ // We use this semaphore to limit the number of tasks that are currently executing.
+ var semaphore = new SemaphoreSlim(CommandLineOptions.Clo.VcsCores);
+
+ // Create a task per implementation.
+ for (int i = 0; i < stablePrioritizedImpls.Length; i++)
+ {
+ var taskIndex = i;
+ var id = stablePrioritizedImpls[taskIndex].Id;
+
+ CancellationTokenSource old;
+ if (ImplIdToCancellationTokenSource.TryGetValue(id, out old))
+ {
+ old.Cancel();
+ }
+ ImplIdToCancellationTokenSource.AddOrUpdate(id, cts, (k, ov) => cts);
+
+ var t = new Task((dummy) =>
+ {
+ try
+ {
+ if (outcome == PipelineOutcome.FatalError)
+ {
+ return;
+ }
+ if (cts.Token.IsCancellationRequested)
+ {
+ cts.Token.ThrowIfCancellationRequested();
+ }
+ VerifyImplementation(program, stats, er, requestId, extractLoopMappingInfo, stablePrioritizedImpls, taskIndex, outputCollector, Checkers, programId);
+ ImplIdToCancellationTokenSource.TryRemove(id, out old);
+ }
+ finally
+ {
+ semaphore.Release();
+ }
+ }, cts.Token, TaskCreationOptions.None);
+ tasks[taskIndex] = t;
+ }
+
+ // Execute the tasks.
+ int j = 0;
+ for (; j < stablePrioritizedImpls.Length && outcome != PipelineOutcome.FatalError; j++)
+ {
+ try
+ {
+ semaphore.Wait(cts.Token);
+ }
+ catch (OperationCanceledException)
+ {
+ break;
+ }
+ tasks[j].Start(TaskScheduler.Default);
+ }
+
+ // Don't wait for tasks that haven't been started yet.
+ tasks = tasks.Take(j).ToArray();
+ Task.WaitAll(tasks);
+ }
+ catch (AggregateException ae)
+ {
+ ae.Handle(e =>
+ {
+ var pe = e as ProverException;
+ if (pe != null)
+ {
+ printer.ErrorWriteLine(Console.Out, "Fatal Error: ProverException: {0}", e);
+ outcome = PipelineOutcome.FatalError;
+ return true;
+ }
+ var oce = e as OperationCanceledException;
+ if (oce != null)
+ {
+ return true;
+ }
+ return false;
+ });
+ }
+ finally
+ {
+ CleanupCheckers(requestId);
+ }
+
+ if (CommandLineOptions.Clo.PrintNecessaryAssumes && program.NecessaryAssumes.Any())
+ {
+ Console.WriteLine("Necessary assume command(s): {0}", string.Join(", ", program.NecessaryAssumes));
+ }
+
+ cce.NonNull(CommandLineOptions.Clo.TheProverFactory).Close();
+
+ outputCollector.WriteMoreOutput();
+
+ if (1 < CommandLineOptions.Clo.VerifySnapshots && programId != null)
+ {
+ program.FreezeTopLevelDeclarations();
+ programCache.Set(programId, program, policy);
+ }
+
+ if (0 <= CommandLineOptions.Clo.VerifySnapshots && CommandLineOptions.Clo.TraceCachingForBenchmarking)
+ {
+ var end = DateTime.UtcNow;
+ if (TimePerRequest.Count == 0)
+ {
+ FirstRequestStart = start;
+ }
+ TimePerRequest[requestId] = end.Subtract(start);
+ StatisticsPerRequest[requestId] = stats;
+
+ var printTimes = true;
+
+ Console.Out.WriteLine(CachedVerificationResultInjector.Statistics.Output(printTimes));
+
+ Console.Out.WriteLine("Statistics per request as CSV:");
+ var actions = string.Join(", ", Enum.GetNames(typeof(VC.ConditionGeneration.CachingAction)));
+ Console.Out.WriteLine("Request ID{0}, Error, E (C), Inconclusive, I (C), Out of Memory, OoM (C), Timeout, T (C), Verified, V (C), {1}", printTimes ? ", Time (ms)" : "", actions);
+ foreach (var kv in TimePerRequest.OrderBy(kv => ExecutionEngine.AutoRequestId(kv.Key)))
+ {
+ var s = StatisticsPerRequest[kv.Key];
+ var cacs = s.CachingActionCounts;
+ var c = cacs != null ? ", " + cacs.Select(ac => string.Format("{0,3}", ac)).Concat(", ") : "";
+ var t = printTimes ? string.Format(", {0,8:F0}", kv.Value.TotalMilliseconds) : "";
+ Console.Out.WriteLine("{0,-19}{1}, {2,2}, {3,2}, {4,2}, {5,2}, {6,2}, {7,2}, {8,2}, {9,2}, {10,2}, {11,2}{12}", kv.Key, t, s.ErrorCount, s.CachedErrorCount, s.InconclusiveCount, s.CachedInconclusiveCount, s.OutOfMemoryCount, s.CachedOutOfMemoryCount, s.TimeoutCount, s.CachedTimeoutCount, s.VerifiedCount, s.CachedVerifiedCount, c);
+ }
+
+ if (printTimes)
+ {
+ Console.Out.WriteLine();
+ Console.Out.WriteLine("Total time (ms) since first request: {0:F0}", end.Subtract(FirstRequestStart).TotalMilliseconds);
+ }
+ }
+
+ #endregion
+
+ if (SecureVCGen.outfile != null)
+ SecureVCGen.outfile.Close();
+
+ return outcome;
+ }
+
+ public static void CancelRequest(string requestId)
+ {
+ Contract.Requires(requestId != null);
+
+ CancellationTokenSource cts;
+ if (RequestIdToCancellationTokenSource.TryGetValue(requestId, out cts))
+ {
+ cts.Cancel();
+
+ CleanupCheckers(requestId);
+ }
+ }
+
+
+ private static void CleanupCheckers(string requestId)
+ {
+ if (requestId != null)
+ {
+ CancellationTokenSource old;
+ RequestIdToCancellationTokenSource.TryRemove(requestId, out old);
+ }
+ lock (RequestIdToCancellationTokenSource)
+ {
+ if (RequestIdToCancellationTokenSource.IsEmpty)
+ {
+ lock (Checkers)
+ {
+ foreach (Checker checker in Checkers)
+ {
+ Contract.Assert(checker != null);
+ checker.Close();
+ }
+ }
+ }
+ }
+ }
+
+
+ private static void VerifyImplementation(Program program, PipelineStatistics stats, ErrorReporterDelegate er, string requestId, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo, Implementation[] stablePrioritizedImpls, int index, OutputCollector outputCollector, List<Checker> checkers, string programId)
+ {
+ Implementation impl = stablePrioritizedImpls[index];
+ VerificationResult verificationResult = null;
+ var output = new StringWriter();
+
+ printer.Inform("", output); // newline
+ printer.Inform(string.Format("Verifying {0} ...", impl.Name), output);
+
+ int priority = 0;
+ var wasCached = false;
+ if (0 < CommandLineOptions.Clo.VerifySnapshots) {
+ var cachedResults = Cache.Lookup(impl, out priority);
+ if (cachedResults != null && priority == Priority.SKIP) {
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, cachedResults.Start);
+ }
+
+ printer.Inform(string.Format("Retrieving cached verification result for implementation {0}...", impl.Name), output);
+ if (CommandLineOptions.Clo.VerifySnapshots < 3 || cachedResults.Outcome == ConditionGeneration.Outcome.Correct) {
+ verificationResult = cachedResults;
+ wasCached = true;
+ }
+ }
+ }
+
+ if (!wasCached)
+ {
+ #region Verify the implementation
+
+ verificationResult = new VerificationResult(requestId, impl, programId);
+
+ using (var vcgen = CreateVCGen(program, checkers))
+ {
+ vcgen.CachingActionCounts = stats.CachingActionCounts;
+ verificationResult.ProofObligationCountBefore = vcgen.CumulativeAssertionCount;
+ verificationResult.Start = DateTime.UtcNow;
+
+ if (CommandLineOptions.Clo.XmlSink != null)
+ {
+ CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, verificationResult.Start);
+ }
+ try
+ {
+ if (CommandLineOptions.Clo.inferLeastForUnsat != null)
+ {
+ var svcgen = vcgen as VC.StratifiedVCGen;
+ Contract.Assert(svcgen != null);
+ var ss = new HashSet<string>();
+ foreach (var c in program.Constants)
+ {
+ if (!c.Name.StartsWith(CommandLineOptions.Clo.inferLeastForUnsat)) continue;
+ ss.Add(c.Name);
+ }
+ verificationResult.Outcome = svcgen.FindLeastToVerify(impl, ref ss);
+ verificationResult.Errors = new List<Counterexample>();
+ output.WriteLine("Result: {0}", string.Join(" ", ss));
+ }
+ else
+ {
+ verificationResult.Outcome = vcgen.VerifyImplementation(impl, out verificationResult.Errors, requestId);
+ if (CommandLineOptions.Clo.ExtractLoops && verificationResult.Errors != null)
+ {
+ var vcg = vcgen as VCGen;
+ if (vcg != null)
+ {
+ for (int i = 0; i < verificationResult.Errors.Count; i++)
+ {
+ verificationResult.Errors[i] = vcg.extractLoopTrace(verificationResult.Errors[i], impl.Name, program, extractLoopMappingInfo);
+ }
+ }
+ }
+ }
+ }
+ catch (VCGenException e)
+ {
+ var errorInfo = errorInformationFactory.CreateErrorInformation(impl.tok, String.Format("{0} (encountered in implementation {1}).", e.Message, impl.Name), requestId, "Error");
+ errorInfo.BoogieErrorCode = "BP5010";
+ errorInfo.ImplementationName = impl.Name;
+ printer.WriteErrorInformation(errorInfo, output);
+ if (er != null)
+ {
+ lock (er)
+ {
+ er(errorInfo);
+ }
+ }
+ verificationResult.Errors = null;
+ verificationResult.Outcome = VCGen.Outcome.Inconclusive;
+ }
+ catch (UnexpectedProverOutputException upo)
+ {
+ printer.AdvisoryWriteLine("Advisory: {0} SKIPPED because of internal error: unexpected prover output: {1}", impl.Name, upo.Message);
+ verificationResult.Errors = null;
+ verificationResult.Outcome = VCGen.Outcome.Inconclusive;
+ }
+
+ verificationResult.ProofObligationCountAfter = vcgen.CumulativeAssertionCount;
+ verificationResult.End = DateTime.UtcNow;
+ }
+
+ #endregion
+
+ #region Cache the verification result
+
+ if (0 < CommandLineOptions.Clo.VerifySnapshots && !string.IsNullOrEmpty(impl.Checksum))
+ {
+ Cache.Insert(impl, verificationResult);
+ }
+
+ #endregion
+ }
+
+ #region Process the verification results and statistics
+
+ ProcessOutcome(verificationResult.Outcome, verificationResult.Errors, TimeIndication(verificationResult), stats, output, impl.TimeLimit, er, verificationResult.ImplementationName, verificationResult.ImplementationToken, verificationResult.RequestId, wasCached);
+
+ ProcessErrors(verificationResult.Errors, verificationResult.Outcome, output, er, impl);
+
+ if (CommandLineOptions.Clo.XmlSink != null)
+ {
+ CommandLineOptions.Clo.XmlSink.WriteEndMethod(verificationResult.Outcome.ToString().ToLowerInvariant(), verificationResult.End, verificationResult.End - verificationResult.Start);
+ }
+
+ outputCollector.Add(index, output);
+
+ outputCollector.WriteMoreOutput();
+
+ if (verificationResult.Outcome == VCGen.Outcome.Errors || CommandLineOptions.Clo.Trace)
+ {
+ Console.Out.Flush();
+ }
+
+ #endregion
+ }
+
+
+ class OutputCollector
+ {
+ StringWriter[] outputs;
+
+ int nextPrintableIndex = 0;
+
+ public OutputCollector(Implementation[] implementations)
+ {
+ outputs = new StringWriter[implementations.Length];
+ }
+
+ public void WriteMoreOutput()
+ {
+ lock (outputs)
+ {
+ for (; nextPrintableIndex < outputs.Length && outputs[nextPrintableIndex] != null; nextPrintableIndex++)
+ {
+ Console.Write(outputs[nextPrintableIndex].ToString());
+ outputs[nextPrintableIndex] = null;
+ Console.Out.Flush();
+ }
+ }
+ }
+
+ public void Add(int index, StringWriter output)
+ {
+ Contract.Requires(0 <= index && index < outputs.Length);
+ Contract.Requires(output != null);
+
+ lock (this)
+ {
+ outputs[index] = output;
+ }
+ }
+ }
+
+
+ private static ConditionGeneration CreateVCGen(Program program, List<Checker> checkers)
+ {
+ ConditionGeneration vcgen = null;
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
+ {
+ vcgen = new DCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
+ }
+ else if (CommandLineOptions.Clo.FixedPointEngine != null)
+ {
+ vcgen = new FixedpointVC(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
+ }
+ else if (CommandLineOptions.Clo.StratifiedInlining > 0)
+ {
+ vcgen = new StratifiedVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
+ }
+ else if (CommandLineOptions.Clo.SecureVcGen != null)
+ {
+ vcgen = new SecureVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
+ }
+ else
+ {
+ vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, checkers);
+ }
+ return vcgen;
+ }
+
+
+ #region Houdini
+
+ private static PipelineOutcome RunHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er)
+ {
+ Contract.Requires(stats != null);
+
+ if (CommandLineOptions.Clo.AbstractHoudini != null)
+ {
+ return RunAbstractHoudini(program, stats, er);
+ }
+
+ if (CommandLineOptions.Clo.StagedHoudini != null)
+ {
+ return RunStagedHoudini(program, stats, er);
+ }
+
+ Houdini.HoudiniSession.HoudiniStatistics houdiniStats = new Houdini.HoudiniSession.HoudiniStatistics();
+ Houdini.Houdini houdini = new Houdini.Houdini(program, houdiniStats);
+ Houdini.HoudiniOutcome outcome = houdini.PerformHoudiniInference();
+ houdini.Close();
+
+ if (CommandLineOptions.Clo.PrintAssignment)
+ {
+ Console.WriteLine("Assignment computed by Houdini:");
+ foreach (var x in outcome.assignment)
+ {
+ Console.WriteLine(x.Key + " = " + x.Value);
+ }
+ }
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ int numTrueAssigns = 0;
+ foreach (var x in outcome.assignment)
+ {
+ if (x.Value)
+ numTrueAssigns++;
+ }
+ Console.WriteLine("Number of true assignments = " + numTrueAssigns);
+ Console.WriteLine("Number of false assignments = " + (outcome.assignment.Count - numTrueAssigns));
+ Console.WriteLine("Prover time = " + houdiniStats.proverTime.ToString("F2"));
+ Console.WriteLine("Unsat core prover time = " + houdiniStats.unsatCoreProverTime.ToString("F2"));
+ Console.WriteLine("Number of prover queries = " + houdiniStats.numProverQueries);
+ Console.WriteLine("Number of unsat core prover queries = " + houdiniStats.numUnsatCoreProverQueries);
+ Console.WriteLine("Number of unsat core prunings = " + houdiniStats.numUnsatCorePrunings);
+ }
+
+ foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values)
+ {
+ ProcessOutcome(x.outcome, x.errors, "", stats, Console.Out, CommandLineOptions.Clo.ProverKillTime, er);
+ ProcessErrors(x.errors, x.outcome, Console.Out, er);
+ }
+
+ return PipelineOutcome.Done;
+ }
+
+ public static Program ProgramFromFile(string filename) {
+ Program p = ParseBoogieProgram(new List<string> { filename }, false);
+ System.Diagnostics.Debug.Assert(p != null);
+ LinearTypeChecker linearTypeChecker;
+ CivlTypeChecker civlTypeChecker;
+ PipelineOutcome oc = ExecutionEngine.ResolveAndTypecheck(p, filename, out linearTypeChecker, out civlTypeChecker);
+ System.Diagnostics.Debug.Assert(oc == PipelineOutcome.ResolvedAndTypeChecked);
+ return p;
+ }
+
+ private static PipelineOutcome RunStagedHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er)
+ {
+ Houdini.HoudiniSession.HoudiniStatistics houdiniStats = new Houdini.HoudiniSession.HoudiniStatistics();
+ Houdini.StagedHoudini stagedHoudini = new Houdini.StagedHoudini(program, houdiniStats, ProgramFromFile);
+ Houdini.HoudiniOutcome outcome = stagedHoudini.PerformStagedHoudiniInference();
+
+ if (CommandLineOptions.Clo.PrintAssignment)
+ {
+ Console.WriteLine("Assignment computed by Houdini:");
+ foreach (var x in outcome.assignment)
+ {
+ Console.WriteLine(x.Key + " = " + x.Value);
+ }
+ }
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ int numTrueAssigns = 0;
+ foreach (var x in outcome.assignment)
+ {
+ if (x.Value)
+ numTrueAssigns++;
+ }
+ Console.WriteLine("Number of true assignments = " + numTrueAssigns);
+ Console.WriteLine("Number of false assignments = " + (outcome.assignment.Count - numTrueAssigns));
+ Console.WriteLine("Prover time = " + houdiniStats.proverTime.ToString("F2"));
+ Console.WriteLine("Unsat core prover time = " + houdiniStats.unsatCoreProverTime.ToString("F2"));
+ Console.WriteLine("Number of prover queries = " + houdiniStats.numProverQueries);
+ Console.WriteLine("Number of unsat core prover queries = " + houdiniStats.numUnsatCoreProverQueries);
+ Console.WriteLine("Number of unsat core prunings = " + houdiniStats.numUnsatCorePrunings);
+ }
+
+ foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values)
+ {
+ ProcessOutcome(x.outcome, x.errors, "", stats, Console.Out, CommandLineOptions.Clo.ProverKillTime, er);
+ ProcessErrors(x.errors, x.outcome, Console.Out, er);
+ }
+
+ return PipelineOutcome.Done;
+
+ }
+
+
+ private static PipelineOutcome RunAbstractHoudini(Program program, PipelineStatistics stats, ErrorReporterDelegate er)
+ {
+ Contract.Requires(stats != null);
+
+ //CommandLineOptions.Clo.PrintErrorModel = 1;
+ CommandLineOptions.Clo.UseProverEvaluate = true;
+ CommandLineOptions.Clo.ModelViewFile = "z3model";
+ CommandLineOptions.Clo.UseArrayTheory = true;
+ CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic;
+ Houdini.AbstractDomainFactory.Initialize(program);
+ var domain = Houdini.AbstractDomainFactory.GetInstance(CommandLineOptions.Clo.AbstractHoudini);
+
+ // Run Abstract Houdini
+ var abs = new Houdini.AbsHoudini(program, domain);
+ var absout = abs.ComputeSummaries();
+ ProcessOutcome(absout.outcome, absout.errors, "", stats, Console.Out, CommandLineOptions.Clo.ProverKillTime, er);
+ ProcessErrors(absout.errors, absout.outcome, Console.Out, er);
+
+ //Houdini.PredicateAbs.Initialize(program);
+ //var abs = new Houdini.AbstractHoudini(program);
+ //abs.computeSummaries(new Houdini.PredicateAbs(program.TopLevelDeclarations.OfType<Implementation>().First().Name));
+
+ return PipelineOutcome.Done;
+ }
+
+ #endregion
+
+
+ private static string TimeIndication(VerificationResult verificationResult)
+ {
+ var result = "";
+ if (CommandLineOptions.Clo.Trace)
+ {
+ result = string.Format(" [{0:F3} s, {1} proof obligation{2}] ", (verificationResult.End - verificationResult.Start).TotalSeconds, verificationResult.ProofObligationCount, verificationResult.ProofObligationCount == 1 ? "" : "s");
+ }
+ else if (CommandLineOptions.Clo.TraceProofObligations)
+ {
+ result = string.Format(" [{0} proof obligation{1}] ", verificationResult.ProofObligationCount, verificationResult.ProofObligationCount == 1 ? "" : "s");
+ }
+ return result;
+ }
+
+
+ private static void ProcessOutcome(VC.VCGen.Outcome outcome, List<Counterexample> errors, string timeIndication,
+ PipelineStatistics stats, TextWriter tw, int timeLimit, ErrorReporterDelegate er = null, string implName = null, IToken implTok = null, string requestId = null, bool wasCached = false)
+ {
+ Contract.Requires(stats != null);
+
+ UpdateStatistics(stats, outcome, errors, wasCached);
+
+ printer.Inform(timeIndication + OutcomeIndication(outcome, errors), tw);
+
+ ReportOutcome(outcome, er, implName, implTok, requestId, tw, timeLimit, errors);
+ }
+
+
+ private static void ReportOutcome(VC.VCGen.Outcome outcome, ErrorReporterDelegate er, string implName, IToken implTok, string requestId, TextWriter tw, int timeLimit, List<Counterexample> errors)
+ {
+ ErrorInformation errorInfo = null;
+
+ switch (outcome)
+ {
+ case VCGen.Outcome.ReachedBound:
+ tw.WriteLine(string.Format("Stratified Inlining: Reached recursion bound of {0}", CommandLineOptions.Clo.RecursionBound));
+ break;
+ case VCGen.Outcome.Errors:
+ case VCGen.Outcome.TimedOut:
+ if (implName != null && implTok != null)
+ {
+ if (outcome == ConditionGeneration.Outcome.TimedOut || (errors != null && errors.Any(e => e.IsAuxiliaryCexForDiagnosingTimeouts)))
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(implTok, string.Format("Verification of '{1}' timed out after {0} seconds", timeLimit, implName), requestId);
+ }
+
+ // Report timed out assertions as auxiliary info.
+ if (errors != null)
+ {
+ var cmpr = new CounterexampleComparer();
+ var timedOutAssertions = errors.Where(e => e.IsAuxiliaryCexForDiagnosingTimeouts).Distinct(cmpr).ToList();
+ timedOutAssertions.Sort(cmpr);
+ if (0 < timedOutAssertions.Count)
+ {
+ errorInfo.Msg += string.Format(" with {0} check(s) that timed out individually", timedOutAssertions.Count);
+ }
+ foreach (Counterexample error in timedOutAssertions)
+ {
+ var callError = error as CallCounterexample;
+ var returnError = error as ReturnCounterexample;
+ var assertError = error as AssertCounterexample;
+ IToken tok = null;
+ string msg = null;
+ if (callError != null)
+ {
+ tok = callError.FailingCall.tok;
+ msg = callError.FailingCall.ErrorData as string ?? "A precondition for this call might not hold.";
+ }
+ else if (returnError != null)
+ {
+ tok = returnError.FailingReturn.tok;
+ msg = "A postcondition might not hold on this return path.";
+ }
+ else
+ {
+ tok = assertError.FailingAssert.tok;
+ if (assertError.FailingAssert is LoopInitAssertCmd)
+ {
+ msg = "This loop invariant might not hold on entry.";
+ }
+ else if (assertError.FailingAssert is LoopInvMaintainedAssertCmd)
+ {
+ msg = "This loop invariant might not be maintained by the loop.";
+ }
+ else
+ {
+ msg = assertError.FailingAssert.ErrorData as string;
+ if (!CommandLineOptions.Clo.ForceBplErrors && assertError.FailingAssert.ErrorMessage != null)
+ {
+ msg = assertError.FailingAssert.ErrorMessage;
+ }
+ if (msg == null)
+ {
+ msg = "This assertion might not hold.";
+ }
+ }
+ }
+ errorInfo.AddAuxInfo(tok, msg, "Unverified check due to timeout");
+ }
+ }
+ }
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ if (implName != null && implTok != null)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(implTok, "Verification out of memory (" + implName + ")", requestId);
+ }
+ break;
+ case VCGen.Outcome.Inconclusive:
+ if (implName != null && implTok != null)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(implTok, "Verification inconclusive (" + implName + ")", requestId);
+ }
+ break;
+ }
+
+ if (errorInfo != null)
+ {
+ errorInfo.ImplementationName = implName;
+ if (er != null)
+ {
+ lock (er)
+ {
+ er(errorInfo);
+ }
+ }
+ else
+ {
+ printer.WriteErrorInformation(errorInfo, tw);
+ }
+ }
+ }
+
+
+ private static string OutcomeIndication(VC.VCGen.Outcome outcome, List<Counterexample> errors)
+ {
+ string traceOutput = "";
+ switch (outcome)
+ {
+ default:
+ Contract.Assert(false); // unexpected outcome
+ throw new cce.UnreachableException();
+ case VCGen.Outcome.ReachedBound:
+ traceOutput = "verified";
+ break;
+ case VCGen.Outcome.Correct:
+ traceOutput = (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed ? "credible" : "verified");
+ break;
+ case VCGen.Outcome.TimedOut:
+ traceOutput = "timed out";
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ traceOutput = "out of memory";
+ break;
+ case VCGen.Outcome.Inconclusive:
+ traceOutput = "inconclusive";
+ break;
+ case VCGen.Outcome.Errors:
+ Contract.Assert(errors != null);
+ traceOutput = (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed ? "doomed" : string.Format("error{0}", errors.Count == 1 ? "" : "s"));
+ break;
+ }
+ return traceOutput;
+ }
+
+
+ private static void UpdateStatistics(PipelineStatistics stats, VC.VCGen.Outcome outcome, List<Counterexample> errors, bool wasCached)
+ {
+ Contract.Requires(stats != null);
+
+ switch (outcome)
+ {
+ default:
+ Contract.Assert(false); // unexpected outcome
+ throw new cce.UnreachableException();
+ case VCGen.Outcome.ReachedBound:
+ Interlocked.Increment(ref stats.VerifiedCount);
+ if (wasCached) { Interlocked.Increment(ref stats.CachedVerifiedCount); }
+ break;
+ case VCGen.Outcome.Correct:
+ Interlocked.Increment(ref stats.VerifiedCount);
+ if (wasCached) { Interlocked.Increment(ref stats.CachedVerifiedCount); }
+ break;
+ case VCGen.Outcome.TimedOut:
+ Interlocked.Increment(ref stats.TimeoutCount);
+ if (wasCached) { Interlocked.Increment(ref stats.CachedTimeoutCount); }
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ Interlocked.Increment(ref stats.OutOfMemoryCount);
+ if (wasCached) { Interlocked.Increment(ref stats.CachedOutOfMemoryCount); }
+ break;
+ case VCGen.Outcome.Inconclusive:
+ Interlocked.Increment(ref stats.InconclusiveCount);
+ if (wasCached) { Interlocked.Increment(ref stats.CachedInconclusiveCount); }
+ break;
+ case VCGen.Outcome.Errors:
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed)
+ {
+ Interlocked.Increment(ref stats.ErrorCount);
+ if (wasCached) { Interlocked.Increment(ref stats.CachedErrorCount); }
+ }
+ else
+ {
+ int cnt = errors.Where(e => !e.IsAuxiliaryCexForDiagnosingTimeouts).Count();
+ Interlocked.Add(ref stats.ErrorCount, cnt);
+ if (wasCached) { Interlocked.Add(ref stats.CachedErrorCount, cnt); }
+ }
+ break;
+ }
+ }
+
+
+ private static void ProcessErrors(List<Counterexample> errors, VC.VCGen.Outcome outcome, TextWriter tw, ErrorReporterDelegate er, Implementation impl = null)
+ {
+ var implName = impl != null ? impl.Name : null;
+
+ if (errors != null)
+ {
+ errors.Sort(new CounterexampleComparer());
+ foreach (Counterexample error in errors)
+ {
+ if (error.IsAuxiliaryCexForDiagnosingTimeouts)
+ {
+ continue;
+ }
+ var errorInfo = CreateErrorInformation(error, outcome);
+ errorInfo.ImplementationName = implName;
+
+ if (CommandLineOptions.Clo.XmlSink != null)
+ {
+ WriteErrorInformationToXmlSink(errorInfo, error.Trace);
+ }
+
+ if (CommandLineOptions.Clo.EnhancedErrorMessages == 1)
+ {
+ foreach (string info in error.relatedInformation)
+ {
+ Contract.Assert(info != null);
+ errorInfo.Out.WriteLine(" " + info);
+ }
+ }
+ if (CommandLineOptions.Clo.ErrorTrace > 0)
+ {
+ errorInfo.Out.WriteLine("Execution trace:");
+ error.Print(4, errorInfo.Out, b => { errorInfo.AddAuxInfo(b.tok, b.Label, "Execution trace"); });
+ }
+ if (CommandLineOptions.Clo.ModelViewFile != null)
+ {
+ error.PrintModel(errorInfo.Model);
+ }
+
+ printer.WriteErrorInformation(errorInfo, tw);
+
+ if (er != null)
+ {
+ lock (er)
+ {
+ er(errorInfo);
+ }
+ }
+ }
+ }
+ }
+
+
+ private static ErrorInformation CreateErrorInformation(Counterexample error, VC.VCGen.Outcome outcome)
+ {
+ // BP1xxx: Parsing errors
+ // BP2xxx: Name resolution errors
+ // BP3xxx: Typechecking errors
+ // BP4xxx: Abstract interpretation errors (Is there such a thing?)
+ // BP5xxx: Verification errors
+
+ ErrorInformation errorInfo;
+ var cause = "Error";
+ if (outcome == VCGen.Outcome.TimedOut)
+ {
+ cause = "Timed out on";
+ }
+ else if (outcome == VCGen.Outcome.OutOfMemory)
+ {
+ cause = "Out of memory on";
+ }
+
+ var callError = error as CallCounterexample;
+ var returnError = error as ReturnCounterexample;
+ var assertError = error as AssertCounterexample;
+ if (callError != null)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(callError.FailingCall.tok, callError.FailingCall.ErrorData as string ?? "A precondition for this call might not hold.", callError.RequestId, callError.OriginalRequestId, cause);
+ errorInfo.BoogieErrorCode = "BP5002";
+ errorInfo.Kind = ErrorKind.Precondition;
+ errorInfo.AddAuxInfo(callError.FailingRequires.tok, callError.FailingRequires.ErrorData as string ?? "This is the precondition that might not hold.", "Related location");
+
+ if (!CommandLineOptions.Clo.ForceBplErrors && callError.FailingRequires.ErrorMessage != null)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(null, callError.FailingRequires.ErrorMessage, callError.RequestId, callError.OriginalRequestId, cause);
+ }
+ }
+ else if (returnError != null)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(returnError.FailingReturn.tok, "A postcondition might not hold on this return path.", returnError.RequestId, returnError.OriginalRequestId, cause);
+ errorInfo.BoogieErrorCode = "BP5003";
+ errorInfo.Kind = ErrorKind.Postcondition;
+ errorInfo.AddAuxInfo(returnError.FailingEnsures.tok, returnError.FailingEnsures.ErrorData as string ?? "This is the postcondition that might not hold.", "Related location");
+
+ if (!CommandLineOptions.Clo.ForceBplErrors && returnError.FailingEnsures.ErrorMessage != null)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(null, returnError.FailingEnsures.ErrorMessage, returnError.RequestId, returnError.OriginalRequestId, cause);
+ }
+ }
+ else // error is AssertCounterexample
+ {
+ if (assertError.FailingAssert is LoopInitAssertCmd)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(assertError.FailingAssert.tok, "This loop invariant might not hold on entry.", assertError.RequestId, assertError.OriginalRequestId, cause);
+ errorInfo.BoogieErrorCode = "BP5004";
+ errorInfo.Kind = ErrorKind.InvariantEntry;
+ }
+ else if (assertError.FailingAssert is LoopInvMaintainedAssertCmd)
+ {
+ errorInfo = errorInformationFactory.CreateErrorInformation(assertError.FailingAssert.tok, "This loop invariant might not be maintained by the loop.", assertError.RequestId, assertError.OriginalRequestId, cause);
+ errorInfo.BoogieErrorCode = "BP5005";
+ errorInfo.Kind = ErrorKind.InvariantMaintainance;
+ }
+ else
+ {
+ var msg = assertError.FailingAssert.ErrorData as string;
+ var tok = assertError.FailingAssert.tok;
+ if (!CommandLineOptions.Clo.ForceBplErrors && assertError.FailingAssert.ErrorMessage != null)
+ {
+ msg = assertError.FailingAssert.ErrorMessage;
+ tok = null;
+ if (cause == "Error")
+ {
+ cause = null;
+ }
+ }
+ string bec = null;
+ if (msg == null)
+ {
+ msg = "This assertion might not hold.";
+ bec = "BP5001";
+ }
+
+ errorInfo = errorInformationFactory.CreateErrorInformation(tok, msg, assertError.RequestId, assertError.OriginalRequestId, cause);
+ errorInfo.BoogieErrorCode = bec;
+ errorInfo.Kind = ErrorKind.Assertion;
+ }
+ }
+
+ return errorInfo;
+ }
+
+
+ private static void WriteErrorInformationToXmlSink(ErrorInformation errorInfo, List<Block> trace)
+ {
+ var msg = "assertion violation";
+ switch (errorInfo.Kind)
+ {
+ case ErrorKind.Precondition:
+ msg = "precondition violation";
+ break;
+
+ case ErrorKind.Postcondition:
+ msg = "postcondition violation";
+ break;
+
+ case ErrorKind.InvariantEntry:
+ msg = "loop invariant entry violation";
+ break;
+
+ case ErrorKind.InvariantMaintainance:
+ msg = "loop invariant maintenance violation";
+ break;
+ }
+
+ var relatedError = errorInfo.Aux.FirstOrDefault();
+ CommandLineOptions.Clo.XmlSink.WriteError(msg, errorInfo.Tok, relatedError.Tok, trace);
+ }
+
+ }
+
+}
diff --git a/Source/ExecutionEngine/ExecutionEngine.csproj b/Source/ExecutionEngine/ExecutionEngine.csproj
index 09393f09..b17b1139 100644
--- a/Source/ExecutionEngine/ExecutionEngine.csproj
+++ b/Source/ExecutionEngine/ExecutionEngine.csproj
@@ -1,194 +1,194 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{EAA5EB79-D475-4601-A59B-825C191CD25F}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>ExecutionEngine</RootNamespace>
- <AssemblyName>ExecutionEngine</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">
- </TargetFrameworkProfile>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <ProductVersion>12.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
- <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
- <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
- <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
- <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
- <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
- <CodeContractsInferRequires>True</CodeContractsInferRequires>
- <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
- <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
- <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
- <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
- <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
- <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
- <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
- <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
- <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsSQLServerOption />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
- <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
- <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
- <CodeContractsInferRequires>True</CodeContractsInferRequires>
- <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
- <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
- <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
- <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
- <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsSQLServerOption />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>TRACE;DEBUG;QED</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Runtime.Caching" />
- <Reference Include="System.Xml.Linq" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="ExecutionEngine.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="VerificationResultCache.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\AbsInt\AbsInt.csproj">
- <Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
- <Name>AbsInt</Name>
- </ProjectReference>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Concurrency\Concurrency.csproj">
- <Project>{d07b8e38-e172-47f4-ad02-0373014a46d3}</Project>
- <Name>Concurrency</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Doomed\Doomed.csproj">
- <Project>{884386A3-58E9-40BB-A273-B24976775553}</Project>
- <Name>Doomed</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\Houdini\Houdini.csproj">
- <Project>{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}</Project>
- <Name>Houdini</Name>
- </ProjectReference>
- <ProjectReference Include="..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\Predication\Predication.csproj">
- <Project>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</Project>
- <Name>Predication</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{EAA5EB79-D475-4601-A59B-825C191CD25F}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ExecutionEngine</RootNamespace>
+ <AssemblyName>BoogieExecutionEngine</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">
+ </TargetFrameworkProfile>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <ProductVersion>12.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+ <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
+ <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
+ <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
+ <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+ <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
+ <CodeContractsInferRequires>True</CodeContractsInferRequires>
+ <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+ <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
+ <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+ <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+ <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
+ <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
+ <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
+ <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+ <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsSQLServerOption />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+ <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
+ <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+ <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+ <CodeContractsInferRequires>True</CodeContractsInferRequires>
+ <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+ <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+ <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+ <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
+ <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsSQLServerOption />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+ <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;QED</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Runtime.Caching" />
+ <Reference Include="System.Xml.Linq" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ExecutionEngine.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="VerificationResultCache.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\AbsInt\AbsInt.csproj">
+ <Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
+ <Name>AbsInt</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Concurrency\Concurrency.csproj">
+ <Project>{d07b8e38-e172-47f4-ad02-0373014a46d3}</Project>
+ <Name>Concurrency</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Doomed\Doomed.csproj">
+ <Project>{884386A3-58E9-40BB-A273-B24976775553}</Project>
+ <Name>Doomed</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Houdini\Houdini.csproj">
+ <Project>{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}</Project>
+ <Name>Houdini</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Model\Model.csproj">
+ <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Predication\Predication.csproj">
+ <Project>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</Project>
+ <Name>Predication</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</Name>
+ </ProjectReference>
+ </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/ExecutionEngine/Properties/AssemblyInfo.cs b/Source/ExecutionEngine/Properties/AssemblyInfo.cs
index 5977e799..ea288b03 100644
--- a/Source/ExecutionEngine/Properties/AssemblyInfo.cs
+++ b/Source/ExecutionEngine/Properties/AssemblyInfo.cs
@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ExecutionEngine")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ExecutionEngine")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("03fff764-c3f0-4e42-a897-a1c151b3fe6d")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ExecutionEngine")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ExecutionEngine")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("03fff764-c3f0-4e42-a897-a1c151b3fe6d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/ExecutionEngine/VerificationResultCache.cs b/Source/ExecutionEngine/VerificationResultCache.cs
index 5d20e6e8..3159238c 100644
--- a/Source/ExecutionEngine/VerificationResultCache.cs
+++ b/Source/ExecutionEngine/VerificationResultCache.cs
@@ -1,640 +1,692 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Linq;
-using System.Runtime.Caching;
-using System.Text;
-using System.Text.RegularExpressions;
-using VC;
-
-namespace Microsoft.Boogie
-{
-
- struct CachedVerificationResultInjectorRun
- {
- public DateTime Start { get; internal set; }
- public DateTime End { get; internal set; }
- public int TransformedImplementationCount { get; internal set; }
- public int ImplementationCount { get; internal set; }
- public int SkippedImplementationCount { get; set; }
- public int LowPriorityImplementationCount { get; set; }
- public int MediumPriorityImplementationCount { get; set; }
- public int HighPriorityImplementationCount { get; set; }
- public long[] CachingActionCounts { get; set; }
- }
-
-
- sealed class CachedVerificationResultInjectorStatistics
- {
- ConcurrentDictionary<string, CachedVerificationResultInjectorRun> runs = new ConcurrentDictionary<string, CachedVerificationResultInjectorRun>();
-
- public bool AddRun(string requestId, CachedVerificationResultInjectorRun run)
- {
- return runs.TryAdd(requestId, run);
- }
-
- public string Output(bool printTime = false)
- {
- var wr = new StringWriter();
- if (runs.Any())
- {
- wr.WriteLine("Cached verification result injector statistics as CSV:");
- wr.WriteLine("Request ID, Transformed, Low, Medium, High, Skipped{0}", printTime ? ", Time (ms)" : "");
- foreach (var kv in runs.OrderBy(kv => ExecutionEngine.AutoRequestId(kv.Key)))
- {
- var t = printTime ? string.Format(", {0,8:F0}", kv.Value.End.Subtract(kv.Value.Start).TotalMilliseconds) : "";
- wr.WriteLine("{0,-19}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}{6}", kv.Key, kv.Value.TransformedImplementationCount, kv.Value.LowPriorityImplementationCount, kv.Value.MediumPriorityImplementationCount, kv.Value.HighPriorityImplementationCount, kv.Value.SkippedImplementationCount, t);
- }
- }
- return wr.ToString();
- }
- }
-
-
- sealed class CachedVerificationResultInjector : StandardVisitor
- {
- readonly IEnumerable<Implementation> Implementations;
- readonly Program Program;
- // TODO(wuestholz): We should probably increase the threshold to something like 2 seconds.
- static readonly double TimeThreshold = -1.0d;
- Program programInCachedSnapshot;
- Implementation currentImplementation;
- int assumptionVariableCount;
- int temporaryVariableCount;
-
- public static readonly CachedVerificationResultInjectorStatistics Statistics = new CachedVerificationResultInjectorStatistics();
-
- int FreshAssumptionVariableName
- {
- get
- {
- return assumptionVariableCount++;
- }
- }
-
- int FreshTemporaryVariableName
- {
- get
- {
- return temporaryVariableCount++;
- }
- }
-
- CachedVerificationResultInjector(Program program, IEnumerable<Implementation> implementations)
- {
- Implementations = implementations;
- Program = program;
- }
-
- public Implementation Inject(Implementation implementation, Program programInCachedSnapshot)
- {
- Contract.Requires(implementation != null && programInCachedSnapshot != null);
-
- this.programInCachedSnapshot = programInCachedSnapshot;
- assumptionVariableCount = 0;
- temporaryVariableCount = 0;
- currentImplementation = implementation;
- var result = VisitImplementation(implementation);
- currentImplementation = null;
- this.programInCachedSnapshot = null;
- return result;
- }
-
- public static void Inject(Program program, IEnumerable<Implementation> implementations, string requestId, string programId, out long[] cachingActionCounts)
- {
- var eai = new CachedVerificationResultInjector(program, implementations);
-
- cachingActionCounts = new long[Enum.GetNames(typeof(VC.ConditionGeneration.CachingAction)).Length];
- var run = new CachedVerificationResultInjectorRun { Start = DateTime.UtcNow, ImplementationCount = implementations.Count(), CachingActionCounts = cachingActionCounts };
- foreach (var impl in implementations)
- {
- int priority;
- var vr = ExecutionEngine.Cache.Lookup(impl, out priority);
- if (vr != null && vr.ProgramId == programId)
- {
- if (priority == Priority.LOW)
- {
- run.LowPriorityImplementationCount++;
- if (TimeThreshold < vr.End.Subtract(vr.Start).TotalMilliseconds)
- {
- SetErrorAndAssertionChecksumsInCachedSnapshot(impl, vr);
- if (vr.ProgramId != null)
- {
- var p = ExecutionEngine.CachedProgram(vr.ProgramId);
- if (p != null)
- {
- eai.Inject(impl, p);
- run.TransformedImplementationCount++;
- }
- }
- }
- }
- else if (priority == Priority.MEDIUM)
- {
- run.MediumPriorityImplementationCount++;
- if (TimeThreshold < vr.End.Subtract(vr.Start).TotalMilliseconds)
- {
- SetErrorAndAssertionChecksumsInCachedSnapshot(impl, vr);
- if (vr.ProgramId != null)
- {
- var p = ExecutionEngine.CachedProgram(vr.ProgramId);
- if (p != null)
- {
- eai.Inject(impl, p);
- run.TransformedImplementationCount++;
- }
- }
- }
- }
- else if (priority == Priority.HIGH)
- {
- run.HighPriorityImplementationCount++;
- }
- else if (priority == Priority.SKIP)
- {
- run.SkippedImplementationCount++;
- }
- }
- }
- run.End = DateTime.UtcNow;
- Statistics.AddRun(requestId, run);
- }
-
- private static void SetErrorAndAssertionChecksumsInCachedSnapshot(Implementation implementation, VerificationResult result)
- {
- if (result.Outcome == ConditionGeneration.Outcome.Errors && result.Errors != null && result.Errors.Count < CommandLineOptions.Clo.ProverCCLimit)
- {
- implementation.SetErrorChecksumToCachedError(result.Errors.Select(cex => new Tuple<byte[], byte[], object>(cex.Checksum, cex.SugaredCmdChecksum, cex)));
- implementation.AssertionChecksumsInCachedSnapshot = result.AssertionChecksums;
- }
- else if (result.Outcome == ConditionGeneration.Outcome.Correct)
- {
- implementation.SetErrorChecksumToCachedError(new List<Tuple<byte[], byte[], object>>());
- implementation.AssertionChecksumsInCachedSnapshot = result.AssertionChecksums;
- }
- }
-
- public override Cmd VisitCallCmd(CallCmd node)
- {
- var result = base.VisitCallCmd(node);
-
- var oldProc = programInCachedSnapshot.FindProcedure(node.Proc.Name);
- if (oldProc != null
- && oldProc.DependencyChecksum != node.Proc.DependencyChecksum
- && node.AssignedAssumptionVariable == null)
- {
- var before = new List<Cmd>();
- var beforePrecondtionCheck = new List<Cmd>();
- var after = new List<Cmd>();
- var axioms = new List<Axiom>();
- Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
- // TODO(wuestholz): Try out two alternatives: only do this for low priority implementations or not at all.
- var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program);
- if (canUseSpecs)
- {
- var desugaring = node.Desugaring;
- Contract.Assert(desugaring != null);
- var precond = node.CheckedPrecondition(oldProc, Program, e => FunctionExtractor.Extract(e, Program, axioms));
- if (precond != null)
- {
- var assume = new AssumeCmd(node.tok, precond, new QKeyValue(Token.NoToken, "precondition_previous_snapshot", new List<object>(), null));
- beforePrecondtionCheck.Add(assume);
- }
-
- var unmods = node.UnmodifiedBefore(oldProc);
- var eqs = new List<Expr>();
- foreach (var unmod in unmods)
- {
- var oldUnmod = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", unmod.Name, FreshTemporaryVariableName), unmod.Type));
- var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldUnmod));
- var rhs = new IdentifierExpr(Token.NoToken, unmod.Decl);
- before.Add(new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs }));
- var eq = LiteralExpr.Eq(new IdentifierExpr(Token.NoToken, oldUnmod), new IdentifierExpr(Token.NoToken, unmod.Decl));
- eq.Type = Type.Bool;
- eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- eqs.Add(eq);
- }
-
- var mods = node.ModifiedBefore(oldProc);
- var oldSubst = new Dictionary<Variable, Expr>();
- foreach (var mod in mods)
- {
- var oldMod = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", mod.Name, FreshTemporaryVariableName), mod.Type));
- oldSubst[mod.Decl] = new IdentifierExpr(Token.NoToken, oldMod);
- var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldMod));
- var rhs = new IdentifierExpr(Token.NoToken, mod.Decl);
- before.Add(new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs }));
- }
-
- assumedExpr = node.Postcondition(oldProc, eqs, oldSubst, Program, e => FunctionExtractor.Extract(e, Program, axioms));
- }
-
- if (assumedExpr != null)
- {
- var lv = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken, string.Format("a##post##{0}", FreshAssumptionVariableName), Type.Bool),
- new QKeyValue(Token.NoToken, "assumption", new List<object>(), null));
- node.AssignedAssumptionVariable = lv;
- currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
- var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
- var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
- var assumed = new AssignCmd(node.tok, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
- after.Add(assumed);
- }
-
- node.ExtendDesugaring(before, beforePrecondtionCheck, after);
- if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
- {
- using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
- {
- var loc = node.tok != null && node.tok != Token.NoToken ? string.Format("{0}({1},{2})", node.tok.filename, node.tok.line, node.tok.col) : "<unknown location>";
- Console.Out.WriteLine("Processing call to procedure {0} in implementation {1} (at {2}):", node.Proc.Name, currentImplementation.Name, loc);
- foreach (var a in axioms)
- {
- Console.Out.Write(" >>> added axiom: ");
- a.Expr.Emit(tokTxtWr);
- Console.Out.WriteLine();
- }
- foreach (var b in before)
- {
- Console.Out.Write(" >>> added before: ");
- b.Emit(tokTxtWr, 0);
- }
- foreach (var b in beforePrecondtionCheck)
- {
- Console.Out.Write(" >>> added before precondition check: ");
- b.Emit(tokTxtWr, 0);
- }
- foreach (var a in after)
- {
- Console.Out.Write(" >>> added after: ");
- a.Emit(tokTxtWr, 0);
- }
- }
- }
- }
-
- return result;
- }
- }
-
-
- sealed class FunctionExtractor : StandardVisitor
- {
- readonly Dictionary<Variable, BoundVariable> Substitutions = new Dictionary<Variable, BoundVariable>();
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- if (node.Decl == null || !(node.Decl is LocalVariable || node.Decl is Formal || node.Decl is GlobalVariable))
- {
- return node;
- }
- else
- {
- BoundVariable boundVar;
- if (!Substitutions.TryGetValue(node.Decl, out boundVar))
- {
- boundVar = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, node.Name, node.Type));
- Substitutions[node.Decl] = boundVar;
- }
- return new IdentifierExpr(node.tok, boundVar);
- }
- }
-
- public static Expr Extract(Expr expr, Program program, List<Axiom> axioms)
- {
- Contract.Requires(expr != null && program != null && !program.TopLevelDeclarationsAreFrozen && axioms != null);
-
- if (expr is LiteralExpr)
- {
- return expr;
- }
-
- var extractor = new FunctionExtractor();
-
- var body = extractor.VisitExpr(expr);
-
- var name = program.FreshExtractedFunctionName();
- var originalVars = extractor.Substitutions.Keys.ToList();
- var formalInArgs = originalVars.Select(v => new Formal(Token.NoToken, new TypedIdent(Token.NoToken, extractor.Substitutions[v].Name, extractor.Substitutions[v].TypedIdent.Type), true)).ToList<Variable>();
- var formalOutArg = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, name + "$result$", expr.Type), false);
- var func = new Function(Token.NoToken, name, formalInArgs, formalOutArg);
- func.AddAttribute("never_pattern");
-
- var boundVars = originalVars.Select(k => extractor.Substitutions[k]);
- var axiomCall = new NAryExpr(Token.NoToken, new FunctionCall(func), boundVars.Select(b => new IdentifierExpr(Token.NoToken, b)).ToList<Expr>());
- axiomCall.Type = expr.Type;
- axiomCall.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- var eq = LiteralExpr.Eq(axiomCall, body);
- eq.Type = body.Type;
- eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- if (0 < formalInArgs.Count)
- {
- var forallExpr = new ForallExpr(Token.NoToken, boundVars.ToList<Variable>(), new Trigger(Token.NoToken, true, new List<Expr> { axiomCall }), eq);
- body = forallExpr;
- forallExpr.Attributes = new QKeyValue(Token.NoToken, "weight", new List<object> { new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(30)) }, null);
- body.Type = Type.Bool;
- }
- else
- {
- body = eq;
- }
-
- var axiom = new Axiom(Token.NoToken, body);
- func.DefinitionAxiom = axiom;
- program.AddTopLevelDeclaration(func);
- program.AddTopLevelDeclaration(axiom);
- axioms.Add(axiom);
-
- var call = new NAryExpr(Token.NoToken, new FunctionCall(func), originalVars.Select(v => new IdentifierExpr(Token.NoToken, v)).ToList<Expr>());
- call.Type = expr.Type;
- call.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- return call;
- }
- }
-
-
- sealed class OtherDefinitionAxiomsCollector : ReadOnlyVisitor
- {
- Axiom currentAxiom;
- Trigger currentTrigger;
-
- public static void Collect(IEnumerable<Axiom> axioms)
- {
- var start = DateTime.UtcNow;
-
- var v = new OtherDefinitionAxiomsCollector();
- foreach (var a in axioms)
- {
- v.currentAxiom = a;
- v.VisitExpr(a.Expr);
- v.currentAxiom = null;
- }
-
- var end = DateTime.UtcNow;
- if (CommandLineOptions.Clo.TraceCachingForDebugging)
- {
- Console.Out.WriteLine("Collected other definition axioms within {0:F0} ms.", end.Subtract(start).TotalMilliseconds);
- }
- }
-
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
- {
- currentTrigger = node.Triggers;
- while (currentTrigger != null)
- {
- foreach (var e in currentTrigger.Tr)
- {
- VisitExpr(e);
- }
- currentTrigger = currentTrigger.Next;
- }
- return base.VisitQuantifierExpr(node);
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- if (currentTrigger != null)
- {
- // We found a function call within a trigger of a quantifier expression.
- var funCall = node.Fun as FunctionCall;
- if (funCall != null && funCall.Func != null && funCall.Func.Checksum != null && funCall.Func.Checksum != "stable")
- {
- funCall.Func.AddOtherDefinitionAxiom(currentAxiom);
- }
- }
- return base.VisitNAryExpr(node);
- }
- }
-
-
- sealed class DependencyCollector : ReadOnlyVisitor
- {
- private DeclWithFormals currentDeclaration;
- private Axiom currentAxiom;
-
- public static void Collect(Program program)
- {
- var start = DateTime.UtcNow;
-
- var dc = new DependencyCollector();
- dc.VisitProgram(program);
-
- var end = DateTime.UtcNow;
- if (CommandLineOptions.Clo.TraceCachingForDebugging)
- {
- Console.Out.WriteLine("Collected dependencies within {0:F0} ms.", end.Subtract(start).TotalMilliseconds);
- }
- }
-
- public static bool CanExpressOldSpecs(Procedure oldProc, Program newProg)
- {
- Contract.Requires(oldProc != null && newProg != null);
-
- var funcs = newProg.Functions;
- var globals = newProg.GlobalVariables;
- return oldProc.DependenciesCollected
- && (oldProc.FunctionDependencies == null || oldProc.FunctionDependencies.All(dep => funcs.Any(f => f.Name == dep.Name && f.DependencyChecksum == dep.DependencyChecksum)))
- && oldProc.Modifies.All(m => globals.Any(g => g.Name == m.Name));
- }
-
- public override Procedure VisitProcedure(Procedure node)
- {
- currentDeclaration = node;
-
- foreach (var param in node.InParams)
- {
- if (param.TypedIdent != null && param.TypedIdent.WhereExpr != null)
- {
- VisitExpr(param.TypedIdent.WhereExpr);
- }
- }
-
- var result = base.VisitProcedure(node);
- node.DependenciesCollected = true;
- currentDeclaration = null;
- return result;
- }
-
- public override Implementation VisitImplementation(Implementation node)
- {
- currentDeclaration = node;
-
- foreach (var param in node.InParams)
- {
- if (param.TypedIdent != null && param.TypedIdent.WhereExpr != null)
- {
- VisitExpr(param.TypedIdent.WhereExpr);
- }
- }
-
- if (node.Proc != null)
- {
- node.AddProcedureDependency(node.Proc);
- }
-
- var result = base.VisitImplementation(node);
- node.DependenciesCollected = true;
- currentDeclaration = null;
- return result;
- }
-
- public override Axiom VisitAxiom(Axiom node)
- {
- if (node.DependenciesCollected)
- {
- if (currentDeclaration != null && node.FunctionDependencies != null)
- {
- foreach (var f in node.FunctionDependencies)
- {
- currentDeclaration.AddFunctionDependency(f);
- }
- }
- return node;
- }
- currentAxiom = node;
- var result = base.VisitAxiom(node);
- node.DependenciesCollected = true;
- currentAxiom = null;
- return result;
- }
-
- public override Function VisitFunction(Function node)
- {
- currentDeclaration = node;
-
- if (node.DefinitionAxiom != null)
- {
- VisitAxiom(node.DefinitionAxiom);
- }
- if (node.OtherDefinitionAxioms != null)
- {
- foreach (var a in node.OtherDefinitionAxioms)
- {
- if (a != node.DefinitionAxiom)
- {
- VisitAxiom(a);
- }
- }
- }
-
- var result = base.VisitFunction(node);
- node.DependenciesCollected = true;
- currentDeclaration = null;
- return result;
- }
-
- public override Cmd VisitCallCmd(CallCmd node)
- {
- if (currentDeclaration != null)
- {
- currentDeclaration.AddProcedureDependency(node.Proc);
- }
-
- return base.VisitCallCmd(node);
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- var funCall = node.Fun as FunctionCall;
- if (funCall != null)
- {
- if (currentDeclaration != null)
- {
- currentDeclaration.AddFunctionDependency(funCall.Func);
- }
- if (currentAxiom != null)
- {
- currentAxiom.AddFunctionDependency(funCall.Func);
- }
- }
-
- return base.VisitNAryExpr(node);
- }
- }
-
-
- static internal class Priority
- {
- public static readonly int LOW = 1; // the same snapshot has been verified before, but a callee has changed
- public static readonly int MEDIUM = 2; // old snapshot has been verified before
- public static readonly int HIGH = 3; // has been never verified before
- public static readonly int SKIP = int.MaxValue; // highest priority to get them done as soon as possible
- }
-
-
- public sealed class VerificationResultCache
- {
- private readonly MemoryCache Cache = new MemoryCache("VerificationResultCache");
- private readonly CacheItemPolicy Policy = new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, 10, 0), Priority = CacheItemPriority.Default };
-
-
- public void Insert(Implementation impl, VerificationResult result)
- {
- Contract.Requires(impl != null);
- Contract.Requires(result != null);
-
- Cache.Set(impl.Id, result, Policy);
- }
-
-
- public VerificationResult Lookup(Implementation impl, out int priority)
- {
- Contract.Requires(impl != null);
-
- var result = Cache.Get(impl.Id) as VerificationResult;
- if (result == null)
- {
- priority = Priority.HIGH;
- }
- else if (result.Checksum != impl.Checksum)
- {
- priority = Priority.MEDIUM;
- }
- else if (impl.DependencyChecksum == null || result.DependeciesChecksum != impl.DependencyChecksum)
- {
- priority = Priority.LOW;
- }
- else
- {
- priority = Priority.SKIP;
- }
- return result;
- }
-
-
- public void Clear()
- {
- Cache.Trim(100);
- }
-
-
- public void RemoveMatchingKeys(Regex keyRegexp)
- {
- Contract.Requires(keyRegexp != null);
-
- foreach (var kv in Cache)
- {
- if (keyRegexp.IsMatch(kv.Key))
- {
- Cache.Remove(kv.Key);
- }
- }
- }
-
-
- public int VerificationPriority(Implementation impl)
- {
- Contract.Requires(impl != null);
-
- int priority;
- Lookup(impl, out priority);
- return priority;
- }
- }
-
-}
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Linq;
+using System.Runtime.Caching;
+using System.Text;
+using System.Text.RegularExpressions;
+using VC;
+
+namespace Microsoft.Boogie
+{
+
+ struct CachedVerificationResultInjectorRun
+ {
+ public DateTime Start { get; internal set; }
+ public DateTime End { get; internal set; }
+ public int TransformedImplementationCount { get; internal set; }
+ public int ImplementationCount { get; internal set; }
+ public int SkippedImplementationCount { get; set; }
+ public int LowPriorityImplementationCount { get; set; }
+ public int MediumPriorityImplementationCount { get; set; }
+ public int HighPriorityImplementationCount { get; set; }
+ public long[] CachingActionCounts { get; set; }
+ }
+
+
+ sealed class CachedVerificationResultInjectorStatistics
+ {
+ ConcurrentDictionary<string, CachedVerificationResultInjectorRun> runs = new ConcurrentDictionary<string, CachedVerificationResultInjectorRun>();
+
+ public bool AddRun(string requestId, CachedVerificationResultInjectorRun run)
+ {
+ return runs.TryAdd(requestId, run);
+ }
+
+ public string Output(bool printTime = false)
+ {
+ var wr = new StringWriter();
+ if (runs.Any())
+ {
+ wr.WriteLine("Cached verification result injector statistics as CSV:");
+ wr.WriteLine("Request ID, Transformed, Low, Medium, High, Skipped{0}", printTime ? ", Time (ms)" : "");
+ foreach (var kv in runs.OrderBy(kv => ExecutionEngine.AutoRequestId(kv.Key)))
+ {
+ var t = printTime ? string.Format(", {0,8:F0}", kv.Value.End.Subtract(kv.Value.Start).TotalMilliseconds) : "";
+ wr.WriteLine("{0,-19}, {1,3}, {2,3}, {3,3}, {4,3}, {5,3}{6}", kv.Key, kv.Value.TransformedImplementationCount, kv.Value.LowPriorityImplementationCount, kv.Value.MediumPriorityImplementationCount, kv.Value.HighPriorityImplementationCount, kv.Value.SkippedImplementationCount, t);
+ }
+ }
+ return wr.ToString();
+ }
+ }
+
+
+ sealed class CachedVerificationResultInjector : StandardVisitor
+ {
+ readonly IEnumerable<Implementation> Implementations;
+ readonly Program Program;
+ // TODO(wuestholz): We should probably increase the threshold to something like 2 seconds.
+ static readonly double TimeThreshold = -1.0d;
+ Program programInCachedSnapshot;
+ Implementation currentImplementation;
+ int assumptionVariableCount;
+ int temporaryVariableCount;
+
+ public static readonly CachedVerificationResultInjectorStatistics Statistics = new CachedVerificationResultInjectorStatistics();
+
+ int FreshAssumptionVariableName
+ {
+ get
+ {
+ return assumptionVariableCount++;
+ }
+ }
+
+ int FreshTemporaryVariableName
+ {
+ get
+ {
+ return temporaryVariableCount++;
+ }
+ }
+
+ CachedVerificationResultInjector(Program program, IEnumerable<Implementation> implementations)
+ {
+ Implementations = implementations;
+ Program = program;
+ }
+
+ public Implementation Inject(Implementation implementation, Program programInCachedSnapshot)
+ {
+ Contract.Requires(implementation != null && programInCachedSnapshot != null);
+
+ this.programInCachedSnapshot = programInCachedSnapshot;
+ assumptionVariableCount = 0;
+ temporaryVariableCount = 0;
+ currentImplementation = implementation;
+
+ #region Introduce explict assumption about the precondition.
+
+ var oldProc = programInCachedSnapshot.FindProcedure(currentImplementation.Proc.Name);
+ if (oldProc != null
+ && oldProc.DependencyChecksum != currentImplementation.Proc.DependencyChecksum
+ && currentImplementation.ExplicitAssumptionAboutCachedPrecondition == null)
+ {
+ var axioms = new List<Axiom>();
+ var after = new List<Cmd>();
+ Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
+ var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program, true);
+ if (canUseSpecs && oldProc.SignatureEquals(currentImplementation.Proc))
+ {
+ var always = Substituter.SubstitutionFromHashtable(currentImplementation.GetImplFormalMap(), true, currentImplementation.Proc);
+ var forOld = Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>());
+ var clauses = oldProc.Requires.Select(r => Substituter.FunctionCallReresolvingApply(always, forOld, r.Condition, Program));
+ var conj = Expr.And(clauses, true);
+ assumedExpr = conj != null ? FunctionExtractor.Extract(conj, Program, axioms) : new LiteralExpr(Token.NoToken, true);
+ }
+
+ if (assumedExpr != null)
+ {
+ var lv = new LocalVariable(Token.NoToken,
+ new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool),
+ new QKeyValue(Token.NoToken, "assumption", new List<object>(), null));
+ currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
+ var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
+ var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
+ var assumed = new AssignCmd(currentImplementation.tok, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
+ assumed.IrrelevantForChecksumComputation = true;
+ currentImplementation.ExplicitAssumptionAboutCachedPrecondition = assumed;
+ after.Add(assumed);
+ }
+
+ if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
+ {
+ using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
+ {
+ var loc = currentImplementation.tok != null && currentImplementation.tok != Token.NoToken ? string.Format("{0}({1},{2})", currentImplementation.tok.filename, currentImplementation.tok.line, currentImplementation.tok.col) : "<unknown location>";
+ Console.Out.WriteLine("Processing implementation {0} (at {1}):", currentImplementation.Name, loc);
+ foreach (var a in axioms)
+ {
+ Console.Out.Write(" >>> added axiom: ");
+ a.Expr.Emit(tokTxtWr);
+ Console.Out.WriteLine();
+ }
+ foreach (var b in after)
+ {
+ Console.Out.Write(" >>> added after assuming the current precondition: ");
+ b.Emit(tokTxtWr, 0);
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ var result = VisitImplementation(currentImplementation);
+ currentImplementation = null;
+ this.programInCachedSnapshot = null;
+ return result;
+ }
+
+ public static void Inject(Program program, IEnumerable<Implementation> implementations, string requestId, string programId, out long[] cachingActionCounts)
+ {
+ var eai = new CachedVerificationResultInjector(program, implementations);
+
+ cachingActionCounts = new long[Enum.GetNames(typeof(VC.ConditionGeneration.CachingAction)).Length];
+ var run = new CachedVerificationResultInjectorRun { Start = DateTime.UtcNow, ImplementationCount = implementations.Count(), CachingActionCounts = cachingActionCounts };
+ foreach (var impl in implementations)
+ {
+ int priority;
+ var vr = ExecutionEngine.Cache.Lookup(impl, out priority);
+ if (vr != null && vr.ProgramId == programId)
+ {
+ if (priority == Priority.LOW) {
+ run.LowPriorityImplementationCount++;
+ } else if (priority == Priority.MEDIUM) {
+ run.MediumPriorityImplementationCount++;
+ } else if (priority == Priority.HIGH) {
+ run.HighPriorityImplementationCount++;
+ } else if (priority == Priority.SKIP) {
+ run.SkippedImplementationCount++;
+ }
+
+ if (priority == Priority.LOW || priority == Priority.MEDIUM || 3 <= CommandLineOptions.Clo.VerifySnapshots) {
+ if (TimeThreshold < vr.End.Subtract(vr.Start).TotalMilliseconds) {
+ SetErrorAndAssertionChecksumsInCachedSnapshot(impl, vr);
+ if (vr.ProgramId != null) {
+ var p = ExecutionEngine.CachedProgram(vr.ProgramId);
+ if (p != null) {
+ eai.Inject(impl, p);
+ run.TransformedImplementationCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ run.End = DateTime.UtcNow;
+ Statistics.AddRun(requestId, run);
+ }
+
+ private static void SetErrorAndAssertionChecksumsInCachedSnapshot(Implementation implementation, VerificationResult result)
+ {
+ if (result.Outcome == ConditionGeneration.Outcome.Errors && result.Errors != null && result.Errors.Count < CommandLineOptions.Clo.ProverCCLimit)
+ {
+ implementation.SetErrorChecksumToCachedError(result.Errors.Select(cex => new Tuple<byte[], byte[], object>(cex.Checksum, cex.SugaredCmdChecksum, cex)));
+ implementation.AssertionChecksumsInCachedSnapshot = result.AssertionChecksums;
+ }
+ else if (result.Outcome == ConditionGeneration.Outcome.Correct)
+ {
+ implementation.SetErrorChecksumToCachedError(new List<Tuple<byte[], byte[], object>>());
+ implementation.AssertionChecksumsInCachedSnapshot = result.AssertionChecksums;
+ }
+ }
+
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ var result = base.VisitCallCmd(node);
+
+ var oldProc = programInCachedSnapshot.FindProcedure(node.Proc.Name);
+ if (oldProc != null
+ && oldProc.DependencyChecksum != node.Proc.DependencyChecksum
+ && node.AssignedAssumptionVariable == null)
+ {
+ var before = new List<Cmd>();
+ var beforePrecondtionCheck = new List<Cmd>();
+ var after = new List<Cmd>();
+ var axioms = new List<Axiom>();
+ Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
+ // TODO(wuestholz): Try out two alternatives: only do this for low priority implementations or not at all.
+ var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program);
+ if (canUseSpecs && oldProc.SignatureEquals(node.Proc))
+ {
+ var desugaring = node.Desugaring;
+ Contract.Assert(desugaring != null);
+ var precond = node.CheckedPrecondition(oldProc, Program, e => FunctionExtractor.Extract(e, Program, axioms));
+ if (precond != null)
+ {
+ var assume = new AssumeCmd(node.tok, precond, new QKeyValue(Token.NoToken, "precondition_previous_snapshot", new List<object>(), null));
+ assume.IrrelevantForChecksumComputation = true;
+ beforePrecondtionCheck.Add(assume);
+ }
+
+ var unmods = node.UnmodifiedBefore(oldProc);
+ var eqs = new List<Expr>();
+ foreach (var unmod in unmods)
+ {
+ var oldUnmod = new LocalVariable(Token.NoToken,
+ new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", unmod.Name, FreshTemporaryVariableName), unmod.Type));
+ var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldUnmod));
+ var rhs = new IdentifierExpr(Token.NoToken, unmod.Decl);
+ var cmd = new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
+ cmd.IrrelevantForChecksumComputation = true;
+ before.Add(cmd);
+ var eq = LiteralExpr.Eq(new IdentifierExpr(Token.NoToken, oldUnmod), new IdentifierExpr(Token.NoToken, unmod.Decl));
+ eq.Type = Type.Bool;
+ eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ eqs.Add(eq);
+ }
+
+ var mods = node.ModifiedBefore(oldProc);
+ var oldSubst = new Dictionary<Variable, Expr>();
+ foreach (var mod in mods)
+ {
+ var oldMod = new LocalVariable(Token.NoToken,
+ new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", mod.Name, FreshTemporaryVariableName), mod.Type));
+ oldSubst[mod.Decl] = new IdentifierExpr(Token.NoToken, oldMod);
+ var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldMod));
+ var rhs = new IdentifierExpr(Token.NoToken, mod.Decl);
+ var cmd = new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
+ cmd.IrrelevantForChecksumComputation = true;
+ before.Add(cmd);
+ }
+
+ assumedExpr = node.Postcondition(oldProc, eqs, oldSubst, Program, e => FunctionExtractor.Extract(e, Program, axioms));
+ if (assumedExpr == null)
+ {
+ assumedExpr = new LiteralExpr(Token.NoToken, true);
+ }
+ }
+
+ if (assumedExpr != null)
+ {
+ var lv = new LocalVariable(Token.NoToken,
+ new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool),
+ new QKeyValue(Token.NoToken, "assumption", new List<object>(), null));
+ node.AssignedAssumptionVariable = lv;
+ currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
+ var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
+ var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
+ var assumed = new AssignCmd(node.tok, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
+ assumed.IrrelevantForChecksumComputation = true;
+ after.Add(assumed);
+ }
+
+ node.ExtendDesugaring(before, beforePrecondtionCheck, after);
+ if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
+ {
+ using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
+ {
+ var loc = node.tok != null && node.tok != Token.NoToken ? string.Format("{0}({1},{2})", node.tok.filename, node.tok.line, node.tok.col) : "<unknown location>";
+ Console.Out.WriteLine("Processing call to procedure {0} in implementation {1} (at {2}):", node.Proc.Name, currentImplementation.Name, loc);
+ foreach (var a in axioms)
+ {
+ Console.Out.Write(" >>> added axiom: ");
+ a.Expr.Emit(tokTxtWr);
+ Console.Out.WriteLine();
+ }
+ foreach (var b in before)
+ {
+ Console.Out.Write(" >>> added before: ");
+ b.Emit(tokTxtWr, 0);
+ }
+ foreach (var b in beforePrecondtionCheck)
+ {
+ Console.Out.Write(" >>> added before precondition check: ");
+ b.Emit(tokTxtWr, 0);
+ }
+ foreach (var a in after)
+ {
+ Console.Out.Write(" >>> added after: ");
+ a.Emit(tokTxtWr, 0);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+
+
+ sealed class FunctionExtractor : StandardVisitor
+ {
+ readonly Dictionary<Variable, BoundVariable> Substitutions = new Dictionary<Variable, BoundVariable>();
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ if (node.Decl == null || !(node.Decl is LocalVariable || node.Decl is Formal || node.Decl is GlobalVariable))
+ {
+ return node;
+ }
+ else
+ {
+ BoundVariable boundVar;
+ if (!Substitutions.TryGetValue(node.Decl, out boundVar))
+ {
+ boundVar = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, node.Name, node.Type));
+ Substitutions[node.Decl] = boundVar;
+ }
+ return new IdentifierExpr(node.tok, boundVar);
+ }
+ }
+
+ public static Expr Extract(Expr expr, Program program, List<Axiom> axioms)
+ {
+ Contract.Requires(expr != null && program != null && !program.TopLevelDeclarationsAreFrozen && axioms != null);
+
+ if (expr is LiteralExpr)
+ {
+ return expr;
+ }
+
+ var extractor = new FunctionExtractor();
+
+ var body = extractor.VisitExpr(expr);
+
+ var name = program.FreshExtractedFunctionName();
+ var originalVars = extractor.Substitutions.Keys.ToList();
+ var formalInArgs = originalVars.Select(v => new Formal(Token.NoToken, new TypedIdent(Token.NoToken, extractor.Substitutions[v].Name, extractor.Substitutions[v].TypedIdent.Type), true)).ToList<Variable>();
+ var formalOutArg = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, name + "$result$", expr.Type), false);
+ var func = new Function(Token.NoToken, name, formalInArgs, formalOutArg);
+ func.AddAttribute("never_pattern");
+
+ var boundVars = originalVars.Select(k => extractor.Substitutions[k]);
+ var axiomCall = new NAryExpr(Token.NoToken, new FunctionCall(func), boundVars.Select(b => new IdentifierExpr(Token.NoToken, b)).ToList<Expr>());
+ axiomCall.Type = expr.Type;
+ axiomCall.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ var eq = LiteralExpr.Eq(axiomCall, body);
+ eq.Type = body.Type;
+ eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ if (0 < formalInArgs.Count)
+ {
+ var forallExpr = new ForallExpr(Token.NoToken, boundVars.ToList<Variable>(), new Trigger(Token.NoToken, true, new List<Expr> { axiomCall }), eq);
+ body = forallExpr;
+ forallExpr.Attributes = new QKeyValue(Token.NoToken, "weight", new List<object> { new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(30)) }, null);
+ body.Type = Type.Bool;
+ }
+ else
+ {
+ body = eq;
+ }
+
+ var axiom = new Axiom(Token.NoToken, body);
+ func.DefinitionAxiom = axiom;
+ program.AddTopLevelDeclaration(func);
+ program.AddTopLevelDeclaration(axiom);
+ axioms.Add(axiom);
+
+ var call = new NAryExpr(Token.NoToken, new FunctionCall(func), originalVars.Select(v => new IdentifierExpr(Token.NoToken, v)).ToList<Expr>());
+ call.Type = expr.Type;
+ call.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ return call;
+ }
+ }
+
+
+ sealed class OtherDefinitionAxiomsCollector : ReadOnlyVisitor
+ {
+ Axiom currentAxiom;
+ Trigger currentTrigger;
+
+ public static void Collect(IEnumerable<Axiom> axioms)
+ {
+ var start = DateTime.UtcNow;
+
+ var v = new OtherDefinitionAxiomsCollector();
+ foreach (var a in axioms)
+ {
+ v.currentAxiom = a;
+ v.VisitExpr(a.Expr);
+ v.currentAxiom = null;
+ }
+
+ var end = DateTime.UtcNow;
+ if (CommandLineOptions.Clo.TraceCachingForDebugging)
+ {
+ Console.Out.WriteLine("Collected other definition axioms within {0:F0} ms.", end.Subtract(start).TotalMilliseconds);
+ }
+ }
+
+ public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
+ {
+ currentTrigger = node.Triggers;
+ while (currentTrigger != null)
+ {
+ foreach (var e in currentTrigger.Tr)
+ {
+ VisitExpr(e);
+ }
+ currentTrigger = currentTrigger.Next;
+ }
+ return base.VisitQuantifierExpr(node);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (currentTrigger != null)
+ {
+ // We found a function call within a trigger of a quantifier expression.
+ var funCall = node.Fun as FunctionCall;
+ if (funCall != null && funCall.Func != null && funCall.Func.Checksum != null && funCall.Func.Checksum != "stable")
+ {
+ funCall.Func.AddOtherDefinitionAxiom(currentAxiom);
+ }
+ }
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+
+ sealed class DependencyCollector : ReadOnlyVisitor
+ {
+ private DeclWithFormals currentDeclaration;
+ private Axiom currentAxiom;
+
+ public static void Collect(Program program)
+ {
+ var start = DateTime.UtcNow;
+
+ var dc = new DependencyCollector();
+ dc.VisitProgram(program);
+
+ var end = DateTime.UtcNow;
+ if (CommandLineOptions.Clo.TraceCachingForDebugging)
+ {
+ Console.Out.WriteLine("Collected dependencies within {0:F0} ms.", end.Subtract(start).TotalMilliseconds);
+ }
+ }
+
+ public static bool CanExpressOldSpecs(Procedure oldProc, Program newProg, bool ignoreModifiesClauses = false)
+ {
+ Contract.Requires(oldProc != null && newProg != null);
+
+ var funcs = newProg.Functions;
+ var globals = newProg.GlobalVariables;
+ return oldProc.DependenciesCollected
+ && (oldProc.FunctionDependencies == null || oldProc.FunctionDependencies.All(dep => funcs.Any(f => f.Name == dep.Name && f.DependencyChecksum == dep.DependencyChecksum)))
+ && (ignoreModifiesClauses || oldProc.Modifies.All(m => globals.Any(g => g.Name == m.Name)));
+ }
+
+ public override Procedure VisitProcedure(Procedure node)
+ {
+ currentDeclaration = node;
+
+ foreach (var param in node.InParams)
+ {
+ if (param.TypedIdent != null && param.TypedIdent.WhereExpr != null)
+ {
+ VisitExpr(param.TypedIdent.WhereExpr);
+ }
+ }
+
+ var result = base.VisitProcedure(node);
+ node.DependenciesCollected = true;
+ currentDeclaration = null;
+ return result;
+ }
+
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ currentDeclaration = node;
+
+ foreach (var param in node.InParams)
+ {
+ if (param.TypedIdent != null && param.TypedIdent.WhereExpr != null)
+ {
+ VisitExpr(param.TypedIdent.WhereExpr);
+ }
+ }
+
+ if (node.Proc != null)
+ {
+ node.AddProcedureDependency(node.Proc);
+ }
+
+ var result = base.VisitImplementation(node);
+ node.DependenciesCollected = true;
+ currentDeclaration = null;
+ return result;
+ }
+
+ public override Axiom VisitAxiom(Axiom node)
+ {
+ if (node.DependenciesCollected)
+ {
+ if (currentDeclaration != null && node.FunctionDependencies != null)
+ {
+ foreach (var f in node.FunctionDependencies)
+ {
+ currentDeclaration.AddFunctionDependency(f);
+ }
+ }
+ return node;
+ }
+ currentAxiom = node;
+ var result = base.VisitAxiom(node);
+ node.DependenciesCollected = true;
+ currentAxiom = null;
+ return result;
+ }
+
+ public override Function VisitFunction(Function node)
+ {
+ currentDeclaration = node;
+
+ if (node.DefinitionAxiom != null)
+ {
+ VisitAxiom(node.DefinitionAxiom);
+ }
+ if (node.OtherDefinitionAxioms != null)
+ {
+ foreach (var a in node.OtherDefinitionAxioms)
+ {
+ if (a != node.DefinitionAxiom)
+ {
+ VisitAxiom(a);
+ }
+ }
+ }
+
+ var result = base.VisitFunction(node);
+ node.DependenciesCollected = true;
+ currentDeclaration = null;
+ return result;
+ }
+
+ public override Cmd VisitCallCmd(CallCmd node)
+ {
+ if (currentDeclaration != null)
+ {
+ currentDeclaration.AddProcedureDependency(node.Proc);
+ }
+
+ return base.VisitCallCmd(node);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ var funCall = node.Fun as FunctionCall;
+ if (funCall != null)
+ {
+ if (currentDeclaration != null)
+ {
+ currentDeclaration.AddFunctionDependency(funCall.Func);
+ }
+ if (currentAxiom != null)
+ {
+ currentAxiom.AddFunctionDependency(funCall.Func);
+ }
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+
+ static internal class Priority
+ {
+ public static readonly int LOW = 1; // the same snapshot has been verified before, but a callee has changed
+ public static readonly int MEDIUM = 2; // old snapshot has been verified before
+ public static readonly int HIGH = 3; // has been never verified before
+ public static readonly int SKIP = int.MaxValue; // highest priority to get them done as soon as possible
+ }
+
+
+ public sealed class VerificationResultCache
+ {
+ private readonly MemoryCache Cache = new MemoryCache("VerificationResultCache");
+ private readonly CacheItemPolicy Policy = new CacheItemPolicy { SlidingExpiration = new TimeSpan(0, 10, 0), Priority = CacheItemPriority.Default };
+
+
+ public void Insert(Implementation impl, VerificationResult result)
+ {
+ Contract.Requires(impl != null);
+ Contract.Requires(result != null);
+
+ Cache.Set(impl.Id, result, Policy);
+ }
+
+
+ public VerificationResult Lookup(Implementation impl, out int priority)
+ {
+ Contract.Requires(impl != null);
+
+ var result = Cache.Get(impl.Id) as VerificationResult;
+ if (result == null)
+ {
+ priority = Priority.HIGH;
+ }
+ else if (result.Checksum != impl.Checksum)
+ {
+ priority = Priority.MEDIUM;
+ }
+ else if (impl.DependencyChecksum == null || result.DependeciesChecksum != impl.DependencyChecksum)
+ {
+ priority = Priority.LOW;
+ }
+ else if (result.Outcome == ConditionGeneration.Outcome.TimedOut && CommandLineOptions.Clo.RunDiagnosticsOnTimeout)
+ {
+ priority = Priority.MEDIUM;
+ }
+ else
+ {
+ priority = Priority.SKIP;
+ }
+ return result;
+ }
+
+
+ public void Clear()
+ {
+ Cache.Trim(100);
+ }
+
+
+ public void RemoveMatchingKeys(Regex keyRegexp)
+ {
+ Contract.Requires(keyRegexp != null);
+
+ foreach (var kv in Cache)
+ {
+ if (keyRegexp.IsMatch(kv.Key))
+ {
+ Cache.Remove(kv.Key);
+ }
+ }
+ }
+
+
+ public int VerificationPriority(Implementation impl)
+ {
+ Contract.Requires(impl != null);
+
+ int priority;
+ Lookup(impl, out priority);
+ return priority;
+ }
+ }
+
+}
diff --git a/Source/Forro.sln b/Source/Forro.sln
index 39e50152..daaf8ecc 100644
--- a/Source/Forro.sln
+++ b/Source/Forro.sln
@@ -1,20 +1,20 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Forro", "Forro\Forro.fsproj", "{C75E47A0-E88D-4035-9EBF-F6647AF92B79}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x86 = Debug|x86
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Debug|x86.ActiveCfg = Debug|x86
- {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Debug|x86.Build.0 = Debug|x86
- {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Release|x86.ActiveCfg = Release|x86
- {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Release|x86.Build.0 = Release|x86
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Forro", "Forro\Forro.fsproj", "{C75E47A0-E88D-4035-9EBF-F6647AF92B79}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Debug|x86.ActiveCfg = Debug|x86
+ {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Debug|x86.Build.0 = Debug|x86
+ {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Release|x86.ActiveCfg = Release|x86
+ {C75E47A0-E88D-4035-9EBF-F6647AF92B79}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Source/Forro/Ast.fs b/Source/Forro/Ast.fs
index 6c7ba65c..779beefb 100644
--- a/Source/Forro/Ast.fs
+++ b/Source/Forro/Ast.fs
@@ -1,38 +1,38 @@
-module Forro
-
-type Field = Head | Tail | Valid
-
-type Variable = Var of string
-
-let VarName v =
- match v with Var(x) -> x
-
-type Operator = Eq | Neq | Plus | Minus | Times
- | Less | AtMost | And | Or
-
-type Expression =
- | Constant of int
- | Null
- | Identifier of Variable
- | Not of Expression
- | Binary of Operator * Expression * Expression
- | Select of Expression * Field
- | Old of Expression
-
-type Statement =
- | Assign of Variable * Expression
- | Update of Expression * Field * Expression
- | Alloc of Variable * Expression * Expression
- | IfStmt of Expression * StmtList * StmtList
- | WhileStmt of Expression * Expression list * StmtList
- | CallStmt of Variable list * string * Expression list
- | Assert of Expression
-
-and StmtList =
- Block of Statement list
-
-type Procedure =
- Proc of string * Variable list * Variable list * Expression * Expression * StmtList
-
-type Program =
- Prog of Procedure list
+module Forro
+
+type Field = Head | Tail | Valid
+
+type Variable = Var of string
+
+let VarName v =
+ match v with Var(x) -> x
+
+type Operator = Eq | Neq | Plus | Minus | Times
+ | Less | AtMost | And | Or
+
+type Expression =
+ | Constant of int
+ | Null
+ | Identifier of Variable
+ | Not of Expression
+ | Binary of Operator * Expression * Expression
+ | Select of Expression * Field
+ | Old of Expression
+
+type Statement =
+ | Assign of Variable * Expression
+ | Update of Expression * Field * Expression
+ | Alloc of Variable * Expression * Expression
+ | IfStmt of Expression * StmtList * StmtList
+ | WhileStmt of Expression * Expression list * StmtList
+ | CallStmt of Variable list * string * Expression list
+ | Assert of Expression
+
+and StmtList =
+ Block of Statement list
+
+type Procedure =
+ Proc of string * Variable list * Variable list * Expression * Expression * StmtList
+
+type Program =
+ Prog of Procedure list
diff --git a/Source/Forro/BoogieAst.fs b/Source/Forro/BoogieAst.fs
index 964f6667..7c1819da 100644
--- a/Source/Forro/BoogieAst.fs
+++ b/Source/Forro/BoogieAst.fs
@@ -1,40 +1,40 @@
-namespace BoogieAst
-
-type BType = BInt | BBool
-
-type BOperator = BEq | BNeq | BPlus | BMinus | BTimes | BLess | BAtMost | BAnd | BOr
-
-type BExpression =
- | BConstant of int
- | BFalse
- | BTrue
- | BNull
- | BIdentifier of string
- | BNot of BExpression
- | BBinary of BOperator * BExpression * BExpression
- | BSelect of string * BExpression
- | BToPred of BExpression // BToPred(e) == (e != 0)
- | BToTerm of BExpression // BToTerm(e) == (if e then 1 else 0)
- | BOld of BExpression
- | BFunc of string * BExpression list
-
-type BStmtList =
- BBlock of Statement list
-
-and Statement =
- | BAssign of string * BExpression
- | BUpdate of string * BExpression * BExpression
- | BHavoc of string list
- | BAssert of BExpression
- | BAssume of BExpression
- | BIfStmt of BExpression * BStmtList * BStmtList
- | BWhileStmt of BExpression * BExpression list * BStmtList
- | BCallStmt of string list * string * BExpression list
-
-type BVarDecl = BVar of string * BType
-
-type BProcedure =
- BProc of string * BVarDecl list * BVarDecl list * BExpression * string list * BExpression * BVarDecl list * BStmtList
-
-type BProgram =
- BProg of string * BProcedure list
+namespace BoogieAst
+
+type BType = BInt | BBool
+
+type BOperator = BEq | BNeq | BPlus | BMinus | BTimes | BLess | BAtMost | BAnd | BOr
+
+type BExpression =
+ | BConstant of int
+ | BFalse
+ | BTrue
+ | BNull
+ | BIdentifier of string
+ | BNot of BExpression
+ | BBinary of BOperator * BExpression * BExpression
+ | BSelect of string * BExpression
+ | BToPred of BExpression // BToPred(e) == (e != 0)
+ | BToTerm of BExpression // BToTerm(e) == (if e then 1 else 0)
+ | BOld of BExpression
+ | BFunc of string * BExpression list
+
+type BStmtList =
+ BBlock of Statement list
+
+and Statement =
+ | BAssign of string * BExpression
+ | BUpdate of string * BExpression * BExpression
+ | BHavoc of string list
+ | BAssert of BExpression
+ | BAssume of BExpression
+ | BIfStmt of BExpression * BStmtList * BStmtList
+ | BWhileStmt of BExpression * BExpression list * BStmtList
+ | BCallStmt of string list * string * BExpression list
+
+type BVarDecl = BVar of string * BType
+
+type BProcedure =
+ BProc of string * BVarDecl list * BVarDecl list * BExpression * string list * BExpression * BVarDecl list * BStmtList
+
+type BProgram =
+ BProg of string * BProcedure list
diff --git a/Source/Forro/BoogiePrinter.fs b/Source/Forro/BoogiePrinter.fs
index 8f2b37ee..e9497ab5 100644
--- a/Source/Forro/BoogiePrinter.fs
+++ b/Source/Forro/BoogiePrinter.fs
@@ -1,112 +1,112 @@
-module BoogiePrinter
-
-open ForroPrinter // to get Indent
-open BoogieAst
-
-let PrintWithSep Pr sep list =
- ignore (List.fold (fun sp e -> printf "%s" sp ; Pr e ; sep) "" list)
-
-let TypeName t =
- match t with
- | BInt -> "int"
- | BBool -> "bool"
-
-let PrVarType v =
- match v with
- | BVar(name,t) ->
- printf "%s: %s" name (TypeName t)
-
-let PrintOp op =
- printf " "
- match op with
- | BEq -> printf "=="
- | BNeq -> printf "!="
- | BPlus -> printf "+"
- | BMinus -> printf "-"
- | BTimes -> printf "*"
- | BLess -> printf "<"
- | BAtMost -> printf "<="
- | BAnd -> printf "&&"
- | BOr -> printf "||"
- printf " "
-
-let rec PrintExpr e =
- match e with
- | BConstant(x) -> printf "%d" x
- | BFalse -> printf "false"
- | BTrue -> printf "true"
- | BNull -> printf "null"
- | BIdentifier(id) -> printf "%s" id
- | BNot(e) -> printf "!(" ; PrintExpr e ; printf ")"
- | BBinary(op,e0,e1) -> printf "(" ; PrintExpr e0 ; PrintOp op ; PrintExpr e1 ; printf ")"
- | BSelect(var,e) -> printf "%s[" var ; PrintExpr e ; printf "]"
- | BToPred(e) -> printf "(" ; PrintExpr e ; printf " != 0)"
- | BToTerm(e) -> printf "(if " ; PrintExpr e ; printf " then 1 else 0)"
- | BOld(e) -> printf "old(" ; PrintExpr e ; printf ")"
- | BFunc(id,args) -> printf "%s(" id ; PrintWithSep PrintExpr ", " args ; printf ")"
-
-let rec PrintStmt indent stmt =
- Indent indent
- let ind = indent + 2
- match stmt with
- | BAssign(id,e) -> printf "%s := " id ; PrintExpr e ; printfn ";"
- | BUpdate(id,obj,rhs) -> printf "%s[" id ; PrintExpr obj ; printf "] := " ; PrintExpr rhs ; printfn ";"
- | BHavoc(ids) -> printf "havoc " ; PrintWithSep (printf "%s") ", " ids ; printfn ";"
- | BAssert(e) -> printf "assert " ; PrintExpr e ; printfn ";"
- | BAssume(e) -> printf "assume " ; PrintExpr e ; printfn ";"
- | BIfStmt(e,thn,els) ->
- printf "if (" ; PrintExpr e ; printfn ") {"
- PrintStmtList ind thn
- Indent indent
- printfn "} else {"
- PrintStmtList ind els
- Indent indent
- printfn "}"
- | BWhileStmt(e, invs, body) ->
- printf "while (" ; PrintExpr e ; printfn ")"
- List.iter (fun inv -> Indent ind ; printf "invariant " ; PrintExpr inv ; printfn ";") invs
- Indent indent
- printfn "{"
- PrintStmtList ind body
- Indent indent
- printfn "}"
- | BCallStmt(outs, id, ins) ->
- printf "call "
- if outs.IsEmpty then () else PrintWithSep (fun p -> printf "%s" p) ", " outs ; printf " := "
- printf "%s(" id
- PrintWithSep PrintExpr ", " ins
- printfn ");"
-
-and PrintStmtList indent stmts =
- match stmts with
- | BBlock(slist) -> List.iter (fun s -> PrintStmt indent s) slist
-
-let BPrintProc proc =
- match proc with
- | BProc(name, ins, outs, req, frame, ens, locals, body) ->
- printfn ""
- printf "procedure %s(" name
- PrintWithSep PrVarType ", " ins
- printf ") returns ("
- PrintWithSep PrVarType ", " outs
- printfn ")"
- printf " requires "
- PrintExpr req
- printfn ";"
- printf " modifies "
- PrintWithSep (printf "%s") ", " frame
- printfn ";"
- printf " ensures "
- PrintExpr ens
- printfn ";"
- printfn "{"
- List.iter (fun local -> printf " var " ; PrVarType local ; printfn ";") locals
- if locals.IsEmpty then () else printfn ""
- PrintStmtList 2 body
- printfn "}"
-
-let BPrint (prog: BProgram) =
- match prog with
- | BProg(prelude, procs) ->
- printfn "%s" prelude
- List.iter BPrintProc procs
+module BoogiePrinter
+
+open ForroPrinter // to get Indent
+open BoogieAst
+
+let PrintWithSep Pr sep list =
+ ignore (List.fold (fun sp e -> printf "%s" sp ; Pr e ; sep) "" list)
+
+let TypeName t =
+ match t with
+ | BInt -> "int"
+ | BBool -> "bool"
+
+let PrVarType v =
+ match v with
+ | BVar(name,t) ->
+ printf "%s: %s" name (TypeName t)
+
+let PrintOp op =
+ printf " "
+ match op with
+ | BEq -> printf "=="
+ | BNeq -> printf "!="
+ | BPlus -> printf "+"
+ | BMinus -> printf "-"
+ | BTimes -> printf "*"
+ | BLess -> printf "<"
+ | BAtMost -> printf "<="
+ | BAnd -> printf "&&"
+ | BOr -> printf "||"
+ printf " "
+
+let rec PrintExpr e =
+ match e with
+ | BConstant(x) -> printf "%d" x
+ | BFalse -> printf "false"
+ | BTrue -> printf "true"
+ | BNull -> printf "null"
+ | BIdentifier(id) -> printf "%s" id
+ | BNot(e) -> printf "!(" ; PrintExpr e ; printf ")"
+ | BBinary(op,e0,e1) -> printf "(" ; PrintExpr e0 ; PrintOp op ; PrintExpr e1 ; printf ")"
+ | BSelect(var,e) -> printf "%s[" var ; PrintExpr e ; printf "]"
+ | BToPred(e) -> printf "(" ; PrintExpr e ; printf " != 0)"
+ | BToTerm(e) -> printf "(if " ; PrintExpr e ; printf " then 1 else 0)"
+ | BOld(e) -> printf "old(" ; PrintExpr e ; printf ")"
+ | BFunc(id,args) -> printf "%s(" id ; PrintWithSep PrintExpr ", " args ; printf ")"
+
+let rec PrintStmt indent stmt =
+ Indent indent
+ let ind = indent + 2
+ match stmt with
+ | BAssign(id,e) -> printf "%s := " id ; PrintExpr e ; printfn ";"
+ | BUpdate(id,obj,rhs) -> printf "%s[" id ; PrintExpr obj ; printf "] := " ; PrintExpr rhs ; printfn ";"
+ | BHavoc(ids) -> printf "havoc " ; PrintWithSep (printf "%s") ", " ids ; printfn ";"
+ | BAssert(e) -> printf "assert " ; PrintExpr e ; printfn ";"
+ | BAssume(e) -> printf "assume " ; PrintExpr e ; printfn ";"
+ | BIfStmt(e,thn,els) ->
+ printf "if (" ; PrintExpr e ; printfn ") {"
+ PrintStmtList ind thn
+ Indent indent
+ printfn "} else {"
+ PrintStmtList ind els
+ Indent indent
+ printfn "}"
+ | BWhileStmt(e, invs, body) ->
+ printf "while (" ; PrintExpr e ; printfn ")"
+ List.iter (fun inv -> Indent ind ; printf "invariant " ; PrintExpr inv ; printfn ";") invs
+ Indent indent
+ printfn "{"
+ PrintStmtList ind body
+ Indent indent
+ printfn "}"
+ | BCallStmt(outs, id, ins) ->
+ printf "call "
+ if outs.IsEmpty then () else PrintWithSep (fun p -> printf "%s" p) ", " outs ; printf " := "
+ printf "%s(" id
+ PrintWithSep PrintExpr ", " ins
+ printfn ");"
+
+and PrintStmtList indent stmts =
+ match stmts with
+ | BBlock(slist) -> List.iter (fun s -> PrintStmt indent s) slist
+
+let BPrintProc proc =
+ match proc with
+ | BProc(name, ins, outs, req, frame, ens, locals, body) ->
+ printfn ""
+ printf "procedure %s(" name
+ PrintWithSep PrVarType ", " ins
+ printf ") returns ("
+ PrintWithSep PrVarType ", " outs
+ printfn ")"
+ printf " requires "
+ PrintExpr req
+ printfn ";"
+ printf " modifies "
+ PrintWithSep (printf "%s") ", " frame
+ printfn ";"
+ printf " ensures "
+ PrintExpr ens
+ printfn ";"
+ printfn "{"
+ List.iter (fun local -> printf " var " ; PrVarType local ; printfn ";") locals
+ if locals.IsEmpty then () else printfn ""
+ PrintStmtList 2 body
+ printfn "}"
+
+let BPrint (prog: BProgram) =
+ match prog with
+ | BProg(prelude, procs) ->
+ printfn "%s" prelude
+ List.iter BPrintProc procs
diff --git a/Source/Forro/Forro.fsproj b/Source/Forro/Forro.fsproj
index 8f6fc223..161d79db 100644
--- a/Source/Forro/Forro.fsproj
+++ b/Source/Forro/Forro.fsproj
@@ -1,83 +1,83 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{c75e47a0-e88d-4035-9ebf-f6647af92b79}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <RootNamespace>Language</RootNamespace>
- <AssemblyName>Forro</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- <Name>Language</Name>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <Tailcalls>false</Tailcalls>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <WarningLevel>3</WarningLevel>
- <PlatformTarget>x86</PlatformTarget>
- <DocumentationFile>bin\Debug\Language.XML</DocumentationFile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <Tailcalls>true</Tailcalls>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <WarningLevel>3</WarningLevel>
- <PlatformTarget>x86</PlatformTarget>
- <DocumentationFile>bin\Release\Language.XML</DocumentationFile>
- </PropertyGroup>
- <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
- <Import Project="$(MSBuildExtensionsPath32)\..\FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.targets" />
- <PropertyGroup>
- <FsLexOutputFolder>$(IntermediateOutputPath)</FsLexOutputFolder>
- <FsYaccOutputFolder>$(IntermediateOutputPath)</FsYaccOutputFolder>
- </PropertyGroup>
- <ItemGroup>
- <Compile Include="Ast.fs" />
- <Compile Include="$(IntermediateOutputPath)\Parser.fs">
- <Visible>false</Visible>
- <Link>Parser.fs</Link>
- </Compile>
- <Compile Include="$(IntermediateOutputPath)\Lexer.fs">
- <Visible>false</Visible>
- <Link>Lexer.fs</Link>
- </Compile>
- <FsYacc Include="Parser.fsy">
- <OtherFlags>--module Parser</OtherFlags>
- </FsYacc>
- <FsLex Include="Lexer.fsl">
- <OtherFlags>--unicode</OtherFlags>
- </FsLex>
- <Compile Include="Printer.fs" />
- <Compile Include="Resolver.fs" />
- <Compile Include="BoogieAst.fs" />
- <Compile Include="BoogiePrinter.fs" />
- <Compile Include="Translator.fs" />
- <Compile Include="Main.fs" />
- </ItemGroup>
- <ItemGroup>
- <Reference Include="FSharp.PowerPack">
- <HintPath>C:\Program Files\FSharpPowerPack-1.9.9.9\bin\FSharp.PowerPack.dll</HintPath>
- </Reference>
- <Reference Include="mscorlib" />
- <Reference Include="FSharp.Core" />
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Numerics" />
- </ItemGroup>
- <!-- 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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{c75e47a0-e88d-4035-9ebf-f6647af92b79}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Language</RootNamespace>
+ <AssemblyName>Forro</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+ <Name>Language</Name>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <Tailcalls>false</Tailcalls>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <PlatformTarget>x86</PlatformTarget>
+ <DocumentationFile>bin\Debug\Language.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <Tailcalls>true</Tailcalls>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <WarningLevel>3</WarningLevel>
+ <PlatformTarget>x86</PlatformTarget>
+ <DocumentationFile>bin\Release\Language.XML</DocumentationFile>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+ <Import Project="$(MSBuildExtensionsPath32)\..\FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.targets" />
+ <PropertyGroup>
+ <FsLexOutputFolder>$(IntermediateOutputPath)</FsLexOutputFolder>
+ <FsYaccOutputFolder>$(IntermediateOutputPath)</FsYaccOutputFolder>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Ast.fs" />
+ <Compile Include="$(IntermediateOutputPath)\Parser.fs">
+ <Visible>false</Visible>
+ <Link>Parser.fs</Link>
+ </Compile>
+ <Compile Include="$(IntermediateOutputPath)\Lexer.fs">
+ <Visible>false</Visible>
+ <Link>Lexer.fs</Link>
+ </Compile>
+ <FsYacc Include="Parser.fsy">
+ <OtherFlags>--module Parser</OtherFlags>
+ </FsYacc>
+ <FsLex Include="Lexer.fsl">
+ <OtherFlags>--unicode</OtherFlags>
+ </FsLex>
+ <Compile Include="Printer.fs" />
+ <Compile Include="Resolver.fs" />
+ <Compile Include="BoogieAst.fs" />
+ <Compile Include="BoogiePrinter.fs" />
+ <Compile Include="Translator.fs" />
+ <Compile Include="Main.fs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="FSharp.PowerPack">
+ <HintPath>C:\Program Files\FSharpPowerPack-1.9.9.9\bin\FSharp.PowerPack.dll</HintPath>
+ </Reference>
+ <Reference Include="mscorlib" />
+ <Reference Include="FSharp.Core" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Numerics" />
+ </ItemGroup>
+ <!-- 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/Forro/Lexer.fsl b/Source/Forro/Lexer.fsl
index 4252af23..5f69df7c 100644
--- a/Source/Forro/Lexer.fsl
+++ b/Source/Forro/Lexer.fsl
@@ -1,60 +1,60 @@
-{
-module Lexer
-open System
-open Parser
-open Microsoft.FSharp.Text.Lexing
-}
-
-// These are some regular expression definitions
-let digit = ['0'-'9']
-let nondigit = [ 'a'-'z' 'A'-'Z' '_' ]
-let idchar = (nondigit | digit)
-let whitespace = [' ' '\t' ]
-let newline = ('\n' | '\r' '\n')
-
-rule tokenize = parse
-| whitespace { tokenize lexbuf }
-| newline { // lexbuf.EndPos <- lexbuf.EndPos.AsNewLinePos() ;
- tokenize lexbuf }
-// operators
-| "==" { EQ }
-| "!=" { NEQ }
-| "+" { PLUS }
-| "-" { MINUS }
-| "*" { STAR }
-| "<" { LESS }
-| "<=" { ATMOST }
-| "and" { AND }
-| "or" { OR }
-| "not" { NOT }
-| "old" { OLD }
-| "." { DOT }
-// misc
-| "(" { LPAREN }
-| ")" { RPAREN }
-| "{" { LCURLY }
-| "}" { RCURLY }
-| ";" { SEMI }
-| "," { COMMA }
-| ":=" { ASSIGN }
-// keywords
-| "procedure" { PROCEDURE }
-| "requires" { REQUIRES }
-| "ensures" { ENSURES }
-| "do" { DO }
-| "end" { END }
-| "new" { NEW }
-| "if" { IF }
-| "then" { THEN }
-| "else" { ELSE }
-| "while" { WHILE }
-| "invariant" { INVARIANT }
-| "call" { CALL }
-| "assert" { ASSERT }
-// literals
-| ['-']?digit+ { INT32 (Int32.Parse(LexBuffer<char>.LexemeString lexbuf)) }
-| "null" { NULL }
-// identifiers
-| idchar+ { ID (LexBuffer<char>.LexemeString lexbuf) }
-// EOF
-| eof { EOF }
+{
+module Lexer
+open System
+open Parser
+open Microsoft.FSharp.Text.Lexing
+}
+
+// These are some regular expression definitions
+let digit = ['0'-'9']
+let nondigit = [ 'a'-'z' 'A'-'Z' '_' ]
+let idchar = (nondigit | digit)
+let whitespace = [' ' '\t' ]
+let newline = ('\n' | '\r' '\n')
+
+rule tokenize = parse
+| whitespace { tokenize lexbuf }
+| newline { // lexbuf.EndPos <- lexbuf.EndPos.AsNewLinePos() ;
+ tokenize lexbuf }
+// operators
+| "==" { EQ }
+| "!=" { NEQ }
+| "+" { PLUS }
+| "-" { MINUS }
+| "*" { STAR }
+| "<" { LESS }
+| "<=" { ATMOST }
+| "and" { AND }
+| "or" { OR }
+| "not" { NOT }
+| "old" { OLD }
+| "." { DOT }
+// misc
+| "(" { LPAREN }
+| ")" { RPAREN }
+| "{" { LCURLY }
+| "}" { RCURLY }
+| ";" { SEMI }
+| "," { COMMA }
+| ":=" { ASSIGN }
+// keywords
+| "procedure" { PROCEDURE }
+| "requires" { REQUIRES }
+| "ensures" { ENSURES }
+| "do" { DO }
+| "end" { END }
+| "new" { NEW }
+| "if" { IF }
+| "then" { THEN }
+| "else" { ELSE }
+| "while" { WHILE }
+| "invariant" { INVARIANT }
+| "call" { CALL }
+| "assert" { ASSERT }
+// literals
+| ['-']?digit+ { INT32 (Int32.Parse(LexBuffer<char>.LexemeString lexbuf)) }
+| "null" { NULL }
+// identifiers
+| idchar+ { ID (LexBuffer<char>.LexemeString lexbuf) }
+// EOF
+| eof { EOF }
diff --git a/Source/Forro/Main.fs b/Source/Forro/Main.fs
index 3b0f550f..07d1a12e 100644
--- a/Source/Forro/Main.fs
+++ b/Source/Forro/Main.fs
@@ -1,57 +1,57 @@
-open System
-open Microsoft.FSharp.Text.Lexing
-
-open System.IO
-
-open ForroPrinter
-open Resolver
-open Lexer
-open Parser
-open BoogiePrinter
-
-open Translator
-
-let readAndProcess tracing (filename: string) =
- try
- if tracing then printfn "Forró: version 1.0" else ()
- // lex
- let f = if filename = null then Console.In else new StreamReader(filename) :> TextReader
- let lexbuf = LexBuffer<char>.FromTextReader(f)
- lexbuf.EndPos <- { pos_bol = 0;
- pos_fname=if filename = null then "stdin" else filename;
- pos_cnum=0;
- pos_lnum=1 }
- // parse
- let prog = Parser.start Lexer.tokenize lexbuf
- // print the given Forró program
- if tracing then
- printfn "---------- Given Forró program ----------"
- Print prog
- else ()
- // make sure the program is legal
- let rprog = Resolve prog
- // translate into Boogie
- let bprog = Translate rprog
- // print the Boogie program
- if tracing then printfn "---------- Resulting Boogie program ----------" else ()
- BPrint bprog
- // that's it
- if tracing then printfn "----------" ; printfn "Done" else ()
-
- with
- | ResolutionError(msg) ->
- printfn "Resolution error: %s" msg
- | ex ->
- printfn "Unhandled Exception: %s" ex.Message
-
-let rec start n (args: string []) tracing filename =
- if n < args.Length then
- let arg = args.[n]
- if arg = "/break" then ignore (System.Diagnostics.Debugger.Launch()) else ()
- let filename = if arg.StartsWith "/" then filename else arg
- start (n+1) args (tracing || arg = "/trace") filename
- else
- readAndProcess tracing filename
-
-let args = Environment.GetCommandLineArgs()
-start 1 args false null
+open System
+open Microsoft.FSharp.Text.Lexing
+
+open System.IO
+
+open ForroPrinter
+open Resolver
+open Lexer
+open Parser
+open BoogiePrinter
+
+open Translator
+
+let readAndProcess tracing (filename: string) =
+ try
+ if tracing then printfn "Forró: version 1.0" else ()
+ // lex
+ let f = if filename = null then Console.In else new StreamReader(filename) :> TextReader
+ let lexbuf = LexBuffer<char>.FromTextReader(f)
+ lexbuf.EndPos <- { pos_bol = 0;
+ pos_fname=if filename = null then "stdin" else filename;
+ pos_cnum=0;
+ pos_lnum=1 }
+ // parse
+ let prog = Parser.start Lexer.tokenize lexbuf
+ // print the given Forró program
+ if tracing then
+ printfn "---------- Given Forró program ----------"
+ Print prog
+ else ()
+ // make sure the program is legal
+ let rprog = Resolve prog
+ // translate into Boogie
+ let bprog = Translate rprog
+ // print the Boogie program
+ if tracing then printfn "---------- Resulting Boogie program ----------" else ()
+ BPrint bprog
+ // that's it
+ if tracing then printfn "----------" ; printfn "Done" else ()
+
+ with
+ | ResolutionError(msg) ->
+ printfn "Resolution error: %s" msg
+ | ex ->
+ printfn "Unhandled Exception: %s" ex.Message
+
+let rec start n (args: string []) tracing filename =
+ if n < args.Length then
+ let arg = args.[n]
+ if arg = "/break" then ignore (System.Diagnostics.Debugger.Launch()) else ()
+ let filename = if arg.StartsWith "/" then filename else arg
+ start (n+1) args (tracing || arg = "/trace") filename
+ else
+ readAndProcess tracing filename
+
+let args = Environment.GetCommandLineArgs()
+start 1 args false null
diff --git a/Source/Forro/Parser.fsy b/Source/Forro/Parser.fsy
index 5dbb8a4c..af64d267 100644
--- a/Source/Forro/Parser.fsy
+++ b/Source/Forro/Parser.fsy
@@ -1,122 +1,122 @@
-%{
-
-open Forro
-
-exception ParseError of string
-
-let StringsToVariables ss = [ for s in ss -> Var(s) ]
-
-let IdToField id =
- match id with
- | "head" -> Field.Head
- | "tail" -> Field.Tail
- | "valid" -> Field.Valid
- | _ -> raise (ParseError ("illegal field selector: '" + id + "' (legal selectors are 'head', 'tail', and 'valid')"))
-
-%}
-
-// The start token becomes a parser function in the compiled code:
-%start start
-
-// These are the terminal tokens of the grammar along with the types of
-// the data carried by each token:
-%token <string> ID
-%token <System.Int32> INT32
-%token NULL
-%token DOT
-%token NOT
-%token STAR
-%token PLUS MINUS
-%token EQ NEQ LESS ATMOST
-%token AND OR
-%token OLD LPAREN RPAREN LCURLY RCURLY SEMI COMMA ASSIGN
-%token PROCEDURE REQUIRES ENSURES DO END
-%token NEW IF THEN ELSE WHILE INVARIANT CALL ASSERT
-%token EOF
-
-// This is the type of the data produced by a successful reduction of the 'start'
-// symbol:
-%type < Forro.Program > start
-
-%%
-
-// These are the rules of the grammar along with the F# code of the
-// actions executed as rules are reduced. In this case the actions
-// produce data using F# data construction terms.
-start: Prog EOF { Prog(List.rev($1)) }
-
-Prog: Proc { [$1] }
- | Prog Proc { $2 :: $1 }
-
-Proc:
- PROCEDURE Signature ProcedureSpec
- DO StmtList END SEMI
- { match $2, $3 with (outs,id,ins), (req,ens) -> Proc(id, StringsToVariables ins, StringsToVariables outs, req, ens, $5) }
-
-ProcedureSpec:
- REQUIRES Expression ENSURES Expression { $2, $4 }
-
-Signature:
- ID LPAREN IdList RPAREN { [], $1, $3 }
- | ID LPAREN RPAREN { [], $1, [] }
- | IdList ASSIGN ID LPAREN IdList RPAREN { $1, $3, $5 }
- | IdList ASSIGN ID LPAREN RPAREN { $1, $3, [] }
-
-IdList: ID { [$1] }
- | ID COMMA IdList { $1 :: $3 }
-
-Expression:
- AtomicExpr { $1 }
- | NOT Expression { Not($2) }
- | Expression PLUS Expression { Binary(Operator.Plus, $1, $3) }
- | Expression MINUS Expression { Binary(Operator.Minus, $1, $3) }
- | Expression STAR Expression { Binary(Operator.Times, $1, $3) }
- | Expression EQ Expression { Binary(Operator.Eq, $1, $3) }
- | Expression NEQ Expression { Binary(Operator.Neq, $1, $3) }
- | Expression LESS Expression { Binary(Operator.Less, $1, $3) }
- | Expression ATMOST Expression { Binary(Operator.AtMost, $1, $3) }
- | Expression AND Expression { Binary(Operator.And, $1, $3) }
- | Expression OR Expression { Binary(Operator.Or, $1, $3) }
-
-AtomicExpr:
- INT32 { Constant($1) }
- | NULL { Null }
- | ID { Identifier(Var($1)) }
- | OLD LPAREN Expression RPAREN { Old($3) }
- | LPAREN Expression RPAREN { $2 }
- | FieldSelect { match $1 with e,f -> Select(e,f) }
-
-FieldSelect:
- AtomicExpr DOT ID { $1, IdToField $3 }
-
-ExprList:
- | Expression { [$1] }
- | Expression COMMA ExprList { $1::$3 }
-
-VarList:
- | ID ASSIGN { [Var($1)] }
- | ID COMMA VarList { Var($1)::$3 }
-
-StmtList:
- StmtListX { Block($1) }
-
-StmtListX:
- { [] }
- | Stmt StmtListX { $1::$2 }
-
-Stmt:
- ID ASSIGN Expression SEMI { Assign(Var($1), $3) }
- | ID ASSIGN NEW LPAREN Expression COMMA
- Expression RPAREN SEMI { Alloc(Var($1), $5, $7) }
- | FieldSelect ASSIGN Expression SEMI { match $1 with e,f -> Update(e, f, $3) }
- | IF Expression THEN StmtList ELSE StmtList END SEMI { IfStmt($2,$4,$6) }
- | WHILE Expression Invariants DO StmtList END SEMI { WhileStmt($2,$3,$5) }
- | CALL ID LPAREN RPAREN SEMI { CallStmt([],$2,[]) }
- | CALL ID LPAREN ExprList RPAREN SEMI { CallStmt([],$2,$4) }
- | CALL VarList ID LPAREN RPAREN SEMI { CallStmt($2,$3,[]) }
- | CALL VarList ID LPAREN ExprList RPAREN SEMI { CallStmt($2,$3,$5) }
- | ASSERT Expression SEMI { Assert($2) }
-
-Invariants:
- { [] }
- | INVARIANT Expression Invariants { $2::$3 }
+%{
+
+open Forro
+
+exception ParseError of string
+
+let StringsToVariables ss = [ for s in ss -> Var(s) ]
+
+let IdToField id =
+ match id with
+ | "head" -> Field.Head
+ | "tail" -> Field.Tail
+ | "valid" -> Field.Valid
+ | _ -> raise (ParseError ("illegal field selector: '" + id + "' (legal selectors are 'head', 'tail', and 'valid')"))
+
+%}
+
+// The start token becomes a parser function in the compiled code:
+%start start
+
+// These are the terminal tokens of the grammar along with the types of
+// the data carried by each token:
+%token <string> ID
+%token <System.Int32> INT32
+%token NULL
+%token DOT
+%token NOT
+%token STAR
+%token PLUS MINUS
+%token EQ NEQ LESS ATMOST
+%token AND OR
+%token OLD LPAREN RPAREN LCURLY RCURLY SEMI COMMA ASSIGN
+%token PROCEDURE REQUIRES ENSURES DO END
+%token NEW IF THEN ELSE WHILE INVARIANT CALL ASSERT
+%token EOF
+
+// This is the type of the data produced by a successful reduction of the 'start'
+// symbol:
+%type < Forro.Program > start
+
+%%
+
+// These are the rules of the grammar along with the F# code of the
+// actions executed as rules are reduced. In this case the actions
+// produce data using F# data construction terms.
+start: Prog EOF { Prog(List.rev($1)) }
+
+Prog: Proc { [$1] }
+ | Prog Proc { $2 :: $1 }
+
+Proc:
+ PROCEDURE Signature ProcedureSpec
+ DO StmtList END SEMI
+ { match $2, $3 with (outs,id,ins), (req,ens) -> Proc(id, StringsToVariables ins, StringsToVariables outs, req, ens, $5) }
+
+ProcedureSpec:
+ REQUIRES Expression ENSURES Expression { $2, $4 }
+
+Signature:
+ ID LPAREN IdList RPAREN { [], $1, $3 }
+ | ID LPAREN RPAREN { [], $1, [] }
+ | IdList ASSIGN ID LPAREN IdList RPAREN { $1, $3, $5 }
+ | IdList ASSIGN ID LPAREN RPAREN { $1, $3, [] }
+
+IdList: ID { [$1] }
+ | ID COMMA IdList { $1 :: $3 }
+
+Expression:
+ AtomicExpr { $1 }
+ | NOT Expression { Not($2) }
+ | Expression PLUS Expression { Binary(Operator.Plus, $1, $3) }
+ | Expression MINUS Expression { Binary(Operator.Minus, $1, $3) }
+ | Expression STAR Expression { Binary(Operator.Times, $1, $3) }
+ | Expression EQ Expression { Binary(Operator.Eq, $1, $3) }
+ | Expression NEQ Expression { Binary(Operator.Neq, $1, $3) }
+ | Expression LESS Expression { Binary(Operator.Less, $1, $3) }
+ | Expression ATMOST Expression { Binary(Operator.AtMost, $1, $3) }
+ | Expression AND Expression { Binary(Operator.And, $1, $3) }
+ | Expression OR Expression { Binary(Operator.Or, $1, $3) }
+
+AtomicExpr:
+ INT32 { Constant($1) }
+ | NULL { Null }
+ | ID { Identifier(Var($1)) }
+ | OLD LPAREN Expression RPAREN { Old($3) }
+ | LPAREN Expression RPAREN { $2 }
+ | FieldSelect { match $1 with e,f -> Select(e,f) }
+
+FieldSelect:
+ AtomicExpr DOT ID { $1, IdToField $3 }
+
+ExprList:
+ | Expression { [$1] }
+ | Expression COMMA ExprList { $1::$3 }
+
+VarList:
+ | ID ASSIGN { [Var($1)] }
+ | ID COMMA VarList { Var($1)::$3 }
+
+StmtList:
+ StmtListX { Block($1) }
+
+StmtListX:
+ { [] }
+ | Stmt StmtListX { $1::$2 }
+
+Stmt:
+ ID ASSIGN Expression SEMI { Assign(Var($1), $3) }
+ | ID ASSIGN NEW LPAREN Expression COMMA
+ Expression RPAREN SEMI { Alloc(Var($1), $5, $7) }
+ | FieldSelect ASSIGN Expression SEMI { match $1 with e,f -> Update(e, f, $3) }
+ | IF Expression THEN StmtList ELSE StmtList END SEMI { IfStmt($2,$4,$6) }
+ | WHILE Expression Invariants DO StmtList END SEMI { WhileStmt($2,$3,$5) }
+ | CALL ID LPAREN RPAREN SEMI { CallStmt([],$2,[]) }
+ | CALL ID LPAREN ExprList RPAREN SEMI { CallStmt([],$2,$4) }
+ | CALL VarList ID LPAREN RPAREN SEMI { CallStmt($2,$3,[]) }
+ | CALL VarList ID LPAREN ExprList RPAREN SEMI { CallStmt($2,$3,$5) }
+ | ASSERT Expression SEMI { Assert($2) }
+
+Invariants:
+ { [] }
+ | INVARIANT Expression Invariants { $2::$3 }
diff --git a/Source/Forro/Printer.fs b/Source/Forro/Printer.fs
index 2a9eac84..d168e094 100644
--- a/Source/Forro/Printer.fs
+++ b/Source/Forro/Printer.fs
@@ -1,107 +1,107 @@
-module ForroPrinter
-
-open System
-open Forro
-
-let PrintField f =
- printf "."
- match f with
- | Head -> printf "head"
- | Tail -> printf "tail"
- | Valid -> printf "valid"
-
-let PrintOp op =
- printf " "
- match op with
- | Eq -> printf "=="
- | Neq -> printf "!="
- | Plus -> printf "+"
- | Minus -> printf "-"
- | Times -> printf "*"
- | Less -> printf "<"
- | AtMost -> printf "<="
- | And -> printf "and"
- | Or -> printf "or"
- printf " "
-
-let rec PrintExpr e outermost =
- match e with
- | Constant(x) -> printf "%i" x
- | Null -> printf "null"
- | Identifier(Var(x)) -> printf "%s" x
- | Not(e) -> printf "not(" ; PrintExpr e true ; printf ")"
- | Binary(op,a,b) ->
- if outermost then () else printf "("
- PrintExpr a false ; PrintOp op ; PrintExpr b false
- if outermost then () else printf ")"
- | Select(e,f) -> PrintExpr e false ; PrintField f
- | Old(e) -> printf "old(" ; PrintExpr e true ; printf ")"
-
-let rec Indent n =
- if n = 0 then () else printf " " ; Indent (n-1)
-
-let rec PrintStmt indent s =
- Indent indent
- let ind = indent + 2
- match s with
- | Assign(Var(x), e) -> printf "%s" x ; printf " := " ; PrintExpr e true
- | Update(obj,f,rhs) -> PrintExpr obj false ; PrintField f ; printf " := " ; PrintExpr rhs true
- | Alloc(Var(x),hd,tl) -> printf "%s" x ; printf " := new (" ; PrintExpr hd false ; printf ", " ; PrintExpr tl false ; printf ")"
- | IfStmt(guard,thn,els) ->
- printf "if " ; PrintExpr guard true ; printfn " then"
- PrintStmtList ind thn
- Indent indent ; printfn "else"
- PrintStmtList ind els
- Indent indent ; printf "end"
- | WhileStmt(guard,invs,body) ->
- printf "while " ; PrintExpr guard true ; printfn ""
- List.iter (fun inv -> Indent ind ; printf "invariant " ; PrintExpr inv true ; printfn "") invs
- Indent indent ; printfn "do"
- PrintStmtList ind body
- Indent indent ; printf "end"
- | CallStmt(outs,id,ins) ->
- printf "call "
- if outs.IsEmpty then () else
- ignore (List.fold (fun sep v -> printf "%s%s" sep (VarName v) ; ", ") "" outs) ; printf " :="
- printf " %s" id
- printf "("
- ignore (List.fold (fun sep e -> printf "%s" sep ; PrintExpr e false ; ", ") "" ins)
- printf ")"
- | Assert(e) ->
- printf "assert " ; PrintExpr e true
- printfn ";"
-
-and PrintStmtList indent slist =
- match slist with
- | Block(ss) -> List.iter (fun s -> PrintStmt indent s) ss
-
-let PrintProc p =
- match p with
- | Proc(name, ins, outs, req, ens, body) ->
- // signature
- printf "procedure "
- if outs.IsEmpty then () else
- ignore (List.fold (fun sep v -> printf "%s%s" sep (VarName v) ; ", ") "" outs) ; printf " :="
- printf " %s(" name
- ignore (List.fold (fun sep v -> printf "%s%s" sep (VarName v) ; ", ") "" ins)
- printfn ")"
- // specification
- printf " requires "
- PrintExpr req true
- printfn ""
- printf " ensures "
- PrintExpr ens true
- printfn ""
- // body
- printfn "do"
- PrintStmtList 2 body
- printfn "end;"
-
-let rec PrintProcs ps =
- match ps with
- | [] -> ()
- | p::rest -> PrintProc p ; PrintProcs rest
-
-let Print prog =
- match prog with
- | Prog(procs) -> PrintProcs procs
+module ForroPrinter
+
+open System
+open Forro
+
+let PrintField f =
+ printf "."
+ match f with
+ | Head -> printf "head"
+ | Tail -> printf "tail"
+ | Valid -> printf "valid"
+
+let PrintOp op =
+ printf " "
+ match op with
+ | Eq -> printf "=="
+ | Neq -> printf "!="
+ | Plus -> printf "+"
+ | Minus -> printf "-"
+ | Times -> printf "*"
+ | Less -> printf "<"
+ | AtMost -> printf "<="
+ | And -> printf "and"
+ | Or -> printf "or"
+ printf " "
+
+let rec PrintExpr e outermost =
+ match e with
+ | Constant(x) -> printf "%i" x
+ | Null -> printf "null"
+ | Identifier(Var(x)) -> printf "%s" x
+ | Not(e) -> printf "not(" ; PrintExpr e true ; printf ")"
+ | Binary(op,a,b) ->
+ if outermost then () else printf "("
+ PrintExpr a false ; PrintOp op ; PrintExpr b false
+ if outermost then () else printf ")"
+ | Select(e,f) -> PrintExpr e false ; PrintField f
+ | Old(e) -> printf "old(" ; PrintExpr e true ; printf ")"
+
+let rec Indent n =
+ if n = 0 then () else printf " " ; Indent (n-1)
+
+let rec PrintStmt indent s =
+ Indent indent
+ let ind = indent + 2
+ match s with
+ | Assign(Var(x), e) -> printf "%s" x ; printf " := " ; PrintExpr e true
+ | Update(obj,f,rhs) -> PrintExpr obj false ; PrintField f ; printf " := " ; PrintExpr rhs true
+ | Alloc(Var(x),hd,tl) -> printf "%s" x ; printf " := new (" ; PrintExpr hd false ; printf ", " ; PrintExpr tl false ; printf ")"
+ | IfStmt(guard,thn,els) ->
+ printf "if " ; PrintExpr guard true ; printfn " then"
+ PrintStmtList ind thn
+ Indent indent ; printfn "else"
+ PrintStmtList ind els
+ Indent indent ; printf "end"
+ | WhileStmt(guard,invs,body) ->
+ printf "while " ; PrintExpr guard true ; printfn ""
+ List.iter (fun inv -> Indent ind ; printf "invariant " ; PrintExpr inv true ; printfn "") invs
+ Indent indent ; printfn "do"
+ PrintStmtList ind body
+ Indent indent ; printf "end"
+ | CallStmt(outs,id,ins) ->
+ printf "call "
+ if outs.IsEmpty then () else
+ ignore (List.fold (fun sep v -> printf "%s%s" sep (VarName v) ; ", ") "" outs) ; printf " :="
+ printf " %s" id
+ printf "("
+ ignore (List.fold (fun sep e -> printf "%s" sep ; PrintExpr e false ; ", ") "" ins)
+ printf ")"
+ | Assert(e) ->
+ printf "assert " ; PrintExpr e true
+ printfn ";"
+
+and PrintStmtList indent slist =
+ match slist with
+ | Block(ss) -> List.iter (fun s -> PrintStmt indent s) ss
+
+let PrintProc p =
+ match p with
+ | Proc(name, ins, outs, req, ens, body) ->
+ // signature
+ printf "procedure "
+ if outs.IsEmpty then () else
+ ignore (List.fold (fun sep v -> printf "%s%s" sep (VarName v) ; ", ") "" outs) ; printf " :="
+ printf " %s(" name
+ ignore (List.fold (fun sep v -> printf "%s%s" sep (VarName v) ; ", ") "" ins)
+ printfn ")"
+ // specification
+ printf " requires "
+ PrintExpr req true
+ printfn ""
+ printf " ensures "
+ PrintExpr ens true
+ printfn ""
+ // body
+ printfn "do"
+ PrintStmtList 2 body
+ printfn "end;"
+
+let rec PrintProcs ps =
+ match ps with
+ | [] -> ()
+ | p::rest -> PrintProc p ; PrintProcs rest
+
+let Print prog =
+ match prog with
+ | Prog(procs) -> PrintProcs procs
diff --git a/Source/Forro/Resolver.fs b/Source/Forro/Resolver.fs
index f227a5ca..9209f640 100644
--- a/Source/Forro/Resolver.fs
+++ b/Source/Forro/Resolver.fs
@@ -1,123 +1,123 @@
-module Resolver
-
-open System
-open Forro
-
-exception ResolutionError of string
-
-let ResolutionError(s: string) =
- raise (ResolutionError s)
-
-type VarKind = InParam | OutParam | Local
-
-type Context(procedures: Collections.Generic.IDictionary<string,Procedure>) =
- let mutable locals = null
- let mutable ProcName = ""
- member c.Procedures = procedures
- member c.StartNewProcedure procName =
- ProcName <- procName
- locals <- new Collections.Generic.Dictionary<string,VarKind>()
- member c.AddLocal v kind =
- let name = VarName v
- if locals.ContainsKey name then ResolutionError ("duplicate variable '" + name + "' in procedure '" + ProcName + "'") else ()
- locals.Add(name, kind)
- member c.HasLocal v =
- locals.ContainsKey (VarName v)
- member c.IncludeAssignmentTarget v =
- let name = VarName v
- if locals.ContainsKey name then
- let kind = locals.Item name
- if kind = VarKind.InParam then ResolutionError ("variable '"+ name + "' is an in-parameter, which cannot be used as an assignment target") else ()
- else
- locals.Add(name, VarKind.Local)
- member v.GetLocals = locals
-
-let rec ResolveExpr (ctx: Context) expr twoState specContext =
- match expr with
- | Constant(x) -> ()
- | Null -> ()
- | Identifier(v) ->
- if ctx.HasLocal v then () else ResolutionError ("undefined variable: " + VarName v)
- | Not(e) -> ResolveExpr ctx e twoState specContext
- | Binary(op,a,b) ->
- ResolveExpr ctx a twoState specContext
- ResolveExpr ctx b twoState specContext
- | Select(e,f) ->
- ResolveExpr ctx e twoState specContext
- match f with
- | Valid -> if specContext then () else ResolutionError "valid can only be used in specification contexts"
- | _ -> ()
- | Old(e) ->
- if twoState then () else ResolutionError "old expressions can only be used in two-state contexts"
- ResolveExpr ctx e twoState specContext
-
-let rec ResolveStmt ctx s =
- match s with
- | Assign(v, e) ->
- ResolveExpr ctx e false false
- ctx.IncludeAssignmentTarget v
- | Update(obj,f,rhs) ->
- ResolveExpr ctx obj false false
- match f with
- | Valid -> ResolutionError "valid can only be used in specification contexts (in particular, it cannot be assigned to)"
- | _ -> ()
- ResolveExpr ctx rhs false false
- | Alloc(v,hd,tl) ->
- ResolveExpr ctx hd false false
- ResolveExpr ctx tl false false
- ctx.IncludeAssignmentTarget v
- | IfStmt(guard,thn,els) ->
- ResolveExpr ctx guard false false
- ResolveStmtList ctx thn
- ResolveStmtList ctx els
- | WhileStmt(guard,invs,body) ->
- ResolveExpr ctx guard false false
- List.iter (fun inv -> ResolveExpr ctx inv true true) invs
- ResolveStmtList ctx body
- | CallStmt(outs,name,ins) ->
- if ctx.Procedures.ContainsKey name then () else ResolutionError ("call to undefined procedure: " + name)
- match ctx.Procedures.Item name with
- | Proc(_,fIns,fOuts,_,_,_) ->
- if fIns.Length = ins.Length then () else ResolutionError ("call to " + name + " has wrong number of in-parameters (got " + ins.Length.ToString() + ", expected " + fIns.Length.ToString() + ")")
- if fOuts.Length = outs.Length then () else ResolutionError ("call to " + name + " has wrong number of out-parameters (got " + outs.Length.ToString() + ", expected " + fOuts.Length.ToString() + ")")
- List.iter (fun e -> ResolveExpr ctx e false false) ins
- let outnames = new Collections.Generic.Dictionary<string,Variable>()
- List.iter (fun v ->
- ctx.IncludeAssignmentTarget v
- let name = VarName v
- if outnames.ContainsKey name then ResolutionError ("an actual out-parameter is allowed only once for a call: " + name) else ()
- outnames.Add(name, v)
- ) outs
- | Assert(e) ->
- ResolveExpr ctx e true true
-
-and ResolveStmtList ctx slist =
- match slist with
- | Block(ss) -> List.iter (fun s -> ResolveStmt ctx s) ss
-
-let ProcedureName p =
- match p with Proc(id,_,_,_,_,_) -> id
-
-let ResolveProc (ctx: Context) p =
- match p with
- | Proc(name, ins, outs, req, ens, body) ->
- // look up 'name' in ctx.Procedures, report an error if it is not 'p'
- let q = ctx.Procedures.Item name
- if p <> q then ResolutionError ("duplicate procedure: " + name) else ()
- ctx.StartNewProcedure name
- // look for duplicates in ins+outs
- List.iter (fun v -> ctx.AddLocal v VarKind.InParam) ins
- List.iter (fun v -> ctx.AddLocal v VarKind.OutParam) outs
- // resolve specification
- ResolveExpr ctx req false true
- ResolveExpr ctx ens true true
- // resolve body
- ResolveStmtList ctx body
- ctx.GetLocals
-
-let Resolve prog =
- match prog with
- | Prog(procs) ->
- let procedures = dict [ for p in procs -> ProcedureName p, p ]
- let ctx = Context(procedures)
- List.map (fun p -> p, ResolveProc ctx p) procs
+module Resolver
+
+open System
+open Forro
+
+exception ResolutionError of string
+
+let ResolutionError(s: string) =
+ raise (ResolutionError s)
+
+type VarKind = InParam | OutParam | Local
+
+type Context(procedures: Collections.Generic.IDictionary<string,Procedure>) =
+ let mutable locals = null
+ let mutable ProcName = ""
+ member c.Procedures = procedures
+ member c.StartNewProcedure procName =
+ ProcName <- procName
+ locals <- new Collections.Generic.Dictionary<string,VarKind>()
+ member c.AddLocal v kind =
+ let name = VarName v
+ if locals.ContainsKey name then ResolutionError ("duplicate variable '" + name + "' in procedure '" + ProcName + "'") else ()
+ locals.Add(name, kind)
+ member c.HasLocal v =
+ locals.ContainsKey (VarName v)
+ member c.IncludeAssignmentTarget v =
+ let name = VarName v
+ if locals.ContainsKey name then
+ let kind = locals.Item name
+ if kind = VarKind.InParam then ResolutionError ("variable '"+ name + "' is an in-parameter, which cannot be used as an assignment target") else ()
+ else
+ locals.Add(name, VarKind.Local)
+ member v.GetLocals = locals
+
+let rec ResolveExpr (ctx: Context) expr twoState specContext =
+ match expr with
+ | Constant(x) -> ()
+ | Null -> ()
+ | Identifier(v) ->
+ if ctx.HasLocal v then () else ResolutionError ("undefined variable: " + VarName v)
+ | Not(e) -> ResolveExpr ctx e twoState specContext
+ | Binary(op,a,b) ->
+ ResolveExpr ctx a twoState specContext
+ ResolveExpr ctx b twoState specContext
+ | Select(e,f) ->
+ ResolveExpr ctx e twoState specContext
+ match f with
+ | Valid -> if specContext then () else ResolutionError "valid can only be used in specification contexts"
+ | _ -> ()
+ | Old(e) ->
+ if twoState then () else ResolutionError "old expressions can only be used in two-state contexts"
+ ResolveExpr ctx e twoState specContext
+
+let rec ResolveStmt ctx s =
+ match s with
+ | Assign(v, e) ->
+ ResolveExpr ctx e false false
+ ctx.IncludeAssignmentTarget v
+ | Update(obj,f,rhs) ->
+ ResolveExpr ctx obj false false
+ match f with
+ | Valid -> ResolutionError "valid can only be used in specification contexts (in particular, it cannot be assigned to)"
+ | _ -> ()
+ ResolveExpr ctx rhs false false
+ | Alloc(v,hd,tl) ->
+ ResolveExpr ctx hd false false
+ ResolveExpr ctx tl false false
+ ctx.IncludeAssignmentTarget v
+ | IfStmt(guard,thn,els) ->
+ ResolveExpr ctx guard false false
+ ResolveStmtList ctx thn
+ ResolveStmtList ctx els
+ | WhileStmt(guard,invs,body) ->
+ ResolveExpr ctx guard false false
+ List.iter (fun inv -> ResolveExpr ctx inv true true) invs
+ ResolveStmtList ctx body
+ | CallStmt(outs,name,ins) ->
+ if ctx.Procedures.ContainsKey name then () else ResolutionError ("call to undefined procedure: " + name)
+ match ctx.Procedures.Item name with
+ | Proc(_,fIns,fOuts,_,_,_) ->
+ if fIns.Length = ins.Length then () else ResolutionError ("call to " + name + " has wrong number of in-parameters (got " + ins.Length.ToString() + ", expected " + fIns.Length.ToString() + ")")
+ if fOuts.Length = outs.Length then () else ResolutionError ("call to " + name + " has wrong number of out-parameters (got " + outs.Length.ToString() + ", expected " + fOuts.Length.ToString() + ")")
+ List.iter (fun e -> ResolveExpr ctx e false false) ins
+ let outnames = new Collections.Generic.Dictionary<string,Variable>()
+ List.iter (fun v ->
+ ctx.IncludeAssignmentTarget v
+ let name = VarName v
+ if outnames.ContainsKey name then ResolutionError ("an actual out-parameter is allowed only once for a call: " + name) else ()
+ outnames.Add(name, v)
+ ) outs
+ | Assert(e) ->
+ ResolveExpr ctx e true true
+
+and ResolveStmtList ctx slist =
+ match slist with
+ | Block(ss) -> List.iter (fun s -> ResolveStmt ctx s) ss
+
+let ProcedureName p =
+ match p with Proc(id,_,_,_,_,_) -> id
+
+let ResolveProc (ctx: Context) p =
+ match p with
+ | Proc(name, ins, outs, req, ens, body) ->
+ // look up 'name' in ctx.Procedures, report an error if it is not 'p'
+ let q = ctx.Procedures.Item name
+ if p <> q then ResolutionError ("duplicate procedure: " + name) else ()
+ ctx.StartNewProcedure name
+ // look for duplicates in ins+outs
+ List.iter (fun v -> ctx.AddLocal v VarKind.InParam) ins
+ List.iter (fun v -> ctx.AddLocal v VarKind.OutParam) outs
+ // resolve specification
+ ResolveExpr ctx req false true
+ ResolveExpr ctx ens true true
+ // resolve body
+ ResolveStmtList ctx body
+ ctx.GetLocals
+
+let Resolve prog =
+ match prog with
+ | Prog(procs) ->
+ let procedures = dict [ for p in procs -> ProcedureName p, p ]
+ let ctx = Context(procedures)
+ List.map (fun p -> p, ResolveProc ctx p) procs
diff --git a/Source/Forro/Translator.fs b/Source/Forro/Translator.fs
index 4e7be216..db771c96 100644
--- a/Source/Forro/Translator.fs
+++ b/Source/Forro/Translator.fs
@@ -1,217 +1,217 @@
-module Translator
-
-open Forro
-open BoogieAst
-open Resolver
-open System.Collections.Generic
-
-let rec Append a b =
- match a with
- | [] -> b
- | hd::tl -> hd::(Append tl b)
-
-let rec Flatten a =
- match a with
- | [] -> []
- | list::rest -> Append list (Flatten rest)
-
-// ---------- Prelude ----------
-
-let Prelude =
- @"// Forro
-
-var $head: [int]int; // int -> int
-var $tail: [int]int;
-var $valid: [int]bool; // array int of bool
-
-const null: int;
-
-function GoodState([int]int, [int]int, [int]bool): bool;
-
-axiom (forall hd, tl: [int]int, valid: [int]bool ::
- { GoodState(hd, tl, valid) }
- GoodState(hd, tl, valid) ==> !valid[null]);
-"
-
-// ---------- Translate Expressions ----------
-
-let TrField f =
- match f with
- | Head -> "$head"
- | Tail -> "$tail"
- | Valid -> "$valid"
-
-let AllFields = ["$head" ; "$tail" ; "$valid"]
-
-let MkPred term =
- match term with
- | BToTerm(p) -> p
- | _ -> BToPred(term)
-
-let MkTerm pred =
- match pred with
- | BToPred(e) -> e
- | _ -> BToTerm(pred)
-
-let rec TrExpr expr =
- match expr with
- | Constant(x) -> BConstant x
- | Null -> BNull
- | Identifier(Var(x)) -> BIdentifier(x)
- | Not(e) -> BNot(TrExpr e)
- | Binary(op,a,b) ->
- let a = TrExpr a
- let b = TrExpr b
- match op with
- | Eq -> MkTerm(BBinary(BEq,a,b))
- | Neq -> MkTerm(BBinary(BNeq,a,b))
- | Plus -> BBinary(BPlus,a,b)
- | Minus -> BBinary(BMinus,a,b)
- | Times -> BBinary(BTimes,a,b)
- | Less -> MkTerm(BBinary(BLess,a,b))
- | AtMost -> MkTerm(BBinary(BAtMost,a,b))
- | And -> MkTerm(BBinary(BAnd, MkPred a, MkPred b))
- | Or -> MkTerm(BBinary(BOr, MkPred a, MkPred b))
- | Select(e,f) ->
- let r = BSelect(TrField f, TrExpr e)
- if f = Field.Valid then MkTerm(r) else r
- | Old(e) -> BOld(TrExpr e)
-
-let rec ListToConjunction list =
- match list with
- | [] -> BTrue
- | [P] -> P
- | hd::tl -> BBinary(BAnd, hd, ListToConjunction tl)
-
-let rec DefL expr =
- match expr with
- | Constant(x) -> []
- | Null -> []
- | Identifier(Var(x)) -> []
- | Not(e) -> DefL e
- | Binary(op,a,b) ->
- match op with
- | And -> BBinary(BOr, BNot(MkPred (TrExpr a)), Def b) :: (DefL a) // (Def a) && ((TrExpr a) ==> (Def b))
- | Or -> BBinary(BOr, MkPred (TrExpr a), Def b) :: (DefL a) // (Def a) && (!(TrExpr a) ==> (Def b))
- | _ -> Append (DefL b) (DefL a)
- | Select(e,f) ->
- let def = DefL e
- if f = Field.Valid then def // it is always okay to ask about .valid
- else BSelect("$valid", TrExpr e) :: def
- | Old(e) -> List.map BOld (DefL e)
-
-and Def expr =
- ListToConjunction (List.rev (DefL expr))
-
-let AssumeGoodState =
- BAssume (BFunc("GoodState", List.map BIdentifier AllFields))
-
-// ---------- Translate Statements ----------
-
-type LocalBookkeeping = LB of int * BVarDecl list
-
-let FreshLocal locals =
- match locals with
- | LB(n, vars) ->
- let name = "nw$" + n.ToString()
- (BIdentifier(name), name, LB(n+1, BVar(name, BInt)::vars))
-
-let rec TrStmt stmt locals =
- match stmt with
- | Assign(v,e) ->
- let s = [ BAssert (Def e) ;
- BAssign(VarName v, TrExpr e) ]
- (s, locals)
- | Update(obj,f,rhs) ->
- let o = TrExpr obj
- let s = [ BAssert(Def obj) ; BAssert (Def rhs) ;
- BAssert(BSelect("$valid", o)) ;
- BUpdate(TrField f, o, if f = Field.Valid then MkPred(TrExpr rhs) else TrExpr rhs) ;
- AssumeGoodState ]
- (s, locals)
- | Alloc(v,hd,tl) ->
- let nw, name, locals = FreshLocal locals
- let s = [ BAssert (Def hd) ; BAssert (Def tl) ;
- BHavoc [name] ;
- BAssume(BNot(BSelect("$valid", nw))) ;
- BAssume(BBinary(BEq, BSelect("$head", nw), TrExpr hd)) ;
- BAssume(BBinary(BEq, BSelect("$tail", nw), TrExpr tl)) ;
- BUpdate("$valid", nw, BTrue) ;
- AssumeGoodState ;
- BAssign(VarName v, nw) ]
- (s, locals)
- | IfStmt(guard,thn,els) ->
- let check = BAssert(Def guard)
- let thn, locals = TrStmtList thn locals
- let els, locals = TrStmtList els locals
- let s = BIfStmt(MkPred (TrExpr guard), thn, els)
- ([check ; s], locals)
- | WhileStmt(guard,invs,body) ->
- let ii = [Def guard]
- let ii = List.fold (fun ii -> fun inv -> (MkPred (TrExpr inv))::(Def inv)::ii) ii invs
- let s, locals = TrStmtList body locals
- match s with
- | BBlock(slist) ->
- ([BWhileStmt(MkPred (TrExpr guard), List.rev ii, BBlock(AssumeGoodState::slist)) ; AssumeGoodState], locals)
- | CallStmt(outs,id,ins) ->
- let check = List.map (fun e -> BAssert (Def e)) ins
- let ins = List.map (fun e -> TrExpr e) ins
- let outs = List.map (fun p -> VarName p) outs
- let s = BCallStmt(outs, id + "#Proc", ins)
- (Append check [s ; AssumeGoodState ], locals)
- | Assert(e) ->
- ([ BAssert (Def e) ; BAssert (MkPred (TrExpr e)) ], locals)
-
-and TrStmtList slist locals =
- match slist with
- | Block([]) -> (BBlock [], locals)
- | Block(s::rest) ->
- let s,locals = TrStmt s locals
- let rest,locals = TrStmtList (Block rest) locals
- match rest with
- | BBlock(slist) -> (BBlock(Append s slist), locals)
-
-// ---------- Translate Procedure Body ----------
-
-let TrSignature ins outs =
- let bIns = List.map (fun v -> BVar(VarName v, BInt)) ins
- let bOuts = List.map (fun v -> BVar(VarName v, BInt)) outs
- (bIns, bOuts)
-
-let LocalDecls (vars: Dictionary<string,VarKind>) =
- Flatten [ for kv in vars -> if kv.Value = VarKind.Local then [BVar(kv.Key, BInt)] else [] ]
-
-let TrProc proc vars =
- match proc with
- | Proc(id, ins, outs, req, ens, body) ->
- let bIns, bOuts = TrSignature ins outs
- let pre = MkPred (TrExpr req)
- let post = MkPred (TrExpr ens)
- let locals = LocalDecls vars
- let b, locals = TrStmtList body (LB(0,locals))
- match b, locals with
- | BBlock(slist), LB(n, vars) ->
- BProc(id + "#Proc", bIns, bOuts, pre, AllFields, post,
- List.rev vars, BBlock(AssumeGoodState::slist))
-
-// --------------------
-
-let TrSpec proc vars =
- match proc with
- | Proc(id, ins, outs, req, ens, body) ->
- let bIns, bOuts = TrSignature ins outs
- let b = [ AssumeGoodState ;
- BAssert (Def req) ; BAssume (MkPred (TrExpr req)) ;
- BHavoc AllFields ; AssumeGoodState ;
- BAssert (Def ens) ]
- BProc(id + "#WellFormedSpec", bIns, bOuts, BTrue, AllFields, BTrue, [], BBlock(b))
-
-let TrProcedure rproc =
- match rproc with
- | proc, (vars: Dictionary<string,VarKind>) ->
- let name = ProcedureName proc
- (TrSpec proc vars, TrProc proc vars)
-
-let Translate (rprog: (Procedure * Dictionary<string,VarKind>) list) =
- let procs = List.fold (fun list -> fun (p,q) -> p::q::list) [] (List.map TrProcedure rprog)
- BProg(Prelude, procs)
+module Translator
+
+open Forro
+open BoogieAst
+open Resolver
+open System.Collections.Generic
+
+let rec Append a b =
+ match a with
+ | [] -> b
+ | hd::tl -> hd::(Append tl b)
+
+let rec Flatten a =
+ match a with
+ | [] -> []
+ | list::rest -> Append list (Flatten rest)
+
+// ---------- Prelude ----------
+
+let Prelude =
+ @"// Forro
+
+var $head: [int]int; // int -> int
+var $tail: [int]int;
+var $valid: [int]bool; // array int of bool
+
+const null: int;
+
+function GoodState([int]int, [int]int, [int]bool): bool;
+
+axiom (forall hd, tl: [int]int, valid: [int]bool ::
+ { GoodState(hd, tl, valid) }
+ GoodState(hd, tl, valid) ==> !valid[null]);
+"
+
+// ---------- Translate Expressions ----------
+
+let TrField f =
+ match f with
+ | Head -> "$head"
+ | Tail -> "$tail"
+ | Valid -> "$valid"
+
+let AllFields = ["$head" ; "$tail" ; "$valid"]
+
+let MkPred term =
+ match term with
+ | BToTerm(p) -> p
+ | _ -> BToPred(term)
+
+let MkTerm pred =
+ match pred with
+ | BToPred(e) -> e
+ | _ -> BToTerm(pred)
+
+let rec TrExpr expr =
+ match expr with
+ | Constant(x) -> BConstant x
+ | Null -> BNull
+ | Identifier(Var(x)) -> BIdentifier(x)
+ | Not(e) -> BNot(TrExpr e)
+ | Binary(op,a,b) ->
+ let a = TrExpr a
+ let b = TrExpr b
+ match op with
+ | Eq -> MkTerm(BBinary(BEq,a,b))
+ | Neq -> MkTerm(BBinary(BNeq,a,b))
+ | Plus -> BBinary(BPlus,a,b)
+ | Minus -> BBinary(BMinus,a,b)
+ | Times -> BBinary(BTimes,a,b)
+ | Less -> MkTerm(BBinary(BLess,a,b))
+ | AtMost -> MkTerm(BBinary(BAtMost,a,b))
+ | And -> MkTerm(BBinary(BAnd, MkPred a, MkPred b))
+ | Or -> MkTerm(BBinary(BOr, MkPred a, MkPred b))
+ | Select(e,f) ->
+ let r = BSelect(TrField f, TrExpr e)
+ if f = Field.Valid then MkTerm(r) else r
+ | Old(e) -> BOld(TrExpr e)
+
+let rec ListToConjunction list =
+ match list with
+ | [] -> BTrue
+ | [P] -> P
+ | hd::tl -> BBinary(BAnd, hd, ListToConjunction tl)
+
+let rec DefL expr =
+ match expr with
+ | Constant(x) -> []
+ | Null -> []
+ | Identifier(Var(x)) -> []
+ | Not(e) -> DefL e
+ | Binary(op,a,b) ->
+ match op with
+ | And -> BBinary(BOr, BNot(MkPred (TrExpr a)), Def b) :: (DefL a) // (Def a) && ((TrExpr a) ==> (Def b))
+ | Or -> BBinary(BOr, MkPred (TrExpr a), Def b) :: (DefL a) // (Def a) && (!(TrExpr a) ==> (Def b))
+ | _ -> Append (DefL b) (DefL a)
+ | Select(e,f) ->
+ let def = DefL e
+ if f = Field.Valid then def // it is always okay to ask about .valid
+ else BSelect("$valid", TrExpr e) :: def
+ | Old(e) -> List.map BOld (DefL e)
+
+and Def expr =
+ ListToConjunction (List.rev (DefL expr))
+
+let AssumeGoodState =
+ BAssume (BFunc("GoodState", List.map BIdentifier AllFields))
+
+// ---------- Translate Statements ----------
+
+type LocalBookkeeping = LB of int * BVarDecl list
+
+let FreshLocal locals =
+ match locals with
+ | LB(n, vars) ->
+ let name = "nw$" + n.ToString()
+ (BIdentifier(name), name, LB(n+1, BVar(name, BInt)::vars))
+
+let rec TrStmt stmt locals =
+ match stmt with
+ | Assign(v,e) ->
+ let s = [ BAssert (Def e) ;
+ BAssign(VarName v, TrExpr e) ]
+ (s, locals)
+ | Update(obj,f,rhs) ->
+ let o = TrExpr obj
+ let s = [ BAssert(Def obj) ; BAssert (Def rhs) ;
+ BAssert(BSelect("$valid", o)) ;
+ BUpdate(TrField f, o, if f = Field.Valid then MkPred(TrExpr rhs) else TrExpr rhs) ;
+ AssumeGoodState ]
+ (s, locals)
+ | Alloc(v,hd,tl) ->
+ let nw, name, locals = FreshLocal locals
+ let s = [ BAssert (Def hd) ; BAssert (Def tl) ;
+ BHavoc [name] ;
+ BAssume(BNot(BSelect("$valid", nw))) ;
+ BAssume(BBinary(BEq, BSelect("$head", nw), TrExpr hd)) ;
+ BAssume(BBinary(BEq, BSelect("$tail", nw), TrExpr tl)) ;
+ BUpdate("$valid", nw, BTrue) ;
+ AssumeGoodState ;
+ BAssign(VarName v, nw) ]
+ (s, locals)
+ | IfStmt(guard,thn,els) ->
+ let check = BAssert(Def guard)
+ let thn, locals = TrStmtList thn locals
+ let els, locals = TrStmtList els locals
+ let s = BIfStmt(MkPred (TrExpr guard), thn, els)
+ ([check ; s], locals)
+ | WhileStmt(guard,invs,body) ->
+ let ii = [Def guard]
+ let ii = List.fold (fun ii -> fun inv -> (MkPred (TrExpr inv))::(Def inv)::ii) ii invs
+ let s, locals = TrStmtList body locals
+ match s with
+ | BBlock(slist) ->
+ ([BWhileStmt(MkPred (TrExpr guard), List.rev ii, BBlock(AssumeGoodState::slist)) ; AssumeGoodState], locals)
+ | CallStmt(outs,id,ins) ->
+ let check = List.map (fun e -> BAssert (Def e)) ins
+ let ins = List.map (fun e -> TrExpr e) ins
+ let outs = List.map (fun p -> VarName p) outs
+ let s = BCallStmt(outs, id + "#Proc", ins)
+ (Append check [s ; AssumeGoodState ], locals)
+ | Assert(e) ->
+ ([ BAssert (Def e) ; BAssert (MkPred (TrExpr e)) ], locals)
+
+and TrStmtList slist locals =
+ match slist with
+ | Block([]) -> (BBlock [], locals)
+ | Block(s::rest) ->
+ let s,locals = TrStmt s locals
+ let rest,locals = TrStmtList (Block rest) locals
+ match rest with
+ | BBlock(slist) -> (BBlock(Append s slist), locals)
+
+// ---------- Translate Procedure Body ----------
+
+let TrSignature ins outs =
+ let bIns = List.map (fun v -> BVar(VarName v, BInt)) ins
+ let bOuts = List.map (fun v -> BVar(VarName v, BInt)) outs
+ (bIns, bOuts)
+
+let LocalDecls (vars: Dictionary<string,VarKind>) =
+ Flatten [ for kv in vars -> if kv.Value = VarKind.Local then [BVar(kv.Key, BInt)] else [] ]
+
+let TrProc proc vars =
+ match proc with
+ | Proc(id, ins, outs, req, ens, body) ->
+ let bIns, bOuts = TrSignature ins outs
+ let pre = MkPred (TrExpr req)
+ let post = MkPred (TrExpr ens)
+ let locals = LocalDecls vars
+ let b, locals = TrStmtList body (LB(0,locals))
+ match b, locals with
+ | BBlock(slist), LB(n, vars) ->
+ BProc(id + "#Proc", bIns, bOuts, pre, AllFields, post,
+ List.rev vars, BBlock(AssumeGoodState::slist))
+
+// --------------------
+
+let TrSpec proc vars =
+ match proc with
+ | Proc(id, ins, outs, req, ens, body) ->
+ let bIns, bOuts = TrSignature ins outs
+ let b = [ AssumeGoodState ;
+ BAssert (Def req) ; BAssume (MkPred (TrExpr req)) ;
+ BHavoc AllFields ; AssumeGoodState ;
+ BAssert (Def ens) ]
+ BProc(id + "#WellFormedSpec", bIns, bOuts, BTrue, AllFields, BTrue, [], BBlock(b))
+
+let TrProcedure rproc =
+ match rproc with
+ | proc, (vars: Dictionary<string,VarKind>) ->
+ let name = ProcedureName proc
+ (TrSpec proc vars, TrProc proc vars)
+
+let Translate (rprog: (Procedure * Dictionary<string,VarKind>) list) =
+ let procs = List.fold (fun list -> fun (p,q) -> p::q::list) [] (List.map TrProcedure rprog)
+ BProg(Prelude, procs)
diff --git a/Source/Graph/Graph.cs b/Source/Graph/Graph.cs
index 8e5479e3..7f636200 100644
--- a/Source/Graph/Graph.cs
+++ b/Source/Graph/Graph.cs
@@ -1,1447 +1,1447 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Text; // for StringBuilder
-using System.Diagnostics.Contracts;
-namespace Microsoft.Boogie.GraphUtil {
-
- internal static class Util {
- private static string/*!*/ ListToString<T>(IEnumerable<T> xs) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("[");
- bool first = true;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (!first)
- sb.Append(", ");
- sb.Append(x.ToString());
- first = false;
- }
- sb.Append("]");
- return sb.ToString();
- }
- public static string/*!*/ MapToString<Node>(Dictionary<Node, List<Node>> d) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("{");
- bool first = true;
- foreach (KeyValuePair<Node, List<Node>> de in d) {
- if (!first)
- sb.Append(", ");
- Contract.Assert(!object.Equals(de.Key,default(Node)));
- sb.Append(de.Key.ToString());
- sb.Append("~>");
- sb.Append(ListToString(de.Value));
- first = false;
- }
- sb.Append("}");
- return sb.ToString();
- }
- }
-
- // own struct to represent possibly undefined values, because Mono does
- // not like arrays with element type T! or T?
- public struct Maybe<T> {
- private T Value;
- public bool IsSet; // initialised with false by the default ctor
- public T Val {
- get {
- Contract.Assume(IsSet);
- return Value;
- }
- set {
- Value = value;
- IsSet = true;
- }
- }
- public void UnSet() {
- IsSet = false;
- }
- }
-
- public class DomRelation<Node> {
- // doms maps (unique) node numbers to the node numbers of the immediate dominator
- // to use it on Nodes, one needs the two way mapping between nodes and their numbers.
- private int[] doms; // 0 is unused: means undefined
- // here are the two mappings
- private Maybe<Node>[] postOrderNumberToNode;
- private Dictionary<Node, int> nodeToPostOrderNumber;
- private int sourceNum; // (number for) root of the graph
- private Node source; // root of the graph
- private Graph<Node> graph;
- private Dictionary<Node, List<Node>> immediateDominatorMap;
-
- [NotDelayed]
- internal DomRelation(Graph<Node> g, Node source) {
- this.graph = g;
- // slot 0 not used: nodes are numbered from 1 to n so zero
- // can represent undefined.
- this.source = source;
- //:base();
- this.NewComputeDominators();
- }
- public Dictionary<Node, List<Node>> ImmediateDominatorMap {
- get {
- Contract.Assume(this.immediateDominatorMap != null);
- return this.immediateDominatorMap;
- }
- }
- public bool DominatedBy(Node dominee, Node dominator, List<Node> path = null) {
- Contract.Assume(this.nodeToPostOrderNumber != null);
- Contract.Assume(this.doms != null);
- int domineeNum = this.nodeToPostOrderNumber[dominee];
- int dominatorNum = this.nodeToPostOrderNumber[dominator];
- if (domineeNum == dominatorNum)
- return true;
- int currentNodeNum = this.doms[domineeNum];
- while (true) {
- if (currentNodeNum == dominatorNum)
- return true;
- if (currentNodeNum == this.sourceNum)
- return false;
- if (path != null)
- path.Add(postOrderNumberToNode[currentNodeNum].Val);
- currentNodeNum = this.doms[currentNodeNum];
- }
- }
- private Dictionary<Node, List<Node>> domMap = null;
- [Pure]
- public override string ToString() {
- Contract.Assume(this.doms != null);
- int[] localDoms = this.doms;
- Contract.Assume(this.postOrderNumberToNode != null);
- if (domMap == null) {
- domMap = new Dictionary<Node, List<Node>>();
- for (int i = 1; i < localDoms.Length; i++) { // 0 slot is not used
- int domineeNum = i;
- int currentNodeNum = domineeNum;
- List<Node> dominators = new List<Node>();
- while (currentNodeNum != this.sourceNum) {
- dominators.Add(this.postOrderNumberToNode[currentNodeNum].Val);
- currentNodeNum = this.doms[currentNodeNum];
- }
- dominators.Add(this.postOrderNumberToNode[this.sourceNum].Val);
- domMap.Add(this.postOrderNumberToNode[i].Val, dominators);
- }
- }
- StringBuilder sb = new StringBuilder();
- sb.Append("{");
- bool first = true;
- foreach (KeyValuePair<Node, List<Node>> de in domMap) {
- if (!first)
- sb.Append(", ");
- Contract.Assert(!object.Equals(de.Key, default(Node)));
- sb.Append(de.Key.ToString());
- sb.Append("~>");
- sb.Append(ListToString(de.Value));
- first = false;
- }
- sb.Append("}");
- return sb.ToString();
- }
- private void PrintIntArray(int[] xs) {
- Console.Write("[");
- for (int i = 0; i < xs.Length; i++) {
- if (0 < i)
- Console.Write(", ");
- Console.Write(xs[i]);
- }
- Console.WriteLine("]");
- }
- public void PrintList<T>(IEnumerable<T> xs) {
- Console.Write("[");
- int i = 0;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (0 < i)
- Console.Write(", ");
- Console.Write(x.ToString());
- i++;
- }
- Console.WriteLine("]");
- }
- public string/*!*/ ListToString<T>(IEnumerable<T> xs) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("[");
- bool first = true;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (!first)
- sb.Append(", ");
- sb.Append(x.ToString());
- first = false;
- }
- sb.Append("]");
- return sb.ToString();
- }
-
- // Keith D. Cooper, Timothy J. Harvey, Ken Kennedy, "A Simple, Fast Dominance Algorithm ", Software Practice and Experience, 2001.
- // http://citeseer.ist.psu.edu/cooper01simple.html
- private void NewComputeDominators() {
- int n = this.graph.Nodes.Count;
- this.postOrderNumberToNode = new Maybe<Node>[n + 1];
- this.nodeToPostOrderNumber = new Dictionary<Node, int>();
- //HashSet<Node> visited = new HashSet<Node>();
- //int currentNumber = 1;
- Contract.Assume(this.source != null);
- //this.PostOrderVisit(this.source, visited, ref currentNumber);
- this.PostOrderVisitIterative(this.source);
- this.sourceNum = this.nodeToPostOrderNumber[source];
- // for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); }
- this.doms = new int[n + 1]; // 0 is unused: means undefined
- Node start_node = this.source;
- this.doms[this.nodeToPostOrderNumber[start_node]] = this.nodeToPostOrderNumber[start_node];
- bool changed = true;
- // PrintIntArray(doms);
- while (changed) {
- changed = false;
- // for all nodes, b, in reverse postorder (except start_node)
- for (int nodeNum = n - 1; 1 <= nodeNum; nodeNum--) {
- Node b = this.postOrderNumberToNode[nodeNum].Val;
- IEnumerable<Node> predecessors = this.graph.Predecessors(b);
- // find a predecessor (i.e., a higher number) for which
- // the doms array has been set
- int new_idom = 0;
- int first_processed_predecessor = 0;
- #region new_idom <- number of first (processed) predecessor of b (pick one)
- foreach (Node p in predecessors) {
- if (this.doms[this.nodeToPostOrderNumber[p]] != 0) {
- int x = this.nodeToPostOrderNumber[p];
- new_idom = x;
- first_processed_predecessor = x;
- break;
- }
- }
- #endregion
- #region for all other predecessors, p, of b
- foreach (Node p in predecessors) {
- if (this.nodeToPostOrderNumber[p] == first_processed_predecessor) {
- continue;
- }
- if (this.doms[this.nodeToPostOrderNumber[p]] != 0)
- new_idom = intersect(this.nodeToPostOrderNumber[p], new_idom, this.doms);
- }
- #endregion
- if (this.doms[this.nodeToPostOrderNumber[b]] != new_idom) {
- this.doms[this.nodeToPostOrderNumber[b]] = new_idom;
- changed = true;
- }
- }
- }
- #region Populate the Immediate Dominator Map
- int sourceNum = this.nodeToPostOrderNumber[this.source];
- immediateDominatorMap = new Dictionary<Node, List<Node>>();
- for (int i = 1; i <= n; i++) {
- Node node = this.postOrderNumberToNode[i].Val;
- Node idomNode = this.postOrderNumberToNode[this.doms[i]].Val;
- if (i == sourceNum && this.doms[i] == sourceNum) {
- continue;
- }
- if (immediateDominatorMap.ContainsKey(idomNode)) {
- immediateDominatorMap[idomNode].Add(node);
- } else {
- List<Node> l = new List<Node>();
- l.Add(node);
- immediateDominatorMap.Add(idomNode, l);
- }
- }
- #endregion
- }
- private int intersect(int b1, int b2, int[] doms) {
- int finger1 = b1;
- int finger2 = b2;
- while (finger1 != finger2) {
- while (finger1 < finger2) {
- finger1 = doms[finger1];
- }
- while (finger2 < finger1) {
- finger2 = doms[finger2];
- }
- }
- return finger1;
- }
- private void PostOrderVisit(Node/*!*/ n, HashSet<Node> visited, ref int currentNumber) {
- Contract.Requires(n != null);
- if (visited.Contains(n))
- return;
- visited.Add(n);
- foreach (Node/*!*/ child in this.graph.Successors(n)) {
- Contract.Assert(child != null);
- PostOrderVisit(child, visited, ref currentNumber);
- }
- Contract.Assume(this.postOrderNumberToNode != null);
- Contract.Assume(this.nodeToPostOrderNumber != null);
- this.postOrderNumberToNode[currentNumber].Val = n;
- this.nodeToPostOrderNumber[n] = currentNumber;
- currentNumber++;
- return;
- }
- // Iterative version: mimics the above recursive procedure
- private void PostOrderVisitIterative(Node n)
- {
- Contract.Requires(n != null);
- var visited = new HashSet<Node>();
- var grey = new HashSet<Node>();
- var stack = new Stack<Node>();
-
- int currentNumber = 1;
-
- stack.Push(n);
- visited.Add(n);
-
- while (stack.Count != 0)
- {
- var curr = stack.Pop();
-
- if (grey.Contains(curr))
- {
- Contract.Assume(this.postOrderNumberToNode != null);
- Contract.Assume(this.nodeToPostOrderNumber != null);
- this.postOrderNumberToNode[currentNumber].Val = curr;
- this.nodeToPostOrderNumber[curr] = currentNumber;
- currentNumber++;
- }
- else
- {
- grey.Add(curr);
- stack.Push(curr);
- foreach (Node/*!*/ child in this.graph.Successors(curr))
- {
- Contract.Assert(child != null);
- if (!visited.Contains(child))
- {
- visited.Add(child);
- stack.Push(child);
- }
- }
- }
-
- }
-
-
- }
-
- public Node LeastCommonAncestor(Node n1, Node n2)
- {
- int num1 = nodeToPostOrderNumber[n1], num2 = nodeToPostOrderNumber[n2];
- int lca = intersect(num1, num2, this.doms);
- return postOrderNumberToNode[lca].Val;
- }
- }
-
- public class Graph<Node> {
- private HashSet<Tuple<Node/*!*/, Node/*!*/>> es;
- private HashSet<Node> ns;
- private Node source;
- private bool reducible;
- private HashSet<Node> headers;
- private Dictionary<Node, HashSet<Node>> backEdgeNodes;
- private Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
- private HashSet<Node> splitCandidates;
-
- private DomRelation<Node> dominatorMap = null;
- private Dictionary<Node, HashSet<Node>> predCache = new Dictionary<Node, HashSet<Node>>();
- private Dictionary<Node, HashSet<Node>> succCache = new Dictionary<Node, HashSet<Node>>();
- private bool predComputed;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(es == null || Contract.ForAll(es, p => p.Item1 != null && p.Item2 != null));
- Contract.Invariant(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, p => p.Item2 != null && p.Item1 != null));
- }
-
- private class PreHeader {
- Node/*!*/ myHeader;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(myHeader != null);
- }
-
- internal PreHeader(Node/*!*/ h) {
- Contract.Requires(h != null);
- myHeader = h;
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "#" + myHeader.ToString();
- }
- }
-
- public Graph(HashSet<Tuple<Node/*!*/, Node/*!*/>> edges) {
-
- Contract.Requires(cce.NonNullElements(edges) && Contract.ForAll(edges, p => p.Item1 != null && p.Item2 != null));
- es = edges;
-
- // original A#
- //ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
-
- // closest Spec#
- //ns = new Set<Node>{ Tuple<Node,Node> p in edges; p.Item1 } + new Set<Node>{ Tuple<Node,Node> p in edges; p.Item2 };
-
- //
- HashSet<Node> temp = new HashSet<Node>();
- foreach (Tuple<Node/*!*/, Node/*!*/> p in edges) {
- Contract.Assert(p.Item1 != null);
- temp.Add(p.Item1);
- Contract.Assert(p.Item2 != null);
- temp.Add(p.Item2);
- }
- ns = temp;
- }
- public Graph() {
- es = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- ns = new HashSet<Node>();
- }
-
- // BUGBUG: Set<T>.ToString() should return a non-null string
- [Pure]
- public override string/*!*/ ToString() {
- return "" + es.ToString();
- }
-
- public void AddSource(Node/*!*/ x) {
- Contract.Requires(x != null);
- // BUGBUG: This generates bad code in the compiler
- //ns += new Set<Node>{x};
- ns.Add(x);
- source = x;
- }
-
- public void AddEdge(Node/*!*/ source, Node/*!*/ dest) {
- Contract.Requires(source != null);
- Contract.Requires(dest != null);
- //es += Set<Edge>{<source,dest>};
- //ns += Set<Node>{source, dest};
- es.Add(new Tuple<Node/*!*/, Node/*!*/>(source, dest));
- ns.Add(source);
- ns.Add(dest);
- predComputed = false;
- }
-
- public HashSet<Node> Nodes {
- get {
- return ns;
- }
- }
- public IEnumerable<Tuple<Node/*!*/, Node/*!*/>> Edges {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Tuple<Node, Node>>>())
- && Contract.ForAll(Contract.Result<IEnumerable<Tuple<Node, Node>>>(), n =>
- n.Item1 != null && n.Item2 != null));
- return es;
- }
- }
-
- public bool Edge(Node/*!*/ x, Node/*!*/ y) {
- Contract.Requires(x != null);
- Contract.Requires(y != null);
- // original A#
- // return <x,y> in es;
- return es.Contains(new Tuple<Node/*!*/, Node/*!*/>(x, y));
- }
-
- private void ComputePredSuccCaches() {
- if (predComputed)
- return;
- predComputed = true;
- predCache = new Dictionary<Node, HashSet<Node>>();
- succCache = new Dictionary<Node, HashSet<Node>>();
-
- foreach (Node n in Nodes) {
- predCache[n] = new HashSet<Node>();
- succCache[n] = new HashSet<Node>();
- }
-
- foreach (Tuple<Node/*!*/, Node/*!*/> p in Edges) {
- Contract.Assert(p.Item1 != null);
- Contract.Assert(p.Item2 != null);
- HashSet<Node> tmp;
-
- tmp = predCache[p.Item2];
- tmp.Add(p.Item1);
- predCache[p.Item2] = tmp;
-
- tmp = succCache[p.Item1];
- tmp.Add(p.Item2);
- succCache[p.Item1] = tmp;
- }
- }
-
- public IEnumerable<Node> Predecessors(Node n) {
- // original A#
- //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
-
- ComputePredSuccCaches();
- return predCache[n];
- }
-
- public IEnumerable<Node> Successors(Node n) {
- ComputePredSuccCaches();
- return succCache[n];
- }
-
- public List<Node> SuccessorsAsList(Node n) {
- ComputePredSuccCaches();
- List<Node> ret = new List<Node>();
- foreach (Node s in succCache[n])
- ret.Add(s);
- return ret;
- }
-
- public DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap {
- get {
- Contract.Assert(source != null);
- if (this.dominatorMap == null) {
- this.dominatorMap = new DomRelation<Node>(this, this.source);
- }
- return this.dominatorMap;
- }
- }
-
- public Dictionary<Node, List<Node>> ImmediateDominatorMap {
- get {
- Contract.Assert(source != null);
- if (this.dominatorMap == null) {
- this.dominatorMap = new DomRelation<Node>(this, this.source);
- }
- return this.dominatorMap.ImmediateDominatorMap;
- }
- }
- public List<Node> ImmediatelyDominatedBy(Node/*!*/ n) {
- Contract.Requires(n != null);
- List<Node> dominees;
- this.ImmediateDominatorMap.TryGetValue(n, out dominees);
- return dominees == null ? new List<Node>() : dominees;
- }
-
- public IEnumerable<Node/*?*/> TopologicalSort(bool reversed = false) {
- bool acyclic;
- List<Node> sortedList;
- this.TarjanTopSort(out acyclic, out sortedList, reversed);
- return acyclic ? sortedList : new List<Node>();
- }
- // From Tarjan 1972
- public void TarjanTopSort(out bool acyclic, out List<Node> sortedNodes, bool reversed = false) {
- int n = this.Nodes.Count;
- if (n == 0) {
- acyclic = true;
- sortedNodes = new List<Node>();
- return;
- }
- int[] incomingEdges = new int[n];
- // need an arbitrary numbering for the nodes to use as indices into
- // the arrays used within this algorithm
- Dictionary<Node, int> nodeToNumber = new Dictionary<Node, int>(n);
- Maybe<Node>[] numberToNode = new Maybe<Node>[n];
- int counter = 0;
- foreach (Node node in this.Nodes) {
- numberToNode[counter].Val = node;
- nodeToNumber[node] = counter;
- counter++;
- }
- foreach (Tuple<Node/*!*/, Node/*!*/> e in this.Edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- Node/*!*/ target = e.Item2;
- incomingEdges[nodeToNumber[target]]++;
- }
- List<Node> sorted = new List<Node>();
- int sortedIndex = 0;
- while (sortedIndex < n) {
- // find a root (i.e., its index)
- int rootIndex = -1;
- if (reversed) {
- for (int i = n-1; i >= 0; i--) {
- if (incomingEdges[i] == 0) {
- rootIndex = i;
- break;
- }
- }
- } else {
- for (int i = 0; i < n; i++) {
- if (incomingEdges[i] == 0) {
- rootIndex = i;
- break;
- }
- }
- }
- if (rootIndex == -1) {
- acyclic = false;
- sortedNodes = new List<Node>();
- return;
- }
- // mark root so it won't be used again
- incomingEdges[rootIndex] = -1;
- Node root = numberToNode[rootIndex].Val;
- sorted.Add(root);
- ++sortedIndex;
- foreach (Node s in this.Successors(root)) {
- incomingEdges[nodeToNumber[s]]--;
- }
- }
- acyclic = true;
- sortedNodes = sorted;
- return;
- }
- private IEnumerable<Node> OldTopologicalSort() {
- Tuple<bool, List<Node>> result = this.TopSort();
- return result.Item1 ? result.Item2 : (IEnumerable<Node>)new List<Node>();
- }
- // From AsmL distribution example
- private Tuple<bool, List<Node>> TopSort()
- {
- List<Node> S = new List<Node>();
- HashSet<Node> V = this.Nodes;
- HashSet<Node> X = new HashSet<Node>();
- foreach (Node/*!*/ n in V) {
- Contract.Assert(n != null);
- X.Add(n);
- }
- bool change = true;
- while (change)
- // invariant: X = V - S
- {
- change = false;
- if (X.Count > 0) {
- foreach (Node/*!*/ n in X) {
- Contract.Assert(n != null);
- // see if n has any incoming edges from any other node in X
- bool inDegreeZero = true;
- foreach (Node/*!*/ u in X) {
- Contract.Assert(u != null);
- if (this.Edge(u, n)) {
- inDegreeZero = false;
- break; // no point looking further
- }
- }
- if (inDegreeZero) {
- S.Add(n);
- X.Remove(n);
- change = true;
- break; // might as well go back and start looking through X from the beginning
- }
- }
- // Then we made it all the way through X without finding a source node
- if (!change) {
- return new Tuple<bool, List<Node>>(false, new List<Node>());
- }
- }
- }
- return new Tuple<bool, List<Node>>(true, S);
- }
-
- public static bool Acyclic(Graph<Node> g, Node source) {
- bool acyclic;
- List<Node> sortedList;
- g.TarjanTopSort(out acyclic, out sortedList);
- return acyclic;
- }
-
- // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
- static HashSet<Node> NaturalLoop(Graph<Node> g, Tuple<Node/*!*/, Node/*!*/> backEdge)
- {
- Contract.Requires(backEdge.Item1 != null && backEdge.Item2 != null);
- Node/*!*/ n = backEdge.Item1;
- Node/*!*/ d = backEdge.Item2;
- Stack<Node> stack = new Stack<Node>();
- HashSet<Node> loop = new HashSet<Node>();
- loop.Add(d);
- if (!n.Equals(d)) // then n is not in loop
- {
- loop.Add(n);
- stack.Push(n); // push n onto stack
- }
- while (stack.Count > 0) // not empty
- {
- Node m = stack.Peek();
- stack.Pop(); // pop stack
- foreach (Node/*!*/ p in g.Predecessors(m)) {
- Contract.Assert(p != null);
- if (!(loop.Contains(p))) {
- loop.Add(p);
- stack.Push(p); // push p onto stack
- }
- }
- }
- return loop;
- }
-
- internal struct ReducibleResult {
- internal bool reducible;
- internal HashSet<Node> headers;
- internal Dictionary<Node, HashSet<Node>> backEdgeNodes;
- internal Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
- internal HashSet<Node> splitCandidates;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Contract.ForAll(naturalLoops.Keys, p => p.Item1 != null && p.Item2 != null));
- }
-
- internal ReducibleResult(bool b, HashSet<Node> headers, Dictionary<Node, HashSet<Node>> backEdgeNodes, Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops, HashSet<Node> splitCandidates)
- {
- Contract.Requires(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, Key => Key.Item1 != null && Key.Item2 != null));
- this.reducible = b;
- this.headers = headers;
- this.backEdgeNodes = backEdgeNodes;
- this.naturalLoops = naturalLoops;
- this.splitCandidates = splitCandidates;
- }
-
- }
-
- // [Dragon, p. 606]
- static ReducibleResult ComputeReducible(Graph<Node> g, Node source) {
- // first, compute the dom relation
- DomRelation<Node> /*Map<Node,Set<Node>>*/ D = g.DominatorMap;
- return ComputeReducible(g, source, D);
- }
-
- static HashSet<Node> FindCycle(Graph<Node> g, Node source) {
- Stack<Tuple<Node, List<Node>>> stack = new Stack<Tuple<Node, List<Node>>>();
- HashSet<Node> stackAsSet = new HashSet<Node>();
- HashSet<Node> visited = new HashSet<Node>();
- stack.Push(new Tuple<Node, List<Node>>(source, g.SuccessorsAsList(source)));
- stackAsSet.Add(source);
- while (stack.Count > 0) {
- Tuple<Node, List<Node>> tuple = stack.Peek();
- List<Node> children = tuple.Item2;
- if (children.Count == 0) {
- stack.Pop();
- stackAsSet.Remove(tuple.Item1);
- continue;
- }
- Node n = children[0];
- children.RemoveAt(0);
- if (stackAsSet.Contains(n)) {
- HashSet<Node> ret = new HashSet<Node>();
- ret.Add(n);
- while (true) {
- Node x = stack.Pop().Item1;
- if (x.Equals(n))
- return ret;
- }
- }
- if (visited.Contains(n))
- continue;
- stack.Push(new Tuple<Node, List<Node>>(n, g.SuccessorsAsList(n)));
- visited.Add(n);
- stackAsSet.Add(n);
- System.Diagnostics.Debug.Assert(stack.Count == stackAsSet.Count);
- }
- return new HashSet<Node>();
- }
-
- // [Dragon, p. 606]
- static ReducibleResult ComputeReducible(Graph<Node> g,
- Node source,
- DomRelation<Node>/*!*/ DomRelation) {
- Contract.Requires(DomRelation != null);
-
- //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible");
- IEnumerable<Tuple<Node/*!*/, Node/*!*/>> edges = g.Edges;
- Contract.Assert(Contract.ForAll(edges, n => n.Item1 != null && n.Item2 != null));
- HashSet<Tuple<Node/*!*/, Node/*!*/>> backEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- HashSet<Tuple<Node/*!*/, Node/*!*/>> nonBackEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- Node x = e.Item1;
- Node y = e.Item2; // so there is an edge from x to y
- if (DomRelation.DominatedBy(x, y)) { // y dom x: which means y dominates x
- backEdges.Add(e);
- } else {
- nonBackEdges.Add(e);
- }
- }
- Graph<Node> withoutBackEdges = new Graph<Node>(nonBackEdges);
- if (!Acyclic(withoutBackEdges, source)) {
- return new ReducibleResult(false,
- new HashSet<Node>(),
- new Dictionary<Node, HashSet<Node>>(),
- new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(),
- FindCycle(withoutBackEdges, source));
- } else {
- // original A#:
- //Set<Node> headers = Set{ d : <n,d> in backEdges };
- HashSet<Node> headers = new HashSet<Node>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
-
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- headers.Add(e.Item2);
- }
- // original A#:
- //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
- Dictionary<Node, HashSet<Node>> backEdgeNodes = new Dictionary<Node, HashSet<Node>>();
- foreach (Node/*!*/ h in headers) {
- Contract.Assert(h != null);
- HashSet<Node> bs = new HashSet<Node>();
- foreach (Tuple<Node, Node> backedge in backEdges) {
- Contract.Assert(backedge.Item1 != null);
- Contract.Assert(backedge.Item2 != null);
- if (backedge.Item2.Equals(h)) {
- bs.Add(backedge.Item1);
- }
- }
- backEdgeNodes.Add(h, bs);
- }
-
- // original A#:
- //Map<Tuple<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
- Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops = new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
- Contract.Assert(e.Item1 != null && e.Item2 != null);
- naturalLoops.Add(e, NaturalLoop(g, e));
- }
-
- //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible");
- return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops, new HashSet<Node>());
- }
- }
-
- public bool Reducible {
- get {
- return reducible;
- }
- }
- public IEnumerable<Node> Headers {
- get {
- return headers;
- }
- }
- public IEnumerable<Node> BackEdgeNodes(Node/*!*/ h) {
- Contract.Requires(h != null);
- // original A#:
- //return h in backEdgeNodes ? backEdgeNodes[h] : null;
- return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new List<Node>());
- }
- public IEnumerable<Node> NaturalLoops(Node/*!*/ header, Node/*!*/ backEdgeNode) {
- Contract.Requires(header != null);
- Contract.Requires(backEdgeNode != null);
- Tuple<Node/*!*/, Node/*!*/> e = new Tuple<Node/*!*/, Node/*!*/>(backEdgeNode, header);
- return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new List<Node>();
- }
- public HashSet<Node> SplitCandidates {
- get {
- return splitCandidates;
- }
- }
- public void ComputeLoops() {
- ReducibleResult r = ComputeReducible(this, this.source);
- this.reducible = r.reducible;
- this.headers = r.headers;
- this.backEdgeNodes = r.backEdgeNodes;
- this.naturalLoops = r.naturalLoops;
- this.splitCandidates = r.splitCandidates;
- return;
- }
-
- public IEnumerable<Node> SortHeadersByDominance()
- {
- Graph<Node> dag = new Graph<Node>();
- foreach (Node b in headers)
- {
- dag.AddSource(b);
- foreach (Node c in headers)
- {
- if (b.Equals(c)) continue;
- if (DominatorMap.DominatedBy(b, c))
- {
- System.Diagnostics.Debug.Assert(!DominatorMap.DominatedBy(c, b));
- dag.AddEdge(b, c);
- }
- }
- }
- return dag.TopologicalSort();
- }
-
- public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) {
- NodeLabel = NodeLabel ?? (n => n.ToString());
- NodeStyle = NodeStyle ?? (n => "[shape=box]");
- var s = new StringBuilder();
- s.AppendLine("digraph G {");
- foreach (var n in Nodes)
- s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";");
- foreach (var e in Edges)
- s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";");
- s.AppendLine("}");
- return s.ToString();
- }
-
- public ICollection<Node> ComputeReachable() {
- ICollection<Node> result = new HashSet<Node>();
- Stack<Node> stack = new Stack<Node>();
- stack.Push(source);
- while(!(stack.Count() == 0)) {
- Node n = stack.Pop();
- result.Add(n);
- foreach(var m in Successors(n)) {
- if(!result.Contains(m)) {
- stack.Push(m);
- }
- }
- }
- return result;
- }
-
- } // end: class Graph
-
- public static class GraphAlgorithms
- {
-
-
- public static Graph<Node> Dual<Node>(this Graph<Node> g, Node dummySource)
- {
- var exits = g.Nodes.Where(n => g.Successors(n).Count() == 0).ToList();
- Node source;
- if (exits.Count == 0)
- exits.Add(dummySource);
- var dual = new Graph<Node>(new HashSet<Tuple<Node, Node>>(g.Edges.Select(e => new Tuple<Node, Node>(e.Item2, e.Item1))));
- if (exits.Count == 1)
- {
- dual.AddSource(exits[0]);
- source = exits[0];
- }
- else
- {
- dual.AddSource(dummySource);
- source = dummySource;
- foreach (var exit in exits)
- dual.AddEdge(dummySource, exit);
- }
-
- #region Dual graph may not be connected, so add an edge from the dual graph's soure node to any unreachable node
- foreach (var n in dual.Nodes.Where(Item => !dual.ComputeReachable().Contains(Item)))
- {
- dual.AddEdge(source, n);
- }
- #endregion
-
- return dual;
- }
-
- public static List<Tuple<Node, bool>> LoopyTopSort<Node>(this Graph<Node> g)
- {
- Contract.Assert(g.Reducible);
-
- int n = g.Nodes.Count;
- var nodeToNumber = new Dictionary<Node, int>(n);
- var numberToNode = new Node[n];
- var allNodes = new List<int>();
- int counter = 0;
- foreach (Node node in g.Nodes)
- {
- numberToNode[counter] = node;
- nodeToNumber[node] = counter;
- allNodes.Add(counter);
- counter++;
- }
-
- var loops = new List<int>[n];
- foreach (var h in g.Headers)
- {
- var loopNodes = new HashSet<Node>();
- foreach (var b in g.BackEdgeNodes(h))
- loopNodes.UnionWith(g.NaturalLoops(h, b));
- loops[nodeToNumber[h]] =
- new List<int>(loopNodes.Select(node => nodeToNumber[node]));
- }
-
- var successors = new List<int>[n];
- var predecessors = new List<int>[n];
- int[] incomingEdges = new int[n];
-
- for (int i = 0; i < n; i++)
- predecessors[i] = new List<int>();
-
- foreach (var e in g.Edges)
- {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- int source = nodeToNumber[e.Item1], target = nodeToNumber[e.Item2];
- if (loops[target] == null || !loops[target].Contains(source))
- {
- if (successors[source] == null)
- successors[source] = new List<int>();
- successors[source].Add(target);
- incomingEdges[target]++;
- }
- predecessors[target].Add(source);
- }
-
- var sortedNodes = new List<Tuple<Node, bool>>();
- var sortedNodesInternal = new List<int>();
-
- var regionStack = new Stack<Tuple<Node, List<int>>>();
- regionStack.Push(new Tuple<Node, List<int>>(default(Node), allNodes));
-
- while (regionStack.Count != 0)
- {
- var rootIndexes = new List<int>();
- foreach (var i in regionStack.Peek().Item2)
- {
- if (incomingEdges[i] == 0)
- rootIndexes.Add(i);
- }
- if (rootIndexes.Count() == 0)
- {
- var region = regionStack.Pop();
- if (regionStack.Count != 0) {
- sortedNodes.Add(new Tuple<Node, bool>(region.Item1, true));
- sortedNodesInternal.Add(nodeToNumber[region.Item1]);
- }
- continue;
- }
- int rootIndex = rootIndexes[0];
- int maxPredIndex = -1;
- foreach (var i in rootIndexes) {
- foreach (var p in predecessors[i]) {
- int predIndex =
- sortedNodesInternal.FindLastIndex(x => x == p);
- if (predIndex > maxPredIndex) {
- rootIndex = i;
- maxPredIndex = predIndex;
- }
- }
- }
- incomingEdges[rootIndex] = -1;
- sortedNodes.Add(new Tuple<Node, bool>(numberToNode[rootIndex], false));
- sortedNodesInternal.Add(rootIndex);
- if (successors[rootIndex] != null)
- foreach (int s in successors[rootIndex])
- incomingEdges[s]--;
- if (loops[rootIndex] != null)
- regionStack.Push(new Tuple<Node, List<int>>(numberToNode[rootIndex],
- loops[rootIndex]));
- }
-
- return sortedNodes;
- }
-
- // Algorithm from Jeanne Ferrante, Karl J. Ottenstein, Joe D. Warren,
- // "The Program Dependence Graph and Its Use in Optimization"
- public static Dictionary<Node, HashSet<Node>> ControlDependence<Node>(this Graph<Node> g) where Node : class, new()
- {
- Graph<Node> dual = g.Dual(new Node());
- DomRelation<Node> pdom = dual.DominatorMap;
-
- var result = new Dictionary<Node, HashSet<Node>>();
-
- var S = g.Edges.Where(e => !pdom.DominatedBy(e.Item1, e.Item2));
- foreach (var edge in S)
- {
- var L = pdom.LeastCommonAncestor(edge.Item1, edge.Item2);
- var deps = new List<Node>();
- if (L == edge.Item1)
- {
- pdom.DominatedBy(edge.Item2, edge.Item1, deps);
- deps.Add(edge.Item2);
- deps.Add(edge.Item1);
- }
- else
- {
- pdom.DominatedBy(edge.Item2, L, deps);
- deps.Add(edge.Item2);
- }
- if (result.ContainsKey(edge.Item1))
- {
- result[edge.Item1].UnionWith(deps);
- }
- else
- {
- result[edge.Item1] = new HashSet<Node>(deps);
- }
- }
-
- return result;
- }
-
- public static void TransitiveClosure<Node>(this Dictionary<Node, HashSet<Node>> graph) where Node : class {
- bool changed;
- do {
- changed = false;
- foreach (var entry in graph) {
- var newSuccessors = new HashSet<Node>(entry.Value);
- foreach (var successor in entry.Value) {
- if (graph.ContainsKey(successor))
- newSuccessors.UnionWith(graph[successor]);
- }
- if (newSuccessors.Count != entry.Value.Count) {
- entry.Value.UnionWith(newSuccessors);
- changed = true;
- }
- }
- } while (changed);
- }
-
- }
-
- public delegate System.Collections.IEnumerable/*<Node!>*//*!*/ Adjacency<T>(T/*!*/ node);
-
-
- // An SCC is a set of nodes
- public sealed class SCC<Node> : ICollection<Node>
- {
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(nodesMap != null);
- }
-
- private IDictionary<Node, object>/*!*/ nodesMap = new Dictionary<Node, object>();
- private ICollection<Node>/*!*/ nodes
- {
- get
- {
- return cce.NonNull(nodesMap.Keys);
- }
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
- {
- Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
-
- return ((System.Collections.IEnumerable)nodes).GetEnumerator();
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator<Node>/*!*/ IEnumerable<Node>.GetEnumerator()
- {
- Contract.Ensures(Contract.Result<IEnumerator<Node>>() != null);
-
- return ((IEnumerable<Node>)nodes).GetEnumerator();
- }
-
- public int Count
- {
- get
- {
- return nodes.Count;
- }
- }
- public bool IsReadOnly
- {
- get
- {
- return nodesMap.IsReadOnly;
- }
- }
- public void Add(Node item)
- {
- nodesMap.Add(item, null);
- }
- public void Clear()
- {
- nodesMap.Clear();
- }
- [Pure]
- public bool Contains(Node item)
- {
- return nodesMap.ContainsKey(item);
- }
- public void CopyTo(Node[] array, int arrayIndex)
- {
- //Contract.Requires(array != null);
- nodes.CopyTo(array, arrayIndex);
- }
- public bool Remove(Node item)
- {
- return nodesMap.Remove(item);
- }
- }
-
- public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>/*!*/> where Node : class
- {
- private readonly IDictionary<Node/*!*/, object>/*!*/ graph;
- [ContractInvariantMethod]
- void graphInvariantMethod()
- {
- Contract.Invariant(Contract.ForAll(graph, entry => entry.Key != null));
- Contract.Invariant(preds != null);
- Contract.Invariant(succs != null);
- }
- private readonly Adjacency<Node>/*!*/ preds;
- private readonly Adjacency<Node>/*!*/ succs;
-
- private bool computed = false;
- public bool Computed
- {
- get
- {
- return computed;
- }
- }
-
- [NotDelayed]
- public StronglyConnectedComponents(System.Collections.IEnumerable/*<Node!>*/ graph, Adjacency<Node> preds, Adjacency<Node> succs)
- : base()
- {
- Contract.Requires(succs != null);
- Contract.Requires(preds != null);
- Contract.Requires(graph != null);
- Contract.Ensures(!Computed);
- IDictionary<Node/*!*/, object>/*!*/ dict = new Dictionary<Node/*!*/, object>();
- foreach (Node/*!*/ n in graph)
- {
- Contract.Assert(n != null);
- dict.Add(n, null);
- }
-
- this.graph = dict;
- this.preds = preds;
- this.succs = succs;
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
- {
- Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
-
- return ((System.Collections.IEnumerable)sccs).GetEnumerator();
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator<SCC<Node>/*!*/>/*!*/ IEnumerable<SCC<Node>/*!*/>.GetEnumerator()
- {
- Contract.Ensures(Contract.Result<IEnumerator<SCC<Node>>>() != null);
-
- Contract.Assume(Computed);
- Contract.Assert(cce.NonNullElements((IEnumerable<SCC<Node>/*!*/>)sccs));//REVIEW
- return ((IEnumerable<SCC<Node>/*!*/>)sccs).GetEnumerator();
- }
-
- private readonly IList<SCC<Node>/*!*/>/*!*/ sccs = new List<SCC<Node>/*!*/>();
- [ContractInvariantMethod]
- void sccsInvariant()
- {
- Contract.Invariant(cce.NonNullElements(sccs));
- }
-
-
- public void Compute()
- {
- Contract.Requires(!Computed);
- Contract.Ensures(Computed);
- // Compute post times on graph with edges reversed
- this.dfsNext = this.preds;
- foreach (Node/*!*/ n in cce.NonNull(graph.Keys))
- {
- Contract.Assert(n != null);
- if (!seen.ContainsKey(n))
- {
- OrderNodes(n);
- }
- }
-
- // Clear seen
- seen.Clear();
-
- // Compute SCCs
- this.dfsNext = this.succs;
- while (postOrder.Count > 0)
- {
- Node/*!*/ n = postOrder.Pop();
- Contract.Assert(n != null);
-
- if (!seen.ContainsKey(n))
- {
- SCC<Node>/*!*/ curr = new SCC<Node>();
- FindSCCs(n, curr);
- sccs.Add(curr);
- }
- }
-
- // Clear seen
- seen.Clear();
-
- this.computed = true;
- }
-
- private Adjacency<Node>/*?*/ dfsNext = null;
-
- private readonly IDictionary<Node/*!*/, object>/*!*/ seen = new Dictionary<Node/*!*/, object>();
- private readonly Stack<Node/*!*/>/*!*/ postOrder = new Stack<Node/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(seen != null);
- Contract.Invariant(cce.NonNullElements(postOrder));
- }
-
-
- // DFS to order nodes by post times
- private void OrderNodes(Node node)
- {
- Contract.Requires(node != null);
- seen.Add(node, null);
-
- Contract.Assert(dfsNext != null);
- System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
- Contract.Assert(nexts != null);
- foreach (Node/*!*/ n in nexts)
- {
- Contract.Assert(n != null);
- if (graph.ContainsKey(n) && !seen.ContainsKey(n))
- {
- OrderNodes(n);
- }
- }
-
- postOrder.Push(node);
- }
-
- // DFS to compute SCCs
- private void FindSCCs(Node node, SCC<Node> currSCC)
- {
- Contract.Requires(currSCC != null);
- Contract.Requires(node != null);
- //modifies currSCC.*;
- seen.Add(node, null);
- currSCC.Add(node);
-
- Contract.Assert(dfsNext != null);
- System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
- Contract.Assert(nexts != null);
- foreach (Node/*!*/ n in nexts)
- {
- Contract.Assert(n != null);
- if (graph.ContainsKey(n) && !seen.ContainsKey(n))
- {
- FindSCCs(n, currSCC);
- }
- }
- }
-
- [Pure]
- public override string ToString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- string outStr = "";
- int i = 0;
-
- foreach (ICollection<Node> component in this)
- {
- string/*!*/ tmp = System.String.Format("\nComponent #{0} = ", i++);
- Contract.Assert(tmp != null);
- outStr += tmp;
-
- bool firstInRow = true;
-
- foreach (Node b in component)
- {
- string/*!*/ tmpComponent = System.String.Format("{0}{1}", firstInRow ? "" : ", ", b);
- Contract.Assert(tmpComponent != null);
- outStr += tmpComponent;
- firstInRow = false;
- }
- }
- return outStr;
- }
-
- }
-
- public class GraphProgram {
- static void TestGraph<T>(T/*!*/ source, params Tuple<T/*!*/, T/*!*/>[] edges) {
- Contract.Requires(source != null);
- Contract.Requires(Contract.ForAll(edges, pair => pair.Item1 != null && pair.Item2 != null));
- HashSet<Tuple<T/*!*/, T/*!*/>> es = new HashSet<Tuple<T/*!*/, T/*!*/>>();
- foreach (Tuple<T/*!*/, T/*!*/> e in edges) {
- Contract.Assert(e.Item1 != null && e.Item2 != null);
- es.Add(e);
- }
- Graph<T> g = new Graph<T>(es);
- g.AddSource(source);
- Console.WriteLine("G = " + g);
- g.ComputeLoops();
- Console.WriteLine("G's Dominator Map = " + g.DominatorMap);
- Console.WriteLine("G's Immediate Dominator Map = " + Util.MapToString(g.ImmediateDominatorMap));
- Console.WriteLine("G is reducible: " + (g.Reducible ? "yes" : "no"));
- }
-
- static void Main(string[] args)
- //requires forall{string s in args; s != null};
- {
- Console.WriteLine("Spec# says hello!");
- // This generates bad IL -- need to fix a bug in the compiler
- //Graph<int> g = new Graph<int>(new Set<Tuple<int,int>>{ new Tuple<int,int>(1,2), new Tuple<int,int>(1,3), new Tuple<int,int>(2,3) });
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c')
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'd'),
- new Tuple<char, char>('c', 'e'),
- new Tuple<char, char>('c', 'f'),
- new Tuple<char, char>('d', 'e'),
- new Tuple<char, char>('e', 'd'),
- new Tuple<char, char>('e', 'f'),
- new Tuple<char, char>('f', 'e')
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c'),
- new Tuple<char, char>('c', 'b')
- );
-
- Console.WriteLine("");
- TestGraph<int>(1,
- new Tuple<int, int>(1, 2),
- new Tuple<int, int>(1, 3),
- new Tuple<int, int>(2, 3)
- );
-
- Console.WriteLine("");
- TestGraph<int>(1,
- new Tuple<int, int>(1, 2),
- new Tuple<int, int>(1, 3),
- new Tuple<int, int>(2, 3),
- new Tuple<int, int>(3, 2)
- );
-
- Console.WriteLine("");
- TestGraph<int>(2,
- new Tuple<int, int>(2, 3),
- new Tuple<int, int>(2, 4),
- new Tuple<int, int>(3, 2)
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c'),
- new Tuple<char, char>('b', 'b')
- );
-
-
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text; // for StringBuilder
+using System.Diagnostics.Contracts;
+namespace Microsoft.Boogie.GraphUtil {
+
+ internal static class Util {
+ private static string/*!*/ ListToString<T>(IEnumerable<T> xs) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[");
+ bool first = true;
+ foreach (T/*!*/ x in xs) {
+ Contract.Assert(x != null);
+ if (!first)
+ sb.Append(", ");
+ sb.Append(x.ToString());
+ first = false;
+ }
+ sb.Append("]");
+ return sb.ToString();
+ }
+ public static string/*!*/ MapToString<Node>(Dictionary<Node, List<Node>> d) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("{");
+ bool first = true;
+ foreach (KeyValuePair<Node, List<Node>> de in d) {
+ if (!first)
+ sb.Append(", ");
+ Contract.Assert(!object.Equals(de.Key,default(Node)));
+ sb.Append(de.Key.ToString());
+ sb.Append("~>");
+ sb.Append(ListToString(de.Value));
+ first = false;
+ }
+ sb.Append("}");
+ return sb.ToString();
+ }
+ }
+
+ // own struct to represent possibly undefined values, because Mono does
+ // not like arrays with element type T! or T?
+ public struct Maybe<T> {
+ private T Value;
+ public bool IsSet; // initialised with false by the default ctor
+ public T Val {
+ get {
+ Contract.Assume(IsSet);
+ return Value;
+ }
+ set {
+ Value = value;
+ IsSet = true;
+ }
+ }
+ public void UnSet() {
+ IsSet = false;
+ }
+ }
+
+ public class DomRelation<Node> {
+ // doms maps (unique) node numbers to the node numbers of the immediate dominator
+ // to use it on Nodes, one needs the two way mapping between nodes and their numbers.
+ private int[] doms; // 0 is unused: means undefined
+ // here are the two mappings
+ private Maybe<Node>[] postOrderNumberToNode;
+ private Dictionary<Node, int> nodeToPostOrderNumber;
+ private int sourceNum; // (number for) root of the graph
+ private Node source; // root of the graph
+ private Graph<Node> graph;
+ private Dictionary<Node, List<Node>> immediateDominatorMap;
+
+ [NotDelayed]
+ internal DomRelation(Graph<Node> g, Node source) {
+ this.graph = g;
+ // slot 0 not used: nodes are numbered from 1 to n so zero
+ // can represent undefined.
+ this.source = source;
+ //:base();
+ this.NewComputeDominators();
+ }
+ public Dictionary<Node, List<Node>> ImmediateDominatorMap {
+ get {
+ Contract.Assume(this.immediateDominatorMap != null);
+ return this.immediateDominatorMap;
+ }
+ }
+ public bool DominatedBy(Node dominee, Node dominator, List<Node> path = null) {
+ Contract.Assume(this.nodeToPostOrderNumber != null);
+ Contract.Assume(this.doms != null);
+ int domineeNum = this.nodeToPostOrderNumber[dominee];
+ int dominatorNum = this.nodeToPostOrderNumber[dominator];
+ if (domineeNum == dominatorNum)
+ return true;
+ int currentNodeNum = this.doms[domineeNum];
+ while (true) {
+ if (currentNodeNum == dominatorNum)
+ return true;
+ if (currentNodeNum == this.sourceNum)
+ return false;
+ if (path != null)
+ path.Add(postOrderNumberToNode[currentNodeNum].Val);
+ currentNodeNum = this.doms[currentNodeNum];
+ }
+ }
+ private Dictionary<Node, List<Node>> domMap = null;
+ [Pure]
+ public override string ToString() {
+ Contract.Assume(this.doms != null);
+ int[] localDoms = this.doms;
+ Contract.Assume(this.postOrderNumberToNode != null);
+ if (domMap == null) {
+ domMap = new Dictionary<Node, List<Node>>();
+ for (int i = 1; i < localDoms.Length; i++) { // 0 slot is not used
+ int domineeNum = i;
+ int currentNodeNum = domineeNum;
+ List<Node> dominators = new List<Node>();
+ while (currentNodeNum != this.sourceNum) {
+ dominators.Add(this.postOrderNumberToNode[currentNodeNum].Val);
+ currentNodeNum = this.doms[currentNodeNum];
+ }
+ dominators.Add(this.postOrderNumberToNode[this.sourceNum].Val);
+ domMap.Add(this.postOrderNumberToNode[i].Val, dominators);
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.Append("{");
+ bool first = true;
+ foreach (KeyValuePair<Node, List<Node>> de in domMap) {
+ if (!first)
+ sb.Append(", ");
+ Contract.Assert(!object.Equals(de.Key, default(Node)));
+ sb.Append(de.Key.ToString());
+ sb.Append("~>");
+ sb.Append(ListToString(de.Value));
+ first = false;
+ }
+ sb.Append("}");
+ return sb.ToString();
+ }
+ private void PrintIntArray(int[] xs) {
+ Console.Write("[");
+ for (int i = 0; i < xs.Length; i++) {
+ if (0 < i)
+ Console.Write(", ");
+ Console.Write(xs[i]);
+ }
+ Console.WriteLine("]");
+ }
+ public void PrintList<T>(IEnumerable<T> xs) {
+ Console.Write("[");
+ int i = 0;
+ foreach (T/*!*/ x in xs) {
+ Contract.Assert(x != null);
+ if (0 < i)
+ Console.Write(", ");
+ Console.Write(x.ToString());
+ i++;
+ }
+ Console.WriteLine("]");
+ }
+ public string/*!*/ ListToString<T>(IEnumerable<T> xs) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[");
+ bool first = true;
+ foreach (T/*!*/ x in xs) {
+ Contract.Assert(x != null);
+ if (!first)
+ sb.Append(", ");
+ sb.Append(x.ToString());
+ first = false;
+ }
+ sb.Append("]");
+ return sb.ToString();
+ }
+
+ // Keith D. Cooper, Timothy J. Harvey, Ken Kennedy, "A Simple, Fast Dominance Algorithm ", Software Practice and Experience, 2001.
+ // http://citeseer.ist.psu.edu/cooper01simple.html
+ private void NewComputeDominators() {
+ int n = this.graph.Nodes.Count;
+ this.postOrderNumberToNode = new Maybe<Node>[n + 1];
+ this.nodeToPostOrderNumber = new Dictionary<Node, int>();
+ //HashSet<Node> visited = new HashSet<Node>();
+ //int currentNumber = 1;
+ Contract.Assume(this.source != null);
+ //this.PostOrderVisit(this.source, visited, ref currentNumber);
+ this.PostOrderVisitIterative(this.source);
+ this.sourceNum = this.nodeToPostOrderNumber[source];
+ // for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); }
+ this.doms = new int[n + 1]; // 0 is unused: means undefined
+ Node start_node = this.source;
+ this.doms[this.nodeToPostOrderNumber[start_node]] = this.nodeToPostOrderNumber[start_node];
+ bool changed = true;
+ // PrintIntArray(doms);
+ while (changed) {
+ changed = false;
+ // for all nodes, b, in reverse postorder (except start_node)
+ for (int nodeNum = n - 1; 1 <= nodeNum; nodeNum--) {
+ Node b = this.postOrderNumberToNode[nodeNum].Val;
+ IEnumerable<Node> predecessors = this.graph.Predecessors(b);
+ // find a predecessor (i.e., a higher number) for which
+ // the doms array has been set
+ int new_idom = 0;
+ int first_processed_predecessor = 0;
+ #region new_idom <- number of first (processed) predecessor of b (pick one)
+ foreach (Node p in predecessors) {
+ if (this.doms[this.nodeToPostOrderNumber[p]] != 0) {
+ int x = this.nodeToPostOrderNumber[p];
+ new_idom = x;
+ first_processed_predecessor = x;
+ break;
+ }
+ }
+ #endregion
+ #region for all other predecessors, p, of b
+ foreach (Node p in predecessors) {
+ if (this.nodeToPostOrderNumber[p] == first_processed_predecessor) {
+ continue;
+ }
+ if (this.doms[this.nodeToPostOrderNumber[p]] != 0)
+ new_idom = intersect(this.nodeToPostOrderNumber[p], new_idom, this.doms);
+ }
+ #endregion
+ if (this.doms[this.nodeToPostOrderNumber[b]] != new_idom) {
+ this.doms[this.nodeToPostOrderNumber[b]] = new_idom;
+ changed = true;
+ }
+ }
+ }
+ #region Populate the Immediate Dominator Map
+ int sourceNum = this.nodeToPostOrderNumber[this.source];
+ immediateDominatorMap = new Dictionary<Node, List<Node>>();
+ for (int i = 1; i <= n; i++) {
+ Node node = this.postOrderNumberToNode[i].Val;
+ Node idomNode = this.postOrderNumberToNode[this.doms[i]].Val;
+ if (i == sourceNum && this.doms[i] == sourceNum) {
+ continue;
+ }
+ if (immediateDominatorMap.ContainsKey(idomNode)) {
+ immediateDominatorMap[idomNode].Add(node);
+ } else {
+ List<Node> l = new List<Node>();
+ l.Add(node);
+ immediateDominatorMap.Add(idomNode, l);
+ }
+ }
+ #endregion
+ }
+ private int intersect(int b1, int b2, int[] doms) {
+ int finger1 = b1;
+ int finger2 = b2;
+ while (finger1 != finger2) {
+ while (finger1 < finger2) {
+ finger1 = doms[finger1];
+ }
+ while (finger2 < finger1) {
+ finger2 = doms[finger2];
+ }
+ }
+ return finger1;
+ }
+ private void PostOrderVisit(Node/*!*/ n, HashSet<Node> visited, ref int currentNumber) {
+ Contract.Requires(n != null);
+ if (visited.Contains(n))
+ return;
+ visited.Add(n);
+ foreach (Node/*!*/ child in this.graph.Successors(n)) {
+ Contract.Assert(child != null);
+ PostOrderVisit(child, visited, ref currentNumber);
+ }
+ Contract.Assume(this.postOrderNumberToNode != null);
+ Contract.Assume(this.nodeToPostOrderNumber != null);
+ this.postOrderNumberToNode[currentNumber].Val = n;
+ this.nodeToPostOrderNumber[n] = currentNumber;
+ currentNumber++;
+ return;
+ }
+ // Iterative version: mimics the above recursive procedure
+ private void PostOrderVisitIterative(Node n)
+ {
+ Contract.Requires(n != null);
+ var visited = new HashSet<Node>();
+ var grey = new HashSet<Node>();
+ var stack = new Stack<Node>();
+
+ int currentNumber = 1;
+
+ stack.Push(n);
+ visited.Add(n);
+
+ while (stack.Count != 0)
+ {
+ var curr = stack.Pop();
+
+ if (grey.Contains(curr))
+ {
+ Contract.Assume(this.postOrderNumberToNode != null);
+ Contract.Assume(this.nodeToPostOrderNumber != null);
+ this.postOrderNumberToNode[currentNumber].Val = curr;
+ this.nodeToPostOrderNumber[curr] = currentNumber;
+ currentNumber++;
+ }
+ else
+ {
+ grey.Add(curr);
+ stack.Push(curr);
+ foreach (Node/*!*/ child in this.graph.Successors(curr))
+ {
+ Contract.Assert(child != null);
+ if (!visited.Contains(child))
+ {
+ visited.Add(child);
+ stack.Push(child);
+ }
+ }
+ }
+
+ }
+
+
+ }
+
+ public Node LeastCommonAncestor(Node n1, Node n2)
+ {
+ int num1 = nodeToPostOrderNumber[n1], num2 = nodeToPostOrderNumber[n2];
+ int lca = intersect(num1, num2, this.doms);
+ return postOrderNumberToNode[lca].Val;
+ }
+ }
+
+ public class Graph<Node> {
+ private HashSet<Tuple<Node/*!*/, Node/*!*/>> es;
+ private HashSet<Node> ns;
+ private Node source;
+ private bool reducible;
+ private HashSet<Node> headers;
+ private Dictionary<Node, HashSet<Node>> backEdgeNodes;
+ private Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
+ private HashSet<Node> splitCandidates;
+
+ private DomRelation<Node> dominatorMap = null;
+ private Dictionary<Node, HashSet<Node>> predCache = new Dictionary<Node, HashSet<Node>>();
+ private Dictionary<Node, HashSet<Node>> succCache = new Dictionary<Node, HashSet<Node>>();
+ private bool predComputed;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(es == null || Contract.ForAll(es, p => p.Item1 != null && p.Item2 != null));
+ Contract.Invariant(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, p => p.Item2 != null && p.Item1 != null));
+ }
+
+ private class PreHeader {
+ Node/*!*/ myHeader;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(myHeader != null);
+ }
+
+ internal PreHeader(Node/*!*/ h) {
+ Contract.Requires(h != null);
+ myHeader = h;
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "#" + myHeader.ToString();
+ }
+ }
+
+ public Graph(HashSet<Tuple<Node/*!*/, Node/*!*/>> edges) {
+
+ Contract.Requires(cce.NonNullElements(edges) && Contract.ForAll(edges, p => p.Item1 != null && p.Item2 != null));
+ es = edges;
+
+ // original A#
+ //ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
+
+ // closest Spec#
+ //ns = new Set<Node>{ Tuple<Node,Node> p in edges; p.Item1 } + new Set<Node>{ Tuple<Node,Node> p in edges; p.Item2 };
+
+ //
+ HashSet<Node> temp = new HashSet<Node>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> p in edges) {
+ Contract.Assert(p.Item1 != null);
+ temp.Add(p.Item1);
+ Contract.Assert(p.Item2 != null);
+ temp.Add(p.Item2);
+ }
+ ns = temp;
+ }
+ public Graph() {
+ es = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
+ ns = new HashSet<Node>();
+ }
+
+ // BUGBUG: Set<T>.ToString() should return a non-null string
+ [Pure]
+ public override string/*!*/ ToString() {
+ return "" + es.ToString();
+ }
+
+ public void AddSource(Node/*!*/ x) {
+ Contract.Requires(x != null);
+ // BUGBUG: This generates bad code in the compiler
+ //ns += new Set<Node>{x};
+ ns.Add(x);
+ source = x;
+ }
+
+ public void AddEdge(Node/*!*/ source, Node/*!*/ dest) {
+ Contract.Requires(source != null);
+ Contract.Requires(dest != null);
+ //es += Set<Edge>{<source,dest>};
+ //ns += Set<Node>{source, dest};
+ es.Add(new Tuple<Node/*!*/, Node/*!*/>(source, dest));
+ ns.Add(source);
+ ns.Add(dest);
+ predComputed = false;
+ }
+
+ public HashSet<Node> Nodes {
+ get {
+ return ns;
+ }
+ }
+ public IEnumerable<Tuple<Node/*!*/, Node/*!*/>> Edges {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Tuple<Node, Node>>>())
+ && Contract.ForAll(Contract.Result<IEnumerable<Tuple<Node, Node>>>(), n =>
+ n.Item1 != null && n.Item2 != null));
+ return es;
+ }
+ }
+
+ public bool Edge(Node/*!*/ x, Node/*!*/ y) {
+ Contract.Requires(x != null);
+ Contract.Requires(y != null);
+ // original A#
+ // return <x,y> in es;
+ return es.Contains(new Tuple<Node/*!*/, Node/*!*/>(x, y));
+ }
+
+ private void ComputePredSuccCaches() {
+ if (predComputed)
+ return;
+ predComputed = true;
+ predCache = new Dictionary<Node, HashSet<Node>>();
+ succCache = new Dictionary<Node, HashSet<Node>>();
+
+ foreach (Node n in Nodes) {
+ predCache[n] = new HashSet<Node>();
+ succCache[n] = new HashSet<Node>();
+ }
+
+ foreach (Tuple<Node/*!*/, Node/*!*/> p in Edges) {
+ Contract.Assert(p.Item1 != null);
+ Contract.Assert(p.Item2 != null);
+ HashSet<Node> tmp;
+
+ tmp = predCache[p.Item2];
+ tmp.Add(p.Item1);
+ predCache[p.Item2] = tmp;
+
+ tmp = succCache[p.Item1];
+ tmp.Add(p.Item2);
+ succCache[p.Item1] = tmp;
+ }
+ }
+
+ public IEnumerable<Node> Predecessors(Node n) {
+ // original A#
+ //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
+
+ ComputePredSuccCaches();
+ return predCache[n];
+ }
+
+ public IEnumerable<Node> Successors(Node n) {
+ ComputePredSuccCaches();
+ return succCache[n];
+ }
+
+ public List<Node> SuccessorsAsList(Node n) {
+ ComputePredSuccCaches();
+ List<Node> ret = new List<Node>();
+ foreach (Node s in succCache[n])
+ ret.Add(s);
+ return ret;
+ }
+
+ public DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap {
+ get {
+ Contract.Assert(source != null);
+ if (this.dominatorMap == null) {
+ this.dominatorMap = new DomRelation<Node>(this, this.source);
+ }
+ return this.dominatorMap;
+ }
+ }
+
+ public Dictionary<Node, List<Node>> ImmediateDominatorMap {
+ get {
+ Contract.Assert(source != null);
+ if (this.dominatorMap == null) {
+ this.dominatorMap = new DomRelation<Node>(this, this.source);
+ }
+ return this.dominatorMap.ImmediateDominatorMap;
+ }
+ }
+ public List<Node> ImmediatelyDominatedBy(Node/*!*/ n) {
+ Contract.Requires(n != null);
+ List<Node> dominees;
+ this.ImmediateDominatorMap.TryGetValue(n, out dominees);
+ return dominees == null ? new List<Node>() : dominees;
+ }
+
+ public IEnumerable<Node/*?*/> TopologicalSort(bool reversed = false) {
+ bool acyclic;
+ List<Node> sortedList;
+ this.TarjanTopSort(out acyclic, out sortedList, reversed);
+ return acyclic ? sortedList : new List<Node>();
+ }
+ // From Tarjan 1972
+ public void TarjanTopSort(out bool acyclic, out List<Node> sortedNodes, bool reversed = false) {
+ int n = this.Nodes.Count;
+ if (n == 0) {
+ acyclic = true;
+ sortedNodes = new List<Node>();
+ return;
+ }
+ int[] incomingEdges = new int[n];
+ // need an arbitrary numbering for the nodes to use as indices into
+ // the arrays used within this algorithm
+ Dictionary<Node, int> nodeToNumber = new Dictionary<Node, int>(n);
+ Maybe<Node>[] numberToNode = new Maybe<Node>[n];
+ int counter = 0;
+ foreach (Node node in this.Nodes) {
+ numberToNode[counter].Val = node;
+ nodeToNumber[node] = counter;
+ counter++;
+ }
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in this.Edges) {
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ Node/*!*/ target = e.Item2;
+ incomingEdges[nodeToNumber[target]]++;
+ }
+ List<Node> sorted = new List<Node>();
+ int sortedIndex = 0;
+ while (sortedIndex < n) {
+ // find a root (i.e., its index)
+ int rootIndex = -1;
+ if (reversed) {
+ for (int i = n-1; i >= 0; i--) {
+ if (incomingEdges[i] == 0) {
+ rootIndex = i;
+ break;
+ }
+ }
+ } else {
+ for (int i = 0; i < n; i++) {
+ if (incomingEdges[i] == 0) {
+ rootIndex = i;
+ break;
+ }
+ }
+ }
+ if (rootIndex == -1) {
+ acyclic = false;
+ sortedNodes = new List<Node>();
+ return;
+ }
+ // mark root so it won't be used again
+ incomingEdges[rootIndex] = -1;
+ Node root = numberToNode[rootIndex].Val;
+ sorted.Add(root);
+ ++sortedIndex;
+ foreach (Node s in this.Successors(root)) {
+ incomingEdges[nodeToNumber[s]]--;
+ }
+ }
+ acyclic = true;
+ sortedNodes = sorted;
+ return;
+ }
+ private IEnumerable<Node> OldTopologicalSort() {
+ Tuple<bool, List<Node>> result = this.TopSort();
+ return result.Item1 ? result.Item2 : (IEnumerable<Node>)new List<Node>();
+ }
+ // From AsmL distribution example
+ private Tuple<bool, List<Node>> TopSort()
+ {
+ List<Node> S = new List<Node>();
+ HashSet<Node> V = this.Nodes;
+ HashSet<Node> X = new HashSet<Node>();
+ foreach (Node/*!*/ n in V) {
+ Contract.Assert(n != null);
+ X.Add(n);
+ }
+ bool change = true;
+ while (change)
+ // invariant: X = V - S
+ {
+ change = false;
+ if (X.Count > 0) {
+ foreach (Node/*!*/ n in X) {
+ Contract.Assert(n != null);
+ // see if n has any incoming edges from any other node in X
+ bool inDegreeZero = true;
+ foreach (Node/*!*/ u in X) {
+ Contract.Assert(u != null);
+ if (this.Edge(u, n)) {
+ inDegreeZero = false;
+ break; // no point looking further
+ }
+ }
+ if (inDegreeZero) {
+ S.Add(n);
+ X.Remove(n);
+ change = true;
+ break; // might as well go back and start looking through X from the beginning
+ }
+ }
+ // Then we made it all the way through X without finding a source node
+ if (!change) {
+ return new Tuple<bool, List<Node>>(false, new List<Node>());
+ }
+ }
+ }
+ return new Tuple<bool, List<Node>>(true, S);
+ }
+
+ public static bool Acyclic(Graph<Node> g, Node source) {
+ bool acyclic;
+ List<Node> sortedList;
+ g.TarjanTopSort(out acyclic, out sortedList);
+ return acyclic;
+ }
+
+ // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
+ static HashSet<Node> NaturalLoop(Graph<Node> g, Tuple<Node/*!*/, Node/*!*/> backEdge)
+ {
+ Contract.Requires(backEdge.Item1 != null && backEdge.Item2 != null);
+ Node/*!*/ n = backEdge.Item1;
+ Node/*!*/ d = backEdge.Item2;
+ Stack<Node> stack = new Stack<Node>();
+ HashSet<Node> loop = new HashSet<Node>();
+ loop.Add(d);
+ if (!n.Equals(d)) // then n is not in loop
+ {
+ loop.Add(n);
+ stack.Push(n); // push n onto stack
+ }
+ while (stack.Count > 0) // not empty
+ {
+ Node m = stack.Peek();
+ stack.Pop(); // pop stack
+ foreach (Node/*!*/ p in g.Predecessors(m)) {
+ Contract.Assert(p != null);
+ if (!(loop.Contains(p))) {
+ loop.Add(p);
+ stack.Push(p); // push p onto stack
+ }
+ }
+ }
+ return loop;
+ }
+
+ internal struct ReducibleResult {
+ internal bool reducible;
+ internal HashSet<Node> headers;
+ internal Dictionary<Node, HashSet<Node>> backEdgeNodes;
+ internal Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
+ internal HashSet<Node> splitCandidates;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Contract.ForAll(naturalLoops.Keys, p => p.Item1 != null && p.Item2 != null));
+ }
+
+ internal ReducibleResult(bool b, HashSet<Node> headers, Dictionary<Node, HashSet<Node>> backEdgeNodes, Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops, HashSet<Node> splitCandidates)
+ {
+ Contract.Requires(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, Key => Key.Item1 != null && Key.Item2 != null));
+ this.reducible = b;
+ this.headers = headers;
+ this.backEdgeNodes = backEdgeNodes;
+ this.naturalLoops = naturalLoops;
+ this.splitCandidates = splitCandidates;
+ }
+
+ }
+
+ // [Dragon, p. 606]
+ static ReducibleResult ComputeReducible(Graph<Node> g, Node source) {
+ // first, compute the dom relation
+ DomRelation<Node> /*Map<Node,Set<Node>>*/ D = g.DominatorMap;
+ return ComputeReducible(g, source, D);
+ }
+
+ static HashSet<Node> FindCycle(Graph<Node> g, Node source) {
+ Stack<Tuple<Node, List<Node>>> stack = new Stack<Tuple<Node, List<Node>>>();
+ HashSet<Node> stackAsSet = new HashSet<Node>();
+ HashSet<Node> visited = new HashSet<Node>();
+ stack.Push(new Tuple<Node, List<Node>>(source, g.SuccessorsAsList(source)));
+ stackAsSet.Add(source);
+ while (stack.Count > 0) {
+ Tuple<Node, List<Node>> tuple = stack.Peek();
+ List<Node> children = tuple.Item2;
+ if (children.Count == 0) {
+ stack.Pop();
+ stackAsSet.Remove(tuple.Item1);
+ continue;
+ }
+ Node n = children[0];
+ children.RemoveAt(0);
+ if (stackAsSet.Contains(n)) {
+ HashSet<Node> ret = new HashSet<Node>();
+ ret.Add(n);
+ while (true) {
+ Node x = stack.Pop().Item1;
+ if (x.Equals(n))
+ return ret;
+ }
+ }
+ if (visited.Contains(n))
+ continue;
+ stack.Push(new Tuple<Node, List<Node>>(n, g.SuccessorsAsList(n)));
+ visited.Add(n);
+ stackAsSet.Add(n);
+ System.Diagnostics.Debug.Assert(stack.Count == stackAsSet.Count);
+ }
+ return new HashSet<Node>();
+ }
+
+ // [Dragon, p. 606]
+ static ReducibleResult ComputeReducible(Graph<Node> g,
+ Node source,
+ DomRelation<Node>/*!*/ DomRelation) {
+ Contract.Requires(DomRelation != null);
+
+ //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible");
+ IEnumerable<Tuple<Node/*!*/, Node/*!*/>> edges = g.Edges;
+ Contract.Assert(Contract.ForAll(edges, n => n.Item1 != null && n.Item2 != null));
+ HashSet<Tuple<Node/*!*/, Node/*!*/>> backEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
+ HashSet<Tuple<Node/*!*/, Node/*!*/>> nonBackEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in edges) {
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ Node x = e.Item1;
+ Node y = e.Item2; // so there is an edge from x to y
+ if (DomRelation.DominatedBy(x, y)) { // y dom x: which means y dominates x
+ backEdges.Add(e);
+ } else {
+ nonBackEdges.Add(e);
+ }
+ }
+ Graph<Node> withoutBackEdges = new Graph<Node>(nonBackEdges);
+ if (!Acyclic(withoutBackEdges, source)) {
+ return new ReducibleResult(false,
+ new HashSet<Node>(),
+ new Dictionary<Node, HashSet<Node>>(),
+ new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(),
+ FindCycle(withoutBackEdges, source));
+ } else {
+ // original A#:
+ //Set<Node> headers = Set{ d : <n,d> in backEdges };
+ HashSet<Node> headers = new HashSet<Node>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
+
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ headers.Add(e.Item2);
+ }
+ // original A#:
+ //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
+ Dictionary<Node, HashSet<Node>> backEdgeNodes = new Dictionary<Node, HashSet<Node>>();
+ foreach (Node/*!*/ h in headers) {
+ Contract.Assert(h != null);
+ HashSet<Node> bs = new HashSet<Node>();
+ foreach (Tuple<Node, Node> backedge in backEdges) {
+ Contract.Assert(backedge.Item1 != null);
+ Contract.Assert(backedge.Item2 != null);
+ if (backedge.Item2.Equals(h)) {
+ bs.Add(backedge.Item1);
+ }
+ }
+ backEdgeNodes.Add(h, bs);
+ }
+
+ // original A#:
+ //Map<Tuple<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
+ Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops = new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>();
+ foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
+ Contract.Assert(e.Item1 != null && e.Item2 != null);
+ naturalLoops.Add(e, NaturalLoop(g, e));
+ }
+
+ //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible");
+ return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops, new HashSet<Node>());
+ }
+ }
+
+ public bool Reducible {
+ get {
+ return reducible;
+ }
+ }
+ public IEnumerable<Node> Headers {
+ get {
+ return headers;
+ }
+ }
+ public IEnumerable<Node> BackEdgeNodes(Node/*!*/ h) {
+ Contract.Requires(h != null);
+ // original A#:
+ //return h in backEdgeNodes ? backEdgeNodes[h] : null;
+ return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new List<Node>());
+ }
+ public IEnumerable<Node> NaturalLoops(Node/*!*/ header, Node/*!*/ backEdgeNode) {
+ Contract.Requires(header != null);
+ Contract.Requires(backEdgeNode != null);
+ Tuple<Node/*!*/, Node/*!*/> e = new Tuple<Node/*!*/, Node/*!*/>(backEdgeNode, header);
+ return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new List<Node>();
+ }
+ public HashSet<Node> SplitCandidates {
+ get {
+ return splitCandidates;
+ }
+ }
+ public void ComputeLoops() {
+ ReducibleResult r = ComputeReducible(this, this.source);
+ this.reducible = r.reducible;
+ this.headers = r.headers;
+ this.backEdgeNodes = r.backEdgeNodes;
+ this.naturalLoops = r.naturalLoops;
+ this.splitCandidates = r.splitCandidates;
+ return;
+ }
+
+ public IEnumerable<Node> SortHeadersByDominance()
+ {
+ Graph<Node> dag = new Graph<Node>();
+ foreach (Node b in headers)
+ {
+ dag.AddSource(b);
+ foreach (Node c in headers)
+ {
+ if (b.Equals(c)) continue;
+ if (DominatorMap.DominatedBy(b, c))
+ {
+ System.Diagnostics.Debug.Assert(!DominatorMap.DominatedBy(c, b));
+ dag.AddEdge(b, c);
+ }
+ }
+ }
+ return dag.TopologicalSort();
+ }
+
+ public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) {
+ NodeLabel = NodeLabel ?? (n => n.ToString());
+ NodeStyle = NodeStyle ?? (n => "[shape=box]");
+ var s = new StringBuilder();
+ s.AppendLine("digraph G {");
+ foreach (var n in Nodes)
+ s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";");
+ foreach (var e in Edges)
+ s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";");
+ s.AppendLine("}");
+ return s.ToString();
+ }
+
+ public ICollection<Node> ComputeReachable() {
+ ICollection<Node> result = new HashSet<Node>();
+ Stack<Node> stack = new Stack<Node>();
+ stack.Push(source);
+ while(!(stack.Count() == 0)) {
+ Node n = stack.Pop();
+ result.Add(n);
+ foreach(var m in Successors(n)) {
+ if(!result.Contains(m)) {
+ stack.Push(m);
+ }
+ }
+ }
+ return result;
+ }
+
+ } // end: class Graph
+
+ public static class GraphAlgorithms
+ {
+
+
+ public static Graph<Node> Dual<Node>(this Graph<Node> g, Node dummySource)
+ {
+ var exits = g.Nodes.Where(n => g.Successors(n).Count() == 0).ToList();
+ Node source;
+ if (exits.Count == 0)
+ exits.Add(dummySource);
+ var dual = new Graph<Node>(new HashSet<Tuple<Node, Node>>(g.Edges.Select(e => new Tuple<Node, Node>(e.Item2, e.Item1))));
+ if (exits.Count == 1)
+ {
+ dual.AddSource(exits[0]);
+ source = exits[0];
+ }
+ else
+ {
+ dual.AddSource(dummySource);
+ source = dummySource;
+ foreach (var exit in exits)
+ dual.AddEdge(dummySource, exit);
+ }
+
+ #region Dual graph may not be connected, so add an edge from the dual graph's soure node to any unreachable node
+ foreach (var n in dual.Nodes.Where(Item => !dual.ComputeReachable().Contains(Item)))
+ {
+ dual.AddEdge(source, n);
+ }
+ #endregion
+
+ return dual;
+ }
+
+ public static List<Tuple<Node, bool>> LoopyTopSort<Node>(this Graph<Node> g)
+ {
+ Contract.Assert(g.Reducible);
+
+ int n = g.Nodes.Count;
+ var nodeToNumber = new Dictionary<Node, int>(n);
+ var numberToNode = new Node[n];
+ var allNodes = new List<int>();
+ int counter = 0;
+ foreach (Node node in g.Nodes)
+ {
+ numberToNode[counter] = node;
+ nodeToNumber[node] = counter;
+ allNodes.Add(counter);
+ counter++;
+ }
+
+ var loops = new List<int>[n];
+ foreach (var h in g.Headers)
+ {
+ var loopNodes = new HashSet<Node>();
+ foreach (var b in g.BackEdgeNodes(h))
+ loopNodes.UnionWith(g.NaturalLoops(h, b));
+ loops[nodeToNumber[h]] =
+ new List<int>(loopNodes.Select(node => nodeToNumber[node]));
+ }
+
+ var successors = new List<int>[n];
+ var predecessors = new List<int>[n];
+ int[] incomingEdges = new int[n];
+
+ for (int i = 0; i < n; i++)
+ predecessors[i] = new List<int>();
+
+ foreach (var e in g.Edges)
+ {
+ Contract.Assert(e.Item1 != null);
+ Contract.Assert(e.Item2 != null);
+ int source = nodeToNumber[e.Item1], target = nodeToNumber[e.Item2];
+ if (loops[target] == null || !loops[target].Contains(source))
+ {
+ if (successors[source] == null)
+ successors[source] = new List<int>();
+ successors[source].Add(target);
+ incomingEdges[target]++;
+ }
+ predecessors[target].Add(source);
+ }
+
+ var sortedNodes = new List<Tuple<Node, bool>>();
+ var sortedNodesInternal = new List<int>();
+
+ var regionStack = new Stack<Tuple<Node, List<int>>>();
+ regionStack.Push(new Tuple<Node, List<int>>(default(Node), allNodes));
+
+ while (regionStack.Count != 0)
+ {
+ var rootIndexes = new List<int>();
+ foreach (var i in regionStack.Peek().Item2)
+ {
+ if (incomingEdges[i] == 0)
+ rootIndexes.Add(i);
+ }
+ if (rootIndexes.Count() == 0)
+ {
+ var region = regionStack.Pop();
+ if (regionStack.Count != 0) {
+ sortedNodes.Add(new Tuple<Node, bool>(region.Item1, true));
+ sortedNodesInternal.Add(nodeToNumber[region.Item1]);
+ }
+ continue;
+ }
+ int rootIndex = rootIndexes[0];
+ int maxPredIndex = -1;
+ foreach (var i in rootIndexes) {
+ foreach (var p in predecessors[i]) {
+ int predIndex =
+ sortedNodesInternal.FindLastIndex(x => x == p);
+ if (predIndex > maxPredIndex) {
+ rootIndex = i;
+ maxPredIndex = predIndex;
+ }
+ }
+ }
+ incomingEdges[rootIndex] = -1;
+ sortedNodes.Add(new Tuple<Node, bool>(numberToNode[rootIndex], false));
+ sortedNodesInternal.Add(rootIndex);
+ if (successors[rootIndex] != null)
+ foreach (int s in successors[rootIndex])
+ incomingEdges[s]--;
+ if (loops[rootIndex] != null)
+ regionStack.Push(new Tuple<Node, List<int>>(numberToNode[rootIndex],
+ loops[rootIndex]));
+ }
+
+ return sortedNodes;
+ }
+
+ // Algorithm from Jeanne Ferrante, Karl J. Ottenstein, Joe D. Warren,
+ // "The Program Dependence Graph and Its Use in Optimization"
+ public static Dictionary<Node, HashSet<Node>> ControlDependence<Node>(this Graph<Node> g) where Node : class, new()
+ {
+ Graph<Node> dual = g.Dual(new Node());
+ DomRelation<Node> pdom = dual.DominatorMap;
+
+ var result = new Dictionary<Node, HashSet<Node>>();
+
+ var S = g.Edges.Where(e => !pdom.DominatedBy(e.Item1, e.Item2));
+ foreach (var edge in S)
+ {
+ var L = pdom.LeastCommonAncestor(edge.Item1, edge.Item2);
+ var deps = new List<Node>();
+ if (L == edge.Item1)
+ {
+ pdom.DominatedBy(edge.Item2, edge.Item1, deps);
+ deps.Add(edge.Item2);
+ deps.Add(edge.Item1);
+ }
+ else
+ {
+ pdom.DominatedBy(edge.Item2, L, deps);
+ deps.Add(edge.Item2);
+ }
+ if (result.ContainsKey(edge.Item1))
+ {
+ result[edge.Item1].UnionWith(deps);
+ }
+ else
+ {
+ result[edge.Item1] = new HashSet<Node>(deps);
+ }
+ }
+
+ return result;
+ }
+
+ public static void TransitiveClosure<Node>(this Dictionary<Node, HashSet<Node>> graph) where Node : class {
+ bool changed;
+ do {
+ changed = false;
+ foreach (var entry in graph) {
+ var newSuccessors = new HashSet<Node>(entry.Value);
+ foreach (var successor in entry.Value) {
+ if (graph.ContainsKey(successor))
+ newSuccessors.UnionWith(graph[successor]);
+ }
+ if (newSuccessors.Count != entry.Value.Count) {
+ entry.Value.UnionWith(newSuccessors);
+ changed = true;
+ }
+ }
+ } while (changed);
+ }
+
+ }
+
+ public delegate System.Collections.IEnumerable/*<Node!>*//*!*/ Adjacency<T>(T/*!*/ node);
+
+
+ // An SCC is a set of nodes
+ public sealed class SCC<Node> : ICollection<Node>
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(nodesMap != null);
+ }
+
+ private IDictionary<Node, object>/*!*/ nodesMap = new Dictionary<Node, object>();
+ private ICollection<Node>/*!*/ nodes
+ {
+ get
+ {
+ return cce.NonNull(nodesMap.Keys);
+ }
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
+ {
+ Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
+
+ return ((System.Collections.IEnumerable)nodes).GetEnumerator();
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator<Node>/*!*/ IEnumerable<Node>.GetEnumerator()
+ {
+ Contract.Ensures(Contract.Result<IEnumerator<Node>>() != null);
+
+ return ((IEnumerable<Node>)nodes).GetEnumerator();
+ }
+
+ public int Count
+ {
+ get
+ {
+ return nodes.Count;
+ }
+ }
+ public bool IsReadOnly
+ {
+ get
+ {
+ return nodesMap.IsReadOnly;
+ }
+ }
+ public void Add(Node item)
+ {
+ nodesMap.Add(item, null);
+ }
+ public void Clear()
+ {
+ nodesMap.Clear();
+ }
+ [Pure]
+ public bool Contains(Node item)
+ {
+ return nodesMap.ContainsKey(item);
+ }
+ public void CopyTo(Node[] array, int arrayIndex)
+ {
+ //Contract.Requires(array != null);
+ nodes.CopyTo(array, arrayIndex);
+ }
+ public bool Remove(Node item)
+ {
+ return nodesMap.Remove(item);
+ }
+ }
+
+ public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>/*!*/> where Node : class
+ {
+ private readonly IDictionary<Node/*!*/, object>/*!*/ graph;
+ [ContractInvariantMethod]
+ void graphInvariantMethod()
+ {
+ Contract.Invariant(Contract.ForAll(graph, entry => entry.Key != null));
+ Contract.Invariant(preds != null);
+ Contract.Invariant(succs != null);
+ }
+ private readonly Adjacency<Node>/*!*/ preds;
+ private readonly Adjacency<Node>/*!*/ succs;
+
+ private bool computed = false;
+ public bool Computed
+ {
+ get
+ {
+ return computed;
+ }
+ }
+
+ [NotDelayed]
+ public StronglyConnectedComponents(System.Collections.IEnumerable/*<Node!>*/ graph, Adjacency<Node> preds, Adjacency<Node> succs)
+ : base()
+ {
+ Contract.Requires(succs != null);
+ Contract.Requires(preds != null);
+ Contract.Requires(graph != null);
+ Contract.Ensures(!Computed);
+ IDictionary<Node/*!*/, object>/*!*/ dict = new Dictionary<Node/*!*/, object>();
+ foreach (Node/*!*/ n in graph)
+ {
+ Contract.Assert(n != null);
+ dict.Add(n, null);
+ }
+
+ this.graph = dict;
+ this.preds = preds;
+ this.succs = succs;
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
+ {
+ Contract.Ensures(Contract.Result<System.Collections.IEnumerator>() != null);
+
+ return ((System.Collections.IEnumerable)sccs).GetEnumerator();
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator<SCC<Node>/*!*/>/*!*/ IEnumerable<SCC<Node>/*!*/>.GetEnumerator()
+ {
+ Contract.Ensures(Contract.Result<IEnumerator<SCC<Node>>>() != null);
+
+ Contract.Assume(Computed);
+ Contract.Assert(cce.NonNullElements((IEnumerable<SCC<Node>/*!*/>)sccs));//REVIEW
+ return ((IEnumerable<SCC<Node>/*!*/>)sccs).GetEnumerator();
+ }
+
+ private readonly IList<SCC<Node>/*!*/>/*!*/ sccs = new List<SCC<Node>/*!*/>();
+ [ContractInvariantMethod]
+ void sccsInvariant()
+ {
+ Contract.Invariant(cce.NonNullElements(sccs));
+ }
+
+
+ public void Compute()
+ {
+ Contract.Requires(!Computed);
+ Contract.Ensures(Computed);
+ // Compute post times on graph with edges reversed
+ this.dfsNext = this.preds;
+ foreach (Node/*!*/ n in cce.NonNull(graph.Keys))
+ {
+ Contract.Assert(n != null);
+ if (!seen.ContainsKey(n))
+ {
+ OrderNodes(n);
+ }
+ }
+
+ // Clear seen
+ seen.Clear();
+
+ // Compute SCCs
+ this.dfsNext = this.succs;
+ while (postOrder.Count > 0)
+ {
+ Node/*!*/ n = postOrder.Pop();
+ Contract.Assert(n != null);
+
+ if (!seen.ContainsKey(n))
+ {
+ SCC<Node>/*!*/ curr = new SCC<Node>();
+ FindSCCs(n, curr);
+ sccs.Add(curr);
+ }
+ }
+
+ // Clear seen
+ seen.Clear();
+
+ this.computed = true;
+ }
+
+ private Adjacency<Node>/*?*/ dfsNext = null;
+
+ private readonly IDictionary<Node/*!*/, object>/*!*/ seen = new Dictionary<Node/*!*/, object>();
+ private readonly Stack<Node/*!*/>/*!*/ postOrder = new Stack<Node/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(seen != null);
+ Contract.Invariant(cce.NonNullElements(postOrder));
+ }
+
+
+ // DFS to order nodes by post times
+ private void OrderNodes(Node node)
+ {
+ Contract.Requires(node != null);
+ seen.Add(node, null);
+
+ Contract.Assert(dfsNext != null);
+ System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
+ Contract.Assert(nexts != null);
+ foreach (Node/*!*/ n in nexts)
+ {
+ Contract.Assert(n != null);
+ if (graph.ContainsKey(n) && !seen.ContainsKey(n))
+ {
+ OrderNodes(n);
+ }
+ }
+
+ postOrder.Push(node);
+ }
+
+ // DFS to compute SCCs
+ private void FindSCCs(Node node, SCC<Node> currSCC)
+ {
+ Contract.Requires(currSCC != null);
+ Contract.Requires(node != null);
+ //modifies currSCC.*;
+ seen.Add(node, null);
+ currSCC.Add(node);
+
+ Contract.Assert(dfsNext != null);
+ System.Collections.IEnumerable/*!*/ nexts = dfsNext(node);
+ Contract.Assert(nexts != null);
+ foreach (Node/*!*/ n in nexts)
+ {
+ Contract.Assert(n != null);
+ if (graph.ContainsKey(n) && !seen.ContainsKey(n))
+ {
+ FindSCCs(n, currSCC);
+ }
+ }
+ }
+
+ [Pure]
+ public override string ToString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string outStr = "";
+ int i = 0;
+
+ foreach (ICollection<Node> component in this)
+ {
+ string/*!*/ tmp = System.String.Format("\nComponent #{0} = ", i++);
+ Contract.Assert(tmp != null);
+ outStr += tmp;
+
+ bool firstInRow = true;
+
+ foreach (Node b in component)
+ {
+ string/*!*/ tmpComponent = System.String.Format("{0}{1}", firstInRow ? "" : ", ", b);
+ Contract.Assert(tmpComponent != null);
+ outStr += tmpComponent;
+ firstInRow = false;
+ }
+ }
+ return outStr;
+ }
+
+ }
+
+ public class GraphProgram {
+ static void TestGraph<T>(T/*!*/ source, params Tuple<T/*!*/, T/*!*/>[] edges) {
+ Contract.Requires(source != null);
+ Contract.Requires(Contract.ForAll(edges, pair => pair.Item1 != null && pair.Item2 != null));
+ HashSet<Tuple<T/*!*/, T/*!*/>> es = new HashSet<Tuple<T/*!*/, T/*!*/>>();
+ foreach (Tuple<T/*!*/, T/*!*/> e in edges) {
+ Contract.Assert(e.Item1 != null && e.Item2 != null);
+ es.Add(e);
+ }
+ Graph<T> g = new Graph<T>(es);
+ g.AddSource(source);
+ Console.WriteLine("G = " + g);
+ g.ComputeLoops();
+ Console.WriteLine("G's Dominator Map = " + g.DominatorMap);
+ Console.WriteLine("G's Immediate Dominator Map = " + Util.MapToString(g.ImmediateDominatorMap));
+ Console.WriteLine("G is reducible: " + (g.Reducible ? "yes" : "no"));
+ }
+
+ static void Main(string[] args)
+ //requires forall{string s in args; s != null};
+ {
+ Console.WriteLine("Spec# says hello!");
+ // This generates bad IL -- need to fix a bug in the compiler
+ //Graph<int> g = new Graph<int>(new Set<Tuple<int,int>>{ new Tuple<int,int>(1,2), new Tuple<int,int>(1,3), new Tuple<int,int>(2,3) });
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'c')
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'd'),
+ new Tuple<char, char>('c', 'e'),
+ new Tuple<char, char>('c', 'f'),
+ new Tuple<char, char>('d', 'e'),
+ new Tuple<char, char>('e', 'd'),
+ new Tuple<char, char>('e', 'f'),
+ new Tuple<char, char>('f', 'e')
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'c'),
+ new Tuple<char, char>('c', 'b')
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(1,
+ new Tuple<int, int>(1, 2),
+ new Tuple<int, int>(1, 3),
+ new Tuple<int, int>(2, 3)
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(1,
+ new Tuple<int, int>(1, 2),
+ new Tuple<int, int>(1, 3),
+ new Tuple<int, int>(2, 3),
+ new Tuple<int, int>(3, 2)
+ );
+
+ Console.WriteLine("");
+ TestGraph<int>(2,
+ new Tuple<int, int>(2, 3),
+ new Tuple<int, int>(2, 4),
+ new Tuple<int, int>(3, 2)
+ );
+
+ Console.WriteLine("");
+ TestGraph<char>('a',
+ new Tuple<char, char>('a', 'b'),
+ new Tuple<char, char>('a', 'c'),
+ new Tuple<char, char>('b', 'c'),
+ new Tuple<char, char>('b', 'b')
+ );
+
+
+ }
+ }
+
+}
diff --git a/Source/Graph/Graph.csproj b/Source/Graph/Graph.csproj
index b4adf6e4..7e610d46 100644
--- a/Source/Graph/Graph.csproj
+++ b/Source/Graph/Graph.csproj
@@ -1,199 +1,199 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Graph</RootNamespace>
- <AssemblyName>Graph</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Graph.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Graph.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="Graph.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Graph</RootNamespace>
+ <AssemblyName>BoogieGraph</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for Graph.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Graph.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="Graph.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Source/Graph/cce.cs b/Source/Graph/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/Graph/cce.cs
+++ b/Source/Graph/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/Houdini/AbstractHoudini.cs b/Source/Houdini/AbstractHoudini.cs
index de3d3779..e3625dcc 100644
--- a/Source/Houdini/AbstractHoudini.cs
+++ b/Source/Houdini/AbstractHoudini.cs
@@ -1,4609 +1,4714 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using VC;
-using Outcome = VC.VCGen.Outcome;
-using Bpl = Microsoft.Boogie;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie.Houdini {
-
- public class AbsHoudini
- {
- Dictionary<string, Function> existentialFunctions;
- Program program;
- Dictionary<string, Implementation> name2Impl;
- Dictionary<string, VCExpr> impl2VC;
- Dictionary<string, List<Tuple<string, Function, NAryExpr>>> impl2FuncCalls;
- // constant -> the naryexpr that it replaced
- Dictionary<string, NAryExpr> constant2FuncCall;
-
- // function -> its abstract value
- Dictionary<string, IAbstractDomain> function2Value;
-
- // impl -> functions assumed/asserted
- Dictionary<string, HashSet<string>> impl2functionsAsserted, impl2functionsAssumed;
-
- // funtions -> impls where assumed/asserted
- Dictionary<string, HashSet<string>> function2implAssumed, function2implAsserted;
-
- // impl -> handler, collector
- Dictionary<string, Tuple<ProverInterface.ErrorHandler, AbsHoudiniCounterexampleCollector>> impl2ErrorHandler;
-
- // Essentials: VCGen, Prover
- VCGen vcgen;
- ProverInterface prover;
-
- // Stats
- TimeSpan proverTime;
- int numProverQueries;
-
- public AbsHoudini(Program program, IAbstractDomain defaultElem)
- {
- this.program = program;
- this.impl2VC = new Dictionary<string, VCExpr>();
- this.impl2FuncCalls = new Dictionary<string, List<Tuple<string, Function, NAryExpr>>>();
- this.existentialFunctions = new Dictionary<string, Function>();
- this.name2Impl = new Dictionary<string, Implementation>();
- this.impl2functionsAsserted = new Dictionary<string, HashSet<string>>();
- this.impl2functionsAssumed = new Dictionary<string, HashSet<string>>();
- this.function2implAsserted = new Dictionary<string, HashSet<string>>();
- this.function2implAssumed = new Dictionary<string, HashSet<string>>();
- this.impl2ErrorHandler = new Dictionary<string, Tuple<ProverInterface.ErrorHandler, AbsHoudiniCounterexampleCollector>>();
- this.constant2FuncCall = new Dictionary<string, NAryExpr>();
-
- // Find the existential functions
- foreach (var func in program.Functions
- .Where(f => QKeyValue.FindBoolAttribute(f.Attributes, "existential")))
- existentialFunctions.Add(func.Name, func);
-
- this.function2Value = new Dictionary<string, IAbstractDomain>();
- foreach (var func in existentialFunctions.Values)
- {
- // Find if the function wishes to use a specific abstract domain
- var domain = QKeyValue.FindStringAttribute(func.Attributes, "absdomain");
- if (domain == null)
- {
- function2Value[func.Name] = defaultElem.Bottom();
- }
- else
- {
- function2Value[func.Name] = AbstractDomainFactory.GetInstance(domain);
- }
- }
- existentialFunctions.Keys.Iter(f => function2implAssumed.Add(f, new HashSet<string>()));
- existentialFunctions.Keys.Iter(f => function2implAsserted.Add(f, new HashSet<string>()));
-
- // type check
- existentialFunctions.Values.Iter(func =>
- {
- if (func.OutParams.Count != 1 || !func.OutParams[0].TypedIdent.Type.IsBool)
- throw new AbsHoudiniInternalError(string.Format("Existential function {0} must return bool", func.Name));
- if(func.Body != null)
- throw new AbsHoudiniInternalError(string.Format("Existential function {0} should not have a body", func.Name));
- var args = new List<Type>();
- func.InParams.Iter(v => args.Add(v.TypedIdent.Type));
- string msg = "";
- if (!function2Value[func.Name].TypeCheck(args, out msg))
- throw new AbsHoudiniInternalError("TypeError: " + msg);
- });
-
- //if (CommandLineOptions.Clo.ProverKillTime > 0)
- // CommandLineOptions.Clo.ProverOptions.Add(string.Format("TIME_LIMIT={0}", CommandLineOptions.Clo.ProverKillTime));
-
- Inline();
-
- this.vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List<Checker>());
- this.prover = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, CommandLineOptions.Clo.ProverKillTime);
-
- this.proverTime = TimeSpan.Zero;
- this.numProverQueries = 0;
-
- program.Implementations
- .Where(impl => !impl.SkipVerification)
- .Iter(impl => name2Impl.Add(impl.Name, impl));
-
- // Let's do VC Gen (and also build dependencies)
- name2Impl.Values.Iter(GenVC);
- }
-
- public VCGenOutcome ComputeSummaries()
- {
- var overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Valid, new List<Counterexample>());
-
- // Compute SCCs and determine a priority order for impls
- var Succ = new Dictionary<string, HashSet<string>>();
- var Pred = new Dictionary<string, HashSet<string>>();
- name2Impl.Keys.Iter(s => Succ[s] = new HashSet<string>());
- name2Impl.Keys.Iter(s => Pred[s] = new HashSet<string>());
-
- foreach(var impl in name2Impl.Keys) {
- Succ[impl] = new HashSet<string>();
- impl2functionsAsserted[impl].Iter(f =>
- function2implAssumed[f].Iter(succ =>
- {
- Succ[impl].Add(succ);
- Pred[succ].Add(impl);
- }));
- }
-
- var sccs = new StronglyConnectedComponents<string>(name2Impl.Keys,
- new Adjacency<string>(n => Pred[n]),
- new Adjacency<string>(n => Succ[n]));
- sccs.Compute();
-
- // impl -> priority
- var impl2Priority = new Dictionary<string, int>();
- int p = 0;
- foreach (var scc in sccs)
- {
- foreach (var impl in scc)
- {
- impl2Priority.Add(impl, p);
- p++;
- }
- }
-
- var worklist = new SortedSet<Tuple<int, string>>();
- name2Impl.Keys.Iter(k => worklist.Add(Tuple.Create(impl2Priority[k], k)));
-
- while (worklist.Any())
- {
- var impl = worklist.First().Item2;
- worklist.Remove(worklist.First());
-
- var gen = prover.VCExprGen;
- var terms = new List<Expr>();
- foreach (var tup in impl2FuncCalls[impl])
- {
- var controlVar = tup.Item2;
- var exprVars = tup.Item3;
- var varList = new List<Expr>();
- exprVars.Args.OfType<Expr>().Iter(v => varList.Add(v));
-
- var args = new List<Expr>();
- controlVar.InParams.Iter(v => args.Add(Expr.Ident(v)));
- Expr term = Expr.Eq(new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args),
- function2Value[tup.Item1].Gamma(varList));
-
- if (controlVar.InParams.Count != 0)
- {
- term = new ForallExpr(Token.NoToken, new List<Variable>(controlVar.InParams.ToArray()),
- new Trigger(Token.NoToken, true, new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args) }),
- term);
- }
- terms.Add(term);
- }
- var env = Expr.BinaryTreeAnd(terms);
-
- env.Typecheck(new TypecheckingContext((IErrorSink)null));
- var envVC = prover.Context.BoogieExprTranslator.Translate(env);
-
- var vc = gen.Implies(envVC, impl2VC[impl]);
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Verifying {0}: ", impl);
- //Console.WriteLine("env: {0}", envVC);
- var envFuncs = new HashSet<string>();
- impl2FuncCalls[impl].Iter(tup => envFuncs.Add(tup.Item1));
- envFuncs.Iter(f => PrintFunction(existentialFunctions[f]));
- }
-
- var handler = impl2ErrorHandler[impl].Item1;
- var collector = impl2ErrorHandler[impl].Item2;
- collector.Reset(impl);
-
- var start = DateTime.Now;
-
- prover.Push();
- prover.Assert(gen.Not(vc), true);
- prover.FlushAxiomsToTheoremProver();
- prover.Check();
- ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);
-
- //prover.BeginCheck(impl, vc, handler);
- //ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);
-
- var inc = (DateTime.Now - start);
- proverTime += inc;
- numProverQueries++;
-
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Time taken = " + inc.TotalSeconds.ToString());
-
- if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
- {
- // pick some function; make it true and keep going
- bool changed = false;
- foreach (var f in impl2functionsAsserted[impl])
- {
- function2Value[f] = function2Value[f].MakeTop(out changed);
- if (changed) break;
- }
- if(!changed)
- return new VCGenOutcome(proverOutcome, new List<Counterexample>());
- }
-
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine(collector.numErrors > 0 ? "SAT" : "UNSAT");
-
- if (collector.numErrors > 0)
- {
- var funcsChanged = collector.funcsChanged;
- if (funcsChanged.Count == 0)
- {
- overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.errors);
- break;
- }
-
- // propagate dependent guys back into the worklist, including self
- var deps = new HashSet<string>();
- deps.Add(impl);
- funcsChanged.Iter(f => deps.UnionWith(function2implAssumed[f]));
-
- deps.Iter(s => worklist.Add(Tuple.Create(impl2Priority[s], s)));
- }
-
- prover.Pop();
- }
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Prover time = {0}", proverTime.TotalSeconds.ToString("F2"));
- Console.WriteLine("Number of prover queries = " + numProverQueries);
- }
-
- if (CommandLineOptions.Clo.PrintAssignment)
- {
- // Print the answer
- existentialFunctions.Values.Iter(PrintFunction);
- }
-
- return overallOutcome;
- }
-
-
- public IEnumerable<Function> GetAssignment()
- {
- var ret = new List<Function>();
- foreach (var func in existentialFunctions.Values)
- {
- var invars = new List<Expr>(func.InParams.OfType<Variable>().Select(v => Expr.Ident(v)));
- func.Body = function2Value[func.Name].Gamma(invars);
- ret.Add(func);
- }
- return ret;
- }
-
- private void PrintFunction(Function function)
- {
- var tt = new TokenTextWriter(Console.Out, /*pretty=*/ false);
- var invars = new List<Expr>(function.InParams.OfType<Variable>().Select(v => Expr.Ident(v)));
- function.Body = function2Value[function.Name].Gamma(invars);
- function.Emit(tt, 0);
- tt.Close();
- }
-
- public HashSet<string> HandleCounterExample(string impl, Counterexample error)
- {
- var funcsChanged = new HashSet<string>();
- // Find the failing assert -- need to do a join there
- // return the set of functions whose definition has changed
- var cex = ExtractState(impl, error);
- foreach (var tup in cex)
- {
- function2Value[tup.Item1] = function2Value[tup.Item1].Join(tup.Item2);
- funcsChanged.Add(tup.Item1);
- }
- return funcsChanged;
- }
-
- private List<Tuple<string, List<Model.Element>>> ExtractState(string impl, Counterexample error)
- {
- var lastBlock = error.Trace.Last() as Block;
- AssertCmd failingAssert = null;
-
- CallCounterexample callCounterexample = error as CallCounterexample;
- if (callCounterexample != null)
- {
- Procedure failingProcedure = callCounterexample.FailingCall.Proc;
- Requires failingRequires = callCounterexample.FailingRequires;
- failingAssert = lastBlock.Cmds.OfType<AssertRequiresCmd>().FirstOrDefault(ac => ac.Requires == failingRequires);
- }
- ReturnCounterexample returnCounterexample = error as ReturnCounterexample;
- if (returnCounterexample != null)
- {
- Ensures failingEnsures = returnCounterexample.FailingEnsures;
- failingAssert = lastBlock.Cmds.OfType<AssertEnsuresCmd>().FirstOrDefault(ac => ac.Ensures == failingEnsures);
- }
- AssertCounterexample assertCounterexample = error as AssertCounterexample;
- if (assertCounterexample != null)
- {
- failingAssert = lastBlock.Cmds.OfType<AssertCmd>().FirstOrDefault(ac => ac == assertCounterexample.FailingAssert);
- }
-
- Debug.Assert(failingAssert != null);
- return ExtractState(impl, failingAssert.Expr, error.Model);
- }
-
- private static int existentialConstCounter = 0;
-
- private List<Tuple<string, List<Model.Element>>> ExtractState(string impl, Expr expr, Model model)
- {
- var funcsUsed = FunctionCollector.Collect(expr);
-
- var ret = new List<Tuple<string, List<Model.Element>>>();
-
- foreach (var tup in funcsUsed.Where(t => t.Item2 == null))
- {
- var constant = tup.Item1;
- if (!constant2FuncCall.ContainsKey(constant.Name))
- continue;
-
- var func = constant2FuncCall[constant.Name];
- var funcName = (func.Fun as FunctionCall).FunctionName;
- var vals = new List<Model.Element>();
- prover.Context.BoogieExprTranslator.Translate(func.Args).Iter(ve => vals.Add(getValue(ve, model)));
- ret.Add(Tuple.Create(funcName, vals));
- }
-
- foreach (var tup in funcsUsed.Where(t => t.Item2 != null))
- {
- var constant = tup.Item1;
- var boundExpr = tup.Item2;
-
- if (!constant2FuncCall.ContainsKey(constant.Name))
- continue;
-
- // There are some bound variables (because the existential function was inside an \exists).
- // We must find an assignment for bound varibles
-
- // First, peice apart the existential functions
- var cd = new Duplicator();
- var tup2 = ExistentialExprModelMassage.Massage(cd.VisitExpr(boundExpr.Body));
- var be = tup2.Item1;
- Expr env = Expr.True;
- foreach (var ahFunc in tup2.Item2)
- {
- var tup3 = impl2FuncCalls[impl].First(t => t.Item2.Name == ahFunc.Name);
- var varList = new List<Expr>();
- tup3.Item3.Args.OfType<Expr>().Iter(v => varList.Add(v));
-
- env = Expr.And(env, function2Value[tup3.Item1].Gamma(varList));
- }
- be = Expr.And(be, Expr.Not(env));
-
- // map formals to constants
- var formalToConstant = new Dictionary<string, Constant>();
- foreach (var f in boundExpr.Dummies.OfType<Variable>())
- formalToConstant.Add(f.Name, new Constant(Token.NoToken, new TypedIdent(Token.NoToken, f.Name + "@subst@" + (existentialConstCounter++), f.TypedIdent.Type), false));
- be = Substituter.Apply(new Substitution(v => formalToConstant.ContainsKey(v.Name) ? Expr.Ident(formalToConstant[v.Name]) : Expr.Ident(v)), be);
- formalToConstant.Values.Iter(v => prover.Context.DeclareConstant(v, false, null));
-
- var reporter = new AbstractHoudiniErrorReporter();
- var ve = prover.Context.BoogieExprTranslator.Translate(be);
- prover.Assert(ve, true);
- prover.Check();
- var proverOutcome = prover.CheckOutcomeCore(reporter);
- if (proverOutcome != ProverInterface.Outcome.Invalid)
- continue;
- model = reporter.model;
-
- var func = constant2FuncCall[constant.Name];
- var funcName = (func.Fun as FunctionCall).FunctionName;
- var vals = new List<Model.Element>();
- foreach (var funcArg in func.Args.OfType<Expr>())
- {
- var arg = Substituter.Apply(new Substitution(v => formalToConstant.ContainsKey(v.Name) ? Expr.Ident(formalToConstant[v.Name]) : Expr.Ident(v)), funcArg);
- vals.Add(getValue(prover.Context.BoogieExprTranslator.Translate(arg), model));
- }
- ret.Add(Tuple.Create(funcName, vals));
-
- }
-
- return ret;
- }
-
- private Model.Element getValue(VCExpr arg, Model model)
- {
-
-
- if (arg is VCExprLiteral)
- {
- //return model.GetElement(arg.ToString());
- return model.MkElement(arg.ToString());
- }
-
- else if (arg is VCExprVar)
- {
- var el = model.TryGetFunc(prover.Context.Lookup(arg as VCExprVar));
- if (el != null)
- {
- Debug.Assert(el.Arity == 0 && el.AppCount == 1);
- return el.Apps.First().Result;
- }
- else
- {
- // Variable not defined; assign arbitrary value
- if (arg.Type.IsBool)
- return model.MkElement("false");
- else if (arg.Type.IsInt)
- return model.MkIntElement(0);
- else
- return null;
- }
- }
- else if (arg is VCExprNAry && (arg as VCExprNAry).Op is VCExprBvOp)
- {
- // support for BV constants
- var bvc = (arg as VCExprNAry)[0] as VCExprLiteral;
- if (bvc != null)
- {
- var ret = model.TryMkElement(bvc.ToString() + arg.Type.ToString());
- if (ret != null && (ret is Model.BitVector)) return ret;
- }
- }
-
- var val = prover.Evaluate(arg);
- if (val is int || val is bool || val is Microsoft.Basetypes.BigNum)
- {
- return model.MkElement(val.ToString());
- }
- else
- {
- Debug.Assert(false);
- }
- return null;
- }
-
- // Remove functions AbsHoudiniConstant from the expressions and substitute them with "true"
- class ExistentialExprModelMassage : StandardVisitor
- {
- List<Function> ahFuncs;
-
- public ExistentialExprModelMassage()
- {
- ahFuncs = new List<Function>();
- }
-
- public static Tuple<Expr, List<Function>> Massage(Expr expr)
- {
- var ee = new ExistentialExprModelMassage();
- expr = ee.VisitExpr(expr);
- return Tuple.Create(expr, ee.ahFuncs);
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- if (node.Fun is FunctionCall && (node.Fun as FunctionCall).FunctionName.StartsWith("AbsHoudiniConstant"))
- {
- ahFuncs.Add((node.Fun as FunctionCall).Func);
- return Expr.True;
- }
-
- return base.VisitNAryExpr(node);
- }
- }
-
- class FunctionCollector : ReadOnlyVisitor
- {
- public List<Tuple<Function, ExistsExpr>> functionsUsed;
- ExistsExpr existentialExpr;
-
- public FunctionCollector()
- {
- functionsUsed = new List<Tuple<Function, ExistsExpr>>();
- existentialExpr = null;
- }
-
- public static List<Tuple<Function, ExistsExpr>> Collect(Expr expr)
- {
- var fv = new FunctionCollector();
- fv.VisitExpr(expr);
- return fv.functionsUsed;
- }
-
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
- {
- var oldE = existentialExpr;
-
- if (node is ExistsExpr)
- existentialExpr = (node as ExistsExpr);
-
- node = base.VisitQuantifierExpr(node);
-
- existentialExpr = oldE;
- return node;
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- if (node.Fun is FunctionCall)
- {
- var collector = new VariableCollector();
- collector.Visit(node);
-
- if(existentialExpr != null && existentialExpr.Dummies.Intersect(collector.usedVars).Any())
- functionsUsed.Add(Tuple.Create((node.Fun as FunctionCall).Func, existentialExpr));
- else
- functionsUsed.Add(Tuple.Create<Function, ExistsExpr>((node.Fun as FunctionCall).Func, null));
- }
-
- return base.VisitNAryExpr(node);
- }
- }
-
- class AbsHoudiniCounterexampleCollector : VerifierCallback
- {
- public HashSet<string> funcsChanged;
- public string currImpl;
- public int numErrors;
- public List<Counterexample> errors;
-
- AbsHoudini container;
-
- public AbsHoudiniCounterexampleCollector(AbsHoudini container)
- {
- this.container = container;
- Reset(null);
- }
-
- public void Reset(string impl)
- {
- funcsChanged = new HashSet<string>();
- currImpl = impl;
- numErrors = 0;
- errors = new List<Counterexample>();
- }
-
- public override void OnCounterexample(Counterexample ce, string reason)
- {
- numErrors++;
- errors.Add(ce);
-
- funcsChanged.UnionWith(
- container.HandleCounterExample(currImpl, ce));
- }
- }
-
- private void GenVC(Implementation impl)
- {
- ModelViewInfo mvInfo;
- Dictionary<int, Absy> label2absy;
- var collector = new AbsHoudiniCounterexampleCollector(this);
- collector.OnProgress("HdnVCGen", 0, 0, 0.0);
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Generating VC of {0}", impl.Name);
- }
-
- vcgen.ConvertCFG2DAG(impl);
- var gotoCmdOrigins = vcgen.PassifyImpl(impl, out mvInfo);
-
- // Inline functions
- (new InlineFunctionCalls()).VisitBlockList(impl.Blocks);
-
- ExtractQuantifiedExprs(impl);
- StripOutermostForall(impl);
-
- //CommandLineOptions.Clo.PrintInstrumented = true;
- //var tt = new TokenTextWriter(Console.Out);
- //impl.Emit(tt, 0);
- //tt.Close();
-
- // Intercept the FunctionCalls of the existential functions, and replace them with Boolean constants
- var existentialFunctionNames = new HashSet<string>(existentialFunctions.Keys);
- var fv = new ReplaceFunctionCalls(existentialFunctionNames);
- fv.VisitBlockList(impl.Blocks);
-
- impl2functionsAsserted.Add(impl.Name, fv.functionsAsserted);
- impl2functionsAssumed.Add(impl.Name, fv.functionsAssumed);
-
- fv.functionsAssumed.Iter(f => function2implAssumed[f].Add(impl.Name));
- fv.functionsAsserted.Iter(f => function2implAsserted[f].Add(impl.Name));
-
- impl2FuncCalls.Add(impl.Name, fv.functionsUsed);
- fv.functionsUsed.Iter(tup => constant2FuncCall.Add(tup.Item2.Name, tup.Item3));
-
- var gen = prover.VCExprGen;
- VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : gen.Integer(Microsoft.Basetypes.BigNum.ZERO);
-
- var vcexpr = vcgen.GenerateVC(impl, controlFlowVariableExpr, out label2absy, prover.Context);
- if (!CommandLineOptions.Clo.UseLabels)
- {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(gen.Integer(Microsoft.Basetypes.BigNum.ZERO), gen.Integer(Microsoft.Basetypes.BigNum.ZERO));
- VCExpr eqExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(Microsoft.Basetypes.BigNum.FromInt(impl.Blocks[0].UniqueId)));
- vcexpr = gen.Implies(eqExpr, vcexpr);
- }
-
- ProverInterface.ErrorHandler handler = null;
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local)
- handler = new VCGen.ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, prover.Context, program);
- else
- handler = new VCGen.ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, prover.Context, program);
-
- impl2ErrorHandler.Add(impl.Name, Tuple.Create(handler, collector));
-
- //Console.WriteLine("VC of {0}: {1}", impl.Name, vcexpr);
-
- // Create a macro so that the VC can sit with the theorem prover
- Macro macro = new Macro(Token.NoToken, impl.Name + "Macro", new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false));
- prover.DefineMacro(macro, vcexpr);
-
- // Store VC
- impl2VC.Add(impl.Name, gen.Function(macro));
-
- // HACK: push the definitions of constants involved in function calls
- // It is possible that some constants only appear in function calls. Thus, when
- // they are replaced by Boolean constants, it is possible that (get-value) will
- // fail if the expression involves such constants. All we need to do is make sure
- // these constants are declared, because otherwise, semantically we are doing
- // the right thing.
- foreach (var tup in fv.functionsUsed)
- {
- // Ignore ones with bound varibles
- if (tup.Item2.InParams.Count > 0) continue;
- var tt = prover.Context.BoogieExprTranslator.Translate(tup.Item3);
- tt = prover.VCExprGen.Or(VCExpressionGenerator.True, tt);
- prover.Assert(tt, true);
- }
- }
-
- // convert "foo(... forall e ...) to:
- // (p iff forall e) ==> foo(... p ...)
- // where p is a fresh boolean variable and foo is an existential constant
- private void ExtractQuantifiedExprs(Implementation impl)
- {
- var funcs = new HashSet<string>(existentialFunctions.Keys);
- foreach (var blk in impl.Blocks)
- {
- foreach (var acmd in blk.Cmds.OfType<AssertCmd>())
- {
- var ret = ExtractQuantifiers.Extract(acmd.Expr, funcs);
- acmd.Expr = ret.Item1;
- impl.LocVars.AddRange(ret.Item2);
- }
- }
- }
-
- // convert "assert e1 && forall x: e2" to
- // assert e1 && e2[x <- x@bound]
- private void StripOutermostForall(Implementation impl)
- {
- var funcs = new HashSet<string>(existentialFunctions.Keys);
- foreach (var blk in impl.Blocks)
- {
- foreach (var acmd in blk.Cmds.OfType<AssertCmd>())
- {
- var ret = StripQuantifiers.Run(acmd.Expr, funcs);
- acmd.Expr = ret.Item1;
- impl.LocVars.AddRange(ret.Item2);
- }
- }
- }
-
- private void Inline()
- {
- if (CommandLineOptions.Clo.InlineDepth < 0)
- return;
-
- var callGraph = BuildCallGraph();
-
- foreach (Implementation impl in callGraph.Nodes)
- {
- InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
- inlineEnsuresVisitor.Visit(impl);
- }
-
- foreach (Implementation impl in callGraph.Nodes)
- {
- impl.OriginalBlocks = impl.Blocks;
- impl.OriginalLocVars = impl.LocVars;
- }
- foreach (Implementation impl in callGraph.Nodes)
- {
- CommandLineOptions.Inlining savedOption = CommandLineOptions.Clo.ProcedureInlining;
- CommandLineOptions.Clo.ProcedureInlining = CommandLineOptions.Inlining.Spec;
- Inliner.ProcessImplementationForHoudini(program, impl);
- CommandLineOptions.Clo.ProcedureInlining = savedOption;
- }
- foreach (Implementation impl in callGraph.Nodes)
- {
- impl.OriginalBlocks = null;
- impl.OriginalLocVars = null;
- }
-
- Graph<Implementation> oldCallGraph = callGraph;
- callGraph = new Graph<Implementation>();
- foreach (Implementation impl in oldCallGraph.Nodes)
- {
- callGraph.AddSource(impl);
- }
- foreach (Tuple<Implementation, Implementation> edge in oldCallGraph.Edges)
- {
- callGraph.AddEdge(edge.Item1, edge.Item2);
- }
- int count = CommandLineOptions.Clo.InlineDepth;
- while (count > 0)
- {
- foreach (Implementation impl in oldCallGraph.Nodes)
- {
- List<Implementation> newNodes = new List<Implementation>();
- foreach (Implementation succ in callGraph.Successors(impl))
- {
- newNodes.AddRange(oldCallGraph.Successors(succ));
- }
- foreach (Implementation newNode in newNodes)
- {
- callGraph.AddEdge(impl, newNode);
- }
- }
- count--;
- }
- }
-
- private Graph<Implementation> BuildCallGraph()
- {
- Graph<Implementation> callGraph = new Graph<Implementation>();
- Dictionary<Procedure, HashSet<Implementation>> procToImpls = new Dictionary<Procedure, HashSet<Implementation>>();
- foreach (var proc in program.Procedures)
- {
- procToImpls[proc] = new HashSet<Implementation>();
- }
- foreach (var impl in program.Implementations)
- {
- if (impl.SkipVerification) continue;
- callGraph.AddSource(impl);
- procToImpls[impl.Proc].Add(impl);
- }
- foreach (var impl in program.Implementations)
- {
- if (impl.SkipVerification) continue;
- foreach (Block b in impl.Blocks)
- {
- foreach (Cmd c in b.Cmds)
- {
- CallCmd cc = c as CallCmd;
- if (cc == null) continue;
- foreach (Implementation callee in procToImpls[cc.Proc])
- {
- callGraph.AddEdge(impl, callee);
- }
- }
- }
- }
- return callGraph;
- }
-
- }
-
- class InlineFunctionCalls : StandardVisitor
- {
- public Stack<string> inlinedFunctionsStack;
-
- public InlineFunctionCalls()
- {
- inlinedFunctionsStack = new Stack<string>();
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- var fc = node.Fun as FunctionCall;
- if (fc != null && fc.Func.Body != null && QKeyValue.FindBoolAttribute(fc.Func.Attributes, "inline"))
- {
- if (inlinedFunctionsStack.Contains(fc.Func.Name))
- {
- // recursion detected
- throw new AbsHoudiniInternalError("Recursion detected in function declarations");
- }
-
- // create a substitution
- var subst = new Dictionary<Variable, Expr>();
- for (int i = 0; i < node.Args.Count; i++)
- {
- subst.Add(fc.Func.InParams[i], node.Args[i]);
- }
-
- var e =
- Substituter.Apply(new Substitution(v => subst.ContainsKey(v) ? subst[v] : Expr.Ident(v)), fc.Func.Body);
-
- inlinedFunctionsStack.Push(fc.Func.Name);
-
- e = base.VisitExpr(e);
-
- inlinedFunctionsStack.Pop();
-
- return e;
- }
- return base.VisitNAryExpr(node);
- }
- }
-
- class ReplaceFunctionCalls : StandardVisitor
- {
- public List<Tuple<string, Function, NAryExpr>> functionsUsed;
- public List<Function> boolConstants;
-
- public HashSet<string> functionsAssumed;
- public HashSet<string> functionsAsserted;
- HashSet<string> functionsToReplace;
-
- private bool inAssume;
- private bool inAssert;
- private bool inFunction;
- private List<Dictionary<string, Variable>> boundVars;
- private static int IdCounter = 0;
-
- public ReplaceFunctionCalls(HashSet<string> functionsToReplace)
- {
- this.functionsUsed = new List<Tuple<string, Function, NAryExpr>>();
- this.functionsToReplace = functionsToReplace;
- this.functionsAsserted = new HashSet<string>();
- this.functionsAssumed = new HashSet<string>();
- this.boolConstants = new List<Function>();
- this.boundVars = new List<Dictionary<string, Variable>>();
-
- inAssume = false;
- inAssert = false;
- inFunction = false;
- }
-
- public override Cmd VisitAssertCmd(AssertCmd node)
- {
- inAssert = true;
- var ret = base.VisitAssertCmd(node);
- inAssert = false;
- return ret;
- }
-
- public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node)
- {
- return this.VisitAssertCmd(node);
- }
-
- public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node)
- {
- return this.VisitAssertCmd(node);
- }
-
- public override Cmd VisitAssumeCmd(AssumeCmd node)
- {
- inAssume = true;
- var ret = base.VisitAssumeCmd(node);
- inAssume = false;
- return ret;
- }
-
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
- {
- // gather the quantified variables
- var dummies = new Dictionary<string, Variable>();
- node.Dummies.Iter(v => dummies.Add(v.Name, v));
-
- boundVars.Add(dummies);
-
- node = base.VisitQuantifierExpr(node);
-
- boundVars.RemoveAt(boundVars.Count - 1);
-
- return node;
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- var inF = inFunction;
-
- if (node.Fun is FunctionCall && functionsToReplace.Contains((node.Fun as FunctionCall).FunctionName))
- {
- found((node.Fun as FunctionCall).FunctionName);
- inFunction = true;
-
- // collect all the variables used by this function
- var collector = new VariableCollector();
- collector.VisitExpr(node);
-
- // Find the outermost bound variables
- var bound = new List<Variable>();
- if(boundVars.Count > 0)
- bound.AddRange(collector.usedVars.Intersect(boundVars[0].Values));
-
- // create boolean function to replace this guy
- var constant = new Function(Token.NoToken, "AbsHoudiniConstant" + IdCounter, bound,
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "r", Microsoft.Boogie.Type.Bool), false));
- IdCounter++;
-
- functionsUsed.Add(Tuple.Create((node.Fun as FunctionCall).FunctionName, constant, node));
- boolConstants.Add(constant);
-
- var args = new List<Expr>();
- bound.OfType<Variable>().Select(v => Expr.Ident(v)).Iter(v => args.Add(v));
- return new NAryExpr(Token.NoToken, new FunctionCall(constant), args);
- }
- var ret = base.VisitNAryExpr(node);
-
- inFunction = inF;
-
- return ret;
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- if (inFunction)
- {
- // Inside functions we can only refer to the outermost bound variables
- for (int i = boundVars.Count - 1; i >= 1; i--)
- {
- if (boundVars[i].ContainsKey(node.Name))
- throw new AbsHoudiniInternalError("Existential functions can only refer to outermost bound variables in an expression");
- }
- }
-
- return base.VisitIdentifierExpr(node);
- }
-
- private void found(string func)
- {
- if (inAssume) functionsAssumed.Add(func);
- if (inAssert) functionsAsserted.Add(func);
- }
-
- }
-
- // convert "foo(... forall e ...) to:
- // (p iff forall e) ==> foo(... p ...)
- // where p is a fresh boolean variable and foo is an existential constant
- class ExtractQuantifiers : StandardVisitor
- {
- static int freshConstCounter = 0;
- HashSet<string> existentialFunctions;
- bool insideExistential;
- Dictionary<Constant, Expr> newConstants;
-
- private ExtractQuantifiers(HashSet<string> existentialFunctions)
- {
- this.existentialFunctions = existentialFunctions;
- insideExistential = false;
- newConstants = new Dictionary<Constant, Expr>();
- }
-
- public static Tuple<Expr, IEnumerable<Constant>> Extract(Expr expr, HashSet<string> existentialFunctions)
- {
- var eq = new ExtractQuantifiers(existentialFunctions);
- expr = eq.VisitExpr(expr);
- Expr ret = Expr.True;
- foreach (var tup in eq.newConstants)
- {
- ret = Expr.And(ret, Expr.Eq(Expr.Ident(tup.Key), tup.Value));
- }
- ret = Expr.Imp(ret, expr);
- return Tuple.Create(ret, eq.newConstants.Keys.AsEnumerable());
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- var oldIE = insideExistential;
-
- if (node.Fun is FunctionCall && existentialFunctions.Contains((node.Fun as FunctionCall).FunctionName))
- insideExistential = true;
-
- var ret = base.VisitNAryExpr(node);
-
- insideExistential = oldIE;
- return ret;
- }
-
- public override Expr VisitExpr(Expr node)
- {
- if (node is QuantifierExpr)
- {
- return MyVisitQuantifierExpr(node as QuantifierExpr);
- }
- return base.VisitExpr(node);
- }
-
- public Expr MyVisitQuantifierExpr(QuantifierExpr node)
- {
- node = base.VisitQuantifierExpr(node);
-
- if (insideExistential)
- {
- var constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
- "quant@const" + freshConstCounter, Microsoft.Boogie.Type.Bool), false);
- freshConstCounter++;
-
- newConstants.Add(constant, node);
-
- return Expr.Ident(constant);
- }
-
- return node;
- }
- }
-
- // convert "assert e1 && forall x: e2" to
- // assert e1 && e2[x <- x@bound]
- // only if e2 has an existential function
- class StripQuantifiers : StandardVisitor
- {
- static int boundVarCounter = 0;
-
- // 0 -> None, 1 -> Forall, 2 -> Exists, 3 -> Nested
- int insideQuantifier;
-
- bool searchExistentialFunction;
- bool foundExistentialFunction;
-
- HashSet<string> existentialFunctions;
- Dictionary<string, LocalVariable> subst;
- List<LocalVariable> LocalsToAdd;
-
- private StripQuantifiers(HashSet<string> existentialFunctions)
- {
- this.existentialFunctions = existentialFunctions;
- insideQuantifier = 0;
- searchExistentialFunction = false;
- foundExistentialFunction = false;
- LocalsToAdd = new List<LocalVariable>();
- subst = null;
- }
-
- public static Tuple<Expr,List<LocalVariable>> Run(Expr expr, HashSet<string> existentialFunctions)
- {
- // check for type errors first
- var sq = new StripQuantifiers(existentialFunctions);
- var ret = sq.VisitExpr(expr);
-
- return Tuple.Create(ret, sq.LocalsToAdd);
- }
-
- public override Expr VisitExpr(Expr node)
- {
- if (node is QuantifierExpr)
- {
- return MyVisitQuantifierExpr(node as QuantifierExpr);
- }
-
- return base.VisitExpr(node);
- }
-
- private Expr MyVisitQuantifierExpr(QuantifierExpr node)
- {
- var oldIQ = insideQuantifier;
- Expr ret = node;
-
- // update "insideQuantifier"
- if (insideQuantifier == 0)
- {
- if (node is ForallExpr) insideQuantifier = 1;
- else insideQuantifier = 2;
- }
- else if (insideQuantifier > 0)
- {
- insideQuantifier = 3;
- }
-
- // Going inside Forall?
- if (insideQuantifier == 1)
- {
- // see if there is any existential function inside
- searchExistentialFunction = true;
- foundExistentialFunction = false;
- base.VisitQuantifierExpr(node);
-
- if (foundExistentialFunction)
- {
- // create substitution to apply
- subst = new Dictionary<string, LocalVariable>();
- foreach (var bv in node.Dummies.OfType<Variable>())
- {
- var lv = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
- bv + "@bound" + boundVarCounter, bv.TypedIdent.Type));
- boundVarCounter++;
- subst.Add(bv.Name, lv);
- LocalsToAdd.Add(lv);
- }
-
- // apply the subst
- var body = base.VisitExpr(node.Body);
- ret = body;
-
- subst = null;
- }
- else
- {
- ret = base.VisitQuantifierExpr(node);
- }
-
- searchExistentialFunction = false;
- foundExistentialFunction = false;
- }
- else
- {
- ret = base.VisitQuantifierExpr(node);
- }
-
- insideQuantifier = oldIQ;
- return ret;
- }
-
- public override Expr VisitNAryExpr(NAryExpr node)
- {
- if (node.Fun is FunctionCall && existentialFunctions.Contains((node.Fun as FunctionCall).FunctionName))
- {
- if (insideQuantifier == 3)
- throw new AbsHoudiniInternalError("Existential function found inside exists, or nested foralls");
-
- if (searchExistentialFunction)
- foundExistentialFunction = true;
-
- }
-
- return base.VisitNAryExpr(node);
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- if (subst != null && subst.ContainsKey(node.Name))
- return Expr.Ident(subst[node.Name]);
- return base.VisitIdentifierExpr(node);
- }
-
- }
-
- public class Intervals : IAbstractDomain
- {
- // [lower, upper]
- int upper;
- int lower;
- // or: \bot
- bool isBottom;
- // number of times join has been performed
- int nJoin;
- // number of times before we widen
- readonly static int maxJoin = 5;
-
- public Intervals()
- {
- this.upper = 0;
- this.lower = 0;
- this.nJoin = 0;
- this.isBottom = true;
- }
-
- private Intervals(int lower, int upper, int nJoin)
- {
- this.upper = upper;
- this.lower = lower;
- this.nJoin = nJoin;
- }
-
- public IAbstractDomain Bottom()
- {
- return new Intervals();
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- if (lower == Int32.MinValue && upper == Int32.MaxValue)
- {
- changed = false;
- return this;
- }
- changed = true;
- return new Intervals(Int32.MinValue, Int32.MaxValue, 0);
- }
-
- public IAbstractDomain Join(List<Model.Element> states)
- {
- Debug.Assert(states.Count == 1);
- var state = states[0] as Model.Integer;
- if (state == null)
- throw new AbsHoudiniInternalError("Incorrect type, expected int");
- var intval = state.AsInt();
-
- if (isBottom)
- {
- return new Intervals(intval, intval, 1);
- }
-
- if(intval >= lower && intval <= upper)
- return this;
-
- if (nJoin > maxJoin)
- {
- // widen
- if (intval > upper)
- return new Intervals(lower, Int32.MaxValue, 1);
- if(intval < lower)
- return new Intervals(Int32.MinValue, upper, 1);
-
- Debug.Assert(false);
- }
-
- if (intval > upper)
- return new Intervals(lower, intval, nJoin + 1);
- if (intval < lower)
- return new Intervals(intval, upper, nJoin + 1);
-
- Debug.Assert(false);
- return null;
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- Debug.Assert(vars.Count == 1);
- var v = vars[0];
- if (isBottom) return Expr.False;
- Expr ret = Expr.True;
- if (lower != Int32.MinValue)
- ret = Expr.And(ret, Expr.Ge(v, Expr.Literal(lower)));
- if (upper != Int32.MaxValue)
- ret = Expr.And(ret, Expr.Le(v, Expr.Literal(upper)));
- return ret;
- }
-
- public bool TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Count != 1)
- {
- msg = "Illegal number of arguments";
- return false;
- }
- if (!argTypes[0].IsInt)
- {
- msg = "Illegal type, expecting int";
- return false;
- }
- return true;
- }
- }
-
- public class PredicateAbsElem : IAbstractDomain
- {
- public static class ExprExt
- {
- public static Expr AndSimp(Expr e1, Expr e2)
- {
- if (e1 == Expr.True) return e2;
- if (e2 == Expr.True) return e1;
- if (e1 == Expr.False || e2 == Expr.False) return Expr.False;
- return Expr.And(e1, e2);
- }
-
- public static Expr OrSimp(Expr e1, Expr e2)
- {
- if (e1 == Expr.False) return e2;
- if (e2 == Expr.False) return e1;
- if (e1 == Expr.True || e2 == Expr.True) return Expr.True;
- return Expr.Or(e1, e2);
- }
- }
-
- class Disjunct
- {
- public static int DisjunctBound = 3;
- HashSet<int> pos;
- HashSet<int> neg;
- bool isTrue;
-
- public Disjunct()
- {
- isTrue = true;
- pos = new HashSet<int>();
- neg = new HashSet<int>();
- }
-
- public Disjunct(IEnumerable<int> pos, IEnumerable<int> neg)
- {
- this.isTrue = false;
- this.pos = new HashSet<int>(pos);
- this.neg = new HashSet<int>(neg);
- if (this.pos.Overlaps(this.neg))
- {
- this.isTrue = true;
- this.pos = new HashSet<int>();
- this.neg = new HashSet<int>();
- }
- if (this.pos.Count + this.neg.Count > DisjunctBound)
- {
- // Set to true
- this.isTrue = true;
- this.pos = new HashSet<int>();
- this.neg = new HashSet<int>();
- }
-
- }
-
- public Disjunct OR(Disjunct that)
- {
- if (isTrue)
- return this;
- if (that.isTrue)
- return that;
-
- return new Disjunct(this.pos.Concat(that.pos), this.neg.Concat(that.neg));
- }
-
- public bool Implies(Disjunct that)
- {
- if (isTrue) return that.isTrue;
- if (that.isTrue) return true;
-
- return pos.IsSubsetOf(that.pos) && neg.IsSubsetOf(that.neg);
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- if (isTrue) return Expr.True;
- Expr ret = Expr.False;
- pos.Iter(i => ret = ExprExt.OrSimp(ret, vars[i]));
- neg.Iter(i => ret = ExprExt.OrSimp(ret, Expr.Not(vars[i])));
- return ret;
- }
- }
-
- // Conjunction of Disjuncts
- List<Disjunct> conjuncts;
- bool isFalse;
-
- public PredicateAbsElem()
- {
- this.conjuncts = new List<Disjunct>();
- this.isFalse = true;
- }
-
- public IAbstractDomain Bottom()
- {
- return new PredicateAbsElem();
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- if (conjuncts.Count == 0)
- {
- changed = false;
- return this;
- }
- changed = true;
- var ret = new PredicateAbsElem();
- ret.isFalse = false;
- return ret;
- }
-
- public IAbstractDomain Join(List<Model.Element> state)
- {
- if (state.Any(me => !(me is Model.Boolean)))
- throw new AbsHoudiniInternalError("Predicate Abstraction requires that each argument be of type bool");
-
- // quick return if this == true
- if (!this.isFalse && conjuncts.Count == 0)
- return this;
-
- var ret = new PredicateAbsElem();
- ret.isFalse = false;
-
- for (int i = 0; i < state.Count; i++)
- {
- var b = (state[i] as Model.Boolean).Value;
- Disjunct d = null;
- if (b) d = new Disjunct(new int[] { i }, new int[] { });
- else d = new Disjunct(new int[] { }, new int[] { i });
-
- if (isFalse)
- ret.AddDisjunct(d);
- else
- {
- conjuncts.Iter(c => ret.AddDisjunct(c.OR(d)));
- }
- }
-
- return ret;
-
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- if (isFalse) return Expr.False;
- Expr ret = Expr.True;
-
- foreach (var c in conjuncts)
- {
- ret = ExprExt.AndSimp(ret, c.Gamma(vars));
- }
-
- return ret;
- }
-
- public bool TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Any(t => !t.IsBool))
- {
- msg = "Illegal type, expecting bool";
- return false;
- }
- return true;
- }
-
- private void AddDisjunct(Disjunct d)
- {
- if (conjuncts.Any(c => c.Implies(d)))
- return;
-
- conjuncts.RemoveAll(c => d.Implies(c));
- conjuncts.Add(d);
- }
- }
-
- // [false -- (x == true) -- true]
- public class HoudiniConst : IAbstractDomain
- {
- bool isBottom;
- bool isTop;
-
- private HoudiniConst(bool isTop, bool isBottom)
- {
- this.isBottom = isBottom;
- this.isTop = isTop;
- Debug.Assert(!(isTop && isBottom));
- }
-
- public static HoudiniConst GetExtObj()
- {
- return new HoudiniConst(false, false);
- }
-
- public static HoudiniConst GetTop()
- {
- return new HoudiniConst(true, false);
- }
-
- public static HoudiniConst GetBottom()
- {
- return new HoudiniConst(false, true);
- }
-
- public IAbstractDomain Bottom()
- {
- return GetBottom();
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- changed = false;
- if (isTop) return this;
- changed = true;
- return GetTop();
- }
-
- public IAbstractDomain Join(List<Model.Element> states)
- {
- Debug.Assert(states.Count == 1);
- var state = states[0];
-
- if (isTop) return this;
-
- if (state is Model.Boolean)
- {
- if ((state as Model.Boolean).Value)
- return GetExtObj();
- }
-
- return GetTop();
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- Debug.Assert(vars.Count == 1);
- var v = vars[0];
- if (isBottom) return Expr.False;
- if (isTop) return Expr.True;
- return v;
- }
-
- public bool TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Count != 1)
- {
- msg = "Illegal number of arguments, expecting 1";
- return false;
- }
- if (!argTypes[0].IsBool)
- {
- msg = "Illegal type, expecting bool";
- return false;
- }
- return true;
- }
- }
-
- // foo(x) = x < 2^j for some j <= 16
- public class PowDomain : IAbstractDomain
- {
- enum Val { FALSE, NEITHER, TRUE };
- Val tlevel;
- bool isBottom { get { return tlevel == Val.FALSE; } }
- bool isTop { get { return tlevel == Val.TRUE; } }
-
- readonly int Max = 16;
-
- int upper; // <= Max
-
- private PowDomain(Val tlevel) :
- this(tlevel, 0) { }
-
- private PowDomain(Val tlevel, int upper)
- {
- this.tlevel = tlevel;
- this.upper = upper;
- }
-
- public static IAbstractDomain GetBottom()
- {
- return new PowDomain(Val.FALSE) as IAbstractDomain;
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- if (isTop)
- {
- changed = false;
- return this;
- }
- changed = true;
- return new PowDomain(Val.TRUE);
- }
-
- IAbstractDomain IAbstractDomain.Bottom()
- {
- return GetBottom();
- }
-
- IAbstractDomain IAbstractDomain.Join(List<Model.Element> state)
- {
- if (isTop) return this;
-
- int v = 0;
- if (state[0] is Model.BitVector)
- v = (state[0] as Model.BitVector).AsInt();
- else if (state[0] is Model.Integer)
- v = (state[0] as Model.Integer).AsInt();
- else Debug.Assert(false);
-
- var nupper = upper;
- while ((1 << nupper) < v) nupper++;
- var ntlevel = Val.NEITHER;
- if (nupper > Max) ntlevel = Val.TRUE;
- return new PowDomain(ntlevel, nupper);
- }
-
- Expr IAbstractDomain.Gamma(List<Expr> vars)
- {
- if (isBottom) return Expr.False;
- if (isTop) return Expr.True;
- var v = vars[0];
- if (v.Type.IsBv)
- {
- var bits = v.Type.BvBits;
- if (!AbstractDomainFactory.bvslt.ContainsKey(bits))
- throw new AbsHoudiniInternalError("No builtin function found for bv" + bits.ToString());
- var bvslt = AbstractDomainFactory.bvslt[bits];
- return new NAryExpr(Token.NoToken, new FunctionCall(bvslt), new List<Expr> { v,
- new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(1 << (upper+1)), 32) });
- }
- else
- {
- return Expr.Lt(v, Expr.Literal(1 << (upper+1)));
- }
- }
-
- bool IAbstractDomain.TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Count != 1)
- {
- msg = "Illegal number of arguments, expecting 1";
- return false;
- }
- if (argTypes.Any(tt => !tt.IsInt && !tt.IsBv))
- {
- msg = "Illegal type, expecting int or bv";
- return false;
- }
- return true;
- }
- }
-
- // foo(x_i) = all equalities that hold
- public class EqualitiesDomain : IAbstractDomain
- {
- bool isBottom;
- List<HashSet<int>> equalities;
-
- public EqualitiesDomain(bool isBottom, List<HashSet<int>> eq)
- {
- this.isBottom = isBottom;
- this.equalities = eq;
- }
-
- public static IAbstractDomain GetBottom()
- {
- return new EqualitiesDomain(true, new List<HashSet<int>>());
- }
-
- IAbstractDomain IAbstractDomain.Bottom()
- {
- return GetBottom();
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- if (equalities.Count == 0)
- {
- changed = false;
- return this;
- }
- changed = true;
- return new EqualitiesDomain(false, new List<HashSet<int>>());
- }
-
- IAbstractDomain IAbstractDomain.Join(List<Model.Element> state)
- {
- // find the guys that are equal
- var eq = new List<HashSet<int>>();
- for (int i = 0; i < state.Count; i++)
- {
- var added = false;
- foreach (var s in eq)
- {
- var sv = s.First();
- if (state[i].ToString() == state[sv].ToString())
- {
- s.Add(i);
- added = true;
- break;
- }
- }
- if (!added) eq.Add(new HashSet<int>(new int[] { i }));
- }
-
- if (isBottom)
- {
- return new EqualitiesDomain(false, eq);
- }
-
- // intersect two partitions equalities and eq
- var m1 = GetMap(equalities, state.Count);
- var m2 = GetMap(eq, state.Count);
-
- for (int i = 0; i < state.Count; i++)
- m2[i] = new HashSet<int>(m2[i].Intersect(m1[i]));
-
-
- // map from representative to set
- var repToSet = new Dictionary<int, HashSet<int>>();
-
- for (int i = 0; i < state.Count; i++)
- {
- var rep = m2[i].Min();
- if (!repToSet.ContainsKey(rep))
- repToSet[rep] = m2[i];
- }
-
- var ret = new List<HashSet<int>>();
- repToSet.Values.Iter(s => ret.Add(s));
-
- return new EqualitiesDomain(false, ret);
- }
-
- Expr IAbstractDomain.Gamma(List<Expr> vars)
- {
- if (isBottom) return Expr.False;
- Expr ret = Expr.True;
- foreach (var eq in equalities.Select(hs => hs.ToList()))
- {
- if (eq.Count == 1) continue;
- var prev = eq[0];
- for (int i = 1; i < eq.Count; i++)
- {
- ret = Expr.And(ret, Expr.Eq(vars[prev], vars[eq[i]]));
- prev = eq[i];
- }
- }
- return ret;
- }
-
- bool IAbstractDomain.TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Count == 0) return true;
- var ot = argTypes[0];
-
- if (argTypes.Any(tt => !tt.Equals(ot)))
- {
- msg = string.Format("Illegal type, expecting type {0}, got {1}", ot, argTypes.First(tt => !tt.Equals(ot)));
- return false;
- }
- return true;
- }
-
- private HashSet<int>[] GetMap(List<HashSet<int>> eq, int n)
- {
- var ret = new HashSet<int>[n];
- foreach (var s in eq)
- {
- foreach (var i in s)
- ret[i] = s;
- }
- return ret;
- }
- }
-
- // foo(a,b) \in {false, \not a, a ==> b, true}
- public class ImplicationDomain : IAbstractDomain
- {
- enum Val {FALSE, NOT_A, A_IMP_B, TRUE};
- Val val;
-
- private ImplicationDomain(Val val)
- {
- this.val = val;
- }
-
- public static ImplicationDomain GetBottom()
- {
- return new ImplicationDomain(Val.FALSE);
- }
-
- public IAbstractDomain Bottom()
- {
- return GetBottom();
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- if(val == Val.TRUE) {
- changed = false;
- return this;
- }
- changed = true;
- return new ImplicationDomain(Val.TRUE);
- }
-
- public IAbstractDomain Join(List<Model.Element> states)
- {
- Debug.Assert(states.Count == 2);
- var v1 = (states[0] as Model.Boolean).Value;
- var v2 = (states[1] as Model.Boolean).Value;
-
- if (val == Val.TRUE) return this;
-
- var that = Val.TRUE;
- if (!v1) that = Val.NOT_A;
- else if (!v1 || v2) that = Val.A_IMP_B;
-
- if (that == Val.TRUE || val == Val.FALSE)
- return new ImplicationDomain(that);
-
- // Now, neither this or that is FALSE or TRUE
- if (val == that)
- return this;
-
- Debug.Assert(val == Val.A_IMP_B || that == Val.A_IMP_B);
- return new ImplicationDomain(Val.A_IMP_B);
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- Debug.Assert(vars.Count == 2);
-
- var v1 = vars[0];
- var v2 = vars[1];
-
- if (val == Val.FALSE) return Expr.False;
- if (val == Val.TRUE) return Expr.True;
- if (val == Val.NOT_A) return Expr.Not(v1);
- return Expr.Imp(v1, v2);
- }
-
- public bool TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Count != 2)
- {
- msg = "Illegal number of arguments, expecting 2";
- return false;
- }
- if (argTypes.Any(tt => !tt.IsBool))
- {
- msg = "Illegal type, expecting bool";
- return false;
- }
- return true;
- }
- }
-
- public class ConstantProp : IAbstractDomain
- {
- object val;
- bool isBottom;
- bool isTop;
-
- private ConstantProp(object val, bool isTop, bool isBottom)
- {
- this.val = val;
- this.isBottom = isBottom;
- this.isTop = isTop;
- Debug.Assert(!(isTop && isBottom));
- Debug.Assert(val == null || (val is int) || (val is bool));
- }
-
- public static ConstantProp GetExtObj(object val)
- {
- Debug.Assert(val != null);
- return new ConstantProp(val, false, false);
- }
-
- public static ConstantProp GetTop()
- {
- return new ConstantProp(null, true, false);
- }
-
- public static ConstantProp GetBottom()
- {
- return new ConstantProp(null, false, true);
- }
-
- public IAbstractDomain MakeTop(out bool changed) {
- if (isTop)
- {
- changed = false;
- return this;
- }
- changed = true;
- return GetTop();
- }
-
- private ConstantProp Join(ConstantProp that)
- {
- if (isBottom) return that;
- if (isTop) return this;
- if (that.isBottom) return this;
- if (that.isTop) return that;
-
- if ((val is int) && !(that.val is int))
- throw new AbsHoudiniInternalError("Type mismatch in ExtObj");
-
- if ((val is bool) && !(that.val is bool))
- throw new AbsHoudiniInternalError("Type mismatch in ExtObj");
-
- if (val is int)
- {
- var v1 = (int)val;
- var v2 = (int)that.val;
- if (v1 != v2) return GetTop();
- return this;
- }
- else if (val is bool)
- {
- var v1 = (bool)val;
- var v2 = (bool)that.val;
- if (v1 != v2) return GetTop();
- return this;
- }
- throw new AbsHoudiniInternalError("Illegal val type in ExtObj");
- }
-
- public IAbstractDomain Bottom()
- {
- return GetBottom();
- }
-
- public IAbstractDomain Join(List<Model.Element> states)
- {
- Debug.Assert(states.Count == 1);
- var state = states[0];
- ConstantProp that = null;
-
- if (state is Model.Integer)
- {
- that = GetExtObj((state as Model.Integer).AsInt());
- }
- else if (state is Model.Boolean)
- {
- that = GetExtObj((state as Model.Boolean).Value);
- }
- else
- {
- throw new AbsHoudiniInternalError("Illegal type " + state.GetType().ToString());
- }
-
- return Join(that);
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- Debug.Assert(vars.Count == 1);
- var v = vars[0];
- if (isBottom) return Expr.False;
- if (isTop) return Expr.True;
- if (val is int)
- return Expr.Eq(v, Expr.Literal((int)val));
- if (val is bool && (bool)val)
- return v;
- if (val is bool && !(bool)val)
- return Expr.Not(v);
-
- return null;
- }
-
- public bool TypeCheck(List<Type> argTypes, out string msg)
- {
- msg = "";
- if (argTypes.Count != 1)
- {
- msg = "Illegal number of arguments, expecting 1";
- return false;
- }
- if (!argTypes[0].IsInt && ! argTypes[0].IsBool)
- {
- msg = "Illegal type, expecting int or bool";
- return false;
- }
- return true;
- }
- }
-
-
- public class IndependentAttribute<T> : IAbstractDomain where T : class, IAbstractDomain
- {
- bool isBottom;
- int numVars;
- List<T> varVal;
- T underlyingInstance;
-
- public IndependentAttribute()
- {
- isBottom = true;
- numVars = 0;
- varVal = new List<T>();
- underlyingInstance = null;
- }
-
- public IAbstractDomain Bottom()
- {
- return new IndependentAttribute<T>();
- }
-
- public IAbstractDomain MakeTop(out bool changed)
- {
- var mt = new Func<IAbstractDomain>(() =>
- {
- var ret = new IndependentAttribute<T>();
- ret.isBottom = true;
- ret.numVars = numVars;
- ret.underlyingInstance = underlyingInstance;
- ret.varVal = new List<T>();
- bool tmp;
- for (int i = 0; i < varVal.Count; i++)
- ret.varVal.Add(varVal[i].MakeTop(out tmp) as T);
- return ret;
- });
-
- if (!isBottom)
- {
- foreach (var t in varVal)
- {
- var top = t.MakeTop(out changed);
- if (changed)
- {
- return mt();
- }
- }
- }
- else
- {
- changed = true;
- return mt();
- }
-
- changed = false;
- return this;
- }
- public IAbstractDomain Join(List<Model.Element> state)
- {
- SetUnderlyingInstance();
-
- if (!isBottom && numVars != state.Count)
- {
- throw new AbsHoudiniInternalError(
- string.Format("Got illegal number of arguments ({0}), expected {1}", state.Count, numVars));
- }
-
- var ret = new IndependentAttribute<T>();
- ret.isBottom = false;
- ret.numVars = state.Count;
- for(int i = 0; i < state.Count; i++)
- {
- var sl = new List<Model.Element>();
- sl.Add(state[i]);
- T prev = isBottom ? underlyingInstance.Bottom() as T : varVal[i];
- ret.varVal.Add(prev.Join(sl) as T);
- }
-
- return ret;
- }
-
- public Expr Gamma(List<Expr> vars)
- {
- if (isBottom) return Expr.False;
- if (numVars != vars.Count)
- throw new AbsHoudiniInternalError(
- string.Format("Got illegal number of arguments ({0}), expected {1}", vars.Count, numVars));
-
- Expr ret = Expr.True;
- for (int i = 0; i < numVars; i++)
- {
- var sl = new List<Expr>(); sl.Add(vars[i]);
- ret = Expr.And(ret, varVal[i].Gamma(sl));
- }
-
- return ret;
- }
-
- private void SetUnderlyingInstance()
- {
- if (underlyingInstance != null) return;
- var tt = typeof(T);
- underlyingInstance = AbstractDomainFactory.GetInstance(tt) as T;
- }
-
- public bool TypeCheck(List<Type> argTypes, out string msg)
- {
- SetUnderlyingInstance();
-
- msg = "";
- foreach(var t in argTypes)
- {
- if(!underlyingInstance.TypeCheck(new List<Type>(new Type[] { t }), out msg))
- return false;
- }
- return true;
- }
- }
-
- public class AbstractDomainFactory
- {
- // Type name -> Instance
- private static Dictionary<string, IAbstractDomain> abstractDomainInstances = new Dictionary<string, IAbstractDomain>();
- private static Dictionary<string, IAbstractDomain> abstractDomainInstancesFriendly = new Dictionary<string, IAbstractDomain>();
-
- // bitvector operations
- public static Dictionary<int, Function> bvslt = new Dictionary<int, Function>();
-
- public static void Register(string friendlyName, IAbstractDomain instance)
- {
- var Name = instance.GetType().FullName;
- Debug.Assert(!abstractDomainInstances.ContainsKey(Name));
- abstractDomainInstances.Add(Name, instance);
- abstractDomainInstancesFriendly.Add(friendlyName, instance);
- }
-
- public static IAbstractDomain GetInstance(System.Type type)
- {
- var Name = type.FullName;
- Debug.Assert(abstractDomainInstances.ContainsKey(Name));
- return abstractDomainInstances[Name] as IAbstractDomain;
- }
-
- public static IAbstractDomain GetInstance(string friendlyName)
- {
- if (!abstractDomainInstancesFriendly.ContainsKey(friendlyName))
- {
- Console.WriteLine("Domain {0} not found", friendlyName);
- Console.WriteLine("Supported domains are:");
- abstractDomainInstancesFriendly.Keys.Iter(tup => Console.WriteLine(" {0}", tup));
- throw new AbsHoudiniInternalError("Domain not found");
- }
- return abstractDomainInstancesFriendly[friendlyName] as IAbstractDomain;
- }
-
- public static void Initialize(Program program)
- {
- // Declare abstract domains
- var domains = new List<System.Tuple<string, IAbstractDomain>>(new System.Tuple<string, IAbstractDomain>[] {
- System.Tuple.Create("HoudiniConst", HoudiniConst.GetBottom() as IAbstractDomain),
- System.Tuple.Create("Intervals", new Intervals() as IAbstractDomain),
- System.Tuple.Create("ConstantProp", ConstantProp.GetBottom() as IAbstractDomain),
- System.Tuple.Create("PredicateAbs", new PredicateAbsElem() as IAbstractDomain),
- System.Tuple.Create("ImplicationDomain", ImplicationDomain.GetBottom() as IAbstractDomain),
- System.Tuple.Create("PowDomain", PowDomain.GetBottom() as IAbstractDomain),
- System.Tuple.Create("EqualitiesDomain", EqualitiesDomain.GetBottom() as IAbstractDomain),
- System.Tuple.Create("IA[HoudiniConst]", new IndependentAttribute<HoudiniConst>() as IAbstractDomain),
- System.Tuple.Create("IA[ConstantProp]", new IndependentAttribute<ConstantProp>() as IAbstractDomain),
- System.Tuple.Create("IA[Intervals]", new IndependentAttribute<Intervals>() as IAbstractDomain),
- System.Tuple.Create("IA[PowDomain]", new IndependentAttribute<PowDomain>() as IAbstractDomain),
- });
-
- domains.Iter(tup => AbstractDomainFactory.Register(tup.Item1, tup.Item2));
- program.Functions.Iter(RegisterFunction);
- }
-
- private static void RegisterFunction(Function func)
- {
- var attr = QKeyValue.FindStringAttribute(func.Attributes, "bvbuiltin");
- if (attr != null && attr == "bvslt" && func.InParams.Count == 2 && func.InParams[0].TypedIdent.Type.IsBv)
- bvslt.Add(func.InParams[0].TypedIdent.Type.BvBits, func);
- }
- }
-
- public interface IAbstractDomain
- {
- IAbstractDomain Bottom();
- IAbstractDomain MakeTop(out bool changed);
- IAbstractDomain Join(List<Model.Element> state);
- Expr Gamma(List<Expr> vars);
- bool TypeCheck(List<Type> argTypes, out string msg);
- }
-
- public class AbstractHoudini
- {
- // Input Program
- Program program;
- // Impl -> VC
- Dictionary<string, VCExpr> impl2VC;
- // Impl -> Vars at end of the impl
- Dictionary<string, List<VCExpr>> impl2EndStateVars;
- // Impl -> (callee,summary pred)
- Dictionary<string, List<Tuple<string, bool, VCExprVar, VCExprNAry>>> impl2CalleeSummaries;
- // pointer to summary class
- ISummaryElement summaryClass;
- // impl -> summary
- Dictionary<string, ISummaryElement> impl2Summary;
- // name -> impl
- Dictionary<string, Implementation> name2Impl;
- // Use Bilateral algorithm
- public static bool UseBilateralAlgo = true;
- public static int iterTimeLimit = -1; // ms
-
- public static readonly string summaryPredSuffix = "SummaryPred";
-
- // Essentials: VCGen, Prover, and reporter
- VCGen vcgen;
- ProverInterface prover;
- AbstractHoudiniErrorReporter reporter;
-
- // Stats
- TimeSpan proverTime;
- int numProverQueries;
-
- // Produce witness for correctness: can be set programmatically
- public static string WitnessFile = "absHoudiniWitness.bpl";
-
- public AbstractHoudini(Program program)
- {
- this.program = program;
- this.impl2VC = new Dictionary<string, VCExpr>();
- this.impl2EndStateVars = new Dictionary<string, List<VCExpr>>();
- this.impl2CalleeSummaries = new Dictionary<string, List<Tuple<string, bool, VCExprVar, VCExprNAry>>>();
- this.impl2Summary = new Dictionary<string, ISummaryElement>();
- this.name2Impl = SimpleUtil.nameImplMapping(program);
-
- if (CommandLineOptions.Clo.ProverKillTime > 0)
- CommandLineOptions.Clo.ProverOptions = CommandLineOptions.Clo.ProverOptions.Concat1(string.Format("TIME_LIMIT={0}", CommandLineOptions.Clo.ProverKillTime));
-
- this.vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List<Checker>());
- this.prover = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, -1);
-
- this.reporter = new AbstractHoudiniErrorReporter();
-
- this.proverTime = TimeSpan.Zero;
- this.numProverQueries = 0;
-
- if (CommandLineOptions.Clo.AbstractHoudini == "0")
- UseBilateralAlgo = false;
- }
-
- public void computeSummaries(ISummaryElement summaryClass)
- {
- // TODO: move this some place else
- PredicateAbs.FindUnsatPairs(prover.VCExprGen, prover);
-
- this.summaryClass = summaryClass;
-
- name2Impl.Values.Iter(attachEnsures);
-
- program.Implementations
- .Iter(impl => impl2Summary.Add(impl.Name, summaryClass.GetFlaseSummary(program, impl)));
-
- // Build call graph
- var Succ = new Dictionary<Implementation, HashSet<Implementation>>();
- var Pred = new Dictionary<Implementation, HashSet<Implementation>>();
- name2Impl.Values.Iter(impl => Succ.Add(impl, new HashSet<Implementation>()));
- name2Impl.Values.Iter(impl => Pred.Add(impl, new HashSet<Implementation>()));
-
- foreach (var impl in program.Implementations)
- {
- foreach (var blk in impl.Blocks)
- {
- foreach (var cmd in blk.Cmds.OfType<CallCmd>())
- {
- if (!name2Impl.ContainsKey(cmd.callee)) continue;
- Succ[impl].Add(name2Impl[cmd.callee]);
- Pred[name2Impl[cmd.callee]].Add(impl);
- }
- }
- }
-
- // Build SCC
- var sccs = new StronglyConnectedComponents<Implementation>(name2Impl.Values,
- new Adjacency<Implementation>(n => Pred[n]),
- new Adjacency<Implementation>(n => Succ[n]));
- sccs.Compute();
-
- // impl -> priority
- var impl2Priority = new Dictionary<string, int>();
- int p = 0;
- foreach (var scc in sccs)
- {
- foreach (var impl in scc)
- {
- impl2Priority.Add(impl.Name, p);
- p++;
- }
- }
-
-
- Inline();
-
- #region Witness generation setup
- // Create a copy of the program
- var copy = new Dictionary<string, Implementation>();
- if (WitnessFile != null)
- {
- foreach (var impl in program.Implementations)
- {
- var nimpl = new Implementation(Token.NoToken, impl.Name, impl.TypeParameters,
- impl.InParams, impl.OutParams, new List<Variable>(impl.LocVars), new List<Block>());
- foreach (var blk in impl.Blocks)
- {
- var cd = new CodeCopier();
- nimpl.Blocks.Add(new Block(Token.NoToken, blk.Label,
- cd.CopyCmdSeq(blk.Cmds), cd.CopyTransferCmd(blk.TransferCmd)));
- }
-
- copy.Add(impl.Name, nimpl);
- }
- }
- #endregion
-
- // Turn off subsumption. Why? Because then I see multiple occurences of the
- // attached ensures in the VC
- CommandLineOptions.Clo.UseSubsumption = CommandLineOptions.SubsumptionOption.Never;
-
- // Create all VCs
- name2Impl.Values
- .Iter(GenVC);
-
- // Start the iteration
- var worklist = new SortedSet<Tuple<int, Implementation>>();
- name2Impl.Values
- .Iter(impl => worklist.Add(Tuple.Create(impl2Priority[impl.Name], impl)));
-
- while (worklist.Any())
- {
- var impl = worklist.First().Item2;
- worklist.Remove(worklist.First());
-
- var changed = ProcessImpl(impl);
-
- if (changed)
- {
- Pred[impl].Where(pred => UseBilateralAlgo || pred != impl).Iter(pred => worklist.Add(Tuple.Create(impl2Priority[pred.Name], pred)));
- }
- }
-
- var allImpls = new SortedSet<Tuple<int, string>>();
- name2Impl.Values.Iter(impl => allImpls.Add(Tuple.Create(impl2Priority[impl.Name], impl.Name)));
- if (CommandLineOptions.Clo.Trace)
- {
- foreach (var tup in allImpls)
- {
- Console.WriteLine("Summary of {0}:", tup.Item2);
- Console.WriteLine("{0}", impl2Summary[tup.Item2]);
- }
- Console.WriteLine("Prover time = {0}", proverTime.TotalSeconds.ToString("F2"));
- Console.WriteLine("Number of prover queries = " + numProverQueries);
- }
-
- ProduceWitness(copy);
-
- prover.Close();
- CommandLineOptions.Clo.TheProverFactory.Close();
- }
-
- public HashSet<string> GetPredicates()
- {
- var ret = new HashSet<string>();
- prover = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, -1);
-
- foreach (var tup in impl2Summary)
- {
- var s = tup.Value as PredicateAbs;
- if (s == null) continue;
- ret.UnionWith(s.GetPredicates(program, prover.VCExprGen, prover));
- // debug output
- //Console.WriteLine("Summary of {0}:", tup.Key);
- //Console.WriteLine("{0}", tup.Value);
- }
-
- prover.Close();
- CommandLineOptions.Clo.TheProverFactory.Close();
- return ret;
- }
-
- // Obtain the summary expression for a procedure: used programmatically by clients
- // of AbstractHoudini
- public Expr GetSummary(Program program, Procedure proc)
- {
- if (!impl2Summary.ContainsKey(proc.Name))
- return Expr.True;
-
- var vars = new Dictionary<string, Expr>();
- foreach (var g in program.GlobalVariables)
- vars.Add(g.Name, Expr.Ident(g));
- foreach (var v in proc.InParams.OfType<Variable>())
- vars.Add(v.Name, Expr.Ident(v));
- foreach (var v in proc.OutParams.OfType<Variable>())
- vars.Add(v.Name, Expr.Ident(v));
-
- return impl2Summary[proc.Name].GetSummaryExpr(
- v => { if (vars.ContainsKey(v)) return vars[v]; else return null; },
- v => { if (vars.ContainsKey(v)) return new OldExpr(Token.NoToken, vars[v]); else return null; });
- }
-
- public ISummaryElement GetSummaryLowLevel(Procedure proc)
- {
- if (!impl2Summary.ContainsKey(proc.Name)) return null;
- return impl2Summary[proc.Name];
- }
-
- // Produce a witness that proves that the inferred annotations are correct
- private void ProduceWitness(Dictionary<string, Implementation> copy)
- {
- if (WitnessFile == null)
- return;
-
- foreach (var proc in program.Procedures)
- {
- var nensures = new List<Ensures>();
- proc.Ensures.OfType<Ensures>()
- .Where(ens => !QKeyValue.FindBoolAttribute(ens.Attributes, "ah") &&
- !QKeyValue.FindBoolAttribute(ens.Attributes, "pre") &&
- !QKeyValue.FindBoolAttribute(ens.Attributes, "post") &&
- QKeyValue.FindStringAttribute(ens.Attributes, "pre") == null &&
- QKeyValue.FindStringAttribute(ens.Attributes, "post") == null)
- .Iter(ens => nensures.Add(ens));
- foreach (Ensures en in nensures)
- en.Attributes = removeAttr("InlineAssume", en.Attributes);
-
- proc.Ensures = nensures;
- }
-
- var decls = new List<Declaration>(copy.Values);
- decls.AddRange(program.TopLevelDeclarations.Where(decl => !(decl is Implementation)));
- program.TopLevelDeclarations = decls;
- var name2Proc = new Dictionary<string, Procedure>();
- foreach (var proc in program.Procedures)
- {
- name2Proc.Add(proc.Name, proc);
- if (impl2Summary.ContainsKey(proc.Name))
- {
- var ens = new Ensures(false,
- impl2Summary[proc.Name].GetSummaryExpr(
- new Func<string, Expr>(s => null), new Func<string, Expr>(s => null)));
- ens.Attributes = new QKeyValue(Token.NoToken, "inferred", new List<object>(), ens.Attributes);
- proc.Ensures.Add(ens);
- }
- }
-
- using (var wt = new TokenTextWriter(WitnessFile, /*pretty=*/ false))
- {
- program.Emit(wt);
- }
-
- // Replace SummaryPreds with their definition
- foreach (var impl in program.Implementations)
- {
- foreach (var blk in impl.Blocks)
- {
- foreach (var cmd in blk.Cmds.OfType<AssumeCmd>())
- {
- var expr = cmd.Expr as NAryExpr;
- if (expr == null) continue;
- var op = expr.Fun as FunctionCall;
- if (op == null || !op.FunctionName.EndsWith(summaryPredSuffix)) continue;
- var calleeName = op.FunctionName.Substring(0, op.FunctionName.Length - summaryPredSuffix.Length);
- if (!impl2Summary.ContainsKey(calleeName)) continue;
- var callee = name2Impl[calleeName];
-
- // variable order: globals, ins, outs, modifies
- var forold = new Dictionary<string, Expr>();
- var always = new Dictionary<string, Expr>();
- int i = 0;
- foreach (var g in program.GlobalVariables)
- {
- forold.Add(g.Name, expr.Args[i]);
- always.Add(g.Name, expr.Args[i]);
- i++;
- }
- foreach (var v in callee.InParams.OfType<Variable>())
- {
- always.Add(v.Name, expr.Args[i]);
- i++;
- }
- foreach (var v in callee.OutParams.OfType<Variable>())
- {
- always.Add(v.Name, expr.Args[i]);
- i++;
- }
- foreach (var ie in name2Proc[calleeName].Modifies.OfType<IdentifierExpr>())
- {
- always[ie.Name] = expr.Args[i];
- i++;
- }
-
- cmd.Expr = impl2Summary[calleeName].GetSummaryExpr(
- v => { if (always.ContainsKey(v)) return always[v]; else return null; },
- v => { if (forold.ContainsKey(v)) return forold[v]; else return null; });
- }
- }
- }
-
- using (var wt = new TokenTextWriter(WitnessFile, /*pretty=*/ false))
- {
- program.Emit(wt);
- }
- if (CommandLineOptions.Clo.Trace) Console.WriteLine("Witness written to {0}", WitnessFile);
- }
-
- private QKeyValue removeAttr(string key, QKeyValue attr)
- {
- if (attr == null) return attr;
- if (attr.Key == key) return removeAttr(key, attr.Next);
- attr.Next = removeAttr(key, attr.Next);
- return attr;
- }
-
- private void Inline()
- {
- if (CommandLineOptions.Clo.InlineDepth < 0)
- return;
-
- var callGraph = BuildCallGraph();
-
- foreach (Implementation impl in callGraph.Nodes)
- {
- InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
- inlineEnsuresVisitor.Visit(impl);
- }
-
- foreach (Implementation impl in callGraph.Nodes)
- {
- impl.OriginalBlocks = impl.Blocks;
- impl.OriginalLocVars = impl.LocVars;
- }
- foreach (Implementation impl in callGraph.Nodes)
- {
- CommandLineOptions.Inlining savedOption = CommandLineOptions.Clo.ProcedureInlining;
- CommandLineOptions.Clo.ProcedureInlining = CommandLineOptions.Inlining.Spec;
- Inliner.ProcessImplementationForHoudini(program, impl);
- CommandLineOptions.Clo.ProcedureInlining = savedOption;
- }
- foreach (Implementation impl in callGraph.Nodes)
- {
- impl.OriginalBlocks = null;
- impl.OriginalLocVars = null;
- }
-
- Graph<Implementation> oldCallGraph = callGraph;
- callGraph = new Graph<Implementation>();
- foreach (Implementation impl in oldCallGraph.Nodes)
- {
- callGraph.AddSource(impl);
- }
- foreach (Tuple<Implementation, Implementation> edge in oldCallGraph.Edges)
- {
- callGraph.AddEdge(edge.Item1, edge.Item2);
- }
- int count = CommandLineOptions.Clo.InlineDepth;
- while (count > 0)
- {
- foreach (Implementation impl in oldCallGraph.Nodes)
- {
- List<Implementation> newNodes = new List<Implementation>();
- foreach (Implementation succ in callGraph.Successors(impl))
- {
- newNodes.AddRange(oldCallGraph.Successors(succ));
- }
- foreach (Implementation newNode in newNodes)
- {
- callGraph.AddEdge(impl, newNode);
- }
- }
- count--;
- }
- }
-
- private Graph<Implementation> BuildCallGraph()
- {
- Graph<Implementation> callGraph = new Graph<Implementation>();
- Dictionary<Procedure, HashSet<Implementation>> procToImpls = new Dictionary<Procedure, HashSet<Implementation>>();
- foreach (var proc in program.Procedures)
- {
- procToImpls[proc] = new HashSet<Implementation>();
- }
- foreach (var impl in program.Implementations)
- {
- if (impl.SkipVerification) continue;
- callGraph.AddSource(impl);
- procToImpls[impl.Proc].Add(impl);
- }
- foreach (var impl in program.Implementations)
- {
- if (impl.SkipVerification) continue;
- foreach (Block b in impl.Blocks)
- {
- foreach (Cmd c in b.Cmds)
- {
- CallCmd cc = c as CallCmd;
- if (cc == null) continue;
- foreach (Implementation callee in procToImpls[cc.Proc])
- {
- callGraph.AddEdge(impl, callee);
- }
- }
- }
- }
- return callGraph;
- }
-
-
- private bool ProcessImpl(Implementation impl)
- {
- var ret = false;
- var gen = prover.VCExprGen;
-
- // construct summaries
- var env = VCExpressionGenerator.True;
- foreach (var tup in impl2CalleeSummaries[impl.Name])
- {
- // Not Bilateral: then reject self predicates
- if (UseBilateralAlgo == false && tup.Item1 == impl.Name)
- continue;
-
- // Bilateral: only reject self summary
- if (UseBilateralAlgo == true && tup.Item1 == impl.Name && tup.Item2)
- continue;
-
- var calleeSummary =
- impl2Summary[tup.Item1].GetSummaryExpr(
- GetVarMapping(name2Impl[tup.Item1], tup.Item4), prover.VCExprGen);
- env = gen.AndSimp(env, gen.Eq(tup.Item3, calleeSummary));
- }
-
- var prev = impl2Summary[impl.Name].Copy();
- var upper = impl2Summary[impl.Name].GetTrueSummary(program, impl);
- var sw = new Stopwatch();
- sw.Start();
- var lowerTime = TimeSpan.Zero;
-
- while(true)
- {
- var usedLower = true;
- var query = impl2Summary[impl.Name];
- sw.Restart();
-
- // construct self summaries
- var summaryExpr = VCExpressionGenerator.True;
- foreach (var tup in impl2CalleeSummaries[impl.Name])
- {
- if (UseBilateralAlgo == false && tup.Item1 != impl.Name)
- continue;
- if (UseBilateralAlgo == true && (tup.Item1 != impl.Name || !tup.Item2))
- continue;
-
- if (UseBilateralAlgo)
- {
- query = query.AbstractConsequence(upper);
- if (query == null) query = impl2Summary[tup.Item1];
- else usedLower = false;
- }
-
- var ts =
- query.GetSummaryExpr(
- GetVarMapping(name2Impl[tup.Item1], tup.Item4), prover.VCExprGen);
- summaryExpr = gen.AndSimp(summaryExpr, gen.Eq(tup.Item3, ts));
- }
- //Console.WriteLine("Trying summary for {0}: {1}", impl.Name, summaryExpr);
-
- reporter.model = null;
- var vc = gen.AndSimp(env, summaryExpr);
- vc = gen.Implies(vc, impl2VC[impl.Name]);
-
- //Console.WriteLine("Checking: {0}", vc);
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Verifying {0} ({1}): {2}", impl.Name, usedLower ? "lower" : "ac", query);
-
- if (usedLower && lowerTime.TotalMilliseconds >= iterTimeLimit && iterTimeLimit >= 0)
- {
- if (UseBilateralAlgo)
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
- ret = prev.IsEqual(upper) ? false : true;
- impl2Summary[impl.Name] = upper;
- break;
- }
- else
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
- var tt = impl2Summary[impl.Name].GetTrueSummary(program, impl);
- ret = prev.IsEqual(tt) ? false : true; ;
- impl2Summary[impl.Name] = tt;
- break;
- }
- }
-
- var start = DateTime.Now;
-
- //prover.Push();
- //prover.Assert(gen.Not(vc), true);
- //prover.FlushAxiomsToTheoremProver();
- //prover.Check();
- //ProverInterface.Outcome proverOutcome = prover.CheckOutcome(reporter);
- //prover.Pop();
-
- prover.BeginCheck(impl.Name, vc, reporter);
- ProverInterface.Outcome proverOutcome = prover.CheckOutcome(reporter);
-
- var inc = (DateTime.Now - start);
- proverTime += inc;
- numProverQueries++;
-
- sw.Stop();
- if (usedLower) lowerTime += sw.Elapsed;
-
- if(CommandLineOptions.Clo.Trace)
- Console.WriteLine("Time taken = " + inc.TotalSeconds.ToString());
-
- if (UseBilateralAlgo)
- {
- if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
- {
- if(CommandLineOptions.Clo.Trace)
- Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
- ret = prev.IsEqual(upper) ? false : true;
- impl2Summary[impl.Name] = upper;
- break;
- }
-
- if (reporter.model == null && usedLower)
- break;
-
- if (reporter.model == null)
- {
- upper.Meet(query);
- }
- else
- {
- var state = CollectState(impl);
- impl2Summary[impl.Name].Join(state, reporter.model);
- ret = true;
- }
- }
- else
- {
- if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
- var tt = impl2Summary[impl.Name].GetTrueSummary(program, impl);
- ret = prev.IsEqual(tt) ? false : true; ;
- impl2Summary[impl.Name] = tt;
- break;
- }
-
- if (reporter.model == null)
- break;
- //reporter.model.Write(Console.Out);
-
- var state = CollectState(impl);
- impl2Summary[impl.Name].Join(state, reporter.model);
- ret = true;
- }
- }
- return ret;
- }
-
- private Dictionary<string, VCExpr> GetVarMapping(Implementation impl, VCExprNAry summaryPred)
- {
- var ret = new Dictionary<string, VCExpr>();
-
- var cnt = 0;
- foreach (var g in program.GlobalVariables)
- {
- ret.Add(string.Format("old({0})", g.Name), summaryPred[cnt]);
- cnt++;
- }
- foreach (var v in impl.InParams.OfType<Variable>().Concat(
- impl.OutParams.OfType<Variable>().Concat(
- impl.Proc.Modifies.OfType<IdentifierExpr>().Select(ie => ie.Decl))))
- {
- ret.Add(v.Name, summaryPred[cnt]);
- cnt++;
- }
-
- // Fill up values of globals that are not modified
- cnt = 0;
- foreach (var g in program.GlobalVariables)
- {
- if (ret.ContainsKey(g.Name)) { cnt++; continue; }
-
- ret.Add(string.Format("{0}", g.Name), summaryPred[cnt]);
- cnt++;
- }
-
- // Constants
- foreach (var c in program.Constants)
- {
- var value = prover.Context.BoogieExprTranslator.Translate(Expr.Ident(c));
- ret.Add(string.Format("{0}", c.Name), value);
- ret.Add(string.Format("old({0})", c.Name), value);
- }
-
- return ret;
- }
-
- private Dictionary<string, Model.Element> CollectState(Implementation impl)
- {
- var ret = new Dictionary<string, Model.Element>();
-
- var model = reporter.model;
- var implVars = impl2EndStateVars[impl.Name];
-
- var cnt = 0;
- foreach (var g in program.GlobalVariables)
- {
- ret.Add(string.Format("old({0})", g.Name), getValue(implVars[cnt], model));
- cnt++;
- }
- foreach (var v in impl.InParams.OfType<Variable>().Concat(
- impl.OutParams.OfType<Variable>().Concat(
- impl.Proc.Modifies.OfType<IdentifierExpr>().Select(ie => ie.Decl))))
- {
- ret.Add(v.Name, getValue(implVars[cnt], model));
- cnt++;
- }
-
- // Fill up values of globals that are not modified
- cnt = 0;
- foreach (var g in program.GlobalVariables)
- {
- if (ret.ContainsKey(g.Name)) { cnt++; continue; }
-
- ret.Add(string.Format("{0}", g.Name), getValue(implVars[cnt], model));
- cnt++;
- }
-
- // Constants
- foreach (var c in program.Constants)
- {
- try
- {
- var value = getValue(prover.Context.BoogieExprTranslator.Translate(Expr.Ident(c)), model);
- ret.Add(string.Format("{0}", c.Name), value);
- ret.Add(string.Format("old({0})", c.Name), value);
- }
- catch (Exception)
- {
- // constant not assigned a value: add a default value
- Model.Element value = null;
- if (c.TypedIdent.Type.IsInt)
- value = model.MkIntElement(0);
- else if (c.TypedIdent.Type.IsBool)
- value = model.MkElement("false");
-
- ret.Add(string.Format("{0}", c.Name), value);
- ret.Add(string.Format("old({0})", c.Name), value);
- }
- }
-
- return ret;
- }
-
- private Model.Element getValue(VCExpr arg, Model model)
- {
- if (arg is VCExprLiteral)
- {
- //return model.GetElement(arg.ToString());
- return model.MkElement(arg.ToString());
- }
- else if (arg is VCExprVar)
- {
- var el = model.TryGetFunc(prover.Context.Lookup(arg as VCExprVar));
- if (el != null)
- {
- Debug.Assert(el.Arity == 0 && el.AppCount == 1);
- return el.Apps.First().Result;
- }
- else
- {
- // Variable not defined; assign arbitrary value
- if (arg.Type.IsBool)
- return model.MkElement("false");
- else if (arg.Type.IsInt)
- return model.MkIntElement(0);
- else
- return null;
- }
- }
- else
- {
- Debug.Assert(false);
- return null;
- }
- }
-
- private void attachEnsures(Implementation impl)
- {
- List<Variable> functionInterfaceVars = new List<Variable>();
- foreach (Variable v in vcgen.program.GlobalVariables)
- {
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
- }
- foreach (Variable v in impl.InParams)
- {
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
- }
- foreach (Variable v in impl.OutParams)
- {
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
- }
- foreach (IdentifierExpr e in impl.Proc.Modifies)
- {
- if (e.Decl == null) continue;
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", e.Decl.TypedIdent.Type), true));
- }
- Formal returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false);
- var function = new Function(Token.NoToken, impl.Name + summaryPredSuffix, functionInterfaceVars, returnVar);
- prover.Context.DeclareFunction(function, "");
-
- List<Expr> exprs = new List<Expr>();
- foreach (Variable v in vcgen.program.GlobalVariables)
- {
- Contract.Assert(v != null);
- exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
- }
- foreach (Variable v in impl.Proc.InParams)
- {
- Contract.Assert(v != null);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- foreach (Variable v in impl.Proc.OutParams)
- {
- Contract.Assert(v != null);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- foreach (IdentifierExpr ie in impl.Proc.Modifies)
- {
- Contract.Assert(ie != null);
- if (ie.Decl == null)
- continue;
- exprs.Add(ie);
- }
- Expr postExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
- impl.Proc.Ensures.Add(
- new Ensures(Token.NoToken, false, postExpr, "",
- new QKeyValue(Token.NoToken, "ah", new List<object>(), null)));
- }
-
- private void GenVC(Implementation impl)
- {
- ModelViewInfo mvInfo;
- Dictionary<int, Absy> label2absy;
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Generating VC of {0}", impl.Name);
- }
-
- vcgen.ConvertCFG2DAG(impl);
- vcgen.PassifyImpl(impl, out mvInfo);
-
- var gen = prover.VCExprGen;
- var vcexpr = vcgen.GenerateVC(impl, null, out label2absy, prover.Context);
-
-
- // Find the assert
- impl2EndStateVars.Add(impl.Name, new List<VCExpr>());
- var found = false;
- var assertId = -1;
- foreach (var blk in impl.Blocks)
- {
- foreach (var cmd in blk.Cmds.OfType<AssertCmd>())
- {
- if (SimpleUtil.isAssertTrue(cmd)) continue;
- var nary = cmd.Expr as NAryExpr;
- if (nary == null) continue;
- var pred = nary.Fun as FunctionCall;
- if (pred == null || pred.FunctionName != (impl.Name + (AbstractHoudini.summaryPredSuffix)))
- continue;
-
- Debug.Assert(!found);
- found = true;
- assertId = cmd.UniqueId;
- //Console.WriteLine("assert cmd id: {0}", cmd.UniqueId);
- nary.Args.OfType<Expr>()
- .Iter(expr => impl2EndStateVars[impl.Name].Add(prover.Context.BoogieExprTranslator.Translate(expr)));
- }
- }
-
- // It is possible that no assert is found in the procedure. It happens when the
- // procedure doesn't return.
- //Debug.Assert(found);
-
- // Grab summary predicates
- var visitor = new FindSummaryPred(prover.VCExprGen, assertId);
- vcexpr = visitor.Mutate(vcexpr, true);
-
- // Create a macro so that the VC can sit with the theorem prover
- Macro macro = new Macro(Token.NoToken, impl.Name + "Macro", new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false));
- prover.DefineMacro(macro, vcexpr);
-
- // Store VC
- impl2VC.Add(impl.Name, gen.Function(macro));
-
- //Console.WriteLine("VC of {0}: {1}", impl.Name, vcexpr);
-
- // check sanity: only one predicate for self-summary
- // (There may be none when the procedure doesn't return)
- Debug.Assert(visitor.summaryPreds.Count(tup => tup.Item2) <= 1);
-
- impl2CalleeSummaries.Add(impl.Name, new List<Tuple<string, bool, VCExprVar, VCExprNAry>>());
- visitor.summaryPreds.Iter(tup => impl2CalleeSummaries[impl.Name].Add(tup));
- }
- }
-
- public interface ISummaryElement
- {
- ISummaryElement Copy();
- ISummaryElement GetFlaseSummary(Program program, Implementation impl);
- void Join(Dictionary<string, Model.Element> state, Model model);
- VCExpr GetSummaryExpr(Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen);
- Expr GetSummaryExpr(Func<string, Expr> always, Func<string, Expr> forold);
-
- // For Bilateral
- ISummaryElement GetTrueSummary(Program program, Implementation impl);
- void Meet(ISummaryElement other);
- bool IsEqual(ISummaryElement other);
- ISummaryElement AbstractConsequence(ISummaryElement upper);
- }
-
- public class ConstantVal : ISummaryElement
- {
- Program program;
- Implementation impl;
- // var -> const set
- Dictionary<string, HashSet<int>> val;
- // set of vars
- HashSet<Variable> vars;
-
- public static readonly int MAX = 3;
-
- public ConstantVal()
- {
- // this is just a place holder
- val = new Dictionary<string, HashSet<int>>();
- vars = new HashSet<Variable>();
- }
-
- private ConstantVal(Program program, Implementation impl)
- {
- this.program = program;
- this.impl = impl;
- this.val = new Dictionary<string, HashSet<int>>();
-
- vars = new HashSet<Variable>();
- impl.Proc.Modifies
- .OfType<IdentifierExpr>()
- .Select(ie => ie.Decl)
- .Where(v => v.TypedIdent.Type.IsInt)
- .Iter(v => vars.Add(v));
- impl.OutParams.OfType<Variable>()
- .Where(v => v.TypedIdent.Type.IsInt)
- .Iter(v => vars.Add(v));
-
- vars.Iter(v => val.Add(v.Name, null));
- }
-
-
- public void Join(Dictionary<string, Model.Element> state, Model model)
- {
- foreach (var vv in vars)
- {
- var v = vv.Name;
- var newv = state[v].AsInt();
- var oldv = val[v];
-
- if (oldv == null)
- {
- val[v] = new HashSet<int>();
- val[v].Add(newv);
- }
- else if(oldv.Count > 0)
- {
- val[v].Add(newv);
- if (val[v].Count > MAX)
- val[v] = new HashSet<int>();
- }
-
- }
- }
-
- public VCExpr GetSummaryExpr(Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen)
- {
- VCExpr ret = VCExpressionGenerator.True;
- if (val.Values.Any(v => v == null))
- return VCExpressionGenerator.False;
-
- foreach (var v in vars)
- {
- var consts = val[v.Name];
- Debug.Assert(consts != null);
-
- if (consts.Count == 0)
- continue;
-
- var vexpr = VCExpressionGenerator.False;
- consts.Iter(c => vexpr = gen.OrSimp(vexpr, gen.Eq(incarnations[v.Name], gen.Integer(Microsoft.Basetypes.BigNum.FromInt(c)))));
- ret = gen.AndSimp(ret, vexpr);
- }
-
- return ret;
- }
-
- public override string ToString()
- {
- var ret = "true";
- if (val.Values.Any(v => v == null))
- return "false";
-
- foreach (var v in vars)
- {
- var consts = val[v.Name];
- Debug.Assert(consts != null);
-
- if (consts.Count == 0)
- continue;
-
- var vexpr = "false";
- consts.Iter(c => vexpr =
- string.Format("{0} OR ({1} == {2})", vexpr, v.Name, c));
-
- ret = string.Format("{0} AND ({1})", ret, vexpr);
- }
-
- return ret;
- }
-
-
- public ISummaryElement GetFlaseSummary(Program program, Implementation impl)
- {
- return new ConstantVal(program, impl);
- }
-
- #region ISummaryElement (Bilateral) Members
-
-
- public ISummaryElement GetTrueSummary(Program program, Implementation impl)
- {
- throw new NotImplementedException();
- }
-
- public void Meet(ISummaryElement other)
- {
- throw new NotImplementedException();
- }
-
- public bool IsEqual(ISummaryElement other)
- {
- throw new NotImplementedException();
- }
-
- public ISummaryElement AbstractConsequence(ISummaryElement upper)
- {
- throw new NotImplementedException();
- }
-
- #endregion
-
- #region ISummaryElement Members
-
-
- public Expr GetSummaryExpr(Func<string, Expr> always, Func<string, Expr> forold)
- {
- throw new NotImplementedException();
- }
-
- #endregion
-
- #region ISummaryElement Members
-
- public ISummaryElement Copy()
- {
- throw new NotImplementedException();
- }
-
- #endregion
- }
-
- public class NamedExpr
- {
- public string name;
- public Expr expr;
-
- public NamedExpr(string name, Expr expr)
- {
- this.name = name;
- this.expr = expr;
- }
-
- public NamedExpr(Expr expr)
- {
- this.name = null;
- this.expr = expr;
- }
-
- public override string ToString()
- {
- if (name != null)
- return name;
-
- return expr.ToString();
- }
- }
-
- public class PredicateAbs : ISummaryElement
- {
- public static Dictionary<string, List<NamedExpr>> PrePreds { get; private set; }
- public static Dictionary<string, HashSet<int>> PosPrePreds { get; private set; }
- public static Dictionary<string, List<NamedExpr>> PostPreds { get; private set; }
- public static Dictionary<Tuple<string, int>, List<PredicateAbsDisjunct>> UpperCandidates;
- private static HashSet<string> boolConstants;
- // {proc, pred-pair} -> polariry
- public static HashSet<Tuple<string, int, int, bool, bool>> unsatPrePredPairs;
- public static HashSet<Tuple<string, int, int, bool, bool>> unsatPostPredPairs;
-
- // Temporary: used during eval
- private static Model model = null;
-
- string procName;
- PredicateAbsDisjunct[] value;
- bool isFalse;
-
- public PredicateAbs(string procName)
- {
- this.procName = procName;
- isFalse = true;
- value = new PredicateAbsDisjunct[PostPreds[this.procName].Count];
- for (int i = 0; i < PostPreds[this.procName].Count; i++) value[i] = null;
- }
-
- public static void Initialize(Program program)
- {
- PrePreds = new Dictionary<string, List<NamedExpr>>();
- PostPreds = new Dictionary<string, List<NamedExpr>>();
- PosPrePreds = new Dictionary<string, HashSet<int>>();
-
- boolConstants = new HashSet<string>();
- UpperCandidates = new Dictionary<Tuple<string, int>, List<PredicateAbsDisjunct>>();
-
- program.Constants
- .Where(c => c.TypedIdent.Type.IsBool)
- .Iter(c => boolConstants.Add(c.Name));
-
- // Add template pre-post to all procedures
- var preT = new List<NamedExpr>();
- var postT = new List<NamedExpr>();
- var posPreT = new HashSet<int>();
- var tempP = new HashSet<Procedure>();
- foreach (var proc in
- program.Procedures
- .Where(proc => QKeyValue.FindBoolAttribute(proc.Attributes, "template")))
- {
- tempP.Add(proc);
- foreach (var ens in proc.Ensures.OfType<Ensures>())
- {
- var pos = QKeyValue.FindBoolAttribute(ens.Attributes, "positive");
-
- if (QKeyValue.FindBoolAttribute(ens.Attributes, "pre"))
- {
- preT.Add(new NamedExpr(null, ens.Condition));
- if (pos) posPreT.Add(preT.Count - 1);
- }
-
- if (QKeyValue.FindBoolAttribute(ens.Attributes, "post"))
- postT.Add(new NamedExpr(null, ens.Condition));
-
- var s = QKeyValue.FindStringAttribute(ens.Attributes, "pre");
- if (s != null)
- {
- preT.Add(new NamedExpr(s, ens.Condition));
- if (pos) posPreT.Add(preT.Count - 1);
- }
-
- s = QKeyValue.FindStringAttribute(ens.Attributes, "post");
- if (s != null)
- postT.Add(new NamedExpr(s, ens.Condition));
- }
- }
-
- program.RemoveTopLevelDeclarations(decl => tempP.Contains(decl));
- var upperPreds = new Dictionary<string, List<Expr>>();
-
- foreach (var impl in program.Implementations)
- {
- PrePreds.Add(impl.Name, new List<NamedExpr>());
- PostPreds.Add(impl.Name, new List<NamedExpr>());
- PosPrePreds.Add(impl.Name, new HashSet<int>());
-
- // Add "false" as the first post predicate
- //PostPreds[impl.Name].Add(new NamedExpr(Expr.False));
-
- preT.Iter(e => PrePreds[impl.Name].Add(e));
- postT.Iter(e => PostPreds[impl.Name].Add(e));
- PosPrePreds[impl.Name].UnionWith(posPreT);
-
- // Pick up per-procedure pre-post
- var nens = new List<Ensures>();
- foreach (var ens in impl.Proc.Ensures.OfType<Ensures>())
- {
- string s = null;
- var pos = QKeyValue.FindBoolAttribute(ens.Attributes, "positive");
-
- if (QKeyValue.FindBoolAttribute(ens.Attributes, "pre"))
- {
- PrePreds[impl.Name].Add(new NamedExpr(ens.Condition));
- PosPrePreds[impl.Name].Add(PrePreds[impl.Name].Count - 1);
- }
- else if (QKeyValue.FindBoolAttribute(ens.Attributes, "post"))
- {
- PostPreds[impl.Name].Add(new NamedExpr(ens.Condition));
- }
- else if ((s = QKeyValue.FindStringAttribute(ens.Attributes, "pre")) != null)
- {
- PrePreds[impl.Name].Add(new NamedExpr(s, ens.Condition));
- PosPrePreds[impl.Name].Add(PrePreds[impl.Name].Count - 1);
- }
- else if ((s = QKeyValue.FindStringAttribute(ens.Attributes, "post")) != null)
- {
- PostPreds[impl.Name].Add(new NamedExpr(s, ens.Condition));
- }
- else if (QKeyValue.FindBoolAttribute(ens.Attributes, "upper"))
- {
- var key = impl.Name;
- if (!upperPreds.ContainsKey(key))
- upperPreds.Add(key, new List<Expr>());
- upperPreds[key].Add(ens.Condition);
- }
- else
- {
- nens.Add(ens);
- }
- }
- impl.Proc.Ensures = nens;
- }
-
- foreach (var tup in upperPreds)
- {
- var procName = tup.Key;
- var candidates = tup.Value;
- if (!candidates.Any()) continue;
-
- var strToPost = new Dictionary<string, int>();
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- strToPost.Add(PostPreds[procName][i].expr.ToString(), i);
- }
-
- foreach (var expr in candidates)
- {
- if (strToPost.ContainsKey(expr.ToString()))
- {
- var key = Tuple.Create(procName, strToPost[expr.ToString()]);
- if (!UpperCandidates.ContainsKey(key))
- UpperCandidates.Add(key, new List<PredicateAbsDisjunct>());
- UpperCandidates[key].Add(new PredicateAbsDisjunct(true, procName));
- }
- else
- {
- // Try parsing the expression as (pre-conjunct ==> post-pred)
- var parsed = ParseExpr(expr, procName);
- if (parsed != null && strToPost.ContainsKey(parsed.Item2.ToString()))
- {
- var key = Tuple.Create(procName, strToPost[parsed.Item2.ToString()]);
- if (!UpperCandidates.ContainsKey(key))
- UpperCandidates.Add(key, new List<PredicateAbsDisjunct>());
- UpperCandidates[key].Add(parsed.Item1);
- }
- }
- }
-
- }
- //Console.WriteLine("Running Abstract Houdini");
- //PostPreds.Iter(expr => Console.WriteLine("\tPost: {0}", expr));
- //PrePreds.Iter(expr => Console.WriteLine("\tPre: {0}", expr));
- }
-
- // Try parsing the expression as (pre-conjunct ==> post-pred)
- private static Tuple<PredicateAbsDisjunct, Expr> ParseExpr(Expr expr, string procName)
- {
- Expr postExpr = null;
- Expr preExpr = null;
-
- // Decompose outer Implies
- var nexpr = expr as NAryExpr;
- if (nexpr != null && (nexpr.Fun is BinaryOperator)
- && (nexpr.Fun as BinaryOperator).Op == BinaryOperator.Opcode.Imp
- && (nexpr.Args.Count == 2))
- {
- postExpr = nexpr.Args[1];
- preExpr = nexpr.Args[0];
- }
- else
- {
- if(CommandLineOptions.Clo.Trace) Console.WriteLine("Failed to parse {0} (ignoring)", expr);
- return null;
- }
-
-
- var atoms = DecomposeOuterAnd(preExpr);
- var pos = new HashSet<int>();
- var neg = new HashSet<int>();
-
- foreach (var atom in atoms)
- {
- var index = PrePreds[procName].FindIndex(ne => ne.expr.ToString() == atom.ToString());
- if (index == -1)
- {
- index = PrePreds[procName].FindIndex(ne => Expr.Not(ne.expr).ToString() == atom.ToString());
- if (index == -1)
- {
- if(CommandLineOptions.Clo.Trace) Console.WriteLine("Failed to parse {0} (ignoring)", atom);
- return null;
- }
- else
- {
- neg.Add(index);
- }
- }
- else
- {
- pos.Add(index);
- }
- }
-
- var conj = new PredicateAbsConjunct(pos, neg, procName);
- var conjls = new List<PredicateAbsConjunct>();
- conjls.Add(conj);
-
- return Tuple.Create(new PredicateAbsDisjunct(conjls, procName), postExpr);
- }
-
- // blah && blah ==> {blah, blah}
- static IEnumerable<Expr> DecomposeOuterAnd(Expr expr)
- {
- var ret = new List<Expr>();
-
- var nexpr = expr as NAryExpr;
- if (nexpr == null
- || !(nexpr.Fun is BinaryOperator)
- || (nexpr.Fun as BinaryOperator).Op != BinaryOperator.Opcode.And)
- {
- ret.Add(expr);
- }
- else
- {
- foreach (Expr a in nexpr.Args)
- ret.AddRange(DecomposeOuterAnd(a));
- }
-
- return ret;
- }
-
-
- private Model.Element Eval(Expr expr, Dictionary<string, Model.Element> state)
- {
- if (expr is LiteralExpr)
- {
- return ToElem((expr as LiteralExpr).Val);
- }
-
- if (expr is IdentifierExpr)
- {
- return LookupVariable((expr as IdentifierExpr).Name, state, false);
- }
-
- if (expr is OldExpr)
- {
- var ide = (expr as OldExpr).Expr as IdentifierExpr;
- Debug.Assert(ide != null);
-
- return LookupVariable(ide.Name, state, true);
- }
-
- if (expr is NAryExpr)
- {
- var nary = expr as NAryExpr;
- if (nary.Fun is UnaryOperator)
- {
- return ToElem((nary.Fun as UnaryOperator).Evaluate(ToValue(Eval(nary.Args[0], state))));
- }
- if (nary.Fun is BinaryOperator)
- {
- return ToElem((nary.Fun as BinaryOperator).Evaluate(ToValue(Eval(nary.Args[0], state)), ToValue(Eval(nary.Args[1], state))));
- }
- if (nary.Fun is MapSelect && nary.Args.Count == 2)
- {
- var index = Eval(nary.Args[1], state);
- var map = Eval(nary.Args[0], state) as Model.Array;
- Debug.Assert(map != null, "Variable of map type must have an Array-typed value");
- var ret = map.Value.TryEval(index as Model.Element);
- if (ret == null) ret = map.Value.Else;
- Debug.Assert(ret != null);
- return ret;
- }
- Debug.Assert(false, "No other op is handled");
- }
- throw new NotImplementedException(string.Format("Expr of type {0} is not handled", expr.GetType().ToString()));
- }
-
- private Model.Element LookupVariable(string v, Dictionary<string, Model.Element> state, bool tryOld)
- {
- if (tryOld)
- {
- var oldv = string.Format("old({0})", v);
- if (state.ContainsKey(oldv))
- {
- return state[oldv];
- }
- throw new AbsHoudiniInternalError("Cannot handle this case");
- }
-
- if (state.ContainsKey(v))
- {
- return state[v];
- }
-
- /*
- if (boolConstants.Contains(v))
- {
- // value of this constant is immaterial, return true
- return model.MkElement("true");
- }
- */
-
- throw new AbsHoudiniInternalError("Cannot handle this case");
- }
-
- private static VCExpr ToVcVar(string v, Dictionary<string, VCExpr> incarnations, bool tryOld)
- {
- if (tryOld)
- {
- var oldv = string.Format("old({0})", v);
- if (incarnations.ContainsKey(oldv))
- {
- return incarnations[oldv];
- }
- throw new AbsHoudiniInternalError("Cannot handle this case");
- }
-
- if (incarnations.ContainsKey(v))
- {
- return incarnations[v];
- }
-
- throw new AbsHoudiniInternalError("Cannot handle this case");
- }
-
- public static void FindUnsatPairs(VCExpressionGenerator gen, ProverInterface prover)
- {
- unsatPrePredPairs = new HashSet<Tuple<string, int, int, bool, bool>>();
- unsatPostPredPairs = new HashSet<Tuple<string, int, int, bool, bool>>();
-
- var cachePos = new HashSet<Tuple<string, string>>();
- var cacheNeg = new HashSet<Tuple<string, string>>();
- var record = new Action<object, string, int, int, bool, bool>(
- (map, proc, e1, e2, p1, p2) => {
- var key = Tuple.Create(proc, e1, e2, p1, p2);
- if (map == PrePreds)
- unsatPrePredPairs.Add(key);
- else
- unsatPostPredPairs.Add(key);
- }
- );
-
- var predMaps = new List<Dictionary<string, List<NamedExpr>>>();
- predMaps.Add(PrePreds); predMaps.Add(PostPreds);
-
- foreach (var map in predMaps)
- {
- foreach (var proc in map.Keys)
- {
- for (int i = 0; i < 2 * map[proc].Count(); i++)
- {
- var p1 = (i % 2); // polarity
- var e1 = map[proc][i / 2].expr;
- if (p1 == 0) e1 = Expr.Not(e1);
-
- for (int j = 2 * ((i / 2) + 1); j < 2 * map[proc].Count(); j++)
- {
- var p2 = (j % 2); // polarity
- var e2 = map[proc][j / 2].expr;
- if (p2 == 0) e2 = Expr.Not(e2);
-
- var key = Tuple.Create(e1.ToString(), e2.ToString());
- if (cachePos.Contains(key))
- {
- record(map, proc, i / 2, j / 2, p1 == 1, p2 == 1);
- continue;
- }
- else if (cacheNeg.Contains(key))
- {
- continue;
- }
-
- if (!CheckIfUnsat(e1, e2, gen, prover))
- {
- cacheNeg.Add(key);
- continue;
- }
- cachePos.Add(key);
- record(map, proc, i / 2, j / 2, p1 == 1, p2 == 1);
-
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Proved UNSAT: {0} {1}", e1, e2);
- }
- }
- }
- }
- }
-
- // Is a ^ b UNSAT?
- private static bool CheckIfUnsat(Expr a, Expr b, VCExpressionGenerator gen, ProverInterface prover)
- {
- var gatherLitA = new GatherLiterals();
- var gatherLitB = new GatherLiterals();
-
- gatherLitA.Visit(a);
- gatherLitB.Visit(b);
-
- var seta = new HashSet<Variable>();
- var setb = new HashSet<Variable>();
- gatherLitA.literals.Iter(tup => seta.Add(tup.Item1));
- gatherLitB.literals.Iter(tup => setb.Add(tup.Item1));
- seta.IntersectWith(setb);
- if (!seta.Any()) return false;
-
- // Create fresh variables
- return CheckIfUnsat(Expr.And(a, b), gen, prover);
- }
-
- // Is a UNSAT?
- private static bool CheckIfUnsat(Expr a, VCExpressionGenerator gen, ProverInterface prover)
- {
- var gatherLitA = new GatherLiterals();
- gatherLitA.Visit(a);
-
- // Create fresh variables
- var counter = 0;
- var incarnations = new Dictionary<string, VCExpr>();
- foreach (var literal in gatherLitA.literals)
- {
- if (incarnations.ContainsKey(literal.Item2.ToString()))
- continue;
-
- //if(!literal.Item1.TypedIdent.Type.IsInt && !literal.Item1.TypedIdent.Type.IsBool)
- var v = gen.Variable("UNSATCheck" + counter, literal.Item1.TypedIdent.Type);
- incarnations.Add(literal.Item2.ToString(), v);
- counter++;
- }
-
- var vc1 = ToVcExpr(a, incarnations, gen);
- var vc = gen.LabelPos("Temp", vc1);
-
- // check
- prover.AssertAxioms();
- prover.Push();
- prover.Assert(vc, true);
- prover.Check();
- var outcome = prover.CheckOutcomeCore(new AbstractHoudiniErrorReporter());
- prover.Pop();
-
- if (outcome == ProverInterface.Outcome.Valid)
- return true;
- return false;
- }
-
-
- class GatherLiterals : ReadOnlyVisitor
- {
- public List<Tuple<Variable, Expr>> literals;
- bool inOld;
-
- public GatherLiterals()
- {
- literals = new List<Tuple<Variable, Expr>>();
- inOld = false;
- }
-
- public override Expr VisitOldExpr(OldExpr node)
- {
- var prev = inOld;
- inOld = true;
- var ret = base.VisitOldExpr(node);
- inOld = prev;
- return ret;
- }
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node)
- {
- if (inOld)
- literals.Add(Tuple.Create(node.Decl, new OldExpr(Token.NoToken, node) as Expr));
- else
- literals.Add(Tuple.Create(node.Decl, node as Expr));
-
- return node;
- }
- }
-
- private object ToValue(Model.Element elem)
- {
- if (elem is Model.Integer)
- {
- return Microsoft.Basetypes.BigNum.FromInt((elem as Model.Integer).AsInt());
- }
- if (elem is Model.Boolean)
- {
- return (elem as Model.Boolean).Value;
- }
- if (elem is Model.DatatypeValue && (elem as Model.DatatypeValue).Arguments.Length == 1 &&
- (elem as Model.DatatypeValue).ConstructorName == "-" &&
- (elem as Model.DatatypeValue).Arguments[0] is Model.Integer)
- {
- // negative number as "-" @ int
- return Microsoft.Basetypes.BigNum.FromInt(-1 * ((elem as Model.DatatypeValue).Arguments[0] as Model.Integer).AsInt());
- }
- throw new NotImplementedException("Cannot yet handle this Model.Element type");
- }
-
- private Model.Element ToElem(object val)
- {
- if (val is bool || val is int || val is Basetypes.BigNum)
- return model.MkElement(val.ToString());
- throw new NotImplementedException("Cannot yet handle this value type");
- }
-
- // replace v by old(v)
- private static Expr MakeOld(Expr expr)
- {
- var substalways = new Substitution(v => new OldExpr(Token.NoToken, Expr.Ident(v)));
- var substold = new Substitution(v => Expr.Ident(v));
-
- return Substituter.ApplyReplacingOldExprs(substalways, substold, expr);
- }
-
- private static Expr ToExpr(Expr expr, Func<string, Expr> always, Func<string, Expr> forold)
- {
- var substalways = new Substitution(v =>
- {
- var ret = always(v.Name);
- if (ret != null) return ret;
- else return Expr.Ident(v);
- });
- var substold = new Substitution(v =>
- {
- var ret = forold(v.Name);
- if (ret != null) return ret;
- else return new OldExpr(Token.NoToken, Expr.Ident(v));
- });
-
- return Substituter.ApplyReplacingOldExprs(substalways, substold, expr);
- }
-
- private static VCExpr ToVcExpr(Expr expr, Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen)
- {
- if (expr is LiteralExpr)
- {
- var val = (expr as LiteralExpr).Val;
- if (val is bool)
- {
- if ((bool)val)
- {
- return VCExpressionGenerator.True;
- }
- else
- {
- return VCExpressionGenerator.False;
- }
- }
- else if (val is Microsoft.Basetypes.BigNum)
- {
- return gen.Integer((Microsoft.Basetypes.BigNum)val);
- }
-
- throw new NotImplementedException("Cannot handle literals of this type");
- }
-
- if (expr is IdentifierExpr)
- {
- return ToVcVar((expr as IdentifierExpr).Name, incarnations, false);
- }
-
- if (expr is OldExpr)
- {
- var ide = (expr as OldExpr).Expr as IdentifierExpr;
- Debug.Assert(ide != null);
-
- return ToVcVar(ide.Name, incarnations, true);
- }
-
- if (expr is NAryExpr)
- {
- var nary = expr as NAryExpr;
- if (nary.Fun is UnaryOperator)
- {
- if ((nary.Fun as UnaryOperator).Op == UnaryOperator.Opcode.Not)
- return gen.Not(ToVcExpr(nary.Args[0], incarnations, gen));
- else if ((nary.Fun as UnaryOperator).Op == UnaryOperator.Opcode.Neg)
- return gen.Function(VCExpressionGenerator.SubIOp, gen.Integer(Basetypes.BigNum.FromInt(0)), ToVcExpr(nary.Args[0], incarnations, gen));
- else
- Debug.Assert(false, "No other unary op is handled");
- }
- if (nary.Fun is BinaryOperator)
- {
- return gen.Function(Translate(nary.Fun as BinaryOperator), ToVcExpr(nary.Args[0], incarnations, gen), ToVcExpr(nary.Args[1], incarnations, gen));
- }
- if (nary.Fun is MapSelect && nary.Args.Count == 2)
- {
- return gen.Select(ToVcExpr(nary.Args[0], incarnations, gen), ToVcExpr(nary.Args[1], incarnations, gen));
- }
- Debug.Assert(false, "No other op is handled");
- }
- throw new NotImplementedException(string.Format("Expr of type {0} is not handled", expr.GetType().ToString()));
- }
-
- private static VCExprOp Translate(BinaryOperator op)
- {
- switch (op.Op)
- {
- case BinaryOperator.Opcode.Add:
- return VCExpressionGenerator.AddIOp;
- case BinaryOperator.Opcode.Sub:
- return VCExpressionGenerator.SubIOp;
- case BinaryOperator.Opcode.Mul:
- return VCExpressionGenerator.MulIOp;
- case BinaryOperator.Opcode.Div:
- return VCExpressionGenerator.DivIOp;
- case BinaryOperator.Opcode.Mod:
- return VCExpressionGenerator.ModOp;
- case BinaryOperator.Opcode.Eq:
- case BinaryOperator.Opcode.Iff:
- // we don't distinguish between equality and equivalence at this point
- return VCExpressionGenerator.EqOp;
- case BinaryOperator.Opcode.Neq:
- return VCExpressionGenerator.NeqOp;
- case BinaryOperator.Opcode.Lt:
- return VCExpressionGenerator.LtOp;
- case BinaryOperator.Opcode.Le:
- return VCExpressionGenerator.LeOp;
- case BinaryOperator.Opcode.Ge:
- return VCExpressionGenerator.GeOp;
- case BinaryOperator.Opcode.Gt:
- return VCExpressionGenerator.GtOp;
- case BinaryOperator.Opcode.Imp:
- return VCExpressionGenerator.ImpliesOp;
- case BinaryOperator.Opcode.And:
- return VCExpressionGenerator.AndOp;
- case BinaryOperator.Opcode.Or:
- return VCExpressionGenerator.OrOp;
- case BinaryOperator.Opcode.Subtype:
- return VCExpressionGenerator.SubtypeOp;
- default:
- Contract.Assert(false);
- throw new NotImplementedException();
- }
-
- }
-
- // If "false" is a post-predicate, then remove its "pre" constraint from all others, whenever possible
- public void Simplify()
- {
- // find "false"
- var findex = PostPreds[procName].FindIndex(ne => (ne.expr is LiteralExpr) && (ne.expr as LiteralExpr).IsFalse);
- if (findex < 0) return;
- if (value[findex].isTrue)
- {
- // procedure doesn't return
- for (int i = 0; i < value.Length; i++)
- if (i != findex) value[i] = new PredicateAbsDisjunct(false, procName);
- return;
- }
- if (value[findex].isFalse)
- return;
-
- for (int i = 0; i < value.Length; i++)
- if (i != findex) value[i].Subtract(value[findex]);
- }
-
- public HashSet<string> GetPredicates(Program program, VCExpressionGenerator gen, ProverInterface prover)
- {
- var ret = new HashSet<string>();
- if (isFalse) return ret;
- Simplify();
-
- // Find the free expressions
- var proc = program.Procedures.FirstOrDefault(p => p.Name == procName);
- Contract.Assert(proc != null);
- Expr freeSummary = Expr.True;
- foreach (var req in proc.Requires.OfType<Requires>().Where(req => req.Free))
- {
- freeSummary = Expr.And(freeSummary, MakeOld(req.Condition));
- }
- foreach (var ens in proc.Ensures.OfType<Ensures>().Where(ens => ens.Free))
- {
- freeSummary = Expr.And(freeSummary, ens.Condition);
- }
-
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- if (value[i].isFalse) continue;
- if (PostPreds[procName][i].expr is LiteralExpr && (PostPreds[procName][i].expr as LiteralExpr).IsFalse)
- continue;
-
- if (value[i].isTrue)
- ret.Add(PostPreds[procName][i].expr.ToString());
- else
- {
- foreach (var c in value[i].GetConjuncts())
- {
- var s = Expr.Imp(c.ToExpr(j => PrePreds[procName][j].expr), PostPreds[procName][i].expr);
- if (CheckIfUnsat(Expr.And(freeSummary, Expr.Not(s)), gen, prover))
- continue;
- ret.Add(s.ToString());
- }
- }
- }
- return ret;
- }
-
- public override string ToString()
- {
- var ret = "";
- if (isFalse) return "false";
- var first = true;
-
- for(int i = 0; i < PostPreds[procName].Count; i++)
- {
- if(value[i].isFalse) continue;
-
- if(value[i].isTrue)
- ret += string.Format("{0}{1}", first ? "" : " && ", PostPreds[procName][i]);
- else
- ret += string.Format("{0}({1} ==> {2})", first ? "" : " && ", value[i], PostPreds[procName][i]);
-
- first = false;
- }
- if (ret == "") ret = "true";
- return ret;
- }
-
-
- #region ISummaryElement Members
-
- public ISummaryElement Copy()
- {
- var ret = new PredicateAbs(procName);
- ret.isFalse = isFalse;
- ret.value = new PredicateAbsDisjunct[value.Length];
- for (int i = 0; i < value.Length; i++)
- ret.value[i] = value[i];
- return ret;
- }
-
- public ISummaryElement GetFlaseSummary(Program program, Implementation impl)
- {
- return new PredicateAbs(impl.Name);
- }
-
- public ISummaryElement GetTrueSummary(Program program, Implementation impl)
- {
- var ret = new PredicateAbs(impl.Name);
- ret.isFalse = false;
- for (int i = 0; i < PostPreds[this.procName].Count; i++) ret.value[i] = new PredicateAbsDisjunct(false, impl.Name);
-
- return ret;
- }
-
- public void Join(Dictionary<string, Model.Element> state, Model model)
- {
- PredicateAbs.model = model;
-
- // Evaluate each predicate on the state
- var prePredsVal = new bool[PrePreds[procName].Count];
- var postPredsVal = new bool[PostPreds[procName].Count];
-
- var indexSeq = new List<int>();
- for (int i = 0; i < PrePreds[procName].Count; i++) indexSeq.Add(i);
-
- for (int i = 0; i < PrePreds[procName].Count; i++)
- {
- var v = ToValue(Eval(PrePreds[procName][i].expr, state));
- Debug.Assert(v is bool);
- prePredsVal[i] = (bool)v;
- }
-
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- var v = ToValue(Eval(PostPreds[procName][i].expr, state));
- Debug.Assert(v is bool);
- postPredsVal[i] = (bool)v;
- }
-
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- // No hope for this post pred?
- if (!isFalse && value[i].isFalse) continue;
-
- var newDisj = new PredicateAbsDisjunct(true, procName);
- if (!postPredsVal[i])
- {
- newDisj = new PredicateAbsDisjunct(indexSeq.Where(j => !prePredsVal[j]), indexSeq.Where(j => prePredsVal[j] && !PosPrePreds[procName].Contains(j)), procName);
- }
-
- if (isFalse)
- value[i] = newDisj;
- else
- value[i] = PredicateAbsDisjunct.And(value[i], newDisj);
- }
-
- /*
- // do beta(model)
- var that = new PredicateAbsDisjunct[PostPreds[procName].Count];
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- if (postPredsVal[i])
- that[i] = new PredicateAbsDisjunct(true, procName);
- else if (i == 0)
- {
- Debug.Assert(PostPreds[procName][0].ToString() == "false");
- var newDisj = new PredicateAbsDisjunct(true, procName);
- newDisj = new PredicateAbsDisjunct(indexSeq.Where(j => !prePredsVal[j]), indexSeq.Where(j => prePredsVal[j]), procName);
- that[i] = newDisj;
- }
- else
- {
- // false
- that[i] = new PredicateAbsDisjunct(false, procName);
- }
- }
-
- // Do join
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- if (isFalse)
- value[i] = that[i];
- else
- {
- if (i == 0)
- value[i] = PredicateAbsDisjunct.And(value[i], that[i]);
- else
- {
- var c1 = PredicateAbsDisjunct.And(value[i], that[i]);
- var c2 = PredicateAbsDisjunct.And(value[i], that[0]);
- var c3 = PredicateAbsDisjunct.And(value[0], that[i]);
- value[i] = PredicateAbsDisjunct.Or(c1, c2);
- value[i] = PredicateAbsDisjunct.Or(value[i], c3);
- }
- }
- }
- */
- isFalse = false;
-
- //Console.WriteLine("Result of Join: {0}", this.ToString());
- }
-
- // Precondition: the upper guys are just {true/false/upper-candidate} ==> post-pred
- public void Meet(ISummaryElement iother)
- {
- var other = iother as PredicateAbs;
- if (isFalse) return;
- if (other.isFalse)
- {
- isFalse = true;
- for (int i = 0; i < PostPreds[this.procName].Count; i++) value[i] = null;
- return;
- }
- Debug.Assert(this.procName == other.procName);
-
- for (int i = 0; i < PostPreds[this.procName].Count; i++)
- {
- value[i] = PredicateAbsDisjunct.Or(value[i], other.value[i]);
- }
- }
-
- public bool IsEqual(ISummaryElement other)
- {
- var that = other as PredicateAbs;
- if (isFalse && that.isFalse) return true;
- if (isFalse || that.isFalse) return false;
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- if (!PredicateAbsDisjunct.syntacticLessThan(value[i], that.value[i]) ||
- !PredicateAbsDisjunct.syntacticLessThan(that.value[i], value[i]))
- return false;
- }
- return true;
- }
-
- // Precondition: the upper guys are just {true/false/upper-candidate} ==> post-pred
- // Postcondition: the returned value is also of this form (for just one post-pred)
- public ISummaryElement AbstractConsequence(ISummaryElement iupper)
- {
- var upper = iupper as PredicateAbs;
-
- for (int i = 0; i < PostPreds[this.procName].Count; i++)
- {
- if (upper.value[i].isTrue) continue;
- if (!UpperCandidates.ContainsKey(Tuple.Create(procName, i))) continue;
-
- foreach (var candidate in UpperCandidates[Tuple.Create(procName, i)])
- {
- if (PredicateAbsDisjunct.syntacticLessThan(candidate, upper.value[i]))
- continue;
- if (!this.isFalse && !PredicateAbsDisjunct.syntacticLessThan(candidate, this.value[i]))
- continue;
-
- var ret = new PredicateAbs(this.procName);
- ret.isFalse = false;
- for (int j = 0; j < PostPreds[this.procName].Count; j++)
- ret.value[j] = new PredicateAbsDisjunct(false, this.procName);
-
- ret.value[i] = candidate;
-
- return ret;
- }
- }
-
- // Giveup: the abstract consequence is too difficult to compute
- return null;
- }
-
- public VCExpr GetSummaryExpr(Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen)
- {
- if (isFalse)
- return VCExpressionGenerator.False;
-
- var ret = VCExpressionGenerator.True;
-
- for(int i = 0; i < PostPreds[procName].Count; i++)
- {
- ret = gen.AndSimp(ret, gen.ImpliesSimp(value[i].ToVcExpr(j => ToVcExpr(PrePreds[procName][j].expr, incarnations, gen), gen), ToVcExpr(PostPreds[procName][i].expr, incarnations, gen)));
- }
-
- return ret;
- }
-
- public Expr GetSummaryExpr(Func<string, Expr> always, Func<string, Expr> forold)
- {
- if (isFalse)
- return Expr.False;
-
- Expr ret = Expr.True;
-
- for (int i = 0; i < PostPreds[procName].Count; i++)
- {
- ret = Expr.And(ret, Expr.Imp(value[i].ToExpr(j => ToExpr(PrePreds[procName][j].expr, always, forold)), ToExpr(PostPreds[procName][i].expr, always, forold)));
- }
-
- return ret;
- }
-
- #endregion
- }
-
- public class PredicateAbsDisjunct
- {
- List<PredicateAbsConjunct> conjuncts;
- string ProcName;
- public bool isTrue {get; private set;}
- public bool isFalse
- {
- get
- {
- if (isTrue) return false;
- return conjuncts.Count == 0;
- }
- }
-
- public PredicateAbsDisjunct(bool isTrue, string ProcName)
- {
- this.isTrue = isTrue;
- this.ProcName = ProcName;
- conjuncts = new List<PredicateAbsConjunct>();
- }
-
- public PredicateAbsDisjunct(List<PredicateAbsConjunct> conjuncts, string ProcName)
- {
- isTrue = false;
- this.conjuncts = conjuncts;
- this.ProcName = ProcName;
- }
-
- // Disjunct of singleton conjuncts
- public PredicateAbsDisjunct(IEnumerable<int> pos, IEnumerable<int> neg, string ProcName)
- {
- this.ProcName = ProcName;
- conjuncts = new List<PredicateAbsConjunct>();
- isTrue = false;
- pos.Iter(p => conjuncts.Add(PredicateAbsConjunct.Singleton(p, true, ProcName)));
- neg.Iter(p => conjuncts.Add(PredicateAbsConjunct.Singleton(p, false, ProcName)));
- }
-
- // Does d1 describe a smaller set of states than d2? This is true when every conjunct of d1
- // is smaller than some conjunct of d2
- public static bool syntacticLessThan(PredicateAbsDisjunct d1, PredicateAbsDisjunct d2)
- {
- if (d2.isTrue) return true;
- if (d1.isTrue) return false;
- if (d1.isFalse) return true;
- if (d2.isFalse) return false;
-
- foreach (var c1 in d1.conjuncts)
- {
- if (d2.conjuncts.Any(c2 => PredicateAbsConjunct.syntacticLessThan(c1, c2)))
- continue;
- else
- return false;
- }
- return true;
- }
-
- public static PredicateAbsDisjunct And(PredicateAbsDisjunct v1, PredicateAbsDisjunct v2)
- {
- if (v1.isTrue) return v2;
- if (v2.isTrue) return v1;
-
- var result = new List<PredicateAbsConjunct>();
-
- foreach (var c1 in v1.conjuncts)
- {
- foreach (var c2 in v2.conjuncts)
- {
- var c = PredicateAbsConjunct.And(c1, c2);
- if (c.isFalse) continue;
- if (result.Any(cprime => c.implies(cprime))) continue;
- var tmp = new List<PredicateAbsConjunct>();
- tmp.Add(c);
- result.Where(cprime => !cprime.implies(c)).Iter(cprime => tmp.Add(cprime));
- result = tmp;
- }
- }
-
- return new PredicateAbsDisjunct(result, v1.ProcName);
- }
-
- public static PredicateAbsDisjunct Or(PredicateAbsDisjunct v1, PredicateAbsDisjunct v2)
- {
- if (v1.isTrue) return v1;
- if (v2.isTrue) return v2;
- if (v1.isFalse) return v2;
- if (v2.isFalse) return v1;
-
- var result = new List<PredicateAbsConjunct>();
- v1.conjuncts.Iter(c => result.Add(c));
-
- foreach (var c in v2.conjuncts)
- {
- if (result.Any(cprime => c.implies(cprime))) continue;
- var tmp = new List<PredicateAbsConjunct>();
- tmp.Add(c);
- result.Where(cprime => !cprime.implies(c)).Iter(cprime => tmp.Add(cprime));
- result = tmp;
- }
-
- return new PredicateAbsDisjunct(result, v1.ProcName);
- }
-
- public VCExpr ToVcExpr(Func<int, VCExpr> predToExpr, VCExpressionGenerator gen)
- {
- if (isTrue) return VCExpressionGenerator.True;
- var ret = VCExpressionGenerator.False;
- conjuncts.Iter(c => ret = gen.OrSimp(ret, c.ToVcExpr(predToExpr, gen)));
- return ret;
- }
-
- public Expr ToExpr(Func<int, Expr> predToExpr)
- {
- if (isTrue) return Expr.True;
- Expr ret = Expr.False;
- conjuncts.Iter(c => ret = Expr.Or(ret, c.ToExpr(predToExpr)));
- return ret;
- }
-
- public override string ToString()
- {
- if(isTrue)
- return "true";
- var ret = "";
- var first = true;
- foreach (var c in conjuncts)
- {
- if (c.isFalse) continue;
- ret += string.Format("{0}{1}", first ? "" : " || ", c);
- first = false;
- }
- return ret;
- }
-
- public void Subtract(PredicateAbsDisjunct that)
- {
- var ncon = new List<PredicateAbsConjunct>();
- foreach (var c1 in conjuncts)
- {
- if (that.conjuncts.Any(c2 => c1.implies(c2)))
- continue;
- ncon.Add(c1);
- }
- conjuncts = ncon;
- }
-
- public IEnumerable<PredicateAbsConjunct> GetConjuncts()
- {
- return conjuncts;
- }
-
- }
-
- public class PredicateAbsConjunct
- {
- static int ConjunctBound = 3;
-
- public bool isFalse { get; private set; }
- HashSet<int> posPreds;
- HashSet<int> negPreds;
- string ProcName;
-
- public static void Initialize(int bound)
- {
- ConjunctBound = bound;
- }
-
- private void Normalize()
- {
- if (posPreds.Intersect(negPreds).Any() || negPreds.Intersect(posPreds).Any() || (posPreds.Count + negPreds.Count > ConjunctBound))
- {
- isFalse = true;
- posPreds = new HashSet<int>();
- negPreds = new HashSet<int>();
- }
- }
-
- // Do this step only once in a while?
- private void StrongNormalize()
- {
- if (isFalse) return;
-
- var candidates = new List<Tuple<int, bool>>();
- posPreds.Iter(p => candidates.Add(Tuple.Create(p, true)));
- negPreds.Iter(p => candidates.Add(Tuple.Create(p, false)));
- var drop = new HashSet<int>();
- for (int i = 0; i < candidates.Count; i++)
- {
- for (int j = 0; j < candidates.Count; j++)
- {
- if (i == j) continue;
-
- var key = Tuple.Create(ProcName, candidates[i].Item1, candidates[j].Item1,
- candidates[i].Item2, candidates[j].Item2);
- if (PredicateAbs.unsatPrePredPairs.Contains(key))
- {
- isFalse = true;
- posPreds = new HashSet<int>();
- negPreds = new HashSet<int>();
- return;
- }
-
- key = Tuple.Create(ProcName, candidates[i].Item1, candidates[j].Item1,
- candidates[i].Item2, !candidates[j].Item2);
-
- if (PredicateAbs.unsatPrePredPairs.Contains(key))
- drop.Add(candidates[j].Item1);
- }
- }
-
- posPreds.ExceptWith(drop);
- negPreds.ExceptWith(drop);
- }
-
- public PredicateAbsConjunct(bool isFalse, string ProcName)
- {
- posPreds = new HashSet<int>();
- negPreds = new HashSet<int>();
- this.isFalse = isFalse;
- this.ProcName = ProcName;
- }
-
- // do we know that c1 is surely less than or equal to c2? That is, c1 describes a smaller
- // concretization. We check that c2 is a sub-conjunct of c1
- public static bool syntacticLessThan(PredicateAbsConjunct c1, PredicateAbsConjunct c2)
- {
- if (c1.isFalse) return true;
- if (c2.isFalse) return false;
- return (c2.posPreds.IsSubsetOf(c1.posPreds) && c2.negPreds.IsSubsetOf(c1.negPreds));
- }
-
- public static PredicateAbsConjunct Singleton(int v, bool isPositive, string ProcName)
- {
- if (isPositive)
- return new PredicateAbsConjunct(new int[] { v }, new HashSet<int>(), ProcName);
- else
- return new PredicateAbsConjunct(new HashSet<int>(), new int[] { v }, ProcName);
- }
-
- public PredicateAbsConjunct(IEnumerable<int> pos, IEnumerable<int> neg, string ProcName)
- {
- isFalse = false;
- posPreds = new HashSet<int>(pos);
- negPreds = new HashSet<int>(neg);
- this.ProcName = ProcName;
- Normalize();
- }
-
- public static PredicateAbsConjunct And(PredicateAbsConjunct v1, PredicateAbsConjunct v2)
- {
- if (v1.isFalse || v2.isFalse) return new PredicateAbsConjunct(true, v1.ProcName);
- var ret = new PredicateAbsConjunct(v1.posPreds.Union(v2.posPreds), v1.negPreds.Union(v2.negPreds), v1.ProcName);
- ret.StrongNormalize();
- return ret;
- }
-
- public bool implies(PredicateAbsConjunct v)
- {
- if (isFalse) return true;
- if (v.isFalse) return false;
- return (posPreds.IsSupersetOf(v.posPreds) && negPreds.IsSupersetOf(v.negPreds));
- }
-
- public VCExpr ToVcExpr(Func<int, VCExpr> predToExpr, VCExpressionGenerator gen)
- {
- if (isFalse) return VCExpressionGenerator.False;
- var ret = VCExpressionGenerator.True;
- posPreds.Iter(p => ret = gen.AndSimp(ret, predToExpr(p)));
- negPreds.Iter(p => ret = gen.AndSimp(ret, gen.Not(predToExpr(p))));
- return ret;
- }
-
- public Expr ToExpr(Func<int, Expr> predToExpr)
- {
- if (isFalse) return Expr.False;
- Expr ret = Expr.True;
- var pp = posPreds.ToList(); pp.Sort();
- var np = negPreds.ToList(); np.Sort();
- pp.Iter(p => ret = Expr.And(ret, predToExpr(p)));
- np.Iter(p => ret = Expr.And(ret, Expr.Not(predToExpr(p))));
- return ret;
- }
-
- public override string ToString()
- {
- if (isFalse)
- return "false";
-
- var ret = "";
- var first = true;
- foreach (var p in posPreds)
- {
- ret += string.Format("{0}{1}", first ? "" : " && ", PredicateAbs.PrePreds[ProcName][p]);
- first = false;
- }
- foreach (var p in negPreds)
- {
- ret += string.Format("{0}!{1}", first ? "" : " && ", PredicateAbs.PrePreds[ProcName][p]);
- first = false;
- }
- return ret;
- }
- }
-
- class FindSummaryPred : MutatingVCExprVisitor<bool>
- {
- public List<Tuple<string, bool, VCExprVar, VCExprNAry>> summaryPreds;
- int assertId;
- private static int CounterId = 0;
-
- public FindSummaryPred(VCExpressionGenerator gen, int assertId)
- : base(gen)
- {
- summaryPreds = new List<Tuple<string, bool, VCExprVar, VCExprNAry>>();
- this.assertId = assertId;
- }
-
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
- List<VCExpr/*!*/>/*!*/ newSubExprs,
- // has any of the subexpressions changed?
- bool changed,
- bool arg)
- {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr ret;
- if (changed)
- ret = Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- ret = originalNode;
-
- VCExprNAry retnary = ret as VCExprNAry;
- if (retnary == null) return ret;
- var op = retnary.Op as VCExprBoogieFunctionOp;
-
- if (op == null)
- {
- var lop = retnary.Op as VCExprLabelOp;
- if (lop == null) return ret;
- if (lop.pos) return ret;
- if (!lop.label.Equals("@" + assertId.ToString())) return ret;
-
- //var subexpr = retnary[0] as VCExprNAry;
- //if (subexpr == null) return ret;
- //op = subexpr.Op as VCExprBoogieFunctionOp;
- //if (op == null) return ret;
-
- var subexpr = retnary[0] as VCExprVar;
- if (subexpr == null) return ret;
- if (!subexpr.Name.StartsWith("AbstractHoudiniControl")) return ret;
-
- for (int i = 0; i < summaryPreds.Count; i++)
- {
- if (summaryPreds[i].Item3 == subexpr)
- summaryPreds[i] = Tuple.Create(summaryPreds[i].Item1, true, summaryPreds[i].Item3, summaryPreds[i].Item4);
- }
- return ret;
- }
-
- string calleeName = op.Func.Name;
-
- if (!calleeName.EndsWith(AbstractHoudini.summaryPredSuffix))
- return ret;
-
- var controlConst = Gen.Variable("AbstractHoudiniControl" + CounterId, Microsoft.Boogie.Type.Bool);
- CounterId++;
-
- summaryPreds.Add(Tuple.Create(calleeName.Substring(0, calleeName.Length - AbstractHoudini.summaryPredSuffix.Length), false, controlConst, retnary));
-
- return controlConst;
- //return ret;
- }
-
- }
-
- class FindExistentialFunctions : MutatingVCExprVisitor<bool>
- {
- public List<Tuple<string, VCExprVar, VCExprNAry>> funcCalls;
- private HashSet<string> existentialFunctions;
- private static int CounterId = 0;
-
- public FindExistentialFunctions(VCExpressionGenerator gen, HashSet<string> existentialFunctions)
- : base(gen)
- {
- funcCalls = new List<Tuple<string, VCExprVar, VCExprNAry>>();
- this.existentialFunctions = existentialFunctions;
- }
-
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
- List<VCExpr/*!*/>/*!*/ newSubExprs,
- // has any of the subexpressions changed?
- bool changed,
- bool arg)
- {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr ret;
- if (changed)
- ret = Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- ret = originalNode;
-
- VCExprNAry retnary = ret as VCExprNAry;
- if (retnary == null) return ret;
- var op = retnary.Op as VCExprBoogieFunctionOp;
- if (op == null) return ret;
-
- string calleeName = op.Func.Name;
-
- if (!existentialFunctions.Contains(calleeName))
- return ret;
-
- var controlConst = Gen.Variable("AbsHoudiniControl" + CounterId, Microsoft.Boogie.Type.Bool);
- CounterId++;
-
- funcCalls.Add(Tuple.Create(calleeName, controlConst, retnary));
-
- return controlConst;
- }
-
- }
-
- class AbstractHoudiniErrorReporter : ProverInterface.ErrorHandler
- {
- public Model model;
-
- public AbstractHoudiniErrorReporter()
- {
- model = null;
- }
-
- public override void OnModel(IList<string> labels, Model model, ProverInterface.Outcome proverOutcome)
- {
- Debug.Assert(model != null);
- if(CommandLineOptions.Clo.PrintErrorModel >= 1) model.Write(Console.Out);
- this.model = model;
- }
- }
-
- public class AbsHoudiniInternalError : System.ApplicationException
- {
- public AbsHoudiniInternalError(string msg) : base(msg) { }
-
- };
-
- public class SimpleUtil
- {
- // Constructs a mapping from procedure names to the implementation
- public static Dictionary<string, Implementation> nameImplMapping(Program p)
- {
- var m = new Dictionary<string, Implementation>();
- foreach (var impl in p.Implementations)
- {
- m.Add(impl.Name, impl);
- }
-
- return m;
- }
-
- // is "assert true"?
- public static bool isAssertTrue(Cmd cmd)
- {
- var acmd = cmd as AssertCmd;
- if (acmd == null) return false;
- var le = acmd.Expr as LiteralExpr;
- if (le == null) return false;
- if (le.IsTrue) return true;
- return false;
- }
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using VC;
+using Outcome = VC.VCGen.Outcome;
+using Bpl = Microsoft.Boogie;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie.Houdini {
+
+ public class AbsHoudini
+ {
+ Dictionary<string, Function> existentialFunctions;
+ Program program;
+ Dictionary<string, Implementation> name2Impl;
+ Dictionary<string, VCExpr> impl2VC;
+ Dictionary<string, List<Tuple<string, Function, NAryExpr>>> impl2FuncCalls;
+ // constant -> the naryexpr that it replaced
+ Dictionary<string, NAryExpr> constant2FuncCall;
+
+ // function -> its abstract value
+ Dictionary<string, IAbstractDomain> function2Value;
+
+ // impl -> functions assumed/asserted
+ Dictionary<string, HashSet<string>> impl2functionsAsserted, impl2functionsAssumed;
+
+ // funtions -> impls where assumed/asserted
+ Dictionary<string, HashSet<string>> function2implAssumed, function2implAsserted;
+
+ // impl -> handler, collector
+ Dictionary<string, Tuple<ProverInterface.ErrorHandler, AbsHoudiniCounterexampleCollector>> impl2ErrorHandler;
+
+ // Essentials: VCGen, Prover
+ VCGen vcgen;
+ ProverInterface prover;
+
+ // Stats
+ TimeSpan proverTime;
+ int numProverQueries;
+
+ public AbsHoudini(Program program, IAbstractDomain defaultElem)
+ {
+ this.program = program;
+ this.impl2VC = new Dictionary<string, VCExpr>();
+ this.impl2FuncCalls = new Dictionary<string, List<Tuple<string, Function, NAryExpr>>>();
+ this.existentialFunctions = new Dictionary<string, Function>();
+ this.name2Impl = new Dictionary<string, Implementation>();
+ this.impl2functionsAsserted = new Dictionary<string, HashSet<string>>();
+ this.impl2functionsAssumed = new Dictionary<string, HashSet<string>>();
+ this.function2implAsserted = new Dictionary<string, HashSet<string>>();
+ this.function2implAssumed = new Dictionary<string, HashSet<string>>();
+ this.impl2ErrorHandler = new Dictionary<string, Tuple<ProverInterface.ErrorHandler, AbsHoudiniCounterexampleCollector>>();
+ this.constant2FuncCall = new Dictionary<string, NAryExpr>();
+
+ // Find the existential functions
+ foreach (var func in program.Functions
+ .Where(f => QKeyValue.FindBoolAttribute(f.Attributes, "existential")))
+ existentialFunctions.Add(func.Name, func);
+
+ this.function2Value = new Dictionary<string, IAbstractDomain>();
+ foreach (var func in existentialFunctions.Values)
+ {
+ // Find if the function wishes to use a specific abstract domain
+ var domain = QKeyValue.FindStringAttribute(func.Attributes, "absdomain");
+ if (domain == null)
+ {
+ function2Value[func.Name] = defaultElem.Bottom();
+ }
+ else
+ {
+ function2Value[func.Name] = AbstractDomainFactory.GetInstance(domain);
+ }
+ }
+ existentialFunctions.Keys.Iter(f => function2implAssumed.Add(f, new HashSet<string>()));
+ existentialFunctions.Keys.Iter(f => function2implAsserted.Add(f, new HashSet<string>()));
+
+ // type check
+ existentialFunctions.Values.Iter(func =>
+ {
+ if (func.OutParams.Count != 1 || !func.OutParams[0].TypedIdent.Type.IsBool)
+ throw new AbsHoudiniInternalError(string.Format("Existential function {0} must return bool", func.Name));
+ if(func.Body != null)
+ throw new AbsHoudiniInternalError(string.Format("Existential function {0} should not have a body", func.Name));
+ var args = new List<Type>();
+ func.InParams.Iter(v => args.Add(v.TypedIdent.Type));
+ string msg = "";
+ if (!function2Value[func.Name].TypeCheck(args, out msg))
+ throw new AbsHoudiniInternalError("TypeError: " + msg);
+ });
+
+ //if (CommandLineOptions.Clo.ProverKillTime > 0)
+ // CommandLineOptions.Clo.ProverOptions.Add(string.Format("TIME_LIMIT={0}", CommandLineOptions.Clo.ProverKillTime));
+
+ Inline();
+
+ this.vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List<Checker>());
+ this.prover = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, CommandLineOptions.Clo.ProverKillTime);
+
+ this.proverTime = TimeSpan.Zero;
+ this.numProverQueries = 0;
+
+ program.Implementations
+ .Where(impl => !impl.SkipVerification)
+ .Iter(impl => name2Impl.Add(impl.Name, impl));
+
+ // Let's do VC Gen (and also build dependencies)
+ name2Impl.Values.Iter(GenVC);
+ }
+
+ public VCGenOutcome ComputeSummaries()
+ {
+ var overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Valid, new List<Counterexample>());
+
+ // Compute SCCs and determine a priority order for impls
+ var Succ = new Dictionary<string, HashSet<string>>();
+ var Pred = new Dictionary<string, HashSet<string>>();
+ name2Impl.Keys.Iter(s => Succ[s] = new HashSet<string>());
+ name2Impl.Keys.Iter(s => Pred[s] = new HashSet<string>());
+
+ foreach(var impl in name2Impl.Keys) {
+ Succ[impl] = new HashSet<string>();
+ impl2functionsAsserted[impl].Iter(f =>
+ function2implAssumed[f].Iter(succ =>
+ {
+ Succ[impl].Add(succ);
+ Pred[succ].Add(impl);
+ }));
+ }
+
+ var sccs = new StronglyConnectedComponents<string>(name2Impl.Keys,
+ new Adjacency<string>(n => Pred[n]),
+ new Adjacency<string>(n => Succ[n]));
+ sccs.Compute();
+
+ // impl -> priority
+ var impl2Priority = new Dictionary<string, int>();
+ int p = 0;
+ foreach (var scc in sccs)
+ {
+ foreach (var impl in scc)
+ {
+ impl2Priority.Add(impl, p);
+ p++;
+ }
+ }
+
+ var worklist = new SortedSet<Tuple<int, string>>();
+ name2Impl.Keys.Iter(k => worklist.Add(Tuple.Create(impl2Priority[k], k)));
+
+ while (worklist.Any())
+ {
+ var impl = worklist.First().Item2;
+ worklist.Remove(worklist.First());
+
+ var gen = prover.VCExprGen;
+ var terms = new List<Expr>();
+ foreach (var tup in impl2FuncCalls[impl])
+ {
+ var controlVar = tup.Item2;
+ var exprVars = tup.Item3;
+ var varList = new List<Expr>();
+ exprVars.Args.OfType<Expr>().Iter(v => varList.Add(v));
+
+ var args = new List<Expr>();
+ controlVar.InParams.Iter(v => args.Add(Expr.Ident(v)));
+ Expr term = Expr.Eq(new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args),
+ function2Value[tup.Item1].Gamma(varList));
+
+ if (controlVar.InParams.Count != 0)
+ {
+ term = new ForallExpr(Token.NoToken, new List<Variable>(controlVar.InParams.ToArray()),
+ new Trigger(Token.NoToken, true, new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args) }),
+ term);
+ }
+ terms.Add(term);
+ }
+ var env = Expr.BinaryTreeAnd(terms);
+
+ env.Typecheck(new TypecheckingContext((IErrorSink)null));
+ var envVC = prover.Context.BoogieExprTranslator.Translate(env);
+
+ var vc = gen.Implies(envVC, impl2VC[impl]);
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Verifying {0}: ", impl);
+ //Console.WriteLine("env: {0}", envVC);
+ var envFuncs = new HashSet<string>();
+ impl2FuncCalls[impl].Iter(tup => envFuncs.Add(tup.Item1));
+ envFuncs.Iter(f => PrintFunction(existentialFunctions[f]));
+ }
+
+ var handler = impl2ErrorHandler[impl].Item1;
+ var collector = impl2ErrorHandler[impl].Item2;
+ collector.Reset(impl);
+
+ var start = DateTime.Now;
+
+ prover.Push();
+ prover.Assert(gen.Not(vc), true);
+ prover.FlushAxiomsToTheoremProver();
+ prover.Check();
+ ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);
+
+ //prover.BeginCheck(impl, vc, handler);
+ //ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);
+
+ var inc = (DateTime.Now - start);
+ proverTime += inc;
+ numProverQueries++;
+
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Time taken = " + inc.TotalSeconds.ToString());
+
+ if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
+ {
+ // pick some function; make it true and keep going
+ bool changed = false;
+ foreach (var f in impl2functionsAsserted[impl])
+ {
+ function2Value[f] = function2Value[f].MakeTop(out changed);
+ if (changed) break;
+ }
+ if(!changed)
+ return new VCGenOutcome(proverOutcome, new List<Counterexample>());
+ }
+
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine(collector.numErrors > 0 ? "SAT" : "UNSAT");
+
+ if (collector.numErrors > 0)
+ {
+ var funcsChanged = collector.funcsChanged;
+ if (funcsChanged.Count == 0)
+ {
+ overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.errors);
+ break;
+ }
+
+ // propagate dependent guys back into the worklist, including self
+ var deps = new HashSet<string>();
+ deps.Add(impl);
+ funcsChanged.Iter(f => deps.UnionWith(function2implAssumed[f]));
+
+ deps.Iter(s => worklist.Add(Tuple.Create(impl2Priority[s], s)));
+ }
+
+ prover.Pop();
+ }
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Prover time = {0}", proverTime.TotalSeconds.ToString("F2"));
+ Console.WriteLine("Number of prover queries = " + numProverQueries);
+ }
+
+ if (CommandLineOptions.Clo.PrintAssignment)
+ {
+ // Print the answer
+ existentialFunctions.Values.Iter(PrintFunction);
+ }
+
+ return overallOutcome;
+ }
+
+
+ public IEnumerable<Function> GetAssignment()
+ {
+ var ret = new List<Function>();
+ foreach (var func in existentialFunctions.Values)
+ {
+ var invars = new List<Expr>(func.InParams.OfType<Variable>().Select(v => Expr.Ident(v)));
+ func.Body = function2Value[func.Name].Gamma(invars);
+ ret.Add(func);
+ }
+ return ret;
+ }
+
+ private void PrintFunction(Function function)
+ {
+ var tt = new TokenTextWriter(Console.Out, /*pretty=*/ false);
+ var invars = new List<Expr>(function.InParams.OfType<Variable>().Select(v => Expr.Ident(v)));
+ function.Body = function2Value[function.Name].Gamma(invars);
+ function.Emit(tt, 0);
+ tt.Close();
+ }
+
+ public HashSet<string> HandleCounterExample(string impl, Counterexample error)
+ {
+ var funcsChanged = new HashSet<string>();
+ // Find the failing assert -- need to do a join there
+ // return the set of functions whose definition has changed
+ var cex = ExtractState(impl, error);
+ foreach (var tup in cex)
+ {
+ function2Value[tup.Item1] = function2Value[tup.Item1].Join(tup.Item2);
+ funcsChanged.Add(tup.Item1);
+ }
+ return funcsChanged;
+ }
+
+ private List<Tuple<string, List<Model.Element>>> ExtractState(string impl, Counterexample error)
+ {
+ var lastBlock = error.Trace.Last() as Block;
+ AssertCmd failingAssert = null;
+
+ CallCounterexample callCounterexample = error as CallCounterexample;
+ if (callCounterexample != null)
+ {
+ Procedure failingProcedure = callCounterexample.FailingCall.Proc;
+ Requires failingRequires = callCounterexample.FailingRequires;
+ failingAssert = lastBlock.Cmds.OfType<AssertRequiresCmd>().FirstOrDefault(ac => ac.Requires == failingRequires);
+ }
+ ReturnCounterexample returnCounterexample = error as ReturnCounterexample;
+ if (returnCounterexample != null)
+ {
+ Ensures failingEnsures = returnCounterexample.FailingEnsures;
+ failingAssert = lastBlock.Cmds.OfType<AssertEnsuresCmd>().FirstOrDefault(ac => ac.Ensures == failingEnsures);
+ }
+ AssertCounterexample assertCounterexample = error as AssertCounterexample;
+ if (assertCounterexample != null)
+ {
+ failingAssert = lastBlock.Cmds.OfType<AssertCmd>().FirstOrDefault(ac => ac == assertCounterexample.FailingAssert);
+ }
+
+ Debug.Assert(failingAssert != null);
+ return ExtractState(impl, failingAssert.Expr, error.Model);
+ }
+
+ private static int existentialConstCounter = 0;
+
+ private List<Tuple<string, List<Model.Element>>> ExtractState(string impl, Expr expr, Model model)
+ {
+ var funcsUsed = FunctionCollector.Collect(expr);
+
+ var ret = new List<Tuple<string, List<Model.Element>>>();
+
+ foreach (var tup in funcsUsed.Where(t => t.Item2 == null))
+ {
+ var constant = tup.Item1;
+ if (!constant2FuncCall.ContainsKey(constant.Name))
+ continue;
+
+ var func = constant2FuncCall[constant.Name];
+ var funcName = (func.Fun as FunctionCall).FunctionName;
+ var vals = new List<Model.Element>();
+ prover.Context.BoogieExprTranslator.Translate(func.Args).Iter(ve => vals.Add(getValue(ve, model)));
+ ret.Add(Tuple.Create(funcName, vals));
+ }
+
+ foreach (var tup in funcsUsed.Where(t => t.Item2 != null))
+ {
+ var constant = tup.Item1;
+ var boundExpr = tup.Item2;
+
+ if (!constant2FuncCall.ContainsKey(constant.Name))
+ continue;
+
+ // There are some bound variables (because the existential function was inside an \exists).
+ // We must find an assignment for bound varibles
+
+ // First, peice apart the existential functions
+ var cd = new Duplicator();
+ var tup2 = ExistentialExprModelMassage.Massage(cd.VisitExpr(boundExpr.Body));
+ var be = tup2.Item1;
+ Expr env = Expr.True;
+ foreach (var ahFunc in tup2.Item2)
+ {
+ var tup3 = impl2FuncCalls[impl].First(t => t.Item2.Name == ahFunc.Name);
+ var varList = new List<Expr>();
+ tup3.Item3.Args.OfType<Expr>().Iter(v => varList.Add(v));
+
+ env = Expr.And(env, function2Value[tup3.Item1].Gamma(varList));
+ }
+ be = Expr.And(be, Expr.Not(env));
+
+ // map formals to constants
+ var formalToConstant = new Dictionary<string, Constant>();
+ foreach (var f in boundExpr.Dummies.OfType<Variable>())
+ formalToConstant.Add(f.Name, new Constant(Token.NoToken, new TypedIdent(Token.NoToken, f.Name + "@subst@" + (existentialConstCounter++), f.TypedIdent.Type), false));
+ be = Substituter.Apply(new Substitution(v => formalToConstant.ContainsKey(v.Name) ? Expr.Ident(formalToConstant[v.Name]) : Expr.Ident(v)), be);
+ formalToConstant.Values.Iter(v => prover.Context.DeclareConstant(v, false, null));
+
+ var reporter = new AbstractHoudiniErrorReporter();
+ var ve = prover.Context.BoogieExprTranslator.Translate(be);
+ prover.Assert(ve, true);
+ prover.Check();
+ var proverOutcome = prover.CheckOutcomeCore(reporter);
+ if (proverOutcome != ProverInterface.Outcome.Invalid)
+ continue;
+ model = reporter.model;
+
+ var func = constant2FuncCall[constant.Name];
+ var funcName = (func.Fun as FunctionCall).FunctionName;
+ var vals = new List<Model.Element>();
+ foreach (var funcArg in func.Args.OfType<Expr>())
+ {
+ var arg = Substituter.Apply(new Substitution(v => formalToConstant.ContainsKey(v.Name) ? Expr.Ident(formalToConstant[v.Name]) : Expr.Ident(v)), funcArg);
+ vals.Add(getValue(prover.Context.BoogieExprTranslator.Translate(arg), model));
+ }
+ ret.Add(Tuple.Create(funcName, vals));
+
+ }
+
+ return ret;
+ }
+
+ private Model.Element getValue(VCExpr arg, Model model)
+ {
+
+
+ if (arg is VCExprLiteral)
+ {
+ //return model.GetElement(arg.ToString());
+ return model.MkElement(arg.ToString());
+ }
+
+ else if (arg is VCExprVar)
+ {
+ var el = model.TryGetFunc(prover.Context.Lookup(arg as VCExprVar));
+ if (el != null)
+ {
+ Debug.Assert(el.Arity == 0 && el.AppCount == 1);
+ return el.Apps.First().Result;
+ }
+ else
+ {
+ // Variable not defined; assign arbitrary value
+ if (arg.Type.IsBool)
+ return model.MkElement("false");
+ else if (arg.Type.IsInt)
+ return model.MkIntElement(0);
+ else
+ return null;
+ }
+ }
+ else if (arg is VCExprNAry && (arg as VCExprNAry).Op is VCExprBvOp)
+ {
+ // support for BV constants
+ var bvc = (arg as VCExprNAry)[0] as VCExprLiteral;
+ if (bvc != null)
+ {
+ var ret = model.TryMkElement(bvc.ToString() + arg.Type.ToString());
+ if (ret != null && (ret is Model.BitVector)) return ret;
+ }
+ }
+
+ object val;
+
+ try
+ {
+ val = prover.Evaluate(arg);
+ }
+ catch (ProverInterface.VCExprEvaluationException)
+ {
+ Console.WriteLine("AbsHoudni: Error evaluating expression {0}", arg);
+ throw;
+ }
+
+ if (val is int || val is bool || val is Microsoft.Basetypes.BigNum)
+ {
+ return model.MkElement(val.ToString());
+ }
+ else
+ {
+ Debug.Assert(false);
+ }
+ return null;
+ }
+
+ // Remove functions AbsHoudiniConstant from the expressions and substitute them with "true"
+ class ExistentialExprModelMassage : StandardVisitor
+ {
+ List<Function> ahFuncs;
+
+ public ExistentialExprModelMassage()
+ {
+ ahFuncs = new List<Function>();
+ }
+
+ public static Tuple<Expr, List<Function>> Massage(Expr expr)
+ {
+ var ee = new ExistentialExprModelMassage();
+ expr = ee.VisitExpr(expr);
+ return Tuple.Create(expr, ee.ahFuncs);
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is FunctionCall && (node.Fun as FunctionCall).FunctionName.StartsWith("AbsHoudiniConstant"))
+ {
+ ahFuncs.Add((node.Fun as FunctionCall).Func);
+ return Expr.True;
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+ class FunctionCollector : ReadOnlyVisitor
+ {
+ public List<Tuple<Function, ExistsExpr>> functionsUsed;
+ ExistsExpr existentialExpr;
+
+ public FunctionCollector()
+ {
+ functionsUsed = new List<Tuple<Function, ExistsExpr>>();
+ existentialExpr = null;
+ }
+
+ public static List<Tuple<Function, ExistsExpr>> Collect(Expr expr)
+ {
+ var fv = new FunctionCollector();
+ fv.VisitExpr(expr);
+ return fv.functionsUsed;
+ }
+
+ public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
+ {
+ var oldE = existentialExpr;
+
+ if (node is ExistsExpr)
+ existentialExpr = (node as ExistsExpr);
+
+ node = base.VisitQuantifierExpr(node);
+
+ existentialExpr = oldE;
+ return node;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is FunctionCall)
+ {
+ var collector = new VariableCollector();
+ collector.Visit(node);
+
+ if(existentialExpr != null && existentialExpr.Dummies.Intersect(collector.usedVars).Any())
+ functionsUsed.Add(Tuple.Create((node.Fun as FunctionCall).Func, existentialExpr));
+ else
+ functionsUsed.Add(Tuple.Create<Function, ExistsExpr>((node.Fun as FunctionCall).Func, null));
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+ class AbsHoudiniCounterexampleCollector : VerifierCallback
+ {
+ public HashSet<string> funcsChanged;
+ public string currImpl;
+ public int numErrors;
+ public List<Counterexample> errors;
+
+ AbsHoudini container;
+
+ public AbsHoudiniCounterexampleCollector(AbsHoudini container)
+ {
+ this.container = container;
+ Reset(null);
+ }
+
+ public void Reset(string impl)
+ {
+ funcsChanged = new HashSet<string>();
+ currImpl = impl;
+ numErrors = 0;
+ errors = new List<Counterexample>();
+ }
+
+ public override void OnCounterexample(Counterexample ce, string reason)
+ {
+ numErrors++;
+ errors.Add(ce);
+
+ funcsChanged.UnionWith(
+ container.HandleCounterExample(currImpl, ce));
+ }
+ }
+
+ private void GenVC(Implementation impl)
+ {
+ ModelViewInfo mvInfo;
+ Dictionary<int, Absy> label2absy;
+ var collector = new AbsHoudiniCounterexampleCollector(this);
+ collector.OnProgress("HdnVCGen", 0, 0, 0.0);
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Generating VC of {0}", impl.Name);
+ }
+
+ vcgen.ConvertCFG2DAG(impl);
+ var gotoCmdOrigins = vcgen.PassifyImpl(impl, out mvInfo);
+
+ // Inline functions
+ (new InlineFunctionCalls()).VisitBlockList(impl.Blocks);
+
+
+ StripOutermostForall(impl);
+ //ExtractQuantifiedExprs(impl);
+ ExtractBoolExprs(impl);
+
+ //CommandLineOptions.Clo.PrintInstrumented = true;
+ //using (var tt = new TokenTextWriter(Console.Out))
+ // impl.Emit(tt, 0);
+
+ // Intercept the FunctionCalls of the existential functions, and replace them with Boolean constants
+ var existentialFunctionNames = new HashSet<string>(existentialFunctions.Keys);
+ var fv = new ReplaceFunctionCalls(existentialFunctionNames);
+ fv.VisitBlockList(impl.Blocks);
+
+ //using (var tt = new TokenTextWriter(Console.Out))
+ // impl.Emit(tt, 0);
+
+
+ impl2functionsAsserted.Add(impl.Name, fv.functionsAsserted);
+ impl2functionsAssumed.Add(impl.Name, fv.functionsAssumed);
+
+ fv.functionsAssumed.Iter(f => function2implAssumed[f].Add(impl.Name));
+ fv.functionsAsserted.Iter(f => function2implAsserted[f].Add(impl.Name));
+
+ impl2FuncCalls.Add(impl.Name, fv.functionsUsed);
+ fv.functionsUsed.Iter(tup => constant2FuncCall.Add(tup.Item2.Name, tup.Item3));
+
+ var gen = prover.VCExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : gen.Integer(Microsoft.Basetypes.BigNum.ZERO);
+
+ var vcexpr = vcgen.GenerateVC(impl, controlFlowVariableExpr, out label2absy, prover.Context);
+ if (!CommandLineOptions.Clo.UseLabels)
+ {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(gen.Integer(Microsoft.Basetypes.BigNum.ZERO), gen.Integer(Microsoft.Basetypes.BigNum.ZERO));
+ VCExpr eqExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(Microsoft.Basetypes.BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vcexpr = gen.Implies(eqExpr, vcexpr);
+ }
+
+ ProverInterface.ErrorHandler handler = null;
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local)
+ handler = new VCGen.ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, prover.Context, program);
+ else
+ handler = new VCGen.ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, prover.Context, program);
+
+ impl2ErrorHandler.Add(impl.Name, Tuple.Create(handler, collector));
+
+ //Console.WriteLine("VC of {0}: {1}", impl.Name, vcexpr);
+
+ // Create a macro so that the VC can sit with the theorem prover
+ Macro macro = new Macro(Token.NoToken, impl.Name + "Macro", new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false));
+ prover.DefineMacro(macro, vcexpr);
+
+ // Store VC
+ impl2VC.Add(impl.Name, gen.Function(macro));
+
+ // HACK: push the definitions of constants involved in function calls
+ // It is possible that some constants only appear in function calls. Thus, when
+ // they are replaced by Boolean constants, it is possible that (get-value) will
+ // fail if the expression involves such constants. All we need to do is make sure
+ // these constants are declared, because otherwise, semantically we are doing
+ // the right thing.
+ foreach (var tup in fv.functionsUsed)
+ {
+ // Ignore ones with bound varibles
+ if (tup.Item2.InParams.Count > 0) continue;
+ var tt = prover.Context.BoogieExprTranslator.Translate(tup.Item3);
+ tt = prover.VCExprGen.Or(VCExpressionGenerator.True, tt);
+ prover.Assert(tt, true);
+ }
+ }
+
+ // convert "foo(... forall e ...) to:
+ // (p iff forall e) ==> foo(... p ...)
+ // where p is a fresh boolean variable and foo is an existential constant
+ private void ExtractQuantifiedExprs(Implementation impl)
+ {
+ var funcs = new HashSet<string>(existentialFunctions.Keys);
+ foreach (var blk in impl.Blocks)
+ {
+ foreach (var acmd in blk.Cmds.OfType<AssertCmd>())
+ {
+ var ret = ExtractQuantifiers.Extract(acmd.Expr, funcs);
+ acmd.Expr = ret.Item1;
+ impl.LocVars.AddRange(ret.Item2);
+ }
+ }
+ }
+
+ // convert "foo(... e ...) to:
+ // (p iff e) ==> foo(... p ...)
+ // where p is a fresh boolean variable, foo is an existential constant
+ // and e is a Boolean-typed argument of foo
+ private void ExtractBoolExprs(Implementation impl)
+ {
+ var funcs = new HashSet<string>(existentialFunctions.Keys);
+ foreach (var blk in impl.Blocks)
+ {
+ foreach (var acmd in blk.Cmds.OfType<AssertCmd>())
+ {
+ var ret = ExtractBoolArgs.Extract(acmd.Expr, funcs);
+ acmd.Expr = ret.Item1;
+ impl.LocVars.AddRange(ret.Item2);
+ }
+ }
+ }
+
+ // convert "assert e1 && forall x: e2" to
+ // assert e1 && e2[x <- x@bound]
+ private void StripOutermostForall(Implementation impl)
+ {
+ var funcs = new HashSet<string>(existentialFunctions.Keys);
+ foreach (var blk in impl.Blocks)
+ {
+ foreach (var acmd in blk.Cmds.OfType<AssertCmd>())
+ {
+ var ret = StripQuantifiers.Run(acmd.Expr, funcs);
+ acmd.Expr = ret.Item1;
+ impl.LocVars.AddRange(ret.Item2);
+ }
+ }
+ }
+
+ private void Inline()
+ {
+ if (CommandLineOptions.Clo.InlineDepth < 0)
+ return;
+
+ var callGraph = BuildCallGraph();
+
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
+ inlineEnsuresVisitor.Visit(impl);
+ }
+
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ impl.OriginalBlocks = impl.Blocks;
+ impl.OriginalLocVars = impl.LocVars;
+ }
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ CommandLineOptions.Inlining savedOption = CommandLineOptions.Clo.ProcedureInlining;
+ CommandLineOptions.Clo.ProcedureInlining = CommandLineOptions.Inlining.Spec;
+ Inliner.ProcessImplementationForHoudini(program, impl);
+ CommandLineOptions.Clo.ProcedureInlining = savedOption;
+ }
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ impl.OriginalBlocks = null;
+ impl.OriginalLocVars = null;
+ }
+
+ Graph<Implementation> oldCallGraph = callGraph;
+ callGraph = new Graph<Implementation>();
+ foreach (Implementation impl in oldCallGraph.Nodes)
+ {
+ callGraph.AddSource(impl);
+ }
+ foreach (Tuple<Implementation, Implementation> edge in oldCallGraph.Edges)
+ {
+ callGraph.AddEdge(edge.Item1, edge.Item2);
+ }
+ int count = CommandLineOptions.Clo.InlineDepth;
+ while (count > 0)
+ {
+ foreach (Implementation impl in oldCallGraph.Nodes)
+ {
+ List<Implementation> newNodes = new List<Implementation>();
+ foreach (Implementation succ in callGraph.Successors(impl))
+ {
+ newNodes.AddRange(oldCallGraph.Successors(succ));
+ }
+ foreach (Implementation newNode in newNodes)
+ {
+ callGraph.AddEdge(impl, newNode);
+ }
+ }
+ count--;
+ }
+ }
+
+ private Graph<Implementation> BuildCallGraph()
+ {
+ Graph<Implementation> callGraph = new Graph<Implementation>();
+ Dictionary<Procedure, HashSet<Implementation>> procToImpls = new Dictionary<Procedure, HashSet<Implementation>>();
+ foreach (var proc in program.Procedures)
+ {
+ procToImpls[proc] = new HashSet<Implementation>();
+ }
+ foreach (var impl in program.Implementations)
+ {
+ if (impl.SkipVerification) continue;
+ callGraph.AddSource(impl);
+ procToImpls[impl.Proc].Add(impl);
+ }
+ foreach (var impl in program.Implementations)
+ {
+ if (impl.SkipVerification) continue;
+ foreach (Block b in impl.Blocks)
+ {
+ foreach (Cmd c in b.Cmds)
+ {
+ CallCmd cc = c as CallCmd;
+ if (cc == null) continue;
+ foreach (Implementation callee in procToImpls[cc.Proc])
+ {
+ callGraph.AddEdge(impl, callee);
+ }
+ }
+ }
+ }
+ return callGraph;
+ }
+
+ }
+
+ class InlineFunctionCalls : StandardVisitor
+ {
+ public Stack<string> inlinedFunctionsStack;
+
+ public InlineFunctionCalls()
+ {
+ inlinedFunctionsStack = new Stack<string>();
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ var fc = node.Fun as FunctionCall;
+ if (fc != null && fc.Func.Body != null && QKeyValue.FindBoolAttribute(fc.Func.Attributes, "inline"))
+ {
+ if (inlinedFunctionsStack.Contains(fc.Func.Name))
+ {
+ // recursion detected
+ throw new AbsHoudiniInternalError("Recursion detected in function declarations");
+ }
+
+ // create a substitution
+ var subst = new Dictionary<Variable, Expr>();
+ for (int i = 0; i < node.Args.Count; i++)
+ {
+ subst.Add(fc.Func.InParams[i], node.Args[i]);
+ }
+
+ var e =
+ Substituter.Apply(new Substitution(v => subst.ContainsKey(v) ? subst[v] : Expr.Ident(v)), fc.Func.Body);
+
+ inlinedFunctionsStack.Push(fc.Func.Name);
+
+ e = base.VisitExpr(e);
+
+ inlinedFunctionsStack.Pop();
+
+ return e;
+ }
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+ class ReplaceFunctionCalls : StandardVisitor
+ {
+ public List<Tuple<string, Function, NAryExpr>> functionsUsed;
+ public List<Function> boolConstants;
+
+ public HashSet<string> functionsAssumed;
+ public HashSet<string> functionsAsserted;
+ HashSet<string> functionsToReplace;
+
+ private bool inAssume;
+ private bool inAssert;
+ private bool inFunction;
+ private List<Dictionary<string, Variable>> boundVars;
+ private static int IdCounter = 0;
+
+ public ReplaceFunctionCalls(HashSet<string> functionsToReplace)
+ {
+ this.functionsUsed = new List<Tuple<string, Function, NAryExpr>>();
+ this.functionsToReplace = functionsToReplace;
+ this.functionsAsserted = new HashSet<string>();
+ this.functionsAssumed = new HashSet<string>();
+ this.boolConstants = new List<Function>();
+ this.boundVars = new List<Dictionary<string, Variable>>();
+
+ inAssume = false;
+ inAssert = false;
+ inFunction = false;
+ }
+
+ public override Cmd VisitAssertCmd(AssertCmd node)
+ {
+ inAssert = true;
+ var ret = base.VisitAssertCmd(node);
+ inAssert = false;
+ return ret;
+ }
+
+ public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node)
+ {
+ return this.VisitAssertCmd(node);
+ }
+
+ public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node)
+ {
+ return this.VisitAssertCmd(node);
+ }
+
+ public override Cmd VisitAssumeCmd(AssumeCmd node)
+ {
+ inAssume = true;
+ var ret = base.VisitAssumeCmd(node);
+ inAssume = false;
+ return ret;
+ }
+
+ public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
+ {
+ // gather the quantified variables
+ var dummies = new Dictionary<string, Variable>();
+ node.Dummies.Iter(v => dummies.Add(v.Name, v));
+
+ boundVars.Add(dummies);
+
+ node = base.VisitQuantifierExpr(node);
+
+ boundVars.RemoveAt(boundVars.Count - 1);
+
+ return node;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ var inF = inFunction;
+
+ if (node.Fun is FunctionCall && functionsToReplace.Contains((node.Fun as FunctionCall).FunctionName))
+ {
+ found((node.Fun as FunctionCall).FunctionName);
+ inFunction = true;
+
+ // collect all the variables used by this function
+ var collector = new VariableCollector();
+ collector.VisitExpr(node);
+
+ // Find the outermost bound variables
+ var bound = new List<Variable>();
+ if(boundVars.Count > 0)
+ bound.AddRange(collector.usedVars.Intersect(boundVars[0].Values));
+
+ // create boolean function to replace this guy
+ var constant = new Function(Token.NoToken, "AbsHoudiniConstant" + IdCounter, bound,
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "r", Microsoft.Boogie.Type.Bool), false));
+ IdCounter++;
+
+ functionsUsed.Add(Tuple.Create((node.Fun as FunctionCall).FunctionName, constant, node));
+ boolConstants.Add(constant);
+
+ var args = new List<Expr>();
+ bound.OfType<Variable>().Select(v => Expr.Ident(v)).Iter(v => args.Add(v));
+ return new NAryExpr(Token.NoToken, new FunctionCall(constant), args);
+ }
+ var ret = base.VisitNAryExpr(node);
+
+ inFunction = inF;
+
+ return ret;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ if (inFunction)
+ {
+ // Inside functions we can only refer to the outermost bound variables
+ for (int i = boundVars.Count - 1; i >= 1; i--)
+ {
+ if (boundVars[i].ContainsKey(node.Name))
+ throw new AbsHoudiniInternalError("Existential functions can only refer to outermost bound variables in an expression");
+ }
+ }
+
+ return base.VisitIdentifierExpr(node);
+ }
+
+ private void found(string func)
+ {
+ if (inAssume) functionsAssumed.Add(func);
+ if (inAssert) functionsAsserted.Add(func);
+ }
+
+ }
+
+ // convert "foo(... e ...) to:
+ // (p iff e) ==> foo(... p ...)
+ // where p is a fresh boolean variable, foo is an existential constant
+ // and e is a Boolean-typed argument of foo
+ class ExtractBoolArgs : StandardVisitor
+ {
+ static int freshConstCounter = 0;
+ HashSet<string> existentialFunctions;
+ HashSet<Constant> newConstants;
+
+ private ExtractBoolArgs(HashSet<string> existentialFunctions)
+ {
+ this.existentialFunctions = existentialFunctions;
+ this.newConstants = new HashSet<Constant>();
+ }
+
+ public static Tuple<Expr, IEnumerable<Constant>> Extract(Expr expr, HashSet<string> existentialFunctions)
+ {
+ var eq = new ExtractBoolArgs(existentialFunctions);
+ expr = eq.VisitExpr(expr);
+ return Tuple.Create(expr, eq.newConstants.AsEnumerable());
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is FunctionCall && existentialFunctions.Contains((node.Fun as FunctionCall).FunctionName))
+ {
+ var constants = new Dictionary<Constant, Expr>();
+ for (int i = 0; i < node.Args.Count; i++)
+ {
+ if (node.Args[i].Type == Type.Bool)
+ {
+ var constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
+ "boolArg@const" + freshConstCounter, Microsoft.Boogie.Type.Bool), false);
+ freshConstCounter++;
+ constants.Add(constant, node.Args[i]);
+ node.Args[i] = Expr.Ident(constant);
+ }
+ }
+
+ newConstants.UnionWith(constants.Keys);
+
+ Expr ret = Expr.True;
+ foreach (var tup in constants)
+ {
+ ret = Expr.And(ret, Expr.Eq(Expr.Ident(tup.Key), tup.Value));
+ }
+ return Expr.Imp(ret, node);
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+ }
+
+
+ // convert "foo(... forall e ...) to:
+ // (p iff forall e) ==> foo(... p ...)
+ // where p is a fresh boolean variable and foo is an existential constant
+ class ExtractQuantifiers : StandardVisitor
+ {
+ static int freshConstCounter = 0;
+ HashSet<string> existentialFunctions;
+ bool insideExistential;
+ Dictionary<Constant, Expr> newConstants;
+
+ private ExtractQuantifiers(HashSet<string> existentialFunctions)
+ {
+ this.existentialFunctions = existentialFunctions;
+ insideExistential = false;
+ newConstants = new Dictionary<Constant, Expr>();
+ }
+
+ public static Tuple<Expr, IEnumerable<Constant>> Extract(Expr expr, HashSet<string> existentialFunctions)
+ {
+ var eq = new ExtractQuantifiers(existentialFunctions);
+ expr = eq.VisitExpr(expr);
+ Expr ret = Expr.True;
+ foreach (var tup in eq.newConstants)
+ {
+ ret = Expr.And(ret, Expr.Eq(Expr.Ident(tup.Key), tup.Value));
+ }
+ ret = Expr.Imp(ret, expr);
+ return Tuple.Create(ret, eq.newConstants.Keys.AsEnumerable());
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ var oldIE = insideExistential;
+
+ if (node.Fun is FunctionCall && existentialFunctions.Contains((node.Fun as FunctionCall).FunctionName))
+ insideExistential = true;
+
+ var ret = base.VisitNAryExpr(node);
+
+ insideExistential = oldIE;
+ return ret;
+ }
+
+ public override Expr VisitExpr(Expr node)
+ {
+ if (node is QuantifierExpr)
+ {
+ return MyVisitQuantifierExpr(node as QuantifierExpr);
+ }
+ return base.VisitExpr(node);
+ }
+
+ public Expr MyVisitQuantifierExpr(QuantifierExpr node)
+ {
+ node = base.VisitQuantifierExpr(node);
+
+ if (insideExistential)
+ {
+ var constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
+ "quant@const" + freshConstCounter, Microsoft.Boogie.Type.Bool), false);
+ freshConstCounter++;
+
+ newConstants.Add(constant, node);
+
+ return Expr.Ident(constant);
+ }
+
+ return node;
+ }
+ }
+
+ // convert "assert e1 && forall x: e2" to
+ // assert e1 && e2[x <- x@bound]
+ // only if e2 has an existential function
+ class StripQuantifiers : StandardVisitor
+ {
+ static int boundVarCounter = 0;
+
+ // 0 -> None, 1 -> Forall, 2 -> Exists, 3 -> Nested
+ int insideQuantifier;
+
+ bool searchExistentialFunction;
+ bool foundExistentialFunction;
+
+ HashSet<string> existentialFunctions;
+ Dictionary<string, LocalVariable> subst;
+ List<LocalVariable> LocalsToAdd;
+
+ private StripQuantifiers(HashSet<string> existentialFunctions)
+ {
+ this.existentialFunctions = existentialFunctions;
+ insideQuantifier = 0;
+ searchExistentialFunction = false;
+ foundExistentialFunction = false;
+ LocalsToAdd = new List<LocalVariable>();
+ subst = null;
+ }
+
+ public static Tuple<Expr,List<LocalVariable>> Run(Expr expr, HashSet<string> existentialFunctions)
+ {
+ // check for type errors first
+ var sq = new StripQuantifiers(existentialFunctions);
+ var ret = sq.VisitExpr(expr);
+
+ return Tuple.Create(ret, sq.LocalsToAdd);
+ }
+
+ public override Expr VisitExpr(Expr node)
+ {
+ if (node is QuantifierExpr)
+ {
+ return MyVisitQuantifierExpr(node as QuantifierExpr);
+ }
+
+ return base.VisitExpr(node);
+ }
+
+ private Expr MyVisitQuantifierExpr(QuantifierExpr node)
+ {
+ var oldIQ = insideQuantifier;
+ Expr ret = node;
+
+ // update "insideQuantifier"
+ if (insideQuantifier == 0)
+ {
+ if (node is ForallExpr) insideQuantifier = 1;
+ else insideQuantifier = 2;
+ }
+ else if (insideQuantifier > 0)
+ {
+ insideQuantifier = 3;
+ }
+
+ // Going inside Forall?
+ if (insideQuantifier == 1)
+ {
+ // see if there is any existential function inside
+ searchExistentialFunction = true;
+ foundExistentialFunction = false;
+ base.VisitQuantifierExpr(node);
+
+ if (foundExistentialFunction)
+ {
+ // create substitution to apply
+ subst = new Dictionary<string, LocalVariable>();
+ foreach (var bv in node.Dummies.OfType<Variable>())
+ {
+ var lv = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
+ bv + "@bound" + boundVarCounter, bv.TypedIdent.Type));
+ boundVarCounter++;
+ subst.Add(bv.Name, lv);
+ LocalsToAdd.Add(lv);
+ }
+
+ // apply the subst
+ var body = base.VisitExpr(node.Body);
+ ret = body;
+
+ subst = null;
+ }
+ else
+ {
+ ret = base.VisitQuantifierExpr(node);
+ }
+
+ searchExistentialFunction = false;
+ foundExistentialFunction = false;
+ }
+ else
+ {
+ ret = base.VisitQuantifierExpr(node);
+ }
+
+ insideQuantifier = oldIQ;
+ return ret;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is FunctionCall && existentialFunctions.Contains((node.Fun as FunctionCall).FunctionName))
+ {
+ if (insideQuantifier == 3)
+ throw new AbsHoudiniInternalError("Existential function found inside exists, or nested foralls");
+
+ if (searchExistentialFunction)
+ foundExistentialFunction = true;
+
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ if (subst != null && subst.ContainsKey(node.Name))
+ return Expr.Ident(subst[node.Name]);
+ return base.VisitIdentifierExpr(node);
+ }
+
+ }
+
+ public class Intervals : IAbstractDomain
+ {
+ // [lower, upper]
+ int upper;
+ int lower;
+ // or: \bot
+ bool isBottom;
+ // number of times join has been performed
+ int nJoin;
+ // number of times before we widen
+ readonly static int maxJoin = 5;
+
+ public Intervals()
+ {
+ this.upper = 0;
+ this.lower = 0;
+ this.nJoin = 0;
+ this.isBottom = true;
+ }
+
+ private Intervals(int lower, int upper, int nJoin)
+ {
+ this.upper = upper;
+ this.lower = lower;
+ this.nJoin = nJoin;
+ }
+
+ public IAbstractDomain Bottom()
+ {
+ return new Intervals();
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ if (lower == Int32.MinValue && upper == Int32.MaxValue)
+ {
+ changed = false;
+ return this;
+ }
+ changed = true;
+ return new Intervals(Int32.MinValue, Int32.MaxValue, 0);
+ }
+
+ public IAbstractDomain Join(List<Model.Element> states)
+ {
+ Debug.Assert(states.Count == 1);
+ var state = states[0] as Model.Integer;
+ if (state == null)
+ throw new AbsHoudiniInternalError("Incorrect type, expected int");
+ var intval = state.AsInt();
+
+ if (isBottom)
+ {
+ return new Intervals(intval, intval, 1);
+ }
+
+ if(intval >= lower && intval <= upper)
+ return this;
+
+ if (nJoin > maxJoin)
+ {
+ // widen
+ if (intval > upper)
+ return new Intervals(lower, Int32.MaxValue, 1);
+ if(intval < lower)
+ return new Intervals(Int32.MinValue, upper, 1);
+
+ Debug.Assert(false);
+ }
+
+ if (intval > upper)
+ return new Intervals(lower, intval, nJoin + 1);
+ if (intval < lower)
+ return new Intervals(intval, upper, nJoin + 1);
+
+ Debug.Assert(false);
+ return null;
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ Debug.Assert(vars.Count == 1);
+ var v = vars[0];
+ if (isBottom) return Expr.False;
+ Expr ret = Expr.True;
+ if (lower != Int32.MinValue)
+ ret = Expr.And(ret, Expr.Ge(v, Expr.Literal(lower)));
+ if (upper != Int32.MaxValue)
+ ret = Expr.And(ret, Expr.Le(v, Expr.Literal(upper)));
+ return ret;
+ }
+
+ public bool TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Count != 1)
+ {
+ msg = "Illegal number of arguments";
+ return false;
+ }
+ if (!argTypes[0].IsInt)
+ {
+ msg = "Illegal type, expecting int";
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public class PredicateAbsFullElem : PredicateAbsElem
+ {
+ public PredicateAbsFullElem()
+ : base(1000)
+ { }
+ }
+
+ public class PredicateAbsElem : IAbstractDomain
+ {
+ public static class ExprExt
+ {
+ public static Expr AndSimp(Expr e1, Expr e2)
+ {
+ if (e1 == Expr.True) return e2;
+ if (e2 == Expr.True) return e1;
+ if (e1 == Expr.False || e2 == Expr.False) return Expr.False;
+ return Expr.And(e1, e2);
+ }
+
+ public static Expr OrSimp(Expr e1, Expr e2)
+ {
+ if (e1 == Expr.False) return e2;
+ if (e2 == Expr.False) return e1;
+ if (e1 == Expr.True || e2 == Expr.True) return Expr.True;
+ return Expr.Or(e1, e2);
+ }
+ }
+
+ class Disjunct
+ {
+ HashSet<int> pos;
+ HashSet<int> neg;
+ bool isTrue;
+
+ public Disjunct()
+ {
+ isTrue = true;
+ pos = new HashSet<int>();
+ neg = new HashSet<int>();
+ }
+
+ public Disjunct(IEnumerable<int> pos, IEnumerable<int> neg, int bound)
+ {
+ this.isTrue = false;
+ this.pos = new HashSet<int>(pos);
+ this.neg = new HashSet<int>(neg);
+ if (this.pos.Overlaps(this.neg))
+ {
+ this.isTrue = true;
+ this.pos = new HashSet<int>();
+ this.neg = new HashSet<int>();
+ }
+ if (this.pos.Count + this.neg.Count > bound)
+ {
+ // Set to true
+ this.isTrue = true;
+ this.pos = new HashSet<int>();
+ this.neg = new HashSet<int>();
+ }
+
+ }
+
+ public Disjunct OR(Disjunct that, int bound)
+ {
+ if (isTrue)
+ return this;
+ if (that.isTrue)
+ return that;
+
+ return new Disjunct(this.pos.Concat(that.pos), this.neg.Concat(that.neg), bound);
+ }
+
+ public bool Implies(Disjunct that)
+ {
+ if (isTrue) return that.isTrue;
+ if (that.isTrue) return true;
+
+ return pos.IsSubsetOf(that.pos) && neg.IsSubsetOf(that.neg);
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ if (isTrue) return Expr.True;
+ Expr ret = Expr.False;
+ pos.Iter(i => ret = ExprExt.OrSimp(ret, vars[i]));
+ neg.Iter(i => ret = ExprExt.OrSimp(ret, Expr.Not(vars[i])));
+ return ret;
+ }
+ }
+
+ // Conjunction of Disjuncts
+ List<Disjunct> conjuncts;
+ int DisjunctBound;
+ bool isFalse;
+
+ public PredicateAbsElem()
+ {
+ this.conjuncts = new List<Disjunct>();
+ this.isFalse = true;
+ this.DisjunctBound = 3;
+ }
+
+ public PredicateAbsElem(int bound)
+ {
+ this.conjuncts = new List<Disjunct>();
+ this.isFalse = true;
+ this.DisjunctBound = bound;
+ }
+
+ public IAbstractDomain Bottom()
+ {
+ return new PredicateAbsElem(DisjunctBound);
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ if (conjuncts.Count == 0)
+ {
+ changed = false;
+ return this;
+ }
+ changed = true;
+ var ret = new PredicateAbsElem(DisjunctBound);
+ ret.isFalse = false;
+ return ret;
+ }
+
+ public IAbstractDomain Join(List<Model.Element> state)
+ {
+ if (state.Any(me => !(me is Model.Boolean)))
+ throw new AbsHoudiniInternalError("Predicate Abstraction requires that each argument be of type bool");
+
+ // quick return if this == true
+ if (!this.isFalse && conjuncts.Count == 0)
+ return this;
+
+ var ret = new PredicateAbsElem(DisjunctBound);
+ ret.isFalse = false;
+
+ for (int i = 0; i < state.Count; i++)
+ {
+ var b = (state[i] as Model.Boolean).Value;
+ Disjunct d = null;
+ if (b) d = new Disjunct(new int[] { i }, new int[] { }, DisjunctBound);
+ else d = new Disjunct(new int[] { }, new int[] { i }, DisjunctBound);
+
+ if (isFalse)
+ ret.AddDisjunct(d);
+ else
+ {
+ conjuncts.Iter(c => ret.AddDisjunct(c.OR(d, DisjunctBound)));
+ }
+ }
+
+ return ret;
+
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ if (isFalse) return Expr.False;
+ Expr ret = Expr.True;
+
+ foreach (var c in conjuncts)
+ {
+ ret = ExprExt.AndSimp(ret, c.Gamma(vars));
+ }
+
+ return ret;
+ }
+
+ public bool TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Any(t => !t.IsBool))
+ {
+ msg = "Illegal type, expecting bool";
+ return false;
+ }
+ return true;
+ }
+
+ private void AddDisjunct(Disjunct d)
+ {
+ if (conjuncts.Any(c => c.Implies(d)))
+ return;
+
+ conjuncts.RemoveAll(c => d.Implies(c));
+ conjuncts.Add(d);
+ }
+ }
+
+ // [false -- (x == true) -- true]
+ public class HoudiniConst : IAbstractDomain
+ {
+ bool isBottom;
+ bool isTop;
+
+ private HoudiniConst(bool isTop, bool isBottom)
+ {
+ this.isBottom = isBottom;
+ this.isTop = isTop;
+ Debug.Assert(!(isTop && isBottom));
+ }
+
+ public static HoudiniConst GetExtObj()
+ {
+ return new HoudiniConst(false, false);
+ }
+
+ public static HoudiniConst GetTop()
+ {
+ return new HoudiniConst(true, false);
+ }
+
+ public static HoudiniConst GetBottom()
+ {
+ return new HoudiniConst(false, true);
+ }
+
+ public IAbstractDomain Bottom()
+ {
+ return GetBottom();
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ changed = false;
+ if (isTop) return this;
+ changed = true;
+ return GetTop();
+ }
+
+ public IAbstractDomain Join(List<Model.Element> states)
+ {
+ Debug.Assert(states.Count == 1);
+ var state = states[0];
+
+ if (isTop) return this;
+
+ if (state is Model.Boolean)
+ {
+ if ((state as Model.Boolean).Value)
+ return GetExtObj();
+ }
+
+ return GetTop();
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ Debug.Assert(vars.Count == 1);
+ var v = vars[0];
+ if (isBottom) return Expr.False;
+ if (isTop) return Expr.True;
+ return v;
+ }
+
+ public bool TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Count != 1)
+ {
+ msg = "Illegal number of arguments, expecting 1";
+ return false;
+ }
+ if (!argTypes[0].IsBool)
+ {
+ msg = "Illegal type, expecting bool";
+ return false;
+ }
+ return true;
+ }
+ }
+
+ // foo(x) = x < 2^j for some j <= 16
+ public class PowDomain : IAbstractDomain
+ {
+ enum Val { FALSE, NEITHER, TRUE };
+ Val tlevel;
+ bool isBottom { get { return tlevel == Val.FALSE; } }
+ bool isTop { get { return tlevel == Val.TRUE; } }
+
+ readonly int Max = 16;
+
+ int upper; // <= Max
+
+ private PowDomain(Val tlevel) :
+ this(tlevel, 0) { }
+
+ private PowDomain(Val tlevel, int upper)
+ {
+ this.tlevel = tlevel;
+ this.upper = upper;
+ }
+
+ public static IAbstractDomain GetBottom()
+ {
+ return new PowDomain(Val.FALSE) as IAbstractDomain;
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ if (isTop)
+ {
+ changed = false;
+ return this;
+ }
+ changed = true;
+ return new PowDomain(Val.TRUE);
+ }
+
+ IAbstractDomain IAbstractDomain.Bottom()
+ {
+ return GetBottom();
+ }
+
+ IAbstractDomain IAbstractDomain.Join(List<Model.Element> state)
+ {
+ if (isTop) return this;
+
+ int v = 0;
+ if (state[0] is Model.BitVector)
+ v = (state[0] as Model.BitVector).AsInt();
+ else if (state[0] is Model.Integer)
+ v = (state[0] as Model.Integer).AsInt();
+ else Debug.Assert(false);
+
+ var nupper = upper;
+ while ((1 << nupper) < v) nupper++;
+ var ntlevel = Val.NEITHER;
+ if (nupper > Max) ntlevel = Val.TRUE;
+ return new PowDomain(ntlevel, nupper);
+ }
+
+ Expr IAbstractDomain.Gamma(List<Expr> vars)
+ {
+ if (isBottom) return Expr.False;
+ if (isTop) return Expr.True;
+ var v = vars[0];
+ if (v.Type.IsBv)
+ {
+ var bits = v.Type.BvBits;
+ if (!AbstractDomainFactory.bvslt.ContainsKey(bits))
+ throw new AbsHoudiniInternalError("No builtin function found for bv" + bits.ToString());
+ var bvslt = AbstractDomainFactory.bvslt[bits];
+ return new NAryExpr(Token.NoToken, new FunctionCall(bvslt), new List<Expr> { v,
+ new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(1 << (upper+1)), 32) });
+ }
+ else
+ {
+ return Expr.Lt(v, Expr.Literal(1 << (upper+1)));
+ }
+ }
+
+ bool IAbstractDomain.TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Count != 1)
+ {
+ msg = "Illegal number of arguments, expecting 1";
+ return false;
+ }
+ if (argTypes.Any(tt => !tt.IsInt && !tt.IsBv))
+ {
+ msg = "Illegal type, expecting int or bv";
+ return false;
+ }
+ return true;
+ }
+ }
+
+ // foo(x_i) = all equalities that hold
+ public class EqualitiesDomain : IAbstractDomain
+ {
+ bool isBottom;
+ List<HashSet<int>> equalities;
+
+ public EqualitiesDomain(bool isBottom, List<HashSet<int>> eq)
+ {
+ this.isBottom = isBottom;
+ this.equalities = eq;
+ }
+
+ public static IAbstractDomain GetBottom()
+ {
+ return new EqualitiesDomain(true, new List<HashSet<int>>());
+ }
+
+ IAbstractDomain IAbstractDomain.Bottom()
+ {
+ return GetBottom();
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ if (equalities.Count == 0)
+ {
+ changed = false;
+ return this;
+ }
+ changed = true;
+ return new EqualitiesDomain(false, new List<HashSet<int>>());
+ }
+
+ IAbstractDomain IAbstractDomain.Join(List<Model.Element> state)
+ {
+ // find the guys that are equal
+ var eq = new List<HashSet<int>>();
+ for (int i = 0; i < state.Count; i++)
+ {
+ var added = false;
+ foreach (var s in eq)
+ {
+ var sv = s.First();
+ if (state[i].ToString() == state[sv].ToString())
+ {
+ s.Add(i);
+ added = true;
+ break;
+ }
+ }
+ if (!added) eq.Add(new HashSet<int>(new int[] { i }));
+ }
+
+ if (isBottom)
+ {
+ return new EqualitiesDomain(false, eq);
+ }
+
+ // intersect two partitions equalities and eq
+ var m1 = GetMap(equalities, state.Count);
+ var m2 = GetMap(eq, state.Count);
+
+ for (int i = 0; i < state.Count; i++)
+ m2[i] = new HashSet<int>(m2[i].Intersect(m1[i]));
+
+
+ // map from representative to set
+ var repToSet = new Dictionary<int, HashSet<int>>();
+
+ for (int i = 0; i < state.Count; i++)
+ {
+ var rep = m2[i].Min();
+ if (!repToSet.ContainsKey(rep))
+ repToSet[rep] = m2[i];
+ }
+
+ var ret = new List<HashSet<int>>();
+ repToSet.Values.Iter(s => ret.Add(s));
+
+ return new EqualitiesDomain(false, ret);
+ }
+
+ Expr IAbstractDomain.Gamma(List<Expr> vars)
+ {
+ if (isBottom) return Expr.False;
+ Expr ret = Expr.True;
+ foreach (var eq in equalities.Select(hs => hs.ToList()))
+ {
+ if (eq.Count == 1) continue;
+ var prev = eq[0];
+ for (int i = 1; i < eq.Count; i++)
+ {
+ ret = Expr.And(ret, Expr.Eq(vars[prev], vars[eq[i]]));
+ prev = eq[i];
+ }
+ }
+ return ret;
+ }
+
+ bool IAbstractDomain.TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Count == 0) return true;
+ var ot = argTypes[0];
+
+ if (argTypes.Any(tt => !tt.Equals(ot)))
+ {
+ msg = string.Format("Illegal type, expecting type {0}, got {1}", ot, argTypes.First(tt => !tt.Equals(ot)));
+ return false;
+ }
+ return true;
+ }
+
+ private HashSet<int>[] GetMap(List<HashSet<int>> eq, int n)
+ {
+ var ret = new HashSet<int>[n];
+ foreach (var s in eq)
+ {
+ foreach (var i in s)
+ ret[i] = s;
+ }
+ return ret;
+ }
+ }
+
+ // foo(a,b) \in {false, \not a, a ==> b, true}
+ public class ImplicationDomain : IAbstractDomain
+ {
+ enum Val {FALSE, NOT_A, A_IMP_B, TRUE};
+ Val val;
+
+ private ImplicationDomain(Val val)
+ {
+ this.val = val;
+ }
+
+ public static ImplicationDomain GetBottom()
+ {
+ return new ImplicationDomain(Val.FALSE);
+ }
+
+ public IAbstractDomain Bottom()
+ {
+ return GetBottom();
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ if(val == Val.TRUE) {
+ changed = false;
+ return this;
+ }
+ changed = true;
+ return new ImplicationDomain(Val.TRUE);
+ }
+
+ public IAbstractDomain Join(List<Model.Element> states)
+ {
+ Debug.Assert(states.Count == 2);
+ var v1 = (states[0] as Model.Boolean).Value;
+ var v2 = (states[1] as Model.Boolean).Value;
+
+ if (val == Val.TRUE) return this;
+
+ var that = Val.TRUE;
+ if (!v1) that = Val.NOT_A;
+ else if (!v1 || v2) that = Val.A_IMP_B;
+
+ if (that == Val.TRUE || val == Val.FALSE)
+ return new ImplicationDomain(that);
+
+ // Now, neither this or that is FALSE or TRUE
+ if (val == that)
+ return this;
+
+ Debug.Assert(val == Val.A_IMP_B || that == Val.A_IMP_B);
+ return new ImplicationDomain(Val.A_IMP_B);
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ Debug.Assert(vars.Count == 2);
+
+ var v1 = vars[0];
+ var v2 = vars[1];
+
+ if (val == Val.FALSE) return Expr.False;
+ if (val == Val.TRUE) return Expr.True;
+ if (val == Val.NOT_A) return Expr.Not(v1);
+ return Expr.Imp(v1, v2);
+ }
+
+ public bool TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Count != 2)
+ {
+ msg = "Illegal number of arguments, expecting 2";
+ return false;
+ }
+ if (argTypes.Any(tt => !tt.IsBool))
+ {
+ msg = "Illegal type, expecting bool";
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public class ConstantProp : IAbstractDomain
+ {
+ object val;
+ bool isBottom;
+ bool isTop;
+
+ private ConstantProp(object val, bool isTop, bool isBottom)
+ {
+ this.val = val;
+ this.isBottom = isBottom;
+ this.isTop = isTop;
+ Debug.Assert(!(isTop && isBottom));
+ Debug.Assert(val == null || (val is int) || (val is bool));
+ }
+
+ public static ConstantProp GetExtObj(object val)
+ {
+ Debug.Assert(val != null);
+ return new ConstantProp(val, false, false);
+ }
+
+ public static ConstantProp GetTop()
+ {
+ return new ConstantProp(null, true, false);
+ }
+
+ public static ConstantProp GetBottom()
+ {
+ return new ConstantProp(null, false, true);
+ }
+
+ public IAbstractDomain MakeTop(out bool changed) {
+ if (isTop)
+ {
+ changed = false;
+ return this;
+ }
+ changed = true;
+ return GetTop();
+ }
+
+ private ConstantProp Join(ConstantProp that)
+ {
+ if (isBottom) return that;
+ if (isTop) return this;
+ if (that.isBottom) return this;
+ if (that.isTop) return that;
+
+ if ((val is int) && !(that.val is int))
+ throw new AbsHoudiniInternalError("Type mismatch in ExtObj");
+
+ if ((val is bool) && !(that.val is bool))
+ throw new AbsHoudiniInternalError("Type mismatch in ExtObj");
+
+ if (val is int)
+ {
+ var v1 = (int)val;
+ var v2 = (int)that.val;
+ if (v1 != v2) return GetTop();
+ return this;
+ }
+ else if (val is bool)
+ {
+ var v1 = (bool)val;
+ var v2 = (bool)that.val;
+ if (v1 != v2) return GetTop();
+ return this;
+ }
+ throw new AbsHoudiniInternalError("Illegal val type in ExtObj");
+ }
+
+ public IAbstractDomain Bottom()
+ {
+ return GetBottom();
+ }
+
+ public IAbstractDomain Join(List<Model.Element> states)
+ {
+ Debug.Assert(states.Count == 1);
+ var state = states[0];
+ ConstantProp that = null;
+
+ if (state is Model.Integer)
+ {
+ that = GetExtObj((state as Model.Integer).AsInt());
+ }
+ else if (state is Model.Boolean)
+ {
+ that = GetExtObj((state as Model.Boolean).Value);
+ }
+ else
+ {
+ throw new AbsHoudiniInternalError("Illegal type " + state.GetType().ToString());
+ }
+
+ return Join(that);
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ Debug.Assert(vars.Count == 1);
+ var v = vars[0];
+ if (isBottom) return Expr.False;
+ if (isTop) return Expr.True;
+ if (val is int)
+ return Expr.Eq(v, Expr.Literal((int)val));
+ if (val is bool && (bool)val)
+ return v;
+ if (val is bool && !(bool)val)
+ return Expr.Not(v);
+
+ return null;
+ }
+
+ public bool TypeCheck(List<Type> argTypes, out string msg)
+ {
+ msg = "";
+ if (argTypes.Count != 1)
+ {
+ msg = "Illegal number of arguments, expecting 1";
+ return false;
+ }
+ if (!argTypes[0].IsInt && ! argTypes[0].IsBool)
+ {
+ msg = "Illegal type, expecting int or bool";
+ return false;
+ }
+ return true;
+ }
+ }
+
+
+ public class IndependentAttribute<T> : IAbstractDomain where T : class, IAbstractDomain
+ {
+ bool isBottom;
+ int numVars;
+ List<T> varVal;
+ T underlyingInstance;
+
+ public IndependentAttribute()
+ {
+ isBottom = true;
+ numVars = 0;
+ varVal = new List<T>();
+ underlyingInstance = null;
+ }
+
+ public IAbstractDomain Bottom()
+ {
+ return new IndependentAttribute<T>();
+ }
+
+ public IAbstractDomain MakeTop(out bool changed)
+ {
+ var mt = new Func<IAbstractDomain>(() =>
+ {
+ var ret = new IndependentAttribute<T>();
+ ret.isBottom = true;
+ ret.numVars = numVars;
+ ret.underlyingInstance = underlyingInstance;
+ ret.varVal = new List<T>();
+ bool tmp;
+ for (int i = 0; i < varVal.Count; i++)
+ ret.varVal.Add(varVal[i].MakeTop(out tmp) as T);
+ return ret;
+ });
+
+ if (!isBottom)
+ {
+ foreach (var t in varVal)
+ {
+ var top = t.MakeTop(out changed);
+ if (changed)
+ {
+ return mt();
+ }
+ }
+ }
+ else
+ {
+ changed = true;
+ return mt();
+ }
+
+ changed = false;
+ return this;
+ }
+ public IAbstractDomain Join(List<Model.Element> state)
+ {
+ SetUnderlyingInstance();
+
+ if (!isBottom && numVars != state.Count)
+ {
+ throw new AbsHoudiniInternalError(
+ string.Format("Got illegal number of arguments ({0}), expected {1}", state.Count, numVars));
+ }
+
+ var ret = new IndependentAttribute<T>();
+ ret.isBottom = false;
+ ret.numVars = state.Count;
+ for(int i = 0; i < state.Count; i++)
+ {
+ var sl = new List<Model.Element>();
+ sl.Add(state[i]);
+ T prev = isBottom ? underlyingInstance.Bottom() as T : varVal[i];
+ ret.varVal.Add(prev.Join(sl) as T);
+ }
+
+ return ret;
+ }
+
+ public Expr Gamma(List<Expr> vars)
+ {
+ if (isBottom) return Expr.False;
+ if (numVars != vars.Count)
+ throw new AbsHoudiniInternalError(
+ string.Format("Got illegal number of arguments ({0}), expected {1}", vars.Count, numVars));
+
+ Expr ret = Expr.True;
+ for (int i = 0; i < numVars; i++)
+ {
+ var sl = new List<Expr>(); sl.Add(vars[i]);
+ ret = Expr.And(ret, varVal[i].Gamma(sl));
+ }
+
+ return ret;
+ }
+
+ private void SetUnderlyingInstance()
+ {
+ if (underlyingInstance != null) return;
+ var tt = typeof(T);
+ underlyingInstance = AbstractDomainFactory.GetInstance(tt) as T;
+ }
+
+ public bool TypeCheck(List<Type> argTypes, out string msg)
+ {
+ SetUnderlyingInstance();
+
+ msg = "";
+ foreach(var t in argTypes)
+ {
+ if(!underlyingInstance.TypeCheck(new List<Type>(new Type[] { t }), out msg))
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public class AbstractDomainFactory
+ {
+ // Type name -> Instance
+ private static Dictionary<string, IAbstractDomain> abstractDomainInstances = new Dictionary<string, IAbstractDomain>();
+ private static Dictionary<string, IAbstractDomain> abstractDomainInstancesFriendly = new Dictionary<string, IAbstractDomain>();
+
+ // bitvector operations
+ public static Dictionary<int, Function> bvslt = new Dictionary<int, Function>();
+
+ public static void Register(string friendlyName, IAbstractDomain instance)
+ {
+ var Name = instance.GetType().FullName;
+ Debug.Assert(!abstractDomainInstances.ContainsKey(Name));
+ abstractDomainInstances.Add(Name, instance);
+ abstractDomainInstancesFriendly.Add(friendlyName, instance);
+ }
+
+ public static IAbstractDomain GetInstance(System.Type type)
+ {
+ var Name = type.FullName;
+ Debug.Assert(abstractDomainInstances.ContainsKey(Name));
+ return abstractDomainInstances[Name] as IAbstractDomain;
+ }
+
+ public static IAbstractDomain GetInstance(string friendlyName)
+ {
+ if (!abstractDomainInstancesFriendly.ContainsKey(friendlyName))
+ {
+ Console.WriteLine("Domain {0} not found", friendlyName);
+ Console.WriteLine("Supported domains are:");
+ abstractDomainInstancesFriendly.Keys.Iter(tup => Console.WriteLine(" {0}", tup));
+ throw new AbsHoudiniInternalError("Domain not found");
+ }
+ return abstractDomainInstancesFriendly[friendlyName] as IAbstractDomain;
+ }
+
+ public static void Initialize(Program program)
+ {
+ // Declare abstract domains
+ var domains = new List<System.Tuple<string, IAbstractDomain>>(new System.Tuple<string, IAbstractDomain>[] {
+ System.Tuple.Create("HoudiniConst", HoudiniConst.GetBottom() as IAbstractDomain),
+ System.Tuple.Create("Intervals", new Intervals() as IAbstractDomain),
+ System.Tuple.Create("ConstantProp", ConstantProp.GetBottom() as IAbstractDomain),
+ System.Tuple.Create("PredicateAbs", new PredicateAbsElem() as IAbstractDomain),
+ System.Tuple.Create("PredicateAbsFull", new PredicateAbsFullElem() as IAbstractDomain),
+ System.Tuple.Create("ImplicationDomain", ImplicationDomain.GetBottom() as IAbstractDomain),
+ System.Tuple.Create("PowDomain", PowDomain.GetBottom() as IAbstractDomain),
+ System.Tuple.Create("EqualitiesDomain", EqualitiesDomain.GetBottom() as IAbstractDomain),
+ System.Tuple.Create("IA[HoudiniConst]", new IndependentAttribute<HoudiniConst>() as IAbstractDomain),
+ System.Tuple.Create("IA[ConstantProp]", new IndependentAttribute<ConstantProp>() as IAbstractDomain),
+ System.Tuple.Create("IA[Intervals]", new IndependentAttribute<Intervals>() as IAbstractDomain),
+ System.Tuple.Create("IA[PowDomain]", new IndependentAttribute<PowDomain>() as IAbstractDomain),
+ });
+
+ domains.Iter(tup => AbstractDomainFactory.Register(tup.Item1, tup.Item2));
+ program.Functions.Iter(RegisterFunction);
+ }
+
+ private static void RegisterFunction(Function func)
+ {
+ var attr = QKeyValue.FindStringAttribute(func.Attributes, "bvbuiltin");
+ if (attr != null && attr == "bvslt" && func.InParams.Count == 2 && func.InParams[0].TypedIdent.Type.IsBv)
+ bvslt.Add(func.InParams[0].TypedIdent.Type.BvBits, func);
+ }
+ }
+
+ public interface IAbstractDomain
+ {
+ IAbstractDomain Bottom();
+ IAbstractDomain MakeTop(out bool changed);
+ IAbstractDomain Join(List<Model.Element> state);
+ Expr Gamma(List<Expr> vars);
+ bool TypeCheck(List<Type> argTypes, out string msg);
+ }
+
+ public class AbstractHoudini
+ {
+ // Input Program
+ Program program;
+ // Impl -> VC
+ Dictionary<string, VCExpr> impl2VC;
+ // Impl -> Vars at end of the impl
+ Dictionary<string, List<VCExpr>> impl2EndStateVars;
+ // Impl -> (callee,summary pred)
+ Dictionary<string, List<Tuple<string, bool, VCExprVar, VCExprNAry>>> impl2CalleeSummaries;
+ // pointer to summary class
+ ISummaryElement summaryClass;
+ // impl -> summary
+ Dictionary<string, ISummaryElement> impl2Summary;
+ // name -> impl
+ Dictionary<string, Implementation> name2Impl;
+ // Use Bilateral algorithm
+ public static bool UseBilateralAlgo = true;
+ public static int iterTimeLimit = -1; // ms
+
+ public static readonly string summaryPredSuffix = "SummaryPred";
+
+ // Essentials: VCGen, Prover, and reporter
+ VCGen vcgen;
+ ProverInterface prover;
+ AbstractHoudiniErrorReporter reporter;
+
+ // Stats
+ TimeSpan proverTime;
+ int numProverQueries;
+
+ // Produce witness for correctness: can be set programmatically
+ public static string WitnessFile = "absHoudiniWitness.bpl";
+
+ public AbstractHoudini(Program program)
+ {
+ this.program = program;
+ this.impl2VC = new Dictionary<string, VCExpr>();
+ this.impl2EndStateVars = new Dictionary<string, List<VCExpr>>();
+ this.impl2CalleeSummaries = new Dictionary<string, List<Tuple<string, bool, VCExprVar, VCExprNAry>>>();
+ this.impl2Summary = new Dictionary<string, ISummaryElement>();
+ this.name2Impl = SimpleUtil.nameImplMapping(program);
+
+ if (CommandLineOptions.Clo.ProverKillTime > 0)
+ CommandLineOptions.Clo.ProverOptions = CommandLineOptions.Clo.ProverOptions.Concat1(string.Format("TIME_LIMIT={0}", CommandLineOptions.Clo.ProverKillTime));
+
+ this.vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List<Checker>());
+ this.prover = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, -1);
+
+ this.reporter = new AbstractHoudiniErrorReporter();
+
+ this.proverTime = TimeSpan.Zero;
+ this.numProverQueries = 0;
+
+ if (CommandLineOptions.Clo.AbstractHoudini == "0")
+ UseBilateralAlgo = false;
+ }
+
+ public void computeSummaries(ISummaryElement summaryClass)
+ {
+ // TODO: move this some place else
+ PredicateAbs.FindUnsatPairs(prover.VCExprGen, prover);
+
+ this.summaryClass = summaryClass;
+
+ name2Impl.Values.Iter(attachEnsures);
+
+ program.Implementations
+ .Iter(impl => impl2Summary.Add(impl.Name, summaryClass.GetFlaseSummary(program, impl)));
+
+ // Build call graph
+ var Succ = new Dictionary<Implementation, HashSet<Implementation>>();
+ var Pred = new Dictionary<Implementation, HashSet<Implementation>>();
+ name2Impl.Values.Iter(impl => Succ.Add(impl, new HashSet<Implementation>()));
+ name2Impl.Values.Iter(impl => Pred.Add(impl, new HashSet<Implementation>()));
+
+ foreach (var impl in program.Implementations)
+ {
+ foreach (var blk in impl.Blocks)
+ {
+ foreach (var cmd in blk.Cmds.OfType<CallCmd>())
+ {
+ if (!name2Impl.ContainsKey(cmd.callee)) continue;
+ Succ[impl].Add(name2Impl[cmd.callee]);
+ Pred[name2Impl[cmd.callee]].Add(impl);
+ }
+ }
+ }
+
+ // Build SCC
+ var sccs = new StronglyConnectedComponents<Implementation>(name2Impl.Values,
+ new Adjacency<Implementation>(n => Pred[n]),
+ new Adjacency<Implementation>(n => Succ[n]));
+ sccs.Compute();
+
+ // impl -> priority
+ var impl2Priority = new Dictionary<string, int>();
+ int p = 0;
+ foreach (var scc in sccs)
+ {
+ foreach (var impl in scc)
+ {
+ impl2Priority.Add(impl.Name, p);
+ p++;
+ }
+ }
+
+
+ Inline();
+
+ #region Witness generation setup
+ // Create a copy of the program
+ var copy = new Dictionary<string, Implementation>();
+ if (WitnessFile != null)
+ {
+ foreach (var impl in program.Implementations)
+ {
+ var nimpl = new Implementation(Token.NoToken, impl.Name, impl.TypeParameters,
+ impl.InParams, impl.OutParams, new List<Variable>(impl.LocVars), new List<Block>());
+ foreach (var blk in impl.Blocks)
+ {
+ var cd = new CodeCopier();
+ nimpl.Blocks.Add(new Block(Token.NoToken, blk.Label,
+ cd.CopyCmdSeq(blk.Cmds), cd.CopyTransferCmd(blk.TransferCmd)));
+ }
+
+ copy.Add(impl.Name, nimpl);
+ }
+ }
+ #endregion
+
+ // Turn off subsumption. Why? Because then I see multiple occurences of the
+ // attached ensures in the VC
+ CommandLineOptions.Clo.UseSubsumption = CommandLineOptions.SubsumptionOption.Never;
+
+ // Create all VCs
+ name2Impl.Values
+ .Iter(GenVC);
+
+ // Start the iteration
+ var worklist = new SortedSet<Tuple<int, Implementation>>();
+ name2Impl.Values
+ .Iter(impl => worklist.Add(Tuple.Create(impl2Priority[impl.Name], impl)));
+
+ while (worklist.Any())
+ {
+ var impl = worklist.First().Item2;
+ worklist.Remove(worklist.First());
+
+ var changed = ProcessImpl(impl);
+
+ if (changed)
+ {
+ Pred[impl].Where(pred => UseBilateralAlgo || pred != impl).Iter(pred => worklist.Add(Tuple.Create(impl2Priority[pred.Name], pred)));
+ }
+ }
+
+ var allImpls = new SortedSet<Tuple<int, string>>();
+ name2Impl.Values.Iter(impl => allImpls.Add(Tuple.Create(impl2Priority[impl.Name], impl.Name)));
+ if (CommandLineOptions.Clo.Trace)
+ {
+ foreach (var tup in allImpls)
+ {
+ Console.WriteLine("Summary of {0}:", tup.Item2);
+ Console.WriteLine("{0}", impl2Summary[tup.Item2]);
+ }
+ Console.WriteLine("Prover time = {0}", proverTime.TotalSeconds.ToString("F2"));
+ Console.WriteLine("Number of prover queries = " + numProverQueries);
+ }
+
+ ProduceWitness(copy);
+
+ prover.Close();
+ CommandLineOptions.Clo.TheProverFactory.Close();
+ }
+
+ public HashSet<string> GetPredicates()
+ {
+ var ret = new HashSet<string>();
+ prover = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, -1);
+
+ foreach (var tup in impl2Summary)
+ {
+ var s = tup.Value as PredicateAbs;
+ if (s == null) continue;
+ ret.UnionWith(s.GetPredicates(program, prover.VCExprGen, prover));
+ // debug output
+ //Console.WriteLine("Summary of {0}:", tup.Key);
+ //Console.WriteLine("{0}", tup.Value);
+ }
+
+ prover.Close();
+ CommandLineOptions.Clo.TheProverFactory.Close();
+ return ret;
+ }
+
+ // Obtain the summary expression for a procedure: used programmatically by clients
+ // of AbstractHoudini
+ public Expr GetSummary(Program program, Procedure proc)
+ {
+ if (!impl2Summary.ContainsKey(proc.Name))
+ return Expr.True;
+
+ var vars = new Dictionary<string, Expr>();
+ foreach (var g in program.GlobalVariables)
+ vars.Add(g.Name, Expr.Ident(g));
+ foreach (var v in proc.InParams.OfType<Variable>())
+ vars.Add(v.Name, Expr.Ident(v));
+ foreach (var v in proc.OutParams.OfType<Variable>())
+ vars.Add(v.Name, Expr.Ident(v));
+
+ return impl2Summary[proc.Name].GetSummaryExpr(
+ v => { if (vars.ContainsKey(v)) return vars[v]; else return null; },
+ v => { if (vars.ContainsKey(v)) return new OldExpr(Token.NoToken, vars[v]); else return null; });
+ }
+
+ public ISummaryElement GetSummaryLowLevel(Procedure proc)
+ {
+ if (!impl2Summary.ContainsKey(proc.Name)) return null;
+ return impl2Summary[proc.Name];
+ }
+
+ // Produce a witness that proves that the inferred annotations are correct
+ private void ProduceWitness(Dictionary<string, Implementation> copy)
+ {
+ if (WitnessFile == null)
+ return;
+
+ foreach (var proc in program.Procedures)
+ {
+ var nensures = new List<Ensures>();
+ proc.Ensures.OfType<Ensures>()
+ .Where(ens => !QKeyValue.FindBoolAttribute(ens.Attributes, "ah") &&
+ !QKeyValue.FindBoolAttribute(ens.Attributes, "pre") &&
+ !QKeyValue.FindBoolAttribute(ens.Attributes, "post") &&
+ QKeyValue.FindStringAttribute(ens.Attributes, "pre") == null &&
+ QKeyValue.FindStringAttribute(ens.Attributes, "post") == null)
+ .Iter(ens => nensures.Add(ens));
+ foreach (Ensures en in nensures)
+ en.Attributes = removeAttr("InlineAssume", en.Attributes);
+
+ proc.Ensures = nensures;
+ }
+
+ var decls = new List<Declaration>(copy.Values);
+ decls.AddRange(program.TopLevelDeclarations.Where(decl => !(decl is Implementation)));
+ program.TopLevelDeclarations = decls;
+ var name2Proc = new Dictionary<string, Procedure>();
+ foreach (var proc in program.Procedures)
+ {
+ name2Proc.Add(proc.Name, proc);
+ if (impl2Summary.ContainsKey(proc.Name))
+ {
+ var ens = new Ensures(false,
+ impl2Summary[proc.Name].GetSummaryExpr(
+ new Func<string, Expr>(s => null), new Func<string, Expr>(s => null)));
+ ens.Attributes = new QKeyValue(Token.NoToken, "inferred", new List<object>(), ens.Attributes);
+ proc.Ensures.Add(ens);
+ }
+ }
+
+ using (var wt = new TokenTextWriter(WitnessFile, /*pretty=*/ false))
+ {
+ program.Emit(wt);
+ }
+
+ // Replace SummaryPreds with their definition
+ foreach (var impl in program.Implementations)
+ {
+ foreach (var blk in impl.Blocks)
+ {
+ foreach (var cmd in blk.Cmds.OfType<AssumeCmd>())
+ {
+ var expr = cmd.Expr as NAryExpr;
+ if (expr == null) continue;
+ var op = expr.Fun as FunctionCall;
+ if (op == null || !op.FunctionName.EndsWith(summaryPredSuffix)) continue;
+ var calleeName = op.FunctionName.Substring(0, op.FunctionName.Length - summaryPredSuffix.Length);
+ if (!impl2Summary.ContainsKey(calleeName)) continue;
+ var callee = name2Impl[calleeName];
+
+ // variable order: globals, ins, outs, modifies
+ var forold = new Dictionary<string, Expr>();
+ var always = new Dictionary<string, Expr>();
+ int i = 0;
+ foreach (var g in program.GlobalVariables)
+ {
+ forold.Add(g.Name, expr.Args[i]);
+ always.Add(g.Name, expr.Args[i]);
+ i++;
+ }
+ foreach (var v in callee.InParams.OfType<Variable>())
+ {
+ always.Add(v.Name, expr.Args[i]);
+ i++;
+ }
+ foreach (var v in callee.OutParams.OfType<Variable>())
+ {
+ always.Add(v.Name, expr.Args[i]);
+ i++;
+ }
+ foreach (var ie in name2Proc[calleeName].Modifies.OfType<IdentifierExpr>())
+ {
+ always[ie.Name] = expr.Args[i];
+ i++;
+ }
+
+ cmd.Expr = impl2Summary[calleeName].GetSummaryExpr(
+ v => { if (always.ContainsKey(v)) return always[v]; else return null; },
+ v => { if (forold.ContainsKey(v)) return forold[v]; else return null; });
+ }
+ }
+ }
+
+ using (var wt = new TokenTextWriter(WitnessFile, /*pretty=*/ false))
+ {
+ program.Emit(wt);
+ }
+ if (CommandLineOptions.Clo.Trace) Console.WriteLine("Witness written to {0}", WitnessFile);
+ }
+
+ private QKeyValue removeAttr(string key, QKeyValue attr)
+ {
+ if (attr == null) return attr;
+ if (attr.Key == key) return removeAttr(key, attr.Next);
+ attr.Next = removeAttr(key, attr.Next);
+ return attr;
+ }
+
+ private void Inline()
+ {
+ if (CommandLineOptions.Clo.InlineDepth < 0)
+ return;
+
+ var callGraph = BuildCallGraph();
+
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
+ inlineEnsuresVisitor.Visit(impl);
+ }
+
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ impl.OriginalBlocks = impl.Blocks;
+ impl.OriginalLocVars = impl.LocVars;
+ }
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ CommandLineOptions.Inlining savedOption = CommandLineOptions.Clo.ProcedureInlining;
+ CommandLineOptions.Clo.ProcedureInlining = CommandLineOptions.Inlining.Spec;
+ Inliner.ProcessImplementationForHoudini(program, impl);
+ CommandLineOptions.Clo.ProcedureInlining = savedOption;
+ }
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ impl.OriginalBlocks = null;
+ impl.OriginalLocVars = null;
+ }
+
+ Graph<Implementation> oldCallGraph = callGraph;
+ callGraph = new Graph<Implementation>();
+ foreach (Implementation impl in oldCallGraph.Nodes)
+ {
+ callGraph.AddSource(impl);
+ }
+ foreach (Tuple<Implementation, Implementation> edge in oldCallGraph.Edges)
+ {
+ callGraph.AddEdge(edge.Item1, edge.Item2);
+ }
+ int count = CommandLineOptions.Clo.InlineDepth;
+ while (count > 0)
+ {
+ foreach (Implementation impl in oldCallGraph.Nodes)
+ {
+ List<Implementation> newNodes = new List<Implementation>();
+ foreach (Implementation succ in callGraph.Successors(impl))
+ {
+ newNodes.AddRange(oldCallGraph.Successors(succ));
+ }
+ foreach (Implementation newNode in newNodes)
+ {
+ callGraph.AddEdge(impl, newNode);
+ }
+ }
+ count--;
+ }
+ }
+
+ private Graph<Implementation> BuildCallGraph()
+ {
+ Graph<Implementation> callGraph = new Graph<Implementation>();
+ Dictionary<Procedure, HashSet<Implementation>> procToImpls = new Dictionary<Procedure, HashSet<Implementation>>();
+ foreach (var proc in program.Procedures)
+ {
+ procToImpls[proc] = new HashSet<Implementation>();
+ }
+ foreach (var impl in program.Implementations)
+ {
+ if (impl.SkipVerification) continue;
+ callGraph.AddSource(impl);
+ procToImpls[impl.Proc].Add(impl);
+ }
+ foreach (var impl in program.Implementations)
+ {
+ if (impl.SkipVerification) continue;
+ foreach (Block b in impl.Blocks)
+ {
+ foreach (Cmd c in b.Cmds)
+ {
+ CallCmd cc = c as CallCmd;
+ if (cc == null) continue;
+ foreach (Implementation callee in procToImpls[cc.Proc])
+ {
+ callGraph.AddEdge(impl, callee);
+ }
+ }
+ }
+ }
+ return callGraph;
+ }
+
+
+ private bool ProcessImpl(Implementation impl)
+ {
+ var ret = false;
+ var gen = prover.VCExprGen;
+
+ // construct summaries
+ var env = VCExpressionGenerator.True;
+ foreach (var tup in impl2CalleeSummaries[impl.Name])
+ {
+ // Not Bilateral: then reject self predicates
+ if (UseBilateralAlgo == false && tup.Item1 == impl.Name)
+ continue;
+
+ // Bilateral: only reject self summary
+ if (UseBilateralAlgo == true && tup.Item1 == impl.Name && tup.Item2)
+ continue;
+
+ var calleeSummary =
+ impl2Summary[tup.Item1].GetSummaryExpr(
+ GetVarMapping(name2Impl[tup.Item1], tup.Item4), prover.VCExprGen);
+ env = gen.AndSimp(env, gen.Eq(tup.Item3, calleeSummary));
+ }
+
+ var prev = impl2Summary[impl.Name].Copy();
+ var upper = impl2Summary[impl.Name].GetTrueSummary(program, impl);
+ var sw = new Stopwatch();
+ sw.Start();
+ var lowerTime = TimeSpan.Zero;
+
+ while(true)
+ {
+ var usedLower = true;
+ var query = impl2Summary[impl.Name];
+ sw.Restart();
+
+ // construct self summaries
+ var summaryExpr = VCExpressionGenerator.True;
+ foreach (var tup in impl2CalleeSummaries[impl.Name])
+ {
+ if (UseBilateralAlgo == false && tup.Item1 != impl.Name)
+ continue;
+ if (UseBilateralAlgo == true && (tup.Item1 != impl.Name || !tup.Item2))
+ continue;
+
+ if (UseBilateralAlgo)
+ {
+ query = query.AbstractConsequence(upper);
+ if (query == null) query = impl2Summary[tup.Item1];
+ else usedLower = false;
+ }
+
+ var ts =
+ query.GetSummaryExpr(
+ GetVarMapping(name2Impl[tup.Item1], tup.Item4), prover.VCExprGen);
+ summaryExpr = gen.AndSimp(summaryExpr, gen.Eq(tup.Item3, ts));
+ }
+ //Console.WriteLine("Trying summary for {0}: {1}", impl.Name, summaryExpr);
+
+ reporter.model = null;
+ var vc = gen.AndSimp(env, summaryExpr);
+ vc = gen.Implies(vc, impl2VC[impl.Name]);
+
+ //Console.WriteLine("Checking: {0}", vc);
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Verifying {0} ({1}): {2}", impl.Name, usedLower ? "lower" : "ac", query);
+
+ if (usedLower && lowerTime.TotalMilliseconds >= iterTimeLimit && iterTimeLimit >= 0)
+ {
+ if (UseBilateralAlgo)
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
+ ret = prev.IsEqual(upper) ? false : true;
+ impl2Summary[impl.Name] = upper;
+ break;
+ }
+ else
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
+ var tt = impl2Summary[impl.Name].GetTrueSummary(program, impl);
+ ret = prev.IsEqual(tt) ? false : true; ;
+ impl2Summary[impl.Name] = tt;
+ break;
+ }
+ }
+
+ var start = DateTime.Now;
+
+ //prover.Push();
+ //prover.Assert(gen.Not(vc), true);
+ //prover.FlushAxiomsToTheoremProver();
+ //prover.Check();
+ //ProverInterface.Outcome proverOutcome = prover.CheckOutcome(reporter);
+ //prover.Pop();
+
+ prover.BeginCheck(impl.Name, vc, reporter);
+ ProverInterface.Outcome proverOutcome = prover.CheckOutcome(reporter);
+
+ var inc = (DateTime.Now - start);
+ proverTime += inc;
+ numProverQueries++;
+
+ sw.Stop();
+ if (usedLower) lowerTime += sw.Elapsed;
+
+ if(CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Time taken = " + inc.TotalSeconds.ToString());
+
+ if (UseBilateralAlgo)
+ {
+ if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
+ {
+ if(CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
+ ret = prev.IsEqual(upper) ? false : true;
+ impl2Summary[impl.Name] = upper;
+ break;
+ }
+
+ if (reporter.model == null && usedLower)
+ break;
+
+ if (reporter.model == null)
+ {
+ upper.Meet(query);
+ }
+ else
+ {
+ var state = CollectState(impl);
+ impl2Summary[impl.Name].Join(state, reporter.model);
+ ret = true;
+ }
+ }
+ else
+ {
+ if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Timeout/Spaceout while verifying " + impl.Name);
+ var tt = impl2Summary[impl.Name].GetTrueSummary(program, impl);
+ ret = prev.IsEqual(tt) ? false : true; ;
+ impl2Summary[impl.Name] = tt;
+ break;
+ }
+
+ if (reporter.model == null)
+ break;
+ //reporter.model.Write(Console.Out);
+
+ var state = CollectState(impl);
+ impl2Summary[impl.Name].Join(state, reporter.model);
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+ private Dictionary<string, VCExpr> GetVarMapping(Implementation impl, VCExprNAry summaryPred)
+ {
+ var ret = new Dictionary<string, VCExpr>();
+
+ var cnt = 0;
+ foreach (var g in program.GlobalVariables)
+ {
+ ret.Add(string.Format("old({0})", g.Name), summaryPred[cnt]);
+ cnt++;
+ }
+ foreach (var v in impl.InParams.OfType<Variable>().Concat(
+ impl.OutParams.OfType<Variable>().Concat(
+ impl.Proc.Modifies.OfType<IdentifierExpr>().Select(ie => ie.Decl))))
+ {
+ ret.Add(v.Name, summaryPred[cnt]);
+ cnt++;
+ }
+
+ // Fill up values of globals that are not modified
+ cnt = 0;
+ foreach (var g in program.GlobalVariables)
+ {
+ if (ret.ContainsKey(g.Name)) { cnt++; continue; }
+
+ ret.Add(string.Format("{0}", g.Name), summaryPred[cnt]);
+ cnt++;
+ }
+
+ // Constants
+ foreach (var c in program.Constants)
+ {
+ var value = prover.Context.BoogieExprTranslator.Translate(Expr.Ident(c));
+ ret.Add(string.Format("{0}", c.Name), value);
+ ret.Add(string.Format("old({0})", c.Name), value);
+ }
+
+ return ret;
+ }
+
+ private Dictionary<string, Model.Element> CollectState(Implementation impl)
+ {
+ var ret = new Dictionary<string, Model.Element>();
+
+ var model = reporter.model;
+ var implVars = impl2EndStateVars[impl.Name];
+
+ var cnt = 0;
+ foreach (var g in program.GlobalVariables)
+ {
+ ret.Add(string.Format("old({0})", g.Name), getValue(implVars[cnt], model));
+ cnt++;
+ }
+ foreach (var v in impl.InParams.OfType<Variable>().Concat(
+ impl.OutParams.OfType<Variable>().Concat(
+ impl.Proc.Modifies.OfType<IdentifierExpr>().Select(ie => ie.Decl))))
+ {
+ ret.Add(v.Name, getValue(implVars[cnt], model));
+ cnt++;
+ }
+
+ // Fill up values of globals that are not modified
+ cnt = 0;
+ foreach (var g in program.GlobalVariables)
+ {
+ if (ret.ContainsKey(g.Name)) { cnt++; continue; }
+
+ ret.Add(string.Format("{0}", g.Name), getValue(implVars[cnt], model));
+ cnt++;
+ }
+
+ // Constants
+ foreach (var c in program.Constants)
+ {
+ try
+ {
+ var value = getValue(prover.Context.BoogieExprTranslator.Translate(Expr.Ident(c)), model);
+ ret.Add(string.Format("{0}", c.Name), value);
+ ret.Add(string.Format("old({0})", c.Name), value);
+ }
+ catch (Exception)
+ {
+ // constant not assigned a value: add a default value
+ Model.Element value = null;
+ if (c.TypedIdent.Type.IsInt)
+ value = model.MkIntElement(0);
+ else if (c.TypedIdent.Type.IsBool)
+ value = model.MkElement("false");
+
+ ret.Add(string.Format("{0}", c.Name), value);
+ ret.Add(string.Format("old({0})", c.Name), value);
+ }
+ }
+
+ return ret;
+ }
+
+ private Model.Element getValue(VCExpr arg, Model model)
+ {
+ if (arg is VCExprLiteral)
+ {
+ //return model.GetElement(arg.ToString());
+ return model.MkElement(arg.ToString());
+ }
+ else if (arg is VCExprVar)
+ {
+ var el = model.TryGetFunc(prover.Context.Lookup(arg as VCExprVar));
+ if (el != null)
+ {
+ Debug.Assert(el.Arity == 0 && el.AppCount == 1);
+ return el.Apps.First().Result;
+ }
+ else
+ {
+ // Variable not defined; assign arbitrary value
+ if (arg.Type.IsBool)
+ return model.MkElement("false");
+ else if (arg.Type.IsInt)
+ return model.MkIntElement(0);
+ else
+ return null;
+ }
+ }
+ else
+ {
+ Debug.Assert(false);
+ return null;
+ }
+ }
+
+ private void attachEnsures(Implementation impl)
+ {
+ List<Variable> functionInterfaceVars = new List<Variable>();
+ foreach (Variable v in vcgen.program.GlobalVariables)
+ {
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
+ }
+ foreach (Variable v in impl.InParams)
+ {
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
+ }
+ foreach (Variable v in impl.OutParams)
+ {
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
+ }
+ foreach (IdentifierExpr e in impl.Proc.Modifies)
+ {
+ if (e.Decl == null) continue;
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", e.Decl.TypedIdent.Type), true));
+ }
+ Formal returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false);
+ var function = new Function(Token.NoToken, impl.Name + summaryPredSuffix, functionInterfaceVars, returnVar);
+ prover.Context.DeclareFunction(function, "");
+
+ List<Expr> exprs = new List<Expr>();
+ foreach (Variable v in vcgen.program.GlobalVariables)
+ {
+ Contract.Assert(v != null);
+ exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
+ }
+ foreach (Variable v in impl.Proc.InParams)
+ {
+ Contract.Assert(v != null);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ foreach (Variable v in impl.Proc.OutParams)
+ {
+ Contract.Assert(v != null);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ foreach (IdentifierExpr ie in impl.Proc.Modifies)
+ {
+ Contract.Assert(ie != null);
+ if (ie.Decl == null)
+ continue;
+ exprs.Add(ie);
+ }
+ Expr postExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
+ impl.Proc.Ensures.Add(
+ new Ensures(Token.NoToken, false, postExpr, "",
+ new QKeyValue(Token.NoToken, "ah", new List<object>(), null)));
+ }
+
+ private void GenVC(Implementation impl)
+ {
+ ModelViewInfo mvInfo;
+ Dictionary<int, Absy> label2absy;
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Generating VC of {0}", impl.Name);
+ }
+
+ vcgen.ConvertCFG2DAG(impl);
+ vcgen.PassifyImpl(impl, out mvInfo);
+
+ var gen = prover.VCExprGen;
+ var vcexpr = vcgen.GenerateVC(impl, null, out label2absy, prover.Context);
+
+
+ // Find the assert
+ impl2EndStateVars.Add(impl.Name, new List<VCExpr>());
+ var found = false;
+ var assertId = -1;
+ foreach (var blk in impl.Blocks)
+ {
+ foreach (var cmd in blk.Cmds.OfType<AssertCmd>())
+ {
+ if (SimpleUtil.isAssertTrue(cmd)) continue;
+ var nary = cmd.Expr as NAryExpr;
+ if (nary == null) continue;
+ var pred = nary.Fun as FunctionCall;
+ if (pred == null || pred.FunctionName != (impl.Name + (AbstractHoudini.summaryPredSuffix)))
+ continue;
+
+ Debug.Assert(!found);
+ found = true;
+ assertId = cmd.UniqueId;
+ //Console.WriteLine("assert cmd id: {0}", cmd.UniqueId);
+ nary.Args.OfType<Expr>()
+ .Iter(expr => impl2EndStateVars[impl.Name].Add(prover.Context.BoogieExprTranslator.Translate(expr)));
+ }
+ }
+
+ // It is possible that no assert is found in the procedure. It happens when the
+ // procedure doesn't return.
+ //Debug.Assert(found);
+
+ // Grab summary predicates
+ var visitor = new FindSummaryPred(prover.VCExprGen, assertId);
+ vcexpr = visitor.Mutate(vcexpr, true);
+
+ // Create a macro so that the VC can sit with the theorem prover
+ Macro macro = new Macro(Token.NoToken, impl.Name + "Macro", new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false));
+ prover.DefineMacro(macro, vcexpr);
+
+ // Store VC
+ impl2VC.Add(impl.Name, gen.Function(macro));
+
+ //Console.WriteLine("VC of {0}: {1}", impl.Name, vcexpr);
+
+ // check sanity: only one predicate for self-summary
+ // (There may be none when the procedure doesn't return)
+ Debug.Assert(visitor.summaryPreds.Count(tup => tup.Item2) <= 1);
+
+ impl2CalleeSummaries.Add(impl.Name, new List<Tuple<string, bool, VCExprVar, VCExprNAry>>());
+ visitor.summaryPreds.Iter(tup => impl2CalleeSummaries[impl.Name].Add(tup));
+ }
+ }
+
+ public interface ISummaryElement
+ {
+ ISummaryElement Copy();
+ ISummaryElement GetFlaseSummary(Program program, Implementation impl);
+ void Join(Dictionary<string, Model.Element> state, Model model);
+ VCExpr GetSummaryExpr(Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen);
+ Expr GetSummaryExpr(Func<string, Expr> always, Func<string, Expr> forold);
+
+ // For Bilateral
+ ISummaryElement GetTrueSummary(Program program, Implementation impl);
+ void Meet(ISummaryElement other);
+ bool IsEqual(ISummaryElement other);
+ ISummaryElement AbstractConsequence(ISummaryElement upper);
+ }
+
+ public class ConstantVal : ISummaryElement
+ {
+ Program program;
+ Implementation impl;
+ // var -> const set
+ Dictionary<string, HashSet<int>> val;
+ // set of vars
+ HashSet<Variable> vars;
+
+ public static readonly int MAX = 3;
+
+ public ConstantVal()
+ {
+ // this is just a place holder
+ val = new Dictionary<string, HashSet<int>>();
+ vars = new HashSet<Variable>();
+ }
+
+ private ConstantVal(Program program, Implementation impl)
+ {
+ this.program = program;
+ this.impl = impl;
+ this.val = new Dictionary<string, HashSet<int>>();
+
+ vars = new HashSet<Variable>();
+ impl.Proc.Modifies
+ .OfType<IdentifierExpr>()
+ .Select(ie => ie.Decl)
+ .Where(v => v.TypedIdent.Type.IsInt)
+ .Iter(v => vars.Add(v));
+ impl.OutParams.OfType<Variable>()
+ .Where(v => v.TypedIdent.Type.IsInt)
+ .Iter(v => vars.Add(v));
+
+ vars.Iter(v => val.Add(v.Name, null));
+ }
+
+
+ public void Join(Dictionary<string, Model.Element> state, Model model)
+ {
+ foreach (var vv in vars)
+ {
+ var v = vv.Name;
+ var newv = state[v].AsInt();
+ var oldv = val[v];
+
+ if (oldv == null)
+ {
+ val[v] = new HashSet<int>();
+ val[v].Add(newv);
+ }
+ else if(oldv.Count > 0)
+ {
+ val[v].Add(newv);
+ if (val[v].Count > MAX)
+ val[v] = new HashSet<int>();
+ }
+
+ }
+ }
+
+ public VCExpr GetSummaryExpr(Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen)
+ {
+ VCExpr ret = VCExpressionGenerator.True;
+ if (val.Values.Any(v => v == null))
+ return VCExpressionGenerator.False;
+
+ foreach (var v in vars)
+ {
+ var consts = val[v.Name];
+ Debug.Assert(consts != null);
+
+ if (consts.Count == 0)
+ continue;
+
+ var vexpr = VCExpressionGenerator.False;
+ consts.Iter(c => vexpr = gen.OrSimp(vexpr, gen.Eq(incarnations[v.Name], gen.Integer(Microsoft.Basetypes.BigNum.FromInt(c)))));
+ ret = gen.AndSimp(ret, vexpr);
+ }
+
+ return ret;
+ }
+
+ public override string ToString()
+ {
+ var ret = "true";
+ if (val.Values.Any(v => v == null))
+ return "false";
+
+ foreach (var v in vars)
+ {
+ var consts = val[v.Name];
+ Debug.Assert(consts != null);
+
+ if (consts.Count == 0)
+ continue;
+
+ var vexpr = "false";
+ consts.Iter(c => vexpr =
+ string.Format("{0} OR ({1} == {2})", vexpr, v.Name, c));
+
+ ret = string.Format("{0} AND ({1})", ret, vexpr);
+ }
+
+ return ret;
+ }
+
+
+ public ISummaryElement GetFlaseSummary(Program program, Implementation impl)
+ {
+ return new ConstantVal(program, impl);
+ }
+
+ #region ISummaryElement (Bilateral) Members
+
+
+ public ISummaryElement GetTrueSummary(Program program, Implementation impl)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Meet(ISummaryElement other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsEqual(ISummaryElement other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ISummaryElement AbstractConsequence(ISummaryElement upper)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ #region ISummaryElement Members
+
+
+ public Expr GetSummaryExpr(Func<string, Expr> always, Func<string, Expr> forold)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ #region ISummaryElement Members
+
+ public ISummaryElement Copy()
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
+ public class NamedExpr
+ {
+ public string name;
+ public Expr expr;
+
+ public NamedExpr(string name, Expr expr)
+ {
+ this.name = name;
+ this.expr = expr;
+ }
+
+ public NamedExpr(Expr expr)
+ {
+ this.name = null;
+ this.expr = expr;
+ }
+
+ public override string ToString()
+ {
+ if (name != null)
+ return name;
+
+ return expr.ToString();
+ }
+ }
+
+ public class PredicateAbs : ISummaryElement
+ {
+ public static Dictionary<string, List<NamedExpr>> PrePreds { get; private set; }
+ public static Dictionary<string, HashSet<int>> PosPrePreds { get; private set; }
+ public static Dictionary<string, List<NamedExpr>> PostPreds { get; private set; }
+ public static Dictionary<Tuple<string, int>, List<PredicateAbsDisjunct>> UpperCandidates;
+ private static HashSet<string> boolConstants;
+ // {proc, pred-pair} -> polariry
+ public static HashSet<Tuple<string, int, int, bool, bool>> unsatPrePredPairs;
+ public static HashSet<Tuple<string, int, int, bool, bool>> unsatPostPredPairs;
+
+ // Temporary: used during eval
+ private static Model model = null;
+
+ string procName;
+ PredicateAbsDisjunct[] value;
+ bool isFalse;
+
+ public PredicateAbs(string procName)
+ {
+ this.procName = procName;
+ isFalse = true;
+ value = new PredicateAbsDisjunct[PostPreds[this.procName].Count];
+ for (int i = 0; i < PostPreds[this.procName].Count; i++) value[i] = null;
+ }
+
+ public static void Initialize(Program program)
+ {
+ PrePreds = new Dictionary<string, List<NamedExpr>>();
+ PostPreds = new Dictionary<string, List<NamedExpr>>();
+ PosPrePreds = new Dictionary<string, HashSet<int>>();
+
+ boolConstants = new HashSet<string>();
+ UpperCandidates = new Dictionary<Tuple<string, int>, List<PredicateAbsDisjunct>>();
+
+ program.Constants
+ .Where(c => c.TypedIdent.Type.IsBool)
+ .Iter(c => boolConstants.Add(c.Name));
+
+ // Add template pre-post to all procedures
+ var preT = new List<NamedExpr>();
+ var postT = new List<NamedExpr>();
+ var posPreT = new HashSet<int>();
+ var tempP = new HashSet<Procedure>();
+ foreach (var proc in
+ program.Procedures
+ .Where(proc => QKeyValue.FindBoolAttribute(proc.Attributes, "template")))
+ {
+ tempP.Add(proc);
+ foreach (var ens in proc.Ensures.OfType<Ensures>())
+ {
+ var pos = QKeyValue.FindBoolAttribute(ens.Attributes, "positive");
+
+ if (QKeyValue.FindBoolAttribute(ens.Attributes, "pre"))
+ {
+ preT.Add(new NamedExpr(null, ens.Condition));
+ if (pos) posPreT.Add(preT.Count - 1);
+ }
+
+ if (QKeyValue.FindBoolAttribute(ens.Attributes, "post"))
+ postT.Add(new NamedExpr(null, ens.Condition));
+
+ var s = QKeyValue.FindStringAttribute(ens.Attributes, "pre");
+ if (s != null)
+ {
+ preT.Add(new NamedExpr(s, ens.Condition));
+ if (pos) posPreT.Add(preT.Count - 1);
+ }
+
+ s = QKeyValue.FindStringAttribute(ens.Attributes, "post");
+ if (s != null)
+ postT.Add(new NamedExpr(s, ens.Condition));
+ }
+ }
+
+ program.RemoveTopLevelDeclarations(decl => tempP.Contains(decl));
+ var upperPreds = new Dictionary<string, List<Expr>>();
+
+ foreach (var impl in program.Implementations)
+ {
+ PrePreds.Add(impl.Name, new List<NamedExpr>());
+ PostPreds.Add(impl.Name, new List<NamedExpr>());
+ PosPrePreds.Add(impl.Name, new HashSet<int>());
+
+ // Add "false" as the first post predicate
+ //PostPreds[impl.Name].Add(new NamedExpr(Expr.False));
+
+ preT.Iter(e => PrePreds[impl.Name].Add(e));
+ postT.Iter(e => PostPreds[impl.Name].Add(e));
+ PosPrePreds[impl.Name].UnionWith(posPreT);
+
+ // Pick up per-procedure pre-post
+ var nens = new List<Ensures>();
+ foreach (var ens in impl.Proc.Ensures.OfType<Ensures>())
+ {
+ string s = null;
+ var pos = QKeyValue.FindBoolAttribute(ens.Attributes, "positive");
+
+ if (QKeyValue.FindBoolAttribute(ens.Attributes, "pre"))
+ {
+ PrePreds[impl.Name].Add(new NamedExpr(ens.Condition));
+ PosPrePreds[impl.Name].Add(PrePreds[impl.Name].Count - 1);
+ }
+ else if (QKeyValue.FindBoolAttribute(ens.Attributes, "post"))
+ {
+ PostPreds[impl.Name].Add(new NamedExpr(ens.Condition));
+ }
+ else if ((s = QKeyValue.FindStringAttribute(ens.Attributes, "pre")) != null)
+ {
+ PrePreds[impl.Name].Add(new NamedExpr(s, ens.Condition));
+ PosPrePreds[impl.Name].Add(PrePreds[impl.Name].Count - 1);
+ }
+ else if ((s = QKeyValue.FindStringAttribute(ens.Attributes, "post")) != null)
+ {
+ PostPreds[impl.Name].Add(new NamedExpr(s, ens.Condition));
+ }
+ else if (QKeyValue.FindBoolAttribute(ens.Attributes, "upper"))
+ {
+ var key = impl.Name;
+ if (!upperPreds.ContainsKey(key))
+ upperPreds.Add(key, new List<Expr>());
+ upperPreds[key].Add(ens.Condition);
+ }
+ else
+ {
+ nens.Add(ens);
+ }
+ }
+ impl.Proc.Ensures = nens;
+ }
+
+ foreach (var tup in upperPreds)
+ {
+ var procName = tup.Key;
+ var candidates = tup.Value;
+ if (!candidates.Any()) continue;
+
+ var strToPost = new Dictionary<string, int>();
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ strToPost.Add(PostPreds[procName][i].expr.ToString(), i);
+ }
+
+ foreach (var expr in candidates)
+ {
+ if (strToPost.ContainsKey(expr.ToString()))
+ {
+ var key = Tuple.Create(procName, strToPost[expr.ToString()]);
+ if (!UpperCandidates.ContainsKey(key))
+ UpperCandidates.Add(key, new List<PredicateAbsDisjunct>());
+ UpperCandidates[key].Add(new PredicateAbsDisjunct(true, procName));
+ }
+ else
+ {
+ // Try parsing the expression as (pre-conjunct ==> post-pred)
+ var parsed = ParseExpr(expr, procName);
+ if (parsed != null && strToPost.ContainsKey(parsed.Item2.ToString()))
+ {
+ var key = Tuple.Create(procName, strToPost[parsed.Item2.ToString()]);
+ if (!UpperCandidates.ContainsKey(key))
+ UpperCandidates.Add(key, new List<PredicateAbsDisjunct>());
+ UpperCandidates[key].Add(parsed.Item1);
+ }
+ }
+ }
+
+ }
+ //Console.WriteLine("Running Abstract Houdini");
+ //PostPreds.Iter(expr => Console.WriteLine("\tPost: {0}", expr));
+ //PrePreds.Iter(expr => Console.WriteLine("\tPre: {0}", expr));
+ }
+
+ // Try parsing the expression as (pre-conjunct ==> post-pred)
+ private static Tuple<PredicateAbsDisjunct, Expr> ParseExpr(Expr expr, string procName)
+ {
+ Expr postExpr = null;
+ Expr preExpr = null;
+
+ // Decompose outer Implies
+ var nexpr = expr as NAryExpr;
+ if (nexpr != null && (nexpr.Fun is BinaryOperator)
+ && (nexpr.Fun as BinaryOperator).Op == BinaryOperator.Opcode.Imp
+ && (nexpr.Args.Count == 2))
+ {
+ postExpr = nexpr.Args[1];
+ preExpr = nexpr.Args[0];
+ }
+ else
+ {
+ if(CommandLineOptions.Clo.Trace) Console.WriteLine("Failed to parse {0} (ignoring)", expr);
+ return null;
+ }
+
+
+ var atoms = DecomposeOuterAnd(preExpr);
+ var pos = new HashSet<int>();
+ var neg = new HashSet<int>();
+
+ foreach (var atom in atoms)
+ {
+ var index = PrePreds[procName].FindIndex(ne => ne.expr.ToString() == atom.ToString());
+ if (index == -1)
+ {
+ index = PrePreds[procName].FindIndex(ne => Expr.Not(ne.expr).ToString() == atom.ToString());
+ if (index == -1)
+ {
+ if(CommandLineOptions.Clo.Trace) Console.WriteLine("Failed to parse {0} (ignoring)", atom);
+ return null;
+ }
+ else
+ {
+ neg.Add(index);
+ }
+ }
+ else
+ {
+ pos.Add(index);
+ }
+ }
+
+ var conj = new PredicateAbsConjunct(pos, neg, procName);
+ var conjls = new List<PredicateAbsConjunct>();
+ conjls.Add(conj);
+
+ return Tuple.Create(new PredicateAbsDisjunct(conjls, procName), postExpr);
+ }
+
+ // blah && blah ==> {blah, blah}
+ static IEnumerable<Expr> DecomposeOuterAnd(Expr expr)
+ {
+ var ret = new List<Expr>();
+
+ var nexpr = expr as NAryExpr;
+ if (nexpr == null
+ || !(nexpr.Fun is BinaryOperator)
+ || (nexpr.Fun as BinaryOperator).Op != BinaryOperator.Opcode.And)
+ {
+ ret.Add(expr);
+ }
+ else
+ {
+ foreach (Expr a in nexpr.Args)
+ ret.AddRange(DecomposeOuterAnd(a));
+ }
+
+ return ret;
+ }
+
+
+ private Model.Element Eval(Expr expr, Dictionary<string, Model.Element> state)
+ {
+ if (expr is LiteralExpr)
+ {
+ return ToElem((expr as LiteralExpr).Val);
+ }
+
+ if (expr is IdentifierExpr)
+ {
+ return LookupVariable((expr as IdentifierExpr).Name, state, false);
+ }
+
+ if (expr is OldExpr)
+ {
+ var ide = (expr as OldExpr).Expr as IdentifierExpr;
+ Debug.Assert(ide != null);
+
+ return LookupVariable(ide.Name, state, true);
+ }
+
+ if (expr is NAryExpr)
+ {
+ var nary = expr as NAryExpr;
+ if (nary.Fun is UnaryOperator)
+ {
+ return ToElem((nary.Fun as UnaryOperator).Evaluate(ToValue(Eval(nary.Args[0], state))));
+ }
+ if (nary.Fun is BinaryOperator)
+ {
+ return ToElem((nary.Fun as BinaryOperator).Evaluate(ToValue(Eval(nary.Args[0], state)), ToValue(Eval(nary.Args[1], state))));
+ }
+ if (nary.Fun is MapSelect && nary.Args.Count == 2)
+ {
+ var index = Eval(nary.Args[1], state);
+ var map = Eval(nary.Args[0], state) as Model.Array;
+ Debug.Assert(map != null, "Variable of map type must have an Array-typed value");
+ var ret = map.Value.TryEval(index as Model.Element);
+ if (ret == null) ret = map.Value.Else;
+ Debug.Assert(ret != null);
+ return ret;
+ }
+ Debug.Assert(false, "No other op is handled");
+ }
+ throw new NotImplementedException(string.Format("Expr of type {0} is not handled", expr.GetType().ToString()));
+ }
+
+ private Model.Element LookupVariable(string v, Dictionary<string, Model.Element> state, bool tryOld)
+ {
+ if (tryOld)
+ {
+ var oldv = string.Format("old({0})", v);
+ if (state.ContainsKey(oldv))
+ {
+ return state[oldv];
+ }
+ throw new AbsHoudiniInternalError("Cannot handle this case");
+ }
+
+ if (state.ContainsKey(v))
+ {
+ return state[v];
+ }
+
+ /*
+ if (boolConstants.Contains(v))
+ {
+ // value of this constant is immaterial, return true
+ return model.MkElement("true");
+ }
+ */
+
+ throw new AbsHoudiniInternalError("Cannot handle this case");
+ }
+
+ private static VCExpr ToVcVar(string v, Dictionary<string, VCExpr> incarnations, bool tryOld)
+ {
+ if (tryOld)
+ {
+ var oldv = string.Format("old({0})", v);
+ if (incarnations.ContainsKey(oldv))
+ {
+ return incarnations[oldv];
+ }
+ throw new AbsHoudiniInternalError("Cannot handle this case");
+ }
+
+ if (incarnations.ContainsKey(v))
+ {
+ return incarnations[v];
+ }
+
+ throw new AbsHoudiniInternalError("Cannot handle this case");
+ }
+
+ public static void FindUnsatPairs(VCExpressionGenerator gen, ProverInterface prover)
+ {
+ unsatPrePredPairs = new HashSet<Tuple<string, int, int, bool, bool>>();
+ unsatPostPredPairs = new HashSet<Tuple<string, int, int, bool, bool>>();
+
+ var cachePos = new HashSet<Tuple<string, string>>();
+ var cacheNeg = new HashSet<Tuple<string, string>>();
+ var record = new Action<object, string, int, int, bool, bool>(
+ (map, proc, e1, e2, p1, p2) => {
+ var key = Tuple.Create(proc, e1, e2, p1, p2);
+ if (map == PrePreds)
+ unsatPrePredPairs.Add(key);
+ else
+ unsatPostPredPairs.Add(key);
+ }
+ );
+
+ var predMaps = new List<Dictionary<string, List<NamedExpr>>>();
+ predMaps.Add(PrePreds); predMaps.Add(PostPreds);
+
+ foreach (var map in predMaps)
+ {
+ foreach (var proc in map.Keys)
+ {
+ for (int i = 0; i < 2 * map[proc].Count(); i++)
+ {
+ var p1 = (i % 2); // polarity
+ var e1 = map[proc][i / 2].expr;
+ if (p1 == 0) e1 = Expr.Not(e1);
+
+ for (int j = 2 * ((i / 2) + 1); j < 2 * map[proc].Count(); j++)
+ {
+ var p2 = (j % 2); // polarity
+ var e2 = map[proc][j / 2].expr;
+ if (p2 == 0) e2 = Expr.Not(e2);
+
+ var key = Tuple.Create(e1.ToString(), e2.ToString());
+ if (cachePos.Contains(key))
+ {
+ record(map, proc, i / 2, j / 2, p1 == 1, p2 == 1);
+ continue;
+ }
+ else if (cacheNeg.Contains(key))
+ {
+ continue;
+ }
+
+ if (!CheckIfUnsat(e1, e2, gen, prover))
+ {
+ cacheNeg.Add(key);
+ continue;
+ }
+ cachePos.Add(key);
+ record(map, proc, i / 2, j / 2, p1 == 1, p2 == 1);
+
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Proved UNSAT: {0} {1}", e1, e2);
+ }
+ }
+ }
+ }
+ }
+
+ // Is a ^ b UNSAT?
+ private static bool CheckIfUnsat(Expr a, Expr b, VCExpressionGenerator gen, ProverInterface prover)
+ {
+ var gatherLitA = new GatherLiterals();
+ var gatherLitB = new GatherLiterals();
+
+ gatherLitA.Visit(a);
+ gatherLitB.Visit(b);
+
+ var seta = new HashSet<Variable>();
+ var setb = new HashSet<Variable>();
+ gatherLitA.literals.Iter(tup => seta.Add(tup.Item1));
+ gatherLitB.literals.Iter(tup => setb.Add(tup.Item1));
+ seta.IntersectWith(setb);
+ if (!seta.Any()) return false;
+
+ // Create fresh variables
+ return CheckIfUnsat(Expr.And(a, b), gen, prover);
+ }
+
+ // Is a UNSAT?
+ private static bool CheckIfUnsat(Expr a, VCExpressionGenerator gen, ProverInterface prover)
+ {
+ var gatherLitA = new GatherLiterals();
+ gatherLitA.Visit(a);
+
+ // Create fresh variables
+ var counter = 0;
+ var incarnations = new Dictionary<string, VCExpr>();
+ foreach (var literal in gatherLitA.literals)
+ {
+ if (incarnations.ContainsKey(literal.Item2.ToString()))
+ continue;
+
+ //if(!literal.Item1.TypedIdent.Type.IsInt && !literal.Item1.TypedIdent.Type.IsBool)
+ var v = gen.Variable("UNSATCheck" + counter, literal.Item1.TypedIdent.Type);
+ incarnations.Add(literal.Item2.ToString(), v);
+ counter++;
+ }
+
+ var vc1 = ToVcExpr(a, incarnations, gen);
+ var vc = gen.LabelPos("Temp", vc1);
+
+ // check
+ prover.AssertAxioms();
+ prover.Push();
+ prover.Assert(vc, true);
+ prover.Check();
+ var outcome = prover.CheckOutcomeCore(new AbstractHoudiniErrorReporter());
+ prover.Pop();
+
+ if (outcome == ProverInterface.Outcome.Valid)
+ return true;
+ return false;
+ }
+
+
+ class GatherLiterals : ReadOnlyVisitor
+ {
+ public List<Tuple<Variable, Expr>> literals;
+ bool inOld;
+
+ public GatherLiterals()
+ {
+ literals = new List<Tuple<Variable, Expr>>();
+ inOld = false;
+ }
+
+ public override Expr VisitOldExpr(OldExpr node)
+ {
+ var prev = inOld;
+ inOld = true;
+ var ret = base.VisitOldExpr(node);
+ inOld = prev;
+ return ret;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node)
+ {
+ if (inOld)
+ literals.Add(Tuple.Create(node.Decl, new OldExpr(Token.NoToken, node) as Expr));
+ else
+ literals.Add(Tuple.Create(node.Decl, node as Expr));
+
+ return node;
+ }
+ }
+
+ private object ToValue(Model.Element elem)
+ {
+ if (elem is Model.Integer)
+ {
+ return Microsoft.Basetypes.BigNum.FromInt((elem as Model.Integer).AsInt());
+ }
+ if (elem is Model.Boolean)
+ {
+ return (elem as Model.Boolean).Value;
+ }
+ if (elem is Model.DatatypeValue && (elem as Model.DatatypeValue).Arguments.Length == 1 &&
+ (elem as Model.DatatypeValue).ConstructorName == "-" &&
+ (elem as Model.DatatypeValue).Arguments[0] is Model.Integer)
+ {
+ // negative number as "-" @ int
+ return Microsoft.Basetypes.BigNum.FromInt(-1 * ((elem as Model.DatatypeValue).Arguments[0] as Model.Integer).AsInt());
+ }
+ throw new NotImplementedException("Cannot yet handle this Model.Element type");
+ }
+
+ private Model.Element ToElem(object val)
+ {
+ if (val is bool || val is int || val is Basetypes.BigNum)
+ return model.MkElement(val.ToString());
+ throw new NotImplementedException("Cannot yet handle this value type");
+ }
+
+ // replace v by old(v)
+ private static Expr MakeOld(Expr expr)
+ {
+ var substalways = new Substitution(v => new OldExpr(Token.NoToken, Expr.Ident(v)));
+ var substold = new Substitution(v => Expr.Ident(v));
+
+ return Substituter.ApplyReplacingOldExprs(substalways, substold, expr);
+ }
+
+ private static Expr ToExpr(Expr expr, Func<string, Expr> always, Func<string, Expr> forold)
+ {
+ var substalways = new Substitution(v =>
+ {
+ var ret = always(v.Name);
+ if (ret != null) return ret;
+ else return Expr.Ident(v);
+ });
+ var substold = new Substitution(v =>
+ {
+ var ret = forold(v.Name);
+ if (ret != null) return ret;
+ else return new OldExpr(Token.NoToken, Expr.Ident(v));
+ });
+
+ return Substituter.ApplyReplacingOldExprs(substalways, substold, expr);
+ }
+
+ private static VCExpr ToVcExpr(Expr expr, Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen)
+ {
+ if (expr is LiteralExpr)
+ {
+ var val = (expr as LiteralExpr).Val;
+ if (val is bool)
+ {
+ if ((bool)val)
+ {
+ return VCExpressionGenerator.True;
+ }
+ else
+ {
+ return VCExpressionGenerator.False;
+ }
+ }
+ else if (val is Microsoft.Basetypes.BigNum)
+ {
+ return gen.Integer((Microsoft.Basetypes.BigNum)val);
+ }
+
+ throw new NotImplementedException("Cannot handle literals of this type");
+ }
+
+ if (expr is IdentifierExpr)
+ {
+ return ToVcVar((expr as IdentifierExpr).Name, incarnations, false);
+ }
+
+ if (expr is OldExpr)
+ {
+ var ide = (expr as OldExpr).Expr as IdentifierExpr;
+ Debug.Assert(ide != null);
+
+ return ToVcVar(ide.Name, incarnations, true);
+ }
+
+ if (expr is NAryExpr)
+ {
+ var nary = expr as NAryExpr;
+ if (nary.Fun is UnaryOperator)
+ {
+ if ((nary.Fun as UnaryOperator).Op == UnaryOperator.Opcode.Not)
+ return gen.Not(ToVcExpr(nary.Args[0], incarnations, gen));
+ else if ((nary.Fun as UnaryOperator).Op == UnaryOperator.Opcode.Neg)
+ return gen.Function(VCExpressionGenerator.SubIOp, gen.Integer(Basetypes.BigNum.FromInt(0)), ToVcExpr(nary.Args[0], incarnations, gen));
+ else
+ Debug.Assert(false, "No other unary op is handled");
+ }
+ if (nary.Fun is BinaryOperator)
+ {
+ return gen.Function(Translate(nary.Fun as BinaryOperator), ToVcExpr(nary.Args[0], incarnations, gen), ToVcExpr(nary.Args[1], incarnations, gen));
+ }
+ if (nary.Fun is MapSelect && nary.Args.Count == 2)
+ {
+ return gen.Select(ToVcExpr(nary.Args[0], incarnations, gen), ToVcExpr(nary.Args[1], incarnations, gen));
+ }
+ Debug.Assert(false, "No other op is handled");
+ }
+ throw new NotImplementedException(string.Format("Expr of type {0} is not handled", expr.GetType().ToString()));
+ }
+
+ private static VCExprOp Translate(BinaryOperator op)
+ {
+ switch (op.Op)
+ {
+ case BinaryOperator.Opcode.Add:
+ return VCExpressionGenerator.AddIOp;
+ case BinaryOperator.Opcode.Sub:
+ return VCExpressionGenerator.SubIOp;
+ case BinaryOperator.Opcode.Mul:
+ return VCExpressionGenerator.MulIOp;
+ case BinaryOperator.Opcode.Div:
+ return VCExpressionGenerator.DivIOp;
+ case BinaryOperator.Opcode.Mod:
+ return VCExpressionGenerator.ModOp;
+ case BinaryOperator.Opcode.Eq:
+ case BinaryOperator.Opcode.Iff:
+ // we don't distinguish between equality and equivalence at this point
+ return VCExpressionGenerator.EqOp;
+ case BinaryOperator.Opcode.Neq:
+ return VCExpressionGenerator.NeqOp;
+ case BinaryOperator.Opcode.Lt:
+ return VCExpressionGenerator.LtOp;
+ case BinaryOperator.Opcode.Le:
+ return VCExpressionGenerator.LeOp;
+ case BinaryOperator.Opcode.Ge:
+ return VCExpressionGenerator.GeOp;
+ case BinaryOperator.Opcode.Gt:
+ return VCExpressionGenerator.GtOp;
+ case BinaryOperator.Opcode.Imp:
+ return VCExpressionGenerator.ImpliesOp;
+ case BinaryOperator.Opcode.And:
+ return VCExpressionGenerator.AndOp;
+ case BinaryOperator.Opcode.Or:
+ return VCExpressionGenerator.OrOp;
+ case BinaryOperator.Opcode.Subtype:
+ return VCExpressionGenerator.SubtypeOp;
+ default:
+ Contract.Assert(false);
+ throw new NotImplementedException();
+ }
+
+ }
+
+ // If "false" is a post-predicate, then remove its "pre" constraint from all others, whenever possible
+ public void Simplify()
+ {
+ // find "false"
+ var findex = PostPreds[procName].FindIndex(ne => (ne.expr is LiteralExpr) && (ne.expr as LiteralExpr).IsFalse);
+ if (findex < 0) return;
+ if (value[findex].isTrue)
+ {
+ // procedure doesn't return
+ for (int i = 0; i < value.Length; i++)
+ if (i != findex) value[i] = new PredicateAbsDisjunct(false, procName);
+ return;
+ }
+ if (value[findex].isFalse)
+ return;
+
+ for (int i = 0; i < value.Length; i++)
+ if (i != findex) value[i].Subtract(value[findex]);
+ }
+
+ public HashSet<string> GetPredicates(Program program, VCExpressionGenerator gen, ProverInterface prover)
+ {
+ var ret = new HashSet<string>();
+ if (isFalse) return ret;
+ Simplify();
+
+ // Find the free expressions
+ var proc = program.Procedures.FirstOrDefault(p => p.Name == procName);
+ Contract.Assert(proc != null);
+ Expr freeSummary = Expr.True;
+ foreach (var req in proc.Requires.OfType<Requires>().Where(req => req.Free))
+ {
+ freeSummary = Expr.And(freeSummary, MakeOld(req.Condition));
+ }
+ foreach (var ens in proc.Ensures.OfType<Ensures>().Where(ens => ens.Free))
+ {
+ freeSummary = Expr.And(freeSummary, ens.Condition);
+ }
+
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ if (value[i].isFalse) continue;
+ if (PostPreds[procName][i].expr is LiteralExpr && (PostPreds[procName][i].expr as LiteralExpr).IsFalse)
+ continue;
+
+ if (value[i].isTrue)
+ ret.Add(PostPreds[procName][i].expr.ToString());
+ else
+ {
+ foreach (var c in value[i].GetConjuncts())
+ {
+ var s = Expr.Imp(c.ToExpr(j => PrePreds[procName][j].expr), PostPreds[procName][i].expr);
+ if (CheckIfUnsat(Expr.And(freeSummary, Expr.Not(s)), gen, prover))
+ continue;
+ ret.Add(s.ToString());
+ }
+ }
+ }
+ return ret;
+ }
+
+ public override string ToString()
+ {
+ var ret = "";
+ if (isFalse) return "false";
+ var first = true;
+
+ for(int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ if(value[i].isFalse) continue;
+
+ if(value[i].isTrue)
+ ret += string.Format("{0}{1}", first ? "" : " && ", PostPreds[procName][i]);
+ else
+ ret += string.Format("{0}({1} ==> {2})", first ? "" : " && ", value[i], PostPreds[procName][i]);
+
+ first = false;
+ }
+ if (ret == "") ret = "true";
+ return ret;
+ }
+
+
+ #region ISummaryElement Members
+
+ public ISummaryElement Copy()
+ {
+ var ret = new PredicateAbs(procName);
+ ret.isFalse = isFalse;
+ ret.value = new PredicateAbsDisjunct[value.Length];
+ for (int i = 0; i < value.Length; i++)
+ ret.value[i] = value[i];
+ return ret;
+ }
+
+ public ISummaryElement GetFlaseSummary(Program program, Implementation impl)
+ {
+ return new PredicateAbs(impl.Name);
+ }
+
+ public ISummaryElement GetTrueSummary(Program program, Implementation impl)
+ {
+ var ret = new PredicateAbs(impl.Name);
+ ret.isFalse = false;
+ for (int i = 0; i < PostPreds[this.procName].Count; i++) ret.value[i] = new PredicateAbsDisjunct(false, impl.Name);
+
+ return ret;
+ }
+
+ public void Join(Dictionary<string, Model.Element> state, Model model)
+ {
+ PredicateAbs.model = model;
+
+ // Evaluate each predicate on the state
+ var prePredsVal = new bool[PrePreds[procName].Count];
+ var postPredsVal = new bool[PostPreds[procName].Count];
+
+ var indexSeq = new List<int>();
+ for (int i = 0; i < PrePreds[procName].Count; i++) indexSeq.Add(i);
+
+ for (int i = 0; i < PrePreds[procName].Count; i++)
+ {
+ var v = ToValue(Eval(PrePreds[procName][i].expr, state));
+ Debug.Assert(v is bool);
+ prePredsVal[i] = (bool)v;
+ }
+
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ var v = ToValue(Eval(PostPreds[procName][i].expr, state));
+ Debug.Assert(v is bool);
+ postPredsVal[i] = (bool)v;
+ }
+
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ // No hope for this post pred?
+ if (!isFalse && value[i].isFalse) continue;
+
+ var newDisj = new PredicateAbsDisjunct(true, procName);
+ if (!postPredsVal[i])
+ {
+ newDisj = new PredicateAbsDisjunct(indexSeq.Where(j => !prePredsVal[j]), indexSeq.Where(j => prePredsVal[j] && !PosPrePreds[procName].Contains(j)), procName);
+ }
+
+ if (isFalse)
+ value[i] = newDisj;
+ else
+ value[i] = PredicateAbsDisjunct.And(value[i], newDisj);
+ }
+
+ /*
+ // do beta(model)
+ var that = new PredicateAbsDisjunct[PostPreds[procName].Count];
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ if (postPredsVal[i])
+ that[i] = new PredicateAbsDisjunct(true, procName);
+ else if (i == 0)
+ {
+ Debug.Assert(PostPreds[procName][0].ToString() == "false");
+ var newDisj = new PredicateAbsDisjunct(true, procName);
+ newDisj = new PredicateAbsDisjunct(indexSeq.Where(j => !prePredsVal[j]), indexSeq.Where(j => prePredsVal[j]), procName);
+ that[i] = newDisj;
+ }
+ else
+ {
+ // false
+ that[i] = new PredicateAbsDisjunct(false, procName);
+ }
+ }
+
+ // Do join
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ if (isFalse)
+ value[i] = that[i];
+ else
+ {
+ if (i == 0)
+ value[i] = PredicateAbsDisjunct.And(value[i], that[i]);
+ else
+ {
+ var c1 = PredicateAbsDisjunct.And(value[i], that[i]);
+ var c2 = PredicateAbsDisjunct.And(value[i], that[0]);
+ var c3 = PredicateAbsDisjunct.And(value[0], that[i]);
+ value[i] = PredicateAbsDisjunct.Or(c1, c2);
+ value[i] = PredicateAbsDisjunct.Or(value[i], c3);
+ }
+ }
+ }
+ */
+ isFalse = false;
+
+ //Console.WriteLine("Result of Join: {0}", this.ToString());
+ }
+
+ // Precondition: the upper guys are just {true/false/upper-candidate} ==> post-pred
+ public void Meet(ISummaryElement iother)
+ {
+ var other = iother as PredicateAbs;
+ if (isFalse) return;
+ if (other.isFalse)
+ {
+ isFalse = true;
+ for (int i = 0; i < PostPreds[this.procName].Count; i++) value[i] = null;
+ return;
+ }
+ Debug.Assert(this.procName == other.procName);
+
+ for (int i = 0; i < PostPreds[this.procName].Count; i++)
+ {
+ value[i] = PredicateAbsDisjunct.Or(value[i], other.value[i]);
+ }
+ }
+
+ public bool IsEqual(ISummaryElement other)
+ {
+ var that = other as PredicateAbs;
+ if (isFalse && that.isFalse) return true;
+ if (isFalse || that.isFalse) return false;
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ if (!PredicateAbsDisjunct.syntacticLessThan(value[i], that.value[i]) ||
+ !PredicateAbsDisjunct.syntacticLessThan(that.value[i], value[i]))
+ return false;
+ }
+ return true;
+ }
+
+ // Precondition: the upper guys are just {true/false/upper-candidate} ==> post-pred
+ // Postcondition: the returned value is also of this form (for just one post-pred)
+ public ISummaryElement AbstractConsequence(ISummaryElement iupper)
+ {
+ var upper = iupper as PredicateAbs;
+
+ for (int i = 0; i < PostPreds[this.procName].Count; i++)
+ {
+ if (upper.value[i].isTrue) continue;
+ if (!UpperCandidates.ContainsKey(Tuple.Create(procName, i))) continue;
+
+ foreach (var candidate in UpperCandidates[Tuple.Create(procName, i)])
+ {
+ if (PredicateAbsDisjunct.syntacticLessThan(candidate, upper.value[i]))
+ continue;
+ if (!this.isFalse && !PredicateAbsDisjunct.syntacticLessThan(candidate, this.value[i]))
+ continue;
+
+ var ret = new PredicateAbs(this.procName);
+ ret.isFalse = false;
+ for (int j = 0; j < PostPreds[this.procName].Count; j++)
+ ret.value[j] = new PredicateAbsDisjunct(false, this.procName);
+
+ ret.value[i] = candidate;
+
+ return ret;
+ }
+ }
+
+ // Giveup: the abstract consequence is too difficult to compute
+ return null;
+ }
+
+ public VCExpr GetSummaryExpr(Dictionary<string, VCExpr> incarnations, VCExpressionGenerator gen)
+ {
+ if (isFalse)
+ return VCExpressionGenerator.False;
+
+ var ret = VCExpressionGenerator.True;
+
+ for(int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ ret = gen.AndSimp(ret, gen.ImpliesSimp(value[i].ToVcExpr(j => ToVcExpr(PrePreds[procName][j].expr, incarnations, gen), gen), ToVcExpr(PostPreds[procName][i].expr, incarnations, gen)));
+ }
+
+ return ret;
+ }
+
+ public Expr GetSummaryExpr(Func<string, Expr> always, Func<string, Expr> forold)
+ {
+ if (isFalse)
+ return Expr.False;
+
+ Expr ret = Expr.True;
+
+ for (int i = 0; i < PostPreds[procName].Count; i++)
+ {
+ ret = Expr.And(ret, Expr.Imp(value[i].ToExpr(j => ToExpr(PrePreds[procName][j].expr, always, forold)), ToExpr(PostPreds[procName][i].expr, always, forold)));
+ }
+
+ return ret;
+ }
+
+ #endregion
+ }
+
+ public class PredicateAbsDisjunct
+ {
+ List<PredicateAbsConjunct> conjuncts;
+ string ProcName;
+ public bool isTrue {get; private set;}
+ public bool isFalse
+ {
+ get
+ {
+ if (isTrue) return false;
+ return conjuncts.Count == 0;
+ }
+ }
+
+ public PredicateAbsDisjunct(bool isTrue, string ProcName)
+ {
+ this.isTrue = isTrue;
+ this.ProcName = ProcName;
+ conjuncts = new List<PredicateAbsConjunct>();
+ }
+
+ public PredicateAbsDisjunct(List<PredicateAbsConjunct> conjuncts, string ProcName)
+ {
+ isTrue = false;
+ this.conjuncts = conjuncts;
+ this.ProcName = ProcName;
+ }
+
+ // Disjunct of singleton conjuncts
+ public PredicateAbsDisjunct(IEnumerable<int> pos, IEnumerable<int> neg, string ProcName)
+ {
+ this.ProcName = ProcName;
+ conjuncts = new List<PredicateAbsConjunct>();
+ isTrue = false;
+ pos.Iter(p => conjuncts.Add(PredicateAbsConjunct.Singleton(p, true, ProcName)));
+ neg.Iter(p => conjuncts.Add(PredicateAbsConjunct.Singleton(p, false, ProcName)));
+ }
+
+ // Does d1 describe a smaller set of states than d2? This is true when every conjunct of d1
+ // is smaller than some conjunct of d2
+ public static bool syntacticLessThan(PredicateAbsDisjunct d1, PredicateAbsDisjunct d2)
+ {
+ if (d2.isTrue) return true;
+ if (d1.isTrue) return false;
+ if (d1.isFalse) return true;
+ if (d2.isFalse) return false;
+
+ foreach (var c1 in d1.conjuncts)
+ {
+ if (d2.conjuncts.Any(c2 => PredicateAbsConjunct.syntacticLessThan(c1, c2)))
+ continue;
+ else
+ return false;
+ }
+ return true;
+ }
+
+ public static PredicateAbsDisjunct And(PredicateAbsDisjunct v1, PredicateAbsDisjunct v2)
+ {
+ if (v1.isTrue) return v2;
+ if (v2.isTrue) return v1;
+
+ var result = new List<PredicateAbsConjunct>();
+
+ foreach (var c1 in v1.conjuncts)
+ {
+ foreach (var c2 in v2.conjuncts)
+ {
+ var c = PredicateAbsConjunct.And(c1, c2);
+ if (c.isFalse) continue;
+ if (result.Any(cprime => c.implies(cprime))) continue;
+ var tmp = new List<PredicateAbsConjunct>();
+ tmp.Add(c);
+ result.Where(cprime => !cprime.implies(c)).Iter(cprime => tmp.Add(cprime));
+ result = tmp;
+ }
+ }
+
+ return new PredicateAbsDisjunct(result, v1.ProcName);
+ }
+
+ public static PredicateAbsDisjunct Or(PredicateAbsDisjunct v1, PredicateAbsDisjunct v2)
+ {
+ if (v1.isTrue) return v1;
+ if (v2.isTrue) return v2;
+ if (v1.isFalse) return v2;
+ if (v2.isFalse) return v1;
+
+ var result = new List<PredicateAbsConjunct>();
+ v1.conjuncts.Iter(c => result.Add(c));
+
+ foreach (var c in v2.conjuncts)
+ {
+ if (result.Any(cprime => c.implies(cprime))) continue;
+ var tmp = new List<PredicateAbsConjunct>();
+ tmp.Add(c);
+ result.Where(cprime => !cprime.implies(c)).Iter(cprime => tmp.Add(cprime));
+ result = tmp;
+ }
+
+ return new PredicateAbsDisjunct(result, v1.ProcName);
+ }
+
+ public VCExpr ToVcExpr(Func<int, VCExpr> predToExpr, VCExpressionGenerator gen)
+ {
+ if (isTrue) return VCExpressionGenerator.True;
+ var ret = VCExpressionGenerator.False;
+ conjuncts.Iter(c => ret = gen.OrSimp(ret, c.ToVcExpr(predToExpr, gen)));
+ return ret;
+ }
+
+ public Expr ToExpr(Func<int, Expr> predToExpr)
+ {
+ if (isTrue) return Expr.True;
+ Expr ret = Expr.False;
+ conjuncts.Iter(c => ret = Expr.Or(ret, c.ToExpr(predToExpr)));
+ return ret;
+ }
+
+ public override string ToString()
+ {
+ if(isTrue)
+ return "true";
+ var ret = "";
+ var first = true;
+ foreach (var c in conjuncts)
+ {
+ if (c.isFalse) continue;
+ ret += string.Format("{0}{1}", first ? "" : " || ", c);
+ first = false;
+ }
+ return ret;
+ }
+
+ public void Subtract(PredicateAbsDisjunct that)
+ {
+ var ncon = new List<PredicateAbsConjunct>();
+ foreach (var c1 in conjuncts)
+ {
+ if (that.conjuncts.Any(c2 => c1.implies(c2)))
+ continue;
+ ncon.Add(c1);
+ }
+ conjuncts = ncon;
+ }
+
+ public IEnumerable<PredicateAbsConjunct> GetConjuncts()
+ {
+ return conjuncts;
+ }
+
+ }
+
+ public class PredicateAbsConjunct
+ {
+ static int ConjunctBound = 3;
+
+ public bool isFalse { get; private set; }
+ HashSet<int> posPreds;
+ HashSet<int> negPreds;
+ string ProcName;
+
+ public static void Initialize(int bound)
+ {
+ ConjunctBound = bound;
+ }
+
+ private void Normalize()
+ {
+ if (posPreds.Intersect(negPreds).Any() || negPreds.Intersect(posPreds).Any() || (posPreds.Count + negPreds.Count > ConjunctBound))
+ {
+ isFalse = true;
+ posPreds = new HashSet<int>();
+ negPreds = new HashSet<int>();
+ }
+ }
+
+ // Do this step only once in a while?
+ private void StrongNormalize()
+ {
+ if (isFalse) return;
+
+ var candidates = new List<Tuple<int, bool>>();
+ posPreds.Iter(p => candidates.Add(Tuple.Create(p, true)));
+ negPreds.Iter(p => candidates.Add(Tuple.Create(p, false)));
+ var drop = new HashSet<int>();
+ for (int i = 0; i < candidates.Count; i++)
+ {
+ for (int j = 0; j < candidates.Count; j++)
+ {
+ if (i == j) continue;
+
+ var key = Tuple.Create(ProcName, candidates[i].Item1, candidates[j].Item1,
+ candidates[i].Item2, candidates[j].Item2);
+ if (PredicateAbs.unsatPrePredPairs.Contains(key))
+ {
+ isFalse = true;
+ posPreds = new HashSet<int>();
+ negPreds = new HashSet<int>();
+ return;
+ }
+
+ key = Tuple.Create(ProcName, candidates[i].Item1, candidates[j].Item1,
+ candidates[i].Item2, !candidates[j].Item2);
+
+ if (PredicateAbs.unsatPrePredPairs.Contains(key))
+ drop.Add(candidates[j].Item1);
+ }
+ }
+
+ posPreds.ExceptWith(drop);
+ negPreds.ExceptWith(drop);
+ }
+
+ public PredicateAbsConjunct(bool isFalse, string ProcName)
+ {
+ posPreds = new HashSet<int>();
+ negPreds = new HashSet<int>();
+ this.isFalse = isFalse;
+ this.ProcName = ProcName;
+ }
+
+ // do we know that c1 is surely less than or equal to c2? That is, c1 describes a smaller
+ // concretization. We check that c2 is a sub-conjunct of c1
+ public static bool syntacticLessThan(PredicateAbsConjunct c1, PredicateAbsConjunct c2)
+ {
+ if (c1.isFalse) return true;
+ if (c2.isFalse) return false;
+ return (c2.posPreds.IsSubsetOf(c1.posPreds) && c2.negPreds.IsSubsetOf(c1.negPreds));
+ }
+
+ public static PredicateAbsConjunct Singleton(int v, bool isPositive, string ProcName)
+ {
+ if (isPositive)
+ return new PredicateAbsConjunct(new int[] { v }, new HashSet<int>(), ProcName);
+ else
+ return new PredicateAbsConjunct(new HashSet<int>(), new int[] { v }, ProcName);
+ }
+
+ public PredicateAbsConjunct(IEnumerable<int> pos, IEnumerable<int> neg, string ProcName)
+ {
+ isFalse = false;
+ posPreds = new HashSet<int>(pos);
+ negPreds = new HashSet<int>(neg);
+ this.ProcName = ProcName;
+ Normalize();
+ }
+
+ public static PredicateAbsConjunct And(PredicateAbsConjunct v1, PredicateAbsConjunct v2)
+ {
+ if (v1.isFalse || v2.isFalse) return new PredicateAbsConjunct(true, v1.ProcName);
+ var ret = new PredicateAbsConjunct(v1.posPreds.Union(v2.posPreds), v1.negPreds.Union(v2.negPreds), v1.ProcName);
+ ret.StrongNormalize();
+ return ret;
+ }
+
+ public bool implies(PredicateAbsConjunct v)
+ {
+ if (isFalse) return true;
+ if (v.isFalse) return false;
+ return (posPreds.IsSupersetOf(v.posPreds) && negPreds.IsSupersetOf(v.negPreds));
+ }
+
+ public VCExpr ToVcExpr(Func<int, VCExpr> predToExpr, VCExpressionGenerator gen)
+ {
+ if (isFalse) return VCExpressionGenerator.False;
+ var ret = VCExpressionGenerator.True;
+ posPreds.Iter(p => ret = gen.AndSimp(ret, predToExpr(p)));
+ negPreds.Iter(p => ret = gen.AndSimp(ret, gen.Not(predToExpr(p))));
+ return ret;
+ }
+
+ public Expr ToExpr(Func<int, Expr> predToExpr)
+ {
+ if (isFalse) return Expr.False;
+ Expr ret = Expr.True;
+ var pp = posPreds.ToList(); pp.Sort();
+ var np = negPreds.ToList(); np.Sort();
+ pp.Iter(p => ret = Expr.And(ret, predToExpr(p)));
+ np.Iter(p => ret = Expr.And(ret, Expr.Not(predToExpr(p))));
+ return ret;
+ }
+
+ public override string ToString()
+ {
+ if (isFalse)
+ return "false";
+
+ var ret = "";
+ var first = true;
+ foreach (var p in posPreds)
+ {
+ ret += string.Format("{0}{1}", first ? "" : " && ", PredicateAbs.PrePreds[ProcName][p]);
+ first = false;
+ }
+ foreach (var p in negPreds)
+ {
+ ret += string.Format("{0}!{1}", first ? "" : " && ", PredicateAbs.PrePreds[ProcName][p]);
+ first = false;
+ }
+ return ret;
+ }
+ }
+
+ class FindSummaryPred : MutatingVCExprVisitor<bool>
+ {
+ public List<Tuple<string, bool, VCExprVar, VCExprNAry>> summaryPreds;
+ int assertId;
+ private static int CounterId = 0;
+
+ public FindSummaryPred(VCExpressionGenerator gen, int assertId)
+ : base(gen)
+ {
+ summaryPreds = new List<Tuple<string, bool, VCExprVar, VCExprNAry>>();
+ this.assertId = assertId;
+ }
+
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
+ List<VCExpr/*!*/>/*!*/ newSubExprs,
+ // has any of the subexpressions changed?
+ bool changed,
+ bool arg)
+ {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr ret;
+ if (changed)
+ ret = Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ ret = originalNode;
+
+ VCExprNAry retnary = ret as VCExprNAry;
+ if (retnary == null) return ret;
+ var op = retnary.Op as VCExprBoogieFunctionOp;
+
+ if (op == null)
+ {
+ var lop = retnary.Op as VCExprLabelOp;
+ if (lop == null) return ret;
+ if (lop.pos) return ret;
+ if (!lop.label.Equals("@" + assertId.ToString())) return ret;
+
+ //var subexpr = retnary[0] as VCExprNAry;
+ //if (subexpr == null) return ret;
+ //op = subexpr.Op as VCExprBoogieFunctionOp;
+ //if (op == null) return ret;
+
+ var subexpr = retnary[0] as VCExprVar;
+ if (subexpr == null) return ret;
+ if (!subexpr.Name.StartsWith("AbstractHoudiniControl")) return ret;
+
+ for (int i = 0; i < summaryPreds.Count; i++)
+ {
+ if (summaryPreds[i].Item3 == subexpr)
+ summaryPreds[i] = Tuple.Create(summaryPreds[i].Item1, true, summaryPreds[i].Item3, summaryPreds[i].Item4);
+ }
+ return ret;
+ }
+
+ string calleeName = op.Func.Name;
+
+ if (!calleeName.EndsWith(AbstractHoudini.summaryPredSuffix))
+ return ret;
+
+ var controlConst = Gen.Variable("AbstractHoudiniControl" + CounterId, Microsoft.Boogie.Type.Bool);
+ CounterId++;
+
+ summaryPreds.Add(Tuple.Create(calleeName.Substring(0, calleeName.Length - AbstractHoudini.summaryPredSuffix.Length), false, controlConst, retnary));
+
+ return controlConst;
+ //return ret;
+ }
+
+ }
+
+ class FindExistentialFunctions : MutatingVCExprVisitor<bool>
+ {
+ public List<Tuple<string, VCExprVar, VCExprNAry>> funcCalls;
+ private HashSet<string> existentialFunctions;
+ private static int CounterId = 0;
+
+ public FindExistentialFunctions(VCExpressionGenerator gen, HashSet<string> existentialFunctions)
+ : base(gen)
+ {
+ funcCalls = new List<Tuple<string, VCExprVar, VCExprNAry>>();
+ this.existentialFunctions = existentialFunctions;
+ }
+
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
+ List<VCExpr/*!*/>/*!*/ newSubExprs,
+ // has any of the subexpressions changed?
+ bool changed,
+ bool arg)
+ {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr ret;
+ if (changed)
+ ret = Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ ret = originalNode;
+
+ VCExprNAry retnary = ret as VCExprNAry;
+ if (retnary == null) return ret;
+ var op = retnary.Op as VCExprBoogieFunctionOp;
+ if (op == null) return ret;
+
+ string calleeName = op.Func.Name;
+
+ if (!existentialFunctions.Contains(calleeName))
+ return ret;
+
+ var controlConst = Gen.Variable("AbsHoudiniControl" + CounterId, Microsoft.Boogie.Type.Bool);
+ CounterId++;
+
+ funcCalls.Add(Tuple.Create(calleeName, controlConst, retnary));
+
+ return controlConst;
+ }
+
+ }
+
+ class AbstractHoudiniErrorReporter : ProverInterface.ErrorHandler
+ {
+ public Model model;
+
+ public AbstractHoudiniErrorReporter()
+ {
+ model = null;
+ }
+
+ public override void OnModel(IList<string> labels, Model model, ProverInterface.Outcome proverOutcome)
+ {
+ Debug.Assert(model != null);
+ if(CommandLineOptions.Clo.PrintErrorModel >= 1) model.Write(Console.Out);
+ this.model = model;
+ }
+ }
+
+ public class AbsHoudiniInternalError : System.ApplicationException
+ {
+ public AbsHoudiniInternalError(string msg) : base(msg) { }
+
+ };
+
+ public class SimpleUtil
+ {
+ // Constructs a mapping from procedure names to the implementation
+ public static Dictionary<string, Implementation> nameImplMapping(Program p)
+ {
+ var m = new Dictionary<string, Implementation>();
+ foreach (var impl in p.Implementations)
+ {
+ m.Add(impl.Name, impl);
+ }
+
+ return m;
+ }
+
+ // is "assert true"?
+ public static bool isAssertTrue(Cmd cmd)
+ {
+ var acmd = cmd as AssertCmd;
+ if (acmd == null) return false;
+ var le = acmd.Expr as LiteralExpr;
+ if (le == null) return false;
+ if (le.IsTrue) return true;
+ return false;
+ }
+ }
+
+}
diff --git a/Source/Houdini/AnnotationDependenceAnalyser.cs b/Source/Houdini/AnnotationDependenceAnalyser.cs
index e925d413..dacac233 100644
--- a/Source/Houdini/AnnotationDependenceAnalyser.cs
+++ b/Source/Houdini/AnnotationDependenceAnalyser.cs
@@ -1,878 +1,878 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie.GraphUtil;
-using Microsoft.Basetypes;
-using System.Diagnostics;
-
-namespace Microsoft.Boogie.Houdini {
-
- public class AnnotationDependenceAnalyser {
-
- private const string COARSE_STAGES = "COARSE";
- private const string FINE_STAGES = "FINE";
- private const string BALANCED_STAGES = "BALANCED";
-
- private Program prog;
- private IVariableDependenceAnalyser varDepAnalyser;
- private IEnumerable<string> CandidateIdentifiers; // Candidate Boolean names
- private IEnumerable<string> NonCandidateIdentifiers; // Additional names introduced for non-candidate annotations
- private Dictionary<string, HashSet<VariableDescriptor>> annotationDependsOn;
- private Dictionary<VariableDescriptor, HashSet<string>> variableDirectlyReferredToByAnnotations;
- private Graph<string> AnnotationDependences;
- private StronglyConnectedComponents<string> SCCs;
- private Graph<SCC<string>> StagesDAG;
- private StagedHoudiniPlan Plan;
-
- public AnnotationDependenceAnalyser(Program prog) {
- this.prog = prog;
- this.varDepAnalyser = new VariableDependenceAnalyser(prog);
- varDepAnalyser.Analyse();
- }
-
- public void Analyse() {
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Annotation dependence analysis: Getting annotations");
- }
-
- CandidateIdentifiers = GetCandidates();
- NonCandidateIdentifiers = GetNonCandidateAnnotations();
-
- DetermineAnnotationVariableDependences();
-
- ConstructAnnotationDependenceGraph();
-
- ConstructStagesDAG();
-
- }
-
- private IEnumerable<string> AllAnnotationIdentifiers() {
- HashSet<string> Result = new HashSet<string>();
- foreach (var c in CandidateIdentifiers) {
- Result.Add(c);
- }
- foreach (var a in NonCandidateIdentifiers) {
- Result.Add(a);
- }
- return Result;
- }
-
- private void ConstructStagesDAG()
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Annotation dependence analysis: Computing SCCs");
- }
-
- Adjacency<string> next = new Adjacency<string>(AnnotationDependences.Successors);
- Adjacency<string> prev = new Adjacency<string>(AnnotationDependences.Predecessors);
- SCCs = new StronglyConnectedComponents<string>(
- AnnotationDependences.Nodes, next, prev);
- SCCs.Compute();
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Annotation dependence analysis: Building stages DAG");
- }
-
- Dictionary<string, SCC<string>> rep = new Dictionary<string, SCC<string>>();
- foreach (var scc in SCCs)
- {
- foreach (var s in scc)
- {
- rep[s] = scc;
- }
- }
-
- StagesDAG = new Graph<SCC<string>>();
-
- foreach (var edge in AnnotationDependences.Edges)
- {
- if (rep[edge.Item1] != rep[edge.Item2])
- {
- StagesDAG.AddEdge(rep[edge.Item1], rep[edge.Item2]);
- }
- }
-
- SCC<string> dummy = new SCC<string>();
- foreach (var scc in SCCs)
- {
- StagesDAG.AddEdge(scc, dummy);
- }
- }
-
- private void ConstructAnnotationDependenceGraph()
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Annotation dependence analysis: Building dependence graph");
- }
-
- IAnnotationReachabilityChecker reachabilityChecker;
-
- if(CommandLineOptions.Clo.StagedHoudiniReachabilityAnalysis) {
- reachabilityChecker = new AnnotationReachabilityChecker(prog, AllAnnotationIdentifiers());
- } else {
- reachabilityChecker = new DummyAnnotationReachabilityChecker();
- }
-
- AnnotationDependences = new Graph<string>();
- foreach (var c in AllAnnotationIdentifiers())
- {
- AnnotationDependences.AddEdge(c, c);
- foreach (var vd in annotationDependsOn[c])
- {
- if (variableDirectlyReferredToByAnnotations.ContainsKey(vd))
- {
- foreach (var d in variableDirectlyReferredToByAnnotations[vd])
- {
- if(reachabilityChecker.MayReach(d, c))
- {
- AnnotationDependences.AddEdge(c, d);
- }
- }
- }
- }
- }
-
- if(CommandLineOptions.Clo.StagedHoudiniMergeIgnoredAnnotations) {
- MergeIgnoredAnnotations();
- }
-
- }
-
- private void MergeIgnoredAnnotations()
- {
- var IgnoredAnnotationsToVariables = new Dictionary<string, HashSet<Variable>>();
- foreach(var c in AllAnnotationIdentifiers()) {
- IgnoredAnnotationsToVariables[c] = new HashSet<Variable>();
- }
- foreach(var ci in AnnotationInstances()) {
- if(!IgnoredAnnotationsToVariables.ContainsKey(ci.AnnotationIdentifier)) {
- continue;
- }
- VariableCollector vc = new VariableCollector();
- vc.Visit(ci.Expr);
- if(vc.usedVars.Select(Item => varDepAnalyser.VariableRelevantToAnalysis(Item, ci.Proc)).Count() != 0) {
- continue;
- }
- foreach(var v in vc.usedVars) {
- if(varDepAnalyser.Ignoring(v, ci.Proc)) {
- IgnoredAnnotationsToVariables[ci.AnnotationIdentifier].Add(v);
- }
- }
- }
- foreach(var c in IgnoredAnnotationsToVariables.Keys) {
- foreach(var d in IgnoredAnnotationsToVariables.Keys) {
- if(c == d) {
- continue;
- }
- if(IgnoredAnnotationsToVariables[c].Equals(IgnoredAnnotationsToVariables[d])) {
- AnnotationDependences.AddEdge(c, d);
- }
- }
- }
- }
-
-
-
- private void DetermineAnnotationVariableDependences()
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Annotation dependence analysis: Working out what annotations depend on");
- }
- annotationDependsOn = new Dictionary<string, HashSet<VariableDescriptor>>();
- variableDirectlyReferredToByAnnotations = new Dictionary<VariableDescriptor, HashSet<string>>();
- foreach (var c in AllAnnotationIdentifiers())
- {
- annotationDependsOn[c] = new HashSet<VariableDescriptor>();
- }
-
- foreach(var annotationInstance in AnnotationInstances()) {
- AddDependences(annotationInstance);
- }
-
- }
-
- private IEnumerable<AnnotationInstance> AnnotationInstances()
- {
- foreach (var impl in prog.Implementations)
- {
- foreach (PredicateCmd p in impl.Blocks.SelectMany(Item => Item.Cmds).OfType<PredicateCmd>())
- {
- string c;
- if(Houdini.MatchCandidate(p.Expr, CandidateIdentifiers, out c)) {
- yield return new AnnotationInstance(c, impl.Name, p.Expr);
- } else if((p is AssertCmd) && QKeyValue.FindBoolAttribute(p.Attributes, "originated_from_invariant")) {
- var tag = GetTagFromNonCandidateAttributes(p.Attributes);
- if (tag != null) {
- yield return new AnnotationInstance(tag, impl.Name, p.Expr);
- }
- }
- }
- }
-
- foreach (var proc in prog.NonInlinedProcedures())
- {
- foreach (Requires r in proc.Requires)
- {
- string c;
- if(Houdini.MatchCandidate(r.Condition, CandidateIdentifiers, out c)) {
- yield return new AnnotationInstance(c, proc.Name, r.Condition);
- } else {
- var tag = GetTagFromNonCandidateAttributes(r.Attributes);
- if (tag != null) {
- yield return new AnnotationInstance(tag, proc.Name, r.Condition);
- }
- }
- }
- foreach (Ensures e in proc.Ensures)
- {
- string c;
- if(Houdini.MatchCandidate(e.Condition, CandidateIdentifiers, out c)) {
- yield return new AnnotationInstance(c, proc.Name, e.Condition);
- } else {
- var tag = GetTagFromNonCandidateAttributes(e.Attributes);
- if (tag != null) {
- yield return new AnnotationInstance(tag, proc.Name, e.Condition);
- }
- }
- }
- }
- }
-
- internal static string GetTagFromNonCandidateAttributes(QKeyValue Attributes)
- {
- string tag = QKeyValue.FindStringAttribute(Attributes, "staged_houdini_tag");
- return tag;
- }
-
- private bool FindInDAG(Graph<SCC<string>> DAG, SCC<string> toFind, SCC<string> start) {
- if (toFind == start) {
- return true;
- }
- foreach (var n in DAG.Successors(start)) {
- if (FindInDAG(DAG, toFind, n)) {
- return true;
- }
- }
- return false;
- }
-
- private void AddDependences(AnnotationInstance ci) {
- VariableCollector vc = new VariableCollector();
- vc.VisitExpr(ci.Expr);
-
- foreach (var v in vc.usedVars.Where(Item => varDepAnalyser.VariableRelevantToAnalysis(Item, ci.Proc))) {
- VariableDescriptor vd =
- varDepAnalyser.MakeDescriptor(ci.Proc, v);
- if (!variableDirectlyReferredToByAnnotations.ContainsKey(vd)) {
- variableDirectlyReferredToByAnnotations[vd] = new HashSet<string>();
- }
- variableDirectlyReferredToByAnnotations[vd].Add(ci.AnnotationIdentifier);
-
- foreach (var w in varDepAnalyser.DependsOn(vd)) {
- annotationDependsOn[ci.AnnotationIdentifier].Add(w);
- }
- }
- }
-
- private bool IsStageDependence(SCC<string> Src, SCC<string> Dst) {
- foreach (var c in Src) {
- foreach (var d in AnnotationDependences.Successors(c)) {
- if (Dst.Contains(d)) {
- return true;
- }
- }
- }
- return false;
- }
-
-
- public void dump() {
-
- if(CommandLineOptions.Clo.DebugStagedHoudini) {
- varDepAnalyser.dump();
-
- Console.WriteLine("Annotations and the variables they depend on");
- Console.WriteLine("============================================");
- foreach (var entry in annotationDependsOn) {
- Console.WriteLine(entry.Key + " <- ");
- foreach (var vd in entry.Value) {
- Console.WriteLine(" " + vd + ", ");
- }
- }
-
- Console.WriteLine("");
-
- Console.WriteLine("Variables and the annotations that directly refer to them");
- Console.WriteLine("========================================================");
- foreach (var entry in variableDirectlyReferredToByAnnotations) {
- Console.WriteLine(entry.Key + " <- ");
- foreach (var annotation in entry.Value) {
- Console.WriteLine(" " + annotation + ", ");
- }
- }
-
- Console.WriteLine("");
-
- Console.WriteLine("Annotation dependence graph");
- Console.WriteLine("==========================");
- foreach (var c in AnnotationDependences.Nodes) {
- Console.WriteLine(c + " <- ");
- foreach (var d in AnnotationDependences.Successors(c)) {
- Console.WriteLine(" " + d);
- }
- }
- }
-
- Console.WriteLine("");
-
- Console.WriteLine("Strongly connected components");
- Console.WriteLine("=============================");
-
- List<SCC<string>> Components = StagesDAG.TopologicalSort().ToList();
-
- for (int i = 0; i < Components.Count(); i++) {
- Console.Write(i + ": ");
- DumpSCC(Components[i]);
- Console.WriteLine(); Console.WriteLine();
- }
-
- Console.WriteLine("Stages DAG");
- Console.WriteLine("==========");
- for (int i = 0; i < Components.Count(); i++) {
- Console.Write(i + " -> { ");
- bool first = true;
- foreach (var d in StagesDAG.Successors(Components[i])) {
- if (first) {
- first = false;
- }
- else {
- Console.Write(", ");
- }
- Console.Write(Components.IndexOf(d));
- }
- Console.WriteLine(" }");
- }
-
- }
-
- private static void DumpSCC(SCC<string> component) {
- var sortedComponent = component.ToList();
- sortedComponent.Sort();
- Console.Write("{ ");
- bool first = true;
- foreach (var s in sortedComponent) {
- if (first) {
- first = false;
- }
- else {
- Console.Write(", ");
- }
- Console.Write(s);
- }
- Console.Write(" }");
- }
-
- private bool OnlyRefersToConstants(Expr e) {
- VariableCollector vc = new VariableCollector();
- vc.Visit(e);
- return vc.usedVars.OfType<Constant>().Count() == vc.usedVars.Count();
- }
-
- private IEnumerable<string> GetNonCandidateAnnotations() {
- var Result = new HashSet<string>();
- int Counter = 0;
- foreach(var Assertion in prog.Blocks().SelectMany(Item => Item.Cmds).
- OfType<AssertCmd>()) {
-
- string unused;
- if (Houdini.MatchCandidate(Assertion.Expr, CandidateIdentifiers, out unused)) {
- continue;
- }
-
- if (!QKeyValue.FindBoolAttribute(Assertion.Attributes, "originated_from_invariant")) {
- continue;
- }
-
- if (OnlyRefersToConstants(Assertion.Expr)) {
- continue;
- }
-
- string Tag = "staged_houdini_tag_" + Counter;
- Result.Add(Tag);
- Assertion.Attributes = new QKeyValue(Token.NoToken, "staged_houdini_tag",
- new List<object> { Tag }, Assertion.Attributes);
- Counter++;
- }
-
- foreach(var Req in prog.NonInlinedProcedures().SelectMany(Item => Item.Requires)) {
-
- string unused;
- if (Houdini.MatchCandidate(Req.Condition, CandidateIdentifiers, out unused)) {
- continue;
- }
-
- if (OnlyRefersToConstants(Req.Condition)) {
- continue;
- }
-
- string Tag = "staged_houdini_tag_" + Counter;
- Result.Add(Tag);
- Req.Attributes = new QKeyValue(Token.NoToken, "staged_houdini_tag",
- new List<object> { Tag }, Req.Attributes);
- Counter++;
-
- }
-
- foreach(var Ens in prog.NonInlinedProcedures().SelectMany(Item => Item.Ensures)) {
-
- string unused;
- if (Houdini.MatchCandidate(Ens.Condition, CandidateIdentifiers, out unused)) {
- continue;
- }
-
- if (OnlyRefersToConstants(Ens.Condition)) {
- continue;
- }
-
- string Tag = "staged_houdini_tag_" + Counter;
- Result.Add(Tag);
- Ens.Attributes = new QKeyValue(Token.NoToken, "staged_houdini_tag",
- new List<object> { Tag }, Ens.Attributes);
- Counter++;
-
- }
-
- return Result;
- }
-
- private IEnumerable<string> GetCandidates() {
- return prog.Variables.Where(Item =>
- QKeyValue.FindBoolAttribute(Item.Attributes, "existential")).Select(Item => Item.Name);
- }
-
-
- public StagedHoudiniPlan ApplyStages() {
-
- if (NoStages())
- {
- Debug.Assert(false);
- var TrivialGraph = new Graph<ScheduledStage>();
- TrivialGraph.AddSource(new ScheduledStage(0, new HashSet<string>()));
- return new StagedHoudiniPlan(TrivialGraph);
- }
-
- #region Assign annotations to stages at a given level of granularity
-
- switch(CommandLineOptions.Clo.StagedHoudini) {
- case COARSE_STAGES:
- Plan = ComputeCoarseStages();
- break;
- case FINE_STAGES:
- Plan = ComputeFineStages();
- break;
- case BALANCED_STAGES:
- Plan = ComputeBalancedStages();
- break;
- default:
- Debug.Assert(false);
- Plan = null;
- break;
- }
-
- foreach(var c in AllAnnotationIdentifiers()) {
- Debug.Assert(Plan.StageForAnnotation(c) != null);
- }
- #endregion
-
- #region Generate boolean variables to control stages
- var stageToActiveBoolean = new Dictionary<int, Constant>();
- var stageToCompleteBoolean = new Dictionary<int, Constant>();
-
- foreach (var stage in Plan)
- {
- var stageActive = new Constant(Token.NoToken,
- new TypedIdent(Token.NoToken, "_stage_" + stage.GetId() + "_active", Type.Bool),
- false);
- stageActive.AddAttribute("stage_active", new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(stage.GetId())) });
- prog.AddTopLevelDeclaration(stageActive);
- stageToActiveBoolean[stage.GetId()] = stageActive;
-
- var stageComplete = new Constant(Token.NoToken,
- new TypedIdent(Token.NoToken, "_stage_" + stage.GetId() + "_complete", Type.Bool),
- false);
- stageComplete.AddAttribute("stage_complete", new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(stage.GetId())) });
- prog.AddTopLevelDeclaration(stageComplete);
- stageToCompleteBoolean[stage.GetId()] = stageComplete;
- }
- #endregion
-
- #region Adapt annotation assertions to take account of stages
- foreach (var b in prog.Implementations.Select(Item => Item.Blocks).SelectMany(Item => Item))
- {
- List<Cmd> newCmds = new List<Cmd>();
- foreach (var cmd in b.Cmds)
- {
- var a = cmd as AssertCmd;
- string c;
- if (a != null) {
- if (Houdini.MatchCandidate(a.Expr, CandidateIdentifiers, out c))
- {
- newCmds.Add(new AssertCmd(a.tok, Houdini.AddConditionToCandidate(a.Expr,
- Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(c).GetId()]), c), a.Attributes));
- newCmds.Add(new AssumeCmd(a.tok, Houdini.AddConditionToCandidate(a.Expr,
- Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(c).GetId()]), c), a.Attributes));
- } else if (QKeyValue.FindBoolAttribute(a.Attributes, "originated_from_invariant")) {
- string tag = GetTagFromNonCandidateAttributes(a.Attributes);
- if (tag == null) {
- newCmds.Add(a);
- } else {
- newCmds.Add(new AssertCmd(a.tok, Expr.Imp(
- Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(tag).GetId()]), a.Expr),
- a.Attributes));
- newCmds.Add(new AssumeCmd(a.tok, Expr.Imp(
- Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(tag).GetId()]), a.Expr),
- a.Attributes));
- }
- }
- }
- else
- {
- newCmds.Add(cmd);
- }
- }
- b.Cmds = newCmds;
- }
- #endregion
-
- #region Adapt pre/postconditions to take account of stages
- foreach (var p in prog.NonInlinedProcedures())
- {
-
- #region Handle the preconditions
- {
- List<Requires> newRequires = new List<Requires>();
- foreach(Requires r in p.Requires) {
- string c;
- if (Houdini.MatchCandidate(r.Condition, CandidateIdentifiers, out c)) {
- newRequires.Add(new Requires(r.tok, false,
- Houdini.AddConditionToCandidate(r.Condition,
- Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(c).GetId()]), c),
- r.Comment, r.Attributes));
- newRequires.Add(new Requires(r.tok, true,
- Houdini.AddConditionToCandidate(r.Condition,
- Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(c).GetId()]), c),
- r.Comment, r.Attributes));
- } else {
- string tag = GetTagFromNonCandidateAttributes(r.Attributes);
- if (tag == null) {
- newRequires.Add(r);
- } else {
- newRequires.Add(new Requires(r.tok, false,
- Expr.Imp(Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(tag).GetId()]), r.Condition),
- r.Comment, r.Attributes));
- newRequires.Add(new Requires(r.tok, true,
- Expr.Imp(Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(tag).GetId()]), r.Condition),
- r.Comment, r.Attributes));
- }
- }
- }
- p.Requires = newRequires;
- }
- #endregion
-
- #region Handle the postconditions
- {
- List<Ensures> newEnsures = new List<Ensures>();
- foreach(Ensures e in p.Ensures) {
- string c;
- if (Houdini.MatchCandidate(e.Condition, CandidateIdentifiers, out c)) {
- int stage = Plan.StageForAnnotation(c).GetId();
- newEnsures.Add(new Ensures(e.tok, false,
- Houdini.AddConditionToCandidate(e.Condition,
- Expr.Ident(stageToActiveBoolean[stage]), c),
- e.Comment, e.Attributes));
- newEnsures.Add(new Ensures(e.tok, true,
- Houdini.AddConditionToCandidate(e.Condition,
- Expr.Ident(stageToCompleteBoolean[stage]), c),
- e.Comment, e.Attributes));
- } else {
- string tag = GetTagFromNonCandidateAttributes(e.Attributes);
- if (tag == null) {
- newEnsures.Add(e);
- } else {
- newEnsures.Add(new Ensures(e.tok, false,
- Expr.Imp(Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(tag).GetId()]), e.Condition),
- e.Comment, e.Attributes));
- newEnsures.Add(new Ensures(e.tok, true,
- Expr.Imp(Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(tag).GetId()]), e.Condition),
- e.Comment, e.Attributes));
- }
- }
- }
- p.Ensures = newEnsures;
- }
- #endregion
-
- }
- #endregion
-
- return Plan;
-
- }
-
- private int FindLargestStage() {
- return StagesDAG.Nodes.Select(Item => Item.Count()).Max();
- }
-
-
- private StagedHoudiniPlan ComputeCoarseStages()
- {
- foreach(var n in StagesDAG.Nodes) {
- Debug.Assert(!StagesDAG.Successors(n).Contains(n));
- }
-
- Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
-
- var done = new Dictionary<SCC<string>, ScheduledStage>();
- done[GetStartNodeOfStagesDAG()] = new ScheduledStage(0, new HashSet<string>());
-
- for(int stageId = 1; done.Count() != StagesDAG.Nodes.Count(); stageId++)
- {
- var Stage = new ScheduledStage(stageId, new HashSet<string>());
- HashSet<SCC<string>> AssignedToThisStage = new HashSet<SCC<string>>();
-
- foreach (var n in StagesDAG.Nodes.Where(Item => !done.ContainsKey(Item)))
- {
- if(StagesDAG.Successors(n).Where(Item => !done.ContainsKey(Item)).Count() == 0) {
- foreach(var s in StagesDAG.Successors(n)) {
- Debug.Assert(s != n);
- Debug.Assert(Stage != done[s]);
- Dependences.AddEdge(Stage, done[s]);
- }
- foreach (var a in n)
- {
- Stage.AddAnnotation(a);
- }
- AssignedToThisStage.Add(n);
- }
- }
-
- foreach(var n in AssignedToThisStage) {
- done[n] = Stage;
- }
- }
- return new StagedHoudiniPlan(Dependences);
- }
-
- private StagedHoudiniPlan ComputeBalancedStages()
- {
- Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
- var done = new Dictionary<SCC<string>, ScheduledStage>();
- done[GetStartNodeOfStagesDAG()] = new ScheduledStage(0, new HashSet<string>());
-
- int maxStageSize = 200;
-
- for(int stageId = 1; done.Count() != StagesDAG.Nodes.Count(); stageId++)
- {
- int stageSize = 0;
- ScheduledStage Stage = new ScheduledStage(stageId, new HashSet<string>());
- HashSet<SCC<string>> AddedToThisStage = new HashSet<SCC<string>>();
-
- foreach (var n in StagesDAG.Nodes.Where(Item => !done.ContainsKey(Item)))
- {
- if(stageSize + n.Count() > maxStageSize) {
- continue;
- }
- if(StagesDAG.Successors(n).Where(Item => !done.ContainsKey(Item)).Count() == 0) {
- foreach (var c in n)
- {
- Stage.AddAnnotation(c);
- stageSize++;
- }
- foreach(var s in StagesDAG.Successors(n)) {
- Dependences.AddEdge(Stage, done[s]);
- }
- AddedToThisStage.Add(n);
- }
- }
- foreach(var n in AddedToThisStage) {
- done[n] = Stage;
- }
- if(stageSize == 0) {
- maxStageSize *= 2;
- }
- }
- return new StagedHoudiniPlan(Dependences);
- }
-
- private StagedHoudiniPlan ComputeFineStages()
- {
- Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
- var done = new Dictionary<SCC<string>, ScheduledStage>();
-
- List<SCC<string>> components = StagesDAG.TopologicalSort().ToList();
- components.Reverse();
-
- for (int i = 0; i < components.Count(); i++)
- {
- ScheduledStage Stage = new ScheduledStage(i, new HashSet<string>());
- done[components[i]] = Stage;
- foreach (var c in components[i])
- {
- Stage.AddAnnotation(c);
- }
- foreach(var s in StagesDAG.Successors(components[i])) {
- Dependences.AddEdge(Stage, done[s]);
- }
- }
- return new StagedHoudiniPlan(Dependences);
- }
-
- private SCC<string> GetStartNodeOfStagesDAG()
- {
- return StagesDAG.Nodes.Where(Item => StagesDAG.Successors(Item).Count() == 0).
- ToList()[0];
- }
-
- private bool NoStages()
- {
- return AllAnnotationIdentifiers().Count() == 0 || StagesDAG.Nodes.Count() == 0;
- }
- }
-
- interface IAnnotationReachabilityChecker {
- bool MayReach(string c, string d);
- }
-
- class DummyAnnotationReachabilityChecker : IAnnotationReachabilityChecker {
- public bool MayReach(string c, string d) {
- return true;
- }
- }
-
- class AnnotationReachabilityChecker : IAnnotationReachabilityChecker {
-
- private enum PrePost {
- PRE, POST
- }
-
- private Program prog;
- private IEnumerable<string> AnnotationIdentifiers;
- private IInterproceduralReachabilityGraph reachabilityGraph;
- private Dictionary<string, HashSet<object>> annotationToOccurences;
-
- internal AnnotationReachabilityChecker(Program prog, IEnumerable<string> AnnotationIdentifiers) {
- this.prog = prog;
- this.AnnotationIdentifiers = AnnotationIdentifiers;
- this.reachabilityGraph = new InterproceduralReachabilityGraph(prog);
- this.annotationToOccurences = new Dictionary<string,HashSet<object>>();
-
- // Add all annotation occurrences in blocks
- foreach(Block b in prog.Blocks()) {
- foreach(var assertCmd in b.Cmds.OfType<AssertCmd>()) {
- string c;
- if(Houdini.MatchCandidate(assertCmd.Expr, AnnotationIdentifiers, out c)) {
- AddAnnotationOccurrence(c, b);
- } else {
- var tag = AnnotationDependenceAnalyser.GetTagFromNonCandidateAttributes(assertCmd.Attributes);
- if (tag != null) {
- AddAnnotationOccurrence(tag, b);
- }
- }
- }
- }
-
- // Add all annotation occurrences in pre and post conditions
- foreach(var proc in prog.NonInlinedProcedures()) {
- foreach(Requires r in proc.Requires) {
- string c;
- if(Houdini.MatchCandidate(r.Condition, AnnotationIdentifiers, out c)) {
- AddAnnotationOccurrence(c, new Tuple<string, PrePost>(proc.Name, PrePost.PRE));
- } else {
- string tag = AnnotationDependenceAnalyser.GetTagFromNonCandidateAttributes(r.Attributes);
- if(tag != null) {
- AddAnnotationOccurrence(tag, new Tuple<string, PrePost>(proc.Name, PrePost.PRE));
- }
- }
- }
- foreach(Ensures e in proc.Ensures) {
- string c;
- if(Houdini.MatchCandidate(e.Condition, AnnotationIdentifiers, out c)) {
- AddAnnotationOccurrence(c, new Tuple<string, PrePost>(proc.Name, PrePost.POST));
- } else {
- string tag = AnnotationDependenceAnalyser.GetTagFromNonCandidateAttributes(e.Attributes);
- if(tag != null) {
- AddAnnotationOccurrence(tag, new Tuple<string, PrePost>(proc.Name, PrePost.PRE));
- }
- }
- }
- }
-
- }
-
- private void AddAnnotationOccurrence(string c, object o) {
- Debug.Assert(o is Block || o is Tuple<string, PrePost>);
- if(!annotationToOccurences.ContainsKey(c)) {
- annotationToOccurences[c] = new HashSet<object>();
- }
- annotationToOccurences[c].Add(o);
- }
-
- public bool MayReach(string c, string d) {
- foreach(object cOccurrence in annotationToOccurences[c]) {
- foreach(object dOccurrence in annotationToOccurences[d]) {
- if(OccurrencesMayReach(cOccurrence, dOccurrence)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private bool OccurrencesMayReach(object cOccurrence, object dOccurrence) {
- Debug.Assert(cOccurrence is Block || cOccurrence is Tuple<string, PrePost>);
- Debug.Assert(dOccurrence is Block || dOccurrence is Tuple<string, PrePost>);
-
- Block cInterproceduralBlock = GetInterproceduralBlock(cOccurrence);
- Block dInterproceduralBlock = GetInterproceduralBlock(dOccurrence);
-
- return reachabilityGraph.MayReach(cInterproceduralBlock, dInterproceduralBlock);
-
- }
-
- private Block GetInterproceduralBlock(object cOccurrence)
- {
- Debug.Assert(cOccurrence is Block || cOccurrence is Tuple<string, PrePost>);
-
- var stringPrePostPair = cOccurrence as Tuple<string, PrePost>;
- if(stringPrePostPair != null) {
- if(stringPrePostPair.Item2 == PrePost.PRE) {
- return reachabilityGraph.GetNewEntryBlock(stringPrePostPair.Item1);
- } else {
- return reachabilityGraph.GetNewExitBlock(stringPrePostPair.Item1);
- }
- }
-
- return reachabilityGraph.GetNewBlock((Block)cOccurrence);
-
- }
- }
-
- class AnnotationInstance {
- public string AnnotationIdentifier;
- public string Proc;
- public Expr Expr;
-
- internal AnnotationInstance(string AnnotationIdentifier, string Proc, Expr Expr) {
- this.AnnotationIdentifier = AnnotationIdentifier;
- this.Proc = Proc;
- this.Expr = Expr;
- }
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie.GraphUtil;
+using Microsoft.Basetypes;
+using System.Diagnostics;
+
+namespace Microsoft.Boogie.Houdini {
+
+ public class AnnotationDependenceAnalyser {
+
+ private const string COARSE_STAGES = "COARSE";
+ private const string FINE_STAGES = "FINE";
+ private const string BALANCED_STAGES = "BALANCED";
+
+ private Program prog;
+ private IVariableDependenceAnalyser varDepAnalyser;
+ private IEnumerable<string> CandidateIdentifiers; // Candidate Boolean names
+ private IEnumerable<string> NonCandidateIdentifiers; // Additional names introduced for non-candidate annotations
+ private Dictionary<string, HashSet<VariableDescriptor>> annotationDependsOn;
+ private Dictionary<VariableDescriptor, HashSet<string>> variableDirectlyReferredToByAnnotations;
+ private Graph<string> AnnotationDependences;
+ private StronglyConnectedComponents<string> SCCs;
+ private Graph<SCC<string>> StagesDAG;
+ private StagedHoudiniPlan Plan;
+
+ public AnnotationDependenceAnalyser(Program prog) {
+ this.prog = prog;
+ this.varDepAnalyser = new VariableDependenceAnalyser(prog);
+ varDepAnalyser.Analyse();
+ }
+
+ public void Analyse() {
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Annotation dependence analysis: Getting annotations");
+ }
+
+ CandidateIdentifiers = GetCandidates();
+ NonCandidateIdentifiers = GetNonCandidateAnnotations();
+
+ DetermineAnnotationVariableDependences();
+
+ ConstructAnnotationDependenceGraph();
+
+ ConstructStagesDAG();
+
+ }
+
+ private IEnumerable<string> AllAnnotationIdentifiers() {
+ HashSet<string> Result = new HashSet<string>();
+ foreach (var c in CandidateIdentifiers) {
+ Result.Add(c);
+ }
+ foreach (var a in NonCandidateIdentifiers) {
+ Result.Add(a);
+ }
+ return Result;
+ }
+
+ private void ConstructStagesDAG()
+ {
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Annotation dependence analysis: Computing SCCs");
+ }
+
+ Adjacency<string> next = new Adjacency<string>(AnnotationDependences.Successors);
+ Adjacency<string> prev = new Adjacency<string>(AnnotationDependences.Predecessors);
+ SCCs = new StronglyConnectedComponents<string>(
+ AnnotationDependences.Nodes, next, prev);
+ SCCs.Compute();
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Annotation dependence analysis: Building stages DAG");
+ }
+
+ Dictionary<string, SCC<string>> rep = new Dictionary<string, SCC<string>>();
+ foreach (var scc in SCCs)
+ {
+ foreach (var s in scc)
+ {
+ rep[s] = scc;
+ }
+ }
+
+ StagesDAG = new Graph<SCC<string>>();
+
+ foreach (var edge in AnnotationDependences.Edges)
+ {
+ if (rep[edge.Item1] != rep[edge.Item2])
+ {
+ StagesDAG.AddEdge(rep[edge.Item1], rep[edge.Item2]);
+ }
+ }
+
+ SCC<string> dummy = new SCC<string>();
+ foreach (var scc in SCCs)
+ {
+ StagesDAG.AddEdge(scc, dummy);
+ }
+ }
+
+ private void ConstructAnnotationDependenceGraph()
+ {
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Annotation dependence analysis: Building dependence graph");
+ }
+
+ IAnnotationReachabilityChecker reachabilityChecker;
+
+ if(CommandLineOptions.Clo.StagedHoudiniReachabilityAnalysis) {
+ reachabilityChecker = new AnnotationReachabilityChecker(prog, AllAnnotationIdentifiers());
+ } else {
+ reachabilityChecker = new DummyAnnotationReachabilityChecker();
+ }
+
+ AnnotationDependences = new Graph<string>();
+ foreach (var c in AllAnnotationIdentifiers())
+ {
+ AnnotationDependences.AddEdge(c, c);
+ foreach (var vd in annotationDependsOn[c])
+ {
+ if (variableDirectlyReferredToByAnnotations.ContainsKey(vd))
+ {
+ foreach (var d in variableDirectlyReferredToByAnnotations[vd])
+ {
+ if(reachabilityChecker.MayReach(d, c))
+ {
+ AnnotationDependences.AddEdge(c, d);
+ }
+ }
+ }
+ }
+ }
+
+ if(CommandLineOptions.Clo.StagedHoudiniMergeIgnoredAnnotations) {
+ MergeIgnoredAnnotations();
+ }
+
+ }
+
+ private void MergeIgnoredAnnotations()
+ {
+ var IgnoredAnnotationsToVariables = new Dictionary<string, HashSet<Variable>>();
+ foreach(var c in AllAnnotationIdentifiers()) {
+ IgnoredAnnotationsToVariables[c] = new HashSet<Variable>();
+ }
+ foreach(var ci in AnnotationInstances()) {
+ if(!IgnoredAnnotationsToVariables.ContainsKey(ci.AnnotationIdentifier)) {
+ continue;
+ }
+ VariableCollector vc = new VariableCollector();
+ vc.Visit(ci.Expr);
+ if(vc.usedVars.Select(Item => varDepAnalyser.VariableRelevantToAnalysis(Item, ci.Proc)).Count() != 0) {
+ continue;
+ }
+ foreach(var v in vc.usedVars) {
+ if(varDepAnalyser.Ignoring(v, ci.Proc)) {
+ IgnoredAnnotationsToVariables[ci.AnnotationIdentifier].Add(v);
+ }
+ }
+ }
+ foreach(var c in IgnoredAnnotationsToVariables.Keys) {
+ foreach(var d in IgnoredAnnotationsToVariables.Keys) {
+ if(c == d) {
+ continue;
+ }
+ if(IgnoredAnnotationsToVariables[c].Equals(IgnoredAnnotationsToVariables[d])) {
+ AnnotationDependences.AddEdge(c, d);
+ }
+ }
+ }
+ }
+
+
+
+ private void DetermineAnnotationVariableDependences()
+ {
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Annotation dependence analysis: Working out what annotations depend on");
+ }
+ annotationDependsOn = new Dictionary<string, HashSet<VariableDescriptor>>();
+ variableDirectlyReferredToByAnnotations = new Dictionary<VariableDescriptor, HashSet<string>>();
+ foreach (var c in AllAnnotationIdentifiers())
+ {
+ annotationDependsOn[c] = new HashSet<VariableDescriptor>();
+ }
+
+ foreach(var annotationInstance in AnnotationInstances()) {
+ AddDependences(annotationInstance);
+ }
+
+ }
+
+ private IEnumerable<AnnotationInstance> AnnotationInstances()
+ {
+ foreach (var impl in prog.Implementations)
+ {
+ foreach (PredicateCmd p in impl.Blocks.SelectMany(Item => Item.Cmds).OfType<PredicateCmd>())
+ {
+ string c;
+ if(Houdini.MatchCandidate(p.Expr, CandidateIdentifiers, out c)) {
+ yield return new AnnotationInstance(c, impl.Name, p.Expr);
+ } else if((p is AssertCmd) && QKeyValue.FindBoolAttribute(p.Attributes, "originated_from_invariant")) {
+ var tag = GetTagFromNonCandidateAttributes(p.Attributes);
+ if (tag != null) {
+ yield return new AnnotationInstance(tag, impl.Name, p.Expr);
+ }
+ }
+ }
+ }
+
+ foreach (var proc in prog.NonInlinedProcedures())
+ {
+ foreach (Requires r in proc.Requires)
+ {
+ string c;
+ if(Houdini.MatchCandidate(r.Condition, CandidateIdentifiers, out c)) {
+ yield return new AnnotationInstance(c, proc.Name, r.Condition);
+ } else {
+ var tag = GetTagFromNonCandidateAttributes(r.Attributes);
+ if (tag != null) {
+ yield return new AnnotationInstance(tag, proc.Name, r.Condition);
+ }
+ }
+ }
+ foreach (Ensures e in proc.Ensures)
+ {
+ string c;
+ if(Houdini.MatchCandidate(e.Condition, CandidateIdentifiers, out c)) {
+ yield return new AnnotationInstance(c, proc.Name, e.Condition);
+ } else {
+ var tag = GetTagFromNonCandidateAttributes(e.Attributes);
+ if (tag != null) {
+ yield return new AnnotationInstance(tag, proc.Name, e.Condition);
+ }
+ }
+ }
+ }
+ }
+
+ internal static string GetTagFromNonCandidateAttributes(QKeyValue Attributes)
+ {
+ string tag = QKeyValue.FindStringAttribute(Attributes, "staged_houdini_tag");
+ return tag;
+ }
+
+ private bool FindInDAG(Graph<SCC<string>> DAG, SCC<string> toFind, SCC<string> start) {
+ if (toFind == start) {
+ return true;
+ }
+ foreach (var n in DAG.Successors(start)) {
+ if (FindInDAG(DAG, toFind, n)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void AddDependences(AnnotationInstance ci) {
+ VariableCollector vc = new VariableCollector();
+ vc.VisitExpr(ci.Expr);
+
+ foreach (var v in vc.usedVars.Where(Item => varDepAnalyser.VariableRelevantToAnalysis(Item, ci.Proc))) {
+ VariableDescriptor vd =
+ varDepAnalyser.MakeDescriptor(ci.Proc, v);
+ if (!variableDirectlyReferredToByAnnotations.ContainsKey(vd)) {
+ variableDirectlyReferredToByAnnotations[vd] = new HashSet<string>();
+ }
+ variableDirectlyReferredToByAnnotations[vd].Add(ci.AnnotationIdentifier);
+
+ foreach (var w in varDepAnalyser.DependsOn(vd)) {
+ annotationDependsOn[ci.AnnotationIdentifier].Add(w);
+ }
+ }
+ }
+
+ private bool IsStageDependence(SCC<string> Src, SCC<string> Dst) {
+ foreach (var c in Src) {
+ foreach (var d in AnnotationDependences.Successors(c)) {
+ if (Dst.Contains(d)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public void dump() {
+
+ if(CommandLineOptions.Clo.DebugStagedHoudini) {
+ varDepAnalyser.dump();
+
+ Console.WriteLine("Annotations and the variables they depend on");
+ Console.WriteLine("============================================");
+ foreach (var entry in annotationDependsOn) {
+ Console.WriteLine(entry.Key + " <- ");
+ foreach (var vd in entry.Value) {
+ Console.WriteLine(" " + vd + ", ");
+ }
+ }
+
+ Console.WriteLine("");
+
+ Console.WriteLine("Variables and the annotations that directly refer to them");
+ Console.WriteLine("========================================================");
+ foreach (var entry in variableDirectlyReferredToByAnnotations) {
+ Console.WriteLine(entry.Key + " <- ");
+ foreach (var annotation in entry.Value) {
+ Console.WriteLine(" " + annotation + ", ");
+ }
+ }
+
+ Console.WriteLine("");
+
+ Console.WriteLine("Annotation dependence graph");
+ Console.WriteLine("==========================");
+ foreach (var c in AnnotationDependences.Nodes) {
+ Console.WriteLine(c + " <- ");
+ foreach (var d in AnnotationDependences.Successors(c)) {
+ Console.WriteLine(" " + d);
+ }
+ }
+ }
+
+ Console.WriteLine("");
+
+ Console.WriteLine("Strongly connected components");
+ Console.WriteLine("=============================");
+
+ List<SCC<string>> Components = StagesDAG.TopologicalSort().ToList();
+
+ for (int i = 0; i < Components.Count(); i++) {
+ Console.Write(i + ": ");
+ DumpSCC(Components[i]);
+ Console.WriteLine(); Console.WriteLine();
+ }
+
+ Console.WriteLine("Stages DAG");
+ Console.WriteLine("==========");
+ for (int i = 0; i < Components.Count(); i++) {
+ Console.Write(i + " -> { ");
+ bool first = true;
+ foreach (var d in StagesDAG.Successors(Components[i])) {
+ if (first) {
+ first = false;
+ }
+ else {
+ Console.Write(", ");
+ }
+ Console.Write(Components.IndexOf(d));
+ }
+ Console.WriteLine(" }");
+ }
+
+ }
+
+ private static void DumpSCC(SCC<string> component) {
+ var sortedComponent = component.ToList();
+ sortedComponent.Sort();
+ Console.Write("{ ");
+ bool first = true;
+ foreach (var s in sortedComponent) {
+ if (first) {
+ first = false;
+ }
+ else {
+ Console.Write(", ");
+ }
+ Console.Write(s);
+ }
+ Console.Write(" }");
+ }
+
+ private bool OnlyRefersToConstants(Expr e) {
+ VariableCollector vc = new VariableCollector();
+ vc.Visit(e);
+ return vc.usedVars.OfType<Constant>().Count() == vc.usedVars.Count();
+ }
+
+ private IEnumerable<string> GetNonCandidateAnnotations() {
+ var Result = new HashSet<string>();
+ int Counter = 0;
+ foreach(var Assertion in prog.Blocks().SelectMany(Item => Item.Cmds).
+ OfType<AssertCmd>()) {
+
+ string unused;
+ if (Houdini.MatchCandidate(Assertion.Expr, CandidateIdentifiers, out unused)) {
+ continue;
+ }
+
+ if (!QKeyValue.FindBoolAttribute(Assertion.Attributes, "originated_from_invariant")) {
+ continue;
+ }
+
+ if (OnlyRefersToConstants(Assertion.Expr)) {
+ continue;
+ }
+
+ string Tag = "staged_houdini_tag_" + Counter;
+ Result.Add(Tag);
+ Assertion.Attributes = new QKeyValue(Token.NoToken, "staged_houdini_tag",
+ new List<object> { Tag }, Assertion.Attributes);
+ Counter++;
+ }
+
+ foreach(var Req in prog.NonInlinedProcedures().SelectMany(Item => Item.Requires)) {
+
+ string unused;
+ if (Houdini.MatchCandidate(Req.Condition, CandidateIdentifiers, out unused)) {
+ continue;
+ }
+
+ if (OnlyRefersToConstants(Req.Condition)) {
+ continue;
+ }
+
+ string Tag = "staged_houdini_tag_" + Counter;
+ Result.Add(Tag);
+ Req.Attributes = new QKeyValue(Token.NoToken, "staged_houdini_tag",
+ new List<object> { Tag }, Req.Attributes);
+ Counter++;
+
+ }
+
+ foreach(var Ens in prog.NonInlinedProcedures().SelectMany(Item => Item.Ensures)) {
+
+ string unused;
+ if (Houdini.MatchCandidate(Ens.Condition, CandidateIdentifiers, out unused)) {
+ continue;
+ }
+
+ if (OnlyRefersToConstants(Ens.Condition)) {
+ continue;
+ }
+
+ string Tag = "staged_houdini_tag_" + Counter;
+ Result.Add(Tag);
+ Ens.Attributes = new QKeyValue(Token.NoToken, "staged_houdini_tag",
+ new List<object> { Tag }, Ens.Attributes);
+ Counter++;
+
+ }
+
+ return Result;
+ }
+
+ private IEnumerable<string> GetCandidates() {
+ return prog.Variables.Where(Item =>
+ QKeyValue.FindBoolAttribute(Item.Attributes, "existential")).Select(Item => Item.Name);
+ }
+
+
+ public StagedHoudiniPlan ApplyStages() {
+
+ if (NoStages())
+ {
+ Debug.Assert(false);
+ var TrivialGraph = new Graph<ScheduledStage>();
+ TrivialGraph.AddSource(new ScheduledStage(0, new HashSet<string>()));
+ return new StagedHoudiniPlan(TrivialGraph);
+ }
+
+ #region Assign annotations to stages at a given level of granularity
+
+ switch(CommandLineOptions.Clo.StagedHoudini) {
+ case COARSE_STAGES:
+ Plan = ComputeCoarseStages();
+ break;
+ case FINE_STAGES:
+ Plan = ComputeFineStages();
+ break;
+ case BALANCED_STAGES:
+ Plan = ComputeBalancedStages();
+ break;
+ default:
+ Debug.Assert(false);
+ Plan = null;
+ break;
+ }
+
+ foreach(var c in AllAnnotationIdentifiers()) {
+ Debug.Assert(Plan.StageForAnnotation(c) != null);
+ }
+ #endregion
+
+ #region Generate boolean variables to control stages
+ var stageToActiveBoolean = new Dictionary<int, Constant>();
+ var stageToCompleteBoolean = new Dictionary<int, Constant>();
+
+ foreach (var stage in Plan)
+ {
+ var stageActive = new Constant(Token.NoToken,
+ new TypedIdent(Token.NoToken, "_stage_" + stage.GetId() + "_active", Type.Bool),
+ false);
+ stageActive.AddAttribute("stage_active", new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(stage.GetId())) });
+ prog.AddTopLevelDeclaration(stageActive);
+ stageToActiveBoolean[stage.GetId()] = stageActive;
+
+ var stageComplete = new Constant(Token.NoToken,
+ new TypedIdent(Token.NoToken, "_stage_" + stage.GetId() + "_complete", Type.Bool),
+ false);
+ stageComplete.AddAttribute("stage_complete", new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(stage.GetId())) });
+ prog.AddTopLevelDeclaration(stageComplete);
+ stageToCompleteBoolean[stage.GetId()] = stageComplete;
+ }
+ #endregion
+
+ #region Adapt annotation assertions to take account of stages
+ foreach (var b in prog.Implementations.Select(Item => Item.Blocks).SelectMany(Item => Item))
+ {
+ List<Cmd> newCmds = new List<Cmd>();
+ foreach (var cmd in b.Cmds)
+ {
+ var a = cmd as AssertCmd;
+ string c;
+ if (a != null) {
+ if (Houdini.MatchCandidate(a.Expr, CandidateIdentifiers, out c))
+ {
+ newCmds.Add(new AssertCmd(a.tok, Houdini.AddConditionToCandidate(a.Expr,
+ Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(c).GetId()]), c), a.Attributes));
+ newCmds.Add(new AssumeCmd(a.tok, Houdini.AddConditionToCandidate(a.Expr,
+ Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(c).GetId()]), c), a.Attributes));
+ } else if (QKeyValue.FindBoolAttribute(a.Attributes, "originated_from_invariant")) {
+ string tag = GetTagFromNonCandidateAttributes(a.Attributes);
+ if (tag == null) {
+ newCmds.Add(a);
+ } else {
+ newCmds.Add(new AssertCmd(a.tok, Expr.Imp(
+ Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(tag).GetId()]), a.Expr),
+ a.Attributes));
+ newCmds.Add(new AssumeCmd(a.tok, Expr.Imp(
+ Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(tag).GetId()]), a.Expr),
+ a.Attributes));
+ }
+ }
+ }
+ else
+ {
+ newCmds.Add(cmd);
+ }
+ }
+ b.Cmds = newCmds;
+ }
+ #endregion
+
+ #region Adapt pre/postconditions to take account of stages
+ foreach (var p in prog.NonInlinedProcedures())
+ {
+
+ #region Handle the preconditions
+ {
+ List<Requires> newRequires = new List<Requires>();
+ foreach(Requires r in p.Requires) {
+ string c;
+ if (Houdini.MatchCandidate(r.Condition, CandidateIdentifiers, out c)) {
+ newRequires.Add(new Requires(r.tok, false,
+ Houdini.AddConditionToCandidate(r.Condition,
+ Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(c).GetId()]), c),
+ r.Comment, r.Attributes));
+ newRequires.Add(new Requires(r.tok, true,
+ Houdini.AddConditionToCandidate(r.Condition,
+ Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(c).GetId()]), c),
+ r.Comment, r.Attributes));
+ } else {
+ string tag = GetTagFromNonCandidateAttributes(r.Attributes);
+ if (tag == null) {
+ newRequires.Add(r);
+ } else {
+ newRequires.Add(new Requires(r.tok, false,
+ Expr.Imp(Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(tag).GetId()]), r.Condition),
+ r.Comment, r.Attributes));
+ newRequires.Add(new Requires(r.tok, true,
+ Expr.Imp(Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(tag).GetId()]), r.Condition),
+ r.Comment, r.Attributes));
+ }
+ }
+ }
+ p.Requires = newRequires;
+ }
+ #endregion
+
+ #region Handle the postconditions
+ {
+ List<Ensures> newEnsures = new List<Ensures>();
+ foreach(Ensures e in p.Ensures) {
+ string c;
+ if (Houdini.MatchCandidate(e.Condition, CandidateIdentifiers, out c)) {
+ int stage = Plan.StageForAnnotation(c).GetId();
+ newEnsures.Add(new Ensures(e.tok, false,
+ Houdini.AddConditionToCandidate(e.Condition,
+ Expr.Ident(stageToActiveBoolean[stage]), c),
+ e.Comment, e.Attributes));
+ newEnsures.Add(new Ensures(e.tok, true,
+ Houdini.AddConditionToCandidate(e.Condition,
+ Expr.Ident(stageToCompleteBoolean[stage]), c),
+ e.Comment, e.Attributes));
+ } else {
+ string tag = GetTagFromNonCandidateAttributes(e.Attributes);
+ if (tag == null) {
+ newEnsures.Add(e);
+ } else {
+ newEnsures.Add(new Ensures(e.tok, false,
+ Expr.Imp(Expr.Ident(stageToActiveBoolean[Plan.StageForAnnotation(tag).GetId()]), e.Condition),
+ e.Comment, e.Attributes));
+ newEnsures.Add(new Ensures(e.tok, true,
+ Expr.Imp(Expr.Ident(stageToCompleteBoolean[Plan.StageForAnnotation(tag).GetId()]), e.Condition),
+ e.Comment, e.Attributes));
+ }
+ }
+ }
+ p.Ensures = newEnsures;
+ }
+ #endregion
+
+ }
+ #endregion
+
+ return Plan;
+
+ }
+
+ private int FindLargestStage() {
+ return StagesDAG.Nodes.Select(Item => Item.Count()).Max();
+ }
+
+
+ private StagedHoudiniPlan ComputeCoarseStages()
+ {
+ foreach(var n in StagesDAG.Nodes) {
+ Debug.Assert(!StagesDAG.Successors(n).Contains(n));
+ }
+
+ Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
+
+ var done = new Dictionary<SCC<string>, ScheduledStage>();
+ done[GetStartNodeOfStagesDAG()] = new ScheduledStage(0, new HashSet<string>());
+
+ for(int stageId = 1; done.Count() != StagesDAG.Nodes.Count(); stageId++)
+ {
+ var Stage = new ScheduledStage(stageId, new HashSet<string>());
+ HashSet<SCC<string>> AssignedToThisStage = new HashSet<SCC<string>>();
+
+ foreach (var n in StagesDAG.Nodes.Where(Item => !done.ContainsKey(Item)))
+ {
+ if(StagesDAG.Successors(n).Where(Item => !done.ContainsKey(Item)).Count() == 0) {
+ foreach(var s in StagesDAG.Successors(n)) {
+ Debug.Assert(s != n);
+ Debug.Assert(Stage != done[s]);
+ Dependences.AddEdge(Stage, done[s]);
+ }
+ foreach (var a in n)
+ {
+ Stage.AddAnnotation(a);
+ }
+ AssignedToThisStage.Add(n);
+ }
+ }
+
+ foreach(var n in AssignedToThisStage) {
+ done[n] = Stage;
+ }
+ }
+ return new StagedHoudiniPlan(Dependences);
+ }
+
+ private StagedHoudiniPlan ComputeBalancedStages()
+ {
+ Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
+ var done = new Dictionary<SCC<string>, ScheduledStage>();
+ done[GetStartNodeOfStagesDAG()] = new ScheduledStage(0, new HashSet<string>());
+
+ int maxStageSize = 200;
+
+ for(int stageId = 1; done.Count() != StagesDAG.Nodes.Count(); stageId++)
+ {
+ int stageSize = 0;
+ ScheduledStage Stage = new ScheduledStage(stageId, new HashSet<string>());
+ HashSet<SCC<string>> AddedToThisStage = new HashSet<SCC<string>>();
+
+ foreach (var n in StagesDAG.Nodes.Where(Item => !done.ContainsKey(Item)))
+ {
+ if(stageSize + n.Count() > maxStageSize) {
+ continue;
+ }
+ if(StagesDAG.Successors(n).Where(Item => !done.ContainsKey(Item)).Count() == 0) {
+ foreach (var c in n)
+ {
+ Stage.AddAnnotation(c);
+ stageSize++;
+ }
+ foreach(var s in StagesDAG.Successors(n)) {
+ Dependences.AddEdge(Stage, done[s]);
+ }
+ AddedToThisStage.Add(n);
+ }
+ }
+ foreach(var n in AddedToThisStage) {
+ done[n] = Stage;
+ }
+ if(stageSize == 0) {
+ maxStageSize *= 2;
+ }
+ }
+ return new StagedHoudiniPlan(Dependences);
+ }
+
+ private StagedHoudiniPlan ComputeFineStages()
+ {
+ Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
+ var done = new Dictionary<SCC<string>, ScheduledStage>();
+
+ List<SCC<string>> components = StagesDAG.TopologicalSort().ToList();
+ components.Reverse();
+
+ for (int i = 0; i < components.Count(); i++)
+ {
+ ScheduledStage Stage = new ScheduledStage(i, new HashSet<string>());
+ done[components[i]] = Stage;
+ foreach (var c in components[i])
+ {
+ Stage.AddAnnotation(c);
+ }
+ foreach(var s in StagesDAG.Successors(components[i])) {
+ Dependences.AddEdge(Stage, done[s]);
+ }
+ }
+ return new StagedHoudiniPlan(Dependences);
+ }
+
+ private SCC<string> GetStartNodeOfStagesDAG()
+ {
+ return StagesDAG.Nodes.Where(Item => StagesDAG.Successors(Item).Count() == 0).
+ ToList()[0];
+ }
+
+ private bool NoStages()
+ {
+ return AllAnnotationIdentifiers().Count() == 0 || StagesDAG.Nodes.Count() == 0;
+ }
+ }
+
+ interface IAnnotationReachabilityChecker {
+ bool MayReach(string c, string d);
+ }
+
+ class DummyAnnotationReachabilityChecker : IAnnotationReachabilityChecker {
+ public bool MayReach(string c, string d) {
+ return true;
+ }
+ }
+
+ class AnnotationReachabilityChecker : IAnnotationReachabilityChecker {
+
+ private enum PrePost {
+ PRE, POST
+ }
+
+ private Program prog;
+ private IEnumerable<string> AnnotationIdentifiers;
+ private IInterproceduralReachabilityGraph reachabilityGraph;
+ private Dictionary<string, HashSet<object>> annotationToOccurences;
+
+ internal AnnotationReachabilityChecker(Program prog, IEnumerable<string> AnnotationIdentifiers) {
+ this.prog = prog;
+ this.AnnotationIdentifiers = AnnotationIdentifiers;
+ this.reachabilityGraph = new InterproceduralReachabilityGraph(prog);
+ this.annotationToOccurences = new Dictionary<string,HashSet<object>>();
+
+ // Add all annotation occurrences in blocks
+ foreach(Block b in prog.Blocks()) {
+ foreach(var assertCmd in b.Cmds.OfType<AssertCmd>()) {
+ string c;
+ if(Houdini.MatchCandidate(assertCmd.Expr, AnnotationIdentifiers, out c)) {
+ AddAnnotationOccurrence(c, b);
+ } else {
+ var tag = AnnotationDependenceAnalyser.GetTagFromNonCandidateAttributes(assertCmd.Attributes);
+ if (tag != null) {
+ AddAnnotationOccurrence(tag, b);
+ }
+ }
+ }
+ }
+
+ // Add all annotation occurrences in pre and post conditions
+ foreach(var proc in prog.NonInlinedProcedures()) {
+ foreach(Requires r in proc.Requires) {
+ string c;
+ if(Houdini.MatchCandidate(r.Condition, AnnotationIdentifiers, out c)) {
+ AddAnnotationOccurrence(c, new Tuple<string, PrePost>(proc.Name, PrePost.PRE));
+ } else {
+ string tag = AnnotationDependenceAnalyser.GetTagFromNonCandidateAttributes(r.Attributes);
+ if(tag != null) {
+ AddAnnotationOccurrence(tag, new Tuple<string, PrePost>(proc.Name, PrePost.PRE));
+ }
+ }
+ }
+ foreach(Ensures e in proc.Ensures) {
+ string c;
+ if(Houdini.MatchCandidate(e.Condition, AnnotationIdentifiers, out c)) {
+ AddAnnotationOccurrence(c, new Tuple<string, PrePost>(proc.Name, PrePost.POST));
+ } else {
+ string tag = AnnotationDependenceAnalyser.GetTagFromNonCandidateAttributes(e.Attributes);
+ if(tag != null) {
+ AddAnnotationOccurrence(tag, new Tuple<string, PrePost>(proc.Name, PrePost.PRE));
+ }
+ }
+ }
+ }
+
+ }
+
+ private void AddAnnotationOccurrence(string c, object o) {
+ Debug.Assert(o is Block || o is Tuple<string, PrePost>);
+ if(!annotationToOccurences.ContainsKey(c)) {
+ annotationToOccurences[c] = new HashSet<object>();
+ }
+ annotationToOccurences[c].Add(o);
+ }
+
+ public bool MayReach(string c, string d) {
+ foreach(object cOccurrence in annotationToOccurences[c]) {
+ foreach(object dOccurrence in annotationToOccurences[d]) {
+ if(OccurrencesMayReach(cOccurrence, dOccurrence)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private bool OccurrencesMayReach(object cOccurrence, object dOccurrence) {
+ Debug.Assert(cOccurrence is Block || cOccurrence is Tuple<string, PrePost>);
+ Debug.Assert(dOccurrence is Block || dOccurrence is Tuple<string, PrePost>);
+
+ Block cInterproceduralBlock = GetInterproceduralBlock(cOccurrence);
+ Block dInterproceduralBlock = GetInterproceduralBlock(dOccurrence);
+
+ return reachabilityGraph.MayReach(cInterproceduralBlock, dInterproceduralBlock);
+
+ }
+
+ private Block GetInterproceduralBlock(object cOccurrence)
+ {
+ Debug.Assert(cOccurrence is Block || cOccurrence is Tuple<string, PrePost>);
+
+ var stringPrePostPair = cOccurrence as Tuple<string, PrePost>;
+ if(stringPrePostPair != null) {
+ if(stringPrePostPair.Item2 == PrePost.PRE) {
+ return reachabilityGraph.GetNewEntryBlock(stringPrePostPair.Item1);
+ } else {
+ return reachabilityGraph.GetNewExitBlock(stringPrePostPair.Item1);
+ }
+ }
+
+ return reachabilityGraph.GetNewBlock((Block)cOccurrence);
+
+ }
+ }
+
+ class AnnotationInstance {
+ public string AnnotationIdentifier;
+ public string Proc;
+ public Expr Expr;
+
+ internal AnnotationInstance(string AnnotationIdentifier, string Proc, Expr Expr) {
+ this.AnnotationIdentifier = AnnotationIdentifier;
+ this.Proc = Proc;
+ this.Expr = Expr;
+ }
+ }
+
+}
diff --git a/Source/Houdini/Checker.cs b/Source/Houdini/Checker.cs
index 30056d99..73842019 100644
--- a/Source/Houdini/Checker.cs
+++ b/Source/Houdini/Checker.cs
@@ -1,456 +1,457 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Diagnostics.Contracts;
-using System.Collections.Generic;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Basetypes;
-using System.Collections;
-using System.IO;
-using System.Threading;
-using VC;
-using System.Linq;
-
-namespace Microsoft.Boogie.Houdini {
- public class ExistentialConstantCollector : ReadOnlyVisitor {
- public static void CollectHoudiniConstants(Houdini houdini, Implementation impl, out ExistentialConstantCollector collector)
- {
- collector = new ExistentialConstantCollector(houdini);
- collector.impl = impl;
- collector.VisitImplementation(impl);
- }
-
- private ExistentialConstantCollector(Houdini houdini) {
- this.houdini = houdini;
- this.houdiniAssertConstants = new HashSet<Variable>();
- this.houdiniAssumeConstants = new HashSet<Variable>();
-
- this.explainNegative = new HashSet<Variable>();
- this.explainPositive = new HashSet<Variable>();
- this.constToControl = new Dictionary<string, Tuple<Variable, Variable>>();
- }
- private Houdini houdini;
- public HashSet<Variable> houdiniAssertConstants;
- public HashSet<Variable> houdiniAssumeConstants;
-
- // Explain Houdini stuff
- public HashSet<Variable> explainPositive;
- public HashSet<Variable> explainNegative;
- public Dictionary<string, Tuple<Variable, Variable>> constToControl;
- Implementation impl;
-
- public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
- AddHoudiniConstant(node);
- return base.VisitAssertRequiresCmd(node);
- }
- public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
- AddHoudiniConstant(node);
- return base.VisitAssertEnsuresCmd(node);
- }
- public override Cmd VisitAssertCmd(AssertCmd node) {
- AddHoudiniConstant(node);
- return base.VisitAssertCmd(node);
- }
- public override Cmd VisitAssumeCmd(AssumeCmd node) {
- AddHoudiniConstant(node);
- return base.VisitAssumeCmd(node);
- }
- private void AddHoudiniConstant(AssertCmd assertCmd)
- {
- Variable houdiniConstant;
- if (houdini.MatchCandidate(assertCmd.Expr, out houdiniConstant))
- houdiniAssertConstants.Add(houdiniConstant);
-
- if (houdiniConstant != null && CommandLineOptions.Clo.ExplainHoudini && !constToControl.ContainsKey(houdiniConstant.Name))
- {
- // For each houdini constant c, create two more constants c_pos and c_neg.
- // Then change the asserted condition (c ==> \phi) to
- // (c ==> (c_pos && (\phi || \not c_neg))
- var control = createNewExplainConstants(houdiniConstant);
- assertCmd.Expr = houdini.InsertCandidateControl(assertCmd.Expr, control.Item1, control.Item2);
- explainPositive.Add(control.Item1);
- explainNegative.Add(control.Item2);
- constToControl.Add(houdiniConstant.Name, control);
- }
- }
- private void AddHoudiniConstant(AssumeCmd assumeCmd)
- {
- Variable houdiniConstant;
- if (houdini.MatchCandidate(assumeCmd.Expr, out houdiniConstant))
- houdiniAssumeConstants.Add(houdiniConstant);
- }
- private Tuple<Variable, Variable> createNewExplainConstants(Variable v)
- {
- Contract.Assert(impl != null);
- Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);
- Variable v1 = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}_{2}", v.Name, impl.Name, "pos"), Microsoft.Boogie.BasicType.Bool));
- Variable v2 = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}_{2}", v.Name, impl.Name, "neg"), Microsoft.Boogie.BasicType.Bool));
-
- return Tuple.Create(v1, v2);
- }
- }
-
-
-
- public class HoudiniSession {
-
- public class HoudiniStatistics {
- public double proverTime = 0;
- public int numProverQueries = 0;
- public double unsatCoreProverTime = 0;
- public int numUnsatCoreProverQueries = 0;
- public int numUnsatCorePrunings = 0;
- }
-
- public string descriptiveName;
- public HoudiniStatistics stats;
- private VCExpr conjecture;
- private ProverInterface.ErrorHandler handler;
- ConditionGeneration.CounterexampleCollector collector;
- HashSet<Variable> unsatCoreSet;
- HashSet<Variable> houdiniConstants;
- public HashSet<Variable> houdiniAssertConstants;
- private HashSet<Variable> houdiniAssumeConstants;
-
- // Extra constants created for ExplainHoudini
- private HashSet<Variable> explainConstantsPositive;
- private HashSet<Variable> explainConstantsNegative;
- private Dictionary<string, Tuple<Variable, Variable>> constantToControl;
-
- public bool InUnsatCore(Variable constant) {
- if (unsatCoreSet == null)
- return true;
- if (unsatCoreSet.Contains(constant))
- return true;
- stats.numUnsatCorePrunings++;
- return false;
- }
-
- public HoudiniSession(Houdini houdini, VCGen vcgen, ProverInterface proverInterface, Program program, Implementation impl, HoudiniStatistics stats, int taskID = -1) {
- this.descriptiveName = impl.Name;
- this.stats = stats;
- collector = new ConditionGeneration.CounterexampleCollector();
- collector.OnProgress("HdnVCGen", 0, 0, 0.0);
-
- vcgen.ConvertCFG2DAG(impl, taskID: taskID);
- ModelViewInfo mvInfo;
- var gotoCmdOrigins = vcgen.PassifyImpl(impl, out mvInfo);
-
- ExistentialConstantCollector ecollector;
- ExistentialConstantCollector.CollectHoudiniConstants(houdini, impl, out ecollector);
- this.houdiniAssertConstants = ecollector.houdiniAssertConstants;
- this.houdiniAssumeConstants = ecollector.houdiniAssumeConstants;
- this.explainConstantsNegative = ecollector.explainNegative;
- this.explainConstantsPositive = ecollector.explainPositive;
- this.constantToControl = ecollector.constToControl;
-
- houdiniConstants = new HashSet<Variable>();
- houdiniConstants.UnionWith(houdiniAssertConstants);
- houdiniConstants.UnionWith(houdiniAssumeConstants);
-
- var exprGen = proverInterface.Context.ExprGen;
- VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
-
- Dictionary<int, Absy> label2absy;
- conjecture = vcgen.GenerateVC(impl, controlFlowVariableExpr, out label2absy, proverInterface.Context);
- if (!CommandLineOptions.Clo.UseLabels) {
- VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
- VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
- conjecture = exprGen.Implies(eqExpr, conjecture);
- }
-
- Macro macro = new Macro(Token.NoToken, descriptiveName, new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Type.Bool), false));
- proverInterface.DefineMacro(macro, conjecture);
- conjecture = exprGen.Function(macro);
-
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local) {
- handler = new VCGen.ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, proverInterface.Context, program);
- }
- else {
- handler = new VCGen.ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, proverInterface.Context, program);
- }
-
- }
-
- private VCExpr BuildAxiom(ProverInterface proverInterface, Dictionary<Variable, bool> currentAssignment) {
- ProverContext proverContext = proverInterface.Context;
- Boogie2VCExprTranslator exprTranslator = proverContext.BoogieExprTranslator;
- VCExpressionGenerator exprGen = proverInterface.VCExprGen;
-
- VCExpr expr = VCExpressionGenerator.True;
-
- foreach (KeyValuePair<Variable, bool> kv in currentAssignment) {
- Variable constant = kv.Key;
- VCExprVar exprVar = exprTranslator.LookupVariable(constant);
- if (kv.Value) {
- expr = exprGen.And(expr, exprVar);
- }
- else {
- expr = exprGen.And(expr, exprGen.Not(exprVar));
- }
- }
-
- if (CommandLineOptions.Clo.ExplainHoudini)
- {
- // default values for ExplainHoudini control variables
- foreach (var constant in explainConstantsNegative.Concat(explainConstantsPositive))
- {
- expr = exprGen.And(expr, exprTranslator.LookupVariable(constant));
- }
- }
-
- /*
- foreach (Variable constant in this.houdiniConstants) {
- VCExprVar exprVar = exprTranslator.LookupVariable(constant);
- if (currentAssignment[constant]) {
- expr = exprGen.And(expr, exprVar);
- }
- else {
- expr = exprGen.And(expr, exprGen.Not(exprVar));
- }
- }
- */
-
- if(CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Houdini assignment axiom: " + expr);
- }
-
- return expr;
- }
-
- public ProverInterface.Outcome Verify(ProverInterface proverInterface, Dictionary<Variable, bool> assignment, out List<Counterexample> errors, int taskID = -1) {
- collector.examples.Clear();
-
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Verifying " + descriptiveName);
- }
- DateTime now = DateTime.UtcNow;
-
- VCExpr vc = proverInterface.VCExprGen.Implies(BuildAxiom(proverInterface, assignment), conjecture);
- proverInterface.BeginCheck(descriptiveName, vc, handler);
- ProverInterface.Outcome proverOutcome = proverInterface.CheckOutcome(handler, taskID: taskID);
-
- double queryTime = (DateTime.UtcNow - now).TotalSeconds;
- stats.proverTime += queryTime;
- stats.numProverQueries++;
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Time taken = " + queryTime);
- }
-
- errors = collector.examples;
- return proverOutcome;
- }
-
- // MAXSAT
- public void Explain(ProverInterface proverInterface,
- Dictionary<Variable, bool> assignment, Variable refutedConstant)
- {
- Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);
-
- collector.examples.Clear();
-
- // debugging
- houdiniAssertConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
- houdiniAssumeConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
- Contract.Assert(assignment.ContainsKey(refutedConstant));
- Contract.Assert(houdiniAssertConstants.Contains(refutedConstant));
-
- var hardAssumptions = new List<VCExpr>();
- var softAssumptions = new List<VCExpr>();
-
- Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
- VCExpressionGenerator exprGen = proverInterface.VCExprGen;
- var controlExpr = VCExpressionGenerator.True;
-
- foreach (var tup in assignment)
- {
- Variable constant = tup.Key;
- VCExprVar exprVar = exprTranslator.LookupVariable(constant);
- var val = tup.Value;
-
- if (houdiniAssumeConstants.Contains(constant))
- {
- if (tup.Value)
- hardAssumptions.Add(exprVar);
- else
- // Previously removed assumed candidates are the soft constraints
- softAssumptions.Add(exprVar);
- }
- else if (houdiniAssertConstants.Contains(constant))
- {
- if (constant == refutedConstant)
- hardAssumptions.Add(exprVar);
- else
- hardAssumptions.Add(exprGen.Not(exprVar));
- }
- else
- {
- if (tup.Value)
- hardAssumptions.Add(exprVar);
- else
- hardAssumptions.Add(exprGen.Not(exprVar));
- }
-
- // For an asserted condition (c ==> \phi),
- // ExplainHoudini's extra control constants (c_pos, c_neg) are used as follows:
- // (true, true): "assert \phi"
- // (false, _): "assert false"
- // (true, false): "assert true"
- if (constant != refutedConstant && constantToControl.ContainsKey(constant.Name))
- {
- var posControl = constantToControl[constant.Name].Item1;
- var negControl = constantToControl[constant.Name].Item2;
-
- // Handle self-recursion
- if (houdiniAssertConstants.Contains(constant) && houdiniAssumeConstants.Contains(constant))
- {
- // disable this assert
- controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprGen.Not(exprTranslator.LookupVariable(negControl))));
- }
- else
- {
- // default values for control variables
- controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprTranslator.LookupVariable(negControl)));
- }
- }
- }
-
- hardAssumptions.Add(exprGen.Not(conjecture));
-
- // default values for control variables
- Contract.Assert(constantToControl.ContainsKey(refutedConstant.Name));
- var pc = constantToControl[refutedConstant.Name].Item1;
- var nc = constantToControl[refutedConstant.Name].Item2;
-
- var controlExprNoop = exprGen.And(controlExpr,
- exprGen.And(exprTranslator.LookupVariable(pc), exprTranslator.LookupVariable(nc)));
-
- var controlExprFalse = exprGen.And(controlExpr,
- exprGen.And(exprGen.Not(exprTranslator.LookupVariable(pc)), exprGen.Not(exprTranslator.LookupVariable(nc))));
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Verifying (MaxSat) " + descriptiveName);
- }
- DateTime now = DateTime.UtcNow;
-
- var el = CommandLineOptions.Clo.ProverCCLimit;
- CommandLineOptions.Clo.ProverCCLimit = 1;
-
- var outcome = ProverInterface.Outcome.Undetermined;
-
- do
- {
- List<int> unsatisfiedSoftAssumptions;
-
- hardAssumptions.Add(controlExprNoop);
- outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, handler);
- hardAssumptions.RemoveAt(hardAssumptions.Count - 1);
-
- if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
- break;
-
- var reason = new HashSet<string>();
- unsatisfiedSoftAssumptions.Iter(i => reason.Add(softAssumptions[i].ToString()));
- if (CommandLineOptions.Clo.Trace)
- {
- Console.Write("Reason for removal of {0}: ", refutedConstant.Name);
- reason.Iter(r => Console.Write("{0} ", r));
- Console.WriteLine();
- }
-
- // Get rid of those constants from the "reason" that can even make
- // "assert false" pass
-
- hardAssumptions.Add(controlExprFalse);
- var softAssumptions2 = new List<VCExpr>();
- for (int i = 0; i < softAssumptions.Count; i++)
- {
- if (unsatisfiedSoftAssumptions.Contains(i))
- {
- softAssumptions2.Add(softAssumptions[i]);
- continue;
- }
- hardAssumptions.Add(softAssumptions[i]);
- }
-
- var unsatisfiedSoftAssumptions2 = new List<int>();
- outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2, out unsatisfiedSoftAssumptions2, handler);
-
- if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
- break;
-
- unsatisfiedSoftAssumptions2.Iter(i => reason.Remove(softAssumptions2[i].ToString()));
- var reason1 = new HashSet<string>(); //these are the reasons for inconsistency
- unsatisfiedSoftAssumptions2.Iter(i => reason1.Add(softAssumptions2[i].ToString()));
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.Write("Revised reason for removal of {0}: ", refutedConstant.Name);
- reason.Iter(r => Console.Write("{0} ", r));
- Console.WriteLine();
- }
- foreach (var r in reason)
- {
- Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, r, descriptiveName);
- }
- //also add the removed reasons using dotted edges (requires- x != 0, requires- x == 0 ==> assert x != 0)
- foreach (var r in reason1)
- {
- Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=blue style=dotted ];", refutedConstant.Name, r, descriptiveName);
- }
- } while (false);
-
- if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
- {
- Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, "TimeOut", descriptiveName);
- }
-
- CommandLineOptions.Clo.ProverCCLimit = el;
-
- double queryTime = (DateTime.UtcNow - now).TotalSeconds;
- stats.proverTime += queryTime;
- stats.numProverQueries++;
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("Time taken = " + queryTime);
- }
- }
-
- public void UpdateUnsatCore(ProverInterface proverInterface, Dictionary<Variable, bool> assignment)
- {
- DateTime now = DateTime.UtcNow;
-
- Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
- proverInterface.Push();
- proverInterface.Assert(conjecture, false);
- foreach (var v in assignment.Keys) {
- if (assignment[v]) continue;
- proverInterface.Assert(exprTranslator.LookupVariable(v), false);
- }
- List<Variable> assumptionVars = new List<Variable>();
- List<VCExpr> assumptionExprs = new List<VCExpr>();
- foreach (var v in assignment.Keys) {
- if (!assignment[v]) continue;
- assumptionVars.Add(v);
- assumptionExprs.Add(exprTranslator.LookupVariable(v));
- }
- List<int> unsatCore;
- ProverInterface.Outcome tmp = proverInterface.CheckAssumptions(assumptionExprs, out unsatCore, handler);
- System.Diagnostics.Debug.Assert(tmp == ProverInterface.Outcome.Valid);
- unsatCoreSet = new HashSet<Variable>();
- foreach (int i in unsatCore)
- unsatCoreSet.Add(assumptionVars[i]);
- proverInterface.Pop();
-
- double unsatCoreQueryTime = (DateTime.UtcNow - now).TotalSeconds;
- stats.unsatCoreProverTime += unsatCoreQueryTime;
- stats.numUnsatCoreProverQueries++;
- }
-
- }
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Basetypes;
+using System.Collections;
+using System.IO;
+using System.Threading;
+using VC;
+using System.Linq;
+
+namespace Microsoft.Boogie.Houdini {
+ public class ExistentialConstantCollector : ReadOnlyVisitor {
+ public static void CollectHoudiniConstants(Houdini houdini, Implementation impl, out ExistentialConstantCollector collector)
+ {
+ collector = new ExistentialConstantCollector(houdini);
+ collector.impl = impl;
+ collector.VisitImplementation(impl);
+ }
+
+ private ExistentialConstantCollector(Houdini houdini) {
+ this.houdini = houdini;
+ this.houdiniAssertConstants = new HashSet<Variable>();
+ this.houdiniAssumeConstants = new HashSet<Variable>();
+
+ this.explainNegative = new HashSet<Variable>();
+ this.explainPositive = new HashSet<Variable>();
+ this.constToControl = new Dictionary<string, Tuple<Variable, Variable>>();
+ }
+ private Houdini houdini;
+ public HashSet<Variable> houdiniAssertConstants;
+ public HashSet<Variable> houdiniAssumeConstants;
+
+ // Explain Houdini stuff
+ public HashSet<Variable> explainPositive;
+ public HashSet<Variable> explainNegative;
+ public Dictionary<string, Tuple<Variable, Variable>> constToControl;
+ Implementation impl;
+
+ public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
+ AddHoudiniConstant(node);
+ return base.VisitAssertRequiresCmd(node);
+ }
+ public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
+ AddHoudiniConstant(node);
+ return base.VisitAssertEnsuresCmd(node);
+ }
+ public override Cmd VisitAssertCmd(AssertCmd node) {
+ AddHoudiniConstant(node);
+ return base.VisitAssertCmd(node);
+ }
+ public override Cmd VisitAssumeCmd(AssumeCmd node) {
+ AddHoudiniConstant(node);
+ return base.VisitAssumeCmd(node);
+ }
+ private void AddHoudiniConstant(AssertCmd assertCmd)
+ {
+ Variable houdiniConstant;
+ if (houdini.MatchCandidate(assertCmd.Expr, out houdiniConstant))
+ houdiniAssertConstants.Add(houdiniConstant);
+
+ if (houdiniConstant != null && CommandLineOptions.Clo.ExplainHoudini && !constToControl.ContainsKey(houdiniConstant.Name))
+ {
+ // For each houdini constant c, create two more constants c_pos and c_neg.
+ // Then change the asserted condition (c ==> \phi) to
+ // (c ==> (c_pos && (\phi || \not c_neg))
+ var control = createNewExplainConstants(houdiniConstant);
+ assertCmd.Expr = houdini.InsertCandidateControl(assertCmd.Expr, control.Item1, control.Item2);
+ explainPositive.Add(control.Item1);
+ explainNegative.Add(control.Item2);
+ constToControl.Add(houdiniConstant.Name, control);
+ }
+ }
+ private void AddHoudiniConstant(AssumeCmd assumeCmd)
+ {
+ Variable houdiniConstant;
+ if (houdini.MatchCandidate(assumeCmd.Expr, out houdiniConstant))
+ houdiniAssumeConstants.Add(houdiniConstant);
+ }
+ private Tuple<Variable, Variable> createNewExplainConstants(Variable v)
+ {
+ Contract.Assert(impl != null);
+ Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);
+ Variable v1 = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}_{2}", v.Name, impl.Name, "pos"), Microsoft.Boogie.BasicType.Bool));
+ Variable v2 = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}_{2}", v.Name, impl.Name, "neg"), Microsoft.Boogie.BasicType.Bool));
+
+ return Tuple.Create(v1, v2);
+ }
+ }
+
+
+
+ public class HoudiniSession {
+
+ public class HoudiniStatistics {
+ public double proverTime = 0;
+ public int numProverQueries = 0;
+ public double unsatCoreProverTime = 0;
+ public int numUnsatCoreProverQueries = 0;
+ public int numUnsatCorePrunings = 0;
+ }
+
+ public string descriptiveName;
+ public HoudiniStatistics stats;
+ private VCExpr conjecture;
+ private ProverInterface.ErrorHandler handler;
+ ConditionGeneration.CounterexampleCollector collector;
+ HashSet<Variable> unsatCoreSet;
+ HashSet<Variable> houdiniConstants;
+ public HashSet<Variable> houdiniAssertConstants;
+ private HashSet<Variable> houdiniAssumeConstants;
+
+ // Extra constants created for ExplainHoudini
+ private HashSet<Variable> explainConstantsPositive;
+ private HashSet<Variable> explainConstantsNegative;
+ private Dictionary<string, Tuple<Variable, Variable>> constantToControl;
+
+ public bool InUnsatCore(Variable constant) {
+ if (unsatCoreSet == null)
+ return true;
+ if (unsatCoreSet.Contains(constant))
+ return true;
+ stats.numUnsatCorePrunings++;
+ return false;
+ }
+
+ public HoudiniSession(Houdini houdini, VCGen vcgen, ProverInterface proverInterface, Program program, Implementation impl, HoudiniStatistics stats, int taskID = -1) {
+ this.descriptiveName = impl.Name;
+ this.stats = stats;
+ collector = new ConditionGeneration.CounterexampleCollector();
+ collector.OnProgress("HdnVCGen", 0, 0, 0.0);
+
+ vcgen.ConvertCFG2DAG(impl, taskID: taskID);
+ ModelViewInfo mvInfo;
+ var gotoCmdOrigins = vcgen.PassifyImpl(impl, out mvInfo);
+
+ ExistentialConstantCollector ecollector;
+ ExistentialConstantCollector.CollectHoudiniConstants(houdini, impl, out ecollector);
+ this.houdiniAssertConstants = ecollector.houdiniAssertConstants;
+ this.houdiniAssumeConstants = ecollector.houdiniAssumeConstants;
+ this.explainConstantsNegative = ecollector.explainNegative;
+ this.explainConstantsPositive = ecollector.explainPositive;
+ this.constantToControl = ecollector.constToControl;
+
+ houdiniConstants = new HashSet<Variable>();
+ houdiniConstants.UnionWith(houdiniAssertConstants);
+ houdiniConstants.UnionWith(houdiniAssumeConstants);
+
+ var exprGen = proverInterface.Context.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+
+ Dictionary<int, Absy> label2absy;
+ conjecture = vcgen.GenerateVC(impl, controlFlowVariableExpr, out label2absy, proverInterface.Context);
+ if (!CommandLineOptions.Clo.UseLabels) {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ conjecture = exprGen.Implies(eqExpr, conjecture);
+ }
+
+ Macro macro = new Macro(Token.NoToken, descriptiveName, new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Type.Bool), false));
+ proverInterface.DefineMacro(macro, conjecture);
+ conjecture = exprGen.Function(macro);
+
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local) {
+ handler = new VCGen.ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, proverInterface.Context, program);
+ }
+ else {
+ handler = new VCGen.ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, proverInterface.Context, program);
+ }
+
+ }
+
+ private VCExpr BuildAxiom(ProverInterface proverInterface, Dictionary<Variable, bool> currentAssignment) {
+ ProverContext proverContext = proverInterface.Context;
+ Boogie2VCExprTranslator exprTranslator = proverContext.BoogieExprTranslator;
+ VCExpressionGenerator exprGen = proverInterface.VCExprGen;
+
+ VCExpr expr = VCExpressionGenerator.True;
+
+ foreach (KeyValuePair<Variable, bool> kv in currentAssignment) {
+ Variable constant = kv.Key;
+ VCExprVar exprVar = exprTranslator.LookupVariable(constant);
+ if (kv.Value) {
+ expr = exprGen.And(expr, exprVar);
+ }
+ else {
+ expr = exprGen.And(expr, exprGen.Not(exprVar));
+ }
+ }
+
+ if (CommandLineOptions.Clo.ExplainHoudini)
+ {
+ // default values for ExplainHoudini control variables
+ foreach (var constant in explainConstantsNegative.Concat(explainConstantsPositive))
+ {
+ expr = exprGen.And(expr, exprTranslator.LookupVariable(constant));
+ }
+ }
+
+ /*
+ foreach (Variable constant in this.houdiniConstants) {
+ VCExprVar exprVar = exprTranslator.LookupVariable(constant);
+ if (currentAssignment[constant]) {
+ expr = exprGen.And(expr, exprVar);
+ }
+ else {
+ expr = exprGen.And(expr, exprGen.Not(exprVar));
+ }
+ }
+ */
+
+ if(CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Houdini assignment axiom: " + expr);
+ }
+
+ return expr;
+ }
+
+ public ProverInterface.Outcome Verify(ProverInterface proverInterface, Dictionary<Variable, bool> assignment, out List<Counterexample> errors, int taskID = -1) {
+ collector.examples.Clear();
+
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Verifying " + descriptiveName);
+ }
+ DateTime now = DateTime.UtcNow;
+
+ VCExpr vc = proverInterface.VCExprGen.Implies(BuildAxiom(proverInterface, assignment), conjecture);
+ proverInterface.BeginCheck(descriptiveName, vc, handler);
+ ProverInterface.Outcome proverOutcome = proverInterface.CheckOutcome(handler, taskID: taskID);
+
+ double queryTime = (DateTime.UtcNow - now).TotalSeconds;
+ stats.proverTime += queryTime;
+ stats.numProverQueries++;
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Outcome = " + proverOutcome);
+ Console.WriteLine("Time taken = " + queryTime);
+ }
+
+ errors = collector.examples;
+ return proverOutcome;
+ }
+
+ // MAXSAT
+ public void Explain(ProverInterface proverInterface,
+ Dictionary<Variable, bool> assignment, Variable refutedConstant)
+ {
+ Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);
+
+ collector.examples.Clear();
+
+ // debugging
+ houdiniAssertConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
+ houdiniAssumeConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
+ Contract.Assert(assignment.ContainsKey(refutedConstant));
+ Contract.Assert(houdiniAssertConstants.Contains(refutedConstant));
+
+ var hardAssumptions = new List<VCExpr>();
+ var softAssumptions = new List<VCExpr>();
+
+ Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
+ VCExpressionGenerator exprGen = proverInterface.VCExprGen;
+ var controlExpr = VCExpressionGenerator.True;
+
+ foreach (var tup in assignment)
+ {
+ Variable constant = tup.Key;
+ VCExprVar exprVar = exprTranslator.LookupVariable(constant);
+ var val = tup.Value;
+
+ if (houdiniAssumeConstants.Contains(constant))
+ {
+ if (tup.Value)
+ hardAssumptions.Add(exprVar);
+ else
+ // Previously removed assumed candidates are the soft constraints
+ softAssumptions.Add(exprVar);
+ }
+ else if (houdiniAssertConstants.Contains(constant))
+ {
+ if (constant == refutedConstant)
+ hardAssumptions.Add(exprVar);
+ else
+ hardAssumptions.Add(exprGen.Not(exprVar));
+ }
+ else
+ {
+ if (tup.Value)
+ hardAssumptions.Add(exprVar);
+ else
+ hardAssumptions.Add(exprGen.Not(exprVar));
+ }
+
+ // For an asserted condition (c ==> \phi),
+ // ExplainHoudini's extra control constants (c_pos, c_neg) are used as follows:
+ // (true, true): "assert \phi"
+ // (false, _): "assert false"
+ // (true, false): "assert true"
+ if (constant != refutedConstant && constantToControl.ContainsKey(constant.Name))
+ {
+ var posControl = constantToControl[constant.Name].Item1;
+ var negControl = constantToControl[constant.Name].Item2;
+
+ // Handle self-recursion
+ if (houdiniAssertConstants.Contains(constant) && houdiniAssumeConstants.Contains(constant))
+ {
+ // disable this assert
+ controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprGen.Not(exprTranslator.LookupVariable(negControl))));
+ }
+ else
+ {
+ // default values for control variables
+ controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprTranslator.LookupVariable(negControl)));
+ }
+ }
+ }
+
+ hardAssumptions.Add(exprGen.Not(conjecture));
+
+ // default values for control variables
+ Contract.Assert(constantToControl.ContainsKey(refutedConstant.Name));
+ var pc = constantToControl[refutedConstant.Name].Item1;
+ var nc = constantToControl[refutedConstant.Name].Item2;
+
+ var controlExprNoop = exprGen.And(controlExpr,
+ exprGen.And(exprTranslator.LookupVariable(pc), exprTranslator.LookupVariable(nc)));
+
+ var controlExprFalse = exprGen.And(controlExpr,
+ exprGen.And(exprGen.Not(exprTranslator.LookupVariable(pc)), exprGen.Not(exprTranslator.LookupVariable(nc))));
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Verifying (MaxSat) " + descriptiveName);
+ }
+ DateTime now = DateTime.UtcNow;
+
+ var el = CommandLineOptions.Clo.ProverCCLimit;
+ CommandLineOptions.Clo.ProverCCLimit = 1;
+
+ var outcome = ProverInterface.Outcome.Undetermined;
+
+ do
+ {
+ List<int> unsatisfiedSoftAssumptions;
+
+ hardAssumptions.Add(controlExprNoop);
+ outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, handler);
+ hardAssumptions.RemoveAt(hardAssumptions.Count - 1);
+
+ if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
+ break;
+
+ var reason = new HashSet<string>();
+ unsatisfiedSoftAssumptions.Iter(i => reason.Add(softAssumptions[i].ToString()));
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.Write("Reason for removal of {0}: ", refutedConstant.Name);
+ reason.Iter(r => Console.Write("{0} ", r));
+ Console.WriteLine();
+ }
+
+ // Get rid of those constants from the "reason" that can even make
+ // "assert false" pass
+
+ hardAssumptions.Add(controlExprFalse);
+ var softAssumptions2 = new List<VCExpr>();
+ for (int i = 0; i < softAssumptions.Count; i++)
+ {
+ if (unsatisfiedSoftAssumptions.Contains(i))
+ {
+ softAssumptions2.Add(softAssumptions[i]);
+ continue;
+ }
+ hardAssumptions.Add(softAssumptions[i]);
+ }
+
+ var unsatisfiedSoftAssumptions2 = new List<int>();
+ outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2, out unsatisfiedSoftAssumptions2, handler);
+
+ if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
+ break;
+
+ unsatisfiedSoftAssumptions2.Iter(i => reason.Remove(softAssumptions2[i].ToString()));
+ var reason1 = new HashSet<string>(); //these are the reasons for inconsistency
+ unsatisfiedSoftAssumptions2.Iter(i => reason1.Add(softAssumptions2[i].ToString()));
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.Write("Revised reason for removal of {0}: ", refutedConstant.Name);
+ reason.Iter(r => Console.Write("{0} ", r));
+ Console.WriteLine();
+ }
+ foreach (var r in reason)
+ {
+ Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, r, descriptiveName);
+ }
+ //also add the removed reasons using dotted edges (requires- x != 0, requires- x == 0 ==> assert x != 0)
+ foreach (var r in reason1)
+ {
+ Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=blue style=dotted ];", refutedConstant.Name, r, descriptiveName);
+ }
+ } while (false);
+
+ if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
+ {
+ Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, "TimeOut", descriptiveName);
+ }
+
+ CommandLineOptions.Clo.ProverCCLimit = el;
+
+ double queryTime = (DateTime.UtcNow - now).TotalSeconds;
+ stats.proverTime += queryTime;
+ stats.numProverQueries++;
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("Time taken = " + queryTime);
+ }
+ }
+
+ public void UpdateUnsatCore(ProverInterface proverInterface, Dictionary<Variable, bool> assignment)
+ {
+ DateTime now = DateTime.UtcNow;
+
+ Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
+ proverInterface.Push();
+ proverInterface.Assert(conjecture, false);
+ foreach (var v in assignment.Keys) {
+ if (assignment[v]) continue;
+ proverInterface.Assert(exprTranslator.LookupVariable(v), false);
+ }
+ List<Variable> assumptionVars = new List<Variable>();
+ List<VCExpr> assumptionExprs = new List<VCExpr>();
+ foreach (var v in assignment.Keys) {
+ if (!assignment[v]) continue;
+ assumptionVars.Add(v);
+ assumptionExprs.Add(exprTranslator.LookupVariable(v));
+ }
+ List<int> unsatCore;
+ ProverInterface.Outcome tmp = proverInterface.CheckAssumptions(assumptionExprs, out unsatCore, handler);
+ System.Diagnostics.Debug.Assert(tmp == ProverInterface.Outcome.Valid);
+ unsatCoreSet = new HashSet<Variable>();
+ foreach (int i in unsatCore)
+ unsatCoreSet.Add(assumptionVars[i]);
+ proverInterface.Pop();
+
+ double unsatCoreQueryTime = (DateTime.UtcNow - now).TotalSeconds;
+ stats.unsatCoreProverTime += unsatCoreQueryTime;
+ stats.numUnsatCoreProverQueries++;
+ }
+
+ }
} \ No newline at end of file
diff --git a/Source/Houdini/ConcurrentHoudini.cs b/Source/Houdini/ConcurrentHoudini.cs
index bfc7cbc1..e13fa802 100644
--- a/Source/Houdini/ConcurrentHoudini.cs
+++ b/Source/Houdini/ConcurrentHoudini.cs
@@ -1,104 +1,104 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.Text.RegularExpressions;
-using System.Linq;
-using VC;
-
-namespace Microsoft.Boogie.Houdini
-{
- public class ConcurrentHoudini : Houdini
- {
-
- protected int taskID;
-
- private static ConcurrentDictionary<string, RefutedAnnotation> refutedSharedAnnotations;
-
- public static ConcurrentDictionary<string, RefutedAnnotation> RefutedSharedAnnotations { get { return refutedSharedAnnotations; } }
-
- public ConcurrentHoudini(int taskId, Program program, HoudiniSession.HoudiniStatistics stats, string cexTraceFile = "houdiniCexTrace.txt") {
- Contract.Assert(taskId >= 0);
- this.program = program;
- this.cexTraceFile = cexTraceFile;
- this.taskID = taskId;
- Initialize(program, stats);
- }
-
- static ConcurrentHoudini()
- {
- refutedSharedAnnotations = new ConcurrentDictionary<string, RefutedAnnotation>();
- }
-
- protected override bool ExchangeRefutedAnnotations()
- {
- int count = 0;
-
- if (CommandLineOptions.Clo.DebugConcurrentHoudini)
- Console.WriteLine("# number of shared refuted annotations: " + refutedSharedAnnotations.Count);
-
- foreach (string key in refutedSharedAnnotations.Keys) {
- KeyValuePair<Variable, bool> kv = currentHoudiniState.Assignment.FirstOrDefault(entry => entry.Key.Name.Equals(key) && entry.Value);
-
- if (kv.Key != null) {
- RefutedAnnotation ra = null;
- Implementation refutationSite = null;
-
- foreach (var r in program.Implementations) {
- if (r.Name.Equals(refutedSharedAnnotations[key].RefutationSite.Name)) {
- refutationSite = r;
- break;
- }
- }
- Debug.Assert(refutationSite != null);
-
- if (refutedSharedAnnotations[key].Kind == RefutedAnnotationKind.REQUIRES) {
- Procedure proc = null;
- foreach (var p in program.Procedures) {
- if (p.Name.Equals(refutedSharedAnnotations[key].CalleeProc.Name)) {
- proc = p;
- break;
- }
- }
- Debug.Assert(proc != null);
- ra = RefutedAnnotation.BuildRefutedRequires(kv.Key, proc, refutationSite);
- } else if (refutedSharedAnnotations[key].Kind == RefutedAnnotationKind.ENSURES)
- ra = RefutedAnnotation.BuildRefutedEnsures(kv.Key, refutationSite);
- else if (refutedSharedAnnotations[key].Kind == RefutedAnnotationKind.ASSERT)
- ra = RefutedAnnotation.BuildRefutedAssert(kv.Key, refutationSite);
- Debug.Assert(ra != null);
-
- if (CommandLineOptions.Clo.DebugConcurrentHoudini)
- Console.WriteLine("(+) " + ra.Constant + "," + ra.Kind + "," + ra.CalleeProc + "," + ra.RefutationSite);
-
- AddRelatedToWorkList(ra);
- UpdateAssignment(ra);
- count++;
- }
- }
-
- return count > 0 ? true : false;
- }
-
- protected override void ShareRefutedAnnotation(RefutedAnnotation refutedAnnotation) {
- refutedSharedAnnotations.TryAdd(refutedAnnotation.Constant.Name, refutedAnnotation);
- }
-
- protected override void ApplyRefutedSharedAnnotations() {
- if (refutedSharedAnnotations.Count > 0) {
- foreach (var v in currentHoudiniState.Assignment.Keys.ToList()) {
- if (refutedSharedAnnotations.ContainsKey(v.Name)) {
- currentHoudiniState.Assignment[v] = false;
- }
- }
- }
- }
-
- protected override int GetTaskID() {
- return taskID;
- }
-
- }
-}
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Text.RegularExpressions;
+using System.Linq;
+using VC;
+
+namespace Microsoft.Boogie.Houdini
+{
+ public class ConcurrentHoudini : Houdini
+ {
+
+ protected int taskID;
+
+ private static ConcurrentDictionary<string, RefutedAnnotation> refutedSharedAnnotations;
+
+ public static ConcurrentDictionary<string, RefutedAnnotation> RefutedSharedAnnotations { get { return refutedSharedAnnotations; } }
+
+ public ConcurrentHoudini(int taskId, Program program, HoudiniSession.HoudiniStatistics stats, string cexTraceFile = "houdiniCexTrace.txt") {
+ Contract.Assert(taskId >= 0);
+ this.program = program;
+ this.cexTraceFile = cexTraceFile;
+ this.taskID = taskId;
+ Initialize(program, stats);
+ }
+
+ static ConcurrentHoudini()
+ {
+ refutedSharedAnnotations = new ConcurrentDictionary<string, RefutedAnnotation>();
+ }
+
+ protected override bool ExchangeRefutedAnnotations()
+ {
+ int count = 0;
+
+ if (CommandLineOptions.Clo.DebugConcurrentHoudini)
+ Console.WriteLine("# number of shared refuted annotations: " + refutedSharedAnnotations.Count);
+
+ foreach (string key in refutedSharedAnnotations.Keys) {
+ KeyValuePair<Variable, bool> kv = currentHoudiniState.Assignment.FirstOrDefault(entry => entry.Key.Name.Equals(key) && entry.Value);
+
+ if (kv.Key != null) {
+ RefutedAnnotation ra = null;
+ Implementation refutationSite = null;
+
+ foreach (var r in program.Implementations) {
+ if (r.Name.Equals(refutedSharedAnnotations[key].RefutationSite.Name)) {
+ refutationSite = r;
+ break;
+ }
+ }
+ Debug.Assert(refutationSite != null);
+
+ if (refutedSharedAnnotations[key].Kind == RefutedAnnotationKind.REQUIRES) {
+ Procedure proc = null;
+ foreach (var p in program.Procedures) {
+ if (p.Name.Equals(refutedSharedAnnotations[key].CalleeProc.Name)) {
+ proc = p;
+ break;
+ }
+ }
+ Debug.Assert(proc != null);
+ ra = RefutedAnnotation.BuildRefutedRequires(kv.Key, proc, refutationSite);
+ } else if (refutedSharedAnnotations[key].Kind == RefutedAnnotationKind.ENSURES)
+ ra = RefutedAnnotation.BuildRefutedEnsures(kv.Key, refutationSite);
+ else if (refutedSharedAnnotations[key].Kind == RefutedAnnotationKind.ASSERT)
+ ra = RefutedAnnotation.BuildRefutedAssert(kv.Key, refutationSite);
+ Debug.Assert(ra != null);
+
+ if (CommandLineOptions.Clo.DebugConcurrentHoudini)
+ Console.WriteLine("(+) " + ra.Constant + "," + ra.Kind + "," + ra.CalleeProc + "," + ra.RefutationSite);
+
+ AddRelatedToWorkList(ra);
+ UpdateAssignment(ra);
+ count++;
+ }
+ }
+
+ return count > 0 ? true : false;
+ }
+
+ protected override void ShareRefutedAnnotation(RefutedAnnotation refutedAnnotation) {
+ refutedSharedAnnotations.TryAdd(refutedAnnotation.Constant.Name, refutedAnnotation);
+ }
+
+ protected override void ApplyRefutedSharedAnnotations() {
+ if (refutedSharedAnnotations.Count > 0) {
+ foreach (var v in currentHoudiniState.Assignment.Keys.ToList()) {
+ if (refutedSharedAnnotations.ContainsKey(v.Name)) {
+ currentHoudiniState.Assignment[v] = false;
+ }
+ }
+ }
+ }
+
+ protected override int GetTaskID() {
+ return taskID;
+ }
+
+ }
+}
diff --git a/Source/Houdini/Houdini.cs b/Source/Houdini/Houdini.cs
index 986d0fff..4c4ab5aa 100644
--- a/Source/Houdini/Houdini.cs
+++ b/Source/Houdini/Houdini.cs
@@ -1,1328 +1,1330 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Diagnostics.Contracts;
-using System.Collections.Generic;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using VC;
-using System.Collections;
-using System.IO;
-using Microsoft.Boogie.GraphUtil;
-using System.Linq;
-using System.Diagnostics;
-
-namespace Microsoft.Boogie.Houdini {
-
- internal class ReadOnlyDictionary<K, V> {
- private Dictionary<K, V> dictionary;
- public ReadOnlyDictionary(Dictionary<K, V> dictionary) {
- this.dictionary = dictionary;
- }
-
- public Dictionary<K, V>.KeyCollection Keys {
- get { return this.dictionary.Keys; }
- }
-
- public bool TryGetValue(K k, out V v) {
- return this.dictionary.TryGetValue(k, out v);
- }
-
- public bool ContainsKey(K k) {
- return this.dictionary.ContainsKey(k);
- }
- }
-
- public abstract class HoudiniObserver {
- public virtual void UpdateStart(Program program, int numConstants) { }
- public virtual void UpdateIteration() { }
- public virtual void UpdateImplementation(Implementation implementation) { }
- public virtual void UpdateAssignment(Dictionary<Variable, bool> assignment) { }
- public virtual void UpdateOutcome(ProverInterface.Outcome outcome) { }
- public virtual void UpdateEnqueue(Implementation implementation) { }
- public virtual void UpdateDequeue() { }
- public virtual void UpdateConstant(string constantName) { }
- public virtual void UpdateEnd(bool isNormalEnd) { }
- public virtual void UpdateFlushStart() { }
- public virtual void UpdateFlushFinish() { }
- public virtual void SeeException(string msg) { }
- }
-
- public class IterationTimer<K> {
- private Dictionary<K, List<double>> times;
-
- public IterationTimer() {
- times = new Dictionary<K, List<double>>();
- }
-
- public void AddTime(K key, double timeMS) {
- List<double> oldList;
- times.TryGetValue(key, out oldList);
- if (oldList == null) {
- oldList = new List<double>();
- }
- else {
- times.Remove(key);
- }
- oldList.Add(timeMS);
- times.Add(key, oldList);
- }
-
- public void PrintTimes(TextWriter wr) {
- wr.WriteLine("Total procedures: {0}", times.Count);
- double total = 0;
- int totalIters = 0;
- foreach (KeyValuePair<K, List<double>> kv in times) {
- int curIter = 0;
- wr.WriteLine("Times for {0}:", kv.Key);
- foreach (double v in kv.Value) {
- wr.WriteLine(" ({0})\t{1}ms", curIter, v);
- total += v;
- curIter++;
- }
- totalIters += curIter;
- }
- total = total / 1000.0;
- wr.WriteLine("Total time: {0} (s)", total);
- wr.WriteLine("Avg: {0} (s/iter)", total / totalIters);
- }
- }
-
- public class HoudiniTimer : HoudiniObserver {
- private DateTime startT;
- private Implementation curImp;
- private IterationTimer<string> times;
- private TextWriter wr;
-
- public HoudiniTimer(TextWriter wr) {
- this.wr = wr;
- times = new IterationTimer<string>();
- }
- public override void UpdateIteration() {
- startT = DateTime.UtcNow;
- }
- public override void UpdateImplementation(Implementation implementation) {
- curImp = implementation;
- }
- public override void UpdateOutcome(ProverInterface.Outcome o) {
- Contract.Assert(curImp != null);
- DateTime endT = DateTime.UtcNow;
- times.AddTime(curImp.Name, (endT - startT).TotalMilliseconds); // assuming names are unique
- }
- public void PrintTimes() {
- wr.WriteLine("-----------------------------------------");
- wr.WriteLine("Times for each iteration for each procedure");
- wr.WriteLine("-----------------------------------------");
- times.PrintTimes(wr);
- }
- }
-
- public class HoudiniTextReporter : HoudiniObserver {
- private TextWriter wr;
- private int currentIteration = -1;
-
- public HoudiniTextReporter(TextWriter wr) {
- this.wr = wr;
- }
- public override void UpdateStart(Program program, int numConstants) {
- wr.WriteLine("Houdini started:" + program.ToString() + " #constants: " + numConstants.ToString());
- currentIteration = -1;
- wr.Flush();
- }
- public override void UpdateIteration() {
- currentIteration++;
- wr.WriteLine("---------------------------------------");
- wr.WriteLine("Houdini iteration #" + currentIteration);
- wr.Flush();
- }
- public override void UpdateImplementation(Implementation implementation) {
- wr.WriteLine("implementation under analysis :" + implementation.Name);
- wr.Flush();
- }
- public override void UpdateAssignment(Dictionary<Variable, bool> assignment) {
- bool firstTime = true;
- wr.Write("assignment under analysis : axiom (");
- foreach (KeyValuePair<Variable, bool> kv in assignment) {
- if (!firstTime) wr.Write(" && "); else firstTime = false;
- string valString; // ugliness to get it lower cased
- if (kv.Value) valString = "true"; else valString = "false";
- wr.Write(kv.Key + " == " + valString);
- }
- wr.WriteLine(");");
- wr.Flush();
- }
- public override void UpdateOutcome(ProverInterface.Outcome outcome) {
- wr.WriteLine("analysis outcome :" + outcome);
- wr.Flush();
- }
- public override void UpdateEnqueue(Implementation implementation) {
- wr.WriteLine("worklist enqueue :" + implementation.Name);
- wr.Flush();
- }
- public override void UpdateDequeue() {
- wr.WriteLine("worklist dequeue");
- wr.Flush();
- }
- public override void UpdateConstant(string constantName) {
- wr.WriteLine("constant disabled : " + constantName);
- wr.Flush();
- }
- public override void UpdateEnd(bool isNormalEnd) {
- wr.WriteLine("Houdini ended: " + (isNormalEnd ? "Normal" : "Abnormal"));
- wr.WriteLine("Number of iterations: " + (this.currentIteration + 1));
- wr.Flush();
- }
- public override void UpdateFlushStart() {
- wr.WriteLine("***************************************");
- wr.WriteLine("Flushing remaining implementations");
- wr.Flush();
- }
- public override void UpdateFlushFinish() {
- wr.WriteLine("***************************************");
- wr.WriteLine("Flushing finished");
- wr.Flush();
- }
- public override void SeeException(string msg) {
- wr.WriteLine("Caught exception: " + msg);
- wr.Flush();
- }
-
- }
-
- public abstract class ObservableHoudini {
- private List<HoudiniObserver> observers = new List<HoudiniObserver>();
-
- public void AddObserver(HoudiniObserver observer) {
- if (!observers.Contains(observer))
- observers.Add(observer);
- }
- private delegate void NotifyDelegate(HoudiniObserver observer);
-
- private void Notify(NotifyDelegate notifyDelegate) {
- foreach (HoudiniObserver observer in observers) {
- notifyDelegate(observer);
- }
- }
- protected void NotifyStart(Program program, int numConstants) {
- NotifyDelegate notifyDelegate = (NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateStart(program, numConstants); };
- Notify(notifyDelegate);
- }
- protected void NotifyIteration() {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateIteration(); });
- }
- protected void NotifyImplementation(Implementation implementation) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateImplementation(implementation); });
- }
- protected void NotifyAssignment(Dictionary<Variable, bool> assignment) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateAssignment(assignment); });
- }
- protected void NotifyOutcome(ProverInterface.Outcome outcome) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateOutcome(outcome); });
- }
- protected void NotifyEnqueue(Implementation implementation) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateEnqueue(implementation); });
- }
- protected void NotifyDequeue() {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateDequeue(); });
- }
- protected void NotifyConstant(string constantName) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateConstant(constantName); });
- }
- protected void NotifyEnd(bool isNormalEnd) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateEnd(isNormalEnd); });
- }
- protected void NotifyFlushStart() {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateFlushStart(); });
- }
- protected void NotifyFlushFinish() {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateFlushFinish(); });
- }
-
- protected void NotifyException(string msg) {
- Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.SeeException(msg); });
- }
- }
-
- public class InlineEnsuresVisitor : ReadOnlyVisitor {
- public override Ensures VisitEnsures(Ensures ensures)
- {
- if (!ensures.Free)
- {
- ensures.Attributes = new QKeyValue(Token.NoToken, "InlineAssume", new List<object>(), ensures.Attributes);
- }
- return base.VisitEnsures(ensures);
- }
- }
-
- public class Houdini : ObservableHoudini {
- protected Program program;
- protected HashSet<Variable> houdiniConstants;
- protected VCGen vcgen;
- protected ProverInterface proverInterface;
- protected Graph<Implementation> callGraph;
- protected HashSet<Implementation> vcgenFailures;
- protected HoudiniState currentHoudiniState;
- protected CrossDependencies crossDependencies;
- internal ReadOnlyDictionary<Implementation, HoudiniSession> houdiniSessions;
-
- protected string cexTraceFile;
-
- public HoudiniState CurrentHoudiniState { get { return currentHoudiniState; } }
-
- public static TextWriter explainHoudiniDottyFile;
-
- protected Houdini() { }
-
- public Houdini(Program program, HoudiniSession.HoudiniStatistics stats, string cexTraceFile = "houdiniCexTrace.txt") {
- this.program = program;
- this.cexTraceFile = cexTraceFile;
- Initialize(program, stats);
- }
-
- protected void Initialize(Program program, HoudiniSession.HoudiniStatistics stats)
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Collecting existential constants...");
- this.houdiniConstants = CollectExistentialConstants();
-
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Building call graph...");
- this.callGraph = Program.BuildCallGraph(program);
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Number of implementations = {0}", callGraph.Nodes.Count);
-
- if (CommandLineOptions.Clo.HoudiniUseCrossDependencies)
- {
- if (CommandLineOptions.Clo.Trace) Console.WriteLine("Computing procedure cross dependencies ...");
- this.crossDependencies = new CrossDependencies(this.houdiniConstants);
- this.crossDependencies.Visit(program);
- }
-
- Inline();
- /*
- {
- int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
- CommandLineOptions.Clo.PrintUnstructured = 1;
- using (TokenTextWriter stream = new TokenTextWriter("houdini_inline.bpl"))
- {
- program.Emit(stream);
- }
- CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
- }
- */
-
- this.vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List<Checker>());
- this.proverInterface = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, CommandLineOptions.Clo.ProverKillTime, taskID: GetTaskID());
-
- vcgenFailures = new HashSet<Implementation>();
- Dictionary<Implementation, HoudiniSession> houdiniSessions = new Dictionary<Implementation, HoudiniSession>();
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Beginning VC generation for Houdini...");
- foreach (Implementation impl in callGraph.Nodes)
- {
- try
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("Generating VC for {0}", impl.Name);
- HoudiniSession session = new HoudiniSession(this, vcgen, proverInterface, program, impl, stats, taskID: GetTaskID());
- houdiniSessions.Add(impl, session);
- }
- catch (VCGenException)
- {
- if (CommandLineOptions.Clo.Trace)
- Console.WriteLine("VC generation failed");
- vcgenFailures.Add(impl);
- }
- }
- this.houdiniSessions = new ReadOnlyDictionary<Implementation, HoudiniSession>(houdiniSessions);
-
- if (CommandLineOptions.Clo.ExplainHoudini)
- {
- // Print results of ExplainHoudini to a dotty file
- explainHoudiniDottyFile = new StreamWriter("explainHoudini.dot");
- explainHoudiniDottyFile.WriteLine("digraph explainHoudini {");
- foreach (var constant in houdiniConstants)
- explainHoudiniDottyFile.WriteLine("{0} [ label = \"{0}\" color=black ];", constant.Name);
- explainHoudiniDottyFile.WriteLine("TimeOut [label = \"TimeOut\" color=red ];");
- }
- }
-
- protected void Inline() {
- if (CommandLineOptions.Clo.InlineDepth <= 0)
- return;
-
- foreach (Implementation impl in callGraph.Nodes) {
- InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
- inlineEnsuresVisitor.Visit(impl);
- }
-
- foreach (Implementation impl in callGraph.Nodes) {
- impl.OriginalBlocks = impl.Blocks;
- impl.OriginalLocVars = impl.LocVars;
- }
- foreach (Implementation impl in callGraph.Nodes) {
- CommandLineOptions.Inlining savedOption = CommandLineOptions.Clo.ProcedureInlining;
- CommandLineOptions.Clo.ProcedureInlining = CommandLineOptions.Inlining.Spec;
- Inliner.ProcessImplementationForHoudini(program, impl);
- CommandLineOptions.Clo.ProcedureInlining = savedOption;
- }
- foreach (Implementation impl in callGraph.Nodes) {
- impl.OriginalBlocks = null;
- impl.OriginalLocVars = null;
- }
-
- Graph<Implementation> oldCallGraph = callGraph;
- callGraph = new Graph<Implementation>();
- foreach (Implementation impl in oldCallGraph.Nodes) {
- callGraph.AddSource(impl);
- }
- foreach (Tuple<Implementation, Implementation> edge in oldCallGraph.Edges) {
- callGraph.AddEdge(edge.Item1, edge.Item2);
- }
- int count = CommandLineOptions.Clo.InlineDepth;
- while (count > 0) {
- foreach (Implementation impl in oldCallGraph.Nodes) {
- List<Implementation> newNodes = new List<Implementation>();
- foreach (Implementation succ in callGraph.Successors(impl)) {
- newNodes.AddRange(oldCallGraph.Successors(succ));
- }
- foreach (Implementation newNode in newNodes) {
- callGraph.AddEdge(impl, newNode);
- }
- }
- count--;
- }
- }
-
- protected HashSet<Variable> CollectExistentialConstants() {
- HashSet<Variable> existentialConstants = new HashSet<Variable>();
- foreach (var constant in program.Constants) {
- bool result = false;
- if (constant.CheckBooleanAttribute("existential", ref result)) {
- if (result == true)
- existentialConstants.Add(constant);
- }
- }
- return existentialConstants;
- }
-
- // Compute dependencies between candidates
- public class CrossDependencies : ReadOnlyVisitor
- {
- public CrossDependencies(HashSet<Variable> constants)
- {
- this.constants = constants;
- }
-
- public override Program VisitProgram(Program node)
- {
- assumedInImpl = new Dictionary<string, HashSet<Implementation>>();
- return base.VisitProgram(node);
- }
-
- public override Implementation VisitImplementation(Implementation node)
- {
- curImpl = node;
- return base.VisitImplementation(node);
- }
-
- public override Cmd VisitAssumeCmd(AssumeCmd node)
- {
- return base.VisitAssumeCmd(node);
- }
-
- public override Variable VisitVariable(Variable node)
- {
- if (node is Constant)
- {
- var constant = node as Constant;
- if (constants.Contains(constant))
- {
- if (!assumedInImpl.ContainsKey(constant.Name))
- assumedInImpl[constant.Name] = new HashSet<Implementation>();
- assumedInImpl[constant.Name].Add(curImpl);
- }
- }
- return base.VisitVariable(node);
- }
-
- HashSet<Variable> constants;
- Implementation curImpl;
-
- // contant -> set of implementations that have an assume command with that constant
- public Dictionary<string, HashSet<Implementation>> assumedInImpl { get; private set; }
- }
-
- protected WorkQueue BuildWorkList(Program program) {
- // adding implementations to the workqueue from the bottom of the call graph upwards
- WorkQueue queue = new WorkQueue();
- StronglyConnectedComponents<Implementation> sccs =
- new StronglyConnectedComponents<Implementation>(callGraph.Nodes,
- new Adjacency<Implementation>(callGraph.Predecessors),
- new Adjacency<Implementation>(callGraph.Successors));
- sccs.Compute();
- foreach (SCC<Implementation> scc in sccs) {
- foreach (Implementation impl in scc) {
- if (vcgenFailures.Contains(impl)) continue;
- queue.Enqueue(impl);
- }
- }
- if (CommandLineOptions.Clo.ReverseHoudiniWorklist)
- queue = queue.Reverse();
- return queue;
- /*
- Queue<Implementation> queue = new Queue<Implementation>();
- foreach (Declaration decl in program.TopLevelDeclarations) {
- Implementation impl = decl as Implementation;
- if (impl == null || impl.SkipVerification) continue;
- queue.Enqueue(impl);
- }
- return queue;
- */
- }
-
- public static bool MatchCandidate(Expr boogieExpr, IEnumerable<string> candidates, out string candidateConstant) {
- candidateConstant = null;
- NAryExpr e = boogieExpr as NAryExpr;
- if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp) {
- Expr antecedent = e.Args[0];
- Expr consequent = e.Args[1];
-
- IdentifierExpr id = antecedent as IdentifierExpr;
- if (id != null && id.Decl is Constant && candidates.Contains(id.Decl.Name)) {
- candidateConstant = id.Decl.Name;
- return true;
- }
-
- if (MatchCandidate(consequent, candidates, out candidateConstant))
- return true;
- }
- return false;
- }
-
- public static bool GetCandidateWithoutConstant(Expr boogieExpr, IEnumerable<string> candidates, out string candidateConstant, out Expr exprWithoutConstant) {
- candidateConstant = null;
- exprWithoutConstant = null;
- NAryExpr e = boogieExpr as NAryExpr;
- if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp) {
- Expr antecedent = e.Args[0];
- Expr consequent = e.Args[1];
-
- IdentifierExpr id = antecedent as IdentifierExpr;
- if (id != null && id.Decl is Constant && candidates.Contains(id.Decl.Name)) {
- candidateConstant = id.Decl.Name;
- exprWithoutConstant = consequent;
- return true;
- }
-
- if (GetCandidateWithoutConstant(consequent, candidates, out candidateConstant, out exprWithoutConstant))
- exprWithoutConstant = Expr.Imp(antecedent, exprWithoutConstant);
- return true;
- }
- return false;
- }
-
- private static Expr AddConditionToCandidateRec(Expr boogieExpr, Expr condition, string candidateConstant, List<Expr> implicationStack)
- {
- NAryExpr e = boogieExpr as NAryExpr;
- if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp)
- {
- Expr antecedent = e.Args[0];
- Expr consequent = e.Args[1];
-
- IdentifierExpr id = antecedent as IdentifierExpr;
- if (id != null && id.Decl is Constant && id.Decl.Name.Equals(candidateConstant))
- {
- Expr result = Expr.Imp(antecedent, Expr.Imp(condition, consequent));
- implicationStack.Reverse();
- foreach (var expr in implicationStack)
- {
- result = Expr.Imp(expr, result);
- }
- return result;
- }
-
- implicationStack.Add(antecedent);
- return AddConditionToCandidateRec(consequent, condition, candidateConstant,
- implicationStack);
- }
- return boogieExpr;
- }
-
- public static Expr AddConditionToCandidate(Expr boogieExpr, Expr condition, string candidateConstant)
- {
- return AddConditionToCandidateRec(boogieExpr, condition, candidateConstant, new List<Expr>());
- }
-
- public bool MatchCandidate(Expr boogieExpr, out Variable candidateConstant) {
- candidateConstant = null;
- string candidateString;
- if(MatchCandidate(boogieExpr, houdiniConstants.Select(item => item.Name), out candidateString)) {
- candidateConstant = houdiniConstants.Where(item => item.Name.Equals(candidateString)).ToList()[0];
- return true;
- }
- return false;
- }
-
- public bool MatchCandidate(Expr boogieExpr, out string candidateConstant) {
- return MatchCandidate(boogieExpr, houdiniConstants.Select(item => item.Name), out candidateConstant);
- }
-
- // For Explain houdini: it decorates the condition \phi as (vpos && (\phi || \not vneg))
- // Precondition: MatchCandidate returns true
- public Expr InsertCandidateControl(Expr boogieExpr, Variable vpos, Variable vneg)
- {
- Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);
-
- NAryExpr e = boogieExpr as NAryExpr;
- if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp)
- {
- Expr antecedent = e.Args[0];
- Expr consequent = e.Args[1];
-
- IdentifierExpr id = antecedent as IdentifierExpr;
- if (id != null && id.Decl is Constant && houdiniConstants.Contains((Constant)id.Decl))
- {
- return Expr.Imp(antecedent, Expr.And(Expr.Ident(vpos), Expr.Or(consequent, Expr.Not(Expr.Ident(vneg)))));
- }
-
- return Expr.Imp(antecedent, InsertCandidateControl(consequent, vpos, vneg));
- }
- Contract.Assert(false);
- return null;
- }
-
- protected Dictionary<Variable, bool> BuildAssignment(HashSet<Variable> constants) {
- Dictionary<Variable, bool> initial = new Dictionary<Variable, bool>();
- foreach (var constant in constants)
- initial.Add(constant, true);
- return initial;
- }
-
- private bool IsOutcomeNotHoudini(ProverInterface.Outcome outcome, List<Counterexample> errors) {
- switch (outcome) {
- case ProverInterface.Outcome.Valid:
- return false;
- case ProverInterface.Outcome.Invalid:
- Contract.Assume(errors != null);
- foreach (Counterexample error in errors) {
- if (ExtractRefutedAnnotation(error) == null)
- return true;
- }
- return false;
- default:
- return true;
- }
- }
-
- // Record most current non-candidate errors found
- // Return true if there was at least one non-candidate error
- protected bool UpdateHoudiniOutcome(HoudiniOutcome houdiniOutcome,
- Implementation implementation,
- ProverInterface.Outcome outcome,
- List<Counterexample> errors) {
- string implName = implementation.Name;
- houdiniOutcome.implementationOutcomes.Remove(implName);
- List<Counterexample> nonCandidateErrors = new List<Counterexample>();
-
- if (outcome == ProverInterface.Outcome.Invalid) {
- foreach (Counterexample error in errors) {
- if (ExtractRefutedAnnotation(error) == null)
- nonCandidateErrors.Add(error);
- }
- }
- houdiniOutcome.implementationOutcomes.Add(implName, new VCGenOutcome(outcome, nonCandidateErrors));
- return nonCandidateErrors.Count > 0;
- }
-
- protected void FlushWorkList(int stage, IEnumerable<int> completedStages) {
- this.NotifyFlushStart();
- while (currentHoudiniState.WorkQueue.Count > 0) {
- this.NotifyIteration();
-
- currentHoudiniState.Implementation = currentHoudiniState.WorkQueue.Peek();
- this.NotifyImplementation(currentHoudiniState.Implementation);
-
- HoudiniSession session;
- houdiniSessions.TryGetValue(currentHoudiniState.Implementation, out session);
- List<Counterexample> errors;
- ProverInterface.Outcome outcome = TryCatchVerify(session, stage, completedStages, out errors);
- UpdateHoudiniOutcome(currentHoudiniState.Outcome, currentHoudiniState.Implementation, outcome, errors);
- this.NotifyOutcome(outcome);
-
- currentHoudiniState.WorkQueue.Dequeue();
- this.NotifyDequeue();
- }
- this.NotifyFlushFinish();
- }
-
- protected void UpdateAssignment(RefutedAnnotation refAnnot) {
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Removing " + refAnnot.Constant);
- using (var cexWriter = new System.IO.StreamWriter(cexTraceFile, true))
- cexWriter.WriteLine("Removing " + refAnnot.Constant);
- }
- currentHoudiniState.Assignment.Remove(refAnnot.Constant);
- currentHoudiniState.Assignment.Add(refAnnot.Constant, false);
- this.NotifyConstant(refAnnot.Constant.Name);
- }
-
- protected void AddRelatedToWorkList(RefutedAnnotation refutedAnnotation) {
- Contract.Assume(currentHoudiniState.Implementation != null);
- foreach (Implementation implementation in FindImplementationsToEnqueue(refutedAnnotation, refutedAnnotation.RefutationSite)) {
- if (!currentHoudiniState.isBlackListed(implementation.Name)) {
- currentHoudiniState.WorkQueue.Enqueue(implementation);
- this.NotifyEnqueue(implementation);
- }
- }
- }
-
- // Updates the worklist and current assignment
- // @return true if the current function is dequeued
- protected bool UpdateAssignmentWorkList(ProverInterface.Outcome outcome,
- List<Counterexample> errors) {
- Contract.Assume(currentHoudiniState.Implementation != null);
- bool dequeue = true;
-
- switch (outcome) {
- case ProverInterface.Outcome.Valid:
- //yeah, dequeue
- break;
-
- case ProverInterface.Outcome.Invalid:
- Contract.Assume(errors != null);
-
- foreach (Counterexample error in errors) {
- RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
- if (refutedAnnotation != null) {
- // some candidate annotation removed
- ShareRefutedAnnotation(refutedAnnotation);
- AddRelatedToWorkList(refutedAnnotation);
- UpdateAssignment(refutedAnnotation);
- dequeue = false;
- #region Extra debugging output
- if (CommandLineOptions.Clo.Trace) {
- using (var cexWriter = new System.IO.StreamWriter(cexTraceFile, true)) {
- cexWriter.WriteLine("Counter example for " + refutedAnnotation.Constant);
- cexWriter.Write(error.ToString());
- cexWriter.WriteLine();
- using (var writer = new Microsoft.Boogie.TokenTextWriter(cexWriter, /*pretty=*/ false))
- foreach (Microsoft.Boogie.Block blk in error.Trace)
- blk.Emit(writer, 15);
- //cexWriter.WriteLine();
- }
- }
- #endregion
- }
- }
-
- if (ExchangeRefutedAnnotations()) dequeue = false;
-
- break;
- default:
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Timeout/Spaceout while verifying " + currentHoudiniState.Implementation.Name);
- }
- HoudiniSession houdiniSession;
- houdiniSessions.TryGetValue(currentHoudiniState.Implementation, out houdiniSession);
- foreach (Variable v in houdiniSession.houdiniAssertConstants) {
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Removing " + v);
- }
- currentHoudiniState.Assignment.Remove(v);
- currentHoudiniState.Assignment.Add(v, false);
- this.NotifyConstant(v.Name);
- }
- currentHoudiniState.addToBlackList(currentHoudiniState.Implementation.Name);
- break;
- }
-
- return dequeue;
- }
-
- // This method is a hook used by ConcurrentHoudini to
- // exchange refuted annotations with other Houdini engines.
- // If the method returns true, this indicates that at least
- // one new refutation was received from some other engine.
- // In the base class we thus return false.
- protected virtual bool ExchangeRefutedAnnotations() {
- return false;
- }
-
- // This method is a hook used by ConcurrentHoudini to
- // apply a set of existing refuted annotations at the
- // start of inference.
- protected virtual void ApplyRefutedSharedAnnotations() {
- // Empty in base class; can be overridden.
- }
-
- // This method is a hook used by ConcurrentHoudini to
- // broadcast to other Houdini engines the fact that an
- // annotation was refuted.
- protected virtual void ShareRefutedAnnotation(RefutedAnnotation refutedAnnotation) {
- // Empty in base class; can be overridden.
- }
-
- // Hook for ConcurrentHoudini, which requires a task id.
- // Non-concurrent Houdini has -1 as a task id
- protected virtual int GetTaskID() {
- return -1;
- }
-
- public class WorkQueue {
- private Queue<Implementation> queue;
- private HashSet<Implementation> set;
- public WorkQueue() {
- queue = new Queue<Implementation>();
- set = new HashSet<Implementation>();
- }
- public void Enqueue(Implementation impl) {
- if (set.Contains(impl))
- return;
- queue.Enqueue(impl);
- set.Add(impl);
- }
- public Implementation Dequeue() {
- Implementation impl = queue.Dequeue();
- set.Remove(impl);
- return impl;
- }
- public Implementation Peek() {
- return queue.Peek();
- }
- public int Count {
- get { return queue.Count; }
- }
- public bool Contains(Implementation impl) {
- return set.Contains(impl);
- }
- public WorkQueue Reverse()
- {
- var ret = new WorkQueue();
- foreach (var impl in queue.Reverse())
- ret.Enqueue(impl);
- return ret;
- }
- }
-
- public class HoudiniState {
- public WorkQueue _workQueue;
- public HashSet<string> blackList;
- public Dictionary<Variable, bool> _assignment;
- public Implementation _implementation;
- public HoudiniOutcome _outcome;
-
- public HoudiniState(WorkQueue workQueue, Dictionary<Variable, bool> currentAssignment) {
- this._workQueue = workQueue;
- this._assignment = currentAssignment;
- this._implementation = null;
- this._outcome = new HoudiniOutcome();
- this.blackList = new HashSet<string>();
- }
-
- public WorkQueue WorkQueue {
- get { return this._workQueue; }
- }
- public Dictionary<Variable, bool> Assignment {
- get { return this._assignment; }
- }
- public Implementation Implementation {
- get { return this._implementation; }
- set { this._implementation = value; }
- }
- public HoudiniOutcome Outcome {
- get { return this._outcome; }
- }
- public bool isBlackListed(string funcName) {
- return blackList.Contains(funcName);
- }
- public void addToBlackList(string funcName) {
- blackList.Add(funcName);
- }
- }
-
- public HoudiniOutcome PerformHoudiniInference(int stage = 0,
- IEnumerable<int> completedStages = null,
- Dictionary<string, bool> initialAssignment = null) {
- this.NotifyStart(program, houdiniConstants.Count);
-
- currentHoudiniState = new HoudiniState(BuildWorkList(program), BuildAssignment(houdiniConstants));
-
- if(initialAssignment != null) {
- foreach(var v in CurrentHoudiniState.Assignment.Keys.ToList()) {
- CurrentHoudiniState.Assignment[v] = initialAssignment[v.Name];
- }
- }
-
- ApplyRefutedSharedAnnotations();
-
- foreach (Implementation impl in vcgenFailures) {
- currentHoudiniState.addToBlackList(impl.Name);
- }
-
- while (currentHoudiniState.WorkQueue.Count > 0) {
- this.NotifyIteration();
-
- currentHoudiniState.Implementation = currentHoudiniState.WorkQueue.Peek();
- this.NotifyImplementation(currentHoudiniState.Implementation);
-
- HoudiniSession session;
- this.houdiniSessions.TryGetValue(currentHoudiniState.Implementation, out session);
- HoudiniVerifyCurrent(session, stage, completedStages);
- }
-
- this.NotifyEnd(true);
- Dictionary<string, bool> assignment = new Dictionary<string, bool>();
- foreach (var x in currentHoudiniState.Assignment)
- assignment[x.Key.Name] = x.Value;
- currentHoudiniState.Outcome.assignment = assignment;
- return currentHoudiniState.Outcome;
- }
-
- public void Close() {
- vcgen.Close();
- proverInterface.Close();
- if (CommandLineOptions.Clo.ExplainHoudini)
- {
- explainHoudiniDottyFile.WriteLine("};");
- explainHoudiniDottyFile.Close();
- }
- }
-
- private int NumberOfStages()
- {
- int result = 1;
- foreach(var c in program.Constants) {
- result = Math.Max(result, 1 + QKeyValue.FindIntAttribute(c.Attributes, "stage_active", -1));
- }
- return result;
- }
-
- private List<Implementation> FindImplementationsToEnqueue(RefutedAnnotation refutedAnnotation, Implementation currentImplementation) {
- HoudiniSession session;
- List<Implementation> implementations = new List<Implementation>();
- switch (refutedAnnotation.Kind) {
- case RefutedAnnotationKind.REQUIRES:
- foreach (Implementation callee in callGraph.Successors(currentImplementation))
- {
- if (vcgenFailures.Contains(callee)) continue;
- houdiniSessions.TryGetValue(callee, out session);
- Contract.Assume(callee.Proc != null);
- if (callee.Proc.Equals(refutedAnnotation.CalleeProc) && session.InUnsatCore(refutedAnnotation.Constant))
- implementations.Add(callee);
- }
- break;
- case RefutedAnnotationKind.ENSURES:
- foreach (Implementation caller in callGraph.Predecessors(currentImplementation))
- {
- if (vcgenFailures.Contains(caller)) continue;
- houdiniSessions.TryGetValue(caller, out session);
- if (session.InUnsatCore(refutedAnnotation.Constant))
- implementations.Add(caller);
- }
- break;
- case RefutedAnnotationKind.ASSERT: //the implementation is already in queue
- if (CommandLineOptions.Clo.HoudiniUseCrossDependencies && crossDependencies.assumedInImpl.ContainsKey(refutedAnnotation.Constant.Name))
- {
- foreach (var impl in crossDependencies.assumedInImpl[refutedAnnotation.Constant.Name])
- {
- if (vcgenFailures.Contains(impl)) continue;
- houdiniSessions.TryGetValue(impl, out session);
- if (session.InUnsatCore(refutedAnnotation.Constant))
- implementations.Add(impl);
- }
- }
- break;
- default:
- throw new Exception("Unknown Refuted annotation kind:" + refutedAnnotation.Kind);
- }
- return implementations;
- }
-
- public enum RefutedAnnotationKind { REQUIRES, ENSURES, ASSERT };
-
- public class RefutedAnnotation {
- private Variable _constant;
- private RefutedAnnotationKind _kind;
- private Procedure _callee;
- private Implementation _refutationSite;
-
- private RefutedAnnotation(Variable constant, RefutedAnnotationKind kind, Procedure callee, Implementation refutationSite) {
- this._constant = constant;
- this._kind = kind;
- this._callee = callee;
- this._refutationSite = refutationSite;
- }
- public RefutedAnnotationKind Kind {
- get { return this._kind; }
- }
- public Variable Constant {
- get { return this._constant; }
- }
- public Procedure CalleeProc {
- get { return this._callee; }
- }
- public Implementation RefutationSite {
- get { return this._refutationSite; }
- }
- public static RefutedAnnotation BuildRefutedRequires(Variable constant, Procedure callee, Implementation refutationSite) {
- return new RefutedAnnotation(constant, RefutedAnnotationKind.REQUIRES, callee, refutationSite);
- }
- public static RefutedAnnotation BuildRefutedEnsures(Variable constant, Implementation refutationSite) {
- return new RefutedAnnotation(constant, RefutedAnnotationKind.ENSURES, null, refutationSite);
- }
- public static RefutedAnnotation BuildRefutedAssert(Variable constant, Implementation refutationSite) {
- return new RefutedAnnotation(constant, RefutedAnnotationKind.ASSERT, null, refutationSite);
- }
-
- public override int GetHashCode()
- {
- unchecked {
- int hash = 17;
- hash = hash * 23 + this.Constant.GetHashCode();
- hash = hash * 23 + this.Kind.GetHashCode();
- if (this.CalleeProc != null)
- hash = hash * 23 + this.CalleeProc.GetHashCode();
- hash = hash * 23 + this.RefutationSite.GetHashCode();
- return hash;
- }
- }
-
- public override bool Equals(object obj) {
- bool result = true;
- var other = obj as RefutedAnnotation;
-
- if (other == null) {
- result = false;
- } else {
- result = result && String.Equals(other.Constant, this.Constant);
- result = result && String.Equals(other.Kind, this.Kind);
- if (other.CalleeProc != null && this.CalleeProc != null)
- result = result && String.Equals(other.CalleeProc, this.CalleeProc);
- result = result && String.Equals(other.RefutationSite, this.RefutationSite);
- }
-
- return result;
- }
- }
-
- private void PrintRefutedCall(CallCounterexample err, XmlSink xmlOut) {
- Expr cond = err.FailingRequires.Condition;
- Variable houdiniConst;
- if (MatchCandidate(cond, out houdiniConst)) {
- xmlOut.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, err.Trace);
- }
- }
-
- private void PrintRefutedReturn(ReturnCounterexample err, XmlSink xmlOut) {
- Expr cond = err.FailingEnsures.Condition;
- Variable houdiniConst;
- if (MatchCandidate(cond, out houdiniConst)) {
- xmlOut.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, err.Trace);
- }
- }
-
- private void PrintRefutedAssert(AssertCounterexample err, XmlSink xmlOut) {
- Expr cond = err.FailingAssert.OrigExpr;
- Variable houdiniConst;
- if (MatchCandidate(cond, out houdiniConst)) {
- xmlOut.WriteError("postcondition violation", err.FailingAssert.tok, err.FailingAssert.tok, err.Trace);
- }
- }
-
- protected void DebugRefutedCandidates(Implementation curFunc, List<Counterexample> errors) {
- XmlSink xmlRefuted = CommandLineOptions.Clo.XmlRefuted;
- if (xmlRefuted != null && errors != null) {
- DateTime start = DateTime.UtcNow;
- xmlRefuted.WriteStartMethod(curFunc.ToString(), start);
-
- foreach (Counterexample error in errors) {
- CallCounterexample ce = error as CallCounterexample;
- if (ce != null) PrintRefutedCall(ce, xmlRefuted);
- ReturnCounterexample re = error as ReturnCounterexample;
- if (re != null) PrintRefutedReturn(re, xmlRefuted);
- AssertCounterexample ae = error as AssertCounterexample;
- if (ae != null) PrintRefutedAssert(ae, xmlRefuted);
- }
-
- DateTime end = DateTime.UtcNow;
- xmlRefuted.WriteEndMethod("errors", end, end.Subtract(start));
- }
- }
-
- private RefutedAnnotation ExtractRefutedAnnotation(Counterexample error) {
- Variable houdiniConstant;
- CallCounterexample callCounterexample = error as CallCounterexample;
- if (callCounterexample != null) {
- Procedure failingProcedure = callCounterexample.FailingCall.Proc;
- Requires failingRequires = callCounterexample.FailingRequires;
- if (MatchCandidate(failingRequires.Condition, out houdiniConstant)) {
- Contract.Assert(houdiniConstant != null);
- return RefutedAnnotation.BuildRefutedRequires(houdiniConstant, failingProcedure, currentHoudiniState.Implementation);
- }
- }
- ReturnCounterexample returnCounterexample = error as ReturnCounterexample;
- if (returnCounterexample != null) {
- Ensures failingEnsures = returnCounterexample.FailingEnsures;
- if (MatchCandidate(failingEnsures.Condition, out houdiniConstant)) {
- Contract.Assert(houdiniConstant != null);
- return RefutedAnnotation.BuildRefutedEnsures(houdiniConstant, currentHoudiniState.Implementation);
- }
- }
- AssertCounterexample assertCounterexample = error as AssertCounterexample;
- if (assertCounterexample != null) {
- AssertCmd failingAssert = assertCounterexample.FailingAssert;
- if (MatchCandidate(failingAssert.OrigExpr, out houdiniConstant)) {
- Contract.Assert(houdiniConstant != null);
- return RefutedAnnotation.BuildRefutedAssert(houdiniConstant, currentHoudiniState.Implementation);
- }
- }
-
- return null;
- }
-
- private ProverInterface.Outcome TryCatchVerify(HoudiniSession session, int stage, IEnumerable<int> completedStages, out List<Counterexample> errors) {
- ProverInterface.Outcome outcome;
- try {
- outcome = session.Verify(proverInterface, GetAssignmentWithStages(stage, completedStages), out errors, taskID: GetTaskID());
- }
- catch (UnexpectedProverOutputException upo) {
- Contract.Assume(upo != null);
- errors = null;
- outcome = ProverInterface.Outcome.Undetermined;
- }
- return outcome;
- }
-
- protected Dictionary<Variable, bool> GetAssignmentWithStages(int currentStage, IEnumerable<int> completedStages)
- {
- Dictionary<Variable, bool> result = new Dictionary<Variable, bool>(currentHoudiniState.Assignment);
- foreach (var c in program.Constants)
- {
- int stageActive = QKeyValue.FindIntAttribute(c.Attributes, "stage_active", -1);
- if (stageActive != -1)
- {
- result[c] = (stageActive == currentStage);
- }
- int stageComplete = QKeyValue.FindIntAttribute(c.Attributes, "stage_complete", -1);
- if (stageComplete != -1)
- {
- result[c] = (completedStages.Contains(stageComplete));
- }
- }
- return result;
- }
-
- private void HoudiniVerifyCurrent(HoudiniSession session, int stage, IEnumerable<int> completedStages) {
- while (true) {
- this.NotifyAssignment(currentHoudiniState.Assignment);
-
- //check the VC with the current assignment
- List<Counterexample> errors;
- ProverInterface.Outcome outcome = TryCatchVerify(session, stage, completedStages, out errors);
- this.NotifyOutcome(outcome);
-
- DebugRefutedCandidates(currentHoudiniState.Implementation, errors);
-
- #region Explain Houdini
- if (CommandLineOptions.Clo.ExplainHoudini && outcome == ProverInterface.Outcome.Invalid)
- {
- Contract.Assume(errors != null);
- // make a copy of this variable
- errors = new List<Counterexample>(errors);
- var refutedAnnotations = new List<RefutedAnnotation>();
- foreach (Counterexample error in errors)
- {
- RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
- if (refutedAnnotation == null || refutedAnnotation.Kind == RefutedAnnotationKind.ASSERT) continue;
- refutedAnnotations.Add(refutedAnnotation);
- }
- foreach (var refutedAnnotation in refutedAnnotations)
- {
- session.Explain(proverInterface, currentHoudiniState.Assignment, refutedAnnotation.Constant);
- }
- }
- #endregion
-
- if (UpdateHoudiniOutcome(currentHoudiniState.Outcome, currentHoudiniState.Implementation, outcome, errors)) { // abort
- currentHoudiniState.WorkQueue.Dequeue();
- this.NotifyDequeue();
- FlushWorkList(stage, completedStages);
- return;
- }
- else if (UpdateAssignmentWorkList(outcome, errors)) {
- if (CommandLineOptions.Clo.UseUnsatCoreForContractInfer && outcome == ProverInterface.Outcome.Valid)
- session.UpdateUnsatCore(proverInterface, currentHoudiniState.Assignment);
- currentHoudiniState.WorkQueue.Dequeue();
- this.NotifyDequeue();
- return;
- }
- }
- }
-
- /// <summary>
- /// Transforms given program based on Houdini outcome. If a constant is assigned "true",
- /// any preconditions or postconditions guarded by the constant are made free, and any assertions
- /// guarded by the constant are replaced with assumptions.
- ///
- /// If a constant is assigned "false", any preconditions or postconditions
- /// guarded by the constant are replaced with "true", and assertions guarded by the constant
- /// are removed.
- ///
- /// In addition, all Houdini constants are removed from the program.
- /// </summary>
- public static void ApplyAssignment(Program prog, HoudiniOutcome outcome) {
-
- var Candidates = prog.TopLevelDeclarations.OfType<Constant>().Where
- (Item => QKeyValue.FindBoolAttribute(Item.Attributes, "existential")).Select(Item => Item.Name);
-
- // Treat all assertions
- // TODO: do we need to also consider assumptions?
- foreach (Block block in prog.Implementations.Select(item => item.Blocks).SelectMany(item => item)) {
- List<Cmd> newCmds = new List<Cmd>();
- foreach (Cmd cmd in block.Cmds) {
- string c;
- AssertCmd assertCmd = cmd as AssertCmd;
- if (assertCmd != null && MatchCandidate(assertCmd.Expr, Candidates, out c)) {
- var cVar = outcome.assignment.Keys.Where(item => item.Equals(c)).ToList()[0];
- if (outcome.assignment[cVar]) {
- Dictionary<Variable, Expr> cToTrue = new Dictionary<Variable, Expr>();
- Variable cVarProg = prog.Variables.Where(item => item.Name.Equals(c)).ToList()[0];
- cToTrue[cVarProg] = Expr.True;
- newCmds.Add(new AssumeCmd(assertCmd.tok,
- Substituter.Apply(Substituter.SubstitutionFromHashtable(cToTrue), assertCmd.Expr),
- assertCmd.Attributes));
- }
- }
- else {
- newCmds.Add(cmd);
- }
- }
- block.Cmds = newCmds;
- }
-
- foreach (var proc in prog.Procedures) {
- List<Requires> newRequires = new List<Requires>();
- foreach (Requires r in proc.Requires) {
- string c;
- if (MatchCandidate(r.Condition, Candidates, out c)) {
- var cVar = outcome.assignment.Keys.Where(item => item.Equals(c)).ToList()[0];
- if (outcome.assignment[cVar]) {
- Variable cVarProg = prog.Variables.Where(item => item.Name.Equals(c)).ToList()[0];
- Dictionary<Variable, Expr> subst = new Dictionary<Variable, Expr>();
- subst[cVarProg] = Expr.True;
- newRequires.Add(new Requires(Token.NoToken, true,
- Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), r.Condition),
- r.Comment, r.Attributes));
- }
- }
- else {
- newRequires.Add(r);
- }
- }
- proc.Requires = newRequires;
-
- List<Ensures> newEnsures = new List<Ensures>();
- foreach (Ensures e in proc.Ensures) {
- string c;
- if (MatchCandidate(e.Condition, Candidates, out c)) {
- var cVar = outcome.assignment.Keys.Where(item => item.Equals(c)).ToList()[0];
- if (outcome.assignment[cVar]) {
- Variable cVarProg = prog.Variables.Where(item => item.Name.Equals(c)).ToList()[0];
- Dictionary<Variable, Expr> subst = new Dictionary<Variable, Expr>();
- subst[cVarProg] = Expr.True;
- newEnsures.Add(new Ensures(Token.NoToken, true,
- Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), e.Condition),
- e.Comment, e.Attributes));
- }
- }
- else {
- newEnsures.Add(e);
- }
- }
- proc.Ensures = newEnsures;
- }
-
- // Remove the existential constants
- prog.RemoveTopLevelDeclarations(item => (item is Constant) &&
- (Candidates.Any(item2 => item2.Equals((item as Constant).Name))));
- }
-
- }
-
- public class VCGenOutcome {
- public VCGen.Outcome outcome;
- public List<Counterexample> errors;
- public VCGenOutcome(ProverInterface.Outcome outcome, List<Counterexample> errors) {
- this.outcome = ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
- this.errors = errors;
- }
- }
-
- public class HoudiniOutcome {
- // final assignment
- public Dictionary<string, bool> assignment = new Dictionary<string, bool>();
- // boogie errors
- public Dictionary<string, VCGenOutcome> implementationOutcomes = new Dictionary<string, VCGenOutcome>();
-
- // statistics
-
- private int CountResults(VCGen.Outcome outcome) {
- int outcomeCount = 0;
- foreach (VCGenOutcome verifyOutcome in implementationOutcomes.Values) {
- if (verifyOutcome.outcome == outcome)
- outcomeCount++;
- }
- return outcomeCount;
- }
-
- private List<string> ListOutcomeMatches(VCGen.Outcome outcome) {
- List<string> result = new List<string>();
- foreach (KeyValuePair<string, VCGenOutcome> kvpair in implementationOutcomes) {
- if (kvpair.Value.outcome == outcome)
- result.Add(kvpair.Key);
- }
- return result;
- }
-
- public int ErrorCount {
- get {
- return CountResults(VCGen.Outcome.Errors);
- }
- }
- public int Verified {
- get {
- return CountResults(VCGen.Outcome.Correct);
- }
- }
- public int Inconclusives {
- get {
- return CountResults(VCGen.Outcome.Inconclusive);
- }
- }
- public int TimeOuts {
- get {
- return CountResults(VCGen.Outcome.TimedOut);
- }
- }
- public List<string> ListOfTimeouts {
- get {
- return ListOutcomeMatches(VCGen.Outcome.TimedOut);
- }
- }
- public List<string> ListOfInconclusives {
- get {
- return ListOutcomeMatches(VCGen.Outcome.Inconclusive);
- }
- }
- public List<string> ListOfErrors {
- get {
- return ListOutcomeMatches(VCGen.Outcome.Errors);
- }
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using VC;
+using System.Collections;
+using System.IO;
+using Microsoft.Boogie.GraphUtil;
+using System.Linq;
+using System.Diagnostics;
+
+namespace Microsoft.Boogie.Houdini {
+
+ internal class ReadOnlyDictionary<K, V> {
+ private Dictionary<K, V> dictionary;
+ public ReadOnlyDictionary(Dictionary<K, V> dictionary) {
+ this.dictionary = dictionary;
+ }
+
+ public Dictionary<K, V>.KeyCollection Keys {
+ get { return this.dictionary.Keys; }
+ }
+
+ public bool TryGetValue(K k, out V v) {
+ return this.dictionary.TryGetValue(k, out v);
+ }
+
+ public bool ContainsKey(K k) {
+ return this.dictionary.ContainsKey(k);
+ }
+ }
+
+ public abstract class HoudiniObserver {
+ public virtual void UpdateStart(Program program, int numConstants) { }
+ public virtual void UpdateIteration() { }
+ public virtual void UpdateImplementation(Implementation implementation) { }
+ public virtual void UpdateAssignment(Dictionary<Variable, bool> assignment) { }
+ public virtual void UpdateOutcome(ProverInterface.Outcome outcome) { }
+ public virtual void UpdateEnqueue(Implementation implementation) { }
+ public virtual void UpdateDequeue() { }
+ public virtual void UpdateConstant(string constantName) { }
+ public virtual void UpdateEnd(bool isNormalEnd) { }
+ public virtual void UpdateFlushStart() { }
+ public virtual void UpdateFlushFinish() { }
+ public virtual void SeeException(string msg) { }
+ }
+
+ public class IterationTimer<K> {
+ private Dictionary<K, List<double>> times;
+
+ public IterationTimer() {
+ times = new Dictionary<K, List<double>>();
+ }
+
+ public void AddTime(K key, double timeMS) {
+ List<double> oldList;
+ times.TryGetValue(key, out oldList);
+ if (oldList == null) {
+ oldList = new List<double>();
+ }
+ else {
+ times.Remove(key);
+ }
+ oldList.Add(timeMS);
+ times.Add(key, oldList);
+ }
+
+ public void PrintTimes(TextWriter wr) {
+ wr.WriteLine("Total procedures: {0}", times.Count);
+ double total = 0;
+ int totalIters = 0;
+ foreach (KeyValuePair<K, List<double>> kv in times) {
+ int curIter = 0;
+ wr.WriteLine("Times for {0}:", kv.Key);
+ foreach (double v in kv.Value) {
+ wr.WriteLine(" ({0})\t{1}ms", curIter, v);
+ total += v;
+ curIter++;
+ }
+ totalIters += curIter;
+ }
+ total = total / 1000.0;
+ wr.WriteLine("Total time: {0} (s)", total);
+ wr.WriteLine("Avg: {0} (s/iter)", total / totalIters);
+ }
+ }
+
+ public class HoudiniTimer : HoudiniObserver {
+ private DateTime startT;
+ private Implementation curImp;
+ private IterationTimer<string> times;
+ private TextWriter wr;
+
+ public HoudiniTimer(TextWriter wr) {
+ this.wr = wr;
+ times = new IterationTimer<string>();
+ }
+ public override void UpdateIteration() {
+ startT = DateTime.UtcNow;
+ }
+ public override void UpdateImplementation(Implementation implementation) {
+ curImp = implementation;
+ }
+ public override void UpdateOutcome(ProverInterface.Outcome o) {
+ Contract.Assert(curImp != null);
+ DateTime endT = DateTime.UtcNow;
+ times.AddTime(curImp.Name, (endT - startT).TotalMilliseconds); // assuming names are unique
+ }
+ public void PrintTimes() {
+ wr.WriteLine("-----------------------------------------");
+ wr.WriteLine("Times for each iteration for each procedure");
+ wr.WriteLine("-----------------------------------------");
+ times.PrintTimes(wr);
+ }
+ }
+
+ public class HoudiniTextReporter : HoudiniObserver {
+ private TextWriter wr;
+ private int currentIteration = -1;
+
+ public HoudiniTextReporter(TextWriter wr) {
+ this.wr = wr;
+ }
+ public override void UpdateStart(Program program, int numConstants) {
+ wr.WriteLine("Houdini started:" + program.ToString() + " #constants: " + numConstants.ToString());
+ currentIteration = -1;
+ wr.Flush();
+ }
+ public override void UpdateIteration() {
+ currentIteration++;
+ wr.WriteLine("---------------------------------------");
+ wr.WriteLine("Houdini iteration #" + currentIteration);
+ wr.Flush();
+ }
+ public override void UpdateImplementation(Implementation implementation) {
+ wr.WriteLine("implementation under analysis :" + implementation.Name);
+ wr.Flush();
+ }
+ public override void UpdateAssignment(Dictionary<Variable, bool> assignment) {
+ bool firstTime = true;
+ wr.Write("assignment under analysis : axiom (");
+ foreach (KeyValuePair<Variable, bool> kv in assignment) {
+ if (!firstTime) wr.Write(" && "); else firstTime = false;
+ string valString; // ugliness to get it lower cased
+ if (kv.Value) valString = "true"; else valString = "false";
+ wr.Write(kv.Key + " == " + valString);
+ }
+ wr.WriteLine(");");
+ wr.Flush();
+ }
+ public override void UpdateOutcome(ProverInterface.Outcome outcome) {
+ wr.WriteLine("analysis outcome :" + outcome);
+ wr.Flush();
+ }
+ public override void UpdateEnqueue(Implementation implementation) {
+ wr.WriteLine("worklist enqueue :" + implementation.Name);
+ wr.Flush();
+ }
+ public override void UpdateDequeue() {
+ wr.WriteLine("worklist dequeue");
+ wr.Flush();
+ }
+ public override void UpdateConstant(string constantName) {
+ wr.WriteLine("constant disabled : " + constantName);
+ wr.Flush();
+ }
+ public override void UpdateEnd(bool isNormalEnd) {
+ wr.WriteLine("Houdini ended: " + (isNormalEnd ? "Normal" : "Abnormal"));
+ wr.WriteLine("Number of iterations: " + (this.currentIteration + 1));
+ wr.Flush();
+ }
+ public override void UpdateFlushStart() {
+ wr.WriteLine("***************************************");
+ wr.WriteLine("Flushing remaining implementations");
+ wr.Flush();
+ }
+ public override void UpdateFlushFinish() {
+ wr.WriteLine("***************************************");
+ wr.WriteLine("Flushing finished");
+ wr.Flush();
+ }
+ public override void SeeException(string msg) {
+ wr.WriteLine("Caught exception: " + msg);
+ wr.Flush();
+ }
+
+ }
+
+ public abstract class ObservableHoudini {
+ private List<HoudiniObserver> observers = new List<HoudiniObserver>();
+
+ public void AddObserver(HoudiniObserver observer) {
+ if (!observers.Contains(observer))
+ observers.Add(observer);
+ }
+ private delegate void NotifyDelegate(HoudiniObserver observer);
+
+ private void Notify(NotifyDelegate notifyDelegate) {
+ foreach (HoudiniObserver observer in observers) {
+ notifyDelegate(observer);
+ }
+ }
+ protected void NotifyStart(Program program, int numConstants) {
+ NotifyDelegate notifyDelegate = (NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateStart(program, numConstants); };
+ Notify(notifyDelegate);
+ }
+ protected void NotifyIteration() {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateIteration(); });
+ }
+ protected void NotifyImplementation(Implementation implementation) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateImplementation(implementation); });
+ }
+ protected void NotifyAssignment(Dictionary<Variable, bool> assignment) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateAssignment(assignment); });
+ }
+ protected void NotifyOutcome(ProverInterface.Outcome outcome) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateOutcome(outcome); });
+ }
+ protected void NotifyEnqueue(Implementation implementation) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateEnqueue(implementation); });
+ }
+ protected void NotifyDequeue() {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateDequeue(); });
+ }
+ protected void NotifyConstant(string constantName) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateConstant(constantName); });
+ }
+ protected void NotifyEnd(bool isNormalEnd) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateEnd(isNormalEnd); });
+ }
+ protected void NotifyFlushStart() {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateFlushStart(); });
+ }
+ protected void NotifyFlushFinish() {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.UpdateFlushFinish(); });
+ }
+
+ protected void NotifyException(string msg) {
+ Notify((NotifyDelegate)delegate(HoudiniObserver r) { r.SeeException(msg); });
+ }
+ }
+
+ public class InlineEnsuresVisitor : ReadOnlyVisitor {
+ public override Ensures VisitEnsures(Ensures ensures)
+ {
+ if (!ensures.Free)
+ {
+ ensures.Attributes = new QKeyValue(Token.NoToken, "InlineAssume", new List<object>(), ensures.Attributes);
+ }
+ return base.VisitEnsures(ensures);
+ }
+ }
+
+ public class Houdini : ObservableHoudini {
+ protected Program program;
+ protected HashSet<Variable> houdiniConstants;
+ protected VCGen vcgen;
+ protected ProverInterface proverInterface;
+ protected Graph<Implementation> callGraph;
+ protected HashSet<Implementation> vcgenFailures;
+ protected HoudiniState currentHoudiniState;
+ protected CrossDependencies crossDependencies;
+ internal ReadOnlyDictionary<Implementation, HoudiniSession> houdiniSessions;
+
+ protected string cexTraceFile;
+
+ public HoudiniState CurrentHoudiniState { get { return currentHoudiniState; } }
+
+ public static TextWriter explainHoudiniDottyFile;
+
+ protected Houdini() { }
+
+ public Houdini(Program program, HoudiniSession.HoudiniStatistics stats, string cexTraceFile = "houdiniCexTrace.txt") {
+ this.program = program;
+ this.cexTraceFile = cexTraceFile;
+ Initialize(program, stats);
+ }
+
+ protected void Initialize(Program program, HoudiniSession.HoudiniStatistics stats)
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Collecting existential constants...");
+ this.houdiniConstants = CollectExistentialConstants();
+
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Building call graph...");
+ this.callGraph = Program.BuildCallGraph(program);
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Number of implementations = {0}", callGraph.Nodes.Count);
+
+ if (CommandLineOptions.Clo.HoudiniUseCrossDependencies)
+ {
+ if (CommandLineOptions.Clo.Trace) Console.WriteLine("Computing procedure cross dependencies ...");
+ this.crossDependencies = new CrossDependencies(this.houdiniConstants);
+ this.crossDependencies.Visit(program);
+ }
+
+ Inline();
+ /*
+ {
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 1;
+ using (TokenTextWriter stream = new TokenTextWriter("houdini_inline.bpl"))
+ {
+ program.Emit(stream);
+ }
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+ */
+
+ this.vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List<Checker>());
+ this.proverInterface = ProverInterface.CreateProver(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, CommandLineOptions.Clo.ProverKillTime, taskID: GetTaskID());
+
+ vcgenFailures = new HashSet<Implementation>();
+ Dictionary<Implementation, HoudiniSession> houdiniSessions = new Dictionary<Implementation, HoudiniSession>();
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Beginning VC generation for Houdini...");
+ foreach (Implementation impl in callGraph.Nodes)
+ {
+ try
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("Generating VC for {0}", impl.Name);
+ HoudiniSession session = new HoudiniSession(this, vcgen, proverInterface, program, impl, stats, taskID: GetTaskID());
+ houdiniSessions.Add(impl, session);
+ }
+ catch (VCGenException)
+ {
+ if (CommandLineOptions.Clo.Trace)
+ Console.WriteLine("VC generation failed");
+ vcgenFailures.Add(impl);
+ }
+ }
+ this.houdiniSessions = new ReadOnlyDictionary<Implementation, HoudiniSession>(houdiniSessions);
+
+ if (CommandLineOptions.Clo.ExplainHoudini)
+ {
+ // Print results of ExplainHoudini to a dotty file
+ explainHoudiniDottyFile = new StreamWriter("explainHoudini.dot");
+ explainHoudiniDottyFile.WriteLine("digraph explainHoudini {");
+ foreach (var constant in houdiniConstants)
+ explainHoudiniDottyFile.WriteLine("{0} [ label = \"{0}\" color=black ];", constant.Name);
+ explainHoudiniDottyFile.WriteLine("TimeOut [label = \"TimeOut\" color=red ];");
+ }
+ }
+
+ protected void Inline() {
+ if (CommandLineOptions.Clo.InlineDepth <= 0)
+ return;
+
+ foreach (Implementation impl in callGraph.Nodes) {
+ InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
+ inlineEnsuresVisitor.Visit(impl);
+ }
+
+ foreach (Implementation impl in callGraph.Nodes) {
+ impl.OriginalBlocks = impl.Blocks;
+ impl.OriginalLocVars = impl.LocVars;
+ }
+ foreach (Implementation impl in callGraph.Nodes) {
+ CommandLineOptions.Inlining savedOption = CommandLineOptions.Clo.ProcedureInlining;
+ CommandLineOptions.Clo.ProcedureInlining = CommandLineOptions.Inlining.Spec;
+ Inliner.ProcessImplementationForHoudini(program, impl);
+ CommandLineOptions.Clo.ProcedureInlining = savedOption;
+ }
+ foreach (Implementation impl in callGraph.Nodes) {
+ impl.OriginalBlocks = null;
+ impl.OriginalLocVars = null;
+ }
+
+ Graph<Implementation> oldCallGraph = callGraph;
+ callGraph = new Graph<Implementation>();
+ foreach (Implementation impl in oldCallGraph.Nodes) {
+ callGraph.AddSource(impl);
+ }
+ foreach (Tuple<Implementation, Implementation> edge in oldCallGraph.Edges) {
+ callGraph.AddEdge(edge.Item1, edge.Item2);
+ }
+ int count = CommandLineOptions.Clo.InlineDepth;
+ while (count > 0) {
+ foreach (Implementation impl in oldCallGraph.Nodes) {
+ List<Implementation> newNodes = new List<Implementation>();
+ foreach (Implementation succ in callGraph.Successors(impl)) {
+ newNodes.AddRange(oldCallGraph.Successors(succ));
+ }
+ foreach (Implementation newNode in newNodes) {
+ callGraph.AddEdge(impl, newNode);
+ }
+ }
+ count--;
+ }
+ }
+
+ protected HashSet<Variable> CollectExistentialConstants() {
+ HashSet<Variable> existentialConstants = new HashSet<Variable>();
+ foreach (var constant in program.Constants) {
+ bool result = false;
+ if (constant.CheckBooleanAttribute("existential", ref result)) {
+ if (result == true)
+ existentialConstants.Add(constant);
+ }
+ }
+ return existentialConstants;
+ }
+
+ // Compute dependencies between candidates
+ public class CrossDependencies : ReadOnlyVisitor
+ {
+ public CrossDependencies(HashSet<Variable> constants)
+ {
+ this.constants = constants;
+ }
+
+ public override Program VisitProgram(Program node)
+ {
+ assumedInImpl = new Dictionary<string, HashSet<Implementation>>();
+ return base.VisitProgram(node);
+ }
+
+ public override Implementation VisitImplementation(Implementation node)
+ {
+ curImpl = node;
+ return base.VisitImplementation(node);
+ }
+
+ public override Cmd VisitAssumeCmd(AssumeCmd node)
+ {
+ return base.VisitAssumeCmd(node);
+ }
+
+ public override Variable VisitVariable(Variable node)
+ {
+ if (node is Constant)
+ {
+ var constant = node as Constant;
+ if (constants.Contains(constant))
+ {
+ if (!assumedInImpl.ContainsKey(constant.Name))
+ assumedInImpl[constant.Name] = new HashSet<Implementation>();
+ assumedInImpl[constant.Name].Add(curImpl);
+ }
+ }
+ return base.VisitVariable(node);
+ }
+
+ HashSet<Variable> constants;
+ Implementation curImpl;
+
+ // contant -> set of implementations that have an assume command with that constant
+ public Dictionary<string, HashSet<Implementation>> assumedInImpl { get; private set; }
+ }
+
+ protected WorkQueue BuildWorkList(Program program) {
+ // adding implementations to the workqueue from the bottom of the call graph upwards
+ WorkQueue queue = new WorkQueue();
+ StronglyConnectedComponents<Implementation> sccs =
+ new StronglyConnectedComponents<Implementation>(callGraph.Nodes,
+ new Adjacency<Implementation>(callGraph.Predecessors),
+ new Adjacency<Implementation>(callGraph.Successors));
+ sccs.Compute();
+ foreach (SCC<Implementation> scc in sccs) {
+ foreach (Implementation impl in scc) {
+ if (vcgenFailures.Contains(impl)) continue;
+ queue.Enqueue(impl);
+ }
+ }
+ if (CommandLineOptions.Clo.ReverseHoudiniWorklist)
+ queue = queue.Reverse();
+ return queue;
+ /*
+ Queue<Implementation> queue = new Queue<Implementation>();
+ foreach (Declaration decl in program.TopLevelDeclarations) {
+ Implementation impl = decl as Implementation;
+ if (impl == null || impl.SkipVerification) continue;
+ queue.Enqueue(impl);
+ }
+ return queue;
+ */
+ }
+
+ public static bool MatchCandidate(Expr boogieExpr, IEnumerable<string> candidates, out string candidateConstant) {
+ candidateConstant = null;
+ NAryExpr e = boogieExpr as NAryExpr;
+ if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp) {
+ Expr antecedent = e.Args[0];
+ Expr consequent = e.Args[1];
+
+ IdentifierExpr id = antecedent as IdentifierExpr;
+ if (id != null && id.Decl is Constant && candidates.Contains(id.Decl.Name)) {
+ candidateConstant = id.Decl.Name;
+ return true;
+ }
+
+ if (MatchCandidate(consequent, candidates, out candidateConstant))
+ return true;
+ }
+ return false;
+ }
+
+ public static bool GetCandidateWithoutConstant(Expr boogieExpr, IEnumerable<string> candidates, out string candidateConstant, out Expr exprWithoutConstant) {
+ candidateConstant = null;
+ exprWithoutConstant = null;
+ NAryExpr e = boogieExpr as NAryExpr;
+ if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp) {
+ Expr antecedent = e.Args[0];
+ Expr consequent = e.Args[1];
+
+ IdentifierExpr id = antecedent as IdentifierExpr;
+ if (id != null && id.Decl is Constant && candidates.Contains(id.Decl.Name)) {
+ candidateConstant = id.Decl.Name;
+ exprWithoutConstant = consequent;
+ return true;
+ }
+
+ if (GetCandidateWithoutConstant(consequent, candidates, out candidateConstant, out exprWithoutConstant))
+ {
+ exprWithoutConstant = Expr.Imp(antecedent, exprWithoutConstant);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Expr AddConditionToCandidateRec(Expr boogieExpr, Expr condition, string candidateConstant, List<Expr> implicationStack)
+ {
+ NAryExpr e = boogieExpr as NAryExpr;
+ if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp)
+ {
+ Expr antecedent = e.Args[0];
+ Expr consequent = e.Args[1];
+
+ IdentifierExpr id = antecedent as IdentifierExpr;
+ if (id != null && id.Decl is Constant && id.Decl.Name.Equals(candidateConstant))
+ {
+ Expr result = Expr.Imp(antecedent, Expr.Imp(condition, consequent));
+ implicationStack.Reverse();
+ foreach (var expr in implicationStack)
+ {
+ result = Expr.Imp(expr, result);
+ }
+ return result;
+ }
+
+ implicationStack.Add(antecedent);
+ return AddConditionToCandidateRec(consequent, condition, candidateConstant,
+ implicationStack);
+ }
+ return boogieExpr;
+ }
+
+ public static Expr AddConditionToCandidate(Expr boogieExpr, Expr condition, string candidateConstant)
+ {
+ return AddConditionToCandidateRec(boogieExpr, condition, candidateConstant, new List<Expr>());
+ }
+
+ public bool MatchCandidate(Expr boogieExpr, out Variable candidateConstant) {
+ candidateConstant = null;
+ string candidateString;
+ if(MatchCandidate(boogieExpr, houdiniConstants.Select(item => item.Name), out candidateString)) {
+ candidateConstant = houdiniConstants.Where(item => item.Name.Equals(candidateString)).ToList()[0];
+ return true;
+ }
+ return false;
+ }
+
+ public bool MatchCandidate(Expr boogieExpr, out string candidateConstant) {
+ return MatchCandidate(boogieExpr, houdiniConstants.Select(item => item.Name), out candidateConstant);
+ }
+
+ // For Explain houdini: it decorates the condition \phi as (vpos && (\phi || \not vneg))
+ // Precondition: MatchCandidate returns true
+ public Expr InsertCandidateControl(Expr boogieExpr, Variable vpos, Variable vneg)
+ {
+ Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);
+
+ NAryExpr e = boogieExpr as NAryExpr;
+ if (e != null && e.Fun is BinaryOperator && ((BinaryOperator)e.Fun).Op == BinaryOperator.Opcode.Imp)
+ {
+ Expr antecedent = e.Args[0];
+ Expr consequent = e.Args[1];
+
+ IdentifierExpr id = antecedent as IdentifierExpr;
+ if (id != null && id.Decl is Constant && houdiniConstants.Contains((Constant)id.Decl))
+ {
+ return Expr.Imp(antecedent, Expr.And(Expr.Ident(vpos), Expr.Or(consequent, Expr.Not(Expr.Ident(vneg)))));
+ }
+
+ return Expr.Imp(antecedent, InsertCandidateControl(consequent, vpos, vneg));
+ }
+ Contract.Assert(false);
+ return null;
+ }
+
+ protected Dictionary<Variable, bool> BuildAssignment(HashSet<Variable> constants) {
+ Dictionary<Variable, bool> initial = new Dictionary<Variable, bool>();
+ foreach (var constant in constants)
+ initial.Add(constant, true);
+ return initial;
+ }
+
+ private bool IsOutcomeNotHoudini(ProverInterface.Outcome outcome, List<Counterexample> errors) {
+ switch (outcome) {
+ case ProverInterface.Outcome.Valid:
+ return false;
+ case ProverInterface.Outcome.Invalid:
+ Contract.Assume(errors != null);
+ foreach (Counterexample error in errors) {
+ if (ExtractRefutedAnnotation(error) == null)
+ return true;
+ }
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ // Record most current non-candidate errors found
+ // Return true if there was at least one non-candidate error
+ protected bool UpdateHoudiniOutcome(HoudiniOutcome houdiniOutcome,
+ Implementation implementation,
+ ProverInterface.Outcome outcome,
+ List<Counterexample> errors) {
+ string implName = implementation.Name;
+ houdiniOutcome.implementationOutcomes.Remove(implName);
+ List<Counterexample> nonCandidateErrors = new List<Counterexample>();
+
+ if (outcome == ProverInterface.Outcome.Invalid) {
+ foreach (Counterexample error in errors) {
+ if (ExtractRefutedAnnotation(error) == null)
+ nonCandidateErrors.Add(error);
+ }
+ }
+ houdiniOutcome.implementationOutcomes.Add(implName, new VCGenOutcome(outcome, nonCandidateErrors));
+ return nonCandidateErrors.Count > 0;
+ }
+
+ protected void FlushWorkList(int stage, IEnumerable<int> completedStages) {
+ this.NotifyFlushStart();
+ while (currentHoudiniState.WorkQueue.Count > 0) {
+ this.NotifyIteration();
+
+ currentHoudiniState.Implementation = currentHoudiniState.WorkQueue.Peek();
+ this.NotifyImplementation(currentHoudiniState.Implementation);
+
+ HoudiniSession session;
+ houdiniSessions.TryGetValue(currentHoudiniState.Implementation, out session);
+ List<Counterexample> errors;
+ ProverInterface.Outcome outcome = TryCatchVerify(session, stage, completedStages, out errors);
+ UpdateHoudiniOutcome(currentHoudiniState.Outcome, currentHoudiniState.Implementation, outcome, errors);
+ this.NotifyOutcome(outcome);
+
+ currentHoudiniState.WorkQueue.Dequeue();
+ this.NotifyDequeue();
+ }
+ this.NotifyFlushFinish();
+ }
+
+ protected void UpdateAssignment(RefutedAnnotation refAnnot) {
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Removing " + refAnnot.Constant);
+ using (var cexWriter = new System.IO.StreamWriter(cexTraceFile, true))
+ cexWriter.WriteLine("Removing " + refAnnot.Constant);
+ }
+ currentHoudiniState.Assignment.Remove(refAnnot.Constant);
+ currentHoudiniState.Assignment.Add(refAnnot.Constant, false);
+ this.NotifyConstant(refAnnot.Constant.Name);
+ }
+
+ protected void AddRelatedToWorkList(RefutedAnnotation refutedAnnotation) {
+ Contract.Assume(currentHoudiniState.Implementation != null);
+ foreach (Implementation implementation in FindImplementationsToEnqueue(refutedAnnotation, refutedAnnotation.RefutationSite)) {
+ if (!currentHoudiniState.isBlackListed(implementation.Name)) {
+ currentHoudiniState.WorkQueue.Enqueue(implementation);
+ this.NotifyEnqueue(implementation);
+ }
+ }
+ }
+
+ // Updates the worklist and current assignment
+ // @return true if the current function is dequeued
+ protected bool UpdateAssignmentWorkList(ProverInterface.Outcome outcome,
+ List<Counterexample> errors) {
+ Contract.Assume(currentHoudiniState.Implementation != null);
+ bool dequeue = true;
+
+ switch (outcome) {
+ case ProverInterface.Outcome.Valid:
+ //yeah, dequeue
+ break;
+
+ case ProverInterface.Outcome.Invalid:
+ Contract.Assume(errors != null);
+
+ foreach (Counterexample error in errors) {
+ RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
+ if (refutedAnnotation != null) {
+ // some candidate annotation removed
+ ShareRefutedAnnotation(refutedAnnotation);
+ AddRelatedToWorkList(refutedAnnotation);
+ UpdateAssignment(refutedAnnotation);
+ dequeue = false;
+ #region Extra debugging output
+ if (CommandLineOptions.Clo.Trace) {
+ using (var cexWriter = new System.IO.StreamWriter(cexTraceFile, true)) {
+ cexWriter.WriteLine("Counter example for " + refutedAnnotation.Constant);
+ cexWriter.Write(error.ToString());
+ cexWriter.WriteLine();
+ using (var writer = new Microsoft.Boogie.TokenTextWriter(cexWriter, /*pretty=*/ false))
+ foreach (Microsoft.Boogie.Block blk in error.Trace)
+ blk.Emit(writer, 15);
+ //cexWriter.WriteLine();
+ }
+ }
+ #endregion
+ }
+ }
+
+ if (ExchangeRefutedAnnotations()) dequeue = false;
+
+ break;
+ default:
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Timeout/Spaceout while verifying " + currentHoudiniState.Implementation.Name);
+ }
+ HoudiniSession houdiniSession;
+ houdiniSessions.TryGetValue(currentHoudiniState.Implementation, out houdiniSession);
+ foreach (Variable v in houdiniSession.houdiniAssertConstants) {
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Removing " + v);
+ }
+ currentHoudiniState.Assignment.Remove(v);
+ currentHoudiniState.Assignment.Add(v, false);
+ this.NotifyConstant(v.Name);
+ }
+ currentHoudiniState.addToBlackList(currentHoudiniState.Implementation.Name);
+ break;
+ }
+
+ return dequeue;
+ }
+
+ // This method is a hook used by ConcurrentHoudini to
+ // exchange refuted annotations with other Houdini engines.
+ // If the method returns true, this indicates that at least
+ // one new refutation was received from some other engine.
+ // In the base class we thus return false.
+ protected virtual bool ExchangeRefutedAnnotations() {
+ return false;
+ }
+
+ // This method is a hook used by ConcurrentHoudini to
+ // apply a set of existing refuted annotations at the
+ // start of inference.
+ protected virtual void ApplyRefutedSharedAnnotations() {
+ // Empty in base class; can be overridden.
+ }
+
+ // This method is a hook used by ConcurrentHoudini to
+ // broadcast to other Houdini engines the fact that an
+ // annotation was refuted.
+ protected virtual void ShareRefutedAnnotation(RefutedAnnotation refutedAnnotation) {
+ // Empty in base class; can be overridden.
+ }
+
+ // Hook for ConcurrentHoudini, which requires a task id.
+ // Non-concurrent Houdini has -1 as a task id
+ protected virtual int GetTaskID() {
+ return -1;
+ }
+
+ public class WorkQueue {
+ private Queue<Implementation> queue;
+ private HashSet<Implementation> set;
+ public WorkQueue() {
+ queue = new Queue<Implementation>();
+ set = new HashSet<Implementation>();
+ }
+ public void Enqueue(Implementation impl) {
+ if (set.Contains(impl))
+ return;
+ queue.Enqueue(impl);
+ set.Add(impl);
+ }
+ public Implementation Dequeue() {
+ Implementation impl = queue.Dequeue();
+ set.Remove(impl);
+ return impl;
+ }
+ public Implementation Peek() {
+ return queue.Peek();
+ }
+ public int Count {
+ get { return queue.Count; }
+ }
+ public bool Contains(Implementation impl) {
+ return set.Contains(impl);
+ }
+ public WorkQueue Reverse()
+ {
+ var ret = new WorkQueue();
+ foreach (var impl in queue.Reverse())
+ ret.Enqueue(impl);
+ return ret;
+ }
+ }
+
+ public class HoudiniState {
+ public WorkQueue _workQueue;
+ public HashSet<string> blackList;
+ public Dictionary<Variable, bool> _assignment;
+ public Implementation _implementation;
+ public HoudiniOutcome _outcome;
+
+ public HoudiniState(WorkQueue workQueue, Dictionary<Variable, bool> currentAssignment) {
+ this._workQueue = workQueue;
+ this._assignment = currentAssignment;
+ this._implementation = null;
+ this._outcome = new HoudiniOutcome();
+ this.blackList = new HashSet<string>();
+ }
+
+ public WorkQueue WorkQueue {
+ get { return this._workQueue; }
+ }
+ public Dictionary<Variable, bool> Assignment {
+ get { return this._assignment; }
+ }
+ public Implementation Implementation {
+ get { return this._implementation; }
+ set { this._implementation = value; }
+ }
+ public HoudiniOutcome Outcome {
+ get { return this._outcome; }
+ }
+ public bool isBlackListed(string funcName) {
+ return blackList.Contains(funcName);
+ }
+ public void addToBlackList(string funcName) {
+ blackList.Add(funcName);
+ }
+ }
+
+ public HoudiniOutcome PerformHoudiniInference(int stage = 0,
+ IEnumerable<int> completedStages = null,
+ Dictionary<string, bool> initialAssignment = null) {
+ this.NotifyStart(program, houdiniConstants.Count);
+
+ currentHoudiniState = new HoudiniState(BuildWorkList(program), BuildAssignment(houdiniConstants));
+
+ if(initialAssignment != null) {
+ foreach(var v in CurrentHoudiniState.Assignment.Keys.ToList()) {
+ CurrentHoudiniState.Assignment[v] = initialAssignment[v.Name];
+ }
+ }
+
+ ApplyRefutedSharedAnnotations();
+
+ foreach (Implementation impl in vcgenFailures) {
+ currentHoudiniState.addToBlackList(impl.Name);
+ }
+
+ while (currentHoudiniState.WorkQueue.Count > 0) {
+ this.NotifyIteration();
+
+ currentHoudiniState.Implementation = currentHoudiniState.WorkQueue.Peek();
+ this.NotifyImplementation(currentHoudiniState.Implementation);
+
+ HoudiniSession session;
+ this.houdiniSessions.TryGetValue(currentHoudiniState.Implementation, out session);
+ HoudiniVerifyCurrent(session, stage, completedStages);
+ }
+
+ this.NotifyEnd(true);
+ Dictionary<string, bool> assignment = new Dictionary<string, bool>();
+ foreach (var x in currentHoudiniState.Assignment)
+ assignment[x.Key.Name] = x.Value;
+ currentHoudiniState.Outcome.assignment = assignment;
+ return currentHoudiniState.Outcome;
+ }
+
+ public void Close() {
+ vcgen.Close();
+ proverInterface.Close();
+ if (CommandLineOptions.Clo.ExplainHoudini)
+ {
+ explainHoudiniDottyFile.WriteLine("};");
+ explainHoudiniDottyFile.Close();
+ }
+ }
+
+ private int NumberOfStages()
+ {
+ int result = 1;
+ foreach(var c in program.Constants) {
+ result = Math.Max(result, 1 + QKeyValue.FindIntAttribute(c.Attributes, "stage_active", -1));
+ }
+ return result;
+ }
+
+ private List<Implementation> FindImplementationsToEnqueue(RefutedAnnotation refutedAnnotation, Implementation currentImplementation) {
+ HoudiniSession session;
+ List<Implementation> implementations = new List<Implementation>();
+ switch (refutedAnnotation.Kind) {
+ case RefutedAnnotationKind.REQUIRES:
+ foreach (Implementation callee in callGraph.Successors(currentImplementation))
+ {
+ if (vcgenFailures.Contains(callee)) continue;
+ houdiniSessions.TryGetValue(callee, out session);
+ Contract.Assume(callee.Proc != null);
+ if (callee.Proc.Equals(refutedAnnotation.CalleeProc) && session.InUnsatCore(refutedAnnotation.Constant))
+ implementations.Add(callee);
+ }
+ break;
+ case RefutedAnnotationKind.ENSURES:
+ foreach (Implementation caller in callGraph.Predecessors(currentImplementation))
+ {
+ if (vcgenFailures.Contains(caller)) continue;
+ houdiniSessions.TryGetValue(caller, out session);
+ if (session.InUnsatCore(refutedAnnotation.Constant))
+ implementations.Add(caller);
+ }
+ break;
+ case RefutedAnnotationKind.ASSERT: //the implementation is already in queue
+ if (CommandLineOptions.Clo.HoudiniUseCrossDependencies && crossDependencies.assumedInImpl.ContainsKey(refutedAnnotation.Constant.Name))
+ {
+ foreach (var impl in crossDependencies.assumedInImpl[refutedAnnotation.Constant.Name])
+ {
+ if (vcgenFailures.Contains(impl)) continue;
+ houdiniSessions.TryGetValue(impl, out session);
+ if (session.InUnsatCore(refutedAnnotation.Constant))
+ implementations.Add(impl);
+ }
+ }
+ break;
+ default:
+ throw new Exception("Unknown Refuted annotation kind:" + refutedAnnotation.Kind);
+ }
+ return implementations;
+ }
+
+ public enum RefutedAnnotationKind { REQUIRES, ENSURES, ASSERT };
+
+ public class RefutedAnnotation {
+ private Variable _constant;
+ private RefutedAnnotationKind _kind;
+ private Procedure _callee;
+ private Implementation _refutationSite;
+
+ private RefutedAnnotation(Variable constant, RefutedAnnotationKind kind, Procedure callee, Implementation refutationSite) {
+ this._constant = constant;
+ this._kind = kind;
+ this._callee = callee;
+ this._refutationSite = refutationSite;
+ }
+ public RefutedAnnotationKind Kind {
+ get { return this._kind; }
+ }
+ public Variable Constant {
+ get { return this._constant; }
+ }
+ public Procedure CalleeProc {
+ get { return this._callee; }
+ }
+ public Implementation RefutationSite {
+ get { return this._refutationSite; }
+ }
+ public static RefutedAnnotation BuildRefutedRequires(Variable constant, Procedure callee, Implementation refutationSite) {
+ return new RefutedAnnotation(constant, RefutedAnnotationKind.REQUIRES, callee, refutationSite);
+ }
+ public static RefutedAnnotation BuildRefutedEnsures(Variable constant, Implementation refutationSite) {
+ return new RefutedAnnotation(constant, RefutedAnnotationKind.ENSURES, null, refutationSite);
+ }
+ public static RefutedAnnotation BuildRefutedAssert(Variable constant, Implementation refutationSite) {
+ return new RefutedAnnotation(constant, RefutedAnnotationKind.ASSERT, null, refutationSite);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked {
+ int hash = 17;
+ hash = hash * 23 + this.Constant.GetHashCode();
+ hash = hash * 23 + this.Kind.GetHashCode();
+ if (this.CalleeProc != null)
+ hash = hash * 23 + this.CalleeProc.GetHashCode();
+ hash = hash * 23 + this.RefutationSite.GetHashCode();
+ return hash;
+ }
+ }
+
+ public override bool Equals(object obj) {
+ bool result = true;
+ var other = obj as RefutedAnnotation;
+
+ if (other == null) {
+ result = false;
+ } else {
+ result = result && String.Equals(other.Constant, this.Constant);
+ result = result && String.Equals(other.Kind, this.Kind);
+ if (other.CalleeProc != null && this.CalleeProc != null)
+ result = result && String.Equals(other.CalleeProc, this.CalleeProc);
+ result = result && String.Equals(other.RefutationSite, this.RefutationSite);
+ }
+
+ return result;
+ }
+ }
+
+ private void PrintRefutedCall(CallCounterexample err, XmlSink xmlOut) {
+ Expr cond = err.FailingRequires.Condition;
+ Variable houdiniConst;
+ if (MatchCandidate(cond, out houdiniConst)) {
+ xmlOut.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, err.Trace);
+ }
+ }
+
+ private void PrintRefutedReturn(ReturnCounterexample err, XmlSink xmlOut) {
+ Expr cond = err.FailingEnsures.Condition;
+ Variable houdiniConst;
+ if (MatchCandidate(cond, out houdiniConst)) {
+ xmlOut.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, err.Trace);
+ }
+ }
+
+ private void PrintRefutedAssert(AssertCounterexample err, XmlSink xmlOut) {
+ Expr cond = err.FailingAssert.OrigExpr;
+ Variable houdiniConst;
+ if (MatchCandidate(cond, out houdiniConst)) {
+ xmlOut.WriteError("postcondition violation", err.FailingAssert.tok, err.FailingAssert.tok, err.Trace);
+ }
+ }
+
+ protected void DebugRefutedCandidates(Implementation curFunc, List<Counterexample> errors) {
+ XmlSink xmlRefuted = CommandLineOptions.Clo.XmlRefuted;
+ if (xmlRefuted != null && errors != null) {
+ DateTime start = DateTime.UtcNow;
+ xmlRefuted.WriteStartMethod(curFunc.ToString(), start);
+
+ foreach (Counterexample error in errors) {
+ CallCounterexample ce = error as CallCounterexample;
+ if (ce != null) PrintRefutedCall(ce, xmlRefuted);
+ ReturnCounterexample re = error as ReturnCounterexample;
+ if (re != null) PrintRefutedReturn(re, xmlRefuted);
+ AssertCounterexample ae = error as AssertCounterexample;
+ if (ae != null) PrintRefutedAssert(ae, xmlRefuted);
+ }
+
+ DateTime end = DateTime.UtcNow;
+ xmlRefuted.WriteEndMethod("errors", end, end.Subtract(start));
+ }
+ }
+
+ private RefutedAnnotation ExtractRefutedAnnotation(Counterexample error) {
+ Variable houdiniConstant;
+ CallCounterexample callCounterexample = error as CallCounterexample;
+ if (callCounterexample != null) {
+ Procedure failingProcedure = callCounterexample.FailingCall.Proc;
+ Requires failingRequires = callCounterexample.FailingRequires;
+ if (MatchCandidate(failingRequires.Condition, out houdiniConstant)) {
+ Contract.Assert(houdiniConstant != null);
+ return RefutedAnnotation.BuildRefutedRequires(houdiniConstant, failingProcedure, currentHoudiniState.Implementation);
+ }
+ }
+ ReturnCounterexample returnCounterexample = error as ReturnCounterexample;
+ if (returnCounterexample != null) {
+ Ensures failingEnsures = returnCounterexample.FailingEnsures;
+ if (MatchCandidate(failingEnsures.Condition, out houdiniConstant)) {
+ Contract.Assert(houdiniConstant != null);
+ return RefutedAnnotation.BuildRefutedEnsures(houdiniConstant, currentHoudiniState.Implementation);
+ }
+ }
+ AssertCounterexample assertCounterexample = error as AssertCounterexample;
+ if (assertCounterexample != null) {
+ AssertCmd failingAssert = assertCounterexample.FailingAssert;
+ if (MatchCandidate(failingAssert.OrigExpr, out houdiniConstant)) {
+ Contract.Assert(houdiniConstant != null);
+ return RefutedAnnotation.BuildRefutedAssert(houdiniConstant, currentHoudiniState.Implementation);
+ }
+ }
+
+ return null;
+ }
+
+ private ProverInterface.Outcome TryCatchVerify(HoudiniSession session, int stage, IEnumerable<int> completedStages, out List<Counterexample> errors) {
+ ProverInterface.Outcome outcome;
+ try {
+ outcome = session.Verify(proverInterface, GetAssignmentWithStages(stage, completedStages), out errors, taskID: GetTaskID());
+ }
+ catch (UnexpectedProverOutputException upo) {
+ Contract.Assume(upo != null);
+ errors = null;
+ outcome = ProverInterface.Outcome.Undetermined;
+ }
+ return outcome;
+ }
+
+ protected Dictionary<Variable, bool> GetAssignmentWithStages(int currentStage, IEnumerable<int> completedStages)
+ {
+ Dictionary<Variable, bool> result = new Dictionary<Variable, bool>(currentHoudiniState.Assignment);
+ foreach (var c in program.Constants)
+ {
+ int stageActive = QKeyValue.FindIntAttribute(c.Attributes, "stage_active", -1);
+ if (stageActive != -1)
+ {
+ result[c] = (stageActive == currentStage);
+ }
+ int stageComplete = QKeyValue.FindIntAttribute(c.Attributes, "stage_complete", -1);
+ if (stageComplete != -1)
+ {
+ result[c] = (completedStages.Contains(stageComplete));
+ }
+ }
+ return result;
+ }
+
+ private void HoudiniVerifyCurrent(HoudiniSession session, int stage, IEnumerable<int> completedStages) {
+ while (true) {
+ this.NotifyAssignment(currentHoudiniState.Assignment);
+
+ //check the VC with the current assignment
+ List<Counterexample> errors;
+ ProverInterface.Outcome outcome = TryCatchVerify(session, stage, completedStages, out errors);
+ this.NotifyOutcome(outcome);
+
+ DebugRefutedCandidates(currentHoudiniState.Implementation, errors);
+
+ #region Explain Houdini
+ if (CommandLineOptions.Clo.ExplainHoudini && outcome == ProverInterface.Outcome.Invalid)
+ {
+ Contract.Assume(errors != null);
+ // make a copy of this variable
+ errors = new List<Counterexample>(errors);
+ var refutedAnnotations = new List<RefutedAnnotation>();
+ foreach (Counterexample error in errors)
+ {
+ RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
+ if (refutedAnnotation == null || refutedAnnotation.Kind == RefutedAnnotationKind.ASSERT) continue;
+ refutedAnnotations.Add(refutedAnnotation);
+ }
+ foreach (var refutedAnnotation in refutedAnnotations)
+ {
+ session.Explain(proverInterface, currentHoudiniState.Assignment, refutedAnnotation.Constant);
+ }
+ }
+ #endregion
+
+ if (UpdateHoudiniOutcome(currentHoudiniState.Outcome, currentHoudiniState.Implementation, outcome, errors)) { // abort
+ currentHoudiniState.WorkQueue.Dequeue();
+ this.NotifyDequeue();
+ FlushWorkList(stage, completedStages);
+ return;
+ }
+ else if (UpdateAssignmentWorkList(outcome, errors)) {
+ if (CommandLineOptions.Clo.UseUnsatCoreForContractInfer && outcome == ProverInterface.Outcome.Valid)
+ session.UpdateUnsatCore(proverInterface, currentHoudiniState.Assignment);
+ currentHoudiniState.WorkQueue.Dequeue();
+ this.NotifyDequeue();
+ return;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Transforms given program based on Houdini outcome. If a constant is assigned "true",
+ /// any preconditions or postconditions guarded by the constant are made free, and any assertions
+ /// guarded by the constant are replaced with assumptions.
+ ///
+ /// If a constant is assigned "false", any preconditions or postconditions
+ /// guarded by the constant are replaced with "true", and assertions guarded by the constant
+ /// are removed.
+ ///
+ /// In addition, all Houdini constants are removed from the program.
+ /// </summary>
+ public static void ApplyAssignment(Program prog, HoudiniOutcome outcome) {
+
+ var Candidates = prog.TopLevelDeclarations.OfType<Constant>().Where
+ (Item => QKeyValue.FindBoolAttribute(Item.Attributes, "existential")).Select(Item => Item.Name);
+
+ // Treat all assertions
+ // TODO: do we need to also consider assumptions?
+ foreach (Block block in prog.Implementations.Select(item => item.Blocks).SelectMany(item => item)) {
+ List<Cmd> newCmds = new List<Cmd>();
+ foreach (Cmd cmd in block.Cmds) {
+ string c;
+ AssertCmd assertCmd = cmd as AssertCmd;
+ if (assertCmd != null && MatchCandidate(assertCmd.Expr, Candidates, out c)) {
+ var cVar = outcome.assignment.Keys.Where(item => item.Equals(c)).ToList()[0];
+ if (outcome.assignment[cVar]) {
+ Dictionary<Variable, Expr> cToTrue = new Dictionary<Variable, Expr>();
+ Variable cVarProg = prog.Variables.Where(item => item.Name.Equals(c)).ToList()[0];
+ cToTrue[cVarProg] = Expr.True;
+ newCmds.Add(new AssumeCmd(assertCmd.tok,
+ Substituter.Apply(Substituter.SubstitutionFromHashtable(cToTrue), assertCmd.Expr),
+ assertCmd.Attributes));
+ }
+ }
+ else {
+ newCmds.Add(cmd);
+ }
+ }
+ block.Cmds = newCmds;
+ }
+
+ foreach (var proc in prog.Procedures) {
+ List<Requires> newRequires = new List<Requires>();
+ foreach (Requires r in proc.Requires) {
+ string c;
+ if (MatchCandidate(r.Condition, Candidates, out c)) {
+ var cVar = outcome.assignment.Keys.Where(item => item.Equals(c)).ToList()[0];
+ if (outcome.assignment[cVar]) {
+ Variable cVarProg = prog.Variables.Where(item => item.Name.Equals(c)).ToList()[0];
+ Dictionary<Variable, Expr> subst = new Dictionary<Variable, Expr>();
+ subst[cVarProg] = Expr.True;
+ newRequires.Add(new Requires(Token.NoToken, true,
+ Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), r.Condition),
+ r.Comment, r.Attributes));
+ }
+ }
+ else {
+ newRequires.Add(r);
+ }
+ }
+ proc.Requires = newRequires;
+
+ List<Ensures> newEnsures = new List<Ensures>();
+ foreach (Ensures e in proc.Ensures) {
+ string c;
+ if (MatchCandidate(e.Condition, Candidates, out c)) {
+ var cVar = outcome.assignment.Keys.Where(item => item.Equals(c)).ToList()[0];
+ if (outcome.assignment[cVar]) {
+ Variable cVarProg = prog.Variables.Where(item => item.Name.Equals(c)).ToList()[0];
+ Dictionary<Variable, Expr> subst = new Dictionary<Variable, Expr>();
+ subst[cVarProg] = Expr.True;
+ newEnsures.Add(new Ensures(Token.NoToken, true,
+ Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), e.Condition),
+ e.Comment, e.Attributes));
+ }
+ }
+ else {
+ newEnsures.Add(e);
+ }
+ }
+ proc.Ensures = newEnsures;
+ }
+
+ // Remove the existential constants
+ prog.RemoveTopLevelDeclarations(item => (item is Constant) &&
+ (Candidates.Any(item2 => item2.Equals((item as Constant).Name))));
+ }
+
+ }
+
+ public class VCGenOutcome {
+ public VCGen.Outcome outcome;
+ public List<Counterexample> errors;
+ public VCGenOutcome(ProverInterface.Outcome outcome, List<Counterexample> errors) {
+ this.outcome = ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
+ this.errors = errors;
+ }
+ }
+
+ public class HoudiniOutcome {
+ // final assignment
+ public Dictionary<string, bool> assignment = new Dictionary<string, bool>();
+ // boogie errors
+ public Dictionary<string, VCGenOutcome> implementationOutcomes = new Dictionary<string, VCGenOutcome>();
+
+ // statistics
+
+ private int CountResults(VCGen.Outcome outcome) {
+ int outcomeCount = 0;
+ foreach (VCGenOutcome verifyOutcome in implementationOutcomes.Values) {
+ if (verifyOutcome.outcome == outcome)
+ outcomeCount++;
+ }
+ return outcomeCount;
+ }
+
+ private List<string> ListOutcomeMatches(VCGen.Outcome outcome) {
+ List<string> result = new List<string>();
+ foreach (KeyValuePair<string, VCGenOutcome> kvpair in implementationOutcomes) {
+ if (kvpair.Value.outcome == outcome)
+ result.Add(kvpair.Key);
+ }
+ return result;
+ }
+
+ public int ErrorCount {
+ get {
+ return CountResults(VCGen.Outcome.Errors);
+ }
+ }
+ public int Verified {
+ get {
+ return CountResults(VCGen.Outcome.Correct);
+ }
+ }
+ public int Inconclusives {
+ get {
+ return CountResults(VCGen.Outcome.Inconclusive);
+ }
+ }
+ public int TimeOuts {
+ get {
+ return CountResults(VCGen.Outcome.TimedOut);
+ }
+ }
+ public List<string> ListOfTimeouts {
+ get {
+ return ListOutcomeMatches(VCGen.Outcome.TimedOut);
+ }
+ }
+ public List<string> ListOfInconclusives {
+ get {
+ return ListOutcomeMatches(VCGen.Outcome.Inconclusive);
+ }
+ }
+ public List<string> ListOfErrors {
+ get {
+ return ListOutcomeMatches(VCGen.Outcome.Errors);
+ }
+ }
+ }
+
+}
diff --git a/Source/Houdini/Houdini.csproj b/Source/Houdini/Houdini.csproj
index dcb42ef7..43612142 100644
--- a/Source/Houdini/Houdini.csproj
+++ b/Source/Houdini/Houdini.csproj
@@ -1,154 +1,154 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.Houdini</RootNamespace>
- <AssemblyName>Houdini</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </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>
- </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>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <OutputPath>bin\Checked\</OutputPath>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <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>
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="AbstractHoudini.cs" />
- <Compile Include="Checker.cs" />
- <Compile Include="AnnotationDependenceAnalyser.cs" />
- <Compile Include="Houdini.cs" />
- <Compile Include="StagedHoudini.cs" />
- <Compile Include="ConcurrentHoudini.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
- <Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
- <Name>SMTLib</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie.Houdini</RootNamespace>
+ <AssemblyName>BoogieHoudini</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </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>
+ </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>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <OutputPath>bin\Checked\</OutputPath>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <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>
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="AbstractHoudini.cs" />
+ <Compile Include="Checker.cs" />
+ <Compile Include="AnnotationDependenceAnalyser.cs" />
+ <Compile Include="Houdini.cs" />
+ <Compile Include="StagedHoudini.cs" />
+ <Compile Include="ConcurrentHoudini.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Model\Model.csproj">
+ <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
+ <Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
+ <Name>SMTLib</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</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/Houdini/StagedHoudini.cs b/Source/Houdini/StagedHoudini.cs
index 27481e4f..964321c7 100644
--- a/Source/Houdini/StagedHoudini.cs
+++ b/Source/Houdini/StagedHoudini.cs
@@ -1,427 +1,427 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.Diagnostics;
-using System.Threading.Tasks;
-using System.Threading;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie.Houdini
-{
- public class StagedHoudini
- {
-
- private Program program;
- private HoudiniSession.HoudiniStatistics houdiniStats;
- private Func<string, Program> ProgramFromFile;
- private StagedHoudiniPlan plan;
- private List<Houdini>[] houdiniInstances;
- private List<StagedHoudiniTask> tasks = new List<StagedHoudiniTask>();
- private Dictionary<ScheduledStage, HoudiniOutcome> outcomes = new Dictionary<ScheduledStage,HoudiniOutcome>();
-
- private const string tempFilename = "__stagedHoudiniTemp.bpl";
-
- public StagedHoudini(Program program, HoudiniSession.HoudiniStatistics houdiniStats, Func<string, Program> ProgramFromFile) {
- this.program = program;
- this.houdiniStats = houdiniStats;
- this.ProgramFromFile = ProgramFromFile;
- this.houdiniInstances = new List<Houdini>[CommandLineOptions.Clo.StagedHoudiniThreads];
- for (int i = 0; i < CommandLineOptions.Clo.StagedHoudiniThreads; i++) {
- houdiniInstances[i] = new List<Houdini>();
- }
-
- BreakApartConjunctionsInAnnotations();
-
- var annotationDependenceAnalyser = new AnnotationDependenceAnalyser(program);
- annotationDependenceAnalyser.Analyse();
- this.plan = annotationDependenceAnalyser.ApplyStages();
- if (CommandLineOptions.Clo.Trace)
- {
- annotationDependenceAnalyser.dump();
-
- if(CommandLineOptions.Clo.DebugStagedHoudini) {
- Console.WriteLine("Plan\n====\n");
- if(plan == null) {
- Console.WriteLine("No plan, as there were no stages");
- } else {
- Console.WriteLine(this.plan);
- }
- }
-
- EmitProgram("staged.bpl");
- }
- }
-
- private void BreakApartConjunctionsInAnnotations()
- {
- // StagedHoudini works on a syntactic basis, so that
- // if x and y occur in the same annotation, any annotation
- // referring to either x or y will be in the same stage
- // as this annotation. It is thus desirable to separate
- // conjunctive annotations into multiple annotations,
- // to reduce these syntactic dependencies.
-
- foreach(var b in program.Blocks()) {
- List<Cmd> newCmds = new List<Cmd>();
- foreach(var c in b.Cmds) {
- var assertion = c as AssertCmd;
- if (assertion != null) {
- foreach(var e in BreakIntoConjuncts(assertion.Expr)) {
- newCmds.Add(new AssertCmd(assertion.tok, e, assertion.Attributes));
- }
- } else {
- newCmds.Add(c);
- }
- }
- b.Cmds = newCmds;
- }
-
- foreach(var proc in program.Procedures) {
- {
- var newRequires = new List<Requires>();
- foreach(var r in proc.Requires) {
- foreach(var c in BreakIntoConjuncts(r.Condition)) {
- newRequires.Add(new Requires(r.tok, r.Free, c, r.Comment, r.Attributes));
- }
- }
- proc.Requires = newRequires;
- }
- {
- var newEnsures = new List<Ensures>();
- foreach(var e in proc.Ensures) {
- foreach(var c in BreakIntoConjuncts(e.Condition)) {
- newEnsures.Add(new Ensures(e.tok, e.Free, c, e.Comment, e.Attributes));
- }
- }
- proc.Ensures = newEnsures;
- }
- }
- }
-
- private List<Expr> BreakIntoConjuncts(Expr expr)
- {
- var nary = expr as NAryExpr;
- if(nary == null) {
- return new List<Expr> { expr };
- }
- var fun = nary.Fun as BinaryOperator;
- if(fun == null || (fun.Op != BinaryOperator.Opcode.And)) {
- return new List<Expr> { expr };
- }
- var result = new List<Expr>();
- result.AddRange(BreakIntoConjuncts(nary.Args[0]));
- result.AddRange(BreakIntoConjuncts(nary.Args[1]));
- return result;
- }
-
- private bool NoStages() {
- return plan == null;
- }
-
- public HoudiniOutcome PerformStagedHoudiniInference()
- {
-
- if (NoStages()) {
- Houdini houdini = new Houdini(program, houdiniStats);
- return houdini.PerformHoudiniInference();
- }
-
- EmitProgram(tempFilename);
-
- #region Prepare the tasks, but do not launch them
- foreach (var s in plan) {
- Debug.Assert(!plan.GetDependences(s).Contains(s));
- tasks.Add(new StagedHoudiniTask(s, new Task(o => {
- ExecuteStage((ScheduledStage)o);
- }, s, TaskCreationOptions.LongRunning)));
- }
- #endregion
-
- #region Launch the tasks, and wait for them to finish
- foreach (var t in tasks) {
- t.parallelTask.Start();
- }
- Task.WaitAll(tasks.Select(Item => Item.parallelTask).ToArray());
- int count = 0;
- foreach(var h in houdiniInstances) {
- if(h.Count() > 0) {
- count++;
- System.Diagnostics.Debug.Assert(h.Count() == 1);
- h[0].Close();
- }
- }
- #endregion
-
- return UnifyOutcomes();
-
- }
-
- private HoudiniOutcome UnifyOutcomes()
- {
- HoudiniOutcome result = new HoudiniOutcome();
- var scheduledStages = outcomes.Keys.ToList();
-
- result.assignment = new Dictionary<string,bool>();
- foreach(var c in outcomes[scheduledStages[0]].assignment.Keys) {
- result.assignment[c] = outcomes.Select(Item => Item.Value).Select(Item => Item.assignment[c]).All(Item => Item);
- }
-
- result.implementationOutcomes = new Dictionary<string,VCGenOutcome>();
- foreach(var p in outcomes[scheduledStages[0]].implementationOutcomes.Keys) {
- var unifiedImplementationOutcome = outcomes[scheduledStages[0]].implementationOutcomes[p];
- for(int i = 1; i < scheduledStages.Count(); i++) {
- unifiedImplementationOutcome = ChooseOutcome(unifiedImplementationOutcome,
- outcomes[scheduledStages[i]].implementationOutcomes[p]);
- }
- result.implementationOutcomes[p] = unifiedImplementationOutcome;
- }
-
- return result;
- }
-
- private void ExecuteStage(ScheduledStage s)
- {
- Task.WaitAll(tasks.Where(
- Item => plan.GetDependences(s).Contains(Item.stage)).
- Select(Item => Item.parallelTask).ToArray());
-
- if(s.Count() == 0) {
- // This is the trivial first stage, so don't launch Houdini;
- // give this a null outcome
- return;
- }
-
- List<Houdini> h = AcquireHoudiniInstance();
-
- if (h.Count() == 0)
- {
- h.Add(new Houdini(ProgramFromFile(tempFilename), new HoudiniSession.HoudiniStatistics(), "houdiniCexTrace_" + s.GetId() + ".txt"));
- }
-
- System.Diagnostics.Debug.Assert(h.Count() == 1);
-
- Dictionary<string, bool> mergedAssignment = null;
-
- List<Dictionary<string, bool>> relevantAssignments;
- IEnumerable<int> completedStages;
- lock (outcomes)
- {
- relevantAssignments =
- outcomes.Where(Item => plan.Contains(Item.Key)).
- Select(Item => Item.Value).
- Select(Item => Item.assignment).ToList();
- completedStages = plan.GetDependences(s).Select(Item => Item.GetId());
- }
-
- if (relevantAssignments.Count() > 0)
- {
- mergedAssignment = new Dictionary<string, bool>();
- foreach (var v in relevantAssignments[0].Keys)
- {
- mergedAssignment[v] = relevantAssignments.Select(Item => Item[v]).ToList().All(Item => Item);
- }
- }
-
- HoudiniOutcome outcome = h[0].PerformHoudiniInference(
- s.GetId(),
- completedStages,
- mergedAssignment);
-
- lock (outcomes)
- {
- outcomes[s] = outcome;
- }
-
- ReleaseHoudiniInstance(h);
-
- }
-
- private static void ReleaseHoudiniInstance(List<Houdini> h)
- {
- Monitor.Exit(h);
- }
-
- private List<Houdini> AcquireHoudiniInstance()
- {
- while(true) {
- foreach (var houdini in houdiniInstances) {
- if (Monitor.TryEnter(houdini)) {
- return houdini;
- }
- Thread.Sleep(20);
- }
- }
- }
-
- private void EmitProgram(string filename)
- {
- using (TokenTextWriter writer = new TokenTextWriter(filename, true))
- {
- int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
- CommandLineOptions.Clo.PrintUnstructured = 2;
- program.Emit(writer);
- CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
- }
- }
-
-
- private static VCGenOutcome ChooseOutcome(VCGenOutcome o1, VCGenOutcome o2) {
- var vcOutcome1 = o1.outcome;
- var vcOutcome2 = o2.outcome;
-
- if(vcOutcome1 == vcOutcome2) {
- return o1;
- }
-
- // Errors trump everything else
- if(vcOutcome1 == VC.ConditionGeneration.Outcome.Errors) {
- return o1;
- }
- if(vcOutcome2 == VC.ConditionGeneration.Outcome.Errors) {
- return o2;
- }
-
- // If one outcome is Correct, return the other in case it is "worse"
- if(vcOutcome1 == VC.ConditionGeneration.Outcome.Correct) {
- return o2;
- }
- if(vcOutcome2 == VC.ConditionGeneration.Outcome.Correct) {
- return o1;
- }
-
- // Neither outcome is correct, so if one outcome is ReachedBound, return the other in case it is "worse"
- if(vcOutcome1 == VC.ConditionGeneration.Outcome.ReachedBound) {
- return o2;
- }
- if(vcOutcome2 == VC.ConditionGeneration.Outcome.ReachedBound) {
- return o1;
- }
-
- // Both outcomes must be timeout or memout; arbitrarily choose the first
- return o1;
- }
-
- internal class StagedHoudiniTask {
- internal ScheduledStage stage;
- internal Task parallelTask;
- internal StagedHoudiniTask(ScheduledStage stage, Task parallelTask) {
- this.stage = stage;
- this.parallelTask = parallelTask;
- }
- }
-
- }
-
- public class StagedHoudiniPlan : IEnumerable<ScheduledStage> {
-
- private Graph<ScheduledStage> ScheduledStages;
- private Dictionary<string, ScheduledStage> AnnotationToStage;
-
- internal StagedHoudiniPlan(Graph<ScheduledStage> ScheduledStages) {
- this.ScheduledStages = ScheduledStages;
- this.AnnotationToStage = new Dictionary<string, ScheduledStage>();
- foreach(var s in this) {
- Debug.Assert(!GetDependences(s).Contains(s));
- }
- }
-
- public IEnumerable<ScheduledStage> GetDependences(ScheduledStage s) {
- IEnumerable<ScheduledStage> result;
- lock(ScheduledStages) {
- result = ScheduledStages.Successors(s);
- }
- return result;
- }
-
-
- private static int CompareStages(ScheduledStage s1, ScheduledStage s2) {
- if(s1.GetId() < s2.GetId()) {
- return -1;
- }
- if(s2.GetId() < s1.GetId()) {
- return 1;
- }
- return 0;
- }
-
- public IEnumerator<ScheduledStage> GetEnumerator() {
- List<ScheduledStage> sortedStages = ScheduledStages.Nodes.ToList();
- sortedStages.Sort(CompareStages);
- return sortedStages.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return this.GetEnumerator();
- }
-
- internal ScheduledStage StageForAnnotation(string c) {
- if(AnnotationToStage.ContainsKey(c)) {
- return AnnotationToStage[c];
- }
- foreach(var s in ScheduledStages.Nodes) {
- if(s.ContainsAnnotation(c)) {
- AnnotationToStage[c] = s;
- return s;
- }
- }
- return null;
- }
-
- public override string ToString()
- {
- string result = "";
- foreach(ScheduledStage s in this) {
- result += "Stage " + s;
-
- result += " depends on stages: ";
- foreach(var id in GetDependences(s).Select(Item => Item.GetId())) {
- result += id + " ";
- }
- result += "\n";
- }
- return result;
- }
- }
-
- public class ScheduledStage {
- private int Id;
- private HashSet<string> Annotations;
-
- public ScheduledStage(int Id, HashSet<string> Annotations) {
- this.Id = Id;
- this.Annotations = Annotations;
- }
-
- internal void AddAnnotation(string a) {
- Annotations.Add(a);
- }
-
- internal bool ContainsAnnotation(string a) {
- return Annotations.Contains(a);
- }
-
- public int GetId() {
- return Id;
- }
-
- public int Count() {
- return Annotations.Count();
- }
-
- public override string ToString()
- {
- string result = "ID: " + Id + "{ ";
- foreach(var c in Annotations) {
- result += c + " ";
- }
- result += "}\n";
- return result;
- }
- }
-
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics.Contracts;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using System.Threading;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie.Houdini
+{
+ public class StagedHoudini
+ {
+
+ private Program program;
+ private HoudiniSession.HoudiniStatistics houdiniStats;
+ private Func<string, Program> ProgramFromFile;
+ private StagedHoudiniPlan plan;
+ private List<Houdini>[] houdiniInstances;
+ private List<StagedHoudiniTask> tasks = new List<StagedHoudiniTask>();
+ private Dictionary<ScheduledStage, HoudiniOutcome> outcomes = new Dictionary<ScheduledStage,HoudiniOutcome>();
+
+ private const string tempFilename = "__stagedHoudiniTemp.bpl";
+
+ public StagedHoudini(Program program, HoudiniSession.HoudiniStatistics houdiniStats, Func<string, Program> ProgramFromFile) {
+ this.program = program;
+ this.houdiniStats = houdiniStats;
+ this.ProgramFromFile = ProgramFromFile;
+ this.houdiniInstances = new List<Houdini>[CommandLineOptions.Clo.StagedHoudiniThreads];
+ for (int i = 0; i < CommandLineOptions.Clo.StagedHoudiniThreads; i++) {
+ houdiniInstances[i] = new List<Houdini>();
+ }
+
+ BreakApartConjunctionsInAnnotations();
+
+ var annotationDependenceAnalyser = new AnnotationDependenceAnalyser(program);
+ annotationDependenceAnalyser.Analyse();
+ this.plan = annotationDependenceAnalyser.ApplyStages();
+ if (CommandLineOptions.Clo.Trace)
+ {
+ annotationDependenceAnalyser.dump();
+
+ if(CommandLineOptions.Clo.DebugStagedHoudini) {
+ Console.WriteLine("Plan\n====\n");
+ if(plan == null) {
+ Console.WriteLine("No plan, as there were no stages");
+ } else {
+ Console.WriteLine(this.plan);
+ }
+ }
+
+ EmitProgram("staged.bpl");
+ }
+ }
+
+ private void BreakApartConjunctionsInAnnotations()
+ {
+ // StagedHoudini works on a syntactic basis, so that
+ // if x and y occur in the same annotation, any annotation
+ // referring to either x or y will be in the same stage
+ // as this annotation. It is thus desirable to separate
+ // conjunctive annotations into multiple annotations,
+ // to reduce these syntactic dependencies.
+
+ foreach(var b in program.Blocks()) {
+ List<Cmd> newCmds = new List<Cmd>();
+ foreach(var c in b.Cmds) {
+ var assertion = c as AssertCmd;
+ if (assertion != null) {
+ foreach(var e in BreakIntoConjuncts(assertion.Expr)) {
+ newCmds.Add(new AssertCmd(assertion.tok, e, assertion.Attributes));
+ }
+ } else {
+ newCmds.Add(c);
+ }
+ }
+ b.Cmds = newCmds;
+ }
+
+ foreach(var proc in program.Procedures) {
+ {
+ var newRequires = new List<Requires>();
+ foreach(var r in proc.Requires) {
+ foreach(var c in BreakIntoConjuncts(r.Condition)) {
+ newRequires.Add(new Requires(r.tok, r.Free, c, r.Comment, r.Attributes));
+ }
+ }
+ proc.Requires = newRequires;
+ }
+ {
+ var newEnsures = new List<Ensures>();
+ foreach(var e in proc.Ensures) {
+ foreach(var c in BreakIntoConjuncts(e.Condition)) {
+ newEnsures.Add(new Ensures(e.tok, e.Free, c, e.Comment, e.Attributes));
+ }
+ }
+ proc.Ensures = newEnsures;
+ }
+ }
+ }
+
+ private List<Expr> BreakIntoConjuncts(Expr expr)
+ {
+ var nary = expr as NAryExpr;
+ if(nary == null) {
+ return new List<Expr> { expr };
+ }
+ var fun = nary.Fun as BinaryOperator;
+ if(fun == null || (fun.Op != BinaryOperator.Opcode.And)) {
+ return new List<Expr> { expr };
+ }
+ var result = new List<Expr>();
+ result.AddRange(BreakIntoConjuncts(nary.Args[0]));
+ result.AddRange(BreakIntoConjuncts(nary.Args[1]));
+ return result;
+ }
+
+ private bool NoStages() {
+ return plan == null;
+ }
+
+ public HoudiniOutcome PerformStagedHoudiniInference()
+ {
+
+ if (NoStages()) {
+ Houdini houdini = new Houdini(program, houdiniStats);
+ return houdini.PerformHoudiniInference();
+ }
+
+ EmitProgram(tempFilename);
+
+ #region Prepare the tasks, but do not launch them
+ foreach (var s in plan) {
+ Debug.Assert(!plan.GetDependences(s).Contains(s));
+ tasks.Add(new StagedHoudiniTask(s, new Task(o => {
+ ExecuteStage((ScheduledStage)o);
+ }, s, TaskCreationOptions.LongRunning)));
+ }
+ #endregion
+
+ #region Launch the tasks, and wait for them to finish
+ foreach (var t in tasks) {
+ t.parallelTask.Start();
+ }
+ Task.WaitAll(tasks.Select(Item => Item.parallelTask).ToArray());
+ int count = 0;
+ foreach(var h in houdiniInstances) {
+ if(h.Count() > 0) {
+ count++;
+ System.Diagnostics.Debug.Assert(h.Count() == 1);
+ h[0].Close();
+ }
+ }
+ #endregion
+
+ return UnifyOutcomes();
+
+ }
+
+ private HoudiniOutcome UnifyOutcomes()
+ {
+ HoudiniOutcome result = new HoudiniOutcome();
+ var scheduledStages = outcomes.Keys.ToList();
+
+ result.assignment = new Dictionary<string,bool>();
+ foreach(var c in outcomes[scheduledStages[0]].assignment.Keys) {
+ result.assignment[c] = outcomes.Select(Item => Item.Value).Select(Item => Item.assignment[c]).All(Item => Item);
+ }
+
+ result.implementationOutcomes = new Dictionary<string,VCGenOutcome>();
+ foreach(var p in outcomes[scheduledStages[0]].implementationOutcomes.Keys) {
+ var unifiedImplementationOutcome = outcomes[scheduledStages[0]].implementationOutcomes[p];
+ for(int i = 1; i < scheduledStages.Count(); i++) {
+ unifiedImplementationOutcome = ChooseOutcome(unifiedImplementationOutcome,
+ outcomes[scheduledStages[i]].implementationOutcomes[p]);
+ }
+ result.implementationOutcomes[p] = unifiedImplementationOutcome;
+ }
+
+ return result;
+ }
+
+ private void ExecuteStage(ScheduledStage s)
+ {
+ Task.WaitAll(tasks.Where(
+ Item => plan.GetDependences(s).Contains(Item.stage)).
+ Select(Item => Item.parallelTask).ToArray());
+
+ if(s.Count() == 0) {
+ // This is the trivial first stage, so don't launch Houdini;
+ // give this a null outcome
+ return;
+ }
+
+ List<Houdini> h = AcquireHoudiniInstance();
+
+ if (h.Count() == 0)
+ {
+ h.Add(new Houdini(ProgramFromFile(tempFilename), new HoudiniSession.HoudiniStatistics(), "houdiniCexTrace_" + s.GetId() + ".txt"));
+ }
+
+ System.Diagnostics.Debug.Assert(h.Count() == 1);
+
+ Dictionary<string, bool> mergedAssignment = null;
+
+ List<Dictionary<string, bool>> relevantAssignments;
+ IEnumerable<int> completedStages;
+ lock (outcomes)
+ {
+ relevantAssignments =
+ outcomes.Where(Item => plan.Contains(Item.Key)).
+ Select(Item => Item.Value).
+ Select(Item => Item.assignment).ToList();
+ completedStages = plan.GetDependences(s).Select(Item => Item.GetId());
+ }
+
+ if (relevantAssignments.Count() > 0)
+ {
+ mergedAssignment = new Dictionary<string, bool>();
+ foreach (var v in relevantAssignments[0].Keys)
+ {
+ mergedAssignment[v] = relevantAssignments.Select(Item => Item[v]).ToList().All(Item => Item);
+ }
+ }
+
+ HoudiniOutcome outcome = h[0].PerformHoudiniInference(
+ s.GetId(),
+ completedStages,
+ mergedAssignment);
+
+ lock (outcomes)
+ {
+ outcomes[s] = outcome;
+ }
+
+ ReleaseHoudiniInstance(h);
+
+ }
+
+ private static void ReleaseHoudiniInstance(List<Houdini> h)
+ {
+ Monitor.Exit(h);
+ }
+
+ private List<Houdini> AcquireHoudiniInstance()
+ {
+ while(true) {
+ foreach (var houdini in houdiniInstances) {
+ if (Monitor.TryEnter(houdini)) {
+ return houdini;
+ }
+ Thread.Sleep(20);
+ }
+ }
+ }
+
+ private void EmitProgram(string filename)
+ {
+ using (TokenTextWriter writer = new TokenTextWriter(filename, true))
+ {
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 2;
+ program.Emit(writer);
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+ }
+
+
+ private static VCGenOutcome ChooseOutcome(VCGenOutcome o1, VCGenOutcome o2) {
+ var vcOutcome1 = o1.outcome;
+ var vcOutcome2 = o2.outcome;
+
+ if(vcOutcome1 == vcOutcome2) {
+ return o1;
+ }
+
+ // Errors trump everything else
+ if(vcOutcome1 == VC.ConditionGeneration.Outcome.Errors) {
+ return o1;
+ }
+ if(vcOutcome2 == VC.ConditionGeneration.Outcome.Errors) {
+ return o2;
+ }
+
+ // If one outcome is Correct, return the other in case it is "worse"
+ if(vcOutcome1 == VC.ConditionGeneration.Outcome.Correct) {
+ return o2;
+ }
+ if(vcOutcome2 == VC.ConditionGeneration.Outcome.Correct) {
+ return o1;
+ }
+
+ // Neither outcome is correct, so if one outcome is ReachedBound, return the other in case it is "worse"
+ if(vcOutcome1 == VC.ConditionGeneration.Outcome.ReachedBound) {
+ return o2;
+ }
+ if(vcOutcome2 == VC.ConditionGeneration.Outcome.ReachedBound) {
+ return o1;
+ }
+
+ // Both outcomes must be timeout or memout; arbitrarily choose the first
+ return o1;
+ }
+
+ internal class StagedHoudiniTask {
+ internal ScheduledStage stage;
+ internal Task parallelTask;
+ internal StagedHoudiniTask(ScheduledStage stage, Task parallelTask) {
+ this.stage = stage;
+ this.parallelTask = parallelTask;
+ }
+ }
+
+ }
+
+ public class StagedHoudiniPlan : IEnumerable<ScheduledStage> {
+
+ private Graph<ScheduledStage> ScheduledStages;
+ private Dictionary<string, ScheduledStage> AnnotationToStage;
+
+ internal StagedHoudiniPlan(Graph<ScheduledStage> ScheduledStages) {
+ this.ScheduledStages = ScheduledStages;
+ this.AnnotationToStage = new Dictionary<string, ScheduledStage>();
+ foreach(var s in this) {
+ Debug.Assert(!GetDependences(s).Contains(s));
+ }
+ }
+
+ public IEnumerable<ScheduledStage> GetDependences(ScheduledStage s) {
+ IEnumerable<ScheduledStage> result;
+ lock(ScheduledStages) {
+ result = ScheduledStages.Successors(s);
+ }
+ return result;
+ }
+
+
+ private static int CompareStages(ScheduledStage s1, ScheduledStage s2) {
+ if(s1.GetId() < s2.GetId()) {
+ return -1;
+ }
+ if(s2.GetId() < s1.GetId()) {
+ return 1;
+ }
+ return 0;
+ }
+
+ public IEnumerator<ScheduledStage> GetEnumerator() {
+ List<ScheduledStage> sortedStages = ScheduledStages.Nodes.ToList();
+ sortedStages.Sort(CompareStages);
+ return sortedStages.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ internal ScheduledStage StageForAnnotation(string c) {
+ if(AnnotationToStage.ContainsKey(c)) {
+ return AnnotationToStage[c];
+ }
+ foreach(var s in ScheduledStages.Nodes) {
+ if(s.ContainsAnnotation(c)) {
+ AnnotationToStage[c] = s;
+ return s;
+ }
+ }
+ return null;
+ }
+
+ public override string ToString()
+ {
+ string result = "";
+ foreach(ScheduledStage s in this) {
+ result += "Stage " + s;
+
+ result += " depends on stages: ";
+ foreach(var id in GetDependences(s).Select(Item => Item.GetId())) {
+ result += id + " ";
+ }
+ result += "\n";
+ }
+ return result;
+ }
+ }
+
+ public class ScheduledStage {
+ private int Id;
+ private HashSet<string> Annotations;
+
+ public ScheduledStage(int Id, HashSet<string> Annotations) {
+ this.Id = Id;
+ this.Annotations = Annotations;
+ }
+
+ internal void AddAnnotation(string a) {
+ Annotations.Add(a);
+ }
+
+ internal bool ContainsAnnotation(string a) {
+ return Annotations.Contains(a);
+ }
+
+ public int GetId() {
+ return Id;
+ }
+
+ public int Count() {
+ return Annotations.Count();
+ }
+
+ public override string ToString()
+ {
+ string result = "ID: " + Id + "{ ";
+ foreach(var c in Annotations) {
+ result += c + " ";
+ }
+ result += "}\n";
+ return result;
+ }
+ }
+
+
+}
diff --git a/Source/Model/Model.cs b/Source/Model/Model.cs
index 76b7cb4a..1e71d6c2 100644
--- a/Source/Model/Model.cs
+++ b/Source/Model/Model.cs
@@ -1,706 +1,706 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-/*
-An instance of the Model class represents a single model returned from the SMT solver. This usually
-corresponds to a single verification error. The model consists of elements and function interpretations.
-Additionally the model may contain a number of captured states, each consisting of a user-supplied name
-a mapping from Boogie variable names to model elements.
-
-Model elements (which used to be called “partitions” in Z3) are represented by instances of the
-Model.Element class. Each element has an integer identity. The Element class has subclasses
-Uninterpreted, Boolean, Integer, BitVector, and Array. The classes correspond to different sorts of
-elements that the SMT solver may use. Each of these has properties for returning the actual
-value (true/false or a number; for bitvectors also size). For an array the interpretation is a
-particular function defined elsewhere in the model.
-
-A function interpretation is represented by Model.Func class. It consists of a name, arity, and
-a list of defining tuples. A defining tuple (Model.FuncTuple) for a function of arity N has
-N model elements as arguments and a single element as the result. A constant is a function
-of arity 0, with just one defining tuple. Given a constant function f, the result element of
-the defining tuple is retrieved with f.GetConstant().
-
-The Model.Element class exposes methods to look up all the functions that reference it in their
-defining tuples. Additionally Model.Func allows lookup of specific tuples, based on the elements.
-
-An instance of the Model class represents a single model returned from the SMT solver.
-
- */
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Text;
-using System.Diagnostics;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.Boogie
-{
- public class Model
- {
- #region Elements and functions (inner classes)
- public enum ElementKind
- {
- Integer,
- BitVector,
- Boolean,
- Uninterpreted,
- Array,
- DataValue
- }
-
- abstract public class Element
- {
- public readonly Model Model;
- internal List<FuncTuple> references = new List<FuncTuple>();
- public readonly int Id;
-
- public IEnumerable<FuncTuple> References { get { return references; } }
-
- public IEnumerable<FuncTuple> Names {
- get {
- foreach (var f in references)
- if (f.Result == this) yield return f;
- }
- }
-
- protected Element(Model p)
- {
- Model = p;
- Id = Model.elements.Count;
- }
- public abstract ElementKind Kind { get; }
- public virtual int AsInt() { throw new NotImplementedException(); }
-
- public override int GetHashCode() {
- return Id;
- }
-
- public override bool Equals(object obj) {
- return obj == this;
- }
- }
-
- #region element kinds
- public class Uninterpreted : Element
- {
- public override ElementKind Kind { get { return ElementKind.Uninterpreted; } }
- public override string ToString() { return Name; }
-
- internal Uninterpreted(Model p, string n) : base(p) { Name = n; }
- public readonly string Name;
- }
-
- abstract public class Number : Element
- {
- protected Number(Model p, string n) : base(p) { Numeral = n; }
- public readonly string Numeral;
- public override int AsInt() { return int.Parse(Numeral); }
- }
-
- public class Integer : Number
- {
- internal Integer(Model p, string n) : base(p, n) { }
- public override ElementKind Kind { get { return ElementKind.Integer; } }
- public override string ToString() { return Numeral.ToString(); }
- }
-
- public class BitVector : Number
- {
- internal BitVector(Model p, string n, int sz) : base(p, n) { Size = sz; }
- public readonly int Size;
- public override ElementKind Kind { get { return ElementKind.BitVector; } }
- public override string ToString() { return string.Format("{0}bv{1}", Numeral, Size); }
- }
-
- public class Boolean : Element
- {
- public bool Value;
- internal Boolean(Model p, bool v) : base(p) { Value = v; }
- public override ElementKind Kind { get { return ElementKind.Boolean; } }
- public override string ToString() { return Value ? "true" : "false"; }
- }
-
- public class Array : Element
- {
- public Func Value;
- internal Array(Model p, Func v) : base(p) { Value = v; }
- public override ElementKind Kind { get { return ElementKind.Array; } }
- public override string ToString() { return string.Format("as-array[{0}]", Value.Name); }
- }
-
- public class DatatypeValue : Element
- {
- public readonly string ConstructorName;
- public readonly Element[] Arguments;
- internal DatatypeValue(Model p, string name, List<Element> args) : base(p) {
- ConstructorName = name;
- Arguments = args.ToArray();
- }
- public override ElementKind Kind { get { return ElementKind.DataValue; } }
- public override string ToString() {
- StringBuilder builder = new StringBuilder();
- builder.Append("(").Append(ConstructorName);
- foreach (Element arg in Arguments) {
- builder.Append(" ").Append(arg);
- }
- builder.Append(")");
- return builder.ToString();
- }
- }
- #endregion
-
- public class Func
- {
- public readonly Model Model;
- public readonly string Name;
- public readonly int Arity;
- internal readonly List<FuncTuple> apps = new List<FuncTuple>();
- public IEnumerable<FuncTuple> Apps { get { return apps; } }
- public int AppCount { get { return apps.Count; } }
- private Element @else;
-
- internal Func(Model p, string n, int a) { Model = p; Name = n; Arity = a; }
-
- public override string ToString()
- {
- return string.Format("{0}/{1}", Name, Arity);
- }
-
- internal void Substitute(Dictionary<Element, Element> mapping) {
- Element e;
- if (@else != null && mapping.TryGetValue(@else, out e))
- @else = e;
- foreach (var ft in apps) {
- if (mapping.TryGetValue(ft.Result, out e)) ft.Result = e;
- for (var i = 0; i < ft.Args.Length; ++i)
- if (mapping.TryGetValue(ft.Args[i], out e)) ft.Args[i] = e;
- }
- }
-
- public Element Else
- {
- get
- {
- return @else;
- }
- set
- {
- if (@else != null)
- throw new ArgumentException();
- @else = value;
- }
- }
-
- public void SetConstant(Element res)
- {
- if (Arity != 0 || apps.Count > 0)
- throw new ArgumentException();
- var t = new FuncTuple(this, res, null);
- apps.Add(t);
- res.references.Add(t);
- }
-
- /// <summary>
- /// Return the first application where the argument at position argIdx is elt.
- /// </summary>
- public FuncTuple AppWithArg(int argIdx, Element elt)
- {
- foreach (var a in AppsWithArg(argIdx, elt))
- return a;
- return null;
- }
-
- /// <summary>
- /// Return the first application with the result elt.
- /// </summary>
- public FuncTuple AppWithResult(Element elt)
- {
- foreach (var a in AppsWithResult(elt))
- return a;
- return null;
- }
-
- /// <summary>
- /// Return all applications where the argument at position argIdx is elt.
- /// </summary>
- public IEnumerable<FuncTuple> AppsWithArg(int argIdx, Element elt)
- {
- foreach (var r in elt.References) {
- if (r.Func == this && r.Args[argIdx] == elt)
- yield return r;
- }
- }
-
- /// <summary>
- /// Return all applications where the argument at position argIdx0 is elt0 and argument at argIdx1 is elt1.
- /// </summary>
- public IEnumerable<FuncTuple> AppsWithArgs(int argIdx0, Element elt0, int argIdx1, Element elt1)
- {
- foreach (var r in elt0.References) {
- if (r.Func == this && r.Args[argIdx0] == elt0 && r.Args[argIdx1] == elt1)
- yield return r;
- }
- }
-
- /// <summary>
- /// Return all the applications with the result elt.
- /// </summary>
- public IEnumerable<FuncTuple> AppsWithResult(Element elt)
- {
- foreach (var r in elt.References) {
- if (r.Func == this && r.Result == elt)
- yield return r;
- }
- }
-
- /// <summary>
- /// For a nullary function, return its value.
- /// </summary>
- public Element GetConstant()
- {
- if (Arity != 0)
- throw new ArgumentException();
- if (apps.Count == 0)
- SetConstant(Model.MkElement("**" + Name));
- return apps[0].Result;
- }
-
- /// <summary>
- /// If all arguments are non-null, and function application for them exists return the value, otherwise return null.
- /// </summary>
- public Element OptEval(params Element[] args)
- {
- if (args.Any(a => a == null)) return null;
- return TryEval(args);
- }
-
- /// <summary>
- /// Look for function application with given arguments and return its value or null if no such application exists.
- /// </summary>
- public Element TryEval(params Element[] args)
- {
- for (int i = 0; i < args.Length; ++i)
- if(args[i]==null)
- throw new ArgumentException();
-
- if (apps.Count > 10) {
- var best = apps;
- for (int i = 0; i < args.Length; ++i)
- if (args[i].references.Count < best.Count)
- best = args[i].references;
- if (best != apps) {
- foreach (var tpl in best) {
- bool same = true;
- if (tpl.Func != this)
- continue;
- for (int i = 0; i < args.Length; ++i)
- if (tpl.Args[i] != args[i]) {
- same = false;
- break;
- }
- if (same) return tpl.Result;
- }
- return null;
- }
- }
-
- foreach (var tpl in apps) {
- bool same = true;
- for (int i = 0; i < args.Length; ++i)
- if (tpl.Args[i] != args[i]) {
- same = false;
- break;
- }
- if (same) return tpl.Result;
- }
- return null;
- }
-
- /// <summary>
- /// Look for function application with a subsequence of given arguments and return its value or null if no such application exists.
- /// </summary>
- public Element TryPartialEval(params Element[] args)
- {
- foreach (var tpl in apps) {
- int j = 0;
- for (int i = 0; i < args.Length; ++i) {
- if (tpl.Args[j] == args[i]) {
- j++;
- if (j == tpl.Args.Length)
- return tpl.Result;
- }
- }
- }
- return null;
- }
-
- /// <summary>
- /// Short for TryEval(args) == (Element)true
- /// </summary>
- public bool IsTrue(params Element[] args)
- {
- var r = TryEval(args) as Boolean;
- return r != null && r.Value;
- }
-
- /// <summary>
- /// Short for TryEval(args) == (Element)false
- /// </summary>
- public bool IsFalse(params Element[] args)
- {
- var r = TryEval(args) as Boolean;
- return r != null && !r.Value;
- }
-
- public void AddApp(Element res, params Element[] args)
- {
- if (Arity == 0)
- SetConstant(res);
- else {
- if (args.Length != Arity)
- throw new ArgumentException();
- var t = new FuncTuple(this, res, (Element[])args.Clone());
- apps.Add(t);
- var u = new HashSet<Element>();
- res.references.Add(t);
- u.Add(res);
- foreach (var a in args)
- if (!u.Contains(a)) {
- u.Add(a);
- a.references.Add(t);
- }
- }
- }
- }
-
- public class FuncTuple
- {
- static readonly Element[] EmptyArgs = new Element[0];
-
- // These should be immutable, except when Substituting the entire model
- public readonly Func Func;
- public Element Result;
- public readonly Element[] Args;
-
- internal FuncTuple(Func func, Element res, Element[] args)
- {
- if (args == null) Args = EmptyArgs;
- else Args = args;
- Func = func;
- Result = res;
- }
-
- public override string ToString()
- {
- var res = new StringBuilder();
- res.Append("(").Append(Func.Name);
- for (int i = 0; i < Args.Length; ++i) {
- res.Append(" ").Append(Args[i]);
- }
- res.Append(") -> ").Append(Result);
- return res.ToString();
- }
- }
- #endregion
-
- private List<Func> functions = new List<Func>();
- private List<Element> elements = new List<Element>();
- private List<CapturedState> states = new List<CapturedState>();
- private Dictionary<string, Func> functionsByName = new Dictionary<string, Func>();
- private Dictionary<string, Element> elementsByName = new Dictionary<string, Element>();
-
- #region factory methods
- Element ConstructElement(string name)
- {
- if (name.ToLower() == "true") return True;
- if (name.ToLower() == "false") return False;
-
- if (name.StartsWith("bv") && name.Length > 4 && Char.IsDigit(name[2]))
- name = name.Substring(2);
-
- if (Char.IsDigit(name[0]) || name[0] == '-') {
- int col = name.IndexOf("bv");
- int szi = -1;
-
- if (name.EndsWith(":int"))
- name = name.Substring(0, name.Length - 4);
-
- if (col > 0) {
- if (int.TryParse(name.Substring(col + 2), out szi) && szi > 0) {
- name = name.Substring(0, col);
- } else {
- return null;
- }
- } else if (name.EndsWith("]")) {
- col = name.IndexOf("[");
- if (col > 0 && int.TryParse(name.Substring(col + 1, name.Length - col - 2), out szi) && szi > 0) {
- name = name.Substring(0, col);
- } else {
- return null;
- }
- }
-
- for (int i = 1; i < name.Length; ++i)
- if (!Char.IsDigit(name[i]))
- return null;
-
- if (szi > 0)
- return new BitVector(this, name, szi);
- else
- return new Integer(this, name);
- } else if (name[0] == '*' || name.StartsWith("val!") || name.Contains("!val!")) {
- return new Uninterpreted(this, name);
- } else if (name.StartsWith("as-array[") && name.EndsWith("]")) {
- var fnName = name.Substring(9, name.Length - 10);
- return new Array(this, MkFunc(fnName, 1));
- } else {
- return new DatatypeValue(this, name, new List<Element>());
- }
- }
-
- public Element TryMkElement(string name)
- {
- Element res;
-
- if (elementsByName.TryGetValue(name, out res))
- return res;
-
- var tmp = ConstructElement(name);
- if (tmp == null) return null;
-
- name = tmp.ToString();
- if (elementsByName.TryGetValue(name, out res))
- return res;
-
- elementsByName.Add(name, tmp);
- elements.Add(tmp);
- return tmp;
- }
-
- public Element MkElement(string name)
- {
- Element res = TryMkElement(name);
- if (res == null)
- throw new ArgumentException("invalid element name: '" + name + "'");
- return res;
- }
-
- public Func MkFunc(string name, int arity)
- {
- Func res;
- if (functionsByName.TryGetValue(name, out res)) {
- if (res.Arity != arity)
- throw new ArgumentException(string.Format("function '{0}' previously created with arity {1}, now trying to recreate with arity {2}", name, res.Arity, arity));
- return res;
- }
- res = new Func(this, name, arity);
- functionsByName.Add(name, res);
- functions.Add(res);
- return res;
- }
- #endregion
-
- #region state management
- public class CapturedState
- {
- List<string> vars = new List<string>();
- Dictionary<string, Element> valuations = new Dictionary<string, Element>();
- readonly CapturedState previous;
- // AL: Dropping "readonly" for corral
- public /* readonly */ string Name { get; private set; }
-
- public IEnumerable<string> Variables { get { return vars; } }
- public IEnumerable<string> AllVariables {
- get {
- if (previous != null)
- return previous.AllVariables.Concat(Variables).Distinct();
- else
- return Variables;
- }
- }
- public int VariableCount { get { return vars.Count; } }
- public bool HasBinding(string varname)
- {
- return valuations.ContainsKey(varname);
- }
- public Element TryGet(string varname)
- {
- CapturedState curr = this;
- while (curr != null) {
- Element res;
- if (curr.valuations.TryGetValue(varname, out res))
- return res;
- curr = curr.previous;
- }
- return null;
- }
-
- public void AddBinding(string varname, Element value)
- {
- vars.Add(varname);
- valuations.Add(varname, value);
- }
-
- // Change name of the state
- public void ChangeName(string newName)
- {
- Name = newName;
- }
-
- // Change names of variables in this state
- // (Used by corral)
- internal void ChangeVariableNames(Dictionary<string, string> varNameMap)
- {
- var oldVars = vars;
- var oldValuations = valuations;
-
- vars = new List<string>();
- valuations = new Dictionary<string, Element>();
-
- foreach (var v in oldVars)
- {
- if (varNameMap.ContainsKey(v)) vars.Add(varNameMap[v]);
- else vars.Add(v);
- }
-
- foreach (var kvp in oldValuations)
- {
- if (varNameMap.ContainsKey(kvp.Key)) valuations.Add(varNameMap[kvp.Key], kvp.Value);
- else valuations.Add(kvp.Key, kvp.Value);
- }
- }
-
- internal CapturedState(string name, CapturedState prev)
- {
- Name = name;
- previous = prev;
- }
- }
-
- public CapturedState MkState(string name)
- {
- var last = states[states.Count - 1];
- var s = new CapturedState(name, last);
- states.Add(s);
- return s;
- }
-
- // Change names of variables in all captured states
- // (Used by corral)
- public void ChangeVariableNames(Dictionary<string, string> varNameMap)
- {
- foreach (var s in states)
- {
- s.ChangeVariableNames(varNameMap);
- }
- }
-
- #endregion
-
- public Model()
- {
- InitialState = new CapturedState("<initial>", null);
- states.Add(InitialState);
- True = new Boolean(this, true);
- elements.Add(True);
- elementsByName.Add("true", True);
- False = new Boolean(this, false);
- elements.Add(False);
- elementsByName.Add("false", False);
- }
-
- public IEnumerable<Func> Functions { get { return functions; } }
- public IEnumerable<Element> Elements { get { return elements; } }
- public IEnumerable<CapturedState> States { get { return states; } }
- public readonly Element True, False;
- public readonly CapturedState InitialState;
-
- public bool HasFunc(string name)
- {
- return functionsByName.ContainsKey(name);
- }
-
- public Func TryGetFunc(string name)
- {
- Func res;
- if (functionsByName.TryGetValue(name, out res))
- return res;
- else
- return null;
- }
-
- public Func GetFunc(string name)
- {
- Func res = TryGetFunc(name);
- if (res == null)
- throw new KeyNotFoundException("function '" + name + "' undefined in the model");
- return res;
- }
-
- public Func TryGetSkolemFunc(string name)
- {
- return Functions.Where(f => f.Name.StartsWith(name + "!")).FirstOrDefault();
- }
-
- public Element GetElement(string name)
- {
- Element res;
- if (elementsByName.TryGetValue(name, out res))
- return res;
- else
- throw new KeyNotFoundException("element '" + name + "' undefined in the model");
- }
-
- public Element MkIntElement(int v)
- {
- return MkElement(v.ToString());
- }
-
- public void Write(System.IO.TextWriter wr)
- {
- wr.WriteLine("*** MODEL");
- foreach (var f in Functions.OrderBy(f => f.Name))
- if (f.Arity == 0) {
- wr.WriteLine("{0} -> {1}", f.Name, f.GetConstant());
- }
- foreach (var f in Functions)
- if (f.Arity != 0) {
- wr.WriteLine("{0} -> {1}", f.Name, "{");
- foreach (var app in f.Apps) {
- wr.Write(" ");
- foreach (var a in app.Args)
- wr.Write("{0} ", a);
- wr.WriteLine("-> {0}", app.Result);
- }
- if (f.Else != null)
- wr.WriteLine(" else -> {0}", f.Else);
- wr.WriteLine("}");
- }
- foreach (var s in States) {
- if (s == InitialState && s.VariableCount == 0)
- continue;
- wr.WriteLine("*** STATE {0}", s.Name);
- foreach (var v in s.Variables)
- wr.WriteLine(" {0} -> {1}", v, s.TryGet(v));
- wr.WriteLine("*** END_STATE", s.Name);
- }
- wr.WriteLine("*** END_MODEL");
- }
-
- public void Substitute(Dictionary<Element, Element> mapping) {
- foreach (var f in functions) f.Substitute(mapping);
- }
-
- public static List<Model> ParseModels(System.IO.TextReader rd)
- {
- ModelParser p = new ParserZ3();
- p.rd = rd;
- p.Run();
- return p.resModels;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+/*
+An instance of the Model class represents a single model returned from the SMT solver. This usually
+corresponds to a single verification error. The model consists of elements and function interpretations.
+Additionally the model may contain a number of captured states, each consisting of a user-supplied name
+a mapping from Boogie variable names to model elements.
+
+Model elements (which used to be called “partitions” in Z3) are represented by instances of the
+Model.Element class. Each element has an integer identity. The Element class has subclasses
+Uninterpreted, Boolean, Integer, BitVector, and Array. The classes correspond to different sorts of
+elements that the SMT solver may use. Each of these has properties for returning the actual
+value (true/false or a number; for bitvectors also size). For an array the interpretation is a
+particular function defined elsewhere in the model.
+
+A function interpretation is represented by Model.Func class. It consists of a name, arity, and
+a list of defining tuples. A defining tuple (Model.FuncTuple) for a function of arity N has
+N model elements as arguments and a single element as the result. A constant is a function
+of arity 0, with just one defining tuple. Given a constant function f, the result element of
+the defining tuple is retrieved with f.GetConstant().
+
+The Model.Element class exposes methods to look up all the functions that reference it in their
+defining tuples. Additionally Model.Func allows lookup of specific tuples, based on the elements.
+
+An instance of the Model class represents a single model returned from the SMT solver.
+
+ */
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie
+{
+ public class Model
+ {
+ #region Elements and functions (inner classes)
+ public enum ElementKind
+ {
+ Integer,
+ BitVector,
+ Boolean,
+ Uninterpreted,
+ Array,
+ DataValue
+ }
+
+ abstract public class Element
+ {
+ public readonly Model Model;
+ internal List<FuncTuple> references = new List<FuncTuple>();
+ public readonly int Id;
+
+ public IEnumerable<FuncTuple> References { get { return references; } }
+
+ public IEnumerable<FuncTuple> Names {
+ get {
+ foreach (var f in references)
+ if (f.Result == this) yield return f;
+ }
+ }
+
+ protected Element(Model p)
+ {
+ Model = p;
+ Id = Model.elements.Count;
+ }
+ public abstract ElementKind Kind { get; }
+ public virtual int AsInt() { throw new NotImplementedException(); }
+
+ public override int GetHashCode() {
+ return Id;
+ }
+
+ public override bool Equals(object obj) {
+ return obj == this;
+ }
+ }
+
+ #region element kinds
+ public class Uninterpreted : Element
+ {
+ public override ElementKind Kind { get { return ElementKind.Uninterpreted; } }
+ public override string ToString() { return Name; }
+
+ internal Uninterpreted(Model p, string n) : base(p) { Name = n; }
+ public readonly string Name;
+ }
+
+ abstract public class Number : Element
+ {
+ protected Number(Model p, string n) : base(p) { Numeral = n; }
+ public readonly string Numeral;
+ public override int AsInt() { return int.Parse(Numeral); }
+ }
+
+ public class Integer : Number
+ {
+ internal Integer(Model p, string n) : base(p, n) { }
+ public override ElementKind Kind { get { return ElementKind.Integer; } }
+ public override string ToString() { return Numeral.ToString(); }
+ }
+
+ public class BitVector : Number
+ {
+ internal BitVector(Model p, string n, int sz) : base(p, n) { Size = sz; }
+ public readonly int Size;
+ public override ElementKind Kind { get { return ElementKind.BitVector; } }
+ public override string ToString() { return string.Format("{0}bv{1}", Numeral, Size); }
+ }
+
+ public class Boolean : Element
+ {
+ public bool Value;
+ internal Boolean(Model p, bool v) : base(p) { Value = v; }
+ public override ElementKind Kind { get { return ElementKind.Boolean; } }
+ public override string ToString() { return Value ? "true" : "false"; }
+ }
+
+ public class Array : Element
+ {
+ public Func Value;
+ internal Array(Model p, Func v) : base(p) { Value = v; }
+ public override ElementKind Kind { get { return ElementKind.Array; } }
+ public override string ToString() { return string.Format("as-array[{0}]", Value.Name); }
+ }
+
+ public class DatatypeValue : Element
+ {
+ public readonly string ConstructorName;
+ public readonly Element[] Arguments;
+ internal DatatypeValue(Model p, string name, List<Element> args) : base(p) {
+ ConstructorName = name;
+ Arguments = args.ToArray();
+ }
+ public override ElementKind Kind { get { return ElementKind.DataValue; } }
+ public override string ToString() {
+ StringBuilder builder = new StringBuilder();
+ builder.Append("(").Append(ConstructorName);
+ foreach (Element arg in Arguments) {
+ builder.Append(" ").Append(arg);
+ }
+ builder.Append(")");
+ return builder.ToString();
+ }
+ }
+ #endregion
+
+ public class Func
+ {
+ public readonly Model Model;
+ public readonly string Name;
+ public readonly int Arity;
+ internal readonly List<FuncTuple> apps = new List<FuncTuple>();
+ public IEnumerable<FuncTuple> Apps { get { return apps; } }
+ public int AppCount { get { return apps.Count; } }
+ private Element @else;
+
+ internal Func(Model p, string n, int a) { Model = p; Name = n; Arity = a; }
+
+ public override string ToString()
+ {
+ return string.Format("{0}/{1}", Name, Arity);
+ }
+
+ internal void Substitute(Dictionary<Element, Element> mapping) {
+ Element e;
+ if (@else != null && mapping.TryGetValue(@else, out e))
+ @else = e;
+ foreach (var ft in apps) {
+ if (mapping.TryGetValue(ft.Result, out e)) ft.Result = e;
+ for (var i = 0; i < ft.Args.Length; ++i)
+ if (mapping.TryGetValue(ft.Args[i], out e)) ft.Args[i] = e;
+ }
+ }
+
+ public Element Else
+ {
+ get
+ {
+ return @else;
+ }
+ set
+ {
+ if (@else != null)
+ throw new ArgumentException();
+ @else = value;
+ }
+ }
+
+ public void SetConstant(Element res)
+ {
+ if (Arity != 0 || apps.Count > 0)
+ throw new ArgumentException();
+ var t = new FuncTuple(this, res, null);
+ apps.Add(t);
+ res.references.Add(t);
+ }
+
+ /// <summary>
+ /// Return the first application where the argument at position argIdx is elt.
+ /// </summary>
+ public FuncTuple AppWithArg(int argIdx, Element elt)
+ {
+ foreach (var a in AppsWithArg(argIdx, elt))
+ return a;
+ return null;
+ }
+
+ /// <summary>
+ /// Return the first application with the result elt.
+ /// </summary>
+ public FuncTuple AppWithResult(Element elt)
+ {
+ foreach (var a in AppsWithResult(elt))
+ return a;
+ return null;
+ }
+
+ /// <summary>
+ /// Return all applications where the argument at position argIdx is elt.
+ /// </summary>
+ public IEnumerable<FuncTuple> AppsWithArg(int argIdx, Element elt)
+ {
+ foreach (var r in elt.References) {
+ if (r.Func == this && r.Args[argIdx] == elt)
+ yield return r;
+ }
+ }
+
+ /// <summary>
+ /// Return all applications where the argument at position argIdx0 is elt0 and argument at argIdx1 is elt1.
+ /// </summary>
+ public IEnumerable<FuncTuple> AppsWithArgs(int argIdx0, Element elt0, int argIdx1, Element elt1)
+ {
+ foreach (var r in elt0.References) {
+ if (r.Func == this && r.Args[argIdx0] == elt0 && r.Args[argIdx1] == elt1)
+ yield return r;
+ }
+ }
+
+ /// <summary>
+ /// Return all the applications with the result elt.
+ /// </summary>
+ public IEnumerable<FuncTuple> AppsWithResult(Element elt)
+ {
+ foreach (var r in elt.References) {
+ if (r.Func == this && r.Result == elt)
+ yield return r;
+ }
+ }
+
+ /// <summary>
+ /// For a nullary function, return its value.
+ /// </summary>
+ public Element GetConstant()
+ {
+ if (Arity != 0)
+ throw new ArgumentException();
+ if (apps.Count == 0)
+ SetConstant(Model.MkElement("**" + Name));
+ return apps[0].Result;
+ }
+
+ /// <summary>
+ /// If all arguments are non-null, and function application for them exists return the value, otherwise return null.
+ /// </summary>
+ public Element OptEval(params Element[] args)
+ {
+ if (args.Any(a => a == null)) return null;
+ return TryEval(args);
+ }
+
+ /// <summary>
+ /// Look for function application with given arguments and return its value or null if no such application exists.
+ /// </summary>
+ public Element TryEval(params Element[] args)
+ {
+ for (int i = 0; i < args.Length; ++i)
+ if(args[i]==null)
+ throw new ArgumentException();
+
+ if (apps.Count > 10) {
+ var best = apps;
+ for (int i = 0; i < args.Length; ++i)
+ if (args[i].references.Count < best.Count)
+ best = args[i].references;
+ if (best != apps) {
+ foreach (var tpl in best) {
+ bool same = true;
+ if (tpl.Func != this)
+ continue;
+ for (int i = 0; i < args.Length; ++i)
+ if (tpl.Args[i] != args[i]) {
+ same = false;
+ break;
+ }
+ if (same) return tpl.Result;
+ }
+ return null;
+ }
+ }
+
+ foreach (var tpl in apps) {
+ bool same = true;
+ for (int i = 0; i < args.Length; ++i)
+ if (tpl.Args[i] != args[i]) {
+ same = false;
+ break;
+ }
+ if (same) return tpl.Result;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Look for function application with a subsequence of given arguments and return its value or null if no such application exists.
+ /// </summary>
+ public Element TryPartialEval(params Element[] args)
+ {
+ foreach (var tpl in apps) {
+ int j = 0;
+ for (int i = 0; i < args.Length; ++i) {
+ if (tpl.Args[j] == args[i]) {
+ j++;
+ if (j == tpl.Args.Length)
+ return tpl.Result;
+ }
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Short for TryEval(args) == (Element)true
+ /// </summary>
+ public bool IsTrue(params Element[] args)
+ {
+ var r = TryEval(args) as Boolean;
+ return r != null && r.Value;
+ }
+
+ /// <summary>
+ /// Short for TryEval(args) == (Element)false
+ /// </summary>
+ public bool IsFalse(params Element[] args)
+ {
+ var r = TryEval(args) as Boolean;
+ return r != null && !r.Value;
+ }
+
+ public void AddApp(Element res, params Element[] args)
+ {
+ if (Arity == 0)
+ SetConstant(res);
+ else {
+ if (args.Length != Arity)
+ throw new ArgumentException();
+ var t = new FuncTuple(this, res, (Element[])args.Clone());
+ apps.Add(t);
+ var u = new HashSet<Element>();
+ res.references.Add(t);
+ u.Add(res);
+ foreach (var a in args)
+ if (!u.Contains(a)) {
+ u.Add(a);
+ a.references.Add(t);
+ }
+ }
+ }
+ }
+
+ public class FuncTuple
+ {
+ static readonly Element[] EmptyArgs = new Element[0];
+
+ // These should be immutable, except when Substituting the entire model
+ public readonly Func Func;
+ public Element Result;
+ public readonly Element[] Args;
+
+ internal FuncTuple(Func func, Element res, Element[] args)
+ {
+ if (args == null) Args = EmptyArgs;
+ else Args = args;
+ Func = func;
+ Result = res;
+ }
+
+ public override string ToString()
+ {
+ var res = new StringBuilder();
+ res.Append("(").Append(Func.Name);
+ for (int i = 0; i < Args.Length; ++i) {
+ res.Append(" ").Append(Args[i]);
+ }
+ res.Append(") -> ").Append(Result);
+ return res.ToString();
+ }
+ }
+ #endregion
+
+ private List<Func> functions = new List<Func>();
+ private List<Element> elements = new List<Element>();
+ private List<CapturedState> states = new List<CapturedState>();
+ private Dictionary<string, Func> functionsByName = new Dictionary<string, Func>();
+ private Dictionary<string, Element> elementsByName = new Dictionary<string, Element>();
+
+ #region factory methods
+ Element ConstructElement(string name)
+ {
+ if (name.ToLower() == "true") return True;
+ if (name.ToLower() == "false") return False;
+
+ if (name.StartsWith("bv") && name.Length > 4 && Char.IsDigit(name[2]))
+ name = name.Substring(2);
+
+ if (Char.IsDigit(name[0]) || name[0] == '-') {
+ int col = name.IndexOf("bv");
+ int szi = -1;
+
+ if (name.EndsWith(":int"))
+ name = name.Substring(0, name.Length - 4);
+
+ if (col > 0) {
+ if (int.TryParse(name.Substring(col + 2), out szi) && szi > 0) {
+ name = name.Substring(0, col);
+ } else {
+ return null;
+ }
+ } else if (name.EndsWith("]")) {
+ col = name.IndexOf("[");
+ if (col > 0 && int.TryParse(name.Substring(col + 1, name.Length - col - 2), out szi) && szi > 0) {
+ name = name.Substring(0, col);
+ } else {
+ return null;
+ }
+ }
+
+ for (int i = 1; i < name.Length; ++i)
+ if (!Char.IsDigit(name[i]))
+ return null;
+
+ if (szi > 0)
+ return new BitVector(this, name, szi);
+ else
+ return new Integer(this, name);
+ } else if (name[0] == '*' || name.StartsWith("val!") || name.Contains("!val!")) {
+ return new Uninterpreted(this, name);
+ } else if (name.StartsWith("as-array[") && name.EndsWith("]")) {
+ var fnName = name.Substring(9, name.Length - 10);
+ return new Array(this, MkFunc(fnName, 1));
+ } else {
+ return new DatatypeValue(this, name, new List<Element>());
+ }
+ }
+
+ public Element TryMkElement(string name)
+ {
+ Element res;
+
+ if (elementsByName.TryGetValue(name, out res))
+ return res;
+
+ var tmp = ConstructElement(name);
+ if (tmp == null) return null;
+
+ name = tmp.ToString();
+ if (elementsByName.TryGetValue(name, out res))
+ return res;
+
+ elementsByName.Add(name, tmp);
+ elements.Add(tmp);
+ return tmp;
+ }
+
+ public Element MkElement(string name)
+ {
+ Element res = TryMkElement(name);
+ if (res == null)
+ throw new ArgumentException("invalid element name: '" + name + "'");
+ return res;
+ }
+
+ public Func MkFunc(string name, int arity)
+ {
+ Func res;
+ if (functionsByName.TryGetValue(name, out res)) {
+ if (res.Arity != arity)
+ throw new ArgumentException(string.Format("function '{0}' previously created with arity {1}, now trying to recreate with arity {2}", name, res.Arity, arity));
+ return res;
+ }
+ res = new Func(this, name, arity);
+ functionsByName.Add(name, res);
+ functions.Add(res);
+ return res;
+ }
+ #endregion
+
+ #region state management
+ public class CapturedState
+ {
+ List<string> vars = new List<string>();
+ Dictionary<string, Element> valuations = new Dictionary<string, Element>();
+ readonly CapturedState previous;
+ // AL: Dropping "readonly" for corral
+ public /* readonly */ string Name { get; private set; }
+
+ public IEnumerable<string> Variables { get { return vars; } }
+ public IEnumerable<string> AllVariables {
+ get {
+ if (previous != null)
+ return previous.AllVariables.Concat(Variables).Distinct();
+ else
+ return Variables;
+ }
+ }
+ public int VariableCount { get { return vars.Count; } }
+ public bool HasBinding(string varname)
+ {
+ return valuations.ContainsKey(varname);
+ }
+ public Element TryGet(string varname)
+ {
+ CapturedState curr = this;
+ while (curr != null) {
+ Element res;
+ if (curr.valuations.TryGetValue(varname, out res))
+ return res;
+ curr = curr.previous;
+ }
+ return null;
+ }
+
+ public void AddBinding(string varname, Element value)
+ {
+ vars.Add(varname);
+ valuations.Add(varname, value);
+ }
+
+ // Change name of the state
+ public void ChangeName(string newName)
+ {
+ Name = newName;
+ }
+
+ // Change names of variables in this state
+ // (Used by corral)
+ internal void ChangeVariableNames(Dictionary<string, string> varNameMap)
+ {
+ var oldVars = vars;
+ var oldValuations = valuations;
+
+ vars = new List<string>();
+ valuations = new Dictionary<string, Element>();
+
+ foreach (var v in oldVars)
+ {
+ if (varNameMap.ContainsKey(v)) vars.Add(varNameMap[v]);
+ else vars.Add(v);
+ }
+
+ foreach (var kvp in oldValuations)
+ {
+ if (varNameMap.ContainsKey(kvp.Key)) valuations.Add(varNameMap[kvp.Key], kvp.Value);
+ else valuations.Add(kvp.Key, kvp.Value);
+ }
+ }
+
+ internal CapturedState(string name, CapturedState prev)
+ {
+ Name = name;
+ previous = prev;
+ }
+ }
+
+ public CapturedState MkState(string name)
+ {
+ var last = states[states.Count - 1];
+ var s = new CapturedState(name, last);
+ states.Add(s);
+ return s;
+ }
+
+ // Change names of variables in all captured states
+ // (Used by corral)
+ public void ChangeVariableNames(Dictionary<string, string> varNameMap)
+ {
+ foreach (var s in states)
+ {
+ s.ChangeVariableNames(varNameMap);
+ }
+ }
+
+ #endregion
+
+ public Model()
+ {
+ InitialState = new CapturedState("<initial>", null);
+ states.Add(InitialState);
+ True = new Boolean(this, true);
+ elements.Add(True);
+ elementsByName.Add("true", True);
+ False = new Boolean(this, false);
+ elements.Add(False);
+ elementsByName.Add("false", False);
+ }
+
+ public IEnumerable<Func> Functions { get { return functions; } }
+ public IEnumerable<Element> Elements { get { return elements; } }
+ public IEnumerable<CapturedState> States { get { return states; } }
+ public readonly Element True, False;
+ public readonly CapturedState InitialState;
+
+ public bool HasFunc(string name)
+ {
+ return functionsByName.ContainsKey(name);
+ }
+
+ public Func TryGetFunc(string name)
+ {
+ Func res;
+ if (functionsByName.TryGetValue(name, out res))
+ return res;
+ else
+ return null;
+ }
+
+ public Func GetFunc(string name)
+ {
+ Func res = TryGetFunc(name);
+ if (res == null)
+ throw new KeyNotFoundException("function '" + name + "' undefined in the model");
+ return res;
+ }
+
+ public Func TryGetSkolemFunc(string name)
+ {
+ return Functions.Where(f => f.Name.StartsWith(name + "!")).FirstOrDefault();
+ }
+
+ public Element GetElement(string name)
+ {
+ Element res;
+ if (elementsByName.TryGetValue(name, out res))
+ return res;
+ else
+ throw new KeyNotFoundException("element '" + name + "' undefined in the model");
+ }
+
+ public Element MkIntElement(int v)
+ {
+ return MkElement(v.ToString());
+ }
+
+ public void Write(System.IO.TextWriter wr)
+ {
+ wr.WriteLine("*** MODEL");
+ foreach (var f in Functions.OrderBy(f => f.Name))
+ if (f.Arity == 0) {
+ wr.WriteLine("{0} -> {1}", f.Name, f.GetConstant());
+ }
+ foreach (var f in Functions)
+ if (f.Arity != 0) {
+ wr.WriteLine("{0} -> {1}", f.Name, "{");
+ foreach (var app in f.Apps) {
+ wr.Write(" ");
+ foreach (var a in app.Args)
+ wr.Write("{0} ", a);
+ wr.WriteLine("-> {0}", app.Result);
+ }
+ if (f.Else != null)
+ wr.WriteLine(" else -> {0}", f.Else);
+ wr.WriteLine("}");
+ }
+ foreach (var s in States) {
+ if (s == InitialState && s.VariableCount == 0)
+ continue;
+ wr.WriteLine("*** STATE {0}", s.Name);
+ foreach (var v in s.Variables)
+ wr.WriteLine(" {0} -> {1}", v, s.TryGet(v));
+ wr.WriteLine("*** END_STATE", s.Name);
+ }
+ wr.WriteLine("*** END_MODEL");
+ }
+
+ public void Substitute(Dictionary<Element, Element> mapping) {
+ foreach (var f in functions) f.Substitute(mapping);
+ }
+
+ public static List<Model> ParseModels(System.IO.TextReader rd)
+ {
+ ModelParser p = new ParserZ3();
+ p.rd = rd;
+ p.Run();
+ return p.resModels;
+ }
+ }
+}
diff --git a/Source/Model/Model.csproj b/Source/Model/Model.csproj
index c6a1d047..c024975f 100644
--- a/Source/Model/Model.csproj
+++ b/Source/Model/Model.csproj
@@ -1,109 +1,109 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie</RootNamespace>
- <AssemblyName>Model</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Model.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Model.cs" />
- <Compile Include="ModelParser.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="..\version.cs" />
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie</RootNamespace>
+ <AssemblyName>BoogieModel</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Model.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Model.cs" />
+ <Compile Include="ModelParser.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="..\version.cs" />
+ </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/Model/ModelParser.cs b/Source/Model/ModelParser.cs
index 3b9fbb6f..b966d649 100644
--- a/Source/Model/ModelParser.cs
+++ b/Source/Model/ModelParser.cs
@@ -66,8 +66,8 @@ namespace Microsoft.Boogie
string s = o as string;
if (s != null)
return GetElt (s);
- List<object> os = (List<object>)o;
- if (!(os[0] is string))
+ List<object> os = (List<object>)o;
+ if (!(os[0] is string))
os.Insert(0, "_"); // KLM: fix crash on ((as const (Array Int Int)) 0)
List<Model.Element> args = new List<Model.Element> ();
for (int i = 1; i < os.Count; i++) {
diff --git a/Source/Model/Properties/AssemblyInfo.cs b/Source/Model/Properties/AssemblyInfo.cs
index 80c3907a..d69add5b 100644
--- a/Source/Model/Properties/AssemblyInfo.cs
+++ b/Source/Model/Properties/AssemblyInfo.cs
@@ -1,23 +1,23 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Model")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft")]
-[assembly: AssemblyProduct("Model")]
-[assembly: AssemblyCopyright("Copyright © Microsoft 2010-2011")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("24299c94-99db-46c5-8671-5f91faac167e")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Model")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Model")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010-2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("24299c94-99db-46c5-8671-5f91faac167e")]
diff --git a/Source/ModelViewer/BCTProvider.cs b/Source/ModelViewer/BCTProvider.cs
index 6b48c396..3126084f 100644
--- a/Source/ModelViewer/BCTProvider.cs
+++ b/Source/ModelViewer/BCTProvider.cs
@@ -1,147 +1,147 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Microsoft.Boogie.ModelViewer.BCT {
- public class Provider : ILanguageProvider {
- public static Provider Instance = new Provider();
- private Provider() { }
-
- public bool IsMyModel(Model m) {
- return m.TryGetFunc("$Alloc") != null;
- }
-
- public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts) {
- var dm = new BCTModel(m, opts);
- foreach (var s in m.States) {
- var sn = new StateNode(dm.states.Count, dm, s);
- dm.states.Add(sn);
- }
- dm.FinishStates();
- return dm;
- }
- }
-
- class BCTModel : LanguageModel {
- public readonly Model.Func f_heap_select;
- public readonly Dictionary<Model.Element, Model.Element[]> ArrayLengths = new Dictionary<Model.Element, Model.Element[]>();
- Dictionary<Model.Element, string> typeName = new Dictionary<Model.Element, string>();
- public List<StateNode> states = new List<StateNode>();
-
- public BCTModel(Model m, ViewOptions opts)
- : base(m, opts) {
- f_heap_select = m.MkFunc("[3]", 3);
-
- foreach (Model.Func fn in m.Functions) {
-
- }
- }
-
- internal void FinishStates() {
- GenerateSourceLocations(states);
- }
-
- public override IEnumerable<IState> States {
- get { return states; }
- }
-
- public string GetUserVariableName(string name) {
- if (name == "$this")
- return "this";
- if (name.Contains("$"))
- return null;
- if (name == "isControlChecked" || name == "isControlEnabled")
- return null;
- return name;
- }
-
- public Model.Element Image(Model.Element elt, Model.Func f) {
- var r = f.AppWithResult(elt);
- if (r != null)
- return r.Args[0];
- return null;
- }
-
- public IEnumerable<ElementNode> GetExpansion(StateNode state, Model.Element elt) {
- List<ElementNode> result = new List<ElementNode>();
- return result;
- }
- }
-
- class StateNode : NamedState {
- internal readonly BCTModel dm;
- internal readonly List<VariableNode> vars = new List<VariableNode>();
- internal readonly int index;
-
- public StateNode(int i, BCTModel parent, Model.CapturedState s)
- : base(s, parent) {
- dm = parent;
- state = s;
- index = i;
-
- SetupVars();
- }
-
- void SetupVars() {
- var names = Util.Empty<string>();
-
- if (dm.states.Count > 0) {
- var prev = dm.states.Last();
- names = prev.vars.Map(v => v.realName);
- }
-
- names = names.Concat(state.Variables).Distinct();
-
- var curVars = state.Variables.ToDictionary(x => x);
- foreach (var v in names) {
- if (dm.GetUserVariableName(v) != null) {
- var val = state.TryGet(v);
- var vn = new VariableNode(this, v, val);
- vn.updatedHere = dm.states.Count > 0 && curVars.ContainsKey(v);
- if (curVars.ContainsKey(v))
- dm.RegisterLocalValue(vn.Name, val);
- vars.Add(vn);
- }
- }
-
- dm.Flush(Nodes);
- }
-
- public override IEnumerable<IDisplayNode> Nodes {
- get {
- return vars;
- }
- }
- }
-
- class ElementNode : DisplayNode {
- protected StateNode stateNode;
- protected Model.Element elt;
- protected BCTModel vm { get { return stateNode.dm; } }
-
- public ElementNode(StateNode st, EdgeName name, Model.Element elt)
- : base(st.dm, name, elt) {
- this.stateNode = st;
- this.elt = elt;
- }
-
- public ElementNode(StateNode st, string name, Model.Element elt)
- : this(st, new EdgeName(name), elt) { }
-
- protected override void ComputeChildren() {
- children.AddRange(vm.GetExpansion(stateNode, elt));
- }
- }
-
- class VariableNode : ElementNode {
- public bool updatedHere;
- public string realName;
-
- public VariableNode(StateNode par, string realName, Model.Element elt)
- : base(par, realName, elt) {
- this.realName = realName;
- name = new EdgeName(vm.GetUserVariableName(realName));
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Boogie.ModelViewer.BCT {
+ public class Provider : ILanguageProvider {
+ public static Provider Instance = new Provider();
+ private Provider() { }
+
+ public bool IsMyModel(Model m) {
+ return m.TryGetFunc("$Alloc") != null;
+ }
+
+ public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts) {
+ var dm = new BCTModel(m, opts);
+ foreach (var s in m.States) {
+ var sn = new StateNode(dm.states.Count, dm, s);
+ dm.states.Add(sn);
+ }
+ dm.FinishStates();
+ return dm;
+ }
+ }
+
+ class BCTModel : LanguageModel {
+ public readonly Model.Func f_heap_select;
+ public readonly Dictionary<Model.Element, Model.Element[]> ArrayLengths = new Dictionary<Model.Element, Model.Element[]>();
+ Dictionary<Model.Element, string> typeName = new Dictionary<Model.Element, string>();
+ public List<StateNode> states = new List<StateNode>();
+
+ public BCTModel(Model m, ViewOptions opts)
+ : base(m, opts) {
+ f_heap_select = m.MkFunc("[3]", 3);
+
+ foreach (Model.Func fn in m.Functions) {
+
+ }
+ }
+
+ internal void FinishStates() {
+ GenerateSourceLocations(states);
+ }
+
+ public override IEnumerable<IState> States {
+ get { return states; }
+ }
+
+ public string GetUserVariableName(string name) {
+ if (name == "$this")
+ return "this";
+ if (name.Contains("$"))
+ return null;
+ if (name == "isControlChecked" || name == "isControlEnabled")
+ return null;
+ return name;
+ }
+
+ public Model.Element Image(Model.Element elt, Model.Func f) {
+ var r = f.AppWithResult(elt);
+ if (r != null)
+ return r.Args[0];
+ return null;
+ }
+
+ public IEnumerable<ElementNode> GetExpansion(StateNode state, Model.Element elt) {
+ List<ElementNode> result = new List<ElementNode>();
+ return result;
+ }
+ }
+
+ class StateNode : NamedState {
+ internal readonly BCTModel dm;
+ internal readonly List<VariableNode> vars = new List<VariableNode>();
+ internal readonly int index;
+
+ public StateNode(int i, BCTModel parent, Model.CapturedState s)
+ : base(s, parent) {
+ dm = parent;
+ state = s;
+ index = i;
+
+ SetupVars();
+ }
+
+ void SetupVars() {
+ var names = Util.Empty<string>();
+
+ if (dm.states.Count > 0) {
+ var prev = dm.states.Last();
+ names = prev.vars.Map(v => v.realName);
+ }
+
+ names = names.Concat(state.Variables).Distinct();
+
+ var curVars = state.Variables.ToDictionary(x => x);
+ foreach (var v in names) {
+ if (dm.GetUserVariableName(v) != null) {
+ var val = state.TryGet(v);
+ var vn = new VariableNode(this, v, val);
+ vn.updatedHere = dm.states.Count > 0 && curVars.ContainsKey(v);
+ if (curVars.ContainsKey(v))
+ dm.RegisterLocalValue(vn.Name, val);
+ vars.Add(vn);
+ }
+ }
+
+ dm.Flush(Nodes);
+ }
+
+ public override IEnumerable<IDisplayNode> Nodes {
+ get {
+ return vars;
+ }
+ }
+ }
+
+ class ElementNode : DisplayNode {
+ protected StateNode stateNode;
+ protected Model.Element elt;
+ protected BCTModel vm { get { return stateNode.dm; } }
+
+ public ElementNode(StateNode st, EdgeName name, Model.Element elt)
+ : base(st.dm, name, elt) {
+ this.stateNode = st;
+ this.elt = elt;
+ }
+
+ public ElementNode(StateNode st, string name, Model.Element elt)
+ : this(st, new EdgeName(name), elt) { }
+
+ protected override void ComputeChildren() {
+ children.AddRange(vm.GetExpansion(stateNode, elt));
+ }
+ }
+
+ class VariableNode : ElementNode {
+ public bool updatedHere;
+ public string realName;
+
+ public VariableNode(StateNode par, string realName, Model.Element elt)
+ : base(par, realName, elt) {
+ this.realName = realName;
+ name = new EdgeName(vm.GetUserVariableName(realName));
+ }
+ }
+}
diff --git a/Source/ModelViewer/BaseProvider.cs b/Source/ModelViewer/BaseProvider.cs
index 1e9e9cf9..8797fe1f 100644
--- a/Source/ModelViewer/BaseProvider.cs
+++ b/Source/ModelViewer/BaseProvider.cs
@@ -1,136 +1,136 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Microsoft.Boogie.ModelViewer.Base
-{
- public class Provider : ILanguageProvider
- {
- public static Provider Instance = new Provider();
- private Provider() { }
-
- public bool IsMyModel(Model m)
- {
- return true;
- }
-
- public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts)
- {
- return new GenericModel(m, opts);
- }
- }
-
- public class GenericModel : LanguageModel
- {
- List<BaseState> states = new List<BaseState>();
-
- public GenericModel(Model m, ViewOptions opts)
- : base(m, opts)
- {
- foreach (var s in m.States)
- states.Add(new BaseState(this, s) { Name = s.Name });
- foreach (var s in states)
- this.Flush(s.nodes);
- }
-
- public override IEnumerable<IState> States
- {
- get { return states; }
- }
- }
-
- public class BaseState : IState
- {
- internal GenericModel m;
- Model.CapturedState st;
-
- internal List<IDisplayNode> nodes = new List<IDisplayNode>();
- internal Dictionary<Model.Element, string> niceName = new Dictionary<Model.Element, string>();
-
- public BaseState(GenericModel m, Model.CapturedState st)
- {
- this.st = st;
- this.m = m;
-
- foreach (var v in st.AllVariables) {
- var e = st.TryGet(v);
- m.RegisterLocalValue(v, e);
- nodes.Add(new ElementNode(this, v, e));
-
- niceName[e] = v;
- foreach (var r in e.References) {
- if (r.Args.Length == 1 && r.Args[0] == e) {
- if (!niceName.ContainsKey(e))
- niceName[e] = r.Func.Name + "(" + v + ")";
- }
- }
- }
-
- nodes.Add(new ContainerNode<Model.Func>("[Functions]", f => f.Arity == 0 ? null : Function(f), m.model.Functions));
- nodes.Add(new ContainerNode<Model.Func>("[Constants]", f => f.Arity != 0 ? null : new AppNode(this, f.Apps.First()), m.model.Functions));
- }
-
- public virtual SourceViewState ShowSource()
- {
- return null;
- }
-
- IDisplayNode Function(Model.Func f)
- {
- return new ContainerNode<Model.FuncTuple>(f.Name, a => new AppNode(this, a), f.Apps);
- }
-
- public virtual string Name { get; set; }
-
- public virtual IEnumerable<IDisplayNode> Nodes
- {
- get { return nodes; }
- }
- }
-
- public class ElementNode : DisplayNode
- {
- BaseState st;
-
- public ElementNode(BaseState st, string name, Model.Element elt) : base(st.m, name, elt) { this.st = st; }
-
- protected override void ComputeChildren()
- {
- children.Add(new ContainerNode<Model.FuncTuple>(" == ", e => new AppNode(st, e), Element.References.Where(t => t.Result == Element)));
- foreach (var e in Element.References) {
- if (e.Args.Contains(Element))
- children.Add(new AppNode(st, e, x => x == Element ? "*" : st.niceName.GetWithDefault(x, null)));
- }
- }
- }
-
- public class AppNode : ElementNode
- {
- protected Model.FuncTuple tupl;
-
- public AppNode(BaseState m, Model.FuncTuple t) : this(m, t, _ => null) { }
-
- public AppNode(BaseState m, Model.FuncTuple t, Func<Model.Element, string> nameElement)
- : base(m, t.Func.Name, t.Result)
- {
- tupl = t;
- var sb = new StringBuilder();
- sb.Append(t.Func.Name);
- if (t.Args.Length > 0) {
- sb.Append("(");
- for (int i = 0; i < t.Args.Length; ++i) {
- var n = nameElement(t.Args[i]);
- if (n == null)
- sb.AppendFormat("%{0}, ", i);
- else
- sb.AppendFormat("{0}, ", n);
- }
- sb.Length -= 2;
- sb.Append(")");
- }
- name = new EdgeName(m.m, sb.ToString(), t.Args);
- }
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Boogie.ModelViewer.Base
+{
+ public class Provider : ILanguageProvider
+ {
+ public static Provider Instance = new Provider();
+ private Provider() { }
+
+ public bool IsMyModel(Model m)
+ {
+ return true;
+ }
+
+ public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts)
+ {
+ return new GenericModel(m, opts);
+ }
+ }
+
+ public class GenericModel : LanguageModel
+ {
+ List<BaseState> states = new List<BaseState>();
+
+ public GenericModel(Model m, ViewOptions opts)
+ : base(m, opts)
+ {
+ foreach (var s in m.States)
+ states.Add(new BaseState(this, s) { Name = s.Name });
+ foreach (var s in states)
+ this.Flush(s.nodes);
+ }
+
+ public override IEnumerable<IState> States
+ {
+ get { return states; }
+ }
+ }
+
+ public class BaseState : IState
+ {
+ internal GenericModel m;
+ Model.CapturedState st;
+
+ internal List<IDisplayNode> nodes = new List<IDisplayNode>();
+ internal Dictionary<Model.Element, string> niceName = new Dictionary<Model.Element, string>();
+
+ public BaseState(GenericModel m, Model.CapturedState st)
+ {
+ this.st = st;
+ this.m = m;
+
+ foreach (var v in st.AllVariables) {
+ var e = st.TryGet(v);
+ m.RegisterLocalValue(v, e);
+ nodes.Add(new ElementNode(this, v, e));
+
+ niceName[e] = v;
+ foreach (var r in e.References) {
+ if (r.Args.Length == 1 && r.Args[0] == e) {
+ if (!niceName.ContainsKey(e))
+ niceName[e] = r.Func.Name + "(" + v + ")";
+ }
+ }
+ }
+
+ nodes.Add(new ContainerNode<Model.Func>("[Functions]", f => f.Arity == 0 ? null : Function(f), m.model.Functions));
+ nodes.Add(new ContainerNode<Model.Func>("[Constants]", f => f.Arity != 0 ? null : new AppNode(this, f.Apps.First()), m.model.Functions));
+ }
+
+ public virtual SourceViewState ShowSource()
+ {
+ return null;
+ }
+
+ IDisplayNode Function(Model.Func f)
+ {
+ return new ContainerNode<Model.FuncTuple>(f.Name, a => new AppNode(this, a), f.Apps);
+ }
+
+ public virtual string Name { get; set; }
+
+ public virtual IEnumerable<IDisplayNode> Nodes
+ {
+ get { return nodes; }
+ }
+ }
+
+ public class ElementNode : DisplayNode
+ {
+ BaseState st;
+
+ public ElementNode(BaseState st, string name, Model.Element elt) : base(st.m, name, elt) { this.st = st; }
+
+ protected override void ComputeChildren()
+ {
+ children.Add(new ContainerNode<Model.FuncTuple>(" == ", e => new AppNode(st, e), Element.References.Where(t => t.Result == Element)));
+ foreach (var e in Element.References) {
+ if (e.Args.Contains(Element))
+ children.Add(new AppNode(st, e, x => x == Element ? "*" : st.niceName.GetWithDefault(x, null)));
+ }
+ }
+ }
+
+ public class AppNode : ElementNode
+ {
+ protected Model.FuncTuple tupl;
+
+ public AppNode(BaseState m, Model.FuncTuple t) : this(m, t, _ => null) { }
+
+ public AppNode(BaseState m, Model.FuncTuple t, Func<Model.Element, string> nameElement)
+ : base(m, t.Func.Name, t.Result)
+ {
+ tupl = t;
+ var sb = new StringBuilder();
+ sb.Append(t.Func.Name);
+ if (t.Args.Length > 0) {
+ sb.Append("(");
+ for (int i = 0; i < t.Args.Length; ++i) {
+ var n = nameElement(t.Args[i]);
+ if (n == null)
+ sb.AppendFormat("%{0}, ", i);
+ else
+ sb.AppendFormat("{0}, ", n);
+ }
+ sb.Length -= 2;
+ sb.Append(")");
+ }
+ name = new EdgeName(m.m, sb.ToString(), t.Args);
+ }
+ }
+
+}
diff --git a/Source/ModelViewer/DafnyProvider.cs b/Source/ModelViewer/DafnyProvider.cs
index 602df7aa..45c7dada 100644
--- a/Source/ModelViewer/DafnyProvider.cs
+++ b/Source/ModelViewer/DafnyProvider.cs
@@ -1,388 +1,388 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.ModelViewer.Dafny
-{
- public class Provider : ILanguageProvider
- {
- public static Provider Instance = new Provider();
- private Provider() { }
-
- public bool IsMyModel(Model m)
- {
- return m.TryGetFunc("$$Language$Dafny") != null;
- }
-
- public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts)
- {
- var dm = new DafnyModel(m, opts);
- foreach (var s in m.States) {
- var sn = new StateNode(dm.states.Count, dm, s);
- dm.states.Add(sn);
- }
- dm.FinishStates();
- return dm;
- }
- }
-
- public class DafnyModel : LanguageModel
- {
- public readonly Model.Func f_heap_select, f_set_select, f_seq_length, f_seq_index, f_box, f_dim, f_index_field, f_multi_index_field, f_dtype, f_null;
- public readonly Dictionary<Model.Element, Model.Element[]> ArrayLengths = new Dictionary<Model.Element, Model.Element[]>();
- public readonly Dictionary<Model.Element, Model.FuncTuple> DatatypeValues = new Dictionary<Model.Element, Model.FuncTuple>();
- Dictionary<Model.Element, string> typeName = new Dictionary<Model.Element, string>();
- public List<StateNode> states = new List<StateNode>();
-
- public DafnyModel(Model m, ViewOptions opts)
- : base(m, opts)
- {
- f_heap_select = m.MkFunc("[3]", 3);
- f_set_select = m.MkFunc("[2]", 2);
- f_seq_length = m.MkFunc("Seq#Length", 1);
- f_seq_index = m.MkFunc("Seq#Index", 2);
- f_box = m.MkFunc("$Box", 1);
- f_dim = m.MkFunc("FDim", 1);
- f_index_field = m.MkFunc("IndexField", 1);
- f_multi_index_field = m.MkFunc("MultiIndexField", 2);
- f_dtype = m.MkFunc("dtype", 1);
- f_null = m.MkFunc("null", 0);
-
- // collect the array dimensions from the various array.Length functions, and
- // collect all known datatype values
- foreach (var fn in m.Functions) {
- if (Regex.IsMatch(fn.Name, "^_System.array[0-9]*.Length[0-9]*$")) {
- int j = fn.Name.IndexOf('.', 13);
- int dims = j == 13 ? 1 : int.Parse(fn.Name.Substring(13, j - 13));
- int idx = j == 13 ? 0 : int.Parse(fn.Name.Substring(j + 7));
- foreach (var tpl in fn.Apps) {
- var elt = tpl.Args[0];
- var len = tpl.Result;
- Model.Element[] ar;
- if (!ArrayLengths.TryGetValue(elt, out ar)) {
- ar = new Model.Element[dims];
- ArrayLengths.Add(elt, ar);
- }
- Contract.Assert(ar[idx] == null);
- ar[idx] = len;
- }
- } else if (fn.Name.StartsWith("#") && fn.Name.IndexOf('.') != -1 && fn.Name[1] != '#') {
- foreach (var tpl in fn.Apps) {
- var elt = tpl.Result;
- DatatypeValues.Add(elt, tpl);
- }
- }
- }
- }
-
- internal void FinishStates()
- {
- GenerateSourceLocations(states);
- }
-
- public override IEnumerable<IState> States
- {
- get { return states; }
- }
-
- public string GetUserVariableName(string name)
- {
- if (name.StartsWith("$")) // this covers $Heap and $_Frame and $nw...
- return null;
- if (name.Contains("##")) // a temporary variable of the translation
- return null;
-#if SOMETIME_AGAIN
- var hash = name.IndexOf('#');
- if (0 < hash)
- return name.Substring(0, hash);
-#endif
- return name;
- }
-
- public Model.Element Image(Model.Element elt, Model.Func f)
- {
- var r = f.AppWithResult(elt);
- if (r != null)
- return r.Args[0];
- return null;
- }
-
- protected override string CanonicalBaseName(Model.Element elt, out NameSeqSuffix suff)
- {
- Model.FuncTuple fnTuple;
- suff = NameSeqSuffix.WhenNonZero;
- if (DatatypeValues.TryGetValue(elt, out fnTuple)) {
- // elt is s a datatype value, make its name be the name of the datatype constructor
- string nm = fnTuple.Func.Name;
- if (fnTuple.Func.Arity == 0)
- return nm;
- else
- return nm + "(...)";
- }
- var seqLen = f_seq_length.AppWithArg(0, elt);
- if (seqLen != null) {
- // elt is a sequence
- return string.Format("[Length {0}]", seqLen.Result.AsInt());
- }
-
- if (elt == f_null.GetConstant())
- return "null";
-
- var tp = f_dtype.TryEval(elt);
- if (tp != null) {
- foreach (var app in tp.References) {
- if (app.Args.Length == 0 && app.Func.Name.StartsWith("class.")) {
- suff = NameSeqSuffix.Always;
- return app.Func.Name.Substring(6);
- }
- }
- }
-
- return base.CanonicalBaseName(elt, out suff);
- }
-
- public IEnumerable<ElementNode> GetExpansion(StateNode state, Model.Element elt)
- {
- List<ElementNode> result = new List<ElementNode>();
-
- if (elt.Kind != Model.ElementKind.Uninterpreted)
- return result;
-
- // Perhaps elt is a known datatype value
- Model.FuncTuple fnTuple;
- if (DatatypeValues.TryGetValue(elt, out fnTuple)) {
- // elt is a datatype value
- int i = 0;
- foreach (var arg in fnTuple.Args) {
- var edgname = new EdgeName(this, i.ToString());
- result.Add(new FieldNode(state, edgname, arg));
- i++;
- }
- return result;
- }
-
- // Perhaps elt is a sequence
- var seqLen = f_seq_length.AppWithArg(0, elt);
- if (seqLen != null) {
- // elt is a sequence
- foreach (var tpl in f_seq_index.AppsWithArg(0, elt)) {
- var edgname = new EdgeName(this, "[%0]", tpl.Args[1]);
- result.Add(new FieldNode(state, edgname, Unbox(tpl.Result)));
- }
- return result;
- }
-
- // Perhaps elt is a set
- foreach (var tpl in f_set_select.AppsWithArg(0, elt)) {
- var setElement = tpl.Args[1];
- var containment = tpl.Result;
- var edgname = new EdgeName(this, "[%0]", Unbox(setElement));
- result.Add(new FieldNode(state, edgname, containment));
- }
- if (result.Count != 0)
- return result; // elt is a set
-
- // It seems elt is an object or array
- Model.Element[] lengths;
- if (ArrayLengths.TryGetValue(elt, out lengths)) {
- int i = 0;
- foreach (var len in lengths) {
- var name = lengths.Length == 1 ? "Length" : "Length" + i;
- var edgname = new EdgeName(this, name);
- result.Add(new FieldNode(state, edgname, len));
- i++;
- }
- }
- var heap = state.State.TryGet("$Heap");
- if (heap != null) {
- foreach (var tpl in f_heap_select.AppsWithArgs(0, heap, 1, elt)) {
- var field = new FieldName(tpl.Args[2], this);
- if (field.NameFormat != "alloc") {
- var edgname = new EdgeName(this, field.NameFormat, field.NameArgs);
- result.Add(new FieldNode(state, edgname, Unbox(tpl.Result)));
- }
- }
- }
- return result;
- }
-
- class FieldName
- {
- public readonly Model.Element Field;
- public readonly int Dims;
- public readonly string NameFormat;
- public readonly Model.Element[] NameArgs;
-
- public FieldName(Model.Element elt, DafnyModel dm) {
- Field = elt;
- NameArgs = new Model.Element[Dims];
- var tpl = dm.f_dim.AppWithArg(0, elt);
- if (tpl != null) {
- Dims = tpl.Result.AsInt();
- NameArgs = new Model.Element[Dims];
- for (int i = Dims; 0 <= --i; ) {
- if (i == 0) {
- tpl = dm.f_index_field.AppWithResult(elt);
- NameArgs[i] = tpl.Args[0];
- } else {
- tpl = dm.f_multi_index_field.AppWithResult(elt);
- NameArgs[i] = tpl.Args[1];
- elt = tpl.Args[0];
- }
- }
- }
- // now for the name
- if (Dims == 0) {
- NameFormat = Field.ToString();
- foreach (var n in Field.Names) {
- NameFormat = n.Func.Name;
- int dot = NameFormat.LastIndexOf('.');
- if (0 <= dot)
- NameFormat = NameFormat.Substring(dot + 1);
- break;
- }
- } else {
- NameFormat = "[";
- string sep = "";
- for (int i = 0; i < Dims; i++) {
- NameFormat += sep + "%" + i;
- sep = ",";
- }
- NameFormat += "]";
- }
- }
- }
-
- Model.Element Unbox(Model.Element elt) {
- var unboxed = f_box.AppWithResult(elt);
- if (unboxed != null)
- return unboxed.Args[0];
- else
- return elt;
- }
- }
-
- public class StateNode : NamedState
- {
- internal readonly DafnyModel dm;
- public readonly List<VariableNode> Vars = new List<VariableNode>();
- internal readonly List<VariableNode> skolems;
- internal readonly int index;
-
- public StateNode(int i, DafnyModel parent, Model.CapturedState s)
- : base(s, parent)
- {
- dm = parent;
- state = s;
- index = i;
-
- skolems = new List<VariableNode>(SkolemVars());
- SetupVars();
- }
-
- void SetupVars()
- {
- var names = Util.Empty<string>();
-
- if (dm.states.Count > 0) {
- var prev = dm.states.Last();
- names = prev.Vars.Map(v => v.realName);
- }
-
- names = names.Concat(state.Variables).Distinct();
-
- var curVars = state.Variables.ToDictionary(x => x);
- foreach (var v in names) {
- if (dm.GetUserVariableName(v) != null) {
- var val = state.TryGet(v);
- var shortName = Regex.Replace(v, @"#\d+$", "");
- var vn = new VariableNode(this, v, val, names.Any(n => n != v && Regex.Replace(n, @"#\d+$", "") == shortName) ? v : shortName);
- vn.updatedHere = dm.states.Count > 0 && curVars.ContainsKey(v);
- if (curVars.ContainsKey(v))
- dm.RegisterLocalValue(vn.Name, val);
- Vars.Add(vn);
- }
- }
-
- dm.Flush(Nodes);
- }
-
- IEnumerable<VariableNode> SkolemVars() {
- foreach (var f in dm.model.Functions) {
- if (f.Arity != 0) continue;
- int n = f.Name.IndexOf('!');
- if (n == -1) continue;
- string name = f.Name.Substring(0, n);
- if (!name.Contains('#')) continue;
- yield return new VariableNode(this, name, f.GetConstant(), name);
- }
- }
-
- public override IEnumerable<IDisplayNode> Nodes
- {
- get {
- return Vars.Concat(skolems);
- }
- }
- }
-
- public class ElementNode : DisplayNode
- {
- protected StateNode stateNode;
- protected Model.Element elt;
- protected DafnyModel vm { get { return stateNode.dm; } }
-
- public ElementNode(StateNode st, EdgeName name, Model.Element elt)
- : base(st.dm, name, elt)
- {
- this.stateNode = st;
- this.elt = elt;
- }
-
- public ElementNode(StateNode st, string name, Model.Element elt)
- : this(st, new EdgeName(name), elt) { }
-
- protected override void ComputeChildren()
- {
- children.AddRange(vm.GetExpansion(stateNode, elt));
- }
- }
-
- class FieldNode : ElementNode
- {
- public FieldNode(StateNode par, EdgeName realName, Model.Element elt)
- : base(par, realName, elt)
- {
- /*
- var idx = realName.LastIndexOf('.');
- if (idx > 0)
- name = realName.Substring(idx + 1);
- */
- }
- }
-
- class MapletNode : ElementNode
- {
- public MapletNode(StateNode par, EdgeName realName, Model.Element elt)
- : base(par, realName, elt)
- {
- }
- }
-
- public class VariableNode : ElementNode
- {
- public bool updatedHere;
- public string realName;
-
- public VariableNode(StateNode par, string realName, Model.Element elt, string shortName)
- : base(par, realName, elt)
- {
- this.realName = realName;
- name = new EdgeName(vm.GetUserVariableName(realName));
- ShortName = shortName;
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie.ModelViewer.Dafny
+{
+ public class Provider : ILanguageProvider
+ {
+ public static Provider Instance = new Provider();
+ private Provider() { }
+
+ public bool IsMyModel(Model m)
+ {
+ return m.TryGetFunc("$$Language$Dafny") != null;
+ }
+
+ public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts)
+ {
+ var dm = new DafnyModel(m, opts);
+ foreach (var s in m.States) {
+ var sn = new StateNode(dm.states.Count, dm, s);
+ dm.states.Add(sn);
+ }
+ dm.FinishStates();
+ return dm;
+ }
+ }
+
+ public class DafnyModel : LanguageModel
+ {
+ public readonly Model.Func f_heap_select, f_set_select, f_seq_length, f_seq_index, f_box, f_dim, f_index_field, f_multi_index_field, f_dtype, f_null;
+ public readonly Dictionary<Model.Element, Model.Element[]> ArrayLengths = new Dictionary<Model.Element, Model.Element[]>();
+ public readonly Dictionary<Model.Element, Model.FuncTuple> DatatypeValues = new Dictionary<Model.Element, Model.FuncTuple>();
+ Dictionary<Model.Element, string> typeName = new Dictionary<Model.Element, string>();
+ public List<StateNode> states = new List<StateNode>();
+
+ public DafnyModel(Model m, ViewOptions opts)
+ : base(m, opts)
+ {
+ f_heap_select = m.MkFunc("[3]", 3);
+ f_set_select = m.MkFunc("[2]", 2);
+ f_seq_length = m.MkFunc("Seq#Length", 1);
+ f_seq_index = m.MkFunc("Seq#Index", 2);
+ f_box = m.MkFunc("$Box", 1);
+ f_dim = m.MkFunc("FDim", 1);
+ f_index_field = m.MkFunc("IndexField", 1);
+ f_multi_index_field = m.MkFunc("MultiIndexField", 2);
+ f_dtype = m.MkFunc("dtype", 1);
+ f_null = m.MkFunc("null", 0);
+
+ // collect the array dimensions from the various array.Length functions, and
+ // collect all known datatype values
+ foreach (var fn in m.Functions) {
+ if (Regex.IsMatch(fn.Name, "^_System.array[0-9]*.Length[0-9]*$")) {
+ int j = fn.Name.IndexOf('.', 13);
+ int dims = j == 13 ? 1 : int.Parse(fn.Name.Substring(13, j - 13));
+ int idx = j == 13 ? 0 : int.Parse(fn.Name.Substring(j + 7));
+ foreach (var tpl in fn.Apps) {
+ var elt = tpl.Args[0];
+ var len = tpl.Result;
+ Model.Element[] ar;
+ if (!ArrayLengths.TryGetValue(elt, out ar)) {
+ ar = new Model.Element[dims];
+ ArrayLengths.Add(elt, ar);
+ }
+ Contract.Assert(ar[idx] == null);
+ ar[idx] = len;
+ }
+ } else if (fn.Name.StartsWith("#") && fn.Name.IndexOf('.') != -1 && fn.Name[1] != '#') {
+ foreach (var tpl in fn.Apps) {
+ var elt = tpl.Result;
+ DatatypeValues.Add(elt, tpl);
+ }
+ }
+ }
+ }
+
+ internal void FinishStates()
+ {
+ GenerateSourceLocations(states);
+ }
+
+ public override IEnumerable<IState> States
+ {
+ get { return states; }
+ }
+
+ public string GetUserVariableName(string name)
+ {
+ if (name.StartsWith("$")) // this covers $Heap and $_Frame and $nw...
+ return null;
+ if (name.Contains("##")) // a temporary variable of the translation
+ return null;
+#if SOMETIME_AGAIN
+ var hash = name.IndexOf('#');
+ if (0 < hash)
+ return name.Substring(0, hash);
+#endif
+ return name;
+ }
+
+ public Model.Element Image(Model.Element elt, Model.Func f)
+ {
+ var r = f.AppWithResult(elt);
+ if (r != null)
+ return r.Args[0];
+ return null;
+ }
+
+ protected override string CanonicalBaseName(Model.Element elt, out NameSeqSuffix suff)
+ {
+ Model.FuncTuple fnTuple;
+ suff = NameSeqSuffix.WhenNonZero;
+ if (DatatypeValues.TryGetValue(elt, out fnTuple)) {
+ // elt is s a datatype value, make its name be the name of the datatype constructor
+ string nm = fnTuple.Func.Name;
+ if (fnTuple.Func.Arity == 0)
+ return nm;
+ else
+ return nm + "(...)";
+ }
+ var seqLen = f_seq_length.AppWithArg(0, elt);
+ if (seqLen != null) {
+ // elt is a sequence
+ return string.Format("[Length {0}]", seqLen.Result.AsInt());
+ }
+
+ if (elt == f_null.GetConstant())
+ return "null";
+
+ var tp = f_dtype.TryEval(elt);
+ if (tp != null) {
+ foreach (var app in tp.References) {
+ if (app.Args.Length == 0 && app.Func.Name.StartsWith("class.")) {
+ suff = NameSeqSuffix.Always;
+ return app.Func.Name.Substring(6);
+ }
+ }
+ }
+
+ return base.CanonicalBaseName(elt, out suff);
+ }
+
+ public IEnumerable<ElementNode> GetExpansion(StateNode state, Model.Element elt)
+ {
+ List<ElementNode> result = new List<ElementNode>();
+
+ if (elt.Kind != Model.ElementKind.Uninterpreted)
+ return result;
+
+ // Perhaps elt is a known datatype value
+ Model.FuncTuple fnTuple;
+ if (DatatypeValues.TryGetValue(elt, out fnTuple)) {
+ // elt is a datatype value
+ int i = 0;
+ foreach (var arg in fnTuple.Args) {
+ var edgname = new EdgeName(this, i.ToString());
+ result.Add(new FieldNode(state, edgname, arg));
+ i++;
+ }
+ return result;
+ }
+
+ // Perhaps elt is a sequence
+ var seqLen = f_seq_length.AppWithArg(0, elt);
+ if (seqLen != null) {
+ // elt is a sequence
+ foreach (var tpl in f_seq_index.AppsWithArg(0, elt)) {
+ var edgname = new EdgeName(this, "[%0]", tpl.Args[1]);
+ result.Add(new FieldNode(state, edgname, Unbox(tpl.Result)));
+ }
+ return result;
+ }
+
+ // Perhaps elt is a set
+ foreach (var tpl in f_set_select.AppsWithArg(0, elt)) {
+ var setElement = tpl.Args[1];
+ var containment = tpl.Result;
+ var edgname = new EdgeName(this, "[%0]", Unbox(setElement));
+ result.Add(new FieldNode(state, edgname, containment));
+ }
+ if (result.Count != 0)
+ return result; // elt is a set
+
+ // It seems elt is an object or array
+ Model.Element[] lengths;
+ if (ArrayLengths.TryGetValue(elt, out lengths)) {
+ int i = 0;
+ foreach (var len in lengths) {
+ var name = lengths.Length == 1 ? "Length" : "Length" + i;
+ var edgname = new EdgeName(this, name);
+ result.Add(new FieldNode(state, edgname, len));
+ i++;
+ }
+ }
+ var heap = state.State.TryGet("$Heap");
+ if (heap != null) {
+ foreach (var tpl in f_heap_select.AppsWithArgs(0, heap, 1, elt)) {
+ var field = new FieldName(tpl.Args[2], this);
+ if (field.NameFormat != "alloc") {
+ var edgname = new EdgeName(this, field.NameFormat, field.NameArgs);
+ result.Add(new FieldNode(state, edgname, Unbox(tpl.Result)));
+ }
+ }
+ }
+ return result;
+ }
+
+ class FieldName
+ {
+ public readonly Model.Element Field;
+ public readonly int Dims;
+ public readonly string NameFormat;
+ public readonly Model.Element[] NameArgs;
+
+ public FieldName(Model.Element elt, DafnyModel dm) {
+ Field = elt;
+ NameArgs = new Model.Element[Dims];
+ var tpl = dm.f_dim.AppWithArg(0, elt);
+ if (tpl != null) {
+ Dims = tpl.Result.AsInt();
+ NameArgs = new Model.Element[Dims];
+ for (int i = Dims; 0 <= --i; ) {
+ if (i == 0) {
+ tpl = dm.f_index_field.AppWithResult(elt);
+ NameArgs[i] = tpl.Args[0];
+ } else {
+ tpl = dm.f_multi_index_field.AppWithResult(elt);
+ NameArgs[i] = tpl.Args[1];
+ elt = tpl.Args[0];
+ }
+ }
+ }
+ // now for the name
+ if (Dims == 0) {
+ NameFormat = Field.ToString();
+ foreach (var n in Field.Names) {
+ NameFormat = n.Func.Name;
+ int dot = NameFormat.LastIndexOf('.');
+ if (0 <= dot)
+ NameFormat = NameFormat.Substring(dot + 1);
+ break;
+ }
+ } else {
+ NameFormat = "[";
+ string sep = "";
+ for (int i = 0; i < Dims; i++) {
+ NameFormat += sep + "%" + i;
+ sep = ",";
+ }
+ NameFormat += "]";
+ }
+ }
+ }
+
+ Model.Element Unbox(Model.Element elt) {
+ var unboxed = f_box.AppWithResult(elt);
+ if (unboxed != null)
+ return unboxed.Args[0];
+ else
+ return elt;
+ }
+ }
+
+ public class StateNode : NamedState
+ {
+ internal readonly DafnyModel dm;
+ public readonly List<VariableNode> Vars = new List<VariableNode>();
+ internal readonly List<VariableNode> skolems;
+ internal readonly int index;
+
+ public StateNode(int i, DafnyModel parent, Model.CapturedState s)
+ : base(s, parent)
+ {
+ dm = parent;
+ state = s;
+ index = i;
+
+ skolems = new List<VariableNode>(SkolemVars());
+ SetupVars();
+ }
+
+ void SetupVars()
+ {
+ var names = Util.Empty<string>();
+
+ if (dm.states.Count > 0) {
+ var prev = dm.states.Last();
+ names = prev.Vars.Map(v => v.realName);
+ }
+
+ names = names.Concat(state.Variables).Distinct();
+
+ var curVars = state.Variables.ToDictionary(x => x);
+ foreach (var v in names) {
+ if (dm.GetUserVariableName(v) != null) {
+ var val = state.TryGet(v);
+ var shortName = Regex.Replace(v, @"#\d+$", "");
+ var vn = new VariableNode(this, v, val, names.Any(n => n != v && Regex.Replace(n, @"#\d+$", "") == shortName) ? v : shortName);
+ vn.updatedHere = dm.states.Count > 0 && curVars.ContainsKey(v);
+ if (curVars.ContainsKey(v))
+ dm.RegisterLocalValue(vn.Name, val);
+ Vars.Add(vn);
+ }
+ }
+
+ dm.Flush(Nodes);
+ }
+
+ IEnumerable<VariableNode> SkolemVars() {
+ foreach (var f in dm.model.Functions) {
+ if (f.Arity != 0) continue;
+ int n = f.Name.IndexOf('!');
+ if (n == -1) continue;
+ string name = f.Name.Substring(0, n);
+ if (!name.Contains('#')) continue;
+ yield return new VariableNode(this, name, f.GetConstant(), name);
+ }
+ }
+
+ public override IEnumerable<IDisplayNode> Nodes
+ {
+ get {
+ return Vars.Concat(skolems);
+ }
+ }
+ }
+
+ public class ElementNode : DisplayNode
+ {
+ protected StateNode stateNode;
+ protected Model.Element elt;
+ protected DafnyModel vm { get { return stateNode.dm; } }
+
+ public ElementNode(StateNode st, EdgeName name, Model.Element elt)
+ : base(st.dm, name, elt)
+ {
+ this.stateNode = st;
+ this.elt = elt;
+ }
+
+ public ElementNode(StateNode st, string name, Model.Element elt)
+ : this(st, new EdgeName(name), elt) { }
+
+ protected override void ComputeChildren()
+ {
+ children.AddRange(vm.GetExpansion(stateNode, elt));
+ }
+ }
+
+ class FieldNode : ElementNode
+ {
+ public FieldNode(StateNode par, EdgeName realName, Model.Element elt)
+ : base(par, realName, elt)
+ {
+ /*
+ var idx = realName.LastIndexOf('.');
+ if (idx > 0)
+ name = realName.Substring(idx + 1);
+ */
+ }
+ }
+
+ class MapletNode : ElementNode
+ {
+ public MapletNode(StateNode par, EdgeName realName, Model.Element elt)
+ : base(par, realName, elt)
+ {
+ }
+ }
+
+ public class VariableNode : ElementNode
+ {
+ public bool updatedHere;
+ public string realName;
+
+ public VariableNode(StateNode par, string realName, Model.Element elt, string shortName)
+ : base(par, realName, elt)
+ {
+ this.realName = realName;
+ name = new EdgeName(vm.GetUserVariableName(realName));
+ ShortName = shortName;
+ }
+ }
+}
diff --git a/Source/ModelViewer/DataModel.cs b/Source/ModelViewer/DataModel.cs
index 0b54e689..3820a6ab 100644
--- a/Source/ModelViewer/DataModel.cs
+++ b/Source/ModelViewer/DataModel.cs
@@ -1,297 +1,297 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- public class ViewOptions
- {
- // 0 - Normal
- // 1 - Expert
- // 2 - Everything
- // 3 - Include the kitchen sink
- public int ViewLevel = 1;
- public bool DebugMode;
- }
-
- // sync with Main.categoryBrushes!
- public enum NodeCategory
- {
- Local,
- PhysField,
- SpecField,
- MethodologyProperty,
- UserFunction,
- Maplet
- }
-
- public interface ILanguageProvider
- {
- bool IsMyModel(Model m);
- ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts);
- }
-
- public interface ILanguageSpecificModel
- {
- string CanonicalName(Model.Element elt);
-
- Model.Element FindElement(string canonicalName);
-
- string PathName(IEnumerable<IDisplayNode> path);
-
- IEnumerable<IState> States { get; }
-
- // This function is given IDisplayNode possibly from different states.
- IEnumerable<string> SortFields(IEnumerable<IDisplayNode> fields);
- }
-
- public class SourceViewState
- {
- public string Header;
- public string RichTextContent;
- public int Location;
- }
-
- public interface IState
- {
- string Name { get; }
- SourceViewState ShowSource();
- IEnumerable<IDisplayNode> Nodes { get; }
- }
-
- public interface IDisplayNode
- {
- /// <summary>
- /// Used for indexing the state tree.
- /// </summary>
- string Name { get; }
-
- string ShortName { get; }
-
- NodeCategory Category { get; }
- string Value { get; }
- string ToolTip { get; }
-
- int ViewLevel { get; }
-
- /// <summary>
- /// Used to determine aliasing. Can be null.
- /// </summary>
- Model.Element Element { get; }
-
- IEnumerable<Model.Element> References { get; }
-
- IEnumerable<IDisplayNode> Children { get; }
-
- object ViewSync { get; set; }
- }
-
-
- public class TopState : IState
- {
- protected IDisplayNode[] children;
- protected string name;
-
- public TopState(string name, IEnumerable<IDisplayNode> nodes)
- {
- this.name = name;
- children = nodes.ToArray();
- }
-
- public string Name
- {
- get { return name; }
- }
-
- public IEnumerable<IDisplayNode> Nodes
- {
- get { return children; }
- }
-
-
- public SourceViewState ShowSource()
- {
- return null;
- }
-
- }
-
- public abstract class DisplayNode : IDisplayNode
- {
- protected EdgeName name;
- protected Model.Element element;
- protected ILanguageSpecificModel langModel;
- protected List<IDisplayNode> children;
-
- public DisplayNode(ILanguageSpecificModel model, string n, Model.Element elt)
- : this(model, new EdgeName(n), elt) {}
-
- public DisplayNode(ILanguageSpecificModel model, EdgeName n, Model.Element elt)
- {
- langModel = model;
- name = n;
- element = elt;
- }
-
- public virtual string ToolTip
- {
- get { return null; }
- }
-
- public virtual int ViewLevel { get; set; }
- public virtual NodeCategory Category { get; set; }
-
- public virtual IEnumerable<IDisplayNode> Children
- {
- get
- {
- if (children == null) {
- children = new List<IDisplayNode>();
- ComputeChildren();
- }
- return children;
- }
- }
-
- protected virtual void ComputeChildren()
- {
- }
-
- public object ViewSync { get; set; }
-
- public virtual string Name
- {
- get { return name.ToString(); }
- }
-
- private string shortName;
-
- public virtual string ShortName
- {
- get
- {
- if (shortName != null)
- {
- return shortName;
- }
- else
- {
- return name.ToString();
- }
- }
- set
- {
- shortName = value;
- }
- }
-
- public virtual Model.Element Element
- {
- get { return element; }
- }
-
- public virtual string Value
- {
- get
- {
- if (element == null)
- return "";
- return langModel.CanonicalName(element);
- }
- }
-
- public virtual IEnumerable<Model.Element> References
- {
- get
- {
- foreach (var r in name.Dependencies)
- yield return r;
- if (element != null)
- yield return element;
- }
- }
- }
-
- public class ContainerNode<T> : DisplayNode
- {
- protected Func<T, IDisplayNode> convert;
- protected IEnumerable<T> data;
-
- public ContainerNode(EdgeName name, Func<T, IDisplayNode> convert, IEnumerable<T> data) : base(null, name, null)
- {
- this.convert = convert;
- this.data = data;
- }
-
- public ContainerNode(string name, Func<T, IDisplayNode> convert, IEnumerable<T> data)
- : this(new EdgeName(name), convert, data)
- {
- }
-
- protected override void ComputeChildren()
- {
- foreach (var f in data) {
- var res = convert(f);
- if (res != null)
- children.Add(res);
- }
- }
- }
-
-
- public static class Util
- {
- public static void Assert(bool cond)
- {
- if (!cond) throw new System.Exception("assertion violation");
- }
-
- public static string Concat(this IEnumerable<string> strs, string sep)
- {
- var res = new StringBuilder();
- foreach (var e in strs)
- res.Append(e).Append(sep);
- if (res.Length > 0)
- res.Length -= sep.Length;
- return res.ToString();
- }
-
- public static IEnumerable<T> Empty<T>() { yield break; }
-
- public static IEnumerable<T> Singleton<T>(T e) { yield return e; }
-
- public static IEnumerable<T> Concat1<T>(this IEnumerable<T> s, T e) { return s.Concat(Singleton(e)); }
-
- public static IEnumerable<T> Map<S, T>(this IEnumerable<S> inp, Func<S, T> conv)
- {
- foreach (var s in inp) yield return conv(s);
- }
-
- public static void Iter<T>(this IEnumerable<T> inp, Action<T> fn)
- {
- foreach (var s in inp) fn(s);
- }
-
- public static void AddRange<T>(this HashSet<T> st, IEnumerable<T> elts)
- {
- foreach (var e in elts) st.Add(e);
- }
-
- public static T OrElse<T>(T a, T b)
- where T : class
- {
- if (a != null) return a;
- return b;
- }
-
- public static S GetWithDefault<T, S>(this Dictionary<T, S> dict, T key, S defl)
- {
- S r;
- if (dict.TryGetValue(key, out r))
- return r;
- return defl;
- }
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ public class ViewOptions
+ {
+ // 0 - Normal
+ // 1 - Expert
+ // 2 - Everything
+ // 3 - Include the kitchen sink
+ public int ViewLevel = 1;
+ public bool DebugMode;
+ }
+
+ // sync with Main.categoryBrushes!
+ public enum NodeCategory
+ {
+ Local,
+ PhysField,
+ SpecField,
+ MethodologyProperty,
+ UserFunction,
+ Maplet
+ }
+
+ public interface ILanguageProvider
+ {
+ bool IsMyModel(Model m);
+ ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts);
+ }
+
+ public interface ILanguageSpecificModel
+ {
+ string CanonicalName(Model.Element elt);
+
+ Model.Element FindElement(string canonicalName);
+
+ string PathName(IEnumerable<IDisplayNode> path);
+
+ IEnumerable<IState> States { get; }
+
+ // This function is given IDisplayNode possibly from different states.
+ IEnumerable<string> SortFields(IEnumerable<IDisplayNode> fields);
+ }
+
+ public class SourceViewState
+ {
+ public string Header;
+ public string RichTextContent;
+ public int Location;
+ }
+
+ public interface IState
+ {
+ string Name { get; }
+ SourceViewState ShowSource();
+ IEnumerable<IDisplayNode> Nodes { get; }
+ }
+
+ public interface IDisplayNode
+ {
+ /// <summary>
+ /// Used for indexing the state tree.
+ /// </summary>
+ string Name { get; }
+
+ string ShortName { get; }
+
+ NodeCategory Category { get; }
+ string Value { get; }
+ string ToolTip { get; }
+
+ int ViewLevel { get; }
+
+ /// <summary>
+ /// Used to determine aliasing. Can be null.
+ /// </summary>
+ Model.Element Element { get; }
+
+ IEnumerable<Model.Element> References { get; }
+
+ IEnumerable<IDisplayNode> Children { get; }
+
+ object ViewSync { get; set; }
+ }
+
+
+ public class TopState : IState
+ {
+ protected IDisplayNode[] children;
+ protected string name;
+
+ public TopState(string name, IEnumerable<IDisplayNode> nodes)
+ {
+ this.name = name;
+ children = nodes.ToArray();
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public IEnumerable<IDisplayNode> Nodes
+ {
+ get { return children; }
+ }
+
+
+ public SourceViewState ShowSource()
+ {
+ return null;
+ }
+
+ }
+
+ public abstract class DisplayNode : IDisplayNode
+ {
+ protected EdgeName name;
+ protected Model.Element element;
+ protected ILanguageSpecificModel langModel;
+ protected List<IDisplayNode> children;
+
+ public DisplayNode(ILanguageSpecificModel model, string n, Model.Element elt)
+ : this(model, new EdgeName(n), elt) {}
+
+ public DisplayNode(ILanguageSpecificModel model, EdgeName n, Model.Element elt)
+ {
+ langModel = model;
+ name = n;
+ element = elt;
+ }
+
+ public virtual string ToolTip
+ {
+ get { return null; }
+ }
+
+ public virtual int ViewLevel { get; set; }
+ public virtual NodeCategory Category { get; set; }
+
+ public virtual IEnumerable<IDisplayNode> Children
+ {
+ get
+ {
+ if (children == null) {
+ children = new List<IDisplayNode>();
+ ComputeChildren();
+ }
+ return children;
+ }
+ }
+
+ protected virtual void ComputeChildren()
+ {
+ }
+
+ public object ViewSync { get; set; }
+
+ public virtual string Name
+ {
+ get { return name.ToString(); }
+ }
+
+ private string shortName;
+
+ public virtual string ShortName
+ {
+ get
+ {
+ if (shortName != null)
+ {
+ return shortName;
+ }
+ else
+ {
+ return name.ToString();
+ }
+ }
+ set
+ {
+ shortName = value;
+ }
+ }
+
+ public virtual Model.Element Element
+ {
+ get { return element; }
+ }
+
+ public virtual string Value
+ {
+ get
+ {
+ if (element == null)
+ return "";
+ return langModel.CanonicalName(element);
+ }
+ }
+
+ public virtual IEnumerable<Model.Element> References
+ {
+ get
+ {
+ foreach (var r in name.Dependencies)
+ yield return r;
+ if (element != null)
+ yield return element;
+ }
+ }
+ }
+
+ public class ContainerNode<T> : DisplayNode
+ {
+ protected Func<T, IDisplayNode> convert;
+ protected IEnumerable<T> data;
+
+ public ContainerNode(EdgeName name, Func<T, IDisplayNode> convert, IEnumerable<T> data) : base(null, name, null)
+ {
+ this.convert = convert;
+ this.data = data;
+ }
+
+ public ContainerNode(string name, Func<T, IDisplayNode> convert, IEnumerable<T> data)
+ : this(new EdgeName(name), convert, data)
+ {
+ }
+
+ protected override void ComputeChildren()
+ {
+ foreach (var f in data) {
+ var res = convert(f);
+ if (res != null)
+ children.Add(res);
+ }
+ }
+ }
+
+
+ public static class Util
+ {
+ public static void Assert(bool cond)
+ {
+ if (!cond) throw new System.Exception("assertion violation");
+ }
+
+ public static string Concat(this IEnumerable<string> strs, string sep)
+ {
+ var res = new StringBuilder();
+ foreach (var e in strs)
+ res.Append(e).Append(sep);
+ if (res.Length > 0)
+ res.Length -= sep.Length;
+ return res.ToString();
+ }
+
+ public static IEnumerable<T> Empty<T>() { yield break; }
+
+ public static IEnumerable<T> Singleton<T>(T e) { yield return e; }
+
+ public static IEnumerable<T> Concat1<T>(this IEnumerable<T> s, T e) { return s.Concat(Singleton(e)); }
+
+ public static IEnumerable<T> Map<S, T>(this IEnumerable<S> inp, Func<S, T> conv)
+ {
+ foreach (var s in inp) yield return conv(s);
+ }
+
+ public static void Iter<T>(this IEnumerable<T> inp, Action<T> fn)
+ {
+ foreach (var s in inp) fn(s);
+ }
+
+ public static void AddRange<T>(this HashSet<T> st, IEnumerable<T> elts)
+ {
+ foreach (var e in elts) st.Add(e);
+ }
+
+ public static T OrElse<T>(T a, T b)
+ where T : class
+ {
+ if (a != null) return a;
+ return b;
+ }
+
+ public static S GetWithDefault<T, S>(this Dictionary<T, S> dict, T key, S defl)
+ {
+ S r;
+ if (dict.TryGetValue(key, out r))
+ return r;
+ return defl;
+ }
+ }
+
+}
diff --git a/Source/ModelViewer/Main.Designer.cs b/Source/ModelViewer/Main.Designer.cs
index a58e7354..be15f3c6 100644
--- a/Source/ModelViewer/Main.Designer.cs
+++ b/Source/ModelViewer/Main.Designer.cs
@@ -1,499 +1,499 @@
-namespace Microsoft.Boogie.ModelViewer
-{
- partial class Main
- {
- /// <summary>
- /// Required designer variable.
- /// </summary>
- private System.ComponentModel.IContainer components = null;
-
- /// <summary>
- /// Clean up any resources being used.
- /// </summary>
- /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- /// <summary>
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- /// </summary>
- private void InitializeComponent()
- {
- this.components = new System.ComponentModel.Container();
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
- this.currentStateView = new System.Windows.Forms.ListView();
- this.name = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.prevValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.stateViewMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.dummyItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.splitContainer1 = new System.Windows.Forms.SplitContainer();
- this.splitContainer2 = new System.Windows.Forms.SplitContainer();
- this.matchesList = new System.Windows.Forms.ListView();
- this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.linkLabel1 = new System.Windows.Forms.LinkLabel();
- this.label1 = new System.Windows.Forms.Label();
- this.textBox1 = new System.Windows.Forms.TextBox();
- this.stateList = new System.Windows.Forms.ListView();
- this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
- this.showSourceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.menuStrip1 = new System.Windows.Forms.MenuStrip();
- this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.openModelMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
- this.reloadModelFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.normalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.expertToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.everythingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.includeTheKitchenSinkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
- this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.largeFontToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.modelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.openModelFileDialog = new System.Windows.Forms.OpenFileDialog();
- this.stateViewMenu.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
- this.splitContainer1.Panel1.SuspendLayout();
- this.splitContainer1.Panel2.SuspendLayout();
- this.splitContainer1.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
- this.splitContainer2.Panel1.SuspendLayout();
- this.splitContainer2.Panel2.SuspendLayout();
- this.splitContainer2.SuspendLayout();
- this.contextMenuStrip1.SuspendLayout();
- this.menuStrip1.SuspendLayout();
- this.SuspendLayout();
- //
- // currentStateView
- //
- this.currentStateView.BackColor = System.Drawing.SystemColors.Window;
- this.currentStateView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.name,
- this.value,
- this.prevValue});
- this.currentStateView.ContextMenuStrip = this.stateViewMenu;
- this.currentStateView.Dock = System.Windows.Forms.DockStyle.Fill;
- this.currentStateView.FullRowSelect = true;
- this.currentStateView.GridLines = true;
- this.currentStateView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
- this.currentStateView.Location = new System.Drawing.Point(0, 0);
- this.currentStateView.MultiSelect = false;
- this.currentStateView.Name = "currentStateView";
- this.currentStateView.OwnerDraw = true;
- this.currentStateView.ShowItemToolTips = true;
- this.currentStateView.Size = new System.Drawing.Size(596, 344);
- this.currentStateView.TabIndex = 0;
- this.currentStateView.UseCompatibleStateImageBehavior = false;
- this.currentStateView.View = System.Windows.Forms.View.Details;
- this.currentStateView.ColumnWidthChanged += new System.Windows.Forms.ColumnWidthChangedEventHandler(this.listView1_ColumnWidthChanged);
- this.currentStateView.DrawColumnHeader += new System.Windows.Forms.DrawListViewColumnHeaderEventHandler(this.listView1_DrawColumnHeader);
- this.currentStateView.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.listView1_DrawItem);
- this.currentStateView.SelectedIndexChanged += new System.EventHandler(this.currentStateView_SelectedIndexChanged);
- this.currentStateView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.currentStateView_KeyDown);
- this.currentStateView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseUp);
- this.currentStateView.Resize += new System.EventHandler(this.listView1_Resize);
- //
- // name
- //
- this.name.Text = "Name";
- this.name.Width = 298;
- //
- // value
- //
- this.value.Text = "Value";
- this.value.Width = 126;
- //
- // prevValue
- //
- this.prevValue.Text = "Previous";
- this.prevValue.Width = 100;
- //
- // stateViewMenu
- //
- this.stateViewMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.dummyItemToolStripMenuItem});
- this.stateViewMenu.Name = "stateViewMenu";
- this.stateViewMenu.Size = new System.Drawing.Size(145, 26);
- this.stateViewMenu.Opening += new System.ComponentModel.CancelEventHandler(this.stateViewMenu_Opening);
- //
- // dummyItemToolStripMenuItem
- //
- this.dummyItemToolStripMenuItem.Name = "dummyItemToolStripMenuItem";
- this.dummyItemToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
- this.dummyItemToolStripMenuItem.Text = "Dummy item";
- //
- // splitContainer1
- //
- this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.splitContainer1.Location = new System.Drawing.Point(0, 24);
- this.splitContainer1.Name = "splitContainer1";
- //
- // splitContainer1.Panel1
- //
- this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
- //
- // splitContainer1.Panel2
- //
- this.splitContainer1.Panel2.Controls.Add(this.stateList);
- this.splitContainer1.Size = new System.Drawing.Size(915, 449);
- this.splitContainer1.SplitterDistance = 596;
- this.splitContainer1.TabIndex = 1;
- //
- // splitContainer2
- //
- this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
- this.splitContainer2.Location = new System.Drawing.Point(0, 0);
- this.splitContainer2.Name = "splitContainer2";
- this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
- //
- // splitContainer2.Panel1
- //
- this.splitContainer2.Panel1.Controls.Add(this.currentStateView);
- //
- // splitContainer2.Panel2
- //
- this.splitContainer2.Panel2.Controls.Add(this.matchesList);
- this.splitContainer2.Panel2.Controls.Add(this.linkLabel1);
- this.splitContainer2.Panel2.Controls.Add(this.label1);
- this.splitContainer2.Panel2.Controls.Add(this.textBox1);
- this.splitContainer2.Size = new System.Drawing.Size(596, 449);
- this.splitContainer2.SplitterDistance = 344;
- this.splitContainer2.TabIndex = 1;
- //
- // matchesList
- //
- this.matchesList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.matchesList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.columnHeader4,
- this.columnHeader5});
- this.matchesList.FullRowSelect = true;
- this.matchesList.GridLines = true;
- this.matchesList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
- this.matchesList.Location = new System.Drawing.Point(0, 29);
- this.matchesList.MultiSelect = false;
- this.matchesList.Name = "matchesList";
- this.matchesList.OwnerDraw = true;
- this.matchesList.ShowItemToolTips = true;
- this.matchesList.Size = new System.Drawing.Size(596, 72);
- this.matchesList.TabIndex = 4;
- this.matchesList.UseCompatibleStateImageBehavior = false;
- this.matchesList.View = System.Windows.Forms.View.Details;
- this.matchesList.ColumnWidthChanged += new System.Windows.Forms.ColumnWidthChangedEventHandler(this.listView1_ColumnWidthChanged);
- this.matchesList.DrawColumnHeader += new System.Windows.Forms.DrawListViewColumnHeaderEventHandler(this.listView1_DrawColumnHeader);
- this.matchesList.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.listView1_DrawItem);
- this.matchesList.DoubleClick += new System.EventHandler(this.matchesList_DoubleClick);
- this.matchesList.Resize += new System.EventHandler(this.matchesList_Resize);
- //
- // columnHeader4
- //
- this.columnHeader4.Text = "Name";
- this.columnHeader4.Width = 300;
- //
- // columnHeader5
- //
- this.columnHeader5.Text = "Value";
- this.columnHeader5.Width = 250;
- //
- // linkLabel1
- //
- this.linkLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.linkLabel1.AutoSize = true;
- this.linkLabel1.Location = new System.Drawing.Point(536, 5);
- this.linkLabel1.Name = "linkLabel1";
- this.linkLabel1.Size = new System.Drawing.Size(57, 13);
- this.linkLabel1.TabIndex = 3;
- this.linkLabel1.TabStop = true;
- this.linkLabel1.Text = "Show All...";
- this.linkLabel1.VisitedLinkColor = System.Drawing.Color.Blue;
- this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(3, 5);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(44, 13);
- this.label1.TabIndex = 2;
- this.label1.Text = "Search:";
- //
- // textBox1
- //
- this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.textBox1.Location = new System.Drawing.Point(53, 3);
- this.textBox1.Name = "textBox1";
- this.textBox1.Size = new System.Drawing.Size(477, 20);
- this.textBox1.TabIndex = 1;
- this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
- //
- // stateList
- //
- this.stateList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.columnHeader3,
- this.columnHeader1,
- this.columnHeader2});
- this.stateList.ContextMenuStrip = this.contextMenuStrip1;
- this.stateList.Dock = System.Windows.Forms.DockStyle.Fill;
- this.stateList.FullRowSelect = true;
- this.stateList.GridLines = true;
- this.stateList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
- this.stateList.Location = new System.Drawing.Point(0, 0);
- this.stateList.MultiSelect = false;
- this.stateList.Name = "stateList";
- this.stateList.ShowItemToolTips = true;
- this.stateList.Size = new System.Drawing.Size(315, 449);
- this.stateList.TabIndex = 0;
- this.stateList.UseCompatibleStateImageBehavior = false;
- this.stateList.View = System.Windows.Forms.View.Details;
- this.stateList.SelectedIndexChanged += new System.EventHandler(this.stateList_SelectedIndexChanged);
- this.stateList.DoubleClick += new System.EventHandler(this.stateList_DoubleClick);
- //
- // columnHeader3
- //
- this.columnHeader3.Text = "#";
- this.columnHeader3.Width = 22;
- //
- // columnHeader1
- //
- this.columnHeader1.Text = "State";
- this.columnHeader1.Width = 169;
- //
- // columnHeader2
- //
- this.columnHeader2.Text = "Value";
- this.columnHeader2.Width = 116;
- //
- // contextMenuStrip1
- //
- this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.showSourceToolStripMenuItem});
- this.contextMenuStrip1.Name = "contextMenuStrip1";
- this.contextMenuStrip1.Size = new System.Drawing.Size(142, 26);
- //
- // showSourceToolStripMenuItem
- //
- this.showSourceToolStripMenuItem.Name = "showSourceToolStripMenuItem";
- this.showSourceToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
- this.showSourceToolStripMenuItem.Text = "Show source";
- this.showSourceToolStripMenuItem.Click += new System.EventHandler(this.showSourceToolStripMenuItem_Click);
- //
- // menuStrip1
- //
- this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.fileToolStripMenuItem,
- this.viewToolStripMenuItem,
- this.modelsToolStripMenuItem});
- this.menuStrip1.Location = new System.Drawing.Point(0, 0);
- this.menuStrip1.Name = "menuStrip1";
- this.menuStrip1.Size = new System.Drawing.Size(915, 24);
- this.menuStrip1.TabIndex = 1;
- this.menuStrip1.Text = "menuStrip1";
- //
- // fileToolStripMenuItem
- //
- this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.openModelMenuItem,
- this.toolStripSeparator1,
- this.reloadModelFileToolStripMenuItem,
- this.exitToolStripMenuItem});
- this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
- this.fileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
- this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
- this.fileToolStripMenuItem.Text = "&File";
- //
- // openModelMenuItem
- //
- this.openModelMenuItem.Name = "openModelMenuItem";
- this.openModelMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
- this.openModelMenuItem.Size = new System.Drawing.Size(211, 22);
- this.openModelMenuItem.Text = "&Open model file...";
- this.openModelMenuItem.Click += new System.EventHandler(this.openModelMenuItem_Click);
- //
- // toolStripSeparator1
- //
- this.toolStripSeparator1.Name = "toolStripSeparator1";
- this.toolStripSeparator1.Size = new System.Drawing.Size(208, 6);
- //
- // reloadModelFileToolStripMenuItem
- //
- this.reloadModelFileToolStripMenuItem.Name = "reloadModelFileToolStripMenuItem";
- this.reloadModelFileToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5;
- this.reloadModelFileToolStripMenuItem.Size = new System.Drawing.Size(211, 22);
- this.reloadModelFileToolStripMenuItem.Text = "&Reload model file";
- this.reloadModelFileToolStripMenuItem.Click += new System.EventHandler(this.reloadModelFileToolStripMenuItem_Click);
- //
- // exitToolStripMenuItem
- //
- this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
- this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
- this.exitToolStripMenuItem.Size = new System.Drawing.Size(211, 22);
- this.exitToolStripMenuItem.Text = "&Exit";
- this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
- //
- // viewToolStripMenuItem
- //
- this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.normalToolStripMenuItem,
- this.expertToolStripMenuItem,
- this.everythingToolStripMenuItem,
- this.includeTheKitchenSinkToolStripMenuItem,
- this.toolStripMenuItem1,
- this.debugToolStripMenuItem,
- this.largeFontToolStripMenuItem});
- this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
- this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
- this.viewToolStripMenuItem.Text = "&View";
- //
- // normalToolStripMenuItem
- //
- this.normalToolStripMenuItem.Name = "normalToolStripMenuItem";
- this.normalToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
- this.normalToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
- this.normalToolStripMenuItem.Text = "&Normal";
- this.normalToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
- //
- // expertToolStripMenuItem
- //
- this.expertToolStripMenuItem.Checked = true;
- this.expertToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
- this.expertToolStripMenuItem.Name = "expertToolStripMenuItem";
- this.expertToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
- this.expertToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
- this.expertToolStripMenuItem.Text = "E&xpert";
- this.expertToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
- //
- // everythingToolStripMenuItem
- //
- this.everythingToolStripMenuItem.Name = "everythingToolStripMenuItem";
- this.everythingToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E)));
- this.everythingToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
- this.everythingToolStripMenuItem.Text = "&Everything";
- this.everythingToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
- //
- // includeTheKitchenSinkToolStripMenuItem
- //
- this.includeTheKitchenSinkToolStripMenuItem.Name = "includeTheKitchenSinkToolStripMenuItem";
- this.includeTheKitchenSinkToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.K)));
- this.includeTheKitchenSinkToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
- this.includeTheKitchenSinkToolStripMenuItem.Text = "&Include the kitchen sink";
- this.includeTheKitchenSinkToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
- //
- // toolStripMenuItem1
- //
- this.toolStripMenuItem1.Name = "toolStripMenuItem1";
- this.toolStripMenuItem1.Size = new System.Drawing.Size(237, 6);
- //
- // debugToolStripMenuItem
- //
- this.debugToolStripMenuItem.Name = "debugToolStripMenuItem";
- this.debugToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
- this.debugToolStripMenuItem.Text = "Debug";
- this.debugToolStripMenuItem.Click += new System.EventHandler(this.debugToolStripMenuItem_Click);
- //
- // largeFontToolStripMenuItem
- //
- this.largeFontToolStripMenuItem.Name = "largeFontToolStripMenuItem";
- this.largeFontToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
- this.largeFontToolStripMenuItem.Text = "Large font";
- this.largeFontToolStripMenuItem.Click += new System.EventHandler(this.largeFontToolStripMenuItem_Click);
- //
- // modelsToolStripMenuItem
- //
- this.modelsToolStripMenuItem.Name = "modelsToolStripMenuItem";
- this.modelsToolStripMenuItem.Size = new System.Drawing.Size(58, 20);
- this.modelsToolStripMenuItem.Text = "&Models";
- //
- // openModelFileDialog
- //
- this.openModelFileDialog.Filter = "Model files (*.model)|*.model|All files (*.*)|*.*";
- this.openModelFileDialog.Title = "Open model file";
- //
- // Main
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(915, 473);
- this.Controls.Add(this.splitContainer1);
- this.Controls.Add(this.menuStrip1);
- this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.Name = "Main";
- this.Text = "Boogie Verification Debugger";
- this.Load += new System.EventHandler(this.Main_Load);
- this.stateViewMenu.ResumeLayout(false);
- this.splitContainer1.Panel1.ResumeLayout(false);
- this.splitContainer1.Panel2.ResumeLayout(false);
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
- this.splitContainer1.ResumeLayout(false);
- this.splitContainer2.Panel1.ResumeLayout(false);
- this.splitContainer2.Panel2.ResumeLayout(false);
- this.splitContainer2.Panel2.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
- this.splitContainer2.ResumeLayout(false);
- this.contextMenuStrip1.ResumeLayout(false);
- this.menuStrip1.ResumeLayout(false);
- this.menuStrip1.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.ListView currentStateView;
- private System.Windows.Forms.ColumnHeader name;
- private System.Windows.Forms.ColumnHeader value;
- private System.Windows.Forms.SplitContainer splitContainer1;
- private System.Windows.Forms.ListView stateList;
- private System.Windows.Forms.ColumnHeader columnHeader1;
- private System.Windows.Forms.ColumnHeader columnHeader2;
- private System.Windows.Forms.ColumnHeader columnHeader3;
- private System.Windows.Forms.ColumnHeader prevValue;
- private System.Windows.Forms.SplitContainer splitContainer2;
- private System.Windows.Forms.ListView matchesList;
- private System.Windows.Forms.ColumnHeader columnHeader4;
- private System.Windows.Forms.ColumnHeader columnHeader5;
- private System.Windows.Forms.LinkLabel linkLabel1;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.TextBox textBox1;
- private System.Windows.Forms.ContextMenuStrip stateViewMenu;
- private System.Windows.Forms.ToolStripMenuItem dummyItemToolStripMenuItem;
- private System.Windows.Forms.MenuStrip menuStrip1;
- private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem normalToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem expertToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem everythingToolStripMenuItem;
- private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
- private System.Windows.Forms.ToolStripMenuItem debugToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem modelsToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem includeTheKitchenSinkToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem reloadModelFileToolStripMenuItem;
- private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
- private System.Windows.Forms.ToolStripMenuItem showSourceToolStripMenuItem;
- private System.Windows.Forms.ToolStripMenuItem openModelMenuItem;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
- private System.Windows.Forms.OpenFileDialog openModelFileDialog;
- private System.Windows.Forms.ToolStripMenuItem largeFontToolStripMenuItem;
-
-
- }
-}
-
+namespace Microsoft.Boogie.ModelViewer
+{
+ partial class Main
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
+ this.currentStateView = new System.Windows.Forms.ListView();
+ this.name = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.prevValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.stateViewMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.dummyItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.splitContainer2 = new System.Windows.Forms.SplitContainer();
+ this.matchesList = new System.Windows.Forms.ListView();
+ this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.linkLabel1 = new System.Windows.Forms.LinkLabel();
+ this.label1 = new System.Windows.Forms.Label();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.stateList = new System.Windows.Forms.ListView();
+ this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.showSourceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.openModelMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.reloadModelFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.normalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.expertToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.everythingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.includeTheKitchenSinkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
+ this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.largeFontToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.modelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.openModelFileDialog = new System.Windows.Forms.OpenFileDialog();
+ this.stateViewMenu.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
+ this.splitContainer2.Panel1.SuspendLayout();
+ this.splitContainer2.Panel2.SuspendLayout();
+ this.splitContainer2.SuspendLayout();
+ this.contextMenuStrip1.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // currentStateView
+ //
+ this.currentStateView.BackColor = System.Drawing.SystemColors.Window;
+ this.currentStateView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.name,
+ this.value,
+ this.prevValue});
+ this.currentStateView.ContextMenuStrip = this.stateViewMenu;
+ this.currentStateView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.currentStateView.FullRowSelect = true;
+ this.currentStateView.GridLines = true;
+ this.currentStateView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this.currentStateView.Location = new System.Drawing.Point(0, 0);
+ this.currentStateView.MultiSelect = false;
+ this.currentStateView.Name = "currentStateView";
+ this.currentStateView.OwnerDraw = true;
+ this.currentStateView.ShowItemToolTips = true;
+ this.currentStateView.Size = new System.Drawing.Size(596, 344);
+ this.currentStateView.TabIndex = 0;
+ this.currentStateView.UseCompatibleStateImageBehavior = false;
+ this.currentStateView.View = System.Windows.Forms.View.Details;
+ this.currentStateView.ColumnWidthChanged += new System.Windows.Forms.ColumnWidthChangedEventHandler(this.listView1_ColumnWidthChanged);
+ this.currentStateView.DrawColumnHeader += new System.Windows.Forms.DrawListViewColumnHeaderEventHandler(this.listView1_DrawColumnHeader);
+ this.currentStateView.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.listView1_DrawItem);
+ this.currentStateView.SelectedIndexChanged += new System.EventHandler(this.currentStateView_SelectedIndexChanged);
+ this.currentStateView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.currentStateView_KeyDown);
+ this.currentStateView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseUp);
+ this.currentStateView.Resize += new System.EventHandler(this.listView1_Resize);
+ //
+ // name
+ //
+ this.name.Text = "Name";
+ this.name.Width = 298;
+ //
+ // value
+ //
+ this.value.Text = "Value";
+ this.value.Width = 126;
+ //
+ // prevValue
+ //
+ this.prevValue.Text = "Previous";
+ this.prevValue.Width = 100;
+ //
+ // stateViewMenu
+ //
+ this.stateViewMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.dummyItemToolStripMenuItem});
+ this.stateViewMenu.Name = "stateViewMenu";
+ this.stateViewMenu.Size = new System.Drawing.Size(145, 26);
+ this.stateViewMenu.Opening += new System.ComponentModel.CancelEventHandler(this.stateViewMenu_Opening);
+ //
+ // dummyItemToolStripMenuItem
+ //
+ this.dummyItemToolStripMenuItem.Name = "dummyItemToolStripMenuItem";
+ this.dummyItemToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
+ this.dummyItemToolStripMenuItem.Text = "Dummy item";
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 24);
+ this.splitContainer1.Name = "splitContainer1";
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.stateList);
+ this.splitContainer1.Size = new System.Drawing.Size(915, 449);
+ this.splitContainer1.SplitterDistance = 596;
+ this.splitContainer1.TabIndex = 1;
+ //
+ // splitContainer2
+ //
+ this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer2.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer2.Name = "splitContainer2";
+ this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer2.Panel1
+ //
+ this.splitContainer2.Panel1.Controls.Add(this.currentStateView);
+ //
+ // splitContainer2.Panel2
+ //
+ this.splitContainer2.Panel2.Controls.Add(this.matchesList);
+ this.splitContainer2.Panel2.Controls.Add(this.linkLabel1);
+ this.splitContainer2.Panel2.Controls.Add(this.label1);
+ this.splitContainer2.Panel2.Controls.Add(this.textBox1);
+ this.splitContainer2.Size = new System.Drawing.Size(596, 449);
+ this.splitContainer2.SplitterDistance = 344;
+ this.splitContainer2.TabIndex = 1;
+ //
+ // matchesList
+ //
+ this.matchesList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.matchesList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeader4,
+ this.columnHeader5});
+ this.matchesList.FullRowSelect = true;
+ this.matchesList.GridLines = true;
+ this.matchesList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
+ this.matchesList.Location = new System.Drawing.Point(0, 29);
+ this.matchesList.MultiSelect = false;
+ this.matchesList.Name = "matchesList";
+ this.matchesList.OwnerDraw = true;
+ this.matchesList.ShowItemToolTips = true;
+ this.matchesList.Size = new System.Drawing.Size(596, 72);
+ this.matchesList.TabIndex = 4;
+ this.matchesList.UseCompatibleStateImageBehavior = false;
+ this.matchesList.View = System.Windows.Forms.View.Details;
+ this.matchesList.ColumnWidthChanged += new System.Windows.Forms.ColumnWidthChangedEventHandler(this.listView1_ColumnWidthChanged);
+ this.matchesList.DrawColumnHeader += new System.Windows.Forms.DrawListViewColumnHeaderEventHandler(this.listView1_DrawColumnHeader);
+ this.matchesList.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.listView1_DrawItem);
+ this.matchesList.DoubleClick += new System.EventHandler(this.matchesList_DoubleClick);
+ this.matchesList.Resize += new System.EventHandler(this.matchesList_Resize);
+ //
+ // columnHeader4
+ //
+ this.columnHeader4.Text = "Name";
+ this.columnHeader4.Width = 300;
+ //
+ // columnHeader5
+ //
+ this.columnHeader5.Text = "Value";
+ this.columnHeader5.Width = 250;
+ //
+ // linkLabel1
+ //
+ this.linkLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.linkLabel1.AutoSize = true;
+ this.linkLabel1.Location = new System.Drawing.Point(536, 5);
+ this.linkLabel1.Name = "linkLabel1";
+ this.linkLabel1.Size = new System.Drawing.Size(57, 13);
+ this.linkLabel1.TabIndex = 3;
+ this.linkLabel1.TabStop = true;
+ this.linkLabel1.Text = "Show All...";
+ this.linkLabel1.VisitedLinkColor = System.Drawing.Color.Blue;
+ this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(3, 5);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(44, 13);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Search:";
+ //
+ // textBox1
+ //
+ this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBox1.Location = new System.Drawing.Point(53, 3);
+ this.textBox1.Name = "textBox1";
+ this.textBox1.Size = new System.Drawing.Size(477, 20);
+ this.textBox1.TabIndex = 1;
+ this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
+ //
+ // stateList
+ //
+ this.stateList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeader3,
+ this.columnHeader1,
+ this.columnHeader2});
+ this.stateList.ContextMenuStrip = this.contextMenuStrip1;
+ this.stateList.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.stateList.FullRowSelect = true;
+ this.stateList.GridLines = true;
+ this.stateList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this.stateList.Location = new System.Drawing.Point(0, 0);
+ this.stateList.MultiSelect = false;
+ this.stateList.Name = "stateList";
+ this.stateList.ShowItemToolTips = true;
+ this.stateList.Size = new System.Drawing.Size(315, 449);
+ this.stateList.TabIndex = 0;
+ this.stateList.UseCompatibleStateImageBehavior = false;
+ this.stateList.View = System.Windows.Forms.View.Details;
+ this.stateList.SelectedIndexChanged += new System.EventHandler(this.stateList_SelectedIndexChanged);
+ this.stateList.DoubleClick += new System.EventHandler(this.stateList_DoubleClick);
+ //
+ // columnHeader3
+ //
+ this.columnHeader3.Text = "#";
+ this.columnHeader3.Width = 22;
+ //
+ // columnHeader1
+ //
+ this.columnHeader1.Text = "State";
+ this.columnHeader1.Width = 169;
+ //
+ // columnHeader2
+ //
+ this.columnHeader2.Text = "Value";
+ this.columnHeader2.Width = 116;
+ //
+ // contextMenuStrip1
+ //
+ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.showSourceToolStripMenuItem});
+ this.contextMenuStrip1.Name = "contextMenuStrip1";
+ this.contextMenuStrip1.Size = new System.Drawing.Size(142, 26);
+ //
+ // showSourceToolStripMenuItem
+ //
+ this.showSourceToolStripMenuItem.Name = "showSourceToolStripMenuItem";
+ this.showSourceToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
+ this.showSourceToolStripMenuItem.Text = "Show source";
+ this.showSourceToolStripMenuItem.Click += new System.EventHandler(this.showSourceToolStripMenuItem_Click);
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileToolStripMenuItem,
+ this.viewToolStripMenuItem,
+ this.modelsToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(915, 24);
+ this.menuStrip1.TabIndex = 1;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // fileToolStripMenuItem
+ //
+ this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.openModelMenuItem,
+ this.toolStripSeparator1,
+ this.reloadModelFileToolStripMenuItem,
+ this.exitToolStripMenuItem});
+ this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+ this.fileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
+ this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+ this.fileToolStripMenuItem.Text = "&File";
+ //
+ // openModelMenuItem
+ //
+ this.openModelMenuItem.Name = "openModelMenuItem";
+ this.openModelMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
+ this.openModelMenuItem.Size = new System.Drawing.Size(211, 22);
+ this.openModelMenuItem.Text = "&Open model file...";
+ this.openModelMenuItem.Click += new System.EventHandler(this.openModelMenuItem_Click);
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(208, 6);
+ //
+ // reloadModelFileToolStripMenuItem
+ //
+ this.reloadModelFileToolStripMenuItem.Name = "reloadModelFileToolStripMenuItem";
+ this.reloadModelFileToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5;
+ this.reloadModelFileToolStripMenuItem.Size = new System.Drawing.Size(211, 22);
+ this.reloadModelFileToolStripMenuItem.Text = "&Reload model file";
+ this.reloadModelFileToolStripMenuItem.Click += new System.EventHandler(this.reloadModelFileToolStripMenuItem_Click);
+ //
+ // exitToolStripMenuItem
+ //
+ this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
+ this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
+ this.exitToolStripMenuItem.Size = new System.Drawing.Size(211, 22);
+ this.exitToolStripMenuItem.Text = "&Exit";
+ this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
+ //
+ // viewToolStripMenuItem
+ //
+ this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.normalToolStripMenuItem,
+ this.expertToolStripMenuItem,
+ this.everythingToolStripMenuItem,
+ this.includeTheKitchenSinkToolStripMenuItem,
+ this.toolStripMenuItem1,
+ this.debugToolStripMenuItem,
+ this.largeFontToolStripMenuItem});
+ this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
+ this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
+ this.viewToolStripMenuItem.Text = "&View";
+ //
+ // normalToolStripMenuItem
+ //
+ this.normalToolStripMenuItem.Name = "normalToolStripMenuItem";
+ this.normalToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
+ this.normalToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
+ this.normalToolStripMenuItem.Text = "&Normal";
+ this.normalToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
+ //
+ // expertToolStripMenuItem
+ //
+ this.expertToolStripMenuItem.Checked = true;
+ this.expertToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.expertToolStripMenuItem.Name = "expertToolStripMenuItem";
+ this.expertToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
+ this.expertToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
+ this.expertToolStripMenuItem.Text = "E&xpert";
+ this.expertToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
+ //
+ // everythingToolStripMenuItem
+ //
+ this.everythingToolStripMenuItem.Name = "everythingToolStripMenuItem";
+ this.everythingToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E)));
+ this.everythingToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
+ this.everythingToolStripMenuItem.Text = "&Everything";
+ this.everythingToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
+ //
+ // includeTheKitchenSinkToolStripMenuItem
+ //
+ this.includeTheKitchenSinkToolStripMenuItem.Name = "includeTheKitchenSinkToolStripMenuItem";
+ this.includeTheKitchenSinkToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.K)));
+ this.includeTheKitchenSinkToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
+ this.includeTheKitchenSinkToolStripMenuItem.Text = "&Include the kitchen sink";
+ this.includeTheKitchenSinkToolStripMenuItem.Click += new System.EventHandler(this.normalToolStripMenuItem_Click);
+ //
+ // toolStripMenuItem1
+ //
+ this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+ this.toolStripMenuItem1.Size = new System.Drawing.Size(237, 6);
+ //
+ // debugToolStripMenuItem
+ //
+ this.debugToolStripMenuItem.Name = "debugToolStripMenuItem";
+ this.debugToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
+ this.debugToolStripMenuItem.Text = "Debug";
+ this.debugToolStripMenuItem.Click += new System.EventHandler(this.debugToolStripMenuItem_Click);
+ //
+ // largeFontToolStripMenuItem
+ //
+ this.largeFontToolStripMenuItem.Name = "largeFontToolStripMenuItem";
+ this.largeFontToolStripMenuItem.Size = new System.Drawing.Size(240, 22);
+ this.largeFontToolStripMenuItem.Text = "Large font";
+ this.largeFontToolStripMenuItem.Click += new System.EventHandler(this.largeFontToolStripMenuItem_Click);
+ //
+ // modelsToolStripMenuItem
+ //
+ this.modelsToolStripMenuItem.Name = "modelsToolStripMenuItem";
+ this.modelsToolStripMenuItem.Size = new System.Drawing.Size(58, 20);
+ this.modelsToolStripMenuItem.Text = "&Models";
+ //
+ // openModelFileDialog
+ //
+ this.openModelFileDialog.Filter = "Model files (*.model)|*.model|All files (*.*)|*.*";
+ this.openModelFileDialog.Title = "Open model file";
+ //
+ // Main
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(915, 473);
+ this.Controls.Add(this.splitContainer1);
+ this.Controls.Add(this.menuStrip1);
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.Name = "Main";
+ this.Text = "Boogie Verification Debugger";
+ this.Load += new System.EventHandler(this.Main_Load);
+ this.stateViewMenu.ResumeLayout(false);
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ this.splitContainer2.Panel1.ResumeLayout(false);
+ this.splitContainer2.Panel2.ResumeLayout(false);
+ this.splitContainer2.Panel2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
+ this.splitContainer2.ResumeLayout(false);
+ this.contextMenuStrip1.ResumeLayout(false);
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ListView currentStateView;
+ private System.Windows.Forms.ColumnHeader name;
+ private System.Windows.Forms.ColumnHeader value;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.ListView stateList;
+ private System.Windows.Forms.ColumnHeader columnHeader1;
+ private System.Windows.Forms.ColumnHeader columnHeader2;
+ private System.Windows.Forms.ColumnHeader columnHeader3;
+ private System.Windows.Forms.ColumnHeader prevValue;
+ private System.Windows.Forms.SplitContainer splitContainer2;
+ private System.Windows.Forms.ListView matchesList;
+ private System.Windows.Forms.ColumnHeader columnHeader4;
+ private System.Windows.Forms.ColumnHeader columnHeader5;
+ private System.Windows.Forms.LinkLabel linkLabel1;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox textBox1;
+ private System.Windows.Forms.ContextMenuStrip stateViewMenu;
+ private System.Windows.Forms.ToolStripMenuItem dummyItemToolStripMenuItem;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem normalToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem expertToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem everythingToolStripMenuItem;
+ private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem debugToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem modelsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem includeTheKitchenSinkToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem reloadModelFileToolStripMenuItem;
+ private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem showSourceToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem openModelMenuItem;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.OpenFileDialog openModelFileDialog;
+ private System.Windows.Forms.ToolStripMenuItem largeFontToolStripMenuItem;
+
+
+ }
+}
+
diff --git a/Source/ModelViewer/Main.cs b/Source/ModelViewer/Main.cs
index 5fed89da..4697e454 100644
--- a/Source/ModelViewer/Main.cs
+++ b/Source/ModelViewer/Main.cs
@@ -1,870 +1,870 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-
-using System.IO;
-using Microsoft.Boogie;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- public partial class Main : Form
- {
- SkeletonItem unfoldingRoot;
- SkeletonItem[] allItems;
- public int CurrentState, PreviousState = -1;
- IState[] states;
- internal ILanguageProvider langProvider;
- public ILanguageSpecificModel LangModel;
- ToolStripMenuItem[] viewItems;
- Model currentModel;
- Model[] allModels;
- int modelId;
- string lastModelFileName;
- internal ViewOptions viewOpts = new ViewOptions();
- Font smallFont, largeFont;
- int lineHeight;
-
- // TODO this should be dynamically loaded
- IEnumerable<ILanguageProvider> Providers()
- {
- yield return BCT.Provider.Instance;
- yield return Vcc.Provider.Instance;
- yield return Dafny.Provider.Instance;
- yield return Base.Provider.Instance;
- }
-
- public Main(string[] args, bool runAsHostedWindow = false)
- {
- InitializeComponent();
-
- smallFont = stateList.Font;
-
- if (runAsHostedWindow) {
- this.fileToolStripMenuItem.Enabled = false;
- this.fileToolStripMenuItem.Visible = false;
- }
-
- viewItems = new ToolStripMenuItem[] {
- normalToolStripMenuItem,
- expertToolStripMenuItem,
- everythingToolStripMenuItem,
- includeTheKitchenSinkToolStripMenuItem
- };
-
- var debugBreak = false;
- string filename = null;
-
- for (int i = 1; i < args.Length; i++) {
- var arg = args[i];
- if (arg == "/break" || arg == "-break")
- debugBreak = true;
- else
- filename = arg;
- }
-
- if (debugBreak) {
- System.Diagnostics.Debugger.Launch();
- }
-
- if (filename != null) {
- var idx = filename.IndexOf(':');
- if (idx > 0) {
- modelId = int.Parse(filename.Substring(idx + 1));
- filename = filename.Substring(0, idx);
- }
- }
-
- this.ReadModels(filename, this.modelId);
- }
-
- private void SetWindowTitle(string fileName)
- {
- if (fileName == null) {
- this.Text = "Boogie Verification Debugger";
- } else {
- this.Text = Path.GetFileName(fileName) + " - Boogie Verification Debugger";
- }
- }
-
- public void ReadModel(string model, int setModelIdTo = 0)
- {
- Contract.Requires(model != null);
-
- using (var rd = new StringReader(model))
- {
- allModels = Model.ParseModels(rd).ToArray();
- }
-
- AddAndLoadModel(setModelIdTo);
- }
-
- public void ReadModels(string modelFileName, int setModelIdTo)
- {
- this.lastModelFileName = modelFileName;
- this.langProvider = Base.Provider.Instance;
-
- if (!string.IsNullOrWhiteSpace(modelFileName) && File.Exists(modelFileName)) {
- using (var rd = File.OpenText(modelFileName)) {
- allModels = Model.ParseModels(rd).ToArray();
- }
-
- AddAndLoadModel(setModelIdTo);
- } else {
- currentModel = new Model();
- }
-
- this.SetWindowTitle(modelFileName);
- }
-
- private void AddAndLoadModel(int setModelIdTo)
- {
- modelId = setModelIdTo;
-
- if (modelId >= allModels.Length)
- modelId = 0;
-
- currentModel = allModels[modelId];
- AddModelMenu();
-
- foreach (var p in Providers())
- {
- if (p.IsMyModel(currentModel))
- {
- this.langProvider = p;
- break;
- }
- }
-
- LoadModel(modelId);
- }
-
- private void LoadModel(int idx)
- {
- var i = 0;
-
- //var stateIdx = stateList.SelectedIndices.Count == 0 ? 0 : stateList.SelectedIndices[0];
-
- modelId = idx;
- foreach (ToolStripMenuItem it in modelsToolStripMenuItem.DropDownItems) {
- it.Checked = i++ == idx;
- }
- currentModel = allModels[idx];
- BuildModel();
-
- /*
- if (stateList.Items.Count <= stateIdx)
- stateIdx = 0;
- stateList.Items[stateIdx].Selected = true;
- */
- }
-
- private void AddModelMenu()
- {
- modelsToolStripMenuItem.DropDownItems.Clear();
- var idx = 0;
- foreach (var m in allModels) {
- var currIdx = idx++; // this local needs to be in this block
- var menuItem = modelsToolStripMenuItem.DropDownItems.Add(string.Format("Model #&{0}", currIdx), null, (s, a) => LoadModel(currIdx)) as ToolStripMenuItem;
- if (currIdx <= 9) {
- menuItem.ShortcutKeys = Keys.Control | (Keys)(currIdx + Keys.D0);
- }
- }
- }
-
- private void BuildModel()
- {
- stateList.Items.Clear();
-
- var items = new List<ListViewItem>();
- LangModel = langProvider.GetLanguageSpecificModel(currentModel, viewOpts);
- states = LangModel.States.ToArray();
- var oldRoot = unfoldingRoot;
- SkeletonItem selectedSkel = null;
- if (oldRoot != null && SelectedNode() != null) {
- selectedSkel = SelectedNode().skel;
- }
- unfoldingRoot = new SkeletonItem(this, states.Length);
- allItems = unfoldingRoot.PopulateRoot(states);
-
- var idx = 0;
- foreach (var i in states) {
- var it = new ListViewItem(new string[] { idx.ToString(), i.Name, "" });
- it.Tag = i;
- items.Add(it);
- idx++;
- }
- stateList.Items.AddRange(items.ToArray());
- unfoldingRoot.Expanded = true;
-
- if (oldRoot == null) {
- SetState(0);
- stateList.Items[0].Selected = true;
- SetColumnSizes();
- } else {
- var mapping = new Dictionary<SkeletonItem, SkeletonItem>();
- unfoldingRoot.SyncWith(mapping, oldRoot);
- SkeletonItem newIt = null;
- while (selectedSkel != null) {
- if (mapping.TryGetValue(selectedSkel, out newIt)) break;
- selectedSkel = selectedSkel.parent;
- }
- if (CurrentState >= stateList.Items.Count)
- CurrentState = 0;
- if (PreviousState >= stateList.Items.Count)
- PreviousState = -1;
- if (newIt != null) GotoNode(newIt);
- SyncStateListValues();
- UpdateMatches(true);
- }
- }
-
- private void SetColumnSizes()
- {
- currentStateView.Columns[0].Width = currentStateView.Width - currentStateView.Columns[1].Width - currentStateView.Columns[2].Width - 25;
- stateList.Columns[1].Width = stateList.Width - stateList.Columns[0].Width - stateList.Columns[2].Width - 25;
- }
-
- public void SetState(int id, bool updateView = false)
- {
- if (updateView)
- {
- stateList.SelectedIndices.Clear();
- stateList.SelectedIndices.Add(id);
- }
- if (CurrentState != id) {
- PreviousState = CurrentState;
- CurrentState = id;
- }
- UpdateMatches(true);
- }
-
- public void HideStateList()
- {
- stateList.Hide();
- splitContainer1.Panel2.Hide();
- splitContainer1.Panel2Collapsed = true;
- splitContainer1.SplitterDistance = splitContainer1.Width;
- }
-
- public void HideMenuStrip()
- {
- menuStrip1.Hide();
- }
-
- internal void Activate(TreeNode treeNode)
- {
- throw new NotImplementedException();
- }
-
- private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
- {
-
- }
-
- static Color Col(int c)
- {
- return Color.FromArgb(c >> 16, (c >> 8) & 0xff, c & 0xff);
- }
-
- static StringFormat center = new StringFormat() { Alignment = StringAlignment.Center };
- static Pen plusPen = new Pen(Col(0xaaaaaa));
- static Brush grayedOut = new SolidBrush(Col(0xaaaaaa));
- static Brush nonPrimary = new SolidBrush(Col(0xeeeeee));
- static Brush matchBg = new SolidBrush(Col(0xFFFA6F));
-
- static SolidBrush currentStateBrush = new SolidBrush(Color.Red);
- static SolidBrush regularStateBrush = new SolidBrush(Color.Black);
- static SolidBrush previousStateBrush = new SolidBrush(Color.Blue);
-
- static SolidBrush[] categoryBrushes = new SolidBrush[] {
- new SolidBrush(Color.Black), // Local
- new SolidBrush(Color.Black), // PhysField
- new SolidBrush(Color.Green), // SpecField
- new SolidBrush(Color.Peru), // MethodologyProperty
- new SolidBrush(Color.Green), // UserFunction
- new SolidBrush(Color.Black), // Maplet
- };
-
- private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
- {
- var item = (DisplayItem)e.Item;
- var skel = item.skel;
- var rect = e.Bounds;
- var listView = (ListView)sender;
- lineHeight = rect.Height;
- rect.Y += 1;
- rect.Height -= 2;
-
- var textBrush = Brushes.Black;
- if (listView.SelectedIndices.Count > 0 && listView.SelectedIndices[0] == e.ItemIndex) {
- e.Graphics.FillRectangle(Brushes.Aquamarine, rect);
- textBrush = Brushes.White;
- } else {
- var bg = Brushes.White;
- if (item.active && !skel.isPrimary[CurrentState])
- bg = nonPrimary;
- if (item.skel.isMatch)
- bg = matchBg;
- e.Graphics.FillRectangle(bg, rect);
- }
-
- var off = lineHeight * item.skel.level;
- if (item.IsMatchListItem)
- off = 0;
-
- {
- var plusRect = rect;
- plusRect.Width = lineHeight;
- plusRect.X += off;
- var plusBorder = plusRect;
- plusBorder.Height = lineHeight / 2;
- plusBorder.Width = lineHeight / 2;
- plusBorder.X += lineHeight / 4;
- plusBorder.Y += lineHeight / 4;
- e.Graphics.DrawRectangle(plusPen, plusBorder);
- if (skel.Expandable) {
- float midX = plusBorder.X + plusBorder.Width / 2;
- float midY = plusBorder.Y + plusBorder.Height / 2;
- e.Graphics.DrawLine(plusPen, plusBorder.X + 2, midY, plusBorder.Right - 2, midY);
- if (!item.skel.expanded)
- e.Graphics.DrawLine(plusPen, midX, plusBorder.Y + 2, midX, plusBorder.Bottom - 2);
- }
- }
-
- off += lineHeight + 3;
- var nameRect = rect;
- var font = listView.Font;
-
- textBrush = categoryBrushes[(int)item.dispNode.Category];
-
- if (!item.active)
- textBrush = grayedOut;
-
- nameRect.Width = listView.Columns[0].Width - 1 - off;
- nameRect.X += off;
- var width = DrawString(e.Graphics, item.SubItems[0].Text, font, textBrush, nameRect);
-
- textBrush = item.active ? Brushes.Black : grayedOut;
- nameRect.X += width + 4;
- nameRect.Width = listView.Columns[0].Width + listView.Columns[1].Width - nameRect.X;
- width = DrawString(e.Graphics, item.SubItems[1].Text, font, textBrush, nameRect);
-
- nameRect.X += width + 4;
- nameRect.Width = listView.Width - nameRect.X;
- var t = item.SubItems[2].Text;
- width = DrawString(e.Graphics, t, font, t == item.SubItems[1].Text ? grayedOut : Brushes.Black, nameRect);
- }
-
- private int DrawString(Graphics g, string s, Font font, Brush textBrush, Rectangle minRect)
- {
- var sz = g.MeasureString(s, font).Width;
- if (sz > minRect.Width - 2) {
- minRect.Width = (int)(sz + 20);
- }
- g.DrawString(s, font, textBrush, minRect);
- return minRect.Width;
- }
-
- private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
- {
- e.DrawBackground();
- var brush = regularStateBrush;
- if (e.Header.Index == 1)
- brush = currentStateBrush;
- else if (e.Header.Index == 2)
- brush = previousStateBrush;
-
- Rectangle r = e.Bounds;
- r.X += 5;
- r.Y += 4;
- DrawString(e.Graphics, e.Header.Text, e.Header.ListView.Font, brush, r);
- }
-
- private void listView1_MouseUp(object sender, MouseEventArgs e)
- {
- var clickedItem = (DisplayItem)currentStateView.GetItemAt(5, e.Y);
- if (clickedItem != null) {
- clickedItem.Selected = true;
- clickedItem.Focused = true;
-
- var skel = clickedItem.skel;
- int plusLoc = skel.level * lineHeight;
- if (skel.Expandable && e.X >= plusLoc && e.X <= plusLoc + lineHeight) {
- skel.Expanded = !skel.Expanded;
- SyncCurrentStateView();
- }
- }
- }
-
- private void SyncCurrentStateView()
- {
- SyncListView(unfoldingRoot.RecChildren, currentStateView, (x, y) => { });
- }
-
- private void SyncListView(IEnumerable<SkeletonItem> items, ListView listView, Action<DisplayItem, SkeletonItem> cb)
- {
- var ch = items.ToArray();
- var missing = ch.Length - listView.Items.Count;
- listView.BeginUpdate();
- if (missing < 0) {
- missing = -missing;
- while (missing-- > 0) {
- listView.Items.RemoveAt(listView.Items.Count - 1);
- }
- } else {
- while (missing-- > 0) {
- listView.Items.Add(new DisplayItem());
- }
- }
- for (int i = 0; i < ch.Length; ++i) {
- var di = (DisplayItem)listView.Items[i];
- cb(di, ch[i]);
- di.Set(ch[i], CurrentState, PreviousState);
- }
- listView.EndUpdate();
- listView.Invalidate();
- }
-
- private void listView1_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
- {
- currentStateView.Invalidate();
- }
-
- private void listView1_Resize(object sender, EventArgs e)
- {
- SetColumnSizes();
- currentStateView.Invalidate();
- }
-
- private void stateList_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (stateList.SelectedItems.Count == 0) return;
- var sel = stateList.SelectedItems[0].Index;
-
- if (PreviousState >= 0)
- stateList.Items[PreviousState].ForeColor = regularStateBrush.Color;
-
- SetState(sel);
- }
-
- DisplayItem SelectedNode()
- {
- if (currentStateView.SelectedItems.Count == 0) return null;
- return (DisplayItem)currentStateView.SelectedItems[0];
- }
-
- private void currentStateView_SelectedIndexChanged(object sender, EventArgs e)
- {
- SyncStateListValues();
- }
-
- private void SyncStateListValues()
- {
- var sel = SelectedNode();
- if (sel == null) return;
-
- stateList.BeginUpdate();
- for (int i = 0; i < sel.skel.displayNodes.Length; ++i) {
- var dn = sel.skel.displayNodes[i];
- stateList.Items[i].SubItems[2].Text = dn == null ? "" : dn.Value;
- }
- stateList.EndUpdate();
- }
-
- private void ExpandParents(SkeletonItem item)
- {
- item = item.parent;
- while (item != null) {
- item.Expanded = true;
- item = item.parent;
- }
- }
-
- private void textBox1_TextChanged(object sender, EventArgs e)
- {
- UpdateMatches(false);
- }
-
- private void UpdateMatches(bool force)
- {
- var bad = false;
- Model.Element eltEq = null;
- var eltRef = new List<Model.Element>();
- var words = new List<string>();
-
- foreach (var w in textBox1.Text.Split(' ')) {
- if (w == "") continue;
- if (w.StartsWith("eq:")) {
- if (eltEq != null) bad = true;
- else {
- eltEq = LangModel.FindElement(w.Substring(3));
- if (eltEq == null) bad = true;
- }
- } else if (w.StartsWith("use:")) {
- var e = LangModel.FindElement(w.Substring(4));
- if (e == null) bad = true;
- else eltRef.Add(e);
- } else {
- words.Add(w.ToLower());
- }
- }
-
- textBox1.ForeColor = bad ? Color.Red : Color.Black;
-
- var wordsA = words.ToArray();
- var refsA = eltRef.ToArray();
-
- if (eltEq == null && wordsA.Length == 0 && refsA.Length == 0)
- bad = true;
-
- var changed = true; // force;
- var matches = new List<SkeletonItem>();
-
- foreach (var s in allItems) {
- var newMatch = false;
- if (s.isPrimary[CurrentState] && !bad) {
- newMatch = s.MatchesWords(wordsA, refsA, eltEq, CurrentState);
- }
- if (newMatch)
- matches.Add(s);
- if (s.isMatch != newMatch) {
- changed = true;
- s.isMatch = newMatch;
- }
- }
-
- if (PreviousState >= 0)
- stateList.Items[PreviousState].ForeColor = previousStateBrush.Color;
- stateList.Items[CurrentState].ForeColor = currentStateBrush.Color;
-
- if (changed) {
- SyncListView(matches, matchesList, (di, _) => { di.IsMatchListItem = true; });
- SyncCurrentStateView();
- }
- }
-
- private void matchesList_Resize(object sender, EventArgs e)
- {
- matchesList.Invalidate();
- }
-
- private void matchesList_DoubleClick(object sender, EventArgs e)
- {
- if (matchesList.SelectedItems.Count == 0) return;
- var sel = (DisplayItem)matchesList.SelectedItems[0];
- GotoNode(sel.skel);
- }
-
- private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
- {
- foreach (DisplayItem it in matchesList.Items) {
- ExpandParents(it.skel);
- }
- SyncCurrentStateView();
- }
-
- private void SetSearch(string text)
- {
- textBox1.Text = text;
- }
-
- private void GotoNode(SkeletonItem skel)
- {
- ExpandParents(skel);
- SyncCurrentStateView();
- foreach (DisplayItem it in currentStateView.Items) {
- if (it.skel == skel) {
- it.Selected = true;
- currentStateView.EnsureVisible(it.Index);
- break;
- }
- }
- }
-
- private IEnumerable<SkeletonItem> NamesFor(Model.Element elt)
- {
- var words = new string[0];
- var elts = new Model.Element[0];
-
- foreach (var s in allItems) {
- if (s.isPrimary[CurrentState] && s.MatchesWords(words, elts, elt, CurrentState)) {
- yield return s;
- }
- }
- }
-
- private void AddMenuItems(IEnumerable<SkeletonItem> skels, ToolStripItemCollection items, string pref, int max)
- {
- var skelsM = skels.Take(max).ToArray();
-
- foreach (var s in skelsM) {
- var tmp = s;
- items.Add(pref + s.LongName(CurrentState), null, (x, _) => GotoNode(tmp));
- }
-
- if (skelsM.Length == max)
- items.Add(new ToolStripMenuItem("...") { Enabled = false });
- }
-
- private void stateViewMenu_Opening(object sender, CancelEventArgs e)
- {
- IDisplayNode sel = null;
- SkeletonItem skel = null;
- if (SelectedNode() != null) {
- sel = SelectedNode().dispNode;
- skel = SelectedNode().skel;
- }
-
- var items = stateViewMenu.Items;
- items.Clear();
-
- if (sel == null) {
- items.Add(new ToolStripMenuItem("Unavailable") { Enabled = false });
- return;
- }
-
- foreach (var x in sel.References.Where(q => q != sel.Element)) {
- var t = new ToolStripMenuItem(LangModel.CanonicalName(x));
- items.Add(t);
- AddMenuItems(NamesFor(x), t.DropDownItems, "= ", 20);
- }
-
- if (sel.Element != null) {
- var selName = LangModel.CanonicalName(sel.Element);
- items.Add("Find uses...", null, (s, _) => SetSearch("use:" + selName));
-
- var aliases = NamesFor(sel.Element).Where(s => s != skel).ToArray();
- if (aliases.Length > 0) {
- items.Add("Aliases...", null, (s, _) => SetSearch("eq:" + selName));
- AddMenuItems(aliases, items, " = ", 10);
- }
- }
- }
-
- private void normalToolStripMenuItem_Click(object sender, EventArgs e)
- {
- int viewLev = -1;
- for (int i = 0; i < viewItems.Length; ++i) {
- if (viewItems[i] == sender) {
- viewLev = i;
- viewItems[i].Checked = true;
- } else {
- viewItems[i].Checked = false;
- }
- }
- if (viewLev != -1 && viewLev != viewOpts.ViewLevel) {
- viewOpts.ViewLevel = viewLev;
- BuildModel();
- }
- }
-
- private void debugToolStripMenuItem_Click(object sender, EventArgs e)
- {
- debugToolStripMenuItem.Checked = !debugToolStripMenuItem.Checked;
- viewOpts.DebugMode = debugToolStripMenuItem.Checked;
- BuildModel();
- }
-
- private void exitToolStripMenuItem_Click(object sender, EventArgs e)
- {
- this.Close();
- }
-
- private void reloadModelFileToolStripMenuItem_Click(object sender, EventArgs e)
- {
- ReadModels(this.lastModelFileName, this.modelId);
- }
-
- private SourceView sourceView;
- private void ShowSource()
- {
- if (stateList.SelectedItems.Count == 0) return;
- var li = stateList.SelectedItems[0] as ListViewItem;
- if (li != null) {
- var r = ((IState)li.Tag).ShowSource();
- if (r != null) {
- if (sourceView == null) {
- sourceView = new SourceView();
- }
- sourceView.largeFont = largeFontToolStripMenuItem.Checked;
- sourceView.SetSourceLocation(r);
- sourceView.BringToFront();
- }
- }
- }
-
- private void showSourceToolStripMenuItem_Click(object sender, EventArgs e)
- {
- ShowSource();
- }
-
- private void stateList_DoubleClick(object sender, EventArgs e)
- {
- ShowSource();
- }
-
- private void openModelMenuItem_Click(object sender, EventArgs e)
- {
- if (this.openModelFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
- this.ReadModels(this.openModelFileDialog.FileName, 0);
- }
- }
-
- private void largeFontToolStripMenuItem_Click(object sender, EventArgs e)
- {
- largeFontToolStripMenuItem.Checked = !largeFontToolStripMenuItem.Checked;
-
- if (largeFont == null) {
- largeFont = new Font(smallFont.FontFamily, smallFont.Size * 2, smallFont.Unit);
- }
-
- SetFont(largeFontToolStripMenuItem.Checked ? largeFont : smallFont);
- //textBox1.Font = font;
- //linkLabel1.Font = font;
- //label1.Font = font;
- }
-
- public void SetFont(System.Drawing.Font font)
- {
- stateList.Font = font;
- currentStateView.Font = font;
- matchesList.Font = font;
- }
-
- private void Main_Load(object sender, EventArgs e)
- {
-
- }
-
- private void currentStateView_KeyDown(object sender, KeyEventArgs e)
- {
- var node = SelectedNode();
- if (node == null) return;
-
- if (e.KeyCode == Keys.Right && !node.skel.Expanded && node.skel.Expandable) {
- node.skel.Expanded = true;
- SyncCurrentStateView();
- return;
- }
-
- if (e.KeyCode == Keys.Left) {
- if (node.skel.Expanded) {
- node.skel.Expanded = false;
- SyncCurrentStateView();
- return;
- } else {
- var par = node.skel.parent;
- if (par != null && par.parent != null) {
- // par.Expanded = false;
- foreach (DisplayItem it in currentStateView.Items) {
- it.Selected = it.skel == par;
- it.Focused = it.skel == par;
- if (it.Selected) {
- it.EnsureVisible();
- }
- }
- SyncCurrentStateView();
- }
- }
- }
- }
- }
-
- internal class DisplayItem : ListViewItem
- {
- internal SkeletonItem skel;
- internal int stateId;
- internal bool active;
- internal IDisplayNode dispNode;
-
- public bool IsMatchListItem { get; set; }
-
- internal void Set(SkeletonItem s, int id, int prevId)
- {
- if (skel == s && stateId == id)
- return;
- skel = s;
- stateId = id;
-
- dispNode = skel.displayNodes[stateId];
- active = dispNode != null;
-
- var closeStateId = stateId;
-
- if (dispNode == null) {
- while (closeStateId < skel.displayNodes.Length && skel.displayNodes[closeStateId] == null)
- closeStateId++;
- if (closeStateId >= skel.displayNodes.Length) {
- closeStateId = stateId;
- while (closeStateId >= 0 && skel.displayNodes[closeStateId] == null)
- closeStateId--;
- }
- dispNode = skel.displayNodes[closeStateId];
- }
-
- var fullName = skel.LongName(closeStateId);
- var tooltip = dispNode.ToolTip;
- if (tooltip == null)
- tooltip = "";
- if(tooltip.Length > 0 && tooltip[tooltip.Length - 1] != '\n')
- tooltip += "\n";
- tooltip += "Full name: " + fullName;
- if (tooltip != null) {
- this.ToolTipText = tooltip;
- }
-
- var name = dispNode.Name;
- if (name != dispNode.ShortName)
- {
- name = dispNode.ShortName;
- }
-
- if (IsMatchListItem) {
- Util.Assert(active);
- name = fullName;
- }
-
- this.SubItems[0].Text = name;
- this.SubItems[1].Text = active ? dispNode.Value : "";
-
- var prev = "";
-
- if (!IsMatchListItem && prevId >= 0 && skel.displayNodes[prevId] != null) {
- prev = skel.displayNodes[prevId].Value;
- }
-
- this.SubItems[2].Text = prev;
- }
-
- internal DisplayItem()
- : base(new string[] { "", "", "" })
- {
- }
-
- /*
- static internal string AliasesAsString(IDisplayNode dn)
- {
- if (dn == null) return "";
-
- var sb = new StringBuilder();
- var canon = dn.CanonicalValue;
- foreach (var n in dn.Aliases) {
- if (n == canon)
- continue;
- sb.Append(n).Append(", ");
- if (sb.Length > 300)
- break;
- }
- if (sb.Length > 2) sb.Length -= 2;
- return sb.ToString();
- }
- */
- }
-}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+using System.IO;
+using Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ public partial class Main : Form
+ {
+ SkeletonItem unfoldingRoot;
+ SkeletonItem[] allItems;
+ public int CurrentState, PreviousState = -1;
+ IState[] states;
+ internal ILanguageProvider langProvider;
+ public ILanguageSpecificModel LangModel;
+ ToolStripMenuItem[] viewItems;
+ Model currentModel;
+ Model[] allModels;
+ int modelId;
+ string lastModelFileName;
+ internal ViewOptions viewOpts = new ViewOptions();
+ Font smallFont, largeFont;
+ int lineHeight;
+
+ // TODO this should be dynamically loaded
+ IEnumerable<ILanguageProvider> Providers()
+ {
+ yield return BCT.Provider.Instance;
+ yield return Vcc.Provider.Instance;
+ yield return Dafny.Provider.Instance;
+ yield return Base.Provider.Instance;
+ }
+
+ public Main(string[] args, bool runAsHostedWindow = false)
+ {
+ InitializeComponent();
+
+ smallFont = stateList.Font;
+
+ if (runAsHostedWindow) {
+ this.fileToolStripMenuItem.Enabled = false;
+ this.fileToolStripMenuItem.Visible = false;
+ }
+
+ viewItems = new ToolStripMenuItem[] {
+ normalToolStripMenuItem,
+ expertToolStripMenuItem,
+ everythingToolStripMenuItem,
+ includeTheKitchenSinkToolStripMenuItem
+ };
+
+ var debugBreak = false;
+ string filename = null;
+
+ for (int i = 1; i < args.Length; i++) {
+ var arg = args[i];
+ if (arg == "/break" || arg == "-break")
+ debugBreak = true;
+ else
+ filename = arg;
+ }
+
+ if (debugBreak) {
+ System.Diagnostics.Debugger.Launch();
+ }
+
+ if (filename != null) {
+ var idx = filename.IndexOf(':');
+ if (idx > 0) {
+ modelId = int.Parse(filename.Substring(idx + 1));
+ filename = filename.Substring(0, idx);
+ }
+ }
+
+ this.ReadModels(filename, this.modelId);
+ }
+
+ private void SetWindowTitle(string fileName)
+ {
+ if (fileName == null) {
+ this.Text = "Boogie Verification Debugger";
+ } else {
+ this.Text = Path.GetFileName(fileName) + " - Boogie Verification Debugger";
+ }
+ }
+
+ public void ReadModel(string model, int setModelIdTo = 0)
+ {
+ Contract.Requires(model != null);
+
+ using (var rd = new StringReader(model))
+ {
+ allModels = Model.ParseModels(rd).ToArray();
+ }
+
+ AddAndLoadModel(setModelIdTo);
+ }
+
+ public void ReadModels(string modelFileName, int setModelIdTo)
+ {
+ this.lastModelFileName = modelFileName;
+ this.langProvider = Base.Provider.Instance;
+
+ if (!string.IsNullOrWhiteSpace(modelFileName) && File.Exists(modelFileName)) {
+ using (var rd = File.OpenText(modelFileName)) {
+ allModels = Model.ParseModels(rd).ToArray();
+ }
+
+ AddAndLoadModel(setModelIdTo);
+ } else {
+ currentModel = new Model();
+ }
+
+ this.SetWindowTitle(modelFileName);
+ }
+
+ private void AddAndLoadModel(int setModelIdTo)
+ {
+ modelId = setModelIdTo;
+
+ if (modelId >= allModels.Length)
+ modelId = 0;
+
+ currentModel = allModels[modelId];
+ AddModelMenu();
+
+ foreach (var p in Providers())
+ {
+ if (p.IsMyModel(currentModel))
+ {
+ this.langProvider = p;
+ break;
+ }
+ }
+
+ LoadModel(modelId);
+ }
+
+ private void LoadModel(int idx)
+ {
+ var i = 0;
+
+ //var stateIdx = stateList.SelectedIndices.Count == 0 ? 0 : stateList.SelectedIndices[0];
+
+ modelId = idx;
+ foreach (ToolStripMenuItem it in modelsToolStripMenuItem.DropDownItems) {
+ it.Checked = i++ == idx;
+ }
+ currentModel = allModels[idx];
+ BuildModel();
+
+ /*
+ if (stateList.Items.Count <= stateIdx)
+ stateIdx = 0;
+ stateList.Items[stateIdx].Selected = true;
+ */
+ }
+
+ private void AddModelMenu()
+ {
+ modelsToolStripMenuItem.DropDownItems.Clear();
+ var idx = 0;
+ foreach (var m in allModels) {
+ var currIdx = idx++; // this local needs to be in this block
+ var menuItem = modelsToolStripMenuItem.DropDownItems.Add(string.Format("Model #&{0}", currIdx), null, (s, a) => LoadModel(currIdx)) as ToolStripMenuItem;
+ if (currIdx <= 9) {
+ menuItem.ShortcutKeys = Keys.Control | (Keys)(currIdx + Keys.D0);
+ }
+ }
+ }
+
+ private void BuildModel()
+ {
+ stateList.Items.Clear();
+
+ var items = new List<ListViewItem>();
+ LangModel = langProvider.GetLanguageSpecificModel(currentModel, viewOpts);
+ states = LangModel.States.ToArray();
+ var oldRoot = unfoldingRoot;
+ SkeletonItem selectedSkel = null;
+ if (oldRoot != null && SelectedNode() != null) {
+ selectedSkel = SelectedNode().skel;
+ }
+ unfoldingRoot = new SkeletonItem(this, states.Length);
+ allItems = unfoldingRoot.PopulateRoot(states);
+
+ var idx = 0;
+ foreach (var i in states) {
+ var it = new ListViewItem(new string[] { idx.ToString(), i.Name, "" });
+ it.Tag = i;
+ items.Add(it);
+ idx++;
+ }
+ stateList.Items.AddRange(items.ToArray());
+ unfoldingRoot.Expanded = true;
+
+ if (oldRoot == null) {
+ SetState(0);
+ stateList.Items[0].Selected = true;
+ SetColumnSizes();
+ } else {
+ var mapping = new Dictionary<SkeletonItem, SkeletonItem>();
+ unfoldingRoot.SyncWith(mapping, oldRoot);
+ SkeletonItem newIt = null;
+ while (selectedSkel != null) {
+ if (mapping.TryGetValue(selectedSkel, out newIt)) break;
+ selectedSkel = selectedSkel.parent;
+ }
+ if (CurrentState >= stateList.Items.Count)
+ CurrentState = 0;
+ if (PreviousState >= stateList.Items.Count)
+ PreviousState = -1;
+ if (newIt != null) GotoNode(newIt);
+ SyncStateListValues();
+ UpdateMatches(true);
+ }
+ }
+
+ private void SetColumnSizes()
+ {
+ currentStateView.Columns[0].Width = currentStateView.Width - currentStateView.Columns[1].Width - currentStateView.Columns[2].Width - 25;
+ stateList.Columns[1].Width = stateList.Width - stateList.Columns[0].Width - stateList.Columns[2].Width - 25;
+ }
+
+ public void SetState(int id, bool updateView = false)
+ {
+ if (updateView)
+ {
+ stateList.SelectedIndices.Clear();
+ stateList.SelectedIndices.Add(id);
+ }
+ if (CurrentState != id) {
+ PreviousState = CurrentState;
+ CurrentState = id;
+ }
+ UpdateMatches(true);
+ }
+
+ public void HideStateList()
+ {
+ stateList.Hide();
+ splitContainer1.Panel2.Hide();
+ splitContainer1.Panel2Collapsed = true;
+ splitContainer1.SplitterDistance = splitContainer1.Width;
+ }
+
+ public void HideMenuStrip()
+ {
+ menuStrip1.Hide();
+ }
+
+ internal void Activate(TreeNode treeNode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+
+ }
+
+ static Color Col(int c)
+ {
+ return Color.FromArgb(c >> 16, (c >> 8) & 0xff, c & 0xff);
+ }
+
+ static StringFormat center = new StringFormat() { Alignment = StringAlignment.Center };
+ static Pen plusPen = new Pen(Col(0xaaaaaa));
+ static Brush grayedOut = new SolidBrush(Col(0xaaaaaa));
+ static Brush nonPrimary = new SolidBrush(Col(0xeeeeee));
+ static Brush matchBg = new SolidBrush(Col(0xFFFA6F));
+
+ static SolidBrush currentStateBrush = new SolidBrush(Color.Red);
+ static SolidBrush regularStateBrush = new SolidBrush(Color.Black);
+ static SolidBrush previousStateBrush = new SolidBrush(Color.Blue);
+
+ static SolidBrush[] categoryBrushes = new SolidBrush[] {
+ new SolidBrush(Color.Black), // Local
+ new SolidBrush(Color.Black), // PhysField
+ new SolidBrush(Color.Green), // SpecField
+ new SolidBrush(Color.Peru), // MethodologyProperty
+ new SolidBrush(Color.Green), // UserFunction
+ new SolidBrush(Color.Black), // Maplet
+ };
+
+ private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
+ {
+ var item = (DisplayItem)e.Item;
+ var skel = item.skel;
+ var rect = e.Bounds;
+ var listView = (ListView)sender;
+ lineHeight = rect.Height;
+ rect.Y += 1;
+ rect.Height -= 2;
+
+ var textBrush = Brushes.Black;
+ if (listView.SelectedIndices.Count > 0 && listView.SelectedIndices[0] == e.ItemIndex) {
+ e.Graphics.FillRectangle(Brushes.Aquamarine, rect);
+ textBrush = Brushes.White;
+ } else {
+ var bg = Brushes.White;
+ if (item.active && !skel.isPrimary[CurrentState])
+ bg = nonPrimary;
+ if (item.skel.isMatch)
+ bg = matchBg;
+ e.Graphics.FillRectangle(bg, rect);
+ }
+
+ var off = lineHeight * item.skel.level;
+ if (item.IsMatchListItem)
+ off = 0;
+
+ {
+ var plusRect = rect;
+ plusRect.Width = lineHeight;
+ plusRect.X += off;
+ var plusBorder = plusRect;
+ plusBorder.Height = lineHeight / 2;
+ plusBorder.Width = lineHeight / 2;
+ plusBorder.X += lineHeight / 4;
+ plusBorder.Y += lineHeight / 4;
+ e.Graphics.DrawRectangle(plusPen, plusBorder);
+ if (skel.Expandable) {
+ float midX = plusBorder.X + plusBorder.Width / 2;
+ float midY = plusBorder.Y + plusBorder.Height / 2;
+ e.Graphics.DrawLine(plusPen, plusBorder.X + 2, midY, plusBorder.Right - 2, midY);
+ if (!item.skel.expanded)
+ e.Graphics.DrawLine(plusPen, midX, plusBorder.Y + 2, midX, plusBorder.Bottom - 2);
+ }
+ }
+
+ off += lineHeight + 3;
+ var nameRect = rect;
+ var font = listView.Font;
+
+ textBrush = categoryBrushes[(int)item.dispNode.Category];
+
+ if (!item.active)
+ textBrush = grayedOut;
+
+ nameRect.Width = listView.Columns[0].Width - 1 - off;
+ nameRect.X += off;
+ var width = DrawString(e.Graphics, item.SubItems[0].Text, font, textBrush, nameRect);
+
+ textBrush = item.active ? Brushes.Black : grayedOut;
+ nameRect.X += width + 4;
+ nameRect.Width = listView.Columns[0].Width + listView.Columns[1].Width - nameRect.X;
+ width = DrawString(e.Graphics, item.SubItems[1].Text, font, textBrush, nameRect);
+
+ nameRect.X += width + 4;
+ nameRect.Width = listView.Width - nameRect.X;
+ var t = item.SubItems[2].Text;
+ width = DrawString(e.Graphics, t, font, t == item.SubItems[1].Text ? grayedOut : Brushes.Black, nameRect);
+ }
+
+ private int DrawString(Graphics g, string s, Font font, Brush textBrush, Rectangle minRect)
+ {
+ var sz = g.MeasureString(s, font).Width;
+ if (sz > minRect.Width - 2) {
+ minRect.Width = (int)(sz + 20);
+ }
+ g.DrawString(s, font, textBrush, minRect);
+ return minRect.Width;
+ }
+
+ private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
+ {
+ e.DrawBackground();
+ var brush = regularStateBrush;
+ if (e.Header.Index == 1)
+ brush = currentStateBrush;
+ else if (e.Header.Index == 2)
+ brush = previousStateBrush;
+
+ Rectangle r = e.Bounds;
+ r.X += 5;
+ r.Y += 4;
+ DrawString(e.Graphics, e.Header.Text, e.Header.ListView.Font, brush, r);
+ }
+
+ private void listView1_MouseUp(object sender, MouseEventArgs e)
+ {
+ var clickedItem = (DisplayItem)currentStateView.GetItemAt(5, e.Y);
+ if (clickedItem != null) {
+ clickedItem.Selected = true;
+ clickedItem.Focused = true;
+
+ var skel = clickedItem.skel;
+ int plusLoc = skel.level * lineHeight;
+ if (skel.Expandable && e.X >= plusLoc && e.X <= plusLoc + lineHeight) {
+ skel.Expanded = !skel.Expanded;
+ SyncCurrentStateView();
+ }
+ }
+ }
+
+ private void SyncCurrentStateView()
+ {
+ SyncListView(unfoldingRoot.RecChildren, currentStateView, (x, y) => { });
+ }
+
+ private void SyncListView(IEnumerable<SkeletonItem> items, ListView listView, Action<DisplayItem, SkeletonItem> cb)
+ {
+ var ch = items.ToArray();
+ var missing = ch.Length - listView.Items.Count;
+ listView.BeginUpdate();
+ if (missing < 0) {
+ missing = -missing;
+ while (missing-- > 0) {
+ listView.Items.RemoveAt(listView.Items.Count - 1);
+ }
+ } else {
+ while (missing-- > 0) {
+ listView.Items.Add(new DisplayItem());
+ }
+ }
+ for (int i = 0; i < ch.Length; ++i) {
+ var di = (DisplayItem)listView.Items[i];
+ cb(di, ch[i]);
+ di.Set(ch[i], CurrentState, PreviousState);
+ }
+ listView.EndUpdate();
+ listView.Invalidate();
+ }
+
+ private void listView1_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
+ {
+ currentStateView.Invalidate();
+ }
+
+ private void listView1_Resize(object sender, EventArgs e)
+ {
+ SetColumnSizes();
+ currentStateView.Invalidate();
+ }
+
+ private void stateList_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (stateList.SelectedItems.Count == 0) return;
+ var sel = stateList.SelectedItems[0].Index;
+
+ if (PreviousState >= 0)
+ stateList.Items[PreviousState].ForeColor = regularStateBrush.Color;
+
+ SetState(sel);
+ }
+
+ DisplayItem SelectedNode()
+ {
+ if (currentStateView.SelectedItems.Count == 0) return null;
+ return (DisplayItem)currentStateView.SelectedItems[0];
+ }
+
+ private void currentStateView_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ SyncStateListValues();
+ }
+
+ private void SyncStateListValues()
+ {
+ var sel = SelectedNode();
+ if (sel == null) return;
+
+ stateList.BeginUpdate();
+ for (int i = 0; i < sel.skel.displayNodes.Length; ++i) {
+ var dn = sel.skel.displayNodes[i];
+ stateList.Items[i].SubItems[2].Text = dn == null ? "" : dn.Value;
+ }
+ stateList.EndUpdate();
+ }
+
+ private void ExpandParents(SkeletonItem item)
+ {
+ item = item.parent;
+ while (item != null) {
+ item.Expanded = true;
+ item = item.parent;
+ }
+ }
+
+ private void textBox1_TextChanged(object sender, EventArgs e)
+ {
+ UpdateMatches(false);
+ }
+
+ private void UpdateMatches(bool force)
+ {
+ var bad = false;
+ Model.Element eltEq = null;
+ var eltRef = new List<Model.Element>();
+ var words = new List<string>();
+
+ foreach (var w in textBox1.Text.Split(' ')) {
+ if (w == "") continue;
+ if (w.StartsWith("eq:")) {
+ if (eltEq != null) bad = true;
+ else {
+ eltEq = LangModel.FindElement(w.Substring(3));
+ if (eltEq == null) bad = true;
+ }
+ } else if (w.StartsWith("use:")) {
+ var e = LangModel.FindElement(w.Substring(4));
+ if (e == null) bad = true;
+ else eltRef.Add(e);
+ } else {
+ words.Add(w.ToLower());
+ }
+ }
+
+ textBox1.ForeColor = bad ? Color.Red : Color.Black;
+
+ var wordsA = words.ToArray();
+ var refsA = eltRef.ToArray();
+
+ if (eltEq == null && wordsA.Length == 0 && refsA.Length == 0)
+ bad = true;
+
+ var changed = true; // force;
+ var matches = new List<SkeletonItem>();
+
+ foreach (var s in allItems) {
+ var newMatch = false;
+ if (s.isPrimary[CurrentState] && !bad) {
+ newMatch = s.MatchesWords(wordsA, refsA, eltEq, CurrentState);
+ }
+ if (newMatch)
+ matches.Add(s);
+ if (s.isMatch != newMatch) {
+ changed = true;
+ s.isMatch = newMatch;
+ }
+ }
+
+ if (PreviousState >= 0)
+ stateList.Items[PreviousState].ForeColor = previousStateBrush.Color;
+ stateList.Items[CurrentState].ForeColor = currentStateBrush.Color;
+
+ if (changed) {
+ SyncListView(matches, matchesList, (di, _) => { di.IsMatchListItem = true; });
+ SyncCurrentStateView();
+ }
+ }
+
+ private void matchesList_Resize(object sender, EventArgs e)
+ {
+ matchesList.Invalidate();
+ }
+
+ private void matchesList_DoubleClick(object sender, EventArgs e)
+ {
+ if (matchesList.SelectedItems.Count == 0) return;
+ var sel = (DisplayItem)matchesList.SelectedItems[0];
+ GotoNode(sel.skel);
+ }
+
+ private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+ {
+ foreach (DisplayItem it in matchesList.Items) {
+ ExpandParents(it.skel);
+ }
+ SyncCurrentStateView();
+ }
+
+ private void SetSearch(string text)
+ {
+ textBox1.Text = text;
+ }
+
+ private void GotoNode(SkeletonItem skel)
+ {
+ ExpandParents(skel);
+ SyncCurrentStateView();
+ foreach (DisplayItem it in currentStateView.Items) {
+ if (it.skel == skel) {
+ it.Selected = true;
+ currentStateView.EnsureVisible(it.Index);
+ break;
+ }
+ }
+ }
+
+ private IEnumerable<SkeletonItem> NamesFor(Model.Element elt)
+ {
+ var words = new string[0];
+ var elts = new Model.Element[0];
+
+ foreach (var s in allItems) {
+ if (s.isPrimary[CurrentState] && s.MatchesWords(words, elts, elt, CurrentState)) {
+ yield return s;
+ }
+ }
+ }
+
+ private void AddMenuItems(IEnumerable<SkeletonItem> skels, ToolStripItemCollection items, string pref, int max)
+ {
+ var skelsM = skels.Take(max).ToArray();
+
+ foreach (var s in skelsM) {
+ var tmp = s;
+ items.Add(pref + s.LongName(CurrentState), null, (x, _) => GotoNode(tmp));
+ }
+
+ if (skelsM.Length == max)
+ items.Add(new ToolStripMenuItem("...") { Enabled = false });
+ }
+
+ private void stateViewMenu_Opening(object sender, CancelEventArgs e)
+ {
+ IDisplayNode sel = null;
+ SkeletonItem skel = null;
+ if (SelectedNode() != null) {
+ sel = SelectedNode().dispNode;
+ skel = SelectedNode().skel;
+ }
+
+ var items = stateViewMenu.Items;
+ items.Clear();
+
+ if (sel == null) {
+ items.Add(new ToolStripMenuItem("Unavailable") { Enabled = false });
+ return;
+ }
+
+ foreach (var x in sel.References.Where(q => q != sel.Element)) {
+ var t = new ToolStripMenuItem(LangModel.CanonicalName(x));
+ items.Add(t);
+ AddMenuItems(NamesFor(x), t.DropDownItems, "= ", 20);
+ }
+
+ if (sel.Element != null) {
+ var selName = LangModel.CanonicalName(sel.Element);
+ items.Add("Find uses...", null, (s, _) => SetSearch("use:" + selName));
+
+ var aliases = NamesFor(sel.Element).Where(s => s != skel).ToArray();
+ if (aliases.Length > 0) {
+ items.Add("Aliases...", null, (s, _) => SetSearch("eq:" + selName));
+ AddMenuItems(aliases, items, " = ", 10);
+ }
+ }
+ }
+
+ private void normalToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ int viewLev = -1;
+ for (int i = 0; i < viewItems.Length; ++i) {
+ if (viewItems[i] == sender) {
+ viewLev = i;
+ viewItems[i].Checked = true;
+ } else {
+ viewItems[i].Checked = false;
+ }
+ }
+ if (viewLev != -1 && viewLev != viewOpts.ViewLevel) {
+ viewOpts.ViewLevel = viewLev;
+ BuildModel();
+ }
+ }
+
+ private void debugToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ debugToolStripMenuItem.Checked = !debugToolStripMenuItem.Checked;
+ viewOpts.DebugMode = debugToolStripMenuItem.Checked;
+ BuildModel();
+ }
+
+ private void exitToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void reloadModelFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ReadModels(this.lastModelFileName, this.modelId);
+ }
+
+ private SourceView sourceView;
+ private void ShowSource()
+ {
+ if (stateList.SelectedItems.Count == 0) return;
+ var li = stateList.SelectedItems[0] as ListViewItem;
+ if (li != null) {
+ var r = ((IState)li.Tag).ShowSource();
+ if (r != null) {
+ if (sourceView == null) {
+ sourceView = new SourceView();
+ }
+ sourceView.largeFont = largeFontToolStripMenuItem.Checked;
+ sourceView.SetSourceLocation(r);
+ sourceView.BringToFront();
+ }
+ }
+ }
+
+ private void showSourceToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ShowSource();
+ }
+
+ private void stateList_DoubleClick(object sender, EventArgs e)
+ {
+ ShowSource();
+ }
+
+ private void openModelMenuItem_Click(object sender, EventArgs e)
+ {
+ if (this.openModelFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
+ this.ReadModels(this.openModelFileDialog.FileName, 0);
+ }
+ }
+
+ private void largeFontToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ largeFontToolStripMenuItem.Checked = !largeFontToolStripMenuItem.Checked;
+
+ if (largeFont == null) {
+ largeFont = new Font(smallFont.FontFamily, smallFont.Size * 2, smallFont.Unit);
+ }
+
+ SetFont(largeFontToolStripMenuItem.Checked ? largeFont : smallFont);
+ //textBox1.Font = font;
+ //linkLabel1.Font = font;
+ //label1.Font = font;
+ }
+
+ public void SetFont(System.Drawing.Font font)
+ {
+ stateList.Font = font;
+ currentStateView.Font = font;
+ matchesList.Font = font;
+ }
+
+ private void Main_Load(object sender, EventArgs e)
+ {
+
+ }
+
+ private void currentStateView_KeyDown(object sender, KeyEventArgs e)
+ {
+ var node = SelectedNode();
+ if (node == null) return;
+
+ if (e.KeyCode == Keys.Right && !node.skel.Expanded && node.skel.Expandable) {
+ node.skel.Expanded = true;
+ SyncCurrentStateView();
+ return;
+ }
+
+ if (e.KeyCode == Keys.Left) {
+ if (node.skel.Expanded) {
+ node.skel.Expanded = false;
+ SyncCurrentStateView();
+ return;
+ } else {
+ var par = node.skel.parent;
+ if (par != null && par.parent != null) {
+ // par.Expanded = false;
+ foreach (DisplayItem it in currentStateView.Items) {
+ it.Selected = it.skel == par;
+ it.Focused = it.skel == par;
+ if (it.Selected) {
+ it.EnsureVisible();
+ }
+ }
+ SyncCurrentStateView();
+ }
+ }
+ }
+ }
+ }
+
+ internal class DisplayItem : ListViewItem
+ {
+ internal SkeletonItem skel;
+ internal int stateId;
+ internal bool active;
+ internal IDisplayNode dispNode;
+
+ public bool IsMatchListItem { get; set; }
+
+ internal void Set(SkeletonItem s, int id, int prevId)
+ {
+ if (skel == s && stateId == id)
+ return;
+ skel = s;
+ stateId = id;
+
+ dispNode = skel.displayNodes[stateId];
+ active = dispNode != null;
+
+ var closeStateId = stateId;
+
+ if (dispNode == null) {
+ while (closeStateId < skel.displayNodes.Length && skel.displayNodes[closeStateId] == null)
+ closeStateId++;
+ if (closeStateId >= skel.displayNodes.Length) {
+ closeStateId = stateId;
+ while (closeStateId >= 0 && skel.displayNodes[closeStateId] == null)
+ closeStateId--;
+ }
+ dispNode = skel.displayNodes[closeStateId];
+ }
+
+ var fullName = skel.LongName(closeStateId);
+ var tooltip = dispNode.ToolTip;
+ if (tooltip == null)
+ tooltip = "";
+ if(tooltip.Length > 0 && tooltip[tooltip.Length - 1] != '\n')
+ tooltip += "\n";
+ tooltip += "Full name: " + fullName;
+ if (tooltip != null) {
+ this.ToolTipText = tooltip;
+ }
+
+ var name = dispNode.Name;
+ if (name != dispNode.ShortName)
+ {
+ name = dispNode.ShortName;
+ }
+
+ if (IsMatchListItem) {
+ Util.Assert(active);
+ name = fullName;
+ }
+
+ this.SubItems[0].Text = name;
+ this.SubItems[1].Text = active ? dispNode.Value : "";
+
+ var prev = "";
+
+ if (!IsMatchListItem && prevId >= 0 && skel.displayNodes[prevId] != null) {
+ prev = skel.displayNodes[prevId].Value;
+ }
+
+ this.SubItems[2].Text = prev;
+ }
+
+ internal DisplayItem()
+ : base(new string[] { "", "", "" })
+ {
+ }
+
+ /*
+ static internal string AliasesAsString(IDisplayNode dn)
+ {
+ if (dn == null) return "";
+
+ var sb = new StringBuilder();
+ var canon = dn.CanonicalValue;
+ foreach (var n in dn.Aliases) {
+ if (n == canon)
+ continue;
+ sb.Append(n).Append(", ");
+ if (sb.Length > 300)
+ break;
+ }
+ if (sb.Length > 2) sb.Length -= 2;
+ return sb.ToString();
+ }
+ */
+ }
+}
diff --git a/Source/ModelViewer/Main.resx b/Source/ModelViewer/Main.resx
index 657b80c4..764a9fd9 100644
--- a/Source/ModelViewer/Main.resx
+++ b/Source/ModelViewer/Main.resx
@@ -1,2192 +1,2192 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
- <!--
- Microsoft ResX Schema
-
- Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
- associated with the data types.
-
- Example:
-
- ... ado.net/XML headers & schema ...
- <resheader name="resmimetype">text/microsoft-resx</resheader>
- <resheader name="version">2.0</resheader>
- <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
- <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
- <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
- <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
- <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
- <value>[base64 mime encoded serialized .NET Framework object]</value>
- </data>
- <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
- <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
- <comment>This is a comment</comment>
- </data>
-
- There are any number of "resheader" rows that contain simple
- name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
- mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
- extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
- read any of the formats listed below.
-
- mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
- : using a System.ComponentModel.TypeConverter
- : and then encoded with base64 encoding.
- -->
- <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
- <xsd:element name="root" msdata:IsDataSet="true">
- <xsd:complexType>
- <xsd:choice maxOccurs="unbounded">
- <xsd:element name="metadata">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" />
- </xsd:sequence>
- <xsd:attribute name="name" use="required" type="xsd:string" />
- <xsd:attribute name="type" type="xsd:string" />
- <xsd:attribute name="mimetype" type="xsd:string" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="assembly">
- <xsd:complexType>
- <xsd:attribute name="alias" type="xsd:string" />
- <xsd:attribute name="name" type="xsd:string" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="data">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
- <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
- <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="resheader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" />
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>
- <resheader name="resmimetype">
- <value>text/microsoft-resx</value>
- </resheader>
- <resheader name="version">
- <value>2.0</value>
- </resheader>
- <resheader name="reader">
- <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <resheader name="writer">
- <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <metadata name="stateViewMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
- <value>17, 17</value>
- </metadata>
- <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
- <value>267, 17</value>
- </metadata>
- <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
- <value>152, 17</value>
- </metadata>
- <metadata name="openModelFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
- <value>422, 17</value>
- </metadata>
- <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
- <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
- <value>
- AAABAAoAICAQAAEABADoAgAApgAAABAQEAABAAQAKAEAAI4DAAAwMAAAAQAIAKgOAAC2BAAAICAAAAEA
- CACoCAAAXhMAABAQAAABAAgAaAUAAAYcAAAAAAAAAQAgABx9AABuIQAAgIAAAAEAIAAoCAEAip4AADAw
- AAABACAAqCUAALKmAQAgIAAAAQAgAKgQAABazAEAEBAAAAEAIABoBAAAAt0BACgAAAAgAAAAQAAAAAEA
- BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDA
- wAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAAAAB3AAAAAAAAAAAAAAAAAAB6KiAAAAAAAAAA
- AAAAAAAHKqKnAAAAAAAAAAAAAAAAeioqKllwAAAAAAAAAAAHcqKqKiopGQAAAAdwAAAAACqioqKqI5mQ
- AAB1AAAAAAoqKqJyoqIVlQAAkAAAAACqKiohEaKiOZmZmQAAAAAAOiqiB5EyqiEZcAAAAAAAAAcAAAWR
- kqKjmZAAAAkAAAAFcAABkZE6KlmQAACQAAAAAJcACZGVGioplwAJcAAAAAAJlxWZGZGioZmZlwAAAAAA
- AAAJkZGVOqKQAAAAAAAAAAAAAZWZGZIqMAAAcAAAAAB3AAmZkZkZKqAACQAAAAAACXAHWZWZWZKnAJcA
- AAAAAACXB5mZmZmTKhFwAAAAAAAACZlxmVmZk3ogAAAAAAAAAAAACZmZkVAHpwAAAAAAAAAAAAeZmZmQ
- AKoAAAAAAAAAAAAHl3mJcAACcAAAAAAAAAAAAAAAcAAAAKAAAAAAAAAAAAAJAHAAAAByAAAAAAAAAAAA
- dwAJAAAACnAAAAAAAAAAAJAAA3AAAACgAAAAAAAAAAdwAACQAAAABwAAAAAAAAB5AAAACQAAAAcAAAAA
- AABxkAAAAAeTcAAAcAAAAAAAAAAAAAAAB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAD/z////wf///4D///8AH//4AA/n/AAHz/gAA9/wAAA/8CAB//vgAfv54AH3/OAA5/4AAA//4AH//+A
- B9/zgAe/+YADP/yAAH/+AAH//+AY///gHP//4B5///9/f//7fz//87+f//ef3//n3+//z+/v/x/h9///
- +f///////////ygAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA
- AAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAHAAAA
- AAAAB6IgAAAAAAAiqiOQAHAAAqozKhl5AAADd3EyOQAAAABweZKhcAAAAAdRmaKXAAAAAAkZGnAAAAAI
- CVmTKHAAAAAJmZdzAAAAAACZkAYAAAAAAAAAADAAAAAAcIAAAAAAAAcABwAAAAAAcAAAdwAAAAAAAAAA
- AAD7////4f///8B3//+AD///gD///9Af///gD///+B///+gH///4D////G/////3///9f///+7////fP
- ////////KAAAADAAAABgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEZjkACGk/AAR1
- OQAJIm8ABjlkAAgvdgAJOX0ABFtIAAVBVgAKWlMABVBYAAR4QQAGYVwABnJWADN5XQAJSXwACFt3AFJn
- XwBFX3UATVt2AAGQHQABnxgAAK0NAAC9BQAAtwoABrQLAA22DQAAvgkAALgMAAC8DQAKugoACr0KAA29
- DQABphIAAasaAB6oHgABtRMAE7QTABSwFAATuhMAGrYaABm9GQACiCQAA4AtAAKdIwADmy4ABIo4ACyf
- LAA3jTcAOJk4AAKnJQAgpCAAKaEpACa1JgArsCsAKbspADGtMQA4rDgAPao9ADezNwA7ujsAAMICAADG
- AAAAwQQABcEFAAXFBQAKwgoAFcAVAAWGSQBGlUYAUZNRAFiTWABKpkoATKdMAE25TQBXpFcAU7tTAFu1
- WwBmk2YAapRqAGqeagB5mHkAVKFkAG6nbgBsu2wACBuAAAoAkwAKCZYAChSSAAsYlgAaEJ8ACCSAAAsm
- nAAoO4gAODKVAAwHowALAKYACwCpAAwBqAAMBqgADACtAAsOqQAXDaMADACwAAwAtAAMDLEADQC5AA0A
- vQARBbcAFAm1AA0XuwAfFLkAHBC9ACUdpAALM6EANC2hADcvpQA3L64APzilAD84qAAuJbYALyS9ADQq
- vAAmObYAOjKyAEI7sABFPbYAC0SeADxJowA2RawALkG/ADRGuwBHQo4ARUCWAEtGkgBNSZMASUSZAFNO
- nwBSWpQAVlKYAF5amgBhXpsAWXGGAF9mmwBkZZMAb22WAGVimwBta50Ab3OUAHNxmQB2dJsAcHWcAHt5
- mgB/fZwAR0GnAExGpABOSKEATEWsAEdTogBIVKYATFepAFdSogBOW7QASVe7AFpUtgBcVrQAW1W8AGJc
- uwBWYrYAbmugAGllqgBqcqcAfXuiAG5pvgBwbLEAcGu8AGpztQByerMAeHi3AHx5ugANAMEADgDFAA4A
- yQAOBcoADgDNABIFwwAXC8MAGQ3AABEEywAfE8MAHRHIAB8SzgAOANEADwDVAA8A2QAPANwADwvaABAD
- 0gAXCdIAEADeABcJ3gAdD9oAAx/WAAAd2gAfE9QAJxzDACIXyAAjF9sAKh3YAA0kxAAMJcwAFCvDABgu
- wwAdNMsABiLVAA8p0gAEINoALiPHAC0iygA5L8cAIzjHACE3yQA/NcwAMSXTADcs1AAPAOAADwHqABAA
- 4QAWB+EAEADmABMF5QAUBeQAFgjhABwN4gAYCeUAEADrABgI6gARAPEAIRPiAEY+xQBEO8sAMEPEAFZO
- xgBSScsAWFHEAGBY0QBzbsAAcmzLAG15ygB9eMIAdYOdAHuBrwB+hbQAeILHAP///wAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQ/P0JHAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQj8/Pz8/UAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEo/Pz8/Pz8/IQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAOT8/Pz8/Pz8/PzEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp
- Pz8/Pz8/Pz8/Pz8EurhwjAAAAAAAAAAAAAAAAAAApQAAAAAAAAAAAAAAAHQAACA/Pz8/Pz8/Pz8/Pz8V
- Y7fBwr4AAAAAAAAAAAAAAJnKAAAAAAAAAAAAAAAAAAAKPz8/Pz8/Pz8/Pz8/Pz8/C7W5wsTHAAAAAAAA
- AAAAluewAAAAAAAAAAAAAAAAAEw/Pz8/Pz8/Pz8gPz8/Pz8/F1i5wsPIwAAAAAAAAACa598AAAAAAAAA
- AAAAAAAAOz8/Pz8/Pz8/PyYUDD8/Pz8/PwJsxsPI5n4AAAAAAADJ0QAAAAAAAAAAAAAAAAA3Pz8/Pz8/
- Pz8/GhJbYC0/Pz8/Pz5WwcLI5ONyeXZ4eMDrAAAAAAAAAAAAAAAAAE4/Pz8/Pz8/Pz8dXFdoaFodPz8/
- Pz8rbcLI5ObGze3s7O8AAAAAAAAAAAAAAAAAAABCPz8/Pz8/PyGPjmdpaGgHPz8/Pz8/BcbE5OPrAAAA
- AAAAAAAAAAAAAAAAAAAAAAD7D0k8KkI/NgAAAG1raWlpDT8/Pz8/ImTE5ObsAAAAAAAAAAAAAKL6AAAA
- AAAAAAAAepMAAAAAAAAAAGxsa2trbS8/Pz8/PwjB5ObspgAAAAAAAAAAfeAAAAAAAAAAAAAAAMaNAAAA
- AAAAk7ZsbGtsbGojPz8/P0JZ4ubs3AAAAAAAAAB77QAAAAAAAAAAAAAAAK/BlAAAAAAAnba1tbVsbLVd
- HD8/Pz8suObu0AAAAAAAAH7uAAAAAAAAAAAAAAAAAAB/vQAAAAAAdbe2trW2tba2ED8/Pz8/Bufj6wAA
- AAAAou6uAAAAAAAAAAAAAAAAAAAAzruHiIZfbrm3t7a2tra3tw4/Pz8/Fmzs7uju7uvr7vEAAAAAAAAA
- AAAAAAAAAAAAAM/Gwca6usG5ube3t7e5ub0uPz8/Pwvm7bT49vT0+AAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAnsLBwbm5ubm5wcZvJT8/Px5m7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq8LCxsHBwcHG
- wsLDc0I/Pz8DewAAAAAAAACXpwAAAAAAAAAAAAAAAADbAAAAAAAAAMTDwsLCxsLCwsPEyBE/Pz9CEwAA
- AAAAAJzvAAAAAAAAAAAAAAAAAAAA56oAAAAAAMjExMPCwsLDw8TI5ORFPz8/JAAAAAAAfe4AAAAAAAAA
- AAAAAAAAAAAAqOOqAAAAANrkyMjExMPExMjk5ObFMz8/P1AAAAB97gAAAAAAAAAAAAAAAAAAAAAAAPDm
- rQAAAKvk5OTIyMjI5OTk5ubs0h4/PxsAAJvu9wAAAAAAAAAAAAAAAAAAAAAAAADg6Y2Sk4nm5ubk5OTk
- 5Obm5uzu7oA/Pz8Cx+7zAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Ozs7Ozi5ubm5ubm5ubm7Ozu7uFTPz9A
- XvoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Ozm5uzm7Ozs7OPu7QAAPT8/MAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAALxit+zs7O7stWFsAAAAACo/P1IAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAIVst+Tu7u7kZWy/AAAAAABCPycAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG95Onu
- 7u7jvbnkAAAAAAAAPz9IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKfm8QCzALQAAOr1AAAAAAAA
- TT8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChAAAAAAAAAAAAADg/MgAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAACEAAAAAAAAAAAAAABDPwAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAmIMAAAD81AAAAAAAAAAAAAAAPyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1P0A
- AAAA16AAAAAAAAAAAAAAVT9PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQ1wAAAAAAo8wAAAAAAAAA
- AAAAAD0bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTqQAAAAAAANnVAAAAAAAAAAAAAABERgAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAIHXAAAAAAAAALLMggAAAAAAAAAAAAAAQwAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAlcyxAAAAAAAAAACEzJ8AAAAAAAAAAAAAADUAAAAAAAAAAAAAAAAAAAAAAAAAAACV190AAAAA
- AAAAAAAA3syBAAAAAAAAAAAAAEtSAAAAAAAAAAAAAAAAAAAAAACsy9LM2AAAAAAAAAAAAAAAAN7M1IuR
- kAAAAAAAAAA6AAAAAAAAAAAAAAAAAAAAAAAA1tnyAAAAAAAAAAAAAAAAAACkzMzMzAAAAAAAAAAAUQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP75AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAD///////8AAP/8H////wAA//AP////AAD/4A////8AAP/AB////wAA/4AAP/9/
- AAD7AAAf/P8AAPwAAA/4/wAA+AAAB/H/AADwAAAD8/8AAOAAAAAH/wAAwAAAAA//AADgAAAB//8AAOAc
- AAH/nwAA8/wAAP8/AAD5+AAA/n8AAPj4AAD8/wAA/PgAAPj/AAD+AAAAAf8AAP8AAAAD/wAA//gAAP//
- AAD/+AAA/n8AAP38AAD8/wAA/nwAAPn/AAD+PAAAc/8AAP8cAABj/wAA/4AAAAf/AAD/wAAAD/8AAP//
- AAYf/wAA//+ADw//AAD//4APj/8AAP//gA/H/wAA//+Kz8f/AAD///9/4/8AAP//93/z/wAA///nP/n/
- AAD//+ef+P8AAP//z5/8/wAA///Pz/5/AAD//5/H/38AAP//H+P/vwAA//4/8f+fAAD/8H/4H98AAP/4
- //wf7wAA/////z//AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN1NAAZH3oACSZ/AAg9eAArMXwALTx9AARrQgAFd0kABmFVAAZI
- YAAHTG0ACF9uAC5UZQABmRsABrkGAAC/BAAAswsAAbcPAAC6CAAAvwkACbwJAAOlFwABrREAAa4VAAGj
- GwAdqR0AFr8WABm0GQActhwAApAmAAKeJwA1njUAAqogABaqJwAjpyMAJaYlACWzJQAjvCMANa01ADi8
- OAAAwwIAAMYAAADBBQAEwgQAAMgAAASKQwBEm0QAU5lTAE6/TgBUqVQAappqAHufewBesWQAZqJmAGin
- aABpvmkAdaB1AHquegAKH5cACiaKAAo1lgA1LpgADACuAAwKrwAMF60ADQCxAA0AtgANALoADQW4AA0A
- vAAiGqMAKB+pAA0jvwAvJ6QANCyjAC09qwA3MKEANSy+ACE1vQALR5oAPkqgADVFsgBUUJsAU12fAF9k
- lABlYZ8AaWacAGxpmwByd5oAU0yvAEpDsgBJQbQAUku9AFNMvwBJVrEAUl+3AGFppQBua6AAcm+mAGhw
- pgB2dKAAdXKkAHZ0pQB5d6EAf32jAHt4pQBkbrQAc269AHZysgB7d7YAfHm0AA0AwQAOAMYADgDKAA4A
- zQAOBswAEAPBABcJzgAYC8kAHRDNAA8A0QAPANUADwzTAA8A2AAPAN0AFAfRABAA1gATBdQAEADaABMF
- 2gAQAN0AAh7ZAB8S3AAmG8MAIhbPACYayQAmGs8AKR3JACAT1QAjFtQAJBjSACYZ2QAoHNsAByLPABUs
- wwARKs8ABSHVAAgk1gAxJ8IANizCADAlzAAnPMIAPTTAACwh0wAzKdIANivRABAA4QAUBeMAEADlABoM
- 4QAQAOkAFATpABEA7QAXCOgAEQDwAEE2zgBUTMYATl7JAFxWxQBaaMUAaGLDAHx3wgCAfbMAg3/EAHGB
- hgB7gKMAf4a5AFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/kbIA/7HIAP/R
- 3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/cdEA/5HcAP+x
- 5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0Uf8A9nH/APeR
- /wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCmMf8AtFH/AMJx
- /wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+Ef8AWDH/AHFR
- /wCMcf8AppH/AL+x/wDa0f8A////AAAAAAAAAAAAAAA2OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAA6Ki0tJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMi0tLS0tMwAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAACctLS0tLS0VBUpTAAAAAAAAAAAAAAAAAAAAAAAAZ68dLS0tLS0tLS0BcHl2AAAAAAAAAGVeAAAA
- AAAAAAAAEy0tLS0tLC0tLSoDeXyCAAAAAABojgAAAAAAAAAAACwtLS0qKhoGGC0tLQ5Gep2IAAAAAKAA
- AAAAAAAAAAAqKioqLS0ZAj88Ky0tLQp6g59+pKOkAAAAAAAAAAAAACIqKioqJQA+Q0ILLS0tEUCDn5kA
- AAAAAAAAAAAAAAAAAFUAAAAAAEhEQ0MILS0tB3yfogAAAAAAAJYAAAAAAAAAXFYAAAAAdXVGRkUfLS0p
- O5+lAAAAAACLAAAAAAAAAAAAhmkAAABycXB1cEESLS0efKNqAAAAiqwAAAAAAAAAAAAAd01LR3NycXFx
- cz0qLS0Eo56loqKnAAAAAAAAAAAAAAAAAAAAenlzc3NzeQwtLRd0AAAAAAAAAAAAAAAAAAAAAAAAAACA
- f3l5eXp6fC4tLQkAAAAAAFoAAAAAAAAAAABdZgAAAE6BfH9/f4GDeyEtEAAAAACJAAAAAAAAAAAAAACa
- YwAAbZ2Dg4ODg52fSRQtIAAAjK4AAAAAAAAAAAAAAACFYgBXn52dnZ2dn6OjUCoqDYerAAAAAAAAAAAA
- AAAAAACbj5yXoZ+fn5+ho6WmNS0WAAAAAAAAAAAAAAAAAAAAAAAAAACVcJ+jo59GeAAAKC0zAAAAAAAA
- AAAAAAAAAAAAAAAAAFhxgaWlekZbAAAAGxUAAAAAAAAAAAAAAAAAAAAAAAAAb4NuqamtjWwAAAAAKi8A
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAAAAAAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAXwAAAAAA
- AAAxJAAAAAAAAAAAAAAAAAAAAAAAALBrAAAATwAAAAAAAAAmNAAAAAAAAAAAAAAAAAAAAAAAkQAAAACY
- YQAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAFRgAAAAAACTAAAAAAAAAAAwAAAAAAAAAAAAAAAAAABZkgAA
- AAAAAACTAAAAAAAAADgAAAAAAAAAAAAAAABfkJQAAAAAAAAAALGETFEAAAAAADcAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAACqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/z////wf///4D///8AH//4AA/n/AAHz/gAA9/wAAA/8CA
- B//vgAfv54AH3/OAA5/4AAA//4AH//+AB9/zgAe/+YADP/yAAH/+AAH//+AY///gHP//4B5///9/f//7
- fz//87+f//ef3//n3+//z+/v/x/h9///+f///////////ygAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAABHw/AAZYXQAGY1sAEUJxAAC8BgANug0AAq0cAByvHAANiiwAAp4iAASN
- OQAjoS0AJbglADeoNwAAxgAAAMgAAADACAA4wjgAPZNSAEasRgBYtlgAX7hfAEWJZQBgl3cAZMdlAGzE
- bAALK54ADQC2AA0BvgAMErIADCWzAC8lvQAzKbgACkqUAFhTpwBXUa0AVE2/AEdVswBSYL8AamasAHp+
- oQB2dakAcnmsAH57rgBnYbsAcHizAHt4swAOAMAADQ3AAA4AygAPANUADwDdABAC0QAVB9oAEADeACke
- xQA2K80ANivVABAA4AAQAOUAEQDpAFZOxwBQR80AfHTkAIB9rwCCfc4AeoG1AHiBvAB2gckAAM9AAADw
- SgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvP
- AAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEyw
- AABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQ
- AACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBb
- AACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAi
- AABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8D
- AABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAA
- AAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP//
- /wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R
- 8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx
- /wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R
- /wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx
- /wCmkf8Av7H/ANrR/wD///8AAAAAAAAOAAAAAAAAAAAAAAAAABYPEAgAAAAAAAAAAAAAAAwPDw8QAjUA
- AABBAAAAAA0PDwkEDwUeNiMkAAAAAAAXFRoqHAMQATsAAAAAAAAAACwAKDAdCw8bJQAAAAAAAAAALSEy
- MjEHCjlAAAAAAAAAAAAAMzMzHxEYAAAAAAAAAAAvADs3NzwiBilCAAAAAAAAAAA+ND00PxkTAAAAAAAA
- AAAAADg6IAAAEgAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAALgBEAAAAAAAAAAAAAAAAKwAAACYAAAAA
- AAAAAAAARQAAAAAAJ0MAAAAAAAAAAAAAAAAAAAAAAAAAAPv/AADh/wAAwHcAAIAPAACAPwAA0B8AAOAP
- AAD4HwAA6AcAAPgPAAD8bwAA//cAAP1/AAD7vwAA988AAP//AACJUE5HDQoaCgAAAA1JSERSAAABAAAA
- AQAIBgAAAFxyqGYAAHzjSURBVHja7F0HgBPV1v4mfbPZvuwCIkXFhr377A1siGJBUECaIgpYAQEFUWkq
- IlhApAkWREFQsfvs79fnsyv6LA87vWxJT+Y/ZyY3mWTTN9nNLjl6SXaSzNy5c8936j1XQp7ylKfdlqTm
- 7kCe8pSn5qM8AOQpT7sx5QEgT3najSkPAHnK025MeQDIU552Y8oDQJ7y1LJJwmEw4id4UQdZc1xO7sd5
- ylOeWipJ6AIbzkAZluBPggDB9DLyAJCnPLVqklAEE8YR+z+MD/AXnHTMH2h5AMhTnlo1GaDHZPTGj9iK
- pfgYKsMz83sRAoGElAeAPOWp5ZEO5+EIXIL+uJ5goF5hdh81NzUP8hpAnvLUaomdfu0wE49jIibhE/wK
- VeIz87MZIDSAJE+WpzzlqaWQhGJYyOZfiN/wCybg0cBxlvp2qADAmkBS0l89YZ7ylKeWQnpMJ6X/MAwn
- 5f9SbFGYniV+faCxFpC09GfKA0Ce8tQySEcsfwZGY4Wi/C/B21CZnUGghpoDKhgkLf2Z8gCQpzzlPkk4
- FXuRxf8KNmEzBpMWYFdUfVb5d1GrpeZCitJfPXGe8pSnXCYJbWDDQ1iGPdEDYzAIH+BnqAzPzL8Tqvqf
- ku0fOnme8pTbJEW8j2yC5IiGKK8tjSRifQPuxV1k999CjP8cxmEusTqr+qz2b4cKAq507zEPAHnKNZI0
- r9x0gaY/x4IOexhx3IkmHLK/BfsagAr6QiE1Hem+Oz3A5u0+/L3Ojh93+fDRaw58t8UfDItpk2NaCiDo
- MAC9MZwsfhcp/UPp3c/YBlXib4UKAEL6N2qw85Sn5iYt4ysMb5FgOdWCrv1s6He0Bb0MErpIKcxZv4xa
- ux8fv2LHywtr8dzPXmyWVWYRtnIuA4EO3XEgbsc60gE64Ak8iHl4hXrMdj+DwGao0l8k/qRFeQBoSJES
- SDLRwyjSoYBmZQE4FKMOuI/+cezyw+FpmH+dyxMr10iMt5D0hrY6lFxuwxm9bRjUTo+TJAmmxl6k3o9v
- R21Gv3fd+C9Ub3laNnOTjUkXVOMRrEQZTsQGfEuyfzJZ++zs20FtI1QQYM9/yo6/8AvliamB9Kkkhj/A
- gE6nWXFUZwOOP8KM/Sw6dKYvKJORZo7bLePXjx34kiTL68vq8K8/fcrDEepm4Gt5ikMCZBlUDUUSrCTt
- zxhShJvLDTgaGZ6fP3uwrt8mDNrmVyRnSjnzTTomZbDgAczE/rieeunGDHr/Ij6FavdvggoAtUgj7Nfw
- Yrs3aZ1JerIpDWRY7tG7EGedYcVF7Q04lj4okhKMkixDrpfx+Zo6LF1MquavPmxBHgjikda+Z+Y3nkAA
- e2MpxhxqRm+Jl7pkgUhl29V3E875zI2voTrOGs1AGScd3fto9MdlpPCz5vMxPsA4PEqynpmf1f6/oEr/
- tMJ+kbQ7A4B2EhqMgHlUMS66shgTC3XYKxVbUxABgX+bD5/M2IlJrznwgUMOZmYlvTijlZNW01IYv1iC
- bUQxLu9bhFutOnTI9oS8ewcuWVKLf0JNoEk5cy7LpEMfHEcA8CK9K0cdaSq3kvz/HD9BZfo/oWoAdVDB
- q9G0uwMAMz+r9OajTOi6qAqrLRL2UD5sxMh4Zex4xY7779iOR+vk4MPa3f0DWlufJbxxXz3a31aGcScU
- oJ9OgrkpOjFhO/quqFMAgFVosYY+F0hCB7L7l+J1FOJgmiUyVuMl3IfnqIcc62fJzwDAnn8GrozMo90Z
- AHgikuBXJl7hxFIMGlCEe8SHjQEAJtIG3B86sHTcNkzcJIfZnMrHzX3zTUxh2hY18ykWHDSlDPeRmXUM
- jbWuKTpBwGy/cjP6ferCf6Am0LATLe0QWkbHp5rsfjXZ52LlyEb8jeuI/f+kV9Xm/x2q9Ldnss+7MwCw
- CqowP7Wie8sxo1chLhEfNhYAmAgEfN+4sGbcdoz6r1eJ2+6OIKB19BmJ+y1DbTjnmlJMt5HMy8Q4J0tf
- u/DvAZsxulZWpCk7bBsVQ88g6XEvbsaJmEojpace+fAInsKTeIc+Y38SMz/3mUGrUWG/SNqdAYAlEYf1
- iqmV3V+B+3pa0UN8mKmJSU9K/t2N14ZtwaBffMEHuLuAgJb5TTTgBXeWYdDFNkwySArwNhk5/agn9f/u
- NXa8ATWJJlcAQIfhOA/9ieH1sClHvsd/cS1BgENx+v0BFQAYCBod9ouk3RkAWP3nAS+lVjmzAndeaMU5
- 4sNMSibm8p9dWH3pJgypQ3AJZy6GoDJJgvkVe58QoHBuJW4+qwC3pKvyk0bFg+bf7kftejf+/t6DHbt8
- cPAgFupg7mKAra0eRXsYUF5Gr/rA/N7ow8YHduKJF+x4CyojsUONwZifRXP6AHQ4EvuQov8aGQCdld66
- SUDcSMbAf/AdVKnPBT/YDOAoQMZzF3ZnAGDnXxG1CmptBtlw4W1luEV8mA3V9J92PHLdVkzwqEieUumm
- FkZae99EKlbJA20w5WQLrqJxTXlk/TJkZvp19fjmLQfWf+zCH96GyTzatGGpXAfTPkYUkY3n/tSN7wkl
- mPFZ8gvmb24nICf7VGA2VpD9f7pyhO/kdfwLk/AMVHufmZ+l//ZAXzM+V3Z3AGD1nwGgqoMe+z/XFlNp
- 4lQqAxNlZGQ1j9THIUKaZbpUQYImsufpOoyasgNP+sPj0K0JBMKYv0xC+exKTP2HBX1TZX4e7x1+1K2u
- x6dP1OLjP31BDzg3H2IDgNAweHzFenl2xO4IvNYgFAZsjrHnyj5mzMI0dMNoiHGpRR0G4gGS+8z4v0EF
- ABH2y4qpsjsDAJsAQQ2AWvVlheg+vgwDrBKszNw+GX6egP/zYNv3pHJ+5cbWGj8cegn6NmSvHWdBhyNN
- 6ETvEyYLCSJbdNuYbbj8FQchvToBRTy3NYBAmKe/UELZgxWYckoBrkxV7Xf54XnPifVzd+Ht7zyKHSxK
- Xrk045YMAPBv2NZniV8XeLWjOROBjDQ+16Iv/cfJPlblGPdiPl7CErwJ1e7/H9SwH4NWRh1/WtqdAYAn
- qfABMAhU0oEqYupDzrfiGGJ0z79d+PtHDzZu8Coqo3ZFmZjkhk4GVFxhwxGX2HA4rxdI5sJbvfhi5FZc
- SarpL1Afbi7npSdLYZKfmX9aOcafY8UQYv6kM/tY6m/2YSfZ7K+tteMzd0haMxM7A00LAEKF1yHkcBQA
- wJ+7Ar/hczgCjY81lwmmwwU4FmOwikalbfDoBpL7QwkC6hTJz8zPr1uQZT/F7gwAPFGYYVkLKNM0BgT2
- UHOIUJRbjjbZlIlOzcLtBDP2nlSOc7sYFW0iLnHq8OcurBq2BdfXyGGRgZYKAlqHn5k0qOK7ynFTTyuu
- 16WwkIeZn8bl50k7sHq9R1F/hdTmJhhYqwEIUNamdGs1AH9gbD2a34m/m2O8JeyHdrgPz9MsOS541Etz
- azyW4z0lP2FDoLEDsAZZ1lJ2ZwDgScJMzioYg0BxoPF7BgZj4HtexAYAc+C7DBi2joTo91fgwsPM6Jzo
- 4n4Z7uW1uG3aTiz0htdza2kgoGV+Ew2IbVwZBvWz4Q4ylSzJnoTGw/9CPf5v6k6s2+lXwl88+WsDjaW/
- 1gQQWpOWibUAIOa12CxDC+KRv2u6caqiufIQqf17on8Y572HrzEBz9BdsdRnrZAdf9vQBE7K3RkAxKTl
- SWoNNGZkZmhz4LNEGoAAEDYlSqgVtdOj7b0EAsda0DVRB+x+/HXLNvR9w6Egv5BqLQkAwuL8NCiFQ224
- 4IZS3E9/FCd7ErcMz5ydeGVxLd5xharc1ASaVvoLCa4No2oBQNsnoGH6dWTFoKYbJ/aBTMZIdCf5Lynj
- pVId3dv1WIzv8S1U1X8D1My/jOX7x+/Y7ktCWrCkV9YDBJopcCy47h/hkkP8VqQRCzOCAYDNh5IOerSf
- 1wZX7GdS1xXEIlZ5//Di3cs3YcBmv2LvaRcP5TppJS6PmfUsC06YVYkFBbrEZpCgOj/sd+/AqtX1+Nin
- Orx2BprQAITdLhhf6y9pCeMEZYyG4h8YjFfonS3sk2fwAebgRXrqG6ACAEt/HocmiVDszgAg7l8faErC
- CkJOJG6x9lsLqrwImQAMAEFfwl4GdHq8CgMJDCriRQjYH7CyDpNu34G5/paVHxBM7+UxOMKEfRdX4flC
- Hdone4J6Yv7btuHJdQ58BnXSCwDQMn+kyo8WMDbh47QfCYLHiNHN6BT2yZ+k5o/AImxSipQI6c/mT0bz
- /eN3bvemyEIgWvtRkGB8f8TvIs0A1gJYAyiHGlUoP9aM/R+uxIASffy0V6+M7ddsRs/3XPgKubpOveG4
- Ce2poI0OlS+2xcpKAw5N9gQ1ftRP3Ibl61TzhxmfVX9mflb/Wf0VKn80db+lkIS2JCAex3M0I84Jm1k+
- uqd78RJeUPL9NyAU9tuJJnz+uzsApEuRS1tZE1AWFUHVADiZSAGBfjacMKEMF5kShMK+dOHlqzZjaF3u
- RwWE6s/Mb6EbLyaQm3KaFVcle4JdPtRN2oGnXrLjE6jML7LzBPOLUF9LlfrqOJlojO7AJJyBsWF2P9MX
- xPA34QmS9cz47PhjByBnKmY83z9+J/PUGNJWtRErC9n5xVqAAgL0YeW0clx6UaGy7DXmeHMxkQd2Ysij
- tViNUFQgV9aqa+9XqP7sPC28vgiXjirFLF2SsX5m/snE/C/alS2tWeprmb8eITNI2PotjfFV0tN/N+Bi
- +m8xzRBr2Gd20vJuwwoagX8jpPpnLd8/HuUBoPGkBQERURCmADvDKst0aPdUNYbvbcAe8fwBZBP/fMZf
- OGubGgZjUyDXEoQE8ytmz8kWHDG3EkvJ7q9O5sd2PxwTt2P5Wjv+Dyrjbw80nvha5m+pKr8gHU4hc2gy
- nicDoEvYJ3xHb5Cpdyeeoae7ASHHH49DRsp8pUJ5AMgMaX0CDALaDEMFBI4xo9vjbXB1gS5+5Zvn6jD1
- tu24D6ojKJccglq739pOh/ZLq/B4F5NSNzEheWX4pu3As0vrlFRXnuxiSa6Q/E60DuaX0I0s/5nE4BU4
- ucGn28nEuR5LSOn/BiHpn9V8//idzVOmSMsgDAJKnQEEFhtRqxxahDPHlKFXvEF3+bHtqs04m1ewIXcc
- gmF2v0VCCZk1Y863YrgUadtGIY50LKjBK/ftwmp/aEWeiPdHMn+umT2pjZOVZP4M+u8ojEDk+gc/Pcel
- eBfz8TJCjj/O+2cTqFkWJuUBILMUFhdHyB/AWkAbYpy2i9tg6FEW7BvrBMwsnzjx9JVbMAqhLZ+bWyJq
- /Ry23lZ0v7sCD5kkxemZkN4ge/+mbVjqkBVJJ3a0EXvatRbm56duINt+CM7GbETLgvwdW+jTBWTw8N5+
- zPyc7izCfs1y73kAyDyJcKJwCnJ+ADsEGQSqDjPhwCeqcC2ZAjHTZN0yaq/dgovecypOorS2fc4gaUGt
- cE89Oi2vxuI9DDg4mR+vd+N/gzbjoa3+4OIWwfzC2986mJ/H6EIch1uxlqCyosGnLP0nYiXexkcISX/O
- 9xf1Ipvl+eYBIPOkzY0X/gARGqwiTqq6sQTnDy8hORGDOEPwUxdW9tuM66AySnNlCGpV/wJCgJL7KpQV
- fsOSWdu/1Ysdw7ZgztcerEeoEs8OhOL8rYX5JRxOdv99eIUgP3ouxL/xE+l0S+kJstQX+f6sDTVrZeI8
- AGSHovkDhEOwqlSHDqwFHGBCx1gn8MioIS3g0nedSrisucKCwRV+1IrOKcCJD1RikUGKSGeNQg4/HGO2
- Y+ErdqXugajGw8xfg9bG/CYan2fxDKrRKypHueheh+Jx/KhsSLIBoXx/znZs1khPHgCyRwIEIk0Bdgi2
- 6VGAY2dV4iqyo42xTvCFC2sHbsZwuxx0EjWlFhCm+pdKqF5ehfn7m3FCoh9yIZWHd+GFuTVYI6vML1R/
- bSWe1sH8RlL4p+NmGpXpUb/BT2sFqf0PkmkgK2q/cPxltL5/+jeQp2ySNj+ApaZwCFaZJWXp8IDuBTgy
- Vm4AMVLdrdsw4EU7WY5NrwWIsGYBda94RBH63VCGaYl2TGIn5ntOfD5qK+bXy0pyi1D9Raxfm9/Q3NGN
- xo/RKJyLvngOsTY2+ZsYfTBJ/x0k/5sp3z8e5QEgu6S1oTkqwFpA0BTY34j9FrXBiDYGJWcgKn3sxOrB
- m3GdW3UWiUSRbDOOVnuxtdOj05q2eLpcj70T/fA3D/4evAUPbPAq21lpK/DWoXXVQdThJHTFXXhVqegb
- jTjffyZewpoG+f6N3tY7U5QHgOxTcL08IhyC1NrcWoKLhhajhy6GU81D6v/wLehLUpVtae1qwWz2Nwha
- 9KZkShlG9S3CjYl+6PTDPXYb5r/swAcIt/uF06+1lENXK/rOJcu/AqfF5KL/4BfcguV05+z0a7Z8//g3
- kqemIG2WoMgNUACApGuXZVUY2cmoqQ8XQe858NSILbjZFdICsilBtbn+RfsYsM/adlhjkhTgikms+r9k
- x/u3bMPjPjWzjQFA6/RrSbUO4o9PEWlGd2MajsFIxEqE4nz/W/AUPlOWOgvVn8N+ze74C7+ZPDUFRSYI
- KZuRIGAK9LfhzPFluMwQYzK5/Nh65Sb0+sKjVI0RG4tkYwIJ6R/s5/xK3HWGFf0S/fBPDzb224xpf/oU
- SSdUf5HpJ1b25cSkbxSZ6BndRlZ9D8xusMhHS2vwKan/qzT5/iz9Rb5/zoxDHgCajsIkKzQOwQIJ7VZW
- 48b9TBEFIzS0ohYzb9+B+2RVgmRrW2tt/kLRP8w4fGEVVhql+NWOvTK8123BrLfUkGWk6t+6nH7n4liM
- w/MEBO1ifmszAd9ILMWvwTJfHPvnsF8ubEUWRnkAaDqK5hAMagG9rDhpegWuiqUF1Pjxv7P/Qs8takad
- 2NU2kwyllf7KYqZHK3DnmST9E+15sKIOr03cjqWy6t3Wqv4i0681ML+EI9GeFP/VZMQdHfNbnPE3D2/i
- CbyGcMdfVuv7p39TeWpK0joERfEQBQDIPqh+vho3dTNh7xi7EskP7cKNc2qwHKpk1W4ymqm+Bf0UB5qw
- 79NVWFWoix2hYNrsw6aef2PytlCqr1D9tfH+nJr0aY2NjUB7Lh7D/mQOxeIavssfyc7nIp9qvr9w/GW9
- vn/6N5anpqZgai1CYUF2CFYdTyr34iqM1sfYRedXN97vuQn9HbLCZMKTnCnmEj4KRfpPL8etFxfGT/nl
- Ut43bcOcl+x4D6r0Z9Vfu8inNdj9HOHXYwqx9cmYhXgp0JzxNx7P4kPFFNqAJqzvn/7N5ampSesQFGFB
- RQvg9mglhpHafWS0H/LeggM3o8f/ufAFVCbLlEopNBNlu/ROBuy9ohpPVepjVzXm9QpvOvDR6K14xK3a
- tyLbTxTzbD3x/gHojuFY2aCib9iAUHuXbP7b8FQg3184/hism7zQR7KUB4DmIaFuKwwHjRZwiBHdniRT
- wBKjcMiL9XiEpO4UqFIlUxNLrFvglOWykcW4alQJxsfbz2+TF5sJjKb/5MUPCDn+IlN9WzrzSzgRnTAd
- /6Sn1TnuN2sI9K7FIlL8YxX6yMmxyANA81BYnj3CVwu2nVqOKy624aRoP3T48ceJf+LUGjloVzZ2com+
- sO1fUiSh7TPVWLCfCUfE+gF7/adsx6Kn6hVHl1D9o3n9WzJx5kMRluA5VOOsuN/kO+WNvR7GSwgv9NFk
- 9f3Tv8k8NReFOd2g2aV4XyP2JxX8Jpsuejnx8dvQd2U93kBmnIHCJ8HXKj3DglMfaoOHjFLsGPe7Dnw6
- civm2mXFvtUu9Gktqr9Eo2HA/bgHh+IWJFr6zPn+AzCfjJ9ohT5yKuzX8Ebz1FykDbspzAdNRGB8KS4d
- WBxd8nzgwPJBWzAWqrddONvS7YPQRIrpTcWcCkw6uxCXxfrBNh+2D9uC+75yK0tbeZKLXP/WpPrrcSv6
- 4kJian2cZB8E7nQKVuEVvI/wjL+cyfePR3kAaF7SJgdpU4SruxjQlVTxm8r1SqQgjOr8+PuMv3DKdn9Q
- yqTrYRbXV7L+6Jr70jUXVeixZ7Qvs9f/kRqsfHAXnpNDqj9L/8iFPi2ZdOiFw3ET1sKcxC5HXN9/JBkK
- nuBSX+H4y5l8/3iUB4DmJW1ykNAC2BdQLamVgy68tgTnR/6IGNE3dhuuesGu2OCNyQwUGoiSmdjPhgvu
- LMOMWM6/b9z4YeBmzNzlV+xbBgCt6t8aEn54G6/2eJDs/hIcl5A7OOx3PZaSLsRRGW19/5zK949/w3lq
- btLW2tdqAVVt9eiyvAqjIxcKcQjuQyeeIDNgPFT1O10zQGgfJQYCnkcqMe10K86N9kWu6T+CVP8PXEqd
- QuH1FzH/1qD6SzTyFjyAR7EvWfRJlDzDCzQWM7Ga7lxIf219/xYxFnkAaH6KTBEWWoACApcX4vTJ5eir
- j0gR3urD793/wum1ssKIzISpqt/CCcnXLO9kwH6rqrGwRN9Q7SWNQ15aizX37MRTaKj6O9O4du6Rhcbi
- HtyIf2AqktnlaAvZ+EPwOI0Gb+zJGX8bAmOTc/n+8SgPALlBWi0gbKGQTUL7BW0w/CgL9tf+wCvDMWor
- rnzDoTifWA1PNdwk1H8lAnGFDT0JaGZEVvxhbeNHD36+fBPuqQl5/UWFn1zbvCQ9YpPncpxJtjwn+xQn
- /D7n+8/GK3gWb6Hhxp457/gLv/U85QJpKwlrFwopNQNOs+CoBysxTFtKnGfYEzWYefdOslhVj3OqTieh
- /peS6lH1UCXuPiOK+u/ywzVkC6b/n0tZ1x5N9W8Rtm4cknAKuuJOrEEEyMakb0jVvxFPkKXPVY9E2I/H
- pkU4/sJvPk+5QmFluKBJESZUqJ5TicFnFuAo7UKh/7rx8QUb0denSuRUkoKExsGOx/IqPfZa1xaLSvXh
- VYpZ+i+Jrvqzk6s1qP4S2pHJ9SCepDs/J6lfOEnC306awvvK/oYboAIAO/4YhFscGOYBILdIu1AoLDmo
- mxH7L63CaLLRg/nodX5sGbAZF37tVtJxmSmTVT/D1P/uBTj54Uo8Gun9J4D5pe8mTNslK15/7Uq/yE08
- WyKxV8WAubgDh2NCUk4/vtO38DWmkPLvDm7r/XtgXJwtcSzyAJBbFLlQSOsQbHNHGS690oazxAo9vwz3
- mG24fo0dLyK8aGgi4msoqxHpRG0mleGGK2y4SqtdOP1wXLMF93/owqcIT/iJrOzbUkmHIeiNoaTKJyh4
- EiTe2PNGLCO4/QqhsB8vhGqWjT0zQXkAyD2KlSJcVaVD+9XtMI5U9krx5TftWHLtVpJioWy8RBNRm/xT
- Xihhj7VtMa+jAQcJAGDVfzGp/jN24pmI+n6Rqn9LBQAdzid7fxzeppFOamtzxfG3BO/iMaxDC8v3j0d5
- AMg9ipYiLCoHVQy04dQJZRgotICfPPj6so24tFbdeDOZcKAwMzjaUNHVgANfaodnSSUwCgBY78ZPgzbj
- vq3+oHOrdan+e6AE80lrqsCJSXPABtKCeLVfqL4/Z/y1iHz/+IORp1ykWPUDK4lzS9a0xbiuJuzDXyRV
- fdvAzej3mRufI7lwoHA0KpGG4cW48pZSjGWpzwDg8MM+fAtmBVR/rddf7FHYklV/ieDUiNmYhf2IneMs
- dw4jL93zVKwh2d8i8/3jD0iecpHibShSeooF+z/WBhN1EvTEuP5J2zH66XqsQigrMJ4fIJj7zxuVLm6D
- qScUoLusTmF5QQ1W3bsLK6PU92sNm3roMZos/8sxJ+ZOPpHEd/oZfsb1ZACEF/po9o09M0F5AMhd0q7T
- 124oUk4HrQ9UYtA5VnTnL71px7Jrt+J2qCG6eCqp8C8o25SRjdH2kw54zqZDWwaAr9z4dsgW3L/Tr0g3
- nuCtR/VnaX8VTsZQPE8wUJ7071wEelfjcfygrH7UOv7YH+Jt7ttq/LDkKZcpuD8fQg5BboWdDWjzbDWm
- lulR9ZMHX/bbhL47/EGPdCw/gPAtsEZRfqwZhzxZjRX8Qa0fNSO3YOYHLsXDLZi/9aj+h6Az7scLZFAd
- ktIvV+ETpb5/uOOvReX7xx+YPDUlSZpXRcITZxv2gK5Sp0plFsT1O+HfuiVkW0Y6BFl6FdNB09VFOPPm
- UoyiL+7oQwDwjVtZlRbPDyA0CuU8w4twxS1lGMfLfJfU4umpO7ESKtMz87cWr7+EjnS/s7AAHXBxSr/c
- TvffH/NoNCI39mxR+f7xBydPTUVBpqdmIH2+YCDMJ5wNU99jYTjeAIlX/Pn9kLf+Ct/nq+Fe/ghcb2+C
- XB/4nVgnwKYAS3BLiQ7WZVW4Y38Tjpy6HdctqSMJFyoSEs02Fdl/DABlz1RhxpFm9FjvwVcDNuMuUv2Z
- 6blpt/IWzK/0f09IlnLoyugPPV2gnvq6c1fDjT9yBSh4+24TJmEszsAdMbfxikYy/TcL6wgSeWdmwfwt
- Mt8//gDlqSlIMD5PQGM36KpnwXr70TBeRh9YZc2XxBfp1fUVPM+Pgn38f+DfjJD0ZlOAAYAdefoeBTh4
- ViVmvGHHyhu2KfkAoia/L0ofhP1fSipF2ccd8DJ1qOC6LRj3vkvJJmSw2YlQToHC/HRh/Ukw7H0tLJcd
- Cv2pbaFrT8cMBAA16+H972p4nn0CrnUEVtpS4M3PIHr671r0Rj8sRozyajHpG/ymOP6cSrafcPy1yHz/
- eJQHgOxTUOpTM3WGVPkkbA/uC8P5/sD4C/GKwBcFUlDz/wzfq5ehdvh/IW9HSIKzJsAAYCRG1hMAjDrA
- iK6Xb8IVW/xBFTXSD6At/lF8qgUHzW+D50j1f2TaTjwH1Wxge1+7n59EaodpAiz9hsEyzgKpQyyw+hbe
- Ndeg/rYv4f8ToV2AgeYDAh1OxQG4i6S4MXyNQ0Jyk4S/BU+T9c+hULHWXxT6aOnrH8IoDwDZJe0qPzP9
- Y1sA63hS+0cQd+gixaTKUJJgftF8r8H9yEDUT7arqieHBlmKs2OQGVp3kBHtHm6DKYM2Y/QvXqUwZbQy
- YcKMYACxXVOEvj0LcVafTRhbLysmAzu16hAq78VkWoiCWy+A+QaZsCBy1mvBil7lrfD/uw/qBvwbvl8D
- 128ux6GEvVGOOViLCvwj5V+/ii9xDyn/4WW+hOOv1Uh/daDylE0SzK/stnsq9Ic9gSK20608i/xRvhxi
- fLUqBTfioB19UdvrVXi/DnyVTQHWAMzE0eYTYdjjhkLdUNllcLX1GkxWSFVG1Vkors2M6KHrOe2QN22h
- VlnoOeRtj//lF9y+9z+Cj6U2gwBLfod6SRhHw3zuWBTMZ0XArxjF4X3VBTJpRJ/pYvLX8L5wEequ3gxZ
- W7G4KUFAHcZleAj74JqUZ/gOAsDrsJQUf67vz+q/2Nizxeb7x6M8AGSXxMIeJYw3G9Y7esE0mGdRJAAI
- dVowlMr8kiLu+f1yuGdfh/qZ9Na7J3RFvWA8+wIYTyFT4qhSSO3oOyZ2zCWzqE0lhaG9pOe7tpGl8X/w
- vv8KPC+9CM+XNZDltpBKX0PxmnJI+wox7tf0VevU0IIVHXNOhH3QXLheRih5qKmkptq1sWT1X0j2eypO
- PwRu8nG8jUWkA8iK048BQOT7txrHn5byAJBdCm61Ta30UxQ/XwTpAAEAwgSIZCiDhqGMARDYBP9n98Ix
- 91KYehwFYw86aamERPv2RqdoP2I4oBnu3w7/hlXwvLwT/trBMI/xQzJo+yp+H+GrCAOr7+B7pztq+tSF
- FyxtCubRoT+OwXBi4CjVlBPSzyTp2fEXyvfX1vdvVaq/oDwAZI/C6vzRH5XfoOQjmkVGLQAI0jKTMQAA
- RoQAgL7rJxtbshHTFyrHkn90UoLPVOkuK5xaT6+7Aj0z06c+eh9pyMeS/qKvdK6N56D2on/D9x3CNwvJ
- 7ngfiHZKqa7iFJN9mNzUx7uwGm/gQ4SSfkS+f6ty/GkpDwDZI23svrwDdB1fhu11b4CptACgGq1SUPVX
- JanKTCalqYr9n/Qr0iCUZk6qgkX8zmnJS71hTq2lV9ICSG1R+xPNXImw+4N9FQBAxx3nofbyj+BlZhL1
- A7LJQBIqle27H0VnXJny0HDPPsT3GI+nAoU+tPX9W3y+fzzKA0D2iMdWZN1Vct79ByheRzPJEGkUR6r+
- gplMgffM7Kyi/0athN5zs6QBAPG+76Fzs/TfCS4z7CchqhomkRqAcP4ZILSVkMYiwIree3uidsAH8L6D
- +IlJmRlnM11yHG7B2bgzgEGpUQ2p+DdhOb7Bl2iF+f7xKA8A2SNRdSe45dca2OaXQdeZGUq4k7Wef60U
- NQUAQDCVE1yXy49yZUWrjsRd7EeX7EPVfs9F51elP+86qmoaOoRrAFrbPxystP1lzUF29kTdENIAePms
- qCKUHQAw0OUGogcGEwPrlSzJ1IiRdSX+D7OULMoNgcZlvnagleT7x6M8AGSPBAAEi3uOgWVkDxjP02oA
- qvQPOdC0jCQAgDWAjfQLts0rlE1rVQBI5+HF+o0rYPtvo+tspVd1BZIUdOELZ6XIaNLa/OH9ldgHsJM0
- gGGfwseJNGLX4GyE0HT4Bw7A3XieBmS/tM6wkfo3FI/TTXN9f63jr9Xk+8ejPABkj7QagLLd16HQHz0V
- 1sl+NY02KP0F42uZyRxgKHPge+tpLrLaX0GnLVWK2CUHAIm+I5yAWgDYAjUzqExjAojvRjNTQn1WX3+E
- 99tzUTu8Rs2dF4uKMs1MEval4bgXy1BNyn86xJ7P+/EywQfn+29AqL5/iy/0kSzlASB7JHwAophHNTF7
- +9EwDz4BptN4ZgXzg6EykxkhiW/WMNff4HW+MqEI716lC/gAkn14UhJHQgCwPQAAWxVzQ6d814eIfGYN
- WJk1kj/Qf//9cD48E87lUCVpNjQAvpgZMzAVx2J00pV9Imk9WVW81t8TZP5Wme8fj/IAkD0K23gTqhnQ
- zgZ0vgUFV+8HfVetyq+V+Op7laF20Dz8kXinhOZ4pWL/q1EAU4omgBTjL6EBuAM+gB0BH8BmasyxJYoW
- IIWBVaR5IiQ/v/4G/08Xo3b835A5iUZUFMqsD4AX+UxAP5xDzKt2JXXyUX9G4Qn8h/4Lr+/f6vL941Ee
- ALJHIg2Yc+9ZC2AA4CW/7btAd+gNsAxuB53FEsFAWsm/RWF+1SNfoUh/SXlvzVAegBYGRBRANQNkBQC2
- BMKB1qCXP7yvWgDgVwIRx1DUzXgfvo+gVhPmwiLp7FoUj3TE+IfhdlLbdWkk+wh6HV9hEp4JlPkS9f05
- 379F1vdPl/IAkF2KLO/dbm/oDh8M8830vg3b022ptaGZrK7sUVVrZsTfiV9q6LU8oPYL5rcFGE4f49Gl
- 6xdgac8zX+QBbA2YAQwGnMlUCR0sGmaPBAI2mL+C1/8+PK8shnuOM7Rhhigqkgmm4so+VXiImN+EA9M+
- Sy3suAqPkbX/PUL5/gxYrTLfPx7lASB7pK3pp5TgPhT6I8fAMo2U9/Y7iblqA8k3cuBL/APWPfXKD1R1
- vzQQ9itRmB8KExoD6n8m8gDEMRbPbkULgAI8OwIOwW2B93pqbakfFUoEQgUBQ+D3HKH4kz4vUjUV3//B
- 8/T9cM6sDcXSRTpw48bTQv89Qf/tiUvSnrk82PPxFpbgNSC41l8U+mix9f3TpTwAZIfEuCrLgKkVHwF9
- t9koXGiAvCer2Vxup45e7WoOvuKQlgLqvyUg6YsD9j6rD4UBz7+aadf4CEDkZxwOZ/DhwLcwBXYFmH+H
- 0l8Gq1B4UE35VTmGb7AsoKmUqYlK3n/CvWAcHPfUqWp1Y9cDSMr23XfhVpyIKSkv8tHSLwRK12Ix3dxP
- CEl/9lW02nz/eJQHgOyQdouvgr0gdVwO2+PV0B3JDM96Zn3A5nYGcvBFWJAZiwGgMNhUhhNMZ0hT+ms7
- Fu1vWUlPVn0BzoAmUBcAgZqAg1DdC1wORgVEX22B7ETRipT+wr0Qrjsmw/GYO7xASTogoCOmPQ/98SS9
- K0r7qXio65zv/zo+wG6U7x+P8gCQedJGzCxku7d5EoUPHAnDeSTpJWcgxu4MSFSWuCENIBRbtwSYnk0D
- oW6ny/yJnYBMstIDX0ATcAYYXgBVXeCYO9BXBPrK/SsMML0tAFrCRKBBqL0Xjuumw/mCV/UDpFMujCv7
- HITb8TydfJ9GPZkP8QMm4OlAmS9uu0W+fzzKA0BmSVsByELSu/gRWMeeD9O1dFjvC6j7nsCrG6rdLdJt
- RWKQNsNO5NnrUmD+ZJJ/Gv6tAgBzpgABdwCsHEHQUhcN+RDKYGT136pKfOVVOAmNgdChC/LffVFzyWvw
- fYHUy4tLZO9X4CFi2iqc2ajZWku3cRNpEF8rOyiJfH8O+4ky6rsl5QEgcyT4k3lYKb01CubLJ6JgKklu
- qxB7fg3DqzWz5Aa59mJloC7YQjZ/plT/hsdClQm1/VSBKgRYkWAVmQUozBSdZkD+hu+T81Db53v4NyF5
- fwCrFRbcg5k4WtnGK327n6/0DD7CXKylK2+ACgC7Tb5/PMoDQOZIyxPW7jAc+TgKl9ig49h/g5rZapNj
- 6sNSlpg+2vEQ24c+EX3yBQFLvEphYCVME7E6UDgodZqzsV7xGbzLT0DtSITqA8QHASOdaiwGkOX/SMDS
- SJ/+IDWfC31sVCofC8ffbpPvH492ZwCIXhgn/XPxnFcKgFRBarsKtvkHQH9iNKaKdpFYF25Mh1I7JseM
- LQig0vZH0pgkWi1F2yLO75sFx5CJcPIuO4n2GdShO47HHXiBkKUSjSHO+HsA6/BcWL4/O/5aVX3/dKm1
- AkDk/OPaWToTb4FNbX/ozIdAX1oInZUkm/IdssudZOO6SCzJ/4G37nfIyuTgSjySKq189F6mN35PuMNI
- iE7F7qd/imeh4IYrYL6RLytHfBEp/J3oeKKbT3Q80gTQAoAU5XvRj0kNviPF+J0T8tbeqDnnHfjWQwWB
- aP4ACcehA6YT01pwUIq33nDgviKmH63U99cW+uAMxd0m3z8etTYA0M45xZwuJYl8AYwHHwPj+efCeEQh
- pG6kplYjwPhxyMEbX1DbQWrwTmL6GrKFa/+Cv+YT+LY6aDLTZztpFv+9E/7tr8OzbTtd81QYDpuHwnmk
- FgfDVZkAgUwNTLS/tSaAFPc7scBAivl5ODDI+Am+109GzYAdoRV34cWRSlCIpViOtujV6Jt2wI2b8STZ
- H58h3PHHaRgtea/DjFFrAoCw2ppkj5p6w3jUrbDcthf0pwOpOZESpdqEbGTVM14P2b0D8pZKSIUl0JVq
- v5PseyRxPNUBSXQ8lgmQPPMjqAMkAwJkTHgehnPMGDgWIXzfQXad6jEbt+FwTGn0zfMZX8HndKZngeC2
- 3iLfv9XV90+XWgsAaD3wRiup4jfD3HckCqbokMJW0GEnTAwA3LyBEFltIEuuivAnHcZPxPDJAEIqmX+R
- x6Q4GkAyYJAMCIj3O+D/tSdqL/oMPi7CIZhRwkCch+FkradT1iuCdNtgNw7CYt9mrPeqjr8NQNjuyckO
- a6um1gAAWuY3EcNb7oK5/zBYpxErpu09jgcAgvl9mkq6nOHXjphfrNKLxuzJMH2mZ2QyzsBoJkDyTJ8c
- CEQck1+E67GBqL/DKTzxZ6AbJuEFmMj+zwCdNNPgPGyVfksppNpi6LYUQ/qVtI8vVsH9r/Xw//A7/AwE
- 2nqnuyUYtHQACGN+agWDYDpvKqxzjOoKvEacOD4A8KzxBLL5apUVc2ouvPg82mvk+3jH4h1PZlCSOR7L
- CZhI5Y//GjpHPCBwQd5xPeqvqYHsOtVmPGz6fEffLXvJ+2diRlZ/K2HQcDM6efToTM9kT6WWgrrikk5f
- +yf83zwF1+OL4Fr1p7r7stYfsFsBQUsGANH3IPNfQDb/g7AuLIK0R+NPHiskFpL+6mZ6qvTvqEnXSUbi
- N4X0jxyoWMcyqwHEdgpGvt8G/8YaA0ruu95RsOQyF/zp1fUJIx2pZJeONuGozw3oRM+EG69iLFZyFUL9
- 4l2RfoZ33TWou+lj+Hn3H22t1t0GBFo6AIhiugUHQbfXU7AtbA9d6ptCRD15bAAQ0l+smitVnNe6hBK/
- qU2A5NV/9crRnICR6cfJ2PiJTAHxN/tP5lzgxJSbHXCbM3PPB76kx8VTTehMaMLSvwNNkXKE9lHQ3gtn
- N2yC/4uhqO3/Dvw/oXk3NG0WaqkAIJ6lsm6mQllwY5t1FPTnZeqeogGAVvqLTTS4lt6eCaR/Y0J/qczE
- VJyAqYQBkwGBZPwB2u/x1T7Z34s+99diS0Vm+K1gO9B/mBkH/qmq/h2J+auhLlCKtYRaVkoC+T85H7X9
- NoS2Nt9tQKAlAkDYghtCgKLZKLjpMphvABIXh3QCbnrgW7fAX7cdfmedGotmJNHTRDHQSSWy54303kSm
- hIXzCOhvM0kQpfacWj9PcfxJuwIVe4oVH3r8jL/GgUD8uZgoYpGY+dWrxNIAkn2NBwLhoUDgzwo/LiXm
- /3o/X2ZmIZ305DkGnPW0UVH7OxPL7xGooJyogAqNr/xf+F7phdphf0DmMGFz7GrcLNTSAEDr9DPTG9sQ
- mC6aCut9OnUPvpjEWXxr4f7qdjje/gsyJ4LE2rVWO1eCa1ro5MZq6ApoQjEgWAuAkmNh6DICloP0cTL+
- Uon/J2L01AdLivgbMf8WYUDt8cYzf3R/QL1JxnUT6vF8D3fG7rX6OwlXjjJjrzqV+dkno5Zak8LWJcQi
- nh8fwb2gD+rG7wyFCls9CLQkANA6/Zj5rX1gPO0BFM4zIuGOMPJb8H47DPXP16jMzzMvFsprtVWd5lU0
- xedAb2zLUdj7dJj2TsX2byj5G86vxsy46Ha/FPd78ZyAjWP+hqaARyfj4cucmDzKkRGnH5PeBVww0YTj
- 3jcEpL9OCckWaaR/MuSH7J4Jx63T4VzqDd/UtNWCQEsBAC3zKwtuToX+4KWwLSNVPWHceD18v1+BusW/
- QeY0UK5zwbk7DADRc9HDmT+YXRhonFtgOxr6fZ9G0WC6vpJrkBoIZJbpEw1a+DEpxueJw4CpgkCkKcD3
- /fqxHlw1vQ72ggzdJA1c5zd03p5TjN72Xp2/PfS+9pD85dDJZJrpzPTMyHwzFCg5Iom3U/dA3jkJ9iEP
- w/W6L3y9QqsEgZYEAIL5LQdD2ms5ipaQjZdwschmsukGoW7Bx/DxUlAuUMnqHaN7rHXpsTQAEW4spAMl
- s2AdcDnMp6bL+E2dAtxQ/Y8EgvR9AMkcY/phTz8uebAWv7fPYBbuDnisN2K94Xuu6ivtJCm+nR5WPZll
- nmLFlwMLaQKFZ8HUZTjMR5eSGZfolPWQfx2J2oEr4f1Ujr1oqVVQSwAAwYAK81dDavsCbAu6Kktt4xOJ
- esf1qF+0Fp5PoC7/5CYAQGgATNrF8FKUJnbw4slTtDd0+6xG0d2V0FWKH2tfG76PzfiZiACk6/1X/w7J
- 53R8AMkyfw2NXN/7avHRkRksvsNFCpbhF8zDt5CV0l68yo+fsSjwKUoWmOmNeQBMh85A4dmFAYduPNoM
- 37fno/by7+D/GbG1xRZPuQ4AgvkVj38FpPJlKLz3GBh6J+o7L9u9A/an58H9BtS6b+zdFQAgSvH5YlxT
- iri+KPDJK/xKb4Clz62wjCTm0cXP+ovO+M2RAhzfAaj65hujAcT73CPJGHuTHYsvzZzTT6FfSaMbgX/S
- 02XTTrsRiSvwDfHc2Eyz0iQqHIeCk2+G5XQjpISLwzbA994FpAn8kloloxZFuQwAYeE+4ryiR2AdfzZM
- 10hJrOxbBNer4+FY6VVLPvPEYABgByCnfmqrW0UzASJfhfQvKQHaPYuiuQfBcAQQnbGTZfxMA0FqiT/R
- brZxGkC0z3mAnzjfhbFj7fA0eomPhrx06hn4P7yo1Pj7O9D4OQsPfjBaBPXZcYHlIvqjdAas5wyG+YTE
- PgGZt2Vb1wt1Q3+Dn8uHtbrwYK4CgJb5zfQUC++B5frBsNyqQ+K94F6E56MRqF/mCE0KIf2Z+UV12mQf
- JPeDpy5PoLITYTj+SdgeE3X+gNQYP1OrAJN5cMnF/8NDdg2PJX6NBQTc94+7eXHFrDrsLMkwz3yJvzAS
- qwnKOY2XG1f5YSbV7kIktjPkEDHvq8JbiZUSGlQuga3PuTAenHjVpyx/Ae+TF6N29OZQefNWAwK5CABa
- u1t5eNfD3GciCqYbVCaMS2/D+/kQ1C2qVScEMz+r/6wWCts/1QfIaqSyuQe1ihkouPFKWIbGYv70cwAy
- N3iJjsXL6lPfJ68JxMv0+6vSj8sfqMP6fTKU7CPITQA+Cs/iC3wNda0/V/kRW3tpnQzBdSIImG9Ql4eX
- 0ZvqF1E0+HAYOyW6HD1b33twz++L+gk16c2hnKVcA4CwWD+1gj4wnTgL1oXmJNb1fwjvt/1Rt6AmxPzC
- KaSWtU/djhNAxBKktC2kTjRpHm8H/b7JMH5TrwNoHPNH5gEkBoF46j8n+1x7Zz1eOdWT+Vm2jlh/Cp5H
- qNAHawAM9NoKv2HOY4Q0AJ5H7Lyt6Aipw5soGd4euoRziwuZLIHrntGwP+APL2TSokEgFwEgGOs/FLr9
- yN5eUgGpa6Iffg7fTwNQ99jfkEXNN54QrBJy6E94/bXrv5PtD/dF2eK7O4wnP47CecQcrFo2YP5MLAaK
- dzxWB5P5LL7tr161IdOnBwKc7PNgfyfuu9oJf/rFvKNTHT3LvngYW8g8V5mfQSDaxp5aYRKpBVQGWsWR
- BOYrUDSgbaCKUzzyQ7Y/COeYO+FY5m0lIJBLAKBF7IL2kNqtgO2RA6A/JcHvyEbz/W8Y6hf+D36eEOz0
- Y5tfMD+HhLSSP7VdaVTpUUKdq7wX1lv7wNw/mq2fLgjEOtaYQYx3LHkNQLw2BIF4QMCRuXUneTCSpL89
- bnJ2GsRdfBRv4AllY88NSLyxZwONEqopx5mjvFuzAgInw9BtEWx9kgEBL+Sae+EYNQPOVY3Y7ShnKFcA
- QOv0K6B5U7oAhRN6wDQ0UfFOkvy/XIP6Rb+ozC8kP08I9vgL5k/nIWnV/7IySB1fRdGCdqSVAI1n/OaO
- ACSnAYjX0PF4zM/9/76zDwPvq8NvHbJQco839rwaC0nWc2xeSP9EG3s28ClBNQUECLShVn46DActgO2y
- augSFpJxQ95yO+yD5sH1ji/9+ZUTlAsAoGV+E72x3Qhzn9tQcK8OkjHeAhmS/L9cjfrFxPxc820bojN/
- umoa94knDNuOFSdAf+xTKFpEBw2JmL8p6gCmm/yTugaQvFNwa7Efw6bV4/8ymewjyEtMdjuewz/xL4Rq
- /LGvRyzsSjRcwagSVBBgRmfbX2gC5T1hPHwuCi+qhC7hBqQ18P88ALVXvAkfOyKFhtniCo3mCgAIFc3a
- E4Zj5sG2lP6okAL549Ho3/D+lyT/0t8gsxQQzK9V+xNtPpGIhPef1cKKcbAMHwHLddqTxXP85UIEIHMa
- QGIQcOtlZYEPV/bJyqx6H+uVjT3diuTXbuyZbIXfsLwShGsCiikgaUCgAjpbohP+Dt8nF6Ou/3fwcbXh
- Fpko1NwAIOx+xUnTDlL16yh6tl0gxz8WALwP77ck+Z/YApntP5Hlx8wvJH9jmZ+JQYnDjqXUubYrYbv/
- MBhOTEXqp1oSLN7xeAOY6HiyGkCiikDRTAEmtvuf7OnGxLF2eA3pDHUCqqFnOgrL8D2+AoIbfERW+E12
- uIRjV93YOMInQB+WnQfDYXNhu6hNEprAenhf6Inaazaqq0xbXKJQcwJA5MMoehrWKWfBdJXoVzQAeAme
- T26EfeUOyKz+bUdDh59g/sY8CCEpFO8/iYKOn6LkWQskniQJVf/mcgCKjsf6O54GEKsseDR/gPYY/+rf
- B3ox4MFa1CZklzSIL7AMH+JRevRy2O4+bOqls7Gn1tnMGh5Lei0IcCs7HYZunCxUnkAT4DoCr8A16zLU
- T0EoxbzF+AOaCwC0jhkFia+D+fw7UDBXj9BGkBEAIK+A+4MxsK+qVzd21Ob3Z5L5Rf94crCKWNEDxn/M
- R+GCVFT/XHIApqoBxA/7hb7Dfd5S4sfFj9Xif52yZP7+Ss95JJ6kJ/4t/cXOvw1Qnz8/73Q39ozMERCa
- QDlCfoGyf8Cw35Ow9W2TwDHIdQTuhWPQXXCuRQtbQtycABBcXrs/dHutQdGKCkidwr+kAgBBqmcWnOvm
- wPmWK+Tpj2R+4fDLhArGk4NDRkrM+EZYrh4FywggNYbPVEmwRAMZ71i6GkD8mL/6badBxtUz6vDOP7xZ
- mUkSVw2djrfll/BP+pOXc3PhThH2S+T4S2boooGA0AQUMDgY+s4rYLtiT+grYt0id8IFeWtf1J7/BrzC
- KdgiVg82BwCExft5ccYzKLz3JBgvjvblrZB33Qb7c6vh+RThKr9gfrG2P5Ppmaz+s5OonDpb9QqKZu8H
- /fHxmD9TPoBEn2fe+x87ChAPBLz05oEhTjw82Jmxyj6RA9DpA53PPUF+7m+3/AHY3FY1AJb+HH9vrMoh
- bkULAsIxqDh+EUgb7gRd+2WwXX449B3jrR34Db73z0VNvw2QWUC1CKdgUwNAWDiG3hSNhPniiSiYqUP4
- HvA0av7/wPvLzcT836prspnhBfOL3P7Ghvpi9ZEnhBL+o462/RIlqwogVWbC9s+U5I/scLxjiZlf7Uky
- 9fyZeFa/eLobY+6ww5n23kvxyUxPuM8NJvy1Xn71TXiepkPfQVX/hfTPBEUDAWXVIELrBhRzoApS1TwU
- 9j4Dxv31MVYRkrbqXwPX3MGwT3GrC4dy3h/QHAAgVH8bIeoBT8O2pBJSZ+2XSM13L4frw2lwvroTMid6
- 7EBI6rO3VVvVJ5WVfcn2MWj/HwF9t+dQ9GyyzJ/uYqB4x2N1MtHxVDWA+GHAUB+/3duLq++rx1/tsjSv
- 6Wke8aweF842cd3+Tx+Ba6qsagCc8x8v6ScdigQBfvaRIKBoAnSgcjKsZwyA+ZiCGEVFyGqpuwP2oXPg
- Wofwlac5SU0JAGGqPxlbbZahcMYJMF6o/dImyNsnw/HC83B/7lclvWB8fi/W84vc/mzkYov0X374bfrB
- dP5dsN4NxFf5Gyf9G+8CbJz6H98HoP395jI/rp1Wj88OS9f/lpiK/5Qw8Boz9tvK+y3glwlwjCZB8A3U
- nH/tct9MUTQQYHOAQUAsIOJWShphaR+YDp8Caw/SCoqjmQQb4f+uD2r7/Ac+zlfIaX9AUwFAZBJG0XUw
- 956Egvs06/vlj+H9jlT+Vd+rWzUxs4syXsz8wtkXWdAz0wMr0n+VVWO3wnL9cFiuisb86Uv/8C5nzgEo
- ZVwD0P7OYZJx92gHnuntTpCgnT5J9FTPmmHEaWvV+v5V0G0bjrqrf4Kfy7qxbZ0NANDedrCMGEJ1BEoR
- 0gb4teR46PeaDus5R8DAfoGw0eDQ4NtwL+2LunF2de7mbH5AUwJA0Ot/EPRdn0XhEnq4yio/Gh3X43C9
- MQvON3dAFst3BfOLQp7aMF82wyz88BX7n1qb52CbdhgMp2bGBIjG/uGU6IaSUf2TAYJUowA+Scayi12Y
- NtoJbyYr+0TcfLuvSPpfb0Znjx5dlK29dN7BqB9CwoEjAQIAsqlSC01VFBPhaFCwmAjUKIECAmS6lt+O
- gtPIJDjWGFghKsgP2TkTjlFT4VyRy8uHmwIAtAk/BTSiZQtQOOk8GAfyhxvg//VuOFa+BM/6QC12ZniW
- /kLqC5U/0tOfrYHkh64U/6DW5iMUL2sDXWcgeeZPlvGz7wBMZbPPcA1A+30Oxf77EB+G31uPmkxX9tH2
- i57u5deacMTXBnTW1Pe/H85bH4BzJVQnMM+HbNvUAgS0S4lFmFAAgQICNKltF8PUbRqs57eJWE1YA/9v
- l6Ku94fwfo8crS7cVAAgVKrCvjCe8SAKF9Io6FbD/co9cL78O/xis456qMwvHH1C5c+Gsy9WX4MOwDJI
- e76H4tUWSAXJqP7JMH6mkoCSX/0npawBRJ6HK/sMeKQOv3bMLt8duFaPS6ealF19uhDvkfQnFJawAq5H
- RsB+P1QAYKGQPQdE+FCJuasNEwq/gAACBgXrAdBXz4a11z9gOEA74t/Bu/Z01FxTp2qzOWcKZBsAwhx/
- nSBVvYXitTQKpkmwP7IKnu8D8RweGJbyzPTa2v3a6r1NoT5xf4MJQKfAcPR8FD6qrkpUKbnXxIyfSh5A
- ooeU2AGYDAhEDwO69DKunVmP90/Iwgo/DVmIPQb1N2PfLXqF+dn+5409bdTWwP1if9TfjFBhV09WOxM+
- VJEJQ8IkENpASeC9lZCh4GZYThiFgnNNkMzqqMr+x+G8+SY4Fss5uNtQNgFAnFuxpWgEC5agcDz9UTkG
- 9sV/QGamZhWLEZEZnaV/HRqq/DKabsD4QSvr/6m16Q3TedNQMJluRUl1SewIlKMca/g+2t+NHeRof8cD
- gmQ0AN4F+f7hTjw+MEsr/DSDcfKDBpz5jBG8rx+r/ryxJ2lgpH9L+Bm+/5yBmiFb1fUfbBpmuL54UkMs
- 9oYQZcZFqFCAAL9ncNCfDkOHmbD23Q/6fdhBSONYcx5qz/gAXg5l5pQpkG0AECqU6TQY2u0D6ZAF8HBC
- hzlwnElIf3vgVevlb2p1SawAZG9vm4EwDRiPgusFe8SW+skxfibXACSb/JM8CIRrALzC7+UzPBh7px2+
- bKzw01AVb+w50oy96lXHn9jY0wpJeSA74f/leNQM+C2UEObMbo+iUqRfQBslEFoAzx0GB105JP1EFHS/
- AuYL6EtFv8H37pGoudSpCrmcyRJsMgBASH0yBY5JgUHgweAHKqS+1k5q6gEKrgCk1uZ+WG86H6ZL02H+
- VJOAEn0mBjSZ44kdf9FSfkNOQO7H+r29GDanHtsqsvsIdPTEe4014ph/8caeKgCw4684IP25R27IO47G
- rj4/wc/Cg/NCHEkMVzYo0iQQICC0gaLA3+bA99xnwtB+GqxXkzZw+HI4x46A4zFkZrl6xm4o24MlAMAU
- GDRDYAD5xlnKuxGy9bVbdjfHwHD/RASgajlsdx4Fw+nxmD9Ti4HSHeBYfycLApEmABMn+1x3Xz2+6ZZ9
- X9u+r+lw8d0mdPao23rvqTj+dCQtVOkfgCTfsai55BsyBaACQKazAVMhrUkgtAFhEtgCjQUdz3MeVHcV
- JPlWWM69HOaeQ1E34DV4GchywiHYFAAgqvwaAu/F0hG+eR9CjK+1i5prUPhhsjrHFWKqXkTRg/tAf6i2
- QyHIluNoBSHKtAmQvPc/MQiEJ/6oAGA3y7jrFjvWnueBnI1FPhqybgUuG2VCt1/0CvOz468tNXb8Gahp
- t2cehNpBK+DhXAAGAFajmzu9VmsSCG1AhAuFFqBDSMt1nA3DnoNg3n8o6hfXhtKExeA3201k89zaQdI+
- T8FHws5PReWPN6/jUSwhLGvOESwBRq36LRQvbg9dx3ATIL7Kn82lwFIKf6cKAtwLH71d0teFOddmMdlH
- ED3x4xYa0GORER1lXdDxV07NpJH+oneTYb/lXjhXo2lDgYlIO8dFqNuCkLkrTF2h6TrbQfLVQa6rzZGK
- wk0BANqmJb7pZBlfew4d/aM7AvqyUuj2KoXU5RToK23Qlag7B6lpmT7ILjqpizcJraf/v4OvZgPkWvq7
- xk+vHJKh0a930fsf4K/ZoUYllBLg1MrpTbs3UfwkTciyaMyfaj2AeMcbM8Da11jH478K+S/j3eO9GD/Z
- ntVkH0GVP0i4fLQJ++xUvf7C8VdITSstRA9nwzFtAhyLoAIARwJyAQC0w6l1EAonoQkhjVdou65Ay4lq
- wk0RBox1jWT4IVKLMPSA8dhhMA/tBP3JNMJFJMHI5kpaWWVTwyOrzcev9AS8uyA77JB3ctsKueZnAotN
- 8PtvREFfskUtaicTq/yZWBGYysDGG+hUQIDdfz929mH0zHr8nuVkHyY9Tf3uU4w44U2Dwvgi468k4PjT
- RXFSzoPz4Zthn4PQVm/pJCakoymmcm5h8gogMCCkBQiNl/stQtytGgASnT8ZqR+0sdpDKpsK68TDYbhS
- l8QegakSd4Z1shp6t50UE05GIC1DsUXTYf5kTIFkByLWQDZO8odmZa1Vxqh76/GfIzK8h18M6vKeDpfd
- ZkJHn+r460AXZcefqjOHgpFatW8xnE9cD/s0hEq/ix2AY91amOZJ3Kg7GrqCdtDbTMpW4VJB+CIe2Ufi
- uX4jfDvfJwHgaaihJiuwmMS8FU07qsL31RRp7QmpqRYDpdOv4IKMDtC15Yw8khanZ6vP/ATYtcwAsIOe
- C4PBYfTs9IjP3MmYAI0FgWwxPxNv4zXrOiee7OduktlgIuP3shEmHPyjXpH+HPrjjL8iasZgZEJqwMHL
- 4HxhOOyTaFLsoL/r9qRjp8PcoRDSHjRJ2tBzars/dFzCq5Q0iRITdKV0rEQXaHo6ZiRBogucUopyt7yK
- j01GGoka4tA/auD/cj5czz8B5zs7Gi7rTVZz1WmOid8JcGnOiFdYp3KJwpwqJPmr58H2cBfozsrmRflJ
- cHB5F73bQc/DTe1Q6oJ4eqmsBWhMLkCyAxTtvfZvCYmZn5N9XjjXgykTHery3mzPBrrxI5fqce48kxLu
- 02b8mcO8/g0B4GW4330N7g/6w3J8V+i7WiG104WSybLZZdIG/V/PgmPcg3C9401+m7l4fth4U6VJKdcA
- IIz5Sc8vuRfWSSfBODjbfeUnaqfnsEsxAWTlb5ImwYSFVLSAZBk/laeebOaf9n08EGBav7cPw+bVoa4I
- IgqYVSr6ExgwyIy9a9SQ355Bx59Q/WMDwFYSzH/BbyBTQVcSAIymnLwElo4VcE+5DfXzd6jp6slmqmbT
- 79BoyiUA0CYOmUl9s10P88AhsEyR1DhrVomfZH0YAMgBAJCSZv5sO/8iByve+3ggwLStxI/rHqzHD/v7
- Qx3L5mygy3SfbMQJrxsCqr/q+CsNqP7aGHE0ANhGJ/iDWkXAWWhpYgBQh0j2PA/X7Otgn+ZULcZMFqJt
- Fso1AAhuEXYC9EfNgW2ZSY3JZ520ALAtAACHUHe06bHiNVVfQLz3qQ5QrL+TBQEml0HG5NsdeK27J9wy
- zeJsaP+phH6jzOjoV5m/A41tJV2wICLmHw0AmLYHAKA8ABrNAQBMXOhjIZyTJ8Axz5WDq/tSpVwBAKH6
- K8UX9oC0x3zYFnSG/li5icaVAaAuCQ0gGdU/05mA6ar/4jXcBS3jqcvcmDPKGb7IJ4sAoCdxefEIEw79
- TlX9O9K4tg04/gwNpH84CIh7YAD4XQMABc0EAEweyDtuRf3AxXC/jfBaFS2OcgEAxDNX1luzx3Y2Ciaf
- BtOgeJuDMpHEdrwFz/c/wb/xb/hqN9Pf7kCCiI1MCZokBpIuEk00UyE1Uh0LiqGzWuk6JEHMxZAs1Iz8
- mYU0D/qhiSDdSEDAuxJLAgCYUmX+5EEgNRMyEeNr30eq/3ylD47z4PYpdtRG7nWTRQDo9rwePe9TM/7Y
- 669m/Kl2fGTGn9YRqL2HbQEA4AIhpUrIsPkAgGkT/N/2Q22/T+HjzUpyuvBnPGpuAAiz+6kVkt1/+dWw
- zGS7Px4AkFBxjYd91dvw/OCLvTGIFKfp6KJ6uqiB67kR+phoMlrpg0JqtmNh6DgBBUeQhNJFY/70GV9u
- 8FmyA6V9XPGkvvbGtfRrBx9uus+O3zpHEVZZAoDCTUDfq83ouink+KtS8v2hGFiRGX+hv8PNgFwDAB6w
- n+B79TzUDN6ork/IicU9qVJzA4CIkyp2/6lk98+C7RmjuiIPsQCA47Wz4VyzGK4P5fDKQckAgC7Gq9gN
- SFnaeTz0ez+IwnMIHPSpMn8sxk8lByDWg9FCQLJmAFNNoYwJd9vx8XExtvHKBgDQOU++14BTVhkVxmcA
- aK/J+NNmyGgfjri7iCiA/Af8UrIA4IPsZyFhh+zmVkO2OzUXaXceJ31Gk8VP772c8MPnYW2RtcYO0Nn2
- gr6CzIzCRBDD1X5WwT1jKOpn+kOl6luUP6A5AUBr91u7QNdpCWwrSDXcJ/SF6ADwEjwfToCdq62KUuFi
- 8H0xrqNl9EjmF+/ZBGEAUEo9HQV914dQeBlNVCUCkQzzJ8P4mUoBlhr8G/vVTRD20AgnVvR1x06azgIA
- VH8l4dIbzehSr+b6c6sMZPwJ6a99QPEcga/A/dNKuH85Dob2ZL75a+B31tOtETO7yRR07oJcv4NMQAIK
- O6nnDnrv5qSeQMo3L/Tw+wPvA42lRXAhGF1Dx3kFJAVMxPzWuSjs0R3G/RKBAG8MOh32/jPUjUBa1Mag
- Yuyb67rBWoFtIbV5DIXzu0B/aviXGgLAL/D92g91s+rVTULFFmGimEi6GoDIPRDVXcoOhX7fR1F4NfsK
- ojF/fOkfn+nTmRnxpX1DINAm+6zr4cHUiQ744gVTMwwAemKF88YYceTHhqD057BffMdfbABYBtdn16L+
- JYQvI5cjWuTK0ljvIx+Ddj6yNmquhFTyAor6HQR9h0QgQLC67VLU9nwH3q8QXsou56k5AEDr9DPTPyXT
- UXBHd5iGRPYnEgBIZasdgvpZ38HHZZbF7sACABKZAEzRtABtfzglhusBlh8AXdcFsI0tiFIROL70j18k
- BAmOJXo4sVX9hiDAPfn6QB9ufsCO2kQr/DIJAHSurq/p0OtuEzp6VcnPYb9ojr9kAWABnO/cCPsaqM9Z
- WzwmGvPHek0EAKK4h2IK7gVdu3UoGtIO+lIkoG3wf3ERai/9Ej7evThnSn4loqYGgDCnn0FJ9rH0Hwwz
- J/uYG345BAA0oqRqOZ54Du5/yqEtwgUAxNt4IRIEYgEA90lsD92GHv7eZJJMtZItmBzzJ2b8bK4AjAQB
- vtamSj9uml2P/+2TRIQqgwBg3Qz0HmXCARv0Ssivo+L44wq/uuDSuFQBYC6ca26DnesBOBGqGxkp3bWv
- saR/LPVcuweAqPpbfBoMBz4JW/9C6OJug8pmxTfwvNQbtddsbkFOwaYEAPEsxUBbL4XxrLGwzjWrNfii
- /EAFAF6yuxDOtY/Atdan7g/HACBKRLMPIFbp8GRyZ7T94ofOfakiO7DD87A9Wgyd4pBMlfmzlQKcKOYv
- /uVtvO6cbMd7pye5ajZTAEBP4ejH9ThzMTv+VOZvH4jdh+f7pwYA98Kx6E44WAPQmnyR6n88tV+78Cba
- PBGVfRgARLXfMvqg7FqYT74L1gvIdNHHH0LZtxruudej/u56tZ857xRsagAIouzB0B8wF4WLKiB1jf0D
- iW1YeS3c790Fx5Mu3ncR4N2CxZpwzsnOVGEF7hsjvwIA1KpfRNG8tqQGpsv86ZoAiSMAsR1+TDzTFw5x
- YcnQFMp5ZwgAyn+UcNlIE7rsVBN+9gw4/gqBYF5lOgAwEfaZs+FkR5vw+0QWj40n7RNJfyBU9pslPc8D
- xRSkVkGoUDkD1l6DYTkx0RBxpuATcN0xDvbHHC0gU7CpACDM6VdNzEXMP/sAru+RgL4ie/9G1M/bDPk3
- hJhfqP6ZrK7K/RMA0IZa9TOwzdyLgCoR8zcmEzDZwYv3XnuMr/HOyR7cdZcDbnPCU4f/sJGzgSv8nnWn
- Ece8xY4/KZDxp4b9jClJ/4YAMAx1tzwN9zsIaX5aDUD7WKIxe+wgTWgItfko7AMQuwLzXKishNR+OZkC
- x8MYU2AJckPeOR32EQ/A9aI/xyMDTQEA2sG1EAKU3oWCsefBNByhsG9U+g3+P4n5H/0v/D8gZPeLopCZ
- jrtyX1hQKT4AatULYJ14KIzHR59J8Zk/EyZAKuq/oF86+3DTXDu2tUlxSBoLAPT7jh/ocPFtJuzpVRN+
- OgRq/BUog5s+APDZT8Cuq0gYfIqQ9icAIJ2hjTXcwhkstABRIFZpXaHbi0FgfxjaJzoZ7ws4BHVXvg4v
- VzIWTsvG9jHj1BQAIKqjMLLahsF08UgUzJJC24JHpa2QtxHzz/8Cvq8RkvzM/Bz718b9MzWgPBYCAPiB
- V09GwYhzYOrZUMSEZ/OlawKk0rFof4d7/GlwSvwYd78d67v5U3+yjQQAIxljvYeb0O1HVe0XGX8i7BfN
- 65osCHgg1x2DXYN+gv8bhMK/2dgeTKupKtvYQ50Pykax1CqPhH6/pbBduSf05YlOtokA6xLU9v2KBBly
- NDKQbQAIc/p1o8FbjMLnCyBVx/tRPWQ7q/3/gu8zqA+cGzO/cPplI/daTQjTAMBAmK+8Fpb+QHLM35wO
- QKWyzxgnXu7lSe+pNgYA6LeHPK3H2XOMitQPd/zpGiReRIvJxgOAncRAJ6DmGtIIf0TjagImO+TCISg2
- AxVzQmlnwHDwItiuKIXOmmBY5M/hWXU+akfUh/Y0zCkQyCYAaNHUWkyq/7MoemoP6I6N9yMaIfdE2Bet
- g+dfCEl+rcdf2P1MmQYARn1lY1Bq1efDeN4EFIxCYD1ANLW/qUyAeMzPyT4rL3Nj/ihX+tt4NQIAOOzX
- /3IzOtlV5t8jWOhDxPylpACg4TH1dz/A+3V31I7aDvkPqPOB50K2qgJrQYAFl9gWXAsCFVfAdOz9KLyY
- hFlcTVZWndh3Dkb9bG8OOgWzBQBh9hQ91KKpKBhDdv/IeD+ikfFOg33Zs/C8i4aSnz3+2dxSifvLD1MA
- QNWJMBw/A9YpkrIeoKHkT1b6x+potOOpJf+okPTZ4T7cMdOO+qJG3H26AEDy7LQpBhz/qiGo+outvUKO
- v3AAEP2PBISGZoL6uzVw//NK1N2GkEBgH1A2y4JrQ8PKIjWEgwCbA+XXwnzSnbCebw6ki8cZWs/NqOu7
- EO7XkGNOwWwBgNbuL7wQxjMnw/qYXlWpohJJfs/DcD6/EK43EC75RbhPLPjJ5sCJnYGUrcGqIXVZgaLH
- 6KApHsNnKwqQyPbn8/2xhw+3PWDHnx0bOSRpAkC7TyVccgM7/vRB6c8LdrRbe2kBAAhxV7IA8AScT14H
- +2yo86KpdgYKc14jBAJs+wtNoPxmWE67DQVnGxPkCLghb+qF2jM/gvcX5NDy4WwAgDatktMpO5G99BRN
- in1jDw7c8+BcQ8z/ul99yELyi5hvrNV+maawvQGpVb+EokfKIFWlyvyNAYFkbH+mugIZ0yc58NGpGTCH
- 0wAALvTR6zoTDvpWdfyFMv60FX4bhvQiAQCIDgrid1NhnzkNzmcQmhdNtTeg6JIWBER4UDEF6AvlE2Hp
- fgMKTo+XKMTD+1943zgTtQNrIOdMpmCmAUCr+heYlDx/66SzYLwq1rWIs92PEvMvhetNmsZkTYZJfpHm
- 21SDpd0dmAGgaiEKJ/HOrkB85s92DkDk4Hl1spLo88xV7szs4ZcGAHRboUePB43o4A85/hpW+G0cAFDH
- /D1RO/pdeN+DCgCcA9KUuwNHRgZEeFBJEuJGH1ZMIi1gJCyn6CHFfBqcKbgW7vuuRv10Z44sH84GAATR
- 8mwYT7sH1nmmwPr+SKIRcJLkf/EJuN7yhiR/NOZvqk0UGcEZ5YPJQDfAPOwSmC9oahMgltRXzyPjvVO8
- mDElxWSfeJQiANj+AnqPMGGfjaGwXxs6gVUT9ssEADgg7zwdNdd9C9+XCCWBOTN018lSWCIbwkFA0QTo
- MVQSCPS4BpYT42kCBNc1t6J+0BK4X0fIH9Bs5cQyCQBhqj9NhvaPo/CxvWGIWtePy3k9COeqZ+F+zxdK
- 8hEr/Njmj1zj3xQoyf1nP0UwFNgTxnPGKJGA+OllmYgCxHMAau3+DZ18GDvXju1VGRySVACApuuJ9xrw
- j9UNHX+mqAk/6QPAr/D93B011/8NeQPCk4CamiLXC0RqApV0sPI2FJw1gkCAq0zFOtHf8H1OWk2fH0P5
- Ac3mD8gUAGgdJgX0puRWWK7pD/NYrQdd0C5CwSmwP/MmvJ/61YcaTe0XA4MmHBwRChQAUHUAdN0eg212
- ssyfDQeglvnrye4f83A9fjwww0IjBQBgx98FY03oXK9K/z0gtvaKtdQ3fQB4gwTEJagbL4fMQ04Ey0YS
- UDKkzWsR5gBHjYLmAFexHg3Lybeg4AxLjOgAVxJaB8/DQ1E32a4Ku2YzBTIJAMLrX3QE9Ac/gsKlNuja
- BW44+MU/4N84AfanPoPvO6hMLzL8hLdfrPRqjr3TtaFAxRFIN9XuVRQtMCW9LDh7DkCfJGPWeCfeOD/N
- ZJ94lCQAGGjGnj3GiEM/NQTTfcXWXokq/KYDAIvhXDIa9nlQTcTm3hpcGx6MpQlU0Idlw2A+fjKs58TK
- E/CQELyRTIFlcHPUS7ucvclvKFODomT7kf5cOQeF04+F4aJQTX31vj6Fd/14Yn5S51j12R5oIs6fjuSP
- 5SNLFIKPdz5RF0ABADrQ9lFYJxwAw2HRtAAgNT9A6JisuWjDxxDthtb2dmP+Tc70k33iUZIAsN8aHc6e
- YVIcf3tqHH8WxMv1Tw8AqEu+K1E34SV43kQoBMhCojlLcMcCARYaIm24nO6jtDdMh82C9cKSGBmDG8kU
- 6EGmwIZmNAUyBQDB3Ol+MPa6DdY5ksYR4leKJ3revQv2NT71IXIT9r5I8onG/KH5wfPLqGzWZ1Su14Fs
- 9YNRRVcto0dRBC4b4IYdW2mifEL/OkmT8CnnE36EZKMIojRY0BF4LcyD+8DcK31HYOrPVAsK/PvPj/Dh
- 7pl22G0ZeGLRKAkA4Iy/i4ab0PUvvSL5OwQcf4VRHX+NB4CdkLeci9rR38L3LUIRAJ4nzV2DPxYIiGSh
- isBrGWnDXRbBdlln6NpEAj0/1xfgvn8Y6qd6mskUaCwAiGemJPxUQeq4EranK6APLpnkvP55cKxdCvf7
- flXNF8zP70VRz1CGXyHNJaMiUCzYi1Srg9GFju1LQ7oXjkRHGuI9SdfoqOSbxOq/h8D1c7yDt7GajMh/
- 0xXExBHhxHgTiB+qcAQqAHA6DCfdDus4aJ5Oco7A0HNMbwWg+tef7fyYMLcemzpkcV4kAACJIPSYhww4
- +WmDkuzD0l8s9TUh0Uq/+AAQPRFIIo3R8+XZqL3REyoCE2sVYHNQNBAQeQLCL8BzqJRrXs5GYc8eMHbT
- RYQJvZB3DUPdJSQgP0YzmAKNAYCwmD87/ibBcsMl1BC4g7/h23gPHM+8B+93ssrsqsQvoRu1EBNyhYgu
- hJwH05yyEVMbqR1OrQ39bSTtUq8woD7tHjKj/w8f4iE8SFoBWSDKBEqUV8APKGxNQKmSEWibbQzUBxT3
- F5v5k68LmOhB1BMUzZrowL+SreyTLiUAgMrvJPS+jpDXoQs4/tSlvoyUiQt9JAYAcWktACyF88lRsD8K
- 1QEo1oPkUsHNSBDQZgwKk4Abb01efDsKThsGy0lWSGHB2//B+z4B3ZUbSeNBE68abCwA6AM3bTsUum5L
- UPQ8qYIlrPJ/Ce+3U+FY8X2JfzsNhQnt6HvH0L+VpDnuS/Ongo5aaA4ZFCbTxbxCJobBTYy/FouxkObU
- TsKlUHZhNJtL+DOCKcH0xx5zUThxH+gPABJpAeFrBoD0HBFKtw0ylg11Y1V/N+TGwGAyFAcAdDRS3ccZ
- cfi/QtK/KuD4S67QR3IAoG3EAZ6BqLvzRXhEajgDAKvJWUbClEl7OzxvxNqBYFkxqGBQSl8o7AXjAffA
- 2msP6IN7XvKqwUfhGDcejsfk0KajTWIKpAsA2sQIKxnNJUthe/hg6M+pM8C1qovr88cPdf648yBi9q40
- X5jtC5TBSO16/9/elQBIUR3tb869YGGXFRZYIGA4PEC5ongiHngAiqABVERBEFBUQAFRicYjXKLgrySK
- 8UARNd6IUeNFIgbBIwYkRI6oKKAC7u7szt1/VXe/nTezc+5Oz/bg1Pic2WF6prv61VfHq1eVLgCA+j0B
- /BNvYBEWYDc4H5u1ibw7S/7VyIzA8quQN2YU8kbEDwRG3yoc+TqZm8E7/N49y48HbnbDm5/EwY3nT/S7
- Q+93ftuKIfOcaB8R+Gtohd9kAOAH0oaDUTl1h7YFWPj/mUoBTpUE54QlIKoKiRWClvrg1wW9YWt3Lwov
- 7A17V4vakkBNENp3PirP/hCBbYitnAw78VRJbPZRtf+FcJwxvnX+o+tO9NvWDPK6Nh8RQLBITQnXqDF5
- sOllAfdz2ojb6fEVOLDE8Qg5JVOQyAisiwP0ga3/fBTeapFahSUj/ImSgGLIHP7bPYC7FtTipzYZsnZj
- AICDbKWRlzvx691a4K+9Hvhrpgp/slV+UgeAD+Fffy6q5kIz/4X/74F5zP9IkkGAFUhkhWEBAqxYCipg
- aT4PhecOh5OThtR8gU3wrR6EqikIFbo13BVoCADI5k6hpTf6njbQvmzzwEC3vZyZFmtGN/TsjLj8b7EF
- s3EztoOrDbFpKRgufo2vj29e3dbgFrB0Xo6ieWWwtosn/A3V/jL9UBbEHffWYle3DCq7GADQZ7kNAx9z
- qIJfoWf8JRf4azgA8NncipplD8DzLEL+v0gAMisAQOKg2EAkBwdZ8IUVwKCQR9rTfgXyes9CwagSWFuR
- 1eebBdeYP2lpwiIgaOgkSBUAxOftZBy3wFWYjLMxjeyAsrjfZDYAYNpDNsBMzCEQ4G4uwr8UqCviAHzT
- RD5A2xnIn3QWnAOTFf5UQEBcqtehYNHtbnxkdNAvkqIAQPEuCy4a70RHl7VO+7dKOvBXHwCSBYxaKK5h
- qLpuIwJ8b+T1f1NsoU2C5OCgiAuI6kIMAMX63076kNIP9lbkEkwgF7oPuT5bzkDlef9DUAQEDb3mhgCA
- hcS9JXnSS3AExqhLwInIjABAZNuL70+eaH/DsQ/77LActOlpySTUBwl+D+5D0P0VgrZazRVofTLsJ96C
- wuv4zJIV/mRPX3zHqis9WD3Bm6BcqgEUCQAEg6fPsaPP+/a6Nf82eo0/Z0rCnzoAbIH/3yejakYwtPwn
- dgCa0f+PRbKhExkXaK4/a20S6boIEZT5KBo6Cs7xf4FnwQTULEL8hjdpO8nUPl9I938h7kIfTEeyHZpN
- CgBM7bZaMHF6PjocUCe3QmZZ0MZ7UGm4oSiV9PwTgtWEzJUHoXjPhKNLMayOWMLfGADYcIIP8xcYlOmX
- zAlId7PD+1YMucWBCp8m/O30ZT+exalp/9QAgE6EBMH9CI2VCM//N7P/H4siXQJmHwu9sAYK9ff4c376
- kHs4HN0JCK69CtVT3oWf0+UNjQWkCgBWjMCpZDq/pkJBsmRiAGDq9JkVV8zNQ8f9mobLg1bG2k8/XkOj
- kgYJP9mhipqBdDiJQEN3BsZiz+72Qcx7sCZzQb9oJ6HPBgeJ29Crnei+3Spl/FnVwJ89ZeFPDQC8UDzn
- omrKJ1r2n1wBSF6tiTdv5X+Lx8xMbjADQoFzsZFIAAG/dujnw8Lu7glr3jjkdZ+L2rXu0IqAIeecGgBw
- a7c/4F6cgmtTOs7kAMDUeZMVY3+Xh04/CjNXI+Y+A8DPBMIMAHwH+9P9EhZ6MkCQiAXVRQruWVCLLX2b
- ao8LQgBAzz2ftOG05XZ12U8E/lrSSC3w1zAA+BL+zSeiaiakDlAkIR4CHyupUIdV85tZYFij2umc7MfD
- VtAe1ub5sBQ5NKEKc2YIOar2I/jz2/D/REhS44NSRRadWwnXrEbPtMikIbFKkKe/Zvbw+TAI8LQTPRAN
- 3RiXGgC0JiXwGF4hW/C0lI7LAgBgOvxjKy67gywBHQT4LrHacelWAANAFY1j1E631pSsgFgs4WSfR6/3
- 4K0Lfemp7NNQ0gGAA3/DrnWg8w9aR1+x1beIRrw1/2hZfakDgMJdgNd8iMDGX5EWJKujiO5Ds46wFHeH
- rYhAoIWDBheZpc8X0nMzS0RWXYJLrCVJ2kdg/tWb8L62FJ5XdiD4rT+8SKeRM05ml1gqFEOwR4CAVxom
- AYBylOAJrEExBqR0XJYAAFOPdVaMuScPFQc0k5fviptOolp3A3hw0csjVTfAknBzUKzLF0HEt4f4sOJG
- D3zpquzTUOIVXJpmJ91jR/819rplP97qq1X4tcYV4FR3AkYb7HK9Q3O/VO0naFH7CkRWGEonkbvx9Svw
- PDgP7hV7oHCeQSaq9Ua6BMKasUn/FoSme3gYWhQnNZ46SBEsxAocj9+mdFwWAQBTz7dtGLXAiXZVWlsr
- tRAHoMcCguod6Uf3LE8HgIa4APz3tiMCWEim/4FU23gZQXQKbTdYcN5sJzrUhkz/UIXf+IKcDgDYSfN8
- F/GXE41K9QpD7CCL3zbmspXAJ/CvGgPXTT9C4eVgsfaeKZdAAIEMAGIa8XkEYBoAYH9lFD2uIxCwpLBJ
- J8sAgH/zmDdtGD3fida1VtU+41lRpcYCNCvgcGgmcrTNQYkEn8ePZUEsml+L7UeZY2WLA3+DZzpw5Oe2
- Ou0vMv60Qh/pB4Dwvf8KPiAuM6/L9FTjZghfcjSKGAT+Dv/T4+G68ScovOSYSRAA6m+MDJ1aCAjE34ac
- QLLkQAuaGwuwlBzhIUkflW0AAG2h/9g1NlwyPw8t/RraufUYAAMA37E+JBr2CCsgkfbn124n+bqz3Pjg
- XL+xMztZopPq9oIVZy52qIG/9nWBP7nCr7EAsIfm+L9I0bHpz6OF3lTUoTPIaDYRCPjfhG/pRLjurA5t
- OsrU3nxLxHOUOxT2nPYfTpZYDorRCUdhER5EB/RM6qgsBAARjjnuaZv/5AccB0thcXIHGDqdvGooVrYE
- jlZ9VVtM4Y8UfBXKCVleGePFM5O9CDbFen8UKtgHnD/RiS57Qmv+ZXrGnz0KADAl3+cvMQAwfUSOFbtW
- h+navxjh5cUzQX4orkWouWEhvKugBd+aAgRikSnyAPjzWtHMX+FY3EuPduie8KhsBQCmIBT7s9hquR8b
- rIrqi9kcxAOSXWcv2NpMQ8FxdrXwaXwXQAT9Ng3w47673fAWNNF1RRKBXP+ldpzwjBb446h/Gz3fX2z1
- TcYCSLQEGM9K+IFO4lOStRIp+FeE8OYimSKy8vZeDddFr8LHjWkztiuvqaghvGW9xcqhlGbLEVhMDkEn
- UobxvimbAYCJ9+auxCYsx3p6zVpBDdzQR5x3o+C8HrC1FysC8ZKBvm8bxLyHa/BzmUnmE51G6VYLhpP2
- bx+W8RcefDMSAPgkPiKWsqTJwT9eFLFnyPyPZAq5IxvPRNXF30HZg/S3oTcVNYS3fAyDgNZAoy264Q+4
- k/7fN6EH05BfMgMAMPlJ9FfgfTxO8zVYV5ba0R+2rjehYLhVr4EYCwRq8hTc8VANdqa7nHdjLpGuYvAN
- Dhy10aZrfy3w1zxC+xoJALsR8H2GgJVMfxtr/5K6pT8Eg6GhkHnOCT2Kl16Sg+6pglJzAMEafu2C4quk
- UUv/Rpek8Gufzn7SVHYCFGc5rIVksbXtCltre5zuPYI+hO+R0aieUx2+C/GQA4GGgisfJ/qnl9LjV5iP
- 35MdMCDqis2hAABMHpoID+F1PId/6gVH2QrIJytgXDfYO0dbDmSz30fQ8NgNHvxthAHlvBtBnd624txb
- HKrWb6/X+Its7SWX6GoMAEQT/gCUwHVwvbMNQTcJZ6sCWAJcQ9IDxUMWgbuaXru01z4SdvcBKO7K8Nz4
- WJ6XTCLpxk5WTf4s5J8whUYiEKAv8z8N963TUfuQGdt6p4saMx1lEChBK3TGdfQ4HeeS7Rge3jpUAIDJ
- TTCwEM9gLTbSNGTT0Hk0bN1uQ8HVFn1SCcHX1m8UvHWBD4/f6FV3GZmFeNnv/HFOHL5bE/52er4/m3XR
- C300ZBUg/jGkZXdcguqXXCFfW2TAiWU4IeiywEd7L1YcVpya2I2XTyBQtAyFQ4bDeayoxhOL6N7V3oya
- Kx6Gdw1M1tY7XdRYfSTcAQ0E8mguTcYEjMRoNU9G0KEEAExVqMZirMSb+FRfoS0kzTK2Lxx6E1GlbpZs
- PSqAexfVoqqkia4jBh37kA0nPW6v0/5t9GW/2Pn+6QUA1vITUf3UG/BvhSb48hBl3GVhjxT8aKAAhM8Y
- /qnIgp1F5GqU/QXNLj8KtopEKUbkVuyejOqRr8LPtQmaqmGNYZQOg1SAgFZBx4G2uAyjMBZXEcuL1E8c
- agDAVEmP27EC/wBPYFtHWDv+HoXTaJYVilm5r3UQixe68XV38/j9TC22WzBssgMdK236mr9FL/SRWmuv
- xgDAq/B+NAWup72ajy26QbHwR9P+qQh/JACI6lVyea4Wx8LW5Tk0G18Ka/N4vFKDtwh8OgJVo7ZB+QaH
- WFAwXR6pQFpmcjHBQTmG4jxcTS5BC5QekgDAtB8HcCuBwCbs4hWB0XCeMwzOM/mUqwkGHprnxienBEzl
- 93Pg75Tb7Dj2XXtYxl/8Cr+WJIQ9+eP2I3jwYlQv/kIrgMkAwIk3ojdEsgIf+RqIPlsEAKiNayCV674A
- jn7LUTQmXiNP7UsV5VMEXrkU1VP2aunCmWpXbzilc2oKEGDTn1dyDsNvcBJuwRy1FHhDv9HMAMB0AAcx
- HY/gS3zfApaWc1FwZVuLpf0LV3rx0pU+48t5p0gV71kx+DYHKryhjL8SfdktVr5/ojTgVACAG2M+APfz
- d9FA/Yawso8tzKZIXz+a7w9E983Fz4qW9aKFl9rDj/6hbCbyz7wJBeckzsJRAu/B99CVcN1WGV5DMqtB
- IN26STBcbRIKZvTh6IW7MQ8d0aNB32Z2AGDaix8xBQ9jN6p6w9ZjwIn20Svu8Dg8RU107jHISaI2eJoD
- 3f4TWvYr0wN/DsQ22RsLALLFsBn+/w5H1d2VvAIYKvcl92lgihfcS5RwGUlyIQ7RtENt5w2tpXfrpSgc
- eSHy+ifiXwCK+zHU3nozPH/0y92sshgEjDJOhdml1dZvQzBwJ27D0WQTpPKb2QIAfI7fYA+ux1OW5iiy
- LcFYf2kKFZMyQXSORz1hwynL7WinhJb9QhV+lThr9umJAXDgbzQJ/3oEOMuOC36Ict/sAoiOONG42xgS
- Py9Kcola/QIEDiMelD+OoktPgr17oqCgH0rVLagd/zA8axECgXScZ5OQkd6pWH7R6usX0ZybgxsxCOcg
- 2Z2E2QIAgr7GPtSSadidrtVkVLzDgvOucaDTfq3IR9u6Cr/azYgEgMYHAcOP4Vp/98H9zAK4X0Co1j+X
- ++IYgGz+G0HxXAHu+1BGPOmwCs3GHQl7+0S33g1l9wRUj1wbvjKQA4AoJJjO2rCl6nJOxeW4COMIGhKX
- wMg2ADApceDvhLvt6LvWrgp++yitvRoDAMlo/w/g3XQJXPcFNOEXrb5Y+8uNWYwuxCGUEgerRUCwTAxy
- 37r+GUWXdZDadsWib+H/+AK4LtmJ4LfI4pWBTEzz8GVCm7pCMASTcQ15YyUJj8wBQOOI+NduvQWD5zhR
- 4dESfsqlfH9rXeQ/PgCkXgsw9F27Efh+BKrmfwOFW7KJSr+y6Z8p4RGBarEsyCDAc1CAQKvTYe+5DEUX
- t4G1ZaIv+xf8z/0W1dftg8KWTFauDGRqmsvLhJxvUo5+OA2zcC2po4q4R+UAoFHkqATOnO5Aj3/bVOFv
- W6/QhxDYWADQuEKgZC7XTkL1A3+DfwNCpj8H/kSp70xvuZVBgC1TDgoyCAh3oPRs2I9ZiqKLWiXOEVD+
- Avcdk1G7JJil6cKZnObCEuCYAKNtxZGdrWNrpmPcrn5BS8wjcgDQcCLe9VhtxcD7HWirhLS/CPyFJ/3E
- CgImtwIQLWjoh+JbiNpnl8OzNqA1+RBlvuXkn0wLjAwCopOvAAFhCZQOg6MPgcBIcpPibtwOQqmZg5rR
- j8D7DrIwXTjTAFBnBXSCpdcU5P9fTUt0eulaL/51dqB+VdwcADSKinYDQyY60eknTfhFcw9R6CNceGNb
- AA0BAF7vXwHPG/eg9nlvSPjZ9OeuzLyO3pTBs8iVAQYB0cpbrA6UjoSj/xIUXViYoPJwJYI7hqHqnC+0
- eEBWBQUz6QLwUFcFiJutZiL/zl6wX1QNxfJDXhBrx/qw7nJ/+IaZHAA0nMgmHXCXHX3X2FSzvx1hLwf+
- ihGe8ZeMC5B84K+Obcor8H44GzUrq4HvEAr6sekvsv6aWlPKKwMyCHBL+Fb6KB0BRz+yBEbkw+KM9UW8
- 8+NzBJ4dgaqpB7WchqyJB2QqCCi0v5qOOQSOoZOQdz+X1+KZwHX399sUrDvbh1dn+uDPl47MAUCD6LDP
- LBg61YnygEVf87epGX/1C32kNwZApLwB3wYS/qcOQGGNyD4/a36R8GN4v7sUSF4ZiAoCFh0E7idLIB4I
- cGffZXDPuAPux012jQkZkInfqMvEItuq4gEUrSZN1FXkdbLN5NKLbb7Y27v73fn+UjQnVyEHAA07dZp6
- 50xwoNtWDvxZVO1fFjXwlygGkHwGoO69KW/B98l0uB6v5D009YVfLPmZSTvKICB2DIa5AzoI9E0EAlVQ
- dl+MqmEbEPgPsqScmNHTXDb9C+hFixnImzkIjmvkD/FsIMgMvkZm4xPw/j3YBS1xNy5AJ1JchypnDKSu
- z1kxaLFDDfjFD/wlcgGSBwBO9CHh33QDap5whbr6Rgq/Wf3jSBAQuwblmEDJUDiOvR+FF5LyKoxe90bB
- FgRevQDVV+3nwkSh7EazXW/YhRv9/cL0b3YMbL3vQgFNT4RlydfQf0/C89qr8K3Xl1MCaEMgcAsuRV/0
- 1JXWocUZg6iARG/YFU502B/a7NNKLbGt9XGP7ccnBwDRrAcO+P0Vvo0zyed3hZb6hM/PEX+xecbMabNi
- rgp3IBIEeJScBfvRS1A4vA1sLaNNEXIFvEvhvukuuB/LhqVBI6e5mC/qeiv9r3QJCh7pDNsp8of2Qtn7
- INzPf4zAF9CSQxg5PerxzckXm4GxOAOD61UZymbOGEWkW3+z0I5+L9nqov6tYY251TdZAIgXA/DQhH8U
- nreWwP26X9P4IsVXFn5Z85tSEBC645EFRGQQ4NhASX/Yfn0fgUB32MqjVRWqQvDrMai++EME/g2TuwJG
- TXN5mYUZWTwcjguvQt4S1LmLULYh8NVSeFbvQHAXtAnDE0dkiLHplEdHl+EqXIIRGE1/ZW6DTRYCQJuP
- LRh8owPt3da6pB8utZ0PS9zGnpqQRwJAYvN/D4I/LUTtyy/D97GiCT9rfSH8bPaz8Jsh4p8sJQKBUn20
- 7AhLu8UoGjoQ9h7WKCDwEXyrR6H6+iqNF2aLe9S7YCO+VwT+mpXD0pHMptXkh3aBxgluxbT+T/C8TL4S
- LxGx0IuJwxaAS2caf0czgpHWOBvnYRqmkjpLmKdtas4YRHYSt0EzHTjiM5ta4SdU4y924C++BRAbAGge
- Bz+B/6t5qH1xK4Lbod07Ifxif7/Q/KY2gaNQLBAQewdUK4AHoULpbBScNg55J3DTGPlLyBVwE38mPQjP
- SwitCpirNBSMmeZy4I81dvNZyJtzKhyT+H1yiqqeI8F/Cb51bm2isMAfREj4eeII34lJ1BYowwCciFn0
- aIOOWckZA6nr81acusSBdgGtxJcI/OXF6Opb/734ACA+T+atayW86/4Mz/sHyH1DyHLjwfdPDvhlm/AL
- igQBnoMibVisEKiWAH2g+Ug4e92JgiGlsBbLX0IW0paLUXXRZs3CNWUA1CgAqEuu6ANbv1tR8CT9UfI9
- gjsegOfRzxDYpWioyJPlZ30If5Hfl1siy7UFytAFR2Ee5qIbemUdZwyiwu+Bwdc60eVbYfrLNf6SXceX
- AaD+MYqu9e+D+6+bENgWCIE2DxG7YctNLPVlq/ALkkFAzGdVoUEDAVFajJ+LjoOt470oHNED9g7iC/jC
- X4HnvkmoudMXShAyFU/SPc3l5ZSCAmLUXSh4sAdsgzfAv/Z+uFcdCEWE+bkSIa0h/MXIfuhyMJEjs6XE
- /i4EAtPJIjgjazhjFJFR2WeZDcetsusZf9aIjL/kmnNGAoD8/k4Ev3sU7g/WwPdpTcjMlwffPxZ+GbxN
- NdEbQZEZg3JxUQECDAiF7WEpmY/CIYPh6G/VS8T7oVSPRfXQv8K/CeEJQqYgIwCAGaVG/ofAfs545P/h
- GXhWkMn/d4924QGEtL8YrDXkopCIwqTwAiMFqMBUXIHhuIT+Jf0rBFkCAKVbLDhnmgMV1ZFbfS1xavwl
- tgD4eScC362A54M34P2iJhTVF6AtrDYWfBm8Iwt1Hgokg4AoMMogIKyBEv11IU3OvMnIH3AD8ofn6xuJ
- diHw7vGoHO3T+Gaq3IB0TvOwDRatYCmbiby5L8L3+gYEvtXf54sW2t+FkNYQ/lEixtQlFUHUFhhGj+sw
- jbC5mWk5YxBZSeROvsWOXuu0fH95q28i7R8DABS6Eb5NZOo/Bc/69fBv94aEvCrKEPEaUc/fsD72JiB5
- fovgoOwStNBf59OHLANhq1iMogkdYe3M/FiM2kn3wLMaJksTNgIA1KBJBSyt6UqdP5LvCFFzUhNy1hQ8
- aSJN/mQZIi8vMtMPw4l6cPCwBlYfNpozRhBx6rD3LL7Bcx2WDkGrtQJWa7ne3CPU2isRACjqiowLinsb
- At+8Df+X78P35fdagQtxj1j4qyOG8PXl+3coC78geV+LHBcQdQaL9b/5fYVcMetCFI45G45zSeJ/PAuV
- p24mdwomCggaBgDSsOsME9rfow/RCKIhJqO4CaEVgh44BrNxE7qjZ1quy+wA8DPxbjI+bbYDlSz8nWB1
- 9oK9eRdYW3IhiyJYnMR4LnivVuPmBpvE7ABH8Q9AqeRU1S8Q2Pctgvs+h/+bytAuPdZQtagPAMLUr0XI
- ahMumym0WYZIxlCe66K6kMgXaKb/zfM+SMz3TIXzN9ej4PoN8L98OVyzvaFYSZPzzSgAEEMIPxNPFJ4w
- kR1g0EAmRAYHW5HzezjmkkNwPAbRvzSuIr+ZAYC59TD+g0exGeGBOLXABjHFWkL+J6kiB1kDdu6w6yb5
- /5k0vSvkg/r1Icx3AcwCAGqk52iC/0vR+rFIzD+R71LXekwfTv3fVau3N92SpSia8kd4lq2Edz1M4jIZ
- FQOw6xcv4k0C6cSkS2eUuC7dGLxCwNWHr8Z4DMfFdGsSFx7NBGfSTTtxEBPwJulkecMNC2kQoYkpeM8k
- N9XgwfyXAYCFWgYA2QpwI2SxiWMSdeT9pZDsEoi4QIE0RHCaeeZuC4syGs5Oy+FZX2OSPoNGAIA8+WJN
- wHRPHrn6cAu6HW1I/C/CREyiW9K8Qd9oVgDgdsOz8QY+wBaE19b36J+woT4AaEeGVmGiAYAMAvIQ1lpk
- kPaXLvyC5Hkv4gL5+rOwAoTFJYPsIQkAMkPk747Vvjnd1xIeHDyDXIHrMYOcg7ZNypl00npspyt6nqbU
- Hmh77hkE2D8PIKSNBAgkYwHIICA/i+CebK3lhD42ySAgYgP8LLZhCBAQ7lZkvkuTnXQmv8voC5WDgxyQ
- KUNP9MUczELnFFuTmREAakk4J+Jx/FfV/typlttrsQsQTfuLTVeyCxZEOAjwEBNRds9y2r5hFLlKIGJg
- YjZFgu8hBQBmITk4qPUnLEd3/A4zcQxOzGrOPI1/YBleo+myC1AHLymx+e9HaOLJ5f5kigYCYkJGc81y
- Qt8wki1g+X5EA+IcABh4XTxEQ0hOH+6k9iEYiCFIpsCI2TizFwcwASvI4OeW2txg43/Qim+w+S8mUCw3
- LFZzzUSNNXPUcKq/iTIEAkymsLDMNs3TTXJwsIRetcGVGItL1dZkceu9m4ozHPibj1fxMt6DpvkZANj8
- F9o/J7zmpGRnUQ4ADL7GUGsyDg6eh7MwDTNQHKe2gJk4s4kE/kasRI0q+DuhaX8O/nE02XR7zHOUPWSm
- aW70dYrahFpwsA+Ow624BeUxaguYhTMuEvIbsQqfgFtqs/Dvghb9540lpkgnzVH2klmmeaaulV0CkT7c
- Ch1wJG7HLByBvvV4YQbOsGi/gA24Fy+SqLPWZwDg6L+I/OeEP0eNIjNM80xfr9hWrNUW4BIj09Xg4GBY
- pPRhM3BmDw5gKh4jb38rQtqfq/CIdf8c5ahRZIZp3hQkQEALDhaRLXA5LsMojKkLDjY1ZwLk2z+It/AU
- 3gTqlv14WzUH/kRTzRzlqFHU1NO8KUls5GAQaAk7ynE+hmASpqjlyJuSMyzan5LGn4EnUVsX+PsaWtqv
- yPnPUY4aTb9kABDXLzoWF6vVtI7DSZiFmTGDg5mgn8nEvxZPYJu6209E/Tnwx0U4cst+OUob/dIBgEnE
- BdTGpeAVgk44Er/DbPRA74xziE3/xViDF/ABNMHfBW3Nn4t0cOAvp/1zlDbKAYBG9QuPtiQLYB7m4HgM
- hCVDfOKEn4fI71+J9+gVR/sZAESHXTb9c4G/HKWVcgAQTnJwsJTgoByTcSVG4lJ619nI745PLtLuj+Ad
- rMI6aOY++/xC+HOmf44MoRwA1CeRPhzKHDwdg8gnvwZtUJF2a4C1/nbswSKsxefqch8v87Hgi/baLPyi
- ik+OcpRWygFAdAoPDnJcoC1+jXG4BKeSS9BCrb3ZON5xL+n9qMZL2IjnsB4H1f39vLmHBZ9BgFttcZmv
- nN+fI8MoBwCxSQ4OanEBi5o21AODcRpOxgC0J1hwqEV4kycfmfLfkXC/j814HZ9hl+rrc4CPs/tEa20u
- 8cXJPjnNnyNDKQcA8UnOHBS94dTGkGQDlBMYdCUgOAadcTg6kqvQHEUEF/nkQGiNIgP08JAQu1BLHv0B
- bMP/8CEZ/DsJAn5SBZ7Ne9EYVTTX5PdEb8Sc8OfIUMoBQHIkkobk/nDFEGWgrTS4JnEB/e0kELDpteCC
- 9PDRw02PH0mw/XUFNkW5bbnTjmi0YZqa8Tk69CkHAMmTXPVY1IIvlAb/LQpBiqrIogCEXBJdAIA8RDdd
- udR2jnJkOOUAIHWSq8CK/geiCYpcCFLuSyAXhJSr7/5Sm2vkyCSUA4DGUWT9N1EDzobwUlCiBpwQ9lyl
- 3RyZgv4fwxUHs6QSBV4AAAAASUVORK5CYIIoAAAAgAAAAAABAAABACAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAAAAoAAAATAAAAGgAA
- AB4AAAAeAAAAFwAAAA4AAAAGAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABQAAABMAAAApAAAAQAAMAFgAEgBoABMAbAAOAGYAAQBYAAAASAAAADMAAAAcAAAACQAA
- AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAsAAAAmACMAYABqAKwAowDfAL4A9QDG
- AP0AxgD+AL8A+ACkAOUAbAC/ACIAhgAAAFgAAAAzAAAAEwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAAQABAAPQCCALgAwwD6AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AwwD8AHcAygAL
- AHYAAABBAAAAFwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFQApAFgAsADlAMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AKkA6wAXAIMAAABAAAAAEQAAAAEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAA
- ABwAQgB0AL0A8wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AKYA6AAJAHIAAAAxAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAgAkAGAAkwDDAPoAyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AG8AxQAAAFgAAAAdAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAALAAcALgB/
- ALIAxgD+AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AwQD7ACQAjQAAAD8AAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAADwASAD0AmADMAMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AkwDcAAIAZgAA
- ACYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABQAJgBUAK0A4gDH
- AP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8ARQCnAAAASgAAABMAAAACAAAAAQAAAAIAAAADAAAAAwAA
- AAIAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAABAAAAAgAAAAMAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAUAAAAZADoAbAC7APAAxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCv
- AO8ACQB2AAAAOAAAABcAAAAWAAAAGwAAAB4AAAAeAAAAHAAAABgAAAATAAAADQAAAAcAAAADAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAAAMAAAADQAAAAgAAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAABgAAAAYAAAADAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAIABXAIgAwgD5AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wBlAMYAAAByAAAATAAAAEEAAABFAAAASQAA
- AEkAAABHAAAAQgAAADoAAAAxAAAAJgAAABkAAAAOAAAABgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAQAAAAOAAAAGwAAACAAAAAaAAAADQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAgAAAAkAAAAQAAAAEwAAABAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAABAAAACgAEACoAdACmAMYA/QDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AL8A+wAbALEAAACIAAAAdAAAAHIAAAx6AQARfQAACXcAAABvAAAAaAAAAF4AAABRAAAAQQAA
- AC8AAAAdAAAADgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAFAAAACgAAAA2AAAAMwQAQ08DADYmAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAADCAAAAAmAAAAJgAA
- ABkAAAAKAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAA4ADgA4AJAAxADHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AIoF7wQAQtwIAH/kDACw8w0A
- vvkOAML6DgDB+QwAtu8LAJ/fBwB2xAQAPZoAAAZwAAAAWwAAAEUAAAAuAAAAGQAAAAoAAAADAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACQAA
- ABkAAAAyAAAASAAABU4IAH6YCwClogAAAQkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEAAAAJAwA5TAUAT3wAAAFAAAAANwAAACEAAAAOAAAABAAAAAAAAAAAAAAAAAAA
- AAIAAAASACAATQCnANwAxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AxgD/BDlG/wkAi/8MALb/DgDF/w8AyP8PAMr/DwDM/w8Azv8PAND/DgDS/w4A
- xPMIAHS+AQAXfAAAAFgAAAA+AAAAIwAAABAAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAA0AAAAgAAAAPAAAAFcCACBzDAC40w8A5O4BAB8lAAAAAwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAIVCQCJuwcA
- ebsAAAxdAAAARAAAACgAAAASAAAABQAAAAEAAAAEAAAAGAA0AGYAuADuAMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8ApQ//Bwdr/wsA
- oP8NAMD/DwDH/w8Ayf8PAMv/DwDN/w8A0P8OANL/DwDU/xAA1v8PAND4BwB3vQAADm4AAABKAAAALAAA
- ABQAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAPAAAAJQAA
- AEMAAABiBABFlg8A2vERAOz/BwB0dQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAoCACNACwCy9goAm+QCACR+AAAATgAAAC4AAAAWAAAADQAB
- ACAATwCCAMEA+ADHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8DWDT/CQCD/wwAsf8OAMX/DwDI/w8Ayv8PAM3/DwDP/w4A
- 0f8PANP/EADV/xAA1/8QANr/DQC96gMAOI4AAABSAAAAMQAAABYAAAAGAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEAAAAEAAAAEgAAACkAAABKAAADbAcAcbYQAOj8EQDt/w0AxcoAAAoSAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA
- ABIGAGiUDAC2/wsArPYEAD2YAAAAVQAAADoAAwA7AG4AowDFAPwAxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wC6
- Bf8GFl3/CgCY/w4Avf8PAMf/DwDK/w8AzP8PAM7/DgDR/w8A0/8PANX/EADX/xAA2f8QANv/DwDX+gcA
- Z6wAAAFWAAAAMgAAABYAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAAABIAAAArAAAATgAA
- DXUKAJ7READs/xEA7f8QAOn4AwA/QAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAADCQKAKXhDAC2/wwAs/wFAFe2AAgAegCG
- AMoAxgD+AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wJ/If8IAHr/DACr/w4AxP8PAMn/DwDL/w8A
- zv8OAND/DwDS/w8A1P8QANb/EADY/xAA2/8QAN3/DwDe/ggAhsAAAAJXAAAAMQAAABQAAAAFAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAQAAAARAAAAKwAAAE4BABN6DAC54BEA7P8RAO3/EADs/wkAj4wAAAAIAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAACAAAADAQAQmMMALT9CwCq/wkThP8BnBH2AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMcA/wUwTP8JAI//DQC5/w4AyP8PAMv/DwDN/w4Az/8PANH/DwDU/xAA1v8QANj/EADa/xAA
- 3P8QAN7/EADg/wkAicAAAARUAAAALAAAABAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACoAAABOAQAVfA0A
- wuYRAO3/EQDt/xEA7f8OAM3SAAANFAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABGAcAc7QIJXT/Aa0Q/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AaER/wcEb/8LAKP/DgDD/w8A
- yv8PAM3/DgDP/w8A0f8PANP/EADV/xAA1/8QANn/EADc/xAA3v8QAOD/EADi/wgAgLgAAAFMAAAAJQAA
- AAwAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAwAAAA4AAAAoAAAATAEAFXoNAMLmEQDt/xEA7f8RAO3/EADp9gMAPjsAAAAEAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAYAAAAiAEAKjgC6CP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AxwD/A1U3/wkAhv8NALX/DgDI/w8AzP8OAM7/DwDQ/w8A0/8QANX/EADX/xAA
- 2f8QANv/EADd/xAA4P8QAOL/EADi/gYAY6AAAABBAAAAHQAAAAcAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAMAAAAJQAAAEkBABJ2DQC94hEA
- 7f8RAO3/EQDt/xEA7P8HAHp0AAAABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAIQBgAJIAwwD7AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AuAb/BxRh/wsA
- m/8NAMH/DwDL/w4Azv8PAND/DwDS/w8A1P8QANf/EADZ/xAA2/8QAN3/EADf/xAA4f8RAOP/EADe+QMA
- MnkAAAA0AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAABAAAACgAAACAAAABEAAAMcAwAtd0RAO3/EQDt/xEA7f8RAO3/CwCnpgAABQwAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAACgAFACoAfACuAMYA/gDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AxwD/AI0A1wCRAdwAyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8CeiT/CAB9/wwAr/8OAMn/DgDO/w8A0P8PANL/DwDU/xAA
- 1v8QANj/EADa/xAA3P8QAN//EADh/xAA4/8RAOX/DgDI5wAADlcAAAAnAAAACwAAAAEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAbAAAAPQAAA2YKAJ7QEQDs/xEA
- 7f8RAO3/EQDt/w4AyMoBABIVAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAwADgA2AJEAxADHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCWANkABgN9Bw9y4AGrFv8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDE
- Af8FLU//CgCU/w0Av/8OAM3/DwDP/w8A0f8PANT/EADW/xAA2P8QANr/EADc/xAA3v8QAOD/EADi/xEA
- 5P8RAOf/CQCLuAAAAEQAAAAkAAAAFgAAABMAAAARAAAADgAAAA0AAAALAAAACQAAAAgAAAAHAAAABgAA
- AAcAAAALAAAAGQAAADgAAABeCACBvREA7f8RAO3/EQDt/xEA7f8PANvhAQAnJgAAAAMAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAAPABoARQCkANgAxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDI
- AP8AnADbAAwAcQUARqoMAKj/CSqB/wC+B/8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wGcE/8IA3T/DACp/w4AyP8PAM//DwDR/w8A
- 0/8QANX/EADX/xAA2v8QANz/EADe/xAA4P8QAOL/EQDk/xEA5v8QAOT7AwAzggAAAFAAAABCAAAAPAAA
- ADgAAAA1AAAAMgAAAC8AAAAtAAAAKgAAACkAAAAoAAAAKAAAAC4AAAA/AAAAXAUAVqQQAOv+EQDt/xEA
- 7f8RAO3/EADm8gMAPj4AAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAEQAnAFQAsADkAMgA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AKMA4gATAHQAAAt2CwCd8gwAqv8MAKj/Bkxk/wDH
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wRNPf8JAIz/DQC7/w4Azv8PANH/DwDT/xAA1f8QANf/EADZ/xAA2/8QAN7/EADg/xAA
- 4v8RAOT/EQDm/xEA6P8MALHcAAACfgAAAHQAAABrAAAAZgAAAGMAAABgAAAAXQAAAFoAAABYAAAAVgAA
- AFUAAABVAAAAWgAAAGkCAC2RDwDh+BEA7f8RAO3/EQDt/xAA7P0GAGVgAAAABQAAAAEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
- ABIAMwBeALwA8ADIAP8AyAD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wCr
- AO0AFwCMAAAAfAYAWsENAKz/DQCr/w0Aqv8MAKf/BHhA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/ALUI/wcNaf8LAKL/DgDH/w8A
- 0P8PANP/EADV/xAA1/8QANn/EADb/xAA3f8QAN//EADh/xEA4/8RAOb/EQDo/xAA6f4IAH3YCgCQ4QoA
- m9oKAJfQCQCLxwcAeb4HAGe1BgBZqwUATaIEAEGdAwA5mgMAM5gDADueBQBYsA4Az+8RAO3/EQDt/xEA
- 7f8RAO3/CQCPiAAAAQgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANADoAYwC/APQAyAD/AMgA/wDIAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AsQH0ABsDpgAABJoAABOoCwCk+A0Arv8NAKz/DQCr/w0A
- qv8MBqP/Ap0i/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AxwD/A3Aq/wkAhP8MALb/DgDO/w8A0/8QANX/EADX/xAA2f8QANv/EADd/xAA
- 3/8QAOH/EQDj/xEA5v8RAOj/EQDq/w8A2P8MALL/DwDW/xAA6f8RAOz/EQDt/xEA7f8RAO3/EQDt/xEA
- 7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/EQDt/wwAvbwAAAYOAAAAAgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAx
- AEgAwAD0AMgA/wDIAP8AyAD/AMgA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/ALMM/wgc
- dPkKAJL5CQCE/gkAjv8NALH/DQCv/w0Arf8NAKz/DQCs/w0Aq/8KGJT/AbQQ/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AwgL/BSNY/woA
- m/8NAMX/DwDS/xAA1f8QANb/EADZ/xAA2v8QAN3/EADf/xAA4f8RAOP/EQDl/xEA5/8RAOr/EQDs/wwA
- t/8OAMj/EADk/xEA7P8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA
- 7f8PANrfAQAgIgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAAAIAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAJ0AwADIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wC1C/8IJXb/CwCk/woAl/8IAHv/DACq/w0Asv8NALD/DQCv/w0A
- rv8NAK3/DQCt/w0ArP8JNnv/AMIE/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8BkBr/CAJ7/wwAsP8OAM7/EADU/xAA1v8QANj/EADa/xAA
- 3f8QAN//EADh/xEA4/8RAOX/EQDn/xEA6f8RAOz/DgDU/wwAuv8PANz/EADr/xEA7f8RAO3/EQDt/xEA
- 7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/DwDf5gMANTYAAAAEAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACAAAAAYAAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX
- AAcAwADgAMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AuQj/Byty/wsA
- qP8LAKf/CQCN/wkAh/8MALX/DQCz/w0Asv8NALD/DQCv/w0Arv8NAK7/DQCu/wwArf8GYVb/AMcA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDG
- AP8EQkb/CgCT/w0Awv8QANP/EADW/xAA2P8QANr/EADd/xAA3/8QAOH/EADj/xEA5f8RAOf/EQDp/xEA
- 6/8QAOz/CQCOzAsAp8YNAMTSDwDk3xAA6u0QAOz4EQDt/xEA7f8RAO3/EQDt/xEA7f8RAOz9EADn5gsA
- o5wCAC0lAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAAIAAAAEgAAABgAAAAVAAAADAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAgCbALIAyAD/AMgA/wDIAP8AyAD/AMgA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/ALsH/wcub/8LAKn/DACx/wsAof8IAIL/CwCg/w0Atv8NALT/DQCz/w0A
- sv8NALH/DQCw/w0Ar/8NAK//DQCv/wwCrP8DijT/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wCtDP8HCXD/CwCq/w8Azv8QANb/EADY/xAA
- 2v8QANz/EADe/xAA4P8QAOL/EQDl/xEA5/8RAOn/EQDr/xEA7f8IAHeeAAAAKwAAAgwAAA4IAAARDQAA
- DRIBAB4XAwA8IgQAQCsEAEArBAA/JgIAJBcAAAwKAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAAAABsAAAAqAAAALAAACyQCACUfAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAACwAKgC9AOYAyAD/AMgA/wDIAP8AyAD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDBAPkEMUfJCAB3tggA
- f6MHAHOUBQBMlAQARaYNALX+DQC3/w0Atv8NALT/DQCz/w0Asv8NALH/DQCx/w0Asf8NALH/DQCx/wsO
- ov8BrRb/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AxwD/AMgA/wNkMv8JAIv/DQC+/w8A1P8QANj/EADa/xAA3P8QAN7/EADg/xAA4v8RAOX/EQDn/xEA
- 6f8RAOv/EQDt/w0AxtoAAAA3AAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAA
- ABAAAAAkAAAAOwAAAEUCAClTDACupwEAEBQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACACIAKwGKEMIAwgX/AMgA/wDI
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AwAD0AD0AaAAAABQAAAAEAAAAAgAAABEAAAA3BQBKmA4Auv8OALj/DQC3/w0A
- tv8NALT/DQCz/w0As/8NALL/DQCy/w0Asv8NALL/DQCy/wonjf8Avgj/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8AyAD/AMAD/wYaYv8LAKL/DgDM/xAA
- 2P8QANr/EADc/xAA3v8QAOD/EADi/xEA5P8RAOf/EQDp/xEA6/8RAO3/EADs/AIAKFkAAAAaAAAAAwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAAAAUAAAALAAAAEgAAAJaBgBfjxAA5PEGAFhVAAAABgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEAAAAHAQAVKgwZqewGXlrpAJgE2AC8APIAxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/ALgA6wA4AFwAAAAQAAAAAgAA
- AAAAAAACAAAAGQAAAEMJAIPKDgC7/w4Auf8OALj/DQC3/w0Atv8NALX/DQC0/w0AtP8NALP/DQCz/w0A
- tP8NALT/DQC0/wdHcf8AxgH/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMcA/wDIAP8AyAD/Aogf/wkAgv8NALj/DwDV/xAA2v8QANz/EADe/xAA4P8QAOL/EQDk/xEA
- 5v8RAOn/EQDr/xEA7f8RAO//BwBskgAAACQAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAJAAAAGQAA
- ADQAAABTAAAMbgoAmcIRAO/+DAC1sAAAAAoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAPBgBfeA8A
- 0/4KAJXNAQsQcwApAGoATgB4AGsAiACMAKQAngDCAL0A3wDGAPgAxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/gCaAMEAIQA8AAAACwAAAAIAAAAAAAAAAAAAAAUAAAAiAAAFUQ0As/IOALz/DgC7/w4A
- uf8OALj/DQC3/w0Atv8NALX/DQC1/w0Atf8NALX/DQC1/w0Atf8NALX/DAG0/wVvTv8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDIAP8AxgD/BThO/wsA
- mv8OAMn/DwDZ/xAA3P8QAN7/EADg/xAA4v8RAOT/EQDm/xEA6f8RAOv/EQDt/xEA7/8MAK/GAAAALgAA
- AAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAB0AAAA6AAAAWwIAIoQNAL/gEgDx/xEA6PACACgrAAAAAwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAUcDACw0BAA1P8NALTmAgAhfAAAAEsAAAArAAAAEwAA
- AAcABgAIABYAEQAyAC8ATQBUAGUAdgCAAJMAkACkAI8ApAB1AIwAOABGAAIADwAAAAQAAAAAAAAAAAAA
- AAAAAAAAAAAACQAAACoCACp0DgC//w4Avf8OALz/DgC7/w4Auf8OALj/DQC3/w0At/8NALb/DQC2/w0A
- tv8NALb/DQC2/w0At/8NALf/DQaw/wKYKf8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDHAP8AyAD/AMgA/wDIAP8BphD/CAZ4/wwAsf8PANT/EADc/xAA3v8QAOD/EADi/xEA
- 5P8RAOb/EQDp/xEA6/8RAOz/EQDv/xAA4O4AAAw8AAAAEAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAsAAAAfAAAAPgAA
- AGEEAEadEADe8xIA8f8RAPD/CAB5dAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAoDADZMDwDQ+Q8A0/8OAMb1BABAlAAAAFAAAAAtAAAAEwAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAMwUAVZwOAMD/DgC//w4A
- vf8OALz/DgC7/w4Auv8OALn/DgC4/w4AuP8OALj/DQC3/w0At/8OALj/DgC4/w4Auf8OALn/DBSk/wGz
- Ev8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDIAP8AyAD/AMgA/wDI
- AP8DWzn/CgCR/w4Axf8PANv/EADe/xAA4P8QAOL/EQDk/xEA5v8RAOn/EQDr/xEA7P8RAO//EQDx/gMA
- N2AAAAAXAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAIAAAALAAAAIAAAAEAAAABlBwBpsREA7fwSAPH/EgDx/w4AxMQAAAgQAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABIJAIOeDwDT/w8A0/8OAM/8BgBapgAA
- AFIAAAAuAAAAEwAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAABMAAAA7CAB/wA4Awv8OAMD/DgC//w4Avf8OALz/DgC7/w4Auv8OALr/DgC5/w4A
- uf8OALn/DgC5/w4Auf8OALn/DgC6/w4Auv8OALv/CjGK/wDCBP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wC6Bv8HF2j/CwCp/w8A0/8QAN7/EADg/xAA
- 4v8RAOT/EQDm/xEA6f8RAOv/EQDs/xEA7/8RAPH/BwBmiAAAAB0AAAADAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAB8AAABAAAACZggA
- eroRAO/+EgDx/xIA8f8RAOryAwA1NQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABwEAEygNAMDjDwDT/w8A0/8PAND9BwBlrQAAAVIAAAAsAAAAEgAAAAQAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAGAAAAEILAKXfDgDD/w4A
- wf8OAMD/DgC//w4Avf8OALz/DgC8/w4Au/8OALr/DgC6/w4Auv8OALr/DgC6/w4Auv8OALv/DgC7/w4A
- vP8NALz/B1pl/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wJ/Jf8JAIj/DQC//w8A2/8QAOD/EADi/xEA5P8RAOb/EQDp/xEA6/8RAOz/EQDv/xEA
- 8f8KAJGsAAAAIwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAAAkAAAAdAAAAPgAAAGQIAH+9EQDw/hIA8f8SAPH/EQDw/ggAfXcAAAAGAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAUATGAPANL8DwDT/w8A
- 0/8PANH+BwBmrAAAAE4AAAAqAAAAEAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAMAAAAeAAAFSw0Av/gOAMT/DgDD/w4Awf8OAMD/DgC//w4Avv8OAL3/DgC8/w4A
- vP8OALv/DgC7/w4Au/8OALv/DgC7/w4AvP8OALz/DgC9/w4Avv8NArv/BIU9/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMYA/wUwVf8LAKH/DgDQ/xAA
- 4P8QAOL/EQDk/xEA5v8RAOn/EQDr/xEA7P8RAO//EQDx/w0AvcsAAAAoAAAACAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAGgAAADoAAABhCAB3uBEA
- 8P4SAPH/EgDx/xIA8f8NALezAAADDAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAADAAAAEQkAiJ8PANP/DwDT/w8A0/8PANL+BgBbowAAAEoAAAAmAAAADQAA
- AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACICACJkDgDG/g4A
- xf8OAMT/DgDD/w4Awf8OAMD/DgC//w4Avv8OAL7/DgC9/w4Avf8OALz/DgC8/w4AvP8OAL3/DgC9/w4A
- vf8OAL7/DgC//w4AwP8MDLP/Aace/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AaIS/wgCf/8MALn/DwDb/xAA4v8RAOX/EQDn/xEA6f8RAOv/EQDs/xEA
- 7/8RAPH/DwDV5AAABC8AAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAABAAAABQAAABcAAAA2AAAAXQcAa7ARAO/+EgDx/xIA8f8SAPH/EADc3gEAGR0AAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAKHQwA
- tdMPANP/DwDT/w8A0/8OAND8BQBKlgAAAEUAAAAhAAAACgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAGAAAAJgQAN3gPAMj/DwDH/w4Axf8OAMT/DgDD/w4Awv8OAMH/DgDA/w4A
- v/8OAL//DgC+/w4Avv8OAL7/DgC+/w4Avv8OAL7/DgC//w4Av/8OAMD/DgDB/w4Awv8LIp7/ALwK/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/BFRA/woA
- mP8OAMz/EADh/xEA5f8RAOf/EQDp/xEA6/8RAO3/EQDv/xEA8f8RAO31AQAQOwAAAAwAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAASAAAAMAAAAFgFAFKhEQDt/BIA
- 8f8SAPH/EgDx/xEA6/IDAD48AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAgApOw4AyO0PANP/DwDT/w8A0/8OAMv4AwA4hQAA
- AD4AAAAcAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAqBQBQjA8A
- yf8PAMj/DwDH/w4Axf8OAMT/DgDD/w4Awv8OAMH/DgDA/w4AwP8OAL//DgC//w4Av/8OAL//DgC//w4A
- v/8OAMD/DgDA/w4Awf8OAML/DgDD/w4Aw/8IRH7/AMYB/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8Atwj/CBFw/wwAsf8PANr/EQDl/xEA5/8RAOn/EQDr/xEA
- 7f8RAO//EgDx/xIA8/8CACFMAAAAFQAAAAcAAAAGAAAABQAAAAQAAAADAAAAAgAAAAIAAAABAAAAAQAA
- AAEAAAAEAAAAEAAAACoAAABQBAA8kREA5/gSAPH/EgDx/xIA8f8RAO/7BgBnYQAAAAYAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAALBQBQYQ8A0foPANP/DwDT/w8A0/8NAL7uAQAdcAAAADYAAAAWAAAABgAAAAEAAAAAAAAAAAAA
- AAAAAAABAAAAAQAAAAIAAAACAAAADAAAADAGAGCgDwDK/w8Ayf8PAMj/DwDH/w4Axf8OAMT/DgDD/w4A
- wv8OAML/DgDB/w4Awf8OAMD/DgDA/w4AwP8OAMD/DgDB/w4Awf8OAMH/DgDC/w4Aw/8OAMT/DgDF/w4A
- xf8GbVb/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8Cdiv/CgCP/w4Ax/8QAOP/EQDn/xEA6f8RAOv/EQDt/xEA7/8SAPH/EgDz/wQAO20AAAA0AAAAKAAA
- ACYAAAAkAAAAIAAAAB4AAAAcAAAAGgAAABgAAAAYAAAAGAAAAB0AAAAuAAAATQEAHHwPANfvEgDx/xIA
- 8f8SAPH/EQDw/gkAioQAAAIIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAEPCAB1ig8A0/8PANP/DwDT/w8A
- 0/8MAK/hAAAKXgAAADQAAAAcAAAAEwAAABEAAAARAAAAEwAAABQAAAAWAAAAGgAAABwAAAAnAAAASQgA
- dLYPAMz/DwDK/w8Ayf8PAMj/DwDH/w4Axf8OAMX/DgDE/w4Aw/8OAML/DgDC/w4Awv8OAML/DgDC/w4A
- wv8OAML/DgDC/w4Aw/8OAMP/DgDE/w4Axf8OAMb/DwDG/w4Fwf8DkzL/AMgA/wDIAP8AyAD/AMgA/wDH
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDCAv8GKV7/DACp/w8A2f8RAOf/EQDp/xEA
- 6/8RAO3/EQDv/xIA8f8SAPP/BQBFkAAAAF4AAABVAAAAUwAAAFAAAABMAAAASQAAAEYAAABEAAAAQgAA
- AEIAAABCAAAASAAAAFgAAAh0DQC84BIA8f8SAPH/EgDx/xIA8f8MALCpAAAFCwAAAAEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAQAAAYVCgCZsw8A0/8PANP/DwDT/w8A0/8JAIXEAAAAXAAAAEYAAAA7AAAAOQAA
- ADkAAAA7AAAAPgAAAEAAAABDAAAARwAAAFIAAABuCAB8yg8Azf8PAMz/DwDK/w8Ayf8PAMj/DwDH/w4A
- xv8OAMX/DgDF/w4AxP8OAMP/DgDD/w4Aw/8OAMP/DgDD/w4Aw/8OAMP/DgDE/w4AxP8OAMX/DgDG/w8A
- x/8PAMj/DwDJ/w0StP8Brxf/AMgA/wDIAP8AyAD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wGWGv8JAob/DQDB/xAA4/8RAOn/EQDr/xEA7f8RAO//EgDx/xIA8/8HAGa4BQBJqAQA
- QZ4DADeXAgApjAEAFYAAAAZ6AAAFdgAAA3IAAAFwAAAAbwAAAHAAAAF0AAAHgQsAnNERAPD/EgDx/xIA
- 8f8SAPH/DgDQzgEAEBUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAABAhDQC31g8A
- 0/8PANP/DwDT/w8A0v8GAFywAAAAcgAAAGkAAABnAAAAaAAAAGoAAABsAAAAbgAAAXIAAAZ3AAALggAA
- DJgJAIjeDwDP/w8Azf8PAMz/DwDK/w8Ayf8PAMj/DwDH/w8Ax/8PAMb/DgDF/w4Axf8OAMX/DgDE/w4A
- xP8OAMT/DgDF/w4Axf8OAMX/DgDG/w8Axv8PAMf/DwDI/w8AyP8PAMr/DwDK/wstmv8Avwf/AMgA/wDI
- AP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wVGSv8LAKH/DwDV/xAA
- 6f8RAOz/EQDt/xEA8P8SAPH/EgDz/w8A0v8QAN//EgDw/xIA8f8SAPH/EgDx/xEA7fwQAOT2DwDX7w4A
- y+oOAMToDgC+5g4AxukQAOD1EQDw/xIA8f8SAPH/EgDx/xAA5+wCAC4uAAAAAwAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgCACs/DwDL8Q8A0/8PANP/DwDT/w4A0P0LAKPgCQCI0gkA
- f84JAIfRCQCO1AoAm9sMAKjkDACy7A0Av/INAMH4DACq/QwAuP8PAND/DwDP/w8Azf8PAMz/DwDL/w8A
- yv8PAMn/DwDI/w8Ax/8PAMf/DwDG/w8Axv8OAMb/DgDG/w4Axv8OAMb/DwDG/w8Axv8PAMf/DwDH/w8A
- yP8PAMn/DwDJ/w8Ayv8PAMz/DwDM/whSdv8AxwD/AMgA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/ALEL/wgKev8NALr/EADj/xEA7P8RAO7/EQDw/xIA8v8SAPP/DwDT/xAA
- 3/8SAPD/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA
- 8f8RAO/7BgBbVgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
- AA0GAF5yDwDS/g8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w4A
- y/8MAK3/DAC5/w8A0f8PAND/DwDP/w8Azv8PAMz/DwDL/w8Ayv8PAMn/DwDJ/w8AyP8PAMf/DwDH/w8A
- x/8PAMf/DwDH/w8Ax/8PAMf/DwDH/w8AyP8PAMj/DwDJ/w8Ayv8PAMr/DwDL/w8Azf8PAM7/DgHM/wV9
- Sv8AyAD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/A2g1/woA
- mP8OAND/EADq/xEA7v8RAPD/EgDy/xIA9P8PANT/EADg/xIA8P8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA
- 8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EQDw/gkAiIIAAAEIAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAhAJAI2eDwDT/w8A0/8PANP/DwDT/w8A
- 0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DgDM/wwAr/8NALr/DwDS/w8A0f8PAND/DwDP/w8A
- zv8PAM3/DwDM/w8Ay/8PAMr/DwDJ/w8Ayf8PAMj/DwDI/w8AyP8PAMj/DwDI/w8AyP8PAMn/DwDJ/w8A
- yf8PAMr/DwDL/w8Ay/8PAM3/DwDO/w8Az/8PAND/DgjF/wKkI/8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AwQP/Bx1q/wwAsv8PAOH/EQDu/xEA8P8SAPL/EgD0/wwA
- rc4QANrnEgDw/hIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xEA
- 7fQIAH9wAAAEBwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAACAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABAAABxEKAJCcDwDS/A8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A
- 0/8PAM3/DQCy/w0AuP8PANT/DwDS/w8A0f8PAND/DwDP/w8Azv8PAM3/DwDM/w8Ay/8PAMv/DwDK/w8A
- yv8PAMr/DwDJ/w8Ayf8PAMn/DwDJ/w8Ayv8PAMr/DwDL/w8Ay/8PAMz/DwDN/w8Azv8PAM//DwDQ/w8A
- 0f8PANL/DB6v/wC6DP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8CjCD/CQCP/w4Ayv8QAOr/EQDx/xIA8v8SAPT/BQBLagAAARIBACAQBAA3KgQAREEGAGhSCABvYggA
- cnIJAIWCCwCjjgsAp5YMAKeWCwCmkgkAhn8IAG5dAgAgFwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAUAAAAJAAAACgAAAAgAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAAAMAAAAEAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYEAD09CQCEigsA
- orINALnBDQC6xA0AuL8MALS6CgCVrAkAi5oJAIiLCAB1eQYAV2gEAEJnCAB9sxAA1f8PANT/DwDT/w8A
- 0f8PAND/DwDP/w8Az/8PAM7/DwDN/w8Azf8PAMz/DwDL/w8Ay/8PAMv/DwDL/w8Ay/8PAMv/DwDL/w8A
- y/8PAMz/DwDN/w8Azf8PAM7/DwDP/w8A0P8PANH/DwDS/w8A0/8PANP/CkCM/wDEA/8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDGAP8FPVP/CwCp/w8A3f8RAPD/EgDz/xIA
- 9P8EAERZAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAALAAAAFgAAABwAAAAYAAAADQAAAAQAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAwAAAAPAAAADAAA
- AAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAIAAAACAAAAAgAAAAIAAAABAAAAAQAA
- AAAAAAAAAAAABAAAACAGAFyMEADW/xAA1f8PANT/DwDT/w8A0v8PANH/DwDQ/w8Az/8PAM7/DwDO/w8A
- zf8PAM3/DwDM/w8AzP8PAMz/DwDM/w8AzP8PAMz/DwDN/w8Azf8PAM7/DwDO/w8Az/8PAND/DwDR/w8A
- 0v8PANL/DwDU/xAA1f8PANT/B2dk/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wGpEP8ICIH/DQDC/xEA6v8SAPP/EgD1/wMAM0UAAAAJAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAEQAA
- ACMAAAAxAAAAMAEAEisDADcoAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAIAAAAJAAAAFgAAACAAAAAhAAAAFgAAAAgAAAACAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAGwUATHcQANj/EADW/xAA
- 1f8PANT/DwDT/w8A0v8PANH/DwDQ/w8A0P8PAM//DwDP/w8Azv8PAM7/DwDO/w8Azv8PAM7/DwDO/w8A
- zv8PAM7/DwDO/w8Az/8PAM//DwDQ/w8A0f8PANL/DwDS/w8A0/8QANT/EADW/w8A1/8PBNH/BI87/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wNgPP8LAJ//DwDZ/xEA
- 8f8RAPP6AQAUMwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAAACQAAABgAAAAvAAAARAAAAEkEAElrDAC9sgEAERMAAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgFAFJGAwAwTwAA
- ADoAAAAzAAAAHwAAAA0AAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEAAAAWAwAsXg8A2f4QANj/EADX/xAA1f8PANT/DwDT/w8A0/8PANL/DwDR/w8A
- 0P8PAND/DwDQ/w8Az/8PAM//DwDP/w8Az/8PAM//DwDP/w8Az/8PAND/DwDQ/w8A0P8PANH/DwDS/w8A
- 0/8PANP/EADU/xAA1f8QANb/DwDX/xAA2f8OEMX/Aa4Z/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AL0F/wgYcf8NALv/EQDp/xAA5+oAAAwmAAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA4AAAAgAAAAOgAA
- AFQBABBmCgCXthEA8PgEAEZFAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABxcMAL3CBwB2mwAAB1QAAABCAAAAKAAAABMAAAAGAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBABRADwDY/BAA
- 2f8QANj/EADX/xAA1v8QANX/DwDU/w8A0/8PANP/DwDS/w8A0v8PANH/DwDR/w8A0f8PANH/DwDQ/w8A
- 0P8PANH/DwDR/w8A0f8PANH/DwDS/w8A0v8PANP/DwDU/xAA1f8QANX/EADW/xAA1/8PANj/EADa/xAA
- 2/8MKav/AMAH/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AoMm/woA
- lv8PANP/DQDG0QAAABoAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAAAYAAAASAAAAKQAAAEYAAABiBAA7jg8A1ekSAPT/CgCWjgAAAAgAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACQMA
- NEQPAOb2DAC72AIAJncAAABPAAAAMgAAABkAAAAJAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAOAMrnEADa/xAA2f8QANj/EADX/xAA1v8QANX/EADV/w8A
- 1P8PANP/DwDT/w8A0v8PANL/DwDS/w8A0v8PANL/DwDS/w8A0v8PANL/DwDS/w8A0/8PANP/DwDT/w8A
- 1P8QANX/EADW/xAA1v8QANf/EADY/w8A2f8QANr/EADc/w8A3P8JT4L/AMYB/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxgD/BjJd/wwAsf8KAJizAAAAFQAAAAEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAHAAAAFgAAADAAAABQAAAFbwgA
- d7YRAO77EgD0/w4A0s8BAA8UAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAEAgAhY8QAOz/DwDe9AUAVJwAAABaAAAAOgAA
- AB4AAAAMAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAJwsA
- osYQANz/EADb/xAA2f8QANn/EADX/xAA1/8QANb/EADV/xAA1f8PANT/DwDU/w8A0/8PANP/DwDT/w8A
- 0/8PANP/DwDT/w8A0/8PANP/DwDU/w8A1P8QANX/EADV/xAA1v8QANf/EADX/xAA2P8QANn/DwDa/xAA
- 2/8QANz/EADe/w8B3P8FeVX/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8BohX/CgWL/wYAYZoAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAACAAAACAAAABkAAAA1AAAAVwEAF4AMALLaEQDz/xIA9P8RAO30AwA7OwAAAAQAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAGAAAMHw0Ax9AQAOz/EADq/gkAj8MAAApnAAAAQQAAACIAAAANAAAAAwAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAeCAB6nxAA3f8QANz/EADb/xAA2v8QANn/EADY/xAA
- 1/8QANf/EADW/xAA1f8QANX/EADV/xAA1P8QANT/EADU/xAA1P8QANT/EADU/xAA1f8QANX/EADV/xAA
- 1v8QANb/EADX/xAA2P8QANj/EADZ/xAA2v8PANv/EADc/xAA3f8QAN//EADg/w8I1P8Cni3/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8EVEb/AwAsjAAAAB8AAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAkAAAAbAAAAOAAAAFwDADSSDwDX7hIA
- 9P8SAPT/EQDz/ggAgnsAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAKAwA3Rg8A5/cQAOz/EADs/w0A
- v+ECAB93AAAARgAAACQAAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
- ABUFAEpwEADe/xAA3f8QANz/EADb/xAA2v8QANr/EADZ/xAA2P8QANf/EADX/xAA1v8QANb/EADW/xAA
- 1v8QANX/EADV/xAA1f8QANb/EADW/xAA1v8QANb/EADX/xAA1/8QANj/EADZ/xAA2f8QANr/EADb/w8A
- 3P8QAN3/EADe/xAA3/8QAOH/EADi/w4awf8BuBD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wC3CP4AFAaTAAAAOgAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAAJAAAAHAAAADoAAABeBQBInRAA5/gSAPT/EgD0/xIA8/8NAL65AAAIDQAAAAEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAIAAAAPCAB+hRAA7P8QAOz/EADs/w4A1vADAC+CAAAASAAAACYAAAAPAAAABAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAFD0PAN36EADf/xAA3v8QAN3/EADc/xAA
- 2/8QANr/EADZ/xAA2f8QANj/EADY/xAA2P8QANf/EADX/xAA1/8QANf/EADX/xAA1/8QANf/EADX/xAA
- 2P8QANj/EADZ/xAA2f8QANr/EADb/xAA2/8QANz/DwDd/xAA3v8QAN//EADg/xAA4f8RAOP/EQDk/ws4
- oP8AxAP/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wB8ANAAAABeAAAAIAAA
- AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACAAAABwAAAA7AAAAYAYAV6YRAO78EgD0/xIA
- 9P8SAPT/EADg4AIAHx8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAYXDAC8whAA
- 7P8QAOz/EADs/w8A3PQDADqJAAAASAAAACUAAAAOAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAHAAABJg0Au9UQAOD/EADf/xAA3v8QAN3/EADc/xAA2/8QANv/EADa/xAA2v8QANn/EADZ/xAA
- 2f8QANj/EADY/xAA2P8QANj/EADY/xAA2P8QANn/EADZ/xAA2f8QANr/EADa/xAA2/8QANz/EADc/xAA
- 3f8PAN7/EADf/xAA4P8QAOH/EADi/xEA4/8RAOX/EADl/whhc/8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMQA/AAuAJUAAABCAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAcAAAAaAAAAOQAAAF8GAF+qEQDu/BIA9P8SAPT/EgD0/xEA7PIEAEM9AAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYBAB8tDwDa5BAA7P8QAOz/EADs/w8A4PYEAD+MAAAARwAA
- ACQAAAAMAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAaCAB9mxAA4f8QAOD/EADf/xAA
- 3v8QAN3/EADd/xAA3P8QANv/EADb/xAA2v8QANr/EADa/xAA2v8QANn/EADZ/xAA2f8QANn/EADa/xAA
- 2v8QANr/EADa/xAA2/8QANv/EADc/xAA3f8QAN3/EADe/w8A3/8QAOD/EADh/xAA4v8RAOP/EQDk/xEA
- 5f8RAOf/EAPi/wWKRf8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AJwA4gAD
- AGgAAAAoAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAFwAAADYAAABdBgBbpxEA7/wSAPT/EgD0/xIA
- 9P8RAPL6BgBmWgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAoEAENODwDn9hAA7P8QAOz/EADs/w8A4PYEAD2JAAAARAAAACEAAAAKAAAAAgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQAAAA8DADRWEADi/hAA4v8QAOH/EADg/xAA3/8QAN7/EADd/xAA3f8QANz/EADc/xAA
- 2/8QANv/EADb/xAA2/8QANv/EADb/xAA2/8QANv/EADb/xAA2/8QANz/EADc/xAA3P8QAN3/EADe/xAA
- 3v8QAN//DwDg/xAA4f8QAOL/EQDj/xEA5P8RAOX/EQDm/xEA5/8RAOn/Dw/U/wKqIP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AEsArAAAAEwAAAAVAAAAAQAAAAAAAAABAAAABQAA
- ABQAAAAyAAAAWQUAU6ERAO77EgD0/xIA9P8SAPT/EQDz/AgAfHIAAAEGAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAwHAGpwEADr/BAA7P8QAOz/EADs/w8A
- 3fQDADGAAAAAQAAAAB0AAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAABicOAMfcEQDj/xAA
- 4v8QAOH/EADg/xAA4P8QAN//EADe/xAA3v8QAN3/EADd/xAA3P8QANz/EADc/xAA3P8QANz/EADc/xAA
- 3P8QANz/EADc/xAA3f8QAN3/EADe/xAA3v8QAN//EADf/xAA4P8PAOH/EADi/xEA4/8RAOT/EQDl/xEA
- 5v8RAOf/EQDo/xEA6v8RAOv/DSi5/wC+Cv8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AtADyAAwAfgAAADwAAAAUAAAADQAAAA8AAAAaAAAAMgAAAFUDADyTEQDt+hIA9P8SAPT/EgD0/xEA
- 8/4JAJKIAAAACAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAwAAAA4IAIiLEADr/hAA7P8QAOz/EADs/w4A2PACACV0AAAAOgAAABoAAAAIAAAAAgAA
- AAEAAAABAAAAAgAAAAIAAAAFAAAAGggAeZYRAOT/EQDj/xAA4/8QAOL/EADh/xAA4P8QAOD/EADf/xAA
- 3/8QAN7/EADe/xAA3v8QAN7/EADd/xAA3f8QAN3/EADe/xAA3v8QAN7/EADe/xAA3v8QAN//EADf/xAA
- 4P8QAOH/EADh/xAA4v8RAOP/EQDk/xEA5f8RAOb/EQDn/xEA6P8RAOn/EQDr/xEA7P8RAO3/CkyP/wDG
- Af8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AbADPAAAAeQAAAEkAAAA0AAAANQAA
- AEIAAABaAgAoiBAA4PQSAPT/EgD0/xIA9P8RAPT/CwConAAABQkAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABBIKAKClEADs/xAA
- 7P8QAOz/EADs/w0AyOYBABNnAAAAPAAAACQAAAAaAAAAGAAAABgAAAAaAAAAGwAAAB4AAAAqAgAkXRAA
- 4PoRAOX/EQDk/xEA4/8QAOL/EADi/xAA4f8QAOD/EADg/xAA4P8QAN//EADf/xAA3/8QAN//EADf/xAA
- 3/8QAN//EADf/xAA3/8QAN//EADg/xAA4P8QAOH/EADh/xAA4v8QAOL/EADj/xEA5P8RAOX/EQDm/xEA
- 5/8RAOj/EQDp/xEA6v8RAOz/EQDt/xEA7v8QAO3/BnZf/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wC/APwAHwC2AAAAhgAAAGgAAABkAAAAbQEAGYgPANLsEgD0/xIA9P8SAPT/EgD0/wwA
- tLAAAAgOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAACxgMALe9EADs/xAA7P8QAOz/EADs/wsAr9YAAAdoAAAATwAA
- AEQAAABCAAAAQgAAAEMAAABGAAAASAAAAE8AAABhCwCh0hEA5v8RAOX/EQDk/xEA5P8RAOP/EADi/xAA
- 4v8QAOH/EADh/xAA4f8QAOD/EADg/xAA4P8QAOD/EADg/xAA4P8QAOD/EADg/xAA4P8QAOH/EADh/xAA
- 4v8QAOL/EQDj/xEA4/8QAOT/EQDl/xEA5v8RAOf/EQDo/xEA6f8RAOr/EQDr/xEA7P8RAO3/EQDv/xEA
- 8P8QB+b/A5s0/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCKCvEEAUTUBgBdwggA
- dr0JAIvIDwDR7RIA9P8SAPT/EgD0/xIA9P8OAM7IAQAWFwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgEA
- FiQNAMjTEADs/xAA7P8QAOz/EADs/wkAj8gAAAZ7AAAAcAAAAG8AAABvAAAAcAAAAHIAAAB1AAAKfAEA
- G4sFAFm6EADn/xEA5v8RAOb/EQDl/xEA5P8RAOT/EQDj/xEA4/8QAOL/EADi/xAA4f8QAOH/EADh/xAA
- 4f8QAOH/EADh/xAA4f8QAOH/EADi/xAA4v8QAOL/EQDj/xEA4/8RAOT/EQDk/xAA5f8RAOb/EQDn/xEA
- 6P8RAOn/EQDq/xEA6/8RAOz/EQDt/xEA7v8RAO//EQDx/xIA8v8PGNL/AbUV/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMYA/wY5Wf8MAK7/EADi/xIA8v8SAPT/EgD0/xIA9P8SAPT/EADk5AIA
- JCYAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACAIAKzcPAN/rEADs/xAA7P8QAOz/EADs/w8A
- 4PcNAMnqDQC/5g0AxOgNAMzrDwDX8Q8A5foQAOv+EADn/g8A1P8PAN3/EQDo/xEA5/8RAOb/EQDm/xEA
- 5f8RAOX/EQDk/xEA5P8RAOP/EQDj/xEA4/8QAOL/EADi/xAA4v8QAOL/EADi/xEA4/8RAOP/EQDj/xEA
- 4/8RAOT/EQDk/xEA5f8RAOb/EADm/xEA5/8RAOj/EQDp/xEA6v8RAOv/EQDs/xEA7f8RAO7/EQDv/xEA
- 8P8SAPH/EgDz/xIA9P8MNq3/AMMF/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AacR/wkG
- hv8OAMf/EQDt/xIA8/8SAPT/EgD0/xAA6/EEAEI+AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAACAAAACgUAU1gPAOj4EADs/xAA7P8QAOz/EADs/xAA7P8QAOz/EADs/xAA7P8RAO3/EQDt/xEA
- 7f8RAOv/DwDi/w4A0f8QAOn/EQDp/xEA6P8RAOf/EQDn/xEA5v8RAOX/EQDl/xEA5f8RAOT/EQDk/xEA
- 5P8RAOT/EQDk/xEA5P8RAOT/EQDk/xEA5P8RAOT/EQDl/xEA5f8RAOb/EQDm/xEA5/8QAOf/EQDo/xEA
- 6f8RAOr/EQDr/xEA7P8RAO3/EQDu/xEA7/8RAPD/EgDx/xIA8v8SAPT/EgD1/xEA8PkIYHD9AMcA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/BFxA/wsAo/8PANv/EQDx/xIA9P8QAOrqBABUSQAA
- AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAcAc3UQAOv9EADs/xAA
- 7P8QAOz/EADs/xAA7P8QAOz/EADs/xEA7f8RAO3/EQDt/xEA7P8QAOj/DwDZ/w8A3f8RAOr/EQDp/xEA
- 6f8RAOj/EQDn/xEA5/8RAOb/EQDm/xEA5v8RAOX/EQDl/xEA5f8RAOX/EQDl/xEA5f8RAOX/EQDl/xEA
- 5v8RAOb/EQDm/xEA5/8RAOf/EQDo/xAA6P8RAOn/EQDq/xEA6/8RAOz/EQDt/xEA7v8RAO//EQDw/xIA
- 8f8SAPL/EgDz/xIA9P8SAPb/CAB+fAMDNjgAnAW7AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AvQX/BxVu9gsApOUNAMLECQCLgAIAJh4AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAACAAACCgcAb2oPAOPtEADs/xAA7P8QAOz/EADs/xAA7P8QAOz/EQDt/xEA
- 7f8RAO3/EQDt/xEA6/8QAOX/DgDS9xAA6PsRAOv/EQDq/xEA6f8RAOn/EQDo/xEA6P8RAOf/EQDn/xEA
- 5/8RAOf/EQDm/xEA5v8RAOb/EQDm/xEA5v8RAOf/EQDn/xEA5/8RAOj/EQDo/xEA6P8RAOn/EADq/xEA
- 6/8RAOv/EQDs/xEA7f8RAO7/EQDv/xEA8P8RAPH/EgDy/xIA8/8SAPT/EgD1/w8A1tIAAAwUAAAAAgAZ
- ABYAuwDdAMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AhALWAAABYQAAACMAAAAEAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAEA
- GxUGAF5VCACDggsAp5ULAKmYCgClkgkAlY0IAHl/BwB3bgcAcl0FAFNMBABAOAMAOCMAAAwaBwBzfhAA
- 7P8RAOv/EQDr/xEA6v8RAOr/EQDp/xEA6f8RAOj/EQDo/xEA6P8RAOj/EQDo/xEA6P8RAOj/EQDo/xEA
- 6P8RAOj/EQDo/xEA6f8RAOn/EQDq/xEA6v8QAOv/EQDs/xEA7P8RAO3/EQDu/xEA7/8RAPD/EQDw/xIA
- 8v8SAPP/EgD0/xIA9f8RAPT6BABJRAAAAAQAAAAAAAAAAAA9ADYAxgD0AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDFAP4ANACaAAAARAAAABAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAUWDAC2vBEA7f8RAOz/EQDr/xAA6v8QAOn/EADo/xAA
- 6P8RAOn/EQDp/xEA6f8RAOn/EQDp/xEA6f8RAOn/EQDp/xEA6v8RAOr/EQDq/xEA6/8RAOv/EQDs/xAA
- 7P8RAO3/EQDs/xAA6v8PAOb/EADk/xAA5f8QAOr/EQDv/xIA8/8SAPX/EQD2/wkAj4QAAAAHAAAAAQAA
- AAAAAAAAAAAAAABiAGIAxwD9AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCjAOcABgBtAAAAKwAA
- AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAYBAB4sDgDZ4RAA7P8PAOX/DwDd/w4A1f8OANL/DwDX/w8A3/8QAOb/EQDp/xEA6/8RAOv/EQDr/xEA
- 6/8RAOv/EQDr/xEA6/8RAOz/EQDs/xEA7P8RAO3/EADt/xAA6/8PAOX/DwDY/w4Ay/8OAML/DgDE/w8A
- 0P8QAOD/EQDt/xIA9P8NAMK6AAAKDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAQAAwCJAJgAxwD/AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMcA/wBWALMAAABQAAAAFgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgDADpGDwDc8g4A0/8NAL//DACw/wsA
- rP8MALX/DgDH/w8A2f8QAOb/EQDr/xEA7P8RAOz/EQDs/xEA7P8RAOz/EQDs/xEA7f8RAO3/EQDt/xEA
- 7v8QAO3/DwDl/w4A0/8NALr/CwCj/woAmP8KAJr/DACq/w4AxP8PAN7/DgDT2AIAISAAAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAABUADACtAMYAyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/ALgA9AAT
- AH4AAAA1AAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAgAAABIFAEhsDACy+AoAmf8JAIj/CQCK/wkAjv8LAKX/DQDC/w8A3P8QAOr/EQDt/xEA
- 7f8RAO3/EQDt/xEA7f8RAO7/EQDu/xEA7v8RAO//EQDv/xAA6/8PANn/DQC7/wsAmP8JAI3/CwCh/wwA
- rf8LAKb/CwCl/wwAtOYCACs9AAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYAIgDA
- AOkAyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AHcAygAAAFoAAAAeAAAAAgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFQAAAD0DADKXCgCS/QwA
- sP8NAML/DgDK/wwAtP8LAKr/DgDN/w8A5v8RAO7/EQDu/xEA7v8RAO//EQDv/xEA7/8RAO//EQDv/xEA
- 8P8RAPD/EADn/w4Ay/8LAKP/CgCY/wwArf8NALr/DgDI/w8A1f8OAMz8AgArcAAAACIAAAAGAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE4ASADHAPsAyAD/AMgA/wDIAP8AyAD/AMgA/wDI
- AP8AxAD8ACcAkAAAAD8AAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAQAAAAfAAAASwcAasMMAKv/DQC0/w4AwP8OAM7/EADb/w0Ayf8NAL//EADh/xEA
- 8P8RAPD/EQDw/xEA8P8RAPD/EQDw/xEA8f8RAPH/EgDx/xIA8f8QAOT/DQDB/wsApf8MAK//DQCx/w0A
- uv8OAMb/DwDT/xAA4P8JAI+wAAAAKgAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAQABAHcAewDHAP4AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AlwDgAAEAZgAAACcAAAAFAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAACYCAClvDQC3/g0A
- tP8NALj/DgDC/w4Azf8QANr/EADl/w4Axf8QAN7/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPL/EgDy/xIA
- 8v8SAPL/EgDy/xAA5P8NAL//DQC5/w0Au/8NALr/DgC//w4AyP8PANP/EADf/w8A3/AAABA0AAAACQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAGAJwArgDIAP8AyAD/AMgA/wDI
- AP8AyAD/AMgA/wDHAP8ARQCnAAAASgAAABMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAGAAAAJAYAYJkOAMP/DgC//w4AwP8OAMf/DwDQ/xAA2/8QAOf/DwDX/xAA
- 4f8SAPL/EgDy/xIA8v8SAPL/EgDz/xIA8/8SAPP/EgDz/xIA8/8SAPT/EADo/w4Axv8OAMr/DgDG/w4A
- xP8OAMf/DwDN/w8A1/8QAOH/EADs/AIAHToAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAGwAVALQA2ADIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCuAO4ACwB0AAAAMAAA
- AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAbBwBwnA4A
- zv8OAMr/DgDK/w8Azv8PANb/EADf/xAA6f8QAOD+EADn/xIA8/8SAPT/EgD0/xIA9P8SAPT/EgD0/xIA
- 9P8SAPT/EgD1/xIA9f8RAO7/DwDW/w8A1P8PANL/DwDQ/w8A0P8PANX/DwDc/xAA5f8QAO33AQAbKgAA
- AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQAyAMQA8wDI
- AP8AyAD/AMgA/wDIAP8AyAD/AMcA/wBmAL4AAABVAAAAGgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAABAGAFdvDwDa/w8A1v8PANX/DwDX/w8A3P8QAOT/EQDt/wgA
- dHUHAHBzDQDDxBEA7vQRAPT+EgD1/xIA9f8SAPX/EgD1/xIA9f8RAPX+EQDt8QwAubYGAF5oCQCQoBAA
- 3v8QANv/EADb/xAA3v8QAOP/EQDr/w0AxcMAAAMMAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAZgBiAMcA/gDIAP8AyAD/AMgA/wDIAP8AyAD/AL8A+QAd
- AIcAAAA7AAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA
- ESAOANLhEADh/xAA4P8QAOH/EADl/xEA6/8PAN/fAQAUGwAAABYAAAAoAQEdPAQLkpYHAGdlBwBscAcA
- bHMHAGxwBgBhZwMNnKYAABE5AAAAIwAAABABABslDgDV3hAA5v8QAOb/EADn/xEA7P8QAOzxBABEPAAA
- AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAkACcAMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AIgA1gABAGEAAAAiAAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwQAREAPAN7kEQDr/xEA6/8RAO7/DwDm5gQA
- Sj4AAAAOAAAAJAAAADcADm2PAAtYawAAAAkAAAAAAAAAAAAAAAQAAAAaABB7mAAMYokAAAA2AAAAGgAA
- AAoCACIjDACvpBAA6OgRAO/sDQDIvwQAQzcAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAwArwDKAMgA/wDIAP8AyAD/AMgA/wDI
- AP8AxgD+ADYAnAAAAEUAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAABAAAABAEAIBkIAHVqCgCMjwgAf20CACYbAAAABwAAABkAAAA5AAMdWgAczuwABCM3AAAABQAA
- AAAAAAAAAAAAAQAAABQACERmABzQ8wAEImIAAAAvAAAAEQAAAAQAAAACAgAmCwMALw4AAAcCAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAApACYAwADqAMgA/wDIAP8AyAD/AMgA/wDIAP8ApgDpAAQAbAAAACwAAAAGAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAAOAAAALAAAAE4AFJXBABrB3AAABBoAAAACAAAAAAAAAAAAAAAAAAAADQABDzcAHdn5ABWk0AAA
- BEwAAAAkAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSAE0AxwD6AMgA/wDI
- AP8AyAD/AMgA/wDIAP8AVwC0AAAAUAAAABcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAB0AAABEAAg+hgAd2v4AEo6nAAAAEAAA
- AAEAAAAAAAAAAAAAAAAAAAAHAAAAJQAXsNAAHdv/AAxhnwAAAD4AAAAZAAAABgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQB5AH4AxwD+AMgA/wDIAP8AyAD/AMgA/wC6APYAEgB+AAAANgAA
- AAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAARAAAAMwAABV4AGLbiAB7b/wALVm0AAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAaAA5xlgAd
- 2/8AHNH2AAQkbgAAADAAAAAQAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABQCi
- ALUAyAD/AMgA/wDIAP8AyAD/AMgA/wB5AMsAAABbAAAAHwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACIAAABKAAxdpQAd2v8AHdf4AAQfMgAA
- AAQAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABAABjFXAB3b/gAe3P8AFqjVAAADTQAAACQAAAAKAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAFwC7AN4AyAD/AMgA/wDIAP8AyAD/AMMA/AAs
- AJMAAABAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAMAAAAUAAAAOAACEWsAGsfwAB7b/wAZudQAAAAVAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAA
- BiwAGsflAB7c/wAd2/8ADGKgAAAAPQAAABgAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAEAAPADGAPUAyAD/AMgA/wDIAP8AyAD/AJgA4AADAGgAAAAoAAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACgAAACYAAABQAA94uQAe2/8AHtv/ABB8lAAA
- AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGwASiKgAHtz/AB7c/wAc0fYABCJrAAAALwAA
- ABAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG0AbADHAP4AyAD/AMgA/wDI
- AP8AxwD/AEcAqQAAAEsAAAAUAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAQAAAAWAAAAPAAEInkAHNP5AB7b/wAd2v4ABztLAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAEAAAAQAAg+XwAd2/4AHtz/AB7c/wAWptQAAANLAAAAIgAAAAkAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAABgADAJEAoADHAP8AyAD/AMgA/wDIAP8AsgDwAAsAdgAAADEAAAAIAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACwAAACgAAABUABOQygAe2/8AHtv/ABvJ4gAA
- BBYAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAQgpABrF4gAe3P8AHtz/AB3b/gAM
- WpgAAAA6AAAAFgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgAOALAAzQDI
- AP8AyAD/AMgA/wDIAP8AawDCAAAAVgAAABsAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAQAAAAYAAAAPgAFLIEAHdj8AB7b/wAe2/8AEYSXAAAACwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAwAAABYAD3eVAB7c/wAe3P8AHtz/ABvL8QADGWMAAAAsAAAADgAAAAIAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALQAoAMIA7gDIAP8AyAD/AMgA/wDBAPoAHgCIAAAAPAAA
- AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADAAAACsAAABWABSc0gAe2/8AHtv/AB3a/gAG
- MUAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACgAEI0AAHdb4AB7c/wAe
- 3P8AHtz/ABOWyAAAAUcAAAAgAAAACAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAVwBSAMcA/ADIAP8AyAD/AMgA/wCLANcAAABhAAAAIwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAUAAAAbAAAAQgAHOowAHdr+AB7b/wAe2/8AGLfMAAACEQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAUl7IAHtz/AB7c/wAe3P8AHdv+AAlJjAAAADgAAAAWAAAABAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAIAfgCIAMcA/wDIAP8AyAD/AMYA/gA6
- AJ4AAABGAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADwAAADAAAAJbABet3gAe2/8AHtv/AB7b/wAL
- WWoAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAMAAY0TAAd
- 2v0AHtz/AB7c/wAe3P8AGsXsAAIRXgAAACwAAAAOAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAARAAgAowC6AMgA/wDIAP8AyAD/AKcA6gAHAG8AAAAtAAAABgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAgAAAAgAAAASAAKTJoAHdr+AB7b/wAe2/8AG8nkAAENGgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAWABSbtAAe3P8AHtz/AB7c/wAe3P8AE5HFAAAASgAA
- ACIAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABwAuQDgAMgA/wDI
- AP8AyAD/AFsAtgAAAFIAAAAYAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAADcAAQpmABm76QAe2/8AHtv/AB7b/wAO
- b4AAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AAkABSc+AB3X9gAe3P8AHtz/AB7c/wAd2v4ACUqRAAAAPwAAABwAAAAHAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAD8AxQD3AMgA/wDIAP8AugD2ABYAgAAAADcAAAAKAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
- AAwAAAAoAAAAUgAObbQAHdr/AB7b/wAe2/8AHM7oAAIVIAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABIAEIKZAB7c/wAe3P8AHtz/AB7c/wAb
- y/IAAx5wAAAANgAAABYAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBx
- AHAAyAD/AMgA/wDIAP8AfQDOAAAAXQAAACAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAHQAAAEMABCF+ABzQ+AAe2/8AHtv/AB3a/wAO
- bn4AAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAABgACEycAGsjiAB7c/wAe3P8AHtz/AB7c/wAXsN4AAQteAAAAMAAAABMAAAAFAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgCZAKYAyAD/AMgA/wDGAP4ALgCWAAAAQgAA
- AA8AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA
- ABUAAAA2AAACYQAVodcAHtv/AB7b/wAe2/8AG8vlAAIPGwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAAJTF8AHdr8AB7c/wAe
- 3P8AHtz/AB7c/wATjsYAAAJUAAAALQAAABIAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAABwAEAC0ANIAyAD/AMgA/wCeAOQAAwBpAAAAKQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAALgAAAFUADFuqAB7a/wAe2/8AHtv/AB7b/wAN
- Y24AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAADAAACEgASj6EAHtv/AB7c/wAe3P8AHtz/AB3b/wAOa68AAABQAAAALAAA
- ABIAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIALgDDAO8AyAD/AMcA/wBP
- AK4AAABNAAAAFQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAA
- ACgAAABNAAUnhgAc0fgAHtv/AB7b/wAe2/8AGbvOAAAEEAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAIPIAAZ
- vNQAHtz/AB7c/wAe3P8AHtz/AB3Z/QALWqIAAABQAAAALAAAABMAAAAFAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAF0AWgDHAPwAyAD/ALMA8gAOAHgAAAAyAAAACAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA
- AAQAAAAEAAAAAgAAAAEAAAACAAAABAAAABAAAAAnAAAASQABDXQAGLXmAB7b/wAe2/8AHtv/AB3a+gAH
- PUQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAUtPAAd1/MAHtz/AB7c/wAe3P8AHtz/AB3Y/AAL
- WaIAAABSAAAAMQAAABYAAAAIAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgACAIUAkADH
- AP8AyAD/AG0AwwAAAFgAAAAcAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgAAAATAAAAHAAAACAAAAAbAAAAFgAAABYAAAAeAAAAMAAA
- AE4AAAdxABWb1wAd2v8AHtv/AB7b/wAd2v8AEoyWAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAAKAApSYAAd2foAHtz/AB7c/wAe3P8AHtz/AB3Z/AAMW6YAAABZAAAAOQAAAB4AAAAOAAAABAAA
- AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAIAKwAxADIAP8AwQD6ACIAigAAADwAAAAMAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFgAA
- AC4AAABDAAAASwAAAEYAAABAAAAAQAAAAEgAAABbAAEHdwATkNAAHtv/AB7b/wAe2/8AHtv/ABnA1AAC
- EhgAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAANAA5wegAd2/0AHtz/AB7c/wAe
- 3P8AHtz/AB3a/gAPdLkAAARkAAAARgAAAC0AAAAbAAAADwAAAAoAAAAIAAAACQAAAAwAAAAMAAAACQAA
- AAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAJgAgAMAA5wDIAP8AjQDWAAEAYgAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAmAAABSwAGMYQABi+OAAEIdgAAAG0AAABsAAAAdAAF
- JpIAFqfgAB7b/wAe2/8AHtv/AB7b/wAc1fMABzo+AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAMAAAIPABGBjwAd2/4AHtz/AB7c/wAe3P8AHtz/AB3b/wAUnNUAAhZ6AAAAWAAA
- AEQAAAA1AAAALQAAACoAAAAsAAAAMAAAADAAAAAlAAAAFgAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASgBHAMcA+QDHAP4APACcAAAARgAA
- ABEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAA
- ADEACk6OABzX/AAd2v4AG8jzABWg3QASjdMAFqjiABzV/AAe2/8AHtv/AB7b/wAe2/8AHdr+AA1naQAA
- AAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAIQABGKmAAd
- 2/8AHtz/AB7c/wAe3P8AHtz/AB7c/wAayPIADFutAAAGcgAAAGIAAABaAAAAWAAAAFoAAABeAAAAXAAA
- AEsAAAAwAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAACAAEAdwB6AMcA/wCqAOkABgBqAAAALQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAALgAWp9AAHdr/AB7b/wAe2/8AHtv/AB7b/wAe
- 2/8AHtv/AB7b/wAe2/8AHtv/AB7a/wASjpUAAAEIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAMOABGEjwAd2/4AHtz/AB7c/wAe3P8AHtz/AB7c/wAd
- 2/8AGb/tAA93wgAJRaQABjOaAAhAogAMW7IAEH3EAA94tAACFFUAAAAiAAAABgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAYAmgCwAMcA/wBd
- AK8AAABPAAAAGAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAgAAAAgABez2AAd2v8AHtv/AB7b/wAe2/8AHtv/AB7b/wAe2/8AHtv/AB7b/wAd2v4AFJqfAAAICgAA
- AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAEMAA5ydgAd2PgAHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe
- 3P8AHtz/ABarzQAAAyoAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiABQAtwDZAL0A9QAZAHMAAAA2AAAACgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABAAE5ekAB3a/wAe2/8AHtv/AB7b/wAe
- 2/8AHtv/AB7b/wAe2/8AHdr7ABGEiAAABQkAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAlJTQAbzOQAHtz/AB7c/wAe
- 3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHdv8AAQiNgAAAAcAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3
- ADQAxQD0AIIAwgAAAFIAAAAgAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAABAAAABAADHyAAE5OaABzT6wAd2v8AHtv/AB7b/wAe2/8AHdr/ABnBzgAJTUsAAAIEAAAAAQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEAAAAFAAQhJgAWpLAAHtv+AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe
- 3P8AHtz/AB7c/wAd2/sABCQqAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAGMAxAD6ADIAewAAADsAAAAOAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAhQRAAlIQgAP
- dHMAD3eCAA90cwAIRjsAAAYIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAADCQAK
- UlAAGbrFAB3b/gAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/ABaprgAABAoAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAUAAwCQAJsAoADUAAQASwAAACQAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgcABzo0ABB+gwAXr7oAHNPdABzU6AAc
- 0tsAGLbAABKJjAALVU0AAQkJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcADACrAMoAUwCEAAAANwAA
- ABIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAADAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAC4AJwCwANMADwBAAAAAIwAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUAUQB1
- AJMAAAAoAAAAEgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAHwAfQAmADsAAAAYAAAABgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAEAAHAHYAbAACABMAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJQAYAD8AKQAAAAYAAAACAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAALQAMAAQAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/////8AH//////////////////+AAf/////////////////+AA
- D//////////////////AAAf/////////////////gAAD/////////////////wAAA///////////////
- //4AAAH////////////////4AAAB////////////////8AAAAP///////////////+AAAAAA///////g
- ///////AAAAAAA//////wP///4H/gAAAAAAD/////wD///+A/gAAAAAAAP////4A////gHwAAAAAAAB/
- ///8AP///4A4AAAAAAAAH///+AH////AAAAAAAAAAA////AD////wAAAAAAAAAAH///AA////+AAAAAA
- AAAAA///gAf////wAAAAAAAAAAP//4AH////8AAAAAAAAAAB//8AD/////gAAAAAAAAAAP/+AB/////4
- AAAAAAAAAAB//AAf////8AAAAAAAAAAAf/gAP////+AAAAAAAAAAAD/wAH////+AAAAAAAAAAAAAAAD/
- ////AAAAAAAAAAAAAAAB/////gAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAP////8AAAAAAAAAAAA
- AAAH////+AAAAAAAAAAAAAAAD/+H//gAAAAAAAAAAAAAAB/+B//4AAAAAAAAAAAAAAA//Af/+AAAAAAA
- AAAAAAAA//gH//wAAAAAAAAAAAAD///gB//8AAAAAAAAAAAAA///wA///AAAAEAAAAAAAAP//4AP//4A
- AADAAAAAAAAD//8AH///AAADwAAAAAAAAf/+AD///wAPH8AAAAAAAAH//AA///+AB/+AAAAAAAAB//gA
- f///wAf/gAAAAAAAAf/wAH///8AD/4AAAAAAAAH/4AD////gAf+AAAAAAAAB/8AB////8AD/gAAAAAAA
- Af/AA/////AAf4AAAAAAAAAAAAP////4ADgAAAAAAAAAAAAH/////AAAAAAAAAAAAAAAD/////4AAAAA
- AAAAAAAAAB/////+AAAAAAAAAAAAAAA//////wAAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////
- wAAAAAAAAAAAAADw/////+AAAAAAAAAAAAADwP///+DwAAAAAAAAAAH//4D////gPgGAAAAAAAAB//4A
- ////4B//gAAAAAAAAf/8AP///+AH/4AAAAAAAAH/+AH////wA//AAAAAAAAB/+AB////8AH/wAAAAAAA
- Af/AA/////gA/8AAAAAAAAP/gAf////8AH/AAAAAAAAB/wAH/////AA/wAAAAAAAAf4AD/////4AH+AA
- AAAAAAD8AB//////AA/gAAAAAAAA+AA//////wAH4AAAAAAAAHAAP/////+AA+AAAAAAAAAgAH//////
- wAHwAAAAAAAAAAD//////+AAAAAAAAAAAAAB///////wAAAAAAAAAAAAA///////+AAAAAAAAAAAAAf/
- //////gAAAAAAAAAAAAP///////8AAAAAAAAAAAAH////////gAAAAAAAAAAAD////////8AAAAAAAAA
- AAB/////////gAAAAAAAAAAB/////////8AAAAAAAADAAP///////////4AAAAAA4AD///////////+A
- AAAAAeAAf///////////wAAAAAPwAH///////////+AAAAAH+AA////////////gAAAAB/wAP///////
- ////4AAAAAf8AB///////////+AAAAAH/gAP///////////gAAAAB/8AD///////////4AAAAAf/gAf/
- /////////+AAAAAH/4AH///////////wAAAAD//AA///////////8AAYAB//4AH///////////gAGAA/
- //AB////////////4BwD///4AP///////////+AcA///+AD////////////APAH///wAf///////////
- wDwA///+AH///////////4A+AP///wA///////////8AfgB///+AH///////////AH4AP///gB//////
- /////gB/AD///8AP//////////4AfwAf///gD//////////8AP8AD///8Af//////////AD/gA////AD
- //////////gB/4AH///4A//////////wAf/AA////AH/////////8AP/wAH///4B/////////+AD/+AA
- ///+AP/////////AA//wAP///wB/////////wAf/8AB///+Af////////4AP//gAH///wD////////8A
- D//8AA///+A///////8AAB///AAH///gH//////+AAAf//4AAf//8B///////gAAP///AAAB//gP////
- //4AAH///4AAAP/8B//////+AAB////AAAD//Af//////gAA////4AAA//4D//////4AAf////AAAP//
- A//////+AAP////4AAD//4H//////gAH/////AAA///B//////+AH/////8AAP//wP//////////////
- wAH//+B///////////////gP///wf///////////////////+D////////////////////g/////////
- ///////////8H////////////////////h////////////////////8f////////////////////////
- ////////////////////////////////////////KAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAACAA0AIAAuAF8ANQBwABEARgAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAUARQBqALUA7ADHAP8AxwD/AMAA+gBhAK4AAQAhAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAEACQBlAJEAxQD8AMcA/wDHAP8AxwD/AMcA/wDHAP8ASQCVAAAACgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAXAIIAswDGAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8AswDxAA0ARgAAAAUAAAAHAAAABQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAIAAAAMAAAABQAAAAAAAAAAAAAAAQAaACkAmgDOAMYA/wDGAP8AxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AxwD/AG4AyAAACmYBABtsAQATYAAAAT8AAAAbAAAABQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA4AAAcsAQAVGgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAC9QAAALPwAAAAwAAAACACgAQgCuAOUAxgD/AMYA/wDG
- AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMMA/gcgbvwOAMP+DgDI/QwAtOsHAGitAAALRwAA
- AA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAGAIAH2QKAJOrAAATCwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABEdCQCN0gIAH2gAPgBtALwA9ADG
- AP8AxgD/AMYA/wDGAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wGQHf8MAaj/DgDK/w4A
- 0P8PANb/DQC/7AMALWwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAfBAA/hg8A
- 2PAEAENEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBABDbQVX
- T/kAwwD9AMYA/wDGAP8AxgD/AMYA/wDGAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
- AP8FQVb/DgDC/w4Az/8PANT/DwDa/w4A0fUDADJpAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- AB0FAEmOEADk+gkAjJQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAABwAQAHYAqADGAP8AxwD/AMYA/wDGAP8AxgD/AMYA/wDGAP8AxwD/AMcA/wC4APUAxwD/AMcA/wDH
- AP8AxwD/AMcA/wDHAP8ArQ3/CgmW/w4Azf8PANP/DwDZ/xAA3/8OAMvtAQAVQgAAAAIAAAAAAAAAAAAA
- AAAAAAAAAAAAFQQAPoIQAOT6DQC/ygAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAATABwAkADCAMYA/wDGAP8AxwD/AMYA/wDGAP8AxgD/AMYA/wDGAP8AxwD/AK8A7AQY
- PbQEeEH/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/BGY5/w0Avv8PANL/DwDY/w8A3v8QAOP/CgCZxAAA
- AEAAAAAyAAAAKwAAACYAAAApAgAjbA8A3fYPANTiAgAmHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAABgAHwCgANQAxwD/AMYA/wDGAP8AxwD/AMYA/wDGAP8AxgD/AMYA/wDG
- AP8Aswb5AR8UrQsAme8MB6P/Ap0j/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMED/wgbgP8OAND/DwDX/w8A
- 3f8QAOL/EADn/goAmeILAKraCwCc0AoAkMcJAIzHDgDM7RAA5fYEAEA7AAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwApADHAP8AxwD/AMYA/wDGAP8AxwD/AMYA/wDG
- AP8AxgD/AMYA/wC3C/8IJID/CgCT/wwAsf8MAK7/CxiW/wC4DP8AxwD/AMcA/wDHAP8AxwD/AMcA/wKI
- JP8MALb/DwDW/w8A3P8QAOL/EADn/w4A1PsOANHsEADr+RAA7P8QAOz/EADh7QYAXlsAAAABAAAAAAAA
- AAAAAAAAAAAAAgAAAAsAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF4AaQDEAfwAxwD/AMYA/wDG
- AP8AxwD/AMYA/wDGAP8AxgD/ALoA8gQoSKgGAGKhCwCf8g0AtP8MALH/DACw/wk5ff8AxAL/AMcA/wDH
- AP8AxwD/AMcA/wDGAP8GOWT/DwDR/w8A3P8QAOH/EADn/xAA5PcBABMxAAAKBQMAMgwDAD4PAAARAwAA
- AAAAAAAAAAAAAAAAAAAAAAAFAAAAJgQAOl8BABUTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgUe
- TowEWjjPAIIAtQCfAMgAtgDlAMUA+wDGAP8AqQDZADAAQAAAAAEBABFADQC2+g0AuP8NALX/DAC0/wwA
- tP8GYVz/AMcA/wDHAP8AxwD/AMcA/wDHAP8BphL/DAao/w8A2/8QAOH/EADm/xAA7f8FAFJxAAAAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAM7CAB2rQkAf4QAAAABAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAEADxUNALPbBgBanQAAACAACQAGAFMAEgBOABwAGgAHAAAAAAAAAAMEADpyDQC//w0A
- u/8NALn/DQC4/w0AuP8NArb/BIo4/wDHAP8AxwD/AMcA/wDHAP8AxwD/BFtI/w4A0P8QAOH/EADm/xAA
- 7P8KAI+pAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACUYLAKLPDwDP2AEAEg0AAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAEBTDgDQ/AcAZ6YAAAAeAAAAAQAAAAAAAAAAAAAAAAAA
- AAcGAGGcDgDC/w0Av/8NALz/DQC7/w0Au/8NALz/DAyx/wGrGv8AxwD/AMcA/wDHAP8AxwD/AL0F/woU
- kv8QAOD/EADn/xAA7P8NALvQAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAGAAAHQQwArdURAOr3BAA/OwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCAB4kw4A0f4GAFiWAAAAFQAA
- AAAAAAAAAAAAAAAAAAsJAH23DgDG/w0Awv8NAMD/DQC//w0Avv8NAL//DQDB/wsmnP8Avgn/AMcA/wDH
- AP8AxwD/AMcA/wOALf8OAMj/EADn/xAA7f8PANjoAAAFGAAAAAUAAAADAAAAAgAAAAUAAAIzCwCcyREA
- 8P4HAGtsAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICwsA
- oMIOAM77AwA4dwAAACAAAAAdAAAAIQAAADMKAJHQDgDJ/w4Axv8OAMT/DQDC/w0Awv8NAML/DgDD/w4A
- xv8JSXz/AMYB/wDHAP8AxwD/AMcA/wDFAf8IL3b/EADj/xAA7f8QAOX2AgAfcgEAD10AAAJQAAAASgAA
- AFAIAHWxEQDw/woAkZYAAAcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAEAGB4NALzjDQDB9AcAarkHAGi2CAB0vwgAfM0MALP2DgDN/w4Ayv8OAMf/DgDG/w4A
- xf8OAMX/DgDH/w4AyP8OAMr/BnJW/wDHAP8AxwD/AMcA/wDHAP8Bnxj/DQO8/xEA7f8RAPD/EADg/xEA
- 8P8RAO39EADi9xAA4fcRAPD/DQC8xAAACggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDADdADQDD6A8A0v8OANL/DgDS/Q4AxfgNAMH7DgDQ/w4A
- zf8OAMv/DgDJ/w4Ayf8OAMn/DgDK/w4Ay/8OAM7/DgXK/wObLv8AxwD/AMcA/wDHAP8AxwD/BVBY/xAA
- 4/8RAOr4CAB7hQwAqZYNALqnDQC1tQ0AurYLAKOQAgAoFQAAAAAAAAAFAAAABAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAAAUAAAAAAgApDAcAaicHAGwnBQBPGwIA
- HhYKAI66DwDU/w4A0f8OAM//DgDN/w4Azf8OAMz/DgDN/w4Azv8OAND/DwDT/w0Xu/8BtRP/AMcA/wDH
- AP8AxwD/ALcJ/wsOqf8QAN7rAAAODwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAABgBABM+AQAeIAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIEBQBZbwEAEkgAAAAPAAAAAQAA
- AAAAAAAAAAAAAAAAAAQIAHSbDwDX/w8A1f8PANP/DwDR/w4A0P8OAND/DgDQ/w8A0f8PANP/DwDV/w8A
- 2P8LM6H/AMMF/wDHAP8AxwD/AMcA/wR1Of8MALHUAAABBwAAAAAAAAAAAAAAAAAAAAAAAAAFAAAALAUA
- SYsLAKCrAAAKBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAhKg0A
- wt0DADh2AAAAGAAAAAEAAAAAAAAAAAAAAAEFAFFwDwDb/w8A2P8PANb/DwDV/w8A1P8PANP/DwDU/w8A
- 1P8PANb/DwDY/w8A2/8PAN3/CFt3/wDHAP8AxwD/AMcA/wDDAv8EJ0S8AAAABgAAAAAAAAAAAAAAAAAA
- AAcAAAQ8CQCCuRAA4usCACwkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAQYAYGwPAOX6BQBYkgAAABsAAAABAAAAAAAAAAACACM4DwDd/Q8A3P8PANr/DwDY/w8A
- 1/8PANf/DwDX/w8A2P8PANn/DwDb/w8A3f8QAOD/EAHh/wWGSf8AxwD/AMcA/wDHAP8AlwDfAAIAKQAA
- AAAAAAAAAAAABgAABkALAKDMEQDy/QYAWlUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwUKAJajDwDq/gYAXZQAAAAYAAAAAQAAAAAAAAINDQC/3BAA
- 4P8PAN3/DwDc/w8A2/8PANr/DwDa/w8A2/8PANz/DwDe/w8A4P8QAOL/EADl/w8L2v8CpyX/AMcA/wDH
- AP8AxwD/AEcAlAAAAAsAAAAGAAADOAsAo80RAPP+CAB6eQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4PCwCzwQ8A5/wFAE2EAAAAGgAA
- ABAAAAAVCABymBAA4/8QAOH/EADg/xAA3/8QAN7/EADe/xAA3v8QAN//EADh/xAA4v8QAOX/EADn/xAA
- 6/8NIsP/ALwN/wDHAP8AxwD/ALEA8gAJAXQAAAVWCQCKvhEA8/8KAJGRAAAKAwAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAXGQ0A
- ytoPAN/3BgBeowQASZIFAFObCAB0uxAA5f8RAOX/EADj/xAA4v8QAOH/EADh/xAA4f8QAOL/EADj/xAA
- 5f8QAOf/EADq/xAA7f8RAPD/C0Se/wDHAP8AxwD/AMcA/wRmPPoPANL2EQDz/wwArbEAAA8GAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAIALTAOANnoEADs/xAA7P8QAOz/EADq/w8A3/4RAOn/EQDn/xEA5v8RAOX/EQDl/xEA
- 5f8RAOb/EADn/xAA6P8QAOr/EADt/xEA7/8RAPL/DgDM0wF0GKsAxwD/AMcA/wDABP8IHXbdCgCNhwEA
- HAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADMXCQCRUAkAmVcKAJtMCAB/OwMANzMOAMvbEADq/xAA
- 5/8QAOj/EQDo/xEA6P8RAOn/EADq/xAA6/8QAOr/EADn/xEA7v8RAPD4BABCPQAoAAgApQDCAMcA/wDH
- AP8AiwDTAAEAIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAADADE7DQC98gsAqf8OAMn/EADp/xEA7P8RAOz/EADt/xAA6/8NAMH/CwCm/w0Avv4HAG1yAAACAQAA
- AAAASAAdALgA5gDHAP8AxgD+ADoAhQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAUBwBnvQ0Avv8OAMj/DwDh/xEA7/8RAPD/EQDw/xAA4v8MAKz/DQC9/w0A
- xe4AAA0iAAAAAAAAAAAAAAAAAGAAQADFAPkAxwD/AKoA6wAFADYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVDQC57w4Ayv8QAOH+EADh+BIA8/8SAPP/EQD0/xAA
- 5/0OAMj6DgDN/xAA4f4CAC0xAAAAAAAAAAAAAAAAAAAAAAB6AHQAxwD/AMcA/wBbAKcAAAAOAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCgCYqRAA4/8NALvDAQAaNAUF
- eokJAIlqBgR8iQIBOFQGAGFuEADh8gsAqa4AAAwGAAAAAAAAAAAAAAAAAAAAAAAoAAMAmwCsAMcA/wC7
- APYAFQBSAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAlBAkA
- ii4AAA0SAAYyagAKTV4AAAAAAAENHwARhbMAAAAZAgArBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAARQAQAK8A1gDHAP8AfQDHAAAAGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEAAAMwABeq2QADHCIAAAAAAAAACQAWpsoACEJ3AAAACQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAE4ALQDBAPMAxQD9AC0AdQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AClCPABiy0QAAAAUAAAAAAAAAAQANZYQAGsLrAAIPOQAA
- AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2AF0AxwD+AJ0A4QABACoAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgABCDwAGr/rAA5rgQAAAAAAAAAAAAAAAAAD
- HS0AHdb5ABGEtwAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAEAigCTAMcA/wBM
- AJkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEwANYqAAHdX4AAUnJgAA
- AAAAAAAAAAAAAAAAAAUAE5OxAB3a/gAHOG0AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAALgAJAKcAxQCzAPEADgBGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAIQTAAb
- yvMAE5GpAAACAgAAAAAAAAAAAAAAAAAAAAAABSg2AB3W+AAZvecAAQ08AAAAAwAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAEgAHgC7AOoAbgC5AAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAEAAAAnABKGwgAd1vgABSsvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAA92jQAd2/8AFJbJAAADKwAA
- AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjAEYAvwD2ACIAZwAAAAMAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAIAAAADAAAAAwAAAB0ACUiQAB3Z/gARgZUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJDQAX
- r8sAHdv/ABF/uAAAASsAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfgB8AI8A1gAA
- ACIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAgAAAzAAAQtUAAAASgAIPpAAHM/4ABm/3AACFhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAEICMAGsLgAB3b/wASicMAAQhGAAAAGgAAABQAAAATAAAABAAAAAAAAAAAAAAAAAAA
- AAAAJgAEAJwAsgA8AIYAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAOaZUAHdb8ABrC8QAd2v8AHNDwAAYzNAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCYrABrB3gAd2/8AGbzrAA1irQAKT54ADF+gAAEJIwAA
- AAAAAAAAAAAAAAAAAAAAAAAAADkAEgCVAMcACAA2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAJS1cAG8jjAB3a+wAYt88ABz03AAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMcGwAVoLYAHdv+AB3b/wAd
- 2/8AHdv/AAg/TgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfADUAWgCVAAAADgAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSsGAAxkEgAC
- GAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
- DQMAC1c/ABSXhwAWo5IAEYBnAAMdCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZABaABcAPgAA
- AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAFAABAEUASgAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAC4ACAARAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4H/////////AP////
- ////4Af////////AAH//P///4wAAH/w////gAAAP+D////AAAAfwf///8AAAA+B////wAAAB4P///+AA
- AAAB////wAAAAAP////AAAAAA4///8AAAAAPD///wAAAAH4P///gEAAAfB///+BwAAB4P///8HAAAAA/
- ///4AAAAAH////wAAAAA/////AAAAAE////xAAAAfD////BwAAB4P///+DAAAHB////4GAAAYP////wI
- AAAA/////gAAAAH/////AAAAA/////+AAAAH/////8AAAA///////wACB///////AAcH//////8AB4P/
- /////wAHgf//////gh/B///////CH+D//////8IP8P//////hw/wf/////+HB/g//////weD/D/////+
- D4H+H/////APwP8f////4B/gDw/////gP/APj////+B/+A/H////+P/8D+P/////////4//////////z
- /////////////ygAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEANgBHAGQAmQBRAIoACwAmAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAEAGUAhQDGAP0AyAD/AMgA/wCaANwAAwAaAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAA0ADQCAAKsAxwD/AMgA/wDIAP8AyAD/AMgA/wBR
- AJQAAAAZAAAAGAAAAAkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgsBABY8AAAABQAdAB4AmADKAMcA/wDHAP8AyAD/AMgA/wDI
- AP8AyAD/ALgA+QcOZtkKAJTYBwBurwEAF0cAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAMA
- LmIDADo4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQUAW4sCICiPAK0A4wDHAP8AxwD/AMcA/wDI
- AP8AyAD/AMgA/wDIAP8AyAD/A3U0/w4Awv8PANH/DwDN9gQAQXQAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
- AA8FAFGLCwCkswAAAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAD0IYQC6CP8AxwD/AMcA/wDH
- AP8AxwD/AMgA/wDAAPoAyAD/AMgA/wDIAP8AxQH/CSZ//w4Az/8PANj/DwDa+gMAM1oAAAABAAAAAAAA
- AAAAAAAKBQBQiA8A1eYDADAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBWAHAAwwD7AMcA/wDH
- AP8AxwD/AMcA/wDHAP8AngDiBxhl1wGuFf8AyAD/AMgA/wDIAP8BmRv/DQC8/w8A1v8QAN//DgDD5QIA
- JGkBABxVAQAPSQQAO3sPAODzBQBLOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbQBWAMcA/gDH
- AP8AxwD/AMcA/wDHAP8AxwD/AaMb/wcOcOwMAK7/CiaK/wDBBf8AyAD/AMgA/wDHAP8GSGD/DwDU/xAA
- 3v8QAOb/DgDQ+BAA6fkRAO3/EADo9wcAbWEAAAAAAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAAAAAABH
- ADABohPpAMYA/gDHAP8AxwD/AMcA/wCnANoEFEBwCQCC0Q0AtP8NALH/B0xt/wDHAP8AyAD/AMgA/wCz
- C/8MCq//EADd/xAA5f8MALHLAAAECQMANgkBACAFAAAAAAAAAAAAAAADAAAKMwQARlgAAAAAAAAAAAAA
- AAAAAAAAAAAAAAUAU2QGDlijAC0ARQCAAFkAgQBhACEAEgAAAA8LAJ7gDQC6/w0At/8NALf/BXdJ/wDI
- AP8AyAD/AMcA/wRrQv8PANj/EADl/xAA6PoBABEaAAAAAAAAAAAAAAAAAAAABAIAHVANALbTAwAtGwAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAADBAsAm74HAGWeAAAADAAAAAAAAAAAAAAIHw4AwfwOAL//DgC8/w4A
- vP8NBbj/Ap4n/wDIAP8AxwD/AMMC/wofl/8QAOX/EQDu/wQAREIAAAAAAAAAAAAAAAIBABtKDwDS7AcA
- ZVcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAfGw0AvOQFAEyCAAAAFQAAABUBABxLDgDJ/w4A
- xP8OAML/DgDB/w4Awv8MF63/AbcP/wDHAP8AyAD/ApAm/w8A1/8RAO7/BgBWhwAACD8AAAA0AAALSA4A
- w+IKAI6IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA6PQ4Ax/QJAIzPCgCR0woA
- meUPAM7/DwDK/w4Ax/8OAMb/DgDH/w8Ayv8KNZb/AMUC/wDIAP8AxwD/CD14/xEA7v8QAOP6EQDw/xEA
- 6fsRAOr7DACvswAACQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAADBgBXNwsA
- nHAKAJBpBwBldA8A1P8PAND/DwDN/w8Ay/8PAMz/DwDO/w8A0v8IX27/AMgA/wDIAP8BrRH/DgbM/wYA
- XlcFAFQSBwBuIggAcyAAAAUCAAAAFwEAFiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwA5QwMA
- MF8AAAAJAAAAAAAAAAAAAAcTDwDU+g8A1f8PANL/DwDR/w8A0f8PANP/DwDV/w8B2P8EikP/AMgA/wDI
- AP8GYVX/BABFNwAAAAAAAAAAAAAAAwAADToKAI6zAwAzHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAIDCwCitAYAXI0AAAANAAAAAAAAAAUMALHTEADb/xAA2P8QANb/EADW/xAA1/8QANr/DwDd/w8M
- 0/8CqiD/AMgA/wC/BP8AHANLAAAAAAAAAAMBABpLDgDK5QcAaFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAACAB8YDQDN3gYAYpAAAAAJAAAAAQgAdI0QAOD/EADd/xAA3P8QANv/EADc/xAA
- 3v8QAOH/EADl/w0jv/8Avwn/AMgA/wCFAMoAAAAbAQAURA8A0OkJAIqAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADADMsDgDa7QYAXJQDADJuBgBbmRAA5f8QAOP/EADh/xAA
- 4P8QAOH/EADi/xAA5f8RAOn/EQDt/wtHmv8AxwD/AMcA/wQyRtQOAMvpCwCfnQAAAgEAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAExFDQDK1g4A1+MOAMjUDQDE2hEA
- 6P8RAOb/EQDm/xEA5v8RAOf/EADp/xEA7f8RAPH/DgDCyQCEC6EAyAD/AaQV/AcDZHoBABUFAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAABABgRDAC32A0Awf8QAOX/EQDr/xEA7P8QAOb/DQC8/w4Ayu8EAD4oADMABgCqAMcAyAD/AFYAlgAA
- AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAEGAFWWDgDG/w8A2/8RAPD/EQDx/w8A1P8NALz/CgCXvAAAAAIAAAAAAFoAHAC5
- AOkAugD2ABQAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAcYYQAN/9CAB3iAoCpqkLAaqqBwBrgg4AzucJAIyRAAAAAAAA
- AAAAAAAAAG8AQwDGAPwAdwC7AAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAgMAMxoABzZlAAg/NQABCREADmqXAAAECQAA
- AAAAAAAAAAAAAAAAAAAAAAAAAIsAeQDFAP4AKgBbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHQAVnsoAAAUGAAAAAgAU
- lLYABi5VAAAAAQAAAAAAAAAAAAAAAAAAAAAAFAABAKQAsQCYANoAAQAVAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMACk+EABKFmwAA
- AAAAAAAAAApQXQAYtN4AAAUaAAAAAAAAAAAAAAAAAAAAAAAAAAAASgAQALIA3ABHAIQAAAABAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIKgAa
- vuoACD0yAAAAAAAAAAAAAAYIABm42AAObp4AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAZgAwAKwA5gAM
- ACsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AA8AD3KsABSWrQAAAAEAAAAAAAAAAAAAAAAACEJFAB3X+gAIP3EAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAgQBgAGgArAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
- BisAAAA0AApKjQAbzO4ABi8gAAAAAAAAAAAAAAAAAAAAAAAAAAEADm57ABzT+QAIQXoAAAAXAAAADgAA
- AAUAAAAAAAAAAAAAAAAAkQCWAB8ASgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAACABORtgAczvgAHdX3AApQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAD3SAAB3Z/QAU
- mdIAEYLBAAg/YAAAAAAAAAAAAAAAAAA5AAgAbACXAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAABzwcABWiWgAKUSYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAC1ZAABampQAYsrEAC1dEAAAAAAAAAAAAAAAAAAAAAABcACAALgBQAAAAAQAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+ACUABgAIAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ
- AAEAAAAA/wf///4D///MAD/PwAAfj8AADw/AAAYfgAAAP4AAAGeAAADHwAADh8MAAw/gAAAf8AAAH+AA
- AA/jAAMP4QACH/AAAD/4AAA//AAAf//AAH//wAh//+AcP//gPj//8B4f/+MfD//jD4//w4fH/geA5/4P
- wOP/H/Dx////+f////0oAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAEAAQB0AHMAkQDIAEYARwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAwSABAACQCOAKAAxwD/AMgA/wCmAOMFBEx4AwAyQAAAAAEAAAAAAAAAAAAAAAMCACApAAAAAAAA
- AAAAAAAAAhgtOwCTDNwAxwD/AMcA/wDGAP4AyAD/Blhd/w8A0f0GAF90AAAAAAAAAAIHAGSCBwBrNAAA
- AAAAAAAAAFYAFgCsANoAxwD/AMcA/wKFIvMIO2z1AMYB/wC8Bv8MErL/DwDZ+AgAfqwJAIiuCQCNZAAA
- AAAAAAACAAAAAAA+AAwDXy+8AJEApwCZAJMHBWSMDQC2/wZjW/8AyAD/BHw//xAA4P8JAIV6AgAsAwAA
- AAEEAEJWAwA3HQAAAAAAAAAABgBYNwcAY4QAAAALCAB2mQ4AwP8NAb7/BI05/wDGAP8LK57/CwCksgAA
- BB0FAEddCgCScwAAAAAAAAAAAAAAAAAAAAMHAGlbCgCSngwAq9YOAMv/DgDJ/w0NwP8CrRz/Ap4i/w4B
- w9QPAM6LDACodAAACg8AAAAAAAAAAAAAAAACACcSBQBUagAAAAMJAIZ5DwDW/w8A1P8PANb/DCWz/wDA
- CP8CWiegAAAAAQUASFsHAGpLAAAAAAAAAAAAAAAAAAAAAAcAbkkHAHGHBQBPZRAA4f8QAN7/EADf/xAA
- 5f8KSpT/ALcA8gUNT4cLAJ+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQCPRw4Aym4MAK+xDwDd/xEA
- 6f8PAN7/DQC6uACjA5sCcx3DAAALAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQBTRw0A
- vuEOAc3UDACy2ggAelQAWgAHALIAxwA9AD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAACEdZAAMaEwALU2sAAAAAAAAAAAB9AB8AjQC5AAEABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAULABB5jwAAAAAAEYKHAAYvMAAAAAAAAAAAAJEARwBXAGYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAMYAA5qjQANZDMAAAAAAAc0EQAUlrgAAx0mAAAABQAAAAAAegBoABYAFAAAAAAAAAAAAAAAAAAA
- AAAAAAABABWciQASiFoAAAAAAAAAAAAAAAAAC1MhABairQAPc4UAAAAAADkAAgBBAEUAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAJAAkAAuH/
- rEGAM6xBgCOsQQAFrEEAAaxBgAOsQYADrEGAA6xBwAesQeAHrEH4B6xB/GOsQfkzrEHxCaxB44msQf/8
- rEE=
-</value>
- </data>
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <metadata name="stateViewMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>17, 17</value>
+ </metadata>
+ <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>267, 17</value>
+ </metadata>
+ <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>152, 17</value>
+ </metadata>
+ <metadata name="openModelFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>422, 17</value>
+ </metadata>
+ <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>
+ AAABAAoAICAQAAEABADoAgAApgAAABAQEAABAAQAKAEAAI4DAAAwMAAAAQAIAKgOAAC2BAAAICAAAAEA
+ CACoCAAAXhMAABAQAAABAAgAaAUAAAYcAAAAAAAAAQAgABx9AABuIQAAgIAAAAEAIAAoCAEAip4AADAw
+ AAABACAAqCUAALKmAQAgIAAAAQAgAKgQAABazAEAEBAAAAEAIABoBAAAAt0BACgAAAAgAAAAQAAAAAEA
+ BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDA
+ wAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAAAAB3AAAAAAAAAAAAAAAAAAB6KiAAAAAAAAAA
+ AAAAAAAHKqKnAAAAAAAAAAAAAAAAeioqKllwAAAAAAAAAAAHcqKqKiopGQAAAAdwAAAAACqioqKqI5mQ
+ AAB1AAAAAAoqKqJyoqIVlQAAkAAAAACqKiohEaKiOZmZmQAAAAAAOiqiB5EyqiEZcAAAAAAAAAcAAAWR
+ kqKjmZAAAAkAAAAFcAABkZE6KlmQAACQAAAAAJcACZGVGioplwAJcAAAAAAJlxWZGZGioZmZlwAAAAAA
+ AAAJkZGVOqKQAAAAAAAAAAAAAZWZGZIqMAAAcAAAAAB3AAmZkZkZKqAACQAAAAAACXAHWZWZWZKnAJcA
+ AAAAAACXB5mZmZmTKhFwAAAAAAAACZlxmVmZk3ogAAAAAAAAAAAACZmZkVAHpwAAAAAAAAAAAAeZmZmQ
+ AKoAAAAAAAAAAAAHl3mJcAACcAAAAAAAAAAAAAAAcAAAAKAAAAAAAAAAAAAJAHAAAAByAAAAAAAAAAAA
+ dwAJAAAACnAAAAAAAAAAAJAAA3AAAACgAAAAAAAAAAdwAACQAAAABwAAAAAAAAB5AAAACQAAAAcAAAAA
+ AABxkAAAAAeTcAAAcAAAAAAAAAAAAAAAB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD/z////wf///4D///8AH//4AA/n/AAHz/gAA9/wAAA/8CAB//vgAfv54AH3/OAA5/4AAA//4AH//+A
+ B9/zgAe/+YADP/yAAH/+AAH//+AY///gHP//4B5///9/f//7fz//87+f//ef3//n3+//z+/v/x/h9///
+ +f///////////ygAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA
+ AAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAHAAAA
+ AAAAB6IgAAAAAAAiqiOQAHAAAqozKhl5AAADd3EyOQAAAABweZKhcAAAAAdRmaKXAAAAAAkZGnAAAAAI
+ CVmTKHAAAAAJmZdzAAAAAACZkAYAAAAAAAAAADAAAAAAcIAAAAAAAAcABwAAAAAAcAAAdwAAAAAAAAAA
+ AAD7////4f///8B3//+AD///gD///9Af///gD///+B///+gH///4D////G/////3///9f///+7////fP
+ ////////KAAAADAAAABgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEZjkACGk/AAR1
+ OQAJIm8ABjlkAAgvdgAJOX0ABFtIAAVBVgAKWlMABVBYAAR4QQAGYVwABnJWADN5XQAJSXwACFt3AFJn
+ XwBFX3UATVt2AAGQHQABnxgAAK0NAAC9BQAAtwoABrQLAA22DQAAvgkAALgMAAC8DQAKugoACr0KAA29
+ DQABphIAAasaAB6oHgABtRMAE7QTABSwFAATuhMAGrYaABm9GQACiCQAA4AtAAKdIwADmy4ABIo4ACyf
+ LAA3jTcAOJk4AAKnJQAgpCAAKaEpACa1JgArsCsAKbspADGtMQA4rDgAPao9ADezNwA7ujsAAMICAADG
+ AAAAwQQABcEFAAXFBQAKwgoAFcAVAAWGSQBGlUYAUZNRAFiTWABKpkoATKdMAE25TQBXpFcAU7tTAFu1
+ WwBmk2YAapRqAGqeagB5mHkAVKFkAG6nbgBsu2wACBuAAAoAkwAKCZYAChSSAAsYlgAaEJ8ACCSAAAsm
+ nAAoO4gAODKVAAwHowALAKYACwCpAAwBqAAMBqgADACtAAsOqQAXDaMADACwAAwAtAAMDLEADQC5AA0A
+ vQARBbcAFAm1AA0XuwAfFLkAHBC9ACUdpAALM6EANC2hADcvpQA3L64APzilAD84qAAuJbYALyS9ADQq
+ vAAmObYAOjKyAEI7sABFPbYAC0SeADxJowA2RawALkG/ADRGuwBHQo4ARUCWAEtGkgBNSZMASUSZAFNO
+ nwBSWpQAVlKYAF5amgBhXpsAWXGGAF9mmwBkZZMAb22WAGVimwBta50Ab3OUAHNxmQB2dJsAcHWcAHt5
+ mgB/fZwAR0GnAExGpABOSKEATEWsAEdTogBIVKYATFepAFdSogBOW7QASVe7AFpUtgBcVrQAW1W8AGJc
+ uwBWYrYAbmugAGllqgBqcqcAfXuiAG5pvgBwbLEAcGu8AGpztQByerMAeHi3AHx5ugANAMEADgDFAA4A
+ yQAOBcoADgDNABIFwwAXC8MAGQ3AABEEywAfE8MAHRHIAB8SzgAOANEADwDVAA8A2QAPANwADwvaABAD
+ 0gAXCdIAEADeABcJ3gAdD9oAAx/WAAAd2gAfE9QAJxzDACIXyAAjF9sAKh3YAA0kxAAMJcwAFCvDABgu
+ wwAdNMsABiLVAA8p0gAEINoALiPHAC0iygA5L8cAIzjHACE3yQA/NcwAMSXTADcs1AAPAOAADwHqABAA
+ 4QAWB+EAEADmABMF5QAUBeQAFgjhABwN4gAYCeUAEADrABgI6gARAPEAIRPiAEY+xQBEO8sAMEPEAFZO
+ xgBSScsAWFHEAGBY0QBzbsAAcmzLAG15ygB9eMIAdYOdAHuBrwB+hbQAeILHAP///wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQ/P0JHAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUQj8/Pz8/UAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEo/Pz8/Pz8/IQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAOT8/Pz8/Pz8/PzEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp
+ Pz8/Pz8/Pz8/Pz8EurhwjAAAAAAAAAAAAAAAAAAApQAAAAAAAAAAAAAAAHQAACA/Pz8/Pz8/Pz8/Pz8V
+ Y7fBwr4AAAAAAAAAAAAAAJnKAAAAAAAAAAAAAAAAAAAKPz8/Pz8/Pz8/Pz8/Pz8/C7W5wsTHAAAAAAAA
+ AAAAluewAAAAAAAAAAAAAAAAAEw/Pz8/Pz8/Pz8gPz8/Pz8/F1i5wsPIwAAAAAAAAACa598AAAAAAAAA
+ AAAAAAAAOz8/Pz8/Pz8/PyYUDD8/Pz8/PwJsxsPI5n4AAAAAAADJ0QAAAAAAAAAAAAAAAAA3Pz8/Pz8/
+ Pz8/GhJbYC0/Pz8/Pz5WwcLI5ONyeXZ4eMDrAAAAAAAAAAAAAAAAAE4/Pz8/Pz8/Pz8dXFdoaFodPz8/
+ Pz8rbcLI5ObGze3s7O8AAAAAAAAAAAAAAAAAAABCPz8/Pz8/PyGPjmdpaGgHPz8/Pz8/BcbE5OPrAAAA
+ AAAAAAAAAAAAAAAAAAAAAAD7D0k8KkI/NgAAAG1raWlpDT8/Pz8/ImTE5ObsAAAAAAAAAAAAAKL6AAAA
+ AAAAAAAAepMAAAAAAAAAAGxsa2trbS8/Pz8/PwjB5ObspgAAAAAAAAAAfeAAAAAAAAAAAAAAAMaNAAAA
+ AAAAk7ZsbGtsbGojPz8/P0JZ4ubs3AAAAAAAAAB77QAAAAAAAAAAAAAAAK/BlAAAAAAAnba1tbVsbLVd
+ HD8/Pz8suObu0AAAAAAAAH7uAAAAAAAAAAAAAAAAAAB/vQAAAAAAdbe2trW2tba2ED8/Pz8/Bufj6wAA
+ AAAAou6uAAAAAAAAAAAAAAAAAAAAzruHiIZfbrm3t7a2tra3tw4/Pz8/Fmzs7uju7uvr7vEAAAAAAAAA
+ AAAAAAAAAAAAAM/Gwca6usG5ube3t7e5ub0uPz8/Pwvm7bT49vT0+AAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAnsLBwbm5ubm5wcZvJT8/Px5m7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq8LCxsHBwcHG
+ wsLDc0I/Pz8DewAAAAAAAACXpwAAAAAAAAAAAAAAAADbAAAAAAAAAMTDwsLCxsLCwsPEyBE/Pz9CEwAA
+ AAAAAJzvAAAAAAAAAAAAAAAAAAAA56oAAAAAAMjExMPCwsLDw8TI5ORFPz8/JAAAAAAAfe4AAAAAAAAA
+ AAAAAAAAAAAAqOOqAAAAANrkyMjExMPExMjk5ObFMz8/P1AAAAB97gAAAAAAAAAAAAAAAAAAAAAAAPDm
+ rQAAAKvk5OTIyMjI5OTk5ubs0h4/PxsAAJvu9wAAAAAAAAAAAAAAAAAAAAAAAADg6Y2Sk4nm5ubk5OTk
+ 5Obm5uzu7oA/Pz8Cx+7zAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Ozs7Ozi5ubm5ubm5ubm7Ozu7uFTPz9A
+ XvoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Ozm5uzm7Ozs7OPu7QAAPT8/MAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAALxit+zs7O7stWFsAAAAACo/P1IAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAIVst+Tu7u7kZWy/AAAAAABCPycAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG95Onu
+ 7u7jvbnkAAAAAAAAPz9IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKfm8QCzALQAAOr1AAAAAAAA
+ TT8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChAAAAAAAAAAAAADg/MgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAACEAAAAAAAAAAAAAABDPwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAmIMAAAD81AAAAAAAAAAAAAAAPyQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1P0A
+ AAAA16AAAAAAAAAAAAAAVT9PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQ1wAAAAAAo8wAAAAAAAAA
+ AAAAAD0bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTqQAAAAAAANnVAAAAAAAAAAAAAABERgAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAIHXAAAAAAAAALLMggAAAAAAAAAAAAAAQwAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAlcyxAAAAAAAAAACEzJ8AAAAAAAAAAAAAADUAAAAAAAAAAAAAAAAAAAAAAAAAAACV190AAAAA
+ AAAAAAAA3syBAAAAAAAAAAAAAEtSAAAAAAAAAAAAAAAAAAAAAACsy9LM2AAAAAAAAAAAAAAAAN7M1IuR
+ kAAAAAAAAAA6AAAAAAAAAAAAAAAAAAAAAAAA1tnyAAAAAAAAAAAAAAAAAACkzMzMzAAAAAAAAAAAUQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP75AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///////8AAP/8H////wAA//AP////AAD/4A////8AAP/AB////wAA/4AAP/9/
+ AAD7AAAf/P8AAPwAAA/4/wAA+AAAB/H/AADwAAAD8/8AAOAAAAAH/wAAwAAAAA//AADgAAAB//8AAOAc
+ AAH/nwAA8/wAAP8/AAD5+AAA/n8AAPj4AAD8/wAA/PgAAPj/AAD+AAAAAf8AAP8AAAAD/wAA//gAAP//
+ AAD/+AAA/n8AAP38AAD8/wAA/nwAAPn/AAD+PAAAc/8AAP8cAABj/wAA/4AAAAf/AAD/wAAAD/8AAP//
+ AAYf/wAA//+ADw//AAD//4APj/8AAP//gA/H/wAA//+Kz8f/AAD///9/4/8AAP//93/z/wAA///nP/n/
+ AAD//+ef+P8AAP//z5/8/wAA///Pz/5/AAD//5/H/38AAP//H+P/vwAA//4/8f+fAAD/8H/4H98AAP/4
+ //wf7wAA/////z//AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN1NAAZH3oACSZ/AAg9eAArMXwALTx9AARrQgAFd0kABmFVAAZI
+ YAAHTG0ACF9uAC5UZQABmRsABrkGAAC/BAAAswsAAbcPAAC6CAAAvwkACbwJAAOlFwABrREAAa4VAAGj
+ GwAdqR0AFr8WABm0GQActhwAApAmAAKeJwA1njUAAqogABaqJwAjpyMAJaYlACWzJQAjvCMANa01ADi8
+ OAAAwwIAAMYAAADBBQAEwgQAAMgAAASKQwBEm0QAU5lTAE6/TgBUqVQAappqAHufewBesWQAZqJmAGin
+ aABpvmkAdaB1AHquegAKH5cACiaKAAo1lgA1LpgADACuAAwKrwAMF60ADQCxAA0AtgANALoADQW4AA0A
+ vAAiGqMAKB+pAA0jvwAvJ6QANCyjAC09qwA3MKEANSy+ACE1vQALR5oAPkqgADVFsgBUUJsAU12fAF9k
+ lABlYZ8AaWacAGxpmwByd5oAU0yvAEpDsgBJQbQAUku9AFNMvwBJVrEAUl+3AGFppQBua6AAcm+mAGhw
+ pgB2dKAAdXKkAHZ0pQB5d6EAf32jAHt4pQBkbrQAc269AHZysgB7d7YAfHm0AA0AwQAOAMYADgDKAA4A
+ zQAOBswAEAPBABcJzgAYC8kAHRDNAA8A0QAPANUADwzTAA8A2AAPAN0AFAfRABAA1gATBdQAEADaABMF
+ 2gAQAN0AAh7ZAB8S3AAmG8MAIhbPACYayQAmGs8AKR3JACAT1QAjFtQAJBjSACYZ2QAoHNsAByLPABUs
+ wwARKs8ABSHVAAgk1gAxJ8IANizCADAlzAAnPMIAPTTAACwh0wAzKdIANivRABAA4QAUBeMAEADlABoM
+ 4QAQAOkAFATpABEA7QAXCOgAEQDwAEE2zgBUTMYATl7JAFxWxQBaaMUAaGLDAHx3wgCAfbMAg3/EAHGB
+ hgB7gKMAf4a5AFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/kbIA/7HIAP/R
+ 3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/cdEA/5HcAP+x
+ 5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0Uf8A9nH/APeR
+ /wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCmMf8AtFH/AMJx
+ /wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+Ef8AWDH/AHFR
+ /wCMcf8AppH/AL+x/wDa0f8A////AAAAAAAAAAAAAAA2OQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAA6Ki0tJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMi0tLS0tMwAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAACctLS0tLS0VBUpTAAAAAAAAAAAAAAAAAAAAAAAAZ68dLS0tLS0tLS0BcHl2AAAAAAAAAGVeAAAA
+ AAAAAAAAEy0tLS0tLC0tLSoDeXyCAAAAAABojgAAAAAAAAAAACwtLS0qKhoGGC0tLQ5Gep2IAAAAAKAA
+ AAAAAAAAAAAqKioqLS0ZAj88Ky0tLQp6g59+pKOkAAAAAAAAAAAAACIqKioqJQA+Q0ILLS0tEUCDn5kA
+ AAAAAAAAAAAAAAAAAFUAAAAAAEhEQ0MILS0tB3yfogAAAAAAAJYAAAAAAAAAXFYAAAAAdXVGRkUfLS0p
+ O5+lAAAAAACLAAAAAAAAAAAAhmkAAABycXB1cEESLS0efKNqAAAAiqwAAAAAAAAAAAAAd01LR3NycXFx
+ cz0qLS0Eo56loqKnAAAAAAAAAAAAAAAAAAAAenlzc3NzeQwtLRd0AAAAAAAAAAAAAAAAAAAAAAAAAACA
+ f3l5eXp6fC4tLQkAAAAAAFoAAAAAAAAAAABdZgAAAE6BfH9/f4GDeyEtEAAAAACJAAAAAAAAAAAAAACa
+ YwAAbZ2Dg4ODg52fSRQtIAAAjK4AAAAAAAAAAAAAAACFYgBXn52dnZ2dn6OjUCoqDYerAAAAAAAAAAAA
+ AAAAAACbj5yXoZ+fn5+ho6WmNS0WAAAAAAAAAAAAAAAAAAAAAAAAAACVcJ+jo59GeAAAKC0zAAAAAAAA
+ AAAAAAAAAAAAAAAAAFhxgaWlekZbAAAAGxUAAAAAAAAAAAAAAAAAAAAAAAAAb4NuqamtjWwAAAAAKi8A
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAAAAAAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAUgAAXwAAAAAA
+ AAAxJAAAAAAAAAAAAAAAAAAAAAAAALBrAAAATwAAAAAAAAAmNAAAAAAAAAAAAAAAAAAAAAAAkQAAAACY
+ YQAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAFRgAAAAAACTAAAAAAAAAAAwAAAAAAAAAAAAAAAAAABZkgAA
+ AAAAAACTAAAAAAAAADgAAAAAAAAAAAAAAABfkJQAAAAAAAAAALGETFEAAAAAADcAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAACqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/z////wf///4D///8AH//4AA/n/AAHz/gAA9/wAAA/8CA
+ B//vgAfv54AH3/OAA5/4AAA//4AH//+AB9/zgAe/+YADP/yAAH/+AAH//+AY///gHP//4B5///9/f//7
+ fz//87+f//ef3//n3+//z+/v/x/h9///+f///////////ygAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAABHw/AAZYXQAGY1sAEUJxAAC8BgANug0AAq0cAByvHAANiiwAAp4iAASN
+ OQAjoS0AJbglADeoNwAAxgAAAMgAAADACAA4wjgAPZNSAEasRgBYtlgAX7hfAEWJZQBgl3cAZMdlAGzE
+ bAALK54ADQC2AA0BvgAMErIADCWzAC8lvQAzKbgACkqUAFhTpwBXUa0AVE2/AEdVswBSYL8AamasAHp+
+ oQB2dakAcnmsAH57rgBnYbsAcHizAHt4swAOAMAADQ3AAA4AygAPANUADwDdABAC0QAVB9oAEADeACke
+ xQA2K80ANivVABAA4AAQAOUAEQDpAFZOxwBQR80AfHTkAIB9rwCCfc4AeoG1AHiBvAB2gckAAM9AAADw
+ SgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvP
+ AAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEyw
+ AABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQ
+ AACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBb
+ AACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAi
+ AABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8D
+ AABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAA
+ AAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP//
+ /wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R
+ 8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx
+ /wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R
+ /wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx
+ /wCmkf8Av7H/ANrR/wD///8AAAAAAAAOAAAAAAAAAAAAAAAAABYPEAgAAAAAAAAAAAAAAAwPDw8QAjUA
+ AABBAAAAAA0PDwkEDwUeNiMkAAAAAAAXFRoqHAMQATsAAAAAAAAAACwAKDAdCw8bJQAAAAAAAAAALSEy
+ MjEHCjlAAAAAAAAAAAAAMzMzHxEYAAAAAAAAAAAvADs3NzwiBilCAAAAAAAAAAA+ND00PxkTAAAAAAAA
+ AAAAADg6IAAAEgAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAALgBEAAAAAAAAAAAAAAAAKwAAACYAAAAA
+ AAAAAAAARQAAAAAAJ0MAAAAAAAAAAAAAAAAAAAAAAAAAAPv/AADh/wAAwHcAAIAPAACAPwAA0B8AAOAP
+ AAD4HwAA6AcAAPgPAAD8bwAA//cAAP1/AAD7vwAA988AAP//AACJUE5HDQoaCgAAAA1JSERSAAABAAAA
+ AQAIBgAAAFxyqGYAAHzjSURBVHja7F0HgBPV1v4mfbPZvuwCIkXFhr377A1siGJBUECaIgpYAQEFUWkq
+ IlhApAkWREFQsfvs79fnsyv6LA87vWxJT+Y/ZyY3mWTTN9nNLjl6SXaSzNy5c8936j1XQp7ylKfdlqTm
+ 7kCe8pSn5qM8AOQpT7sx5QEgT3najSkPAHnK025MeQDIU552Y8oDQJ7y1LJJwmEw4id4UQdZc1xO7sd5
+ ylOeWipJ6AIbzkAZluBPggDB9DLyAJCnPLVqklAEE8YR+z+MD/AXnHTMH2h5AMhTnlo1GaDHZPTGj9iK
+ pfgYKsMz83sRAoGElAeAPOWp5ZEO5+EIXIL+uJ5goF5hdh81NzUP8hpAnvLUaomdfu0wE49jIibhE/wK
+ VeIz87MZIDSAJE+WpzzlqaWQhGJYyOZfiN/wCybg0cBxlvp2qADAmkBS0l89YZ7ylKeWQnpMJ6X/MAwn
+ 5f9SbFGYniV+faCxFpC09GfKA0Ce8tQySEcsfwZGY4Wi/C/B21CZnUGghpoDKhgkLf2Z8gCQpzzlPkk4
+ FXuRxf8KNmEzBpMWYFdUfVb5d1GrpeZCitJfPXGe8pSnXCYJbWDDQ1iGPdEDYzAIH+BnqAzPzL8Tqvqf
+ ku0fOnme8pTbJEW8j2yC5IiGKK8tjSRifQPuxV1k999CjP8cxmEusTqr+qz2b4cKAq507zEPAHnKNZI0
+ r9x0gaY/x4IOexhx3IkmHLK/BfsagAr6QiE1Hem+Oz3A5u0+/L3Ojh93+fDRaw58t8UfDItpk2NaCiDo
+ MAC9MZwsfhcp/UPp3c/YBlXib4UKAEL6N2qw85Sn5iYt4ysMb5FgOdWCrv1s6He0Bb0MErpIKcxZv4xa
+ ux8fv2LHywtr8dzPXmyWVWYRtnIuA4EO3XEgbsc60gE64Ak8iHl4hXrMdj+DwGao0l8k/qRFeQBoSJES
+ SDLRwyjSoYBmZQE4FKMOuI/+cezyw+FpmH+dyxMr10iMt5D0hrY6lFxuwxm9bRjUTo+TJAmmxl6k3o9v
+ R21Gv3fd+C9Ub3laNnOTjUkXVOMRrEQZTsQGfEuyfzJZ++zs20FtI1QQYM9/yo6/8AvliamB9Kkkhj/A
+ gE6nWXFUZwOOP8KM/Sw6dKYvKJORZo7bLePXjx34kiTL68vq8K8/fcrDEepm4Gt5ikMCZBlUDUUSrCTt
+ zxhShJvLDTgaGZ6fP3uwrt8mDNrmVyRnSjnzTTomZbDgAczE/rieeunGDHr/Ij6FavdvggoAtUgj7Nfw
+ Yrs3aZ1JerIpDWRY7tG7EGedYcVF7Q04lj4okhKMkixDrpfx+Zo6LF1MquavPmxBHgjikda+Z+Y3nkAA
+ e2MpxhxqRm+Jl7pkgUhl29V3E875zI2voTrOGs1AGScd3fto9MdlpPCz5vMxPsA4PEqynpmf1f6/oEr/
+ tMJ+kbQ7A4B2EhqMgHlUMS66shgTC3XYKxVbUxABgX+bD5/M2IlJrznwgUMOZmYlvTijlZNW01IYv1iC
+ bUQxLu9bhFutOnTI9oS8ewcuWVKLf0JNoEk5cy7LpEMfHEcA8CK9K0cdaSq3kvz/HD9BZfo/oWoAdVDB
+ q9G0uwMAMz+r9OajTOi6qAqrLRL2UD5sxMh4Zex4xY7779iOR+vk4MPa3f0DWlufJbxxXz3a31aGcScU
+ oJ9OgrkpOjFhO/quqFMAgFVosYY+F0hCB7L7l+J1FOJgmiUyVuMl3IfnqIcc62fJzwDAnn8GrozMo90Z
+ AHgikuBXJl7hxFIMGlCEe8SHjQEAJtIG3B86sHTcNkzcJIfZnMrHzX3zTUxh2hY18ykWHDSlDPeRmXUM
+ jbWuKTpBwGy/cjP6ferCf6Am0LATLe0QWkbHp5rsfjXZ52LlyEb8jeuI/f+kV9Xm/x2q9Ldnss+7MwCw
+ CqowP7Wie8sxo1chLhEfNhYAmAgEfN+4sGbcdoz6r1eJ2+6OIKB19BmJ+y1DbTjnmlJMt5HMy8Q4J0tf
+ u/DvAZsxulZWpCk7bBsVQ88g6XEvbsaJmEojpace+fAInsKTeIc+Y38SMz/3mUGrUWG/SNqdAYAlEYf1
+ iqmV3V+B+3pa0UN8mKmJSU9K/t2N14ZtwaBffMEHuLuAgJb5TTTgBXeWYdDFNkwySArwNhk5/agn9f/u
+ NXa8ATWJJlcAQIfhOA/9ieH1sClHvsd/cS1BgENx+v0BFQAYCBod9ouk3RkAWP3nAS+lVjmzAndeaMU5
+ 4sNMSibm8p9dWH3pJgypQ3AJZy6GoDJJgvkVe58QoHBuJW4+qwC3pKvyk0bFg+bf7kftejf+/t6DHbt8
+ cPAgFupg7mKAra0eRXsYUF5Gr/rA/N7ow8YHduKJF+x4CyojsUONwZifRXP6AHQ4EvuQov8aGQCdld66
+ SUDcSMbAf/AdVKnPBT/YDOAoQMZzF3ZnAGDnXxG1CmptBtlw4W1luEV8mA3V9J92PHLdVkzwqEieUumm
+ FkZae99EKlbJA20w5WQLrqJxTXlk/TJkZvp19fjmLQfWf+zCH96GyTzatGGpXAfTPkYUkY3n/tSN7wkl
+ mPFZ8gvmb24nICf7VGA2VpD9f7pyhO/kdfwLk/AMVHufmZ+l//ZAXzM+V3Z3AGD1nwGgqoMe+z/XFlNp
+ 4lQqAxNlZGQ1j9THIUKaZbpUQYImsufpOoyasgNP+sPj0K0JBMKYv0xC+exKTP2HBX1TZX4e7x1+1K2u
+ x6dP1OLjP31BDzg3H2IDgNAweHzFenl2xO4IvNYgFAZsjrHnyj5mzMI0dMNoiHGpRR0G4gGS+8z4v0EF
+ ABH2y4qpsjsDAJsAQQ2AWvVlheg+vgwDrBKszNw+GX6egP/zYNv3pHJ+5cbWGj8cegn6NmSvHWdBhyNN
+ 6ETvEyYLCSJbdNuYbbj8FQchvToBRTy3NYBAmKe/UELZgxWYckoBrkxV7Xf54XnPifVzd+Ht7zyKHSxK
+ Xrk045YMAPBv2NZniV8XeLWjOROBjDQ+16Iv/cfJPlblGPdiPl7CErwJ1e7/H9SwH4NWRh1/WtqdAYAn
+ qfABMAhU0oEqYupDzrfiGGJ0z79d+PtHDzZu8Coqo3ZFmZjkhk4GVFxhwxGX2HA4rxdI5sJbvfhi5FZc
+ SarpL1Afbi7npSdLYZKfmX9aOcafY8UQYv6kM/tY6m/2YSfZ7K+tteMzd0haMxM7A00LAEKF1yHkcBQA
+ wJ+7Ar/hczgCjY81lwmmwwU4FmOwikalbfDoBpL7QwkC6hTJz8zPr1uQZT/F7gwAPFGYYVkLKNM0BgT2
+ UHOIUJRbjjbZlIlOzcLtBDP2nlSOc7sYFW0iLnHq8OcurBq2BdfXyGGRgZYKAlqHn5k0qOK7ynFTTyuu
+ 16WwkIeZn8bl50k7sHq9R1F/hdTmJhhYqwEIUNamdGs1AH9gbD2a34m/m2O8JeyHdrgPz9MsOS541Etz
+ azyW4z0lP2FDoLEDsAZZ1lJ2ZwDgScJMzioYg0BxoPF7BgZj4HtexAYAc+C7DBi2joTo91fgwsPM6Jzo
+ 4n4Z7uW1uG3aTiz0htdza2kgoGV+Ew2IbVwZBvWz4Q4ylSzJnoTGw/9CPf5v6k6s2+lXwl88+WsDjaW/
+ 1gQQWpOWibUAIOa12CxDC+KRv2u6caqiufIQqf17on8Y572HrzEBz9BdsdRnrZAdf9vQBE7K3RkAxKTl
+ SWoNNGZkZmhz4LNEGoAAEDYlSqgVtdOj7b0EAsda0DVRB+x+/HXLNvR9w6Egv5BqLQkAwuL8NCiFQ224
+ 4IZS3E9/FCd7ErcMz5ydeGVxLd5xharc1ASaVvoLCa4No2oBQNsnoGH6dWTFoKYbJ/aBTMZIdCf5Lynj
+ pVId3dv1WIzv8S1U1X8D1My/jOX7x+/Y7ktCWrCkV9YDBJopcCy47h/hkkP8VqQRCzOCAYDNh5IOerSf
+ 1wZX7GdS1xXEIlZ5//Di3cs3YcBmv2LvaRcP5TppJS6PmfUsC06YVYkFBbrEZpCgOj/sd+/AqtX1+Nin
+ Orx2BprQAITdLhhf6y9pCeMEZYyG4h8YjFfonS3sk2fwAebgRXrqG6ACAEt/HocmiVDszgAg7l8faErC
+ CkJOJG6x9lsLqrwImQAMAEFfwl4GdHq8CgMJDCriRQjYH7CyDpNu34G5/paVHxBM7+UxOMKEfRdX4flC
+ Hdone4J6Yv7btuHJdQ58BnXSCwDQMn+kyo8WMDbh47QfCYLHiNHN6BT2yZ+k5o/AImxSipQI6c/mT0bz
+ /eN3bvemyEIgWvtRkGB8f8TvIs0A1gJYAyiHGlUoP9aM/R+uxIASffy0V6+M7ddsRs/3XPgKubpOveG4
+ Ce2poI0OlS+2xcpKAw5N9gQ1ftRP3Ibl61TzhxmfVX9mflb/Wf0VKn80db+lkIS2JCAex3M0I84Jm1k+
+ uqd78RJeUPL9NyAU9tuJJnz+uzsApEuRS1tZE1AWFUHVADiZSAGBfjacMKEMF5kShMK+dOHlqzZjaF3u
+ RwWE6s/Mb6EbLyaQm3KaFVcle4JdPtRN2oGnXrLjE6jML7LzBPOLUF9LlfrqOJlojO7AJJyBsWF2P9MX
+ xPA34QmS9cz47PhjByBnKmY83z9+J/PUGNJWtRErC9n5xVqAAgL0YeW0clx6UaGy7DXmeHMxkQd2Ysij
+ tViNUFQgV9aqa+9XqP7sPC28vgiXjirFLF2SsX5m/snE/C/alS2tWeprmb8eITNI2PotjfFV0tN/N+Bi
+ +m8xzRBr2Gd20vJuwwoagX8jpPpnLd8/HuUBoPGkBQERURCmADvDKst0aPdUNYbvbcAe8fwBZBP/fMZf
+ OGubGgZjUyDXEoQE8ytmz8kWHDG3EkvJ7q9O5sd2PxwTt2P5Wjv+Dyrjbw80nvha5m+pKr8gHU4hc2gy
+ nicDoEvYJ3xHb5Cpdyeeoae7ASHHH49DRsp8pUJ5AMgMaX0CDALaDEMFBI4xo9vjbXB1gS5+5Zvn6jD1
+ tu24D6ojKJccglq739pOh/ZLq/B4F5NSNzEheWX4pu3As0vrlFRXnuxiSa6Q/E60DuaX0I0s/5nE4BU4
+ ucGn28nEuR5LSOn/BiHpn9V8//idzVOmSMsgDAJKnQEEFhtRqxxahDPHlKFXvEF3+bHtqs04m1ewIXcc
+ gmF2v0VCCZk1Y863YrgUadtGIY50LKjBK/ftwmp/aEWeiPdHMn+umT2pjZOVZP4M+u8ojEDk+gc/Pcel
+ eBfz8TJCjj/O+2cTqFkWJuUBILMUFhdHyB/AWkAbYpy2i9tg6FEW7BvrBMwsnzjx9JVbMAqhLZ+bWyJq
+ /Ry23lZ0v7sCD5kkxemZkN4ge/+mbVjqkBVJJ3a0EXvatRbm56duINt+CM7GbETLgvwdW+jTBWTw8N5+
+ zPyc7izCfs1y73kAyDyJcKJwCnJ+ADsEGQSqDjPhwCeqcC2ZAjHTZN0yaq/dgovecypOorS2fc4gaUGt
+ cE89Oi2vxuI9DDg4mR+vd+N/gzbjoa3+4OIWwfzC2986mJ/H6EIch1uxlqCyosGnLP0nYiXexkcISX/O
+ 9xf1Ipvl+eYBIPOkzY0X/gARGqwiTqq6sQTnDy8hORGDOEPwUxdW9tuM66AySnNlCGpV/wJCgJL7KpQV
+ fsOSWdu/1Ysdw7ZgztcerEeoEs8OhOL8rYX5JRxOdv99eIUgP3ouxL/xE+l0S+kJstQX+f6sDTVrZeI8
+ AGSHovkDhEOwqlSHDqwFHGBCx1gn8MioIS3g0nedSrisucKCwRV+1IrOKcCJD1RikUGKSGeNQg4/HGO2
+ Y+ErdqXugajGw8xfg9bG/CYan2fxDKrRKypHueheh+Jx/KhsSLIBoXx/znZs1khPHgCyRwIEIk0Bdgi2
+ 6VGAY2dV4iqyo42xTvCFC2sHbsZwuxx0EjWlFhCm+pdKqF5ehfn7m3FCoh9yIZWHd+GFuTVYI6vML1R/
+ bSWe1sH8RlL4p+NmGpXpUb/BT2sFqf0PkmkgK2q/cPxltL5/+jeQp2ySNj+ApaZwCFaZJWXp8IDuBTgy
+ Vm4AMVLdrdsw4EU7WY5NrwWIsGYBda94RBH63VCGaYl2TGIn5ntOfD5qK+bXy0pyi1D9Raxfm9/Q3NGN
+ xo/RKJyLvngOsTY2+ZsYfTBJ/x0k/5sp3z8e5QEgu6S1oTkqwFpA0BTY34j9FrXBiDYGJWcgKn3sxOrB
+ m3GdW3UWiUSRbDOOVnuxtdOj05q2eLpcj70T/fA3D/4evAUPbPAq21lpK/DWoXXVQdThJHTFXXhVqegb
+ jTjffyZewpoG+f6N3tY7U5QHgOxTcL08IhyC1NrcWoKLhhajhy6GU81D6v/wLehLUpVtae1qwWz2Nwha
+ 9KZkShlG9S3CjYl+6PTDPXYb5r/swAcIt/uF06+1lENXK/rOJcu/AqfF5KL/4BfcguV05+z0a7Z8//g3
+ kqemIG2WoMgNUACApGuXZVUY2cmoqQ8XQe858NSILbjZFdICsilBtbn+RfsYsM/adlhjkhTgikms+r9k
+ x/u3bMPjPjWzjQFA6/RrSbUO4o9PEWlGd2MajsFIxEqE4nz/W/AUPlOWOgvVn8N+ze74C7+ZPDUFRSYI
+ KZuRIGAK9LfhzPFluMwQYzK5/Nh65Sb0+sKjVI0RG4tkYwIJ6R/s5/xK3HWGFf0S/fBPDzb224xpf/oU
+ SSdUf5HpJ1b25cSkbxSZ6BndRlZ9D8xusMhHS2vwKan/qzT5/iz9Rb5/zoxDHgCajsIkKzQOwQIJ7VZW
+ 48b9TBEFIzS0ohYzb9+B+2RVgmRrW2tt/kLRP8w4fGEVVhql+NWOvTK8123BrLfUkGWk6t+6nH7n4liM
+ w/MEBO1ifmszAd9ILMWvwTJfHPvnsF8ubEUWRnkAaDqK5hAMagG9rDhpegWuiqUF1Pjxv7P/Qs8takad
+ 2NU2kwyllf7KYqZHK3DnmST9E+15sKIOr03cjqWy6t3Wqv4i0681ML+EI9GeFP/VZMQdHfNbnPE3D2/i
+ CbyGcMdfVuv7p39TeWpK0joERfEQBQDIPqh+vho3dTNh7xi7EskP7cKNc2qwHKpk1W4ymqm+Bf0UB5qw
+ 79NVWFWoix2hYNrsw6aef2PytlCqr1D9tfH+nJr0aY2NjUB7Lh7D/mQOxeIavssfyc7nIp9qvr9w/GW9
+ vn/6N5anpqZgai1CYUF2CFYdTyr34iqM1sfYRedXN97vuQn9HbLCZMKTnCnmEj4KRfpPL8etFxfGT/nl
+ Ut43bcOcl+x4D6r0Z9Vfu8inNdj9HOHXYwqx9cmYhXgp0JzxNx7P4kPFFNqAJqzvn/7N5ampSesQFGFB
+ RQvg9mglhpHafWS0H/LeggM3o8f/ufAFVCbLlEopNBNlu/ROBuy9ohpPVepjVzXm9QpvOvDR6K14xK3a
+ tyLbTxTzbD3x/gHojuFY2aCib9iAUHuXbP7b8FQg3184/hism7zQR7KUB4DmIaFuKwwHjRZwiBHdniRT
+ wBKjcMiL9XiEpO4UqFIlUxNLrFvglOWykcW4alQJxsfbz2+TF5sJjKb/5MUPCDn+IlN9WzrzSzgRnTAd
+ /6Sn1TnuN2sI9K7FIlL8YxX6yMmxyANA81BYnj3CVwu2nVqOKy624aRoP3T48ceJf+LUGjloVzZ2com+
+ sO1fUiSh7TPVWLCfCUfE+gF7/adsx6Kn6hVHl1D9o3n9WzJx5kMRluA5VOOsuN/kO+WNvR7GSwgv9NFk
+ 9f3Tv8k8NReFOd2g2aV4XyP2JxX8Jpsuejnx8dvQd2U93kBmnIHCJ8HXKj3DglMfaoOHjFLsGPe7Dnw6
+ civm2mXFvtUu9Gktqr9Eo2HA/bgHh+IWJFr6zPn+AzCfjJ9ohT5yKuzX8Ebz1FykDbspzAdNRGB8KS4d
+ WBxd8nzgwPJBWzAWqrddONvS7YPQRIrpTcWcCkw6uxCXxfrBNh+2D9uC+75yK0tbeZKLXP/WpPrrcSv6
+ 4kJian2cZB8E7nQKVuEVvI/wjL+cyfePR3kAaF7SJgdpU4SruxjQlVTxm8r1SqQgjOr8+PuMv3DKdn9Q
+ yqTrYRbXV7L+6Jr70jUXVeixZ7Qvs9f/kRqsfHAXnpNDqj9L/8iFPi2ZdOiFw3ET1sKcxC5HXN9/JBkK
+ nuBSX+H4y5l8/3iUB4DmJW1ykNAC2BdQLamVgy68tgTnR/6IGNE3dhuuesGu2OCNyQwUGoiSmdjPhgvu
+ LMOMWM6/b9z4YeBmzNzlV+xbBgCt6t8aEn54G6/2eJDs/hIcl5A7OOx3PZaSLsRRGW19/5zK949/w3lq
+ btLW2tdqAVVt9eiyvAqjIxcKcQjuQyeeIDNgPFT1O10zQGgfJQYCnkcqMe10K86N9kWu6T+CVP8PXEqd
+ QuH1FzH/1qD6SzTyFjyAR7EvWfRJlDzDCzQWM7Ga7lxIf219/xYxFnkAaH6KTBEWWoACApcX4vTJ5eir
+ j0gR3urD793/wum1ssKIzISpqt/CCcnXLO9kwH6rqrGwRN9Q7SWNQ15aizX37MRTaKj6O9O4du6Rhcbi
+ HtyIf2AqktnlaAvZ+EPwOI0Gb+zJGX8bAmOTc/n+8SgPALlBWi0gbKGQTUL7BW0w/CgL9tf+wCvDMWor
+ rnzDoTifWA1PNdwk1H8lAnGFDT0JaGZEVvxhbeNHD36+fBPuqQl5/UWFn1zbvCQ9YpPncpxJtjwn+xQn
+ /D7n+8/GK3gWb6Hhxp457/gLv/U85QJpKwlrFwopNQNOs+CoBysxTFtKnGfYEzWYefdOslhVj3OqTieh
+ /peS6lH1UCXuPiOK+u/ywzVkC6b/n0tZ1x5N9W8Rtm4cknAKuuJOrEEEyMakb0jVvxFPkKXPVY9E2I/H
+ pkU4/sJvPk+5QmFluKBJESZUqJ5TicFnFuAo7UKh/7rx8QUb0denSuRUkoKExsGOx/IqPfZa1xaLSvXh
+ VYpZ+i+Jrvqzk6s1qP4S2pHJ9SCepDs/J6lfOEnC306awvvK/oYboAIAO/4YhFscGOYBILdIu1AoLDmo
+ mxH7L63CaLLRg/nodX5sGbAZF37tVtJxmSmTVT/D1P/uBTj54Uo8Gun9J4D5pe8mTNslK15/7Uq/yE08
+ WyKxV8WAubgDh2NCUk4/vtO38DWmkPLvDm7r/XtgXJwtcSzyAJBbFLlQSOsQbHNHGS690oazxAo9vwz3
+ mG24fo0dLyK8aGgi4msoqxHpRG0mleGGK2y4SqtdOP1wXLMF93/owqcIT/iJrOzbUkmHIeiNoaTKJyh4
+ EiTe2PNGLCO4/QqhsB8vhGqWjT0zQXkAyD2KlSJcVaVD+9XtMI5U9krx5TftWHLtVpJioWy8RBNRm/xT
+ Xihhj7VtMa+jAQcJAGDVfzGp/jN24pmI+n6Rqn9LBQAdzid7fxzeppFOamtzxfG3BO/iMaxDC8v3j0d5
+ AMg9ipYiLCoHVQy04dQJZRgotICfPPj6so24tFbdeDOZcKAwMzjaUNHVgANfaodnSSUwCgBY78ZPgzbj
+ vq3+oHOrdan+e6AE80lrqsCJSXPABtKCeLVfqL4/Z/y1iHz/+IORp1ykWPUDK4lzS9a0xbiuJuzDXyRV
+ fdvAzej3mRufI7lwoHA0KpGG4cW48pZSjGWpzwDg8MM+fAtmBVR/rddf7FHYklV/ieDUiNmYhf2IneMs
+ dw4jL93zVKwh2d8i8/3jD0iecpHibShSeooF+z/WBhN1EvTEuP5J2zH66XqsQigrMJ4fIJj7zxuVLm6D
+ qScUoLusTmF5QQ1W3bsLK6PU92sNm3roMZos/8sxJ+ZOPpHEd/oZfsb1ZACEF/po9o09M0F5AMhd0q7T
+ 124oUk4HrQ9UYtA5VnTnL71px7Jrt+J2qCG6eCqp8C8o25SRjdH2kw54zqZDWwaAr9z4dsgW3L/Tr0g3
+ nuCtR/VnaX8VTsZQPE8wUJ7071wEelfjcfygrH7UOv7YH+Jt7ttq/LDkKZcpuD8fQg5BboWdDWjzbDWm
+ lulR9ZMHX/bbhL47/EGPdCw/gPAtsEZRfqwZhzxZjRX8Qa0fNSO3YOYHLsXDLZi/9aj+h6Az7scLZFAd
+ ktIvV+ETpb5/uOOvReX7xx+YPDUlSZpXRcITZxv2gK5Sp0plFsT1O+HfuiVkW0Y6BFl6FdNB09VFOPPm
+ UoyiL+7oQwDwjVtZlRbPDyA0CuU8w4twxS1lGMfLfJfU4umpO7ESKtMz87cWr7+EjnS/s7AAHXBxSr/c
+ TvffH/NoNCI39mxR+f7xBydPTUVBpqdmIH2+YCDMJ5wNU99jYTjeAIlX/Pn9kLf+Ct/nq+Fe/ghcb2+C
+ XB/4nVgnwKYAS3BLiQ7WZVW4Y38Tjpy6HdctqSMJFyoSEs02Fdl/DABlz1RhxpFm9FjvwVcDNuMuUv2Z
+ 6blpt/IWzK/0f09IlnLoyugPPV2gnvq6c1fDjT9yBSh4+24TJmEszsAdMbfxikYy/TcL6wgSeWdmwfwt
+ Mt8//gDlqSlIMD5PQGM36KpnwXr70TBeRh9YZc2XxBfp1fUVPM+Pgn38f+DfjJD0ZlOAAYAdefoeBTh4
+ ViVmvGHHyhu2KfkAoia/L0ofhP1fSipF2ccd8DJ1qOC6LRj3vkvJJmSw2YlQToHC/HRh/Ukw7H0tLJcd
+ Cv2pbaFrT8cMBAA16+H972p4nn0CrnUEVtpS4M3PIHr671r0Rj8sRozyajHpG/ymOP6cSrafcPy1yHz/
+ eJQHgOxTUOpTM3WGVPkkbA/uC8P5/sD4C/GKwBcFUlDz/wzfq5ehdvh/IW9HSIKzJsAAYCRG1hMAjDrA
+ iK6Xb8IVW/xBFTXSD6At/lF8qgUHzW+D50j1f2TaTjwH1Wxge1+7n59EaodpAiz9hsEyzgKpQyyw+hbe
+ Ndeg/rYv4f8ToV2AgeYDAh1OxQG4i6S4MXyNQ0Jyk4S/BU+T9c+hULHWXxT6aOnrH8IoDwDZJe0qPzP9
+ Y1sA63hS+0cQd+gixaTKUJJgftF8r8H9yEDUT7arqieHBlmKs2OQGVp3kBHtHm6DKYM2Y/QvXqUwZbQy
+ YcKMYACxXVOEvj0LcVafTRhbLysmAzu16hAq78VkWoiCWy+A+QaZsCBy1mvBil7lrfD/uw/qBvwbvl8D
+ 128ux6GEvVGOOViLCvwj5V+/ii9xDyn/4WW+hOOv1Uh/daDylE0SzK/stnsq9Ic9gSK20608i/xRvhxi
+ fLUqBTfioB19UdvrVXi/DnyVTQHWAMzE0eYTYdjjhkLdUNllcLX1GkxWSFVG1Vkors2M6KHrOe2QN22h
+ VlnoOeRtj//lF9y+9z+Cj6U2gwBLfod6SRhHw3zuWBTMZ0XArxjF4X3VBTJpRJ/pYvLX8L5wEequ3gxZ
+ W7G4KUFAHcZleAj74JqUZ/gOAsDrsJQUf67vz+q/2Nizxeb7x6M8AGSXxMIeJYw3G9Y7esE0mGdRJAAI
+ dVowlMr8kiLu+f1yuGdfh/qZ9Na7J3RFvWA8+wIYTyFT4qhSSO3oOyZ2zCWzqE0lhaG9pOe7tpGl8X/w
+ vv8KPC+9CM+XNZDltpBKX0PxmnJI+wox7tf0VevU0IIVHXNOhH3QXLheRih5qKmkptq1sWT1X0j2eypO
+ PwRu8nG8jUWkA8iK048BQOT7txrHn5byAJBdCm61Ta30UxQ/XwTpAAEAwgSIZCiDhqGMARDYBP9n98Ix
+ 91KYehwFYw86aamERPv2RqdoP2I4oBnu3w7/hlXwvLwT/trBMI/xQzJo+yp+H+GrCAOr7+B7pztq+tSF
+ FyxtCubRoT+OwXBi4CjVlBPSzyTp2fEXyvfX1vdvVaq/oDwAZI/C6vzRH5XfoOQjmkVGLQAI0jKTMQAA
+ RoQAgL7rJxtbshHTFyrHkn90UoLPVOkuK5xaT6+7Aj0z06c+eh9pyMeS/qKvdK6N56D2on/D9x3CNwvJ
+ 7ngfiHZKqa7iFJN9mNzUx7uwGm/gQ4SSfkS+f6ty/GkpDwDZI23svrwDdB1fhu11b4CptACgGq1SUPVX
+ JanKTCalqYr9n/Qr0iCUZk6qgkX8zmnJS71hTq2lV9ICSG1R+xPNXImw+4N9FQBAxx3nofbyj+BlZhL1
+ A7LJQBIqle27H0VnXJny0HDPPsT3GI+nAoU+tPX9W3y+fzzKA0D2iMdWZN1Vct79ByheRzPJEGkUR6r+
+ gplMgffM7Kyi/0athN5zs6QBAPG+76Fzs/TfCS4z7CchqhomkRqAcP4ZILSVkMYiwIree3uidsAH8L6D
+ +IlJmRlnM11yHG7B2bgzgEGpUQ2p+DdhOb7Bl2iF+f7xKA8A2SNRdSe45dca2OaXQdeZGUq4k7Wef60U
+ NQUAQDCVE1yXy49yZUWrjsRd7EeX7EPVfs9F51elP+86qmoaOoRrAFrbPxystP1lzUF29kTdENIAePms
+ qCKUHQAw0OUGogcGEwPrlSzJ1IiRdSX+D7OULMoNgcZlvnagleT7x6M8AGSPBAAEi3uOgWVkDxjP02oA
+ qvQPOdC0jCQAgDWAjfQLts0rlE1rVQBI5+HF+o0rYPtvo+tspVd1BZIUdOELZ6XIaNLa/OH9ldgHsJM0
+ gGGfwseJNGLX4GyE0HT4Bw7A3XieBmS/tM6wkfo3FI/TTXN9f63jr9Xk+8ejPABkj7QagLLd16HQHz0V
+ 1sl+NY02KP0F42uZyRxgKHPge+tpLrLaX0GnLVWK2CUHAIm+I5yAWgDYAjUzqExjAojvRjNTQn1WX3+E
+ 99tzUTu8Rs2dF4uKMs1MEval4bgXy1BNyn86xJ7P+/EywQfn+29AqL5/iy/0kSzlASB7JHwAophHNTF7
+ +9EwDz4BptN4ZgXzg6EykxkhiW/WMNff4HW+MqEI716lC/gAkn14UhJHQgCwPQAAWxVzQ6d814eIfGYN
+ WJk1kj/Qf//9cD48E87lUCVpNjQAvpgZMzAVx2J00pV9Imk9WVW81t8TZP5Wme8fj/IAkD0K23gTqhnQ
+ zgZ0vgUFV+8HfVetyq+V+Op7laF20Dz8kXinhOZ4pWL/q1EAU4omgBTjL6EBuAM+gB0BH8BmasyxJYoW
+ IIWBVaR5IiQ/v/4G/08Xo3b835A5iUZUFMqsD4AX+UxAP5xDzKt2JXXyUX9G4Qn8h/4Lr+/f6vL941Ee
+ ALJHIg2Yc+9ZC2AA4CW/7btAd+gNsAxuB53FEsFAWsm/RWF+1SNfoUh/SXlvzVAegBYGRBRANQNkBQC2
+ BMKB1qCXP7yvWgDgVwIRx1DUzXgfvo+gVhPmwiLp7FoUj3TE+IfhdlLbdWkk+wh6HV9hEp4JlPkS9f05
+ 379F1vdPl/IAkF2KLO/dbm/oDh8M8830vg3b022ptaGZrK7sUVVrZsTfiV9q6LU8oPYL5rcFGE4f49Gl
+ 6xdgac8zX+QBbA2YAQwGnMlUCR0sGmaPBAI2mL+C1/8+PK8shnuOM7Rhhigqkgmm4so+VXiImN+EA9M+
+ Sy3suAqPkbX/PUL5/gxYrTLfPx7lASB7pK3pp5TgPhT6I8fAMo2U9/Y7iblqA8k3cuBL/APWPfXKD1R1
+ vzQQ9itRmB8KExoD6n8m8gDEMRbPbkULgAI8OwIOwW2B93pqbakfFUoEQgUBQ+D3HKH4kz4vUjUV3//B
+ 8/T9cM6sDcXSRTpw48bTQv89Qf/tiUvSnrk82PPxFpbgNSC41l8U+mix9f3TpTwAZIfEuCrLgKkVHwF9
+ t9koXGiAvCer2Vxup45e7WoOvuKQlgLqvyUg6YsD9j6rD4UBz7+aadf4CEDkZxwOZ/DhwLcwBXYFmH+H
+ 0l8Gq1B4UE35VTmGb7AsoKmUqYlK3n/CvWAcHPfUqWp1Y9cDSMr23XfhVpyIKSkv8tHSLwRK12Ix3dxP
+ CEl/9lW02nz/eJQHgOyQdouvgr0gdVwO2+PV0B3JDM96Zn3A5nYGcvBFWJAZiwGgMNhUhhNMZ0hT+ms7
+ Fu1vWUlPVn0BzoAmUBcAgZqAg1DdC1wORgVEX22B7ETRipT+wr0Qrjsmw/GYO7xASTogoCOmPQ/98SS9
+ K0r7qXio65zv/zo+wG6U7x+P8gCQedJGzCxku7d5EoUPHAnDeSTpJWcgxu4MSFSWuCENIBRbtwSYnk0D
+ oW6ny/yJnYBMstIDX0ATcAYYXgBVXeCYO9BXBPrK/SsMML0tAFrCRKBBqL0Xjuumw/mCV/UDpFMujCv7
+ HITb8TydfJ9GPZkP8QMm4OlAmS9uu0W+fzzKA0BmSVsByELSu/gRWMeeD9O1dFjvC6j7nsCrG6rdLdJt
+ RWKQNsNO5NnrUmD+ZJJ/Gv6tAgBzpgABdwCsHEHQUhcN+RDKYGT136pKfOVVOAmNgdChC/LffVFzyWvw
+ fYHUy4tLZO9X4CFi2iqc2ajZWku3cRNpEF8rOyiJfH8O+4ky6rsl5QEgcyT4k3lYKb01CubLJ6JgKklu
+ qxB7fg3DqzWz5Aa59mJloC7YQjZ/plT/hsdClQm1/VSBKgRYkWAVmQUozBSdZkD+hu+T81Db53v4NyF5
+ fwCrFRbcg5k4WtnGK327n6/0DD7CXKylK2+ACgC7Tb5/PMoDQOZIyxPW7jAc+TgKl9ig49h/g5rZapNj
+ 6sNSlpg+2vEQ24c+EX3yBQFLvEphYCVME7E6UDgodZqzsV7xGbzLT0DtSITqA8QHASOdaiwGkOX/SMDS
+ SJ/+IDWfC31sVCofC8ffbpPvH492ZwCIXhgn/XPxnFcKgFRBarsKtvkHQH9iNKaKdpFYF25Mh1I7JseM
+ LQig0vZH0pgkWi1F2yLO75sFx5CJcPIuO4n2GdShO47HHXiBkKUSjSHO+HsA6/BcWL4/O/5aVX3/dKm1
+ AkDk/OPaWToTb4FNbX/ozIdAX1oInZUkm/IdssudZOO6SCzJ/4G37nfIyuTgSjySKq189F6mN35PuMNI
+ iE7F7qd/imeh4IYrYL6RLytHfBEp/J3oeKKbT3Q80gTQAoAU5XvRj0kNviPF+J0T8tbeqDnnHfjWQwWB
+ aP4ACcehA6YT01pwUIq33nDgviKmH63U99cW+uAMxd0m3z8etTYA0M45xZwuJYl8AYwHHwPj+efCeEQh
+ pG6kplYjwPhxyMEbX1DbQWrwTmL6GrKFa/+Cv+YT+LY6aDLTZztpFv+9E/7tr8OzbTtd81QYDpuHwnmk
+ FgfDVZkAgUwNTLS/tSaAFPc7scBAivl5ODDI+Am+109GzYAdoRV34cWRSlCIpViOtujV6Jt2wI2b8STZ
+ H58h3PHHaRgtea/DjFFrAoCw2ppkj5p6w3jUrbDcthf0pwOpOZESpdqEbGTVM14P2b0D8pZKSIUl0JVq
+ v5PseyRxPNUBSXQ8lgmQPPMjqAMkAwJkTHgehnPMGDgWIXzfQXad6jEbt+FwTGn0zfMZX8HndKZngeC2
+ 3iLfv9XV90+XWgsAaD3wRiup4jfD3HckCqbokMJW0GEnTAwA3LyBEFltIEuuivAnHcZPxPDJAEIqmX+R
+ x6Q4GkAyYJAMCIj3O+D/tSdqL/oMPi7CIZhRwkCch+FkradT1iuCdNtgNw7CYt9mrPeqjr8NQNjuyckO
+ a6um1gAAWuY3EcNb7oK5/zBYpxErpu09jgcAgvl9mkq6nOHXjphfrNKLxuzJMH2mZ2QyzsBoJkDyTJ8c
+ CEQck1+E67GBqL/DKTzxZ6AbJuEFmMj+zwCdNNPgPGyVfksppNpi6LYUQ/qVtI8vVsH9r/Xw//A7/AwE
+ 2nqnuyUYtHQACGN+agWDYDpvKqxzjOoKvEacOD4A8KzxBLL5apUVc2ouvPg82mvk+3jH4h1PZlCSOR7L
+ CZhI5Y//GjpHPCBwQd5xPeqvqYHsOtVmPGz6fEffLXvJ+2diRlZ/K2HQcDM6efToTM9kT6WWgrrikk5f
+ +yf83zwF1+OL4Fr1p7r7stYfsFsBQUsGANH3IPNfQDb/g7AuLIK0R+NPHiskFpL+6mZ6qvTvqEnXSUbi
+ N4X0jxyoWMcyqwHEdgpGvt8G/8YaA0ruu95RsOQyF/zp1fUJIx2pZJeONuGozw3oRM+EG69iLFZyFUL9
+ 4l2RfoZ33TWou+lj+Hn3H22t1t0GBFo6AIhiugUHQbfXU7AtbA9d6ptCRD15bAAQ0l+smitVnNe6hBK/
+ qU2A5NV/9crRnICR6cfJ2PiJTAHxN/tP5lzgxJSbHXCbM3PPB76kx8VTTehMaMLSvwNNkXKE9lHQ3gtn
+ N2yC/4uhqO3/Dvw/oXk3NG0WaqkAIJ6lsm6mQllwY5t1FPTnZeqeogGAVvqLTTS4lt6eCaR/Y0J/qczE
+ VJyAqYQBkwGBZPwB2u/x1T7Z34s+99diS0Vm+K1gO9B/mBkH/qmq/h2J+auhLlCKtYRaVkoC+T85H7X9
+ NoS2Nt9tQKAlAkDYghtCgKLZKLjpMphvABIXh3QCbnrgW7fAX7cdfmedGotmJNHTRDHQSSWy54303kSm
+ hIXzCOhvM0kQpfacWj9PcfxJuwIVe4oVH3r8jL/GgUD8uZgoYpGY+dWrxNIAkn2NBwLhoUDgzwo/LiXm
+ /3o/X2ZmIZ305DkGnPW0UVH7OxPL7xGooJyogAqNr/xf+F7phdphf0DmMGFz7GrcLNTSAEDr9DPTG9sQ
+ mC6aCut9OnUPvpjEWXxr4f7qdjje/gsyJ4LE2rVWO1eCa1ro5MZq6ApoQjEgWAuAkmNh6DICloP0cTL+
+ Uon/J2L01AdLivgbMf8WYUDt8cYzf3R/QL1JxnUT6vF8D3fG7rX6OwlXjjJjrzqV+dkno5Zak8LWJcQi
+ nh8fwb2gD+rG7wyFCls9CLQkANA6/Zj5rX1gPO0BFM4zIuGOMPJb8H47DPXP16jMzzMvFsprtVWd5lU0
+ xedAb2zLUdj7dJj2TsX2byj5G86vxsy46Ha/FPd78ZyAjWP+hqaARyfj4cucmDzKkRGnH5PeBVww0YTj
+ 3jcEpL9OCckWaaR/MuSH7J4Jx63T4VzqDd/UtNWCQEsBAC3zKwtuToX+4KWwLSNVPWHceD18v1+BusW/
+ QeY0UK5zwbk7DADRc9HDmT+YXRhonFtgOxr6fZ9G0WC6vpJrkBoIZJbpEw1a+DEpxueJw4CpgkCkKcD3
+ /fqxHlw1vQ72ggzdJA1c5zd03p5TjN72Xp2/PfS+9pD85dDJZJrpzPTMyHwzFCg5Iom3U/dA3jkJ9iEP
+ w/W6L3y9QqsEgZYEAIL5LQdD2ms5ipaQjZdwschmsukGoW7Bx/DxUlAuUMnqHaN7rHXpsTQAEW4spAMl
+ s2AdcDnMp6bL+E2dAtxQ/Y8EgvR9AMkcY/phTz8uebAWv7fPYBbuDnisN2K94Xuu6ivtJCm+nR5WPZll
+ nmLFlwMLaQKFZ8HUZTjMR5eSGZfolPWQfx2J2oEr4f1Ujr1oqVVQSwAAwYAK81dDavsCbAu6Kktt4xOJ
+ esf1qF+0Fp5PoC7/5CYAQGgATNrF8FKUJnbw4slTtDd0+6xG0d2V0FWKH2tfG76PzfiZiACk6/1X/w7J
+ 53R8AMkyfw2NXN/7avHRkRksvsNFCpbhF8zDt5CV0l68yo+fsSjwKUoWmOmNeQBMh85A4dmFAYduPNoM
+ 37fno/by7+D/GbG1xRZPuQ4AgvkVj38FpPJlKLz3GBh6J+o7L9u9A/an58H9BtS6b+zdFQAgSvH5YlxT
+ iri+KPDJK/xKb4Clz62wjCTm0cXP+ovO+M2RAhzfAaj65hujAcT73CPJGHuTHYsvzZzTT6FfSaMbgX/S
+ 02XTTrsRiSvwDfHc2Eyz0iQqHIeCk2+G5XQjpISLwzbA994FpAn8kloloxZFuQwAYeE+4ryiR2AdfzZM
+ 10hJrOxbBNer4+FY6VVLPvPEYABgByCnfmqrW0UzASJfhfQvKQHaPYuiuQfBcAQQnbGTZfxMA0FqiT/R
+ brZxGkC0z3mAnzjfhbFj7fA0eomPhrx06hn4P7yo1Pj7O9D4OQsPfjBaBPXZcYHlIvqjdAas5wyG+YTE
+ PgGZt2Vb1wt1Q3+Dn8uHtbrwYK4CgJb5zfQUC++B5frBsNyqQ+K94F6E56MRqF/mCE0KIf2Z+UV12mQf
+ JPeDpy5PoLITYTj+SdgeE3X+gNQYP1OrAJN5cMnF/8NDdg2PJX6NBQTc94+7eXHFrDrsLMkwz3yJvzAS
+ qwnKOY2XG1f5YSbV7kIktjPkEDHvq8JbiZUSGlQuga3PuTAenHjVpyx/Ae+TF6N29OZQefNWAwK5CABa
+ u1t5eNfD3GciCqYbVCaMS2/D+/kQ1C2qVScEMz+r/6wWCts/1QfIaqSyuQe1ihkouPFKWIbGYv70cwAy
+ N3iJjsXL6lPfJ68JxMv0+6vSj8sfqMP6fTKU7CPITQA+Cs/iC3wNda0/V/kRW3tpnQzBdSIImG9Ql4eX
+ 0ZvqF1E0+HAYOyW6HD1b33twz++L+gk16c2hnKVcA4CwWD+1gj4wnTgL1oXmJNb1fwjvt/1Rt6AmxPzC
+ KaSWtU/djhNAxBKktC2kTjRpHm8H/b7JMH5TrwNoHPNH5gEkBoF46j8n+1x7Zz1eOdWT+Vm2jlh/Cp5H
+ qNAHawAM9NoKv2HOY4Q0AJ5H7Lyt6Aipw5soGd4euoRziwuZLIHrntGwP+APL2TSokEgFwEgGOs/FLr9
+ yN5eUgGpa6Iffg7fTwNQ99jfkEXNN54QrBJy6E94/bXrv5PtD/dF2eK7O4wnP47CecQcrFo2YP5MLAaK
+ dzxWB5P5LL7tr161IdOnBwKc7PNgfyfuu9oJf/rFvKNTHT3LvngYW8g8V5mfQSDaxp5aYRKpBVQGWsWR
+ BOYrUDSgbaCKUzzyQ7Y/COeYO+FY5m0lIJBLAKBF7IL2kNqtgO2RA6A/JcHvyEbz/W8Y6hf+D36eEOz0
+ Y5tfMD+HhLSSP7VdaVTpUUKdq7wX1lv7wNw/mq2fLgjEOtaYQYx3LHkNQLw2BIF4QMCRuXUneTCSpL89
+ bnJ2GsRdfBRv4AllY88NSLyxZwONEqopx5mjvFuzAgInw9BtEWx9kgEBL+Sae+EYNQPOVY3Y7ShnKFcA
+ QOv0K6B5U7oAhRN6wDQ0UfFOkvy/XIP6Rb+ozC8kP08I9vgL5k/nIWnV/7IySB1fRdGCdqSVAI1n/OaO
+ ACSnAYjX0PF4zM/9/76zDwPvq8NvHbJQco839rwaC0nWc2xeSP9EG3s28ClBNQUECLShVn46DActgO2y
+ augSFpJxQ95yO+yD5sH1ji/9+ZUTlAsAoGV+E72x3Qhzn9tQcK8OkjHeAhmS/L9cjfrFxPxc820bojN/
+ umoa94knDNuOFSdAf+xTKFpEBw2JmL8p6gCmm/yTugaQvFNwa7Efw6bV4/8ymewjyEtMdjuewz/xL4Rq
+ /LGvRyzsSjRcwagSVBBgRmfbX2gC5T1hPHwuCi+qhC7hBqQ18P88ALVXvAkfOyKFhtniCo3mCgAIFc3a
+ E4Zj5sG2lP6okAL549Ho3/D+lyT/0t8gsxQQzK9V+xNtPpGIhPef1cKKcbAMHwHLddqTxXP85UIEIHMa
+ QGIQcOtlZYEPV/bJyqx6H+uVjT3diuTXbuyZbIXfsLwShGsCiikgaUCgAjpbohP+Dt8nF6Ou/3fwcbXh
+ Fpko1NwAIOx+xUnTDlL16yh6tl0gxz8WALwP77ck+Z/YApntP5Hlx8wvJH9jmZ+JQYnDjqXUubYrYbv/
+ MBhOTEXqp1oSLN7xeAOY6HiyGkCiikDRTAEmtvuf7OnGxLF2eA3pDHUCqqFnOgrL8D2+AoIbfERW+E12
+ uIRjV93YOMInQB+WnQfDYXNhu6hNEprAenhf6Inaazaqq0xbXKJQcwJA5MMoehrWKWfBdJXoVzQAeAme
+ T26EfeUOyKz+bUdDh59g/sY8CCEpFO8/iYKOn6LkWQskniQJVf/mcgCKjsf6O54GEKsseDR/gPYY/+rf
+ B3ox4MFa1CZklzSIL7AMH+JRevRy2O4+bOqls7Gn1tnMGh5Lei0IcCs7HYZunCxUnkAT4DoCr8A16zLU
+ T0EoxbzF+AOaCwC0jhkFia+D+fw7UDBXj9BGkBEAIK+A+4MxsK+qVzd21Ob3Z5L5Rf94crCKWNEDxn/M
+ R+GCVFT/XHIApqoBxA/7hb7Dfd5S4sfFj9Xif52yZP7+Ss95JJ6kJ/4t/cXOvw1Qnz8/73Q39ozMERCa
+ QDlCfoGyf8Cw35Ow9W2TwDHIdQTuhWPQXXCuRQtbQtycABBcXrs/dHutQdGKCkidwr+kAgBBqmcWnOvm
+ wPmWK+Tpj2R+4fDLhArGk4NDRkrM+EZYrh4FywggNYbPVEmwRAMZ71i6GkD8mL/6badBxtUz6vDOP7xZ
+ mUkSVw2djrfll/BP+pOXc3PhThH2S+T4S2boooGA0AQUMDgY+s4rYLtiT+grYt0id8IFeWtf1J7/BrzC
+ KdgiVg82BwCExft5ccYzKLz3JBgvjvblrZB33Qb7c6vh+RThKr9gfrG2P5Ppmaz+s5OonDpb9QqKZu8H
+ /fHxmD9TPoBEn2fe+x87ChAPBLz05oEhTjw82Jmxyj6RA9DpA53PPUF+7m+3/AHY3FY1AJb+HH9vrMoh
+ bkULAsIxqDh+EUgb7gRd+2WwXX449B3jrR34Db73z0VNvw2QWUC1CKdgUwNAWDiG3hSNhPniiSiYqUP4
+ HvA0av7/wPvLzcT836prspnhBfOL3P7Ghvpi9ZEnhBL+o462/RIlqwogVWbC9s+U5I/scLxjiZlf7Uky
+ 9fyZeFa/eLobY+6ww5n23kvxyUxPuM8NJvy1Xn71TXiepkPfQVX/hfTPBEUDAWXVIELrBhRzoApS1TwU
+ 9j4Dxv31MVYRkrbqXwPX3MGwT3GrC4dy3h/QHAAgVH8bIeoBT8O2pBJSZ+2XSM13L4frw2lwvroTMid6
+ 7EBI6rO3VVvVJ5WVfcn2MWj/HwF9t+dQ9GyyzJ/uYqB4x2N1MtHxVDWA+GHAUB+/3duLq++rx1/tsjSv
+ 6Wke8aweF842cd3+Tx+Ba6qsagCc8x8v6ScdigQBfvaRIKBoAnSgcjKsZwyA+ZiCGEVFyGqpuwP2oXPg
+ Wofwlac5SU0JAGGqPxlbbZahcMYJMF6o/dImyNsnw/HC83B/7lclvWB8fi/W84vc/mzkYov0X374bfrB
+ dP5dsN4NxFf5Gyf9G+8CbJz6H98HoP395jI/rp1Wj88OS9f/lpiK/5Qw8Boz9tvK+y3glwlwjCZB8A3U
+ nH/tct9MUTQQYHOAQUAsIOJWShphaR+YDp8Caw/SCoqjmQQb4f+uD2r7/Ac+zlfIaX9AUwFAZBJG0XUw
+ 956Egvs06/vlj+H9jlT+Vd+rWzUxs4syXsz8wtkXWdAz0wMr0n+VVWO3wnL9cFiuisb86Uv/8C5nzgEo
+ ZVwD0P7OYZJx92gHnuntTpCgnT5J9FTPmmHEaWvV+v5V0G0bjrqrf4Kfy7qxbZ0NANDedrCMGEJ1BEoR
+ 0gb4teR46PeaDus5R8DAfoGw0eDQ4NtwL+2LunF2de7mbH5AUwJA0Ot/EPRdn0XhEnq4yio/Gh3X43C9
+ MQvON3dAFst3BfOLQp7aMF82wyz88BX7n1qb52CbdhgMp2bGBIjG/uGU6IaSUf2TAYJUowA+Scayi12Y
+ NtoJbyYr+0TcfLuvSPpfb0Znjx5dlK29dN7BqB9CwoEjAQIAsqlSC01VFBPhaFCwmAjUKIECAmS6lt+O
+ gtPIJDjWGFghKsgP2TkTjlFT4VyRy8uHmwIAtAk/BTSiZQtQOOk8GAfyhxvg//VuOFa+BM/6QC12ZniW
+ /kLqC5U/0tOfrYHkh64U/6DW5iMUL2sDXWcgeeZPlvGz7wBMZbPPcA1A+30Oxf77EB+G31uPmkxX9tH2
+ i57u5deacMTXBnTW1Pe/H85bH4BzJVQnMM+HbNvUAgS0S4lFmFAAgQICNKltF8PUbRqs57eJWE1YA/9v
+ l6Ku94fwfo8crS7cVAAgVKrCvjCe8SAKF9Io6FbD/co9cL78O/xis456qMwvHH1C5c+Gsy9WX4MOwDJI
+ e76H4tUWSAXJqP7JMH6mkoCSX/0npawBRJ6HK/sMeKQOv3bMLt8duFaPS6ealF19uhDvkfQnFJawAq5H
+ RsB+P1QAYKGQPQdE+FCJuasNEwq/gAACBgXrAdBXz4a11z9gOEA74t/Bu/Z01FxTp2qzOWcKZBsAwhx/
+ nSBVvYXitTQKpkmwP7IKnu8D8RweGJbyzPTa2v3a6r1NoT5xf4MJQKfAcPR8FD6qrkpUKbnXxIyfSh5A
+ ooeU2AGYDAhEDwO69DKunVmP90/Iwgo/DVmIPQb1N2PfLXqF+dn+5409bdTWwP1if9TfjFBhV09WOxM+
+ VJEJQ8IkENpASeC9lZCh4GZYThiFgnNNkMzqqMr+x+G8+SY4Fss5uNtQNgFAnFuxpWgEC5agcDz9UTkG
+ 9sV/QGamZhWLEZEZnaV/HRqq/DKabsD4QSvr/6m16Q3TedNQMJluRUl1SewIlKMca/g+2t+NHeRof8cD
+ gmQ0AN4F+f7hTjw+MEsr/DSDcfKDBpz5jBG8rx+r/ryxJ2lgpH9L+Bm+/5yBmiFb1fUfbBpmuL54UkMs
+ 9oYQZcZFqFCAAL9ncNCfDkOHmbD23Q/6fdhBSONYcx5qz/gAXg5l5pQpkG0AECqU6TQY2u0D6ZAF8HBC
+ hzlwnElIf3vgVevlb2p1SawAZG9vm4EwDRiPgusFe8SW+skxfibXACSb/JM8CIRrALzC7+UzPBh7px2+
+ bKzw01AVb+w50oy96lXHn9jY0wpJeSA74f/leNQM+C2UEObMbo+iUqRfQBslEFoAzx0GB105JP1EFHS/
+ AuYL6EtFv8H37pGoudSpCrmcyRJsMgBASH0yBY5JgUHgweAHKqS+1k5q6gEKrgCk1uZ+WG86H6ZL02H+
+ VJOAEn0mBjSZ44kdf9FSfkNOQO7H+r29GDanHtsqsvsIdPTEe4014ph/8caeKgCw4684IP25R27IO47G
+ rj4/wc/Cg/NCHEkMVzYo0iQQICC0gaLA3+bA99xnwtB+GqxXkzZw+HI4x46A4zFkZrl6xm4o24MlAMAU
+ GDRDYAD5xlnKuxGy9bVbdjfHwHD/RASgajlsdx4Fw+nxmD9Ti4HSHeBYfycLApEmABMn+1x3Xz2+6ZZ9
+ X9u+r+lw8d0mdPao23rvqTj+dCQtVOkfgCTfsai55BsyBaACQKazAVMhrUkgtAFhEtgCjQUdz3MeVHcV
+ JPlWWM69HOaeQ1E34DV4GchywiHYFAAgqvwaAu/F0hG+eR9CjK+1i5prUPhhsjrHFWKqXkTRg/tAf6i2
+ QyHIluNoBSHKtAmQvPc/MQiEJ/6oAGA3y7jrFjvWnueBnI1FPhqybgUuG2VCt1/0CvOz468tNXb8Gahp
+ t2cehNpBK+DhXAAGAFajmzu9VmsSCG1AhAuFFqBDSMt1nA3DnoNg3n8o6hfXhtKExeA3201k89zaQdI+
+ T8FHws5PReWPN6/jUSwhLGvOESwBRq36LRQvbg9dx3ATIL7Kn82lwFIKf6cKAtwLH71d0teFOddmMdlH
+ ED3x4xYa0GORER1lXdDxV07NpJH+oneTYb/lXjhXo2lDgYlIO8dFqNuCkLkrTF2h6TrbQfLVQa6rzZGK
+ wk0BANqmJb7pZBlfew4d/aM7AvqyUuj2KoXU5RToK23Qlag7B6lpmT7ILjqpizcJraf/v4OvZgPkWvq7
+ xk+vHJKh0a930fsf4K/ZoUYllBLg1MrpTbs3UfwkTciyaMyfaj2AeMcbM8Da11jH478K+S/j3eO9GD/Z
+ ntVkH0GVP0i4fLQJ++xUvf7C8VdITSstRA9nwzFtAhyLoAIARwJyAQC0w6l1EAonoQkhjVdou65Ay4lq
+ wk0RBox1jWT4IVKLMPSA8dhhMA/tBP3JNMJFJMHI5kpaWWVTwyOrzcev9AS8uyA77JB3ctsKueZnAotN
+ 8PtvREFfskUtaicTq/yZWBGYysDGG+hUQIDdfz929mH0zHr8nuVkHyY9Tf3uU4w44U2Dwvgi468k4PjT
+ RXFSzoPz4Zthn4PQVm/pJCakoymmcm5h8gogMCCkBQiNl/stQtytGgASnT8ZqR+0sdpDKpsK68TDYbhS
+ l8QegakSd4Z1shp6t50UE05GIC1DsUXTYf5kTIFkByLWQDZO8odmZa1Vxqh76/GfIzK8h18M6vKeDpfd
+ ZkJHn+r460AXZcefqjOHgpFatW8xnE9cD/s0hEq/ix2AY91amOZJ3Kg7GrqCdtDbTMpW4VJB+CIe2Ufi
+ uX4jfDvfJwHgaaihJiuwmMS8FU07qsL31RRp7QmpqRYDpdOv4IKMDtC15Yw8khanZ6vP/ATYtcwAsIOe
+ C4PBYfTs9IjP3MmYAI0FgWwxPxNv4zXrOiee7OduktlgIuP3shEmHPyjXpH+HPrjjL8iasZgZEJqwMHL
+ 4HxhOOyTaFLsoL/r9qRjp8PcoRDSHjRJ2tBzars/dFzCq5Q0iRITdKV0rEQXaHo6ZiRBogucUopyt7yK
+ j01GGoka4tA/auD/cj5czz8B5zs7Gi7rTVZz1WmOid8JcGnOiFdYp3KJwpwqJPmr58H2cBfozsrmRflJ
+ cHB5F73bQc/DTe1Q6oJ4eqmsBWhMLkCyAxTtvfZvCYmZn5N9XjjXgykTHery3mzPBrrxI5fqce48kxLu
+ 02b8mcO8/g0B4GW4330N7g/6w3J8V+i7WiG104WSybLZZdIG/V/PgmPcg3C9401+m7l4fth4U6VJKdcA
+ IIz5Sc8vuRfWSSfBODjbfeUnaqfnsEsxAWTlb5ImwYSFVLSAZBk/laeebOaf9n08EGBav7cPw+bVoa4I
+ IgqYVSr6ExgwyIy9a9SQ355Bx59Q/WMDwFYSzH/BbyBTQVcSAIymnLwElo4VcE+5DfXzd6jp6slmqmbT
+ 79BoyiUA0CYOmUl9s10P88AhsEyR1DhrVomfZH0YAMgBAJCSZv5sO/8iByve+3ggwLStxI/rHqzHD/v7
+ Qx3L5mygy3SfbMQJrxsCqr/q+CsNqP7aGHE0ANhGJ/iDWkXAWWhpYgBQh0j2PA/X7Otgn+ZULcZMFqJt
+ Fso1AAhuEXYC9EfNgW2ZSY3JZ520ALAtAACHUHe06bHiNVVfQLz3qQ5QrL+TBQEml0HG5NsdeK27J9wy
+ zeJsaP+phH6jzOjoV5m/A41tJV2wICLmHw0AmLYHAKA8ABrNAQBMXOhjIZyTJ8Axz5WDq/tSpVwBAKH6
+ K8UX9oC0x3zYFnSG/li5icaVAaAuCQ0gGdU/05mA6ar/4jXcBS3jqcvcmDPKGb7IJ4sAoCdxefEIEw79
+ TlX9O9K4tg04/gwNpH84CIh7YAD4XQMABc0EAEweyDtuRf3AxXC/jfBaFS2OcgEAxDNX1luzx3Y2Ciaf
+ BtOgeJuDMpHEdrwFz/c/wb/xb/hqN9Pf7kCCiI1MCZokBpIuEk00UyE1Uh0LiqGzWuk6JEHMxZAs1Iz8
+ mYU0D/qhiSDdSEDAuxJLAgCYUmX+5EEgNRMyEeNr30eq/3ylD47z4PYpdtRG7nWTRQDo9rwePe9TM/7Y
+ 669m/Kl2fGTGn9YRqL2HbQEA4AIhpUrIsPkAgGkT/N/2Q22/T+HjzUpyuvBnPGpuAAiz+6kVkt1/+dWw
+ zGS7Px4AkFBxjYd91dvw/OCLvTGIFKfp6KJ6uqiB67kR+phoMlrpg0JqtmNh6DgBBUeQhNJFY/70GV9u
+ 8FmyA6V9XPGkvvbGtfRrBx9uus+O3zpHEVZZAoDCTUDfq83ouink+KtS8v2hGFiRGX+hv8PNgFwDAB6w
+ n+B79TzUDN6ork/IicU9qVJzA4CIkyp2/6lk98+C7RmjuiIPsQCA47Wz4VyzGK4P5fDKQckAgC7Gq9gN
+ SFnaeTz0ez+IwnMIHPSpMn8sxk8lByDWg9FCQLJmAFNNoYwJd9vx8XExtvHKBgDQOU++14BTVhkVxmcA
+ aK/J+NNmyGgfjri7iCiA/Af8UrIA4IPsZyFhh+zmVkO2OzUXaXceJ31Gk8VP772c8MPnYW2RtcYO0Nn2
+ gr6CzIzCRBDD1X5WwT1jKOpn+kOl6luUP6A5AUBr91u7QNdpCWwrSDXcJ/SF6ADwEjwfToCdq62KUuFi
+ 8H0xrqNl9EjmF+/ZBGEAUEo9HQV914dQeBlNVCUCkQzzJ8P4mUoBlhr8G/vVTRD20AgnVvR1x06azgIA
+ VH8l4dIbzehSr+b6c6sMZPwJ6a99QPEcga/A/dNKuH85Dob2ZL75a+B31tOtETO7yRR07oJcv4NMQAIK
+ O6nnDnrv5qSeQMo3L/Tw+wPvA42lRXAhGF1Dx3kFJAVMxPzWuSjs0R3G/RKBAG8MOh32/jPUjUBa1Mag
+ Yuyb67rBWoFtIbV5DIXzu0B/aviXGgLAL/D92g91s+rVTULFFmGimEi6GoDIPRDVXcoOhX7fR1F4NfsK
+ ojF/fOkfn+nTmRnxpX1DINAm+6zr4cHUiQ744gVTMwwAemKF88YYceTHhqD057BffMdfbABYBtdn16L+
+ JYQvI5cjWuTK0ljvIx+Ddj6yNmquhFTyAor6HQR9h0QgQLC67VLU9nwH3q8QXsou56k5AEDr9DPTPyXT
+ UXBHd5iGRPYnEgBIZasdgvpZ38HHZZbF7sACABKZAEzRtABtfzglhusBlh8AXdcFsI0tiFIROL70j18k
+ BAmOJXo4sVX9hiDAPfn6QB9ufsCO2kQr/DIJAHSurq/p0OtuEzp6VcnPYb9ojr9kAWABnO/cCPsaqM9Z
+ WzwmGvPHek0EAKK4h2IK7gVdu3UoGtIO+lIkoG3wf3ERai/9Ej7evThnSn4loqYGgDCnn0FJ9rH0Hwwz
+ J/uYG345BAA0oqRqOZ54Du5/yqEtwgUAxNt4IRIEYgEA90lsD92GHv7eZJJMtZItmBzzJ2b8bK4AjAQB
+ vtamSj9uml2P/+2TRIQqgwBg3Qz0HmXCARv0Ssivo+L44wq/uuDSuFQBYC6ca26DnesBOBGqGxkp3bWv
+ saR/LPVcuweAqPpbfBoMBz4JW/9C6OJug8pmxTfwvNQbtddsbkFOwaYEAPEsxUBbL4XxrLGwzjWrNfii
+ /EAFAF6yuxDOtY/Atdan7g/HACBKRLMPIFbp8GRyZ7T94ofOfakiO7DD87A9Wgyd4pBMlfmzlQKcKOYv
+ /uVtvO6cbMd7pye5ajZTAEBP4ejH9ThzMTv+VOZvH4jdh+f7pwYA98Kx6E44WAPQmnyR6n88tV+78Cba
+ PBGVfRgARLXfMvqg7FqYT74L1gvIdNHHH0LZtxruudej/u56tZ857xRsagAIouzB0B8wF4WLKiB1jf0D
+ iW1YeS3c790Fx5Mu3ncR4N2CxZpwzsnOVGEF7hsjvwIA1KpfRNG8tqQGpsv86ZoAiSMAsR1+TDzTFw5x
+ YcnQFMp5ZwgAyn+UcNlIE7rsVBN+9gw4/gqBYF5lOgAwEfaZs+FkR5vw+0QWj40n7RNJfyBU9pslPc8D
+ xRSkVkGoUDkD1l6DYTkx0RBxpuATcN0xDvbHHC0gU7CpACDM6VdNzEXMP/sAru+RgL4ie/9G1M/bDPk3
+ hJhfqP6ZrK7K/RMA0IZa9TOwzdyLgCoR8zcmEzDZwYv3XnuMr/HOyR7cdZcDbnPCU4f/sJGzgSv8nnWn
+ Ece8xY4/KZDxp4b9jClJ/4YAMAx1tzwN9zsIaX5aDUD7WKIxe+wgTWgItfko7AMQuwLzXKishNR+OZkC
+ x8MYU2AJckPeOR32EQ/A9aI/xyMDTQEA2sG1EAKU3oWCsefBNByhsG9U+g3+P4n5H/0v/D8gZPeLopCZ
+ jrtyX1hQKT4AatULYJ14KIzHR59J8Zk/EyZAKuq/oF86+3DTXDu2tUlxSBoLAPT7jh/ocPFtJuzpVRN+
+ OgRq/BUog5s+APDZT8Cuq0gYfIqQ9icAIJ2hjTXcwhkstABRIFZpXaHbi0FgfxjaJzoZ7ws4BHVXvg4v
+ VzIWTsvG9jHj1BQAIKqjMLLahsF08UgUzJJC24JHpa2QtxHzz/8Cvq8RkvzM/Bz718b9MzWgPBYCAPiB
+ V09GwYhzYOrZUMSEZ/OlawKk0rFof4d7/GlwSvwYd78d67v5U3+yjQQAIxljvYeb0O1HVe0XGX8i7BfN
+ 65osCHgg1x2DXYN+gv8bhMK/2dgeTKupKtvYQ50Pykax1CqPhH6/pbBduSf05YlOtokA6xLU9v2KBBly
+ NDKQbQAIc/p1o8FbjMLnCyBVx/tRPWQ7q/3/gu8zqA+cGzO/cPplI/daTQjTAMBAmK+8Fpb+QHLM35wO
+ QKWyzxgnXu7lSe+pNgYA6LeHPK3H2XOMitQPd/zpGiReRIvJxgOAncRAJ6DmGtIIf0TjagImO+TCISg2
+ AxVzQmlnwHDwItiuKIXOmmBY5M/hWXU+akfUh/Y0zCkQyCYAaNHUWkyq/7MoemoP6I6N9yMaIfdE2Bet
+ g+dfCEl+rcdf2P1MmQYARn1lY1Bq1efDeN4EFIxCYD1ANLW/qUyAeMzPyT4rL3Nj/ihX+tt4NQIAOOzX
+ /3IzOtlV5t8jWOhDxPylpACg4TH1dz/A+3V31I7aDvkPqPOB50K2qgJrQYAFl9gWXAsCFVfAdOz9KLyY
+ hFlcTVZWndh3Dkb9bG8OOgWzBQBh9hQ91KKpKBhDdv/IeD+ikfFOg33Zs/C8i4aSnz3+2dxSifvLD1MA
+ QNWJMBw/A9YpkrIeoKHkT1b6x+potOOpJf+okPTZ4T7cMdOO+qJG3H26AEDy7LQpBhz/qiGo+outvUKO
+ v3AAEP2PBISGZoL6uzVw//NK1N2GkEBgH1A2y4JrQ8PKIjWEgwCbA+XXwnzSnbCebw6ki8cZWs/NqOu7
+ EO7XkGNOwWwBgNbuL7wQxjMnw/qYXlWpohJJfs/DcD6/EK43EC75RbhPLPjJ5sCJnYGUrcGqIXVZgaLH
+ 6KApHsNnKwqQyPbn8/2xhw+3PWDHnx0bOSRpAkC7TyVccgM7/vRB6c8LdrRbe2kBAAhxV7IA8AScT14H
+ +2yo86KpdgYKc14jBAJs+wtNoPxmWE67DQVnGxPkCLghb+qF2jM/gvcX5NDy4WwAgDatktMpO5G99BRN
+ in1jDw7c8+BcQ8z/ul99yELyi5hvrNV+maawvQGpVb+EokfKIFWlyvyNAYFkbH+mugIZ0yc58NGpGTCH
+ 0wAALvTR6zoTDvpWdfyFMv60FX4bhvQiAQCIDgrid1NhnzkNzmcQmhdNtTeg6JIWBER4UDEF6AvlE2Hp
+ fgMKTo+XKMTD+1943zgTtQNrIOdMpmCmAUCr+heYlDx/66SzYLwq1rWIs92PEvMvhetNmsZkTYZJfpHm
+ 21SDpd0dmAGgaiEKJ/HOrkB85s92DkDk4Hl1spLo88xV7szs4ZcGAHRboUePB43o4A85/hpW+G0cAFDH
+ /D1RO/pdeN+DCgCcA9KUuwNHRgZEeFBJEuJGH1ZMIi1gJCyn6CHFfBqcKbgW7vuuRv10Z44sH84GAATR
+ 8mwYT7sH1nmmwPr+SKIRcJLkf/EJuN7yhiR/NOZvqk0UGcEZ5YPJQDfAPOwSmC9oahMgltRXzyPjvVO8
+ mDElxWSfeJQiANj+AnqPMGGfjaGwXxs6gVUT9ssEADgg7zwdNdd9C9+XCCWBOTN018lSWCIbwkFA0QTo
+ MVQSCPS4BpYT42kCBNc1t6J+0BK4X0fIH9Bs5cQyCQBhqj9NhvaPo/CxvWGIWtePy3k9COeqZ+F+zxdK
+ 8hEr/Njmj1zj3xQoyf1nP0UwFNgTxnPGKJGA+OllmYgCxHMAau3+DZ18GDvXju1VGRySVACApuuJ9xrw
+ j9UNHX+mqAk/6QPAr/D93B011/8NeQPCk4CamiLXC0RqApV0sPI2FJw1gkCAq0zFOtHf8H1OWk2fH0P5
+ Ac3mD8gUAGgdJgX0puRWWK7pD/NYrQdd0C5CwSmwP/MmvJ/61YcaTe0XA4MmHBwRChQAUHUAdN0eg212
+ ssyfDQeglvnrye4f83A9fjwww0IjBQBgx98FY03oXK9K/z0gtvaKtdQ3fQB4gwTEJagbL4fMQ04Ey0YS
+ UDKkzWsR5gBHjYLmAFexHg3Lybeg4AxLjOgAVxJaB8/DQ1E32a4Ku2YzBTIJAMLrX3QE9Ac/gsKlNuja
+ BW44+MU/4N84AfanPoPvO6hMLzL8hLdfrPRqjr3TtaFAxRFIN9XuVRQtMCW9LDh7DkCfJGPWeCfeOD/N
+ ZJ94lCQAGGjGnj3GiEM/NQTTfcXWXokq/KYDAIvhXDIa9nlQTcTm3hpcGx6MpQlU0Idlw2A+fjKs58TK
+ E/CQELyRTIFlcHPUS7ucvclvKFODomT7kf5cOQeF04+F4aJQTX31vj6Fd/14Yn5S51j12R5oIs6fjuSP
+ 5SNLFIKPdz5RF0ABADrQ9lFYJxwAw2HRtAAgNT9A6JisuWjDxxDthtb2dmP+Tc70k33iUZIAsN8aHc6e
+ YVIcf3tqHH8WxMv1Tw8AqEu+K1E34SV43kQoBMhCojlLcMcCARYaIm24nO6jtDdMh82C9cKSGBmDG8kU
+ 6EGmwIZmNAUyBQDB3Ol+MPa6DdY5ksYR4leKJ3revQv2NT71IXIT9r5I8onG/KH5wfPLqGzWZ1Su14Fs
+ 9YNRRVcto0dRBC4b4IYdW2mifEL/OkmT8CnnE36EZKMIojRY0BF4LcyD+8DcK31HYOrPVAsK/PvPj/Dh
+ 7pl22G0ZeGLRKAkA4Iy/i4ab0PUvvSL5OwQcf4VRHX+NB4CdkLeci9rR38L3LUIRAJ4nzV2DPxYIiGSh
+ isBrGWnDXRbBdlln6NpEAj0/1xfgvn8Y6qd6mskUaCwAiGemJPxUQeq4EranK6APLpnkvP55cKxdCvf7
+ flXNF8zP70VRz1CGXyHNJaMiUCzYi1Srg9GFju1LQ7oXjkRHGuI9SdfoqOSbxOq/h8D1c7yDt7GajMh/
+ 0xXExBHhxHgTiB+qcAQqAHA6DCfdDus4aJ5Oco7A0HNMbwWg+tef7fyYMLcemzpkcV4kAACJIPSYhww4
+ +WmDkuzD0l8s9TUh0Uq/+AAQPRFIIo3R8+XZqL3REyoCE2sVYHNQNBAQeQLCL8BzqJRrXs5GYc8eMHbT
+ RYQJvZB3DUPdJSQgP0YzmAKNAYCwmD87/ibBcsMl1BC4g7/h23gPHM+8B+93ssrsqsQvoRu1EBNyhYgu
+ hJwH05yyEVMbqR1OrQ39bSTtUq8woD7tHjKj/w8f4iE8SFoBWSDKBEqUV8APKGxNQKmSEWibbQzUBxT3
+ F5v5k68LmOhB1BMUzZrowL+SreyTLiUAgMrvJPS+jpDXoQs4/tSlvoyUiQt9JAYAcWktACyF88lRsD8K
+ 1QEo1oPkUsHNSBDQZgwKk4Abb01efDsKThsGy0lWSGHB2//B+z4B3ZUbSeNBE68abCwA6AM3bTsUum5L
+ UPQ8qYIlrPJ/Ce+3U+FY8X2JfzsNhQnt6HvH0L+VpDnuS/Ongo5aaA4ZFCbTxbxCJobBTYy/FouxkObU
+ TsKlUHZhNJtL+DOCKcH0xx5zUThxH+gPABJpAeFrBoD0HBFKtw0ylg11Y1V/N+TGwGAyFAcAdDRS3ccZ
+ cfi/QtK/KuD4S67QR3IAoG3EAZ6BqLvzRXhEajgDAKvJWUbClEl7OzxvxNqBYFkxqGBQSl8o7AXjAffA
+ 2msP6IN7XvKqwUfhGDcejsfk0KajTWIKpAsA2sQIKxnNJUthe/hg6M+pM8C1qovr88cPdf648yBi9q40
+ X5jtC5TBSO16/9/elQBIUR3tb869YGGXFRZYIGA4PEC5ongiHngAiqABVERBEFBUQAFRicYjXKLgrySK
+ 8UARNd6IUeNFIgbBIwYkRI6oKKAC7u7szt1/VXe/nTezc+5Oz/bg1Pic2WF6prv61VfHq1eVLgCA+j0B
+ /BNvYBEWYDc4H5u1ibw7S/7VyIzA8quQN2YU8kbEDwRG3yoc+TqZm8E7/N49y48HbnbDm5/EwY3nT/S7
+ Q+93ftuKIfOcaB8R+Gtohd9kAOAH0oaDUTl1h7YFWPj/mUoBTpUE54QlIKoKiRWClvrg1wW9YWt3Lwov
+ 7A17V4vakkBNENp3PirP/hCBbYitnAw78VRJbPZRtf+FcJwxvnX+o+tO9NvWDPK6Nh8RQLBITQnXqDF5
+ sOllAfdz2ojb6fEVOLDE8Qg5JVOQyAisiwP0ga3/fBTeapFahSUj/ImSgGLIHP7bPYC7FtTipzYZsnZj
+ AICDbKWRlzvx691a4K+9Hvhrpgp/slV+UgeAD+Fffy6q5kIz/4X/74F5zP9IkkGAFUhkhWEBAqxYCipg
+ aT4PhecOh5OThtR8gU3wrR6EqikIFbo13BVoCADI5k6hpTf6njbQvmzzwEC3vZyZFmtGN/TsjLj8b7EF
+ s3EztoOrDbFpKRgufo2vj29e3dbgFrB0Xo6ieWWwtosn/A3V/jL9UBbEHffWYle3DCq7GADQZ7kNAx9z
+ qIJfoWf8JRf4azgA8NncipplD8DzLEL+v0gAMisAQOKg2EAkBwdZ8IUVwKCQR9rTfgXyes9CwagSWFuR
+ 1eebBdeYP2lpwiIgaOgkSBUAxOftZBy3wFWYjLMxjeyAsrjfZDYAYNpDNsBMzCEQ4G4uwr8UqCviAHzT
+ RD5A2xnIn3QWnAOTFf5UQEBcqtehYNHtbnxkdNAvkqIAQPEuCy4a70RHl7VO+7dKOvBXHwCSBYxaKK5h
+ qLpuIwJ8b+T1f1NsoU2C5OCgiAuI6kIMAMX63076kNIP9lbkEkwgF7oPuT5bzkDlef9DUAQEDb3mhgCA
+ hcS9JXnSS3AExqhLwInIjABAZNuL70+eaH/DsQ/77LActOlpySTUBwl+D+5D0P0VgrZazRVofTLsJ96C
+ wuv4zJIV/mRPX3zHqis9WD3Bm6BcqgEUCQAEg6fPsaPP+/a6Nf82eo0/Z0rCnzoAbIH/3yejakYwtPwn
+ dgCa0f+PRbKhExkXaK4/a20S6boIEZT5KBo6Cs7xf4FnwQTULEL8hjdpO8nUPl9I938h7kIfTEeyHZpN
+ CgBM7bZaMHF6PjocUCe3QmZZ0MZ7UGm4oSiV9PwTgtWEzJUHoXjPhKNLMayOWMLfGADYcIIP8xcYlOmX
+ zAlId7PD+1YMucWBCp8m/O30ZT+exalp/9QAgE6EBMH9CI2VCM//N7P/H4siXQJmHwu9sAYK9ff4c376
+ kHs4HN0JCK69CtVT3oWf0+UNjQWkCgBWjMCpZDq/pkJBsmRiAGDq9JkVV8zNQ8f9mobLg1bG2k8/XkOj
+ kgYJP9mhipqBdDiJQEN3BsZiz+72Qcx7sCZzQb9oJ6HPBgeJ29Crnei+3Spl/FnVwJ89ZeFPDQC8UDzn
+ omrKJ1r2n1wBSF6tiTdv5X+Lx8xMbjADQoFzsZFIAAG/dujnw8Lu7glr3jjkdZ+L2rXu0IqAIeecGgBw
+ a7c/4F6cgmtTOs7kAMDUeZMVY3+Xh04/CjNXI+Y+A8DPBMIMAHwH+9P9EhZ6MkCQiAXVRQruWVCLLX2b
+ ao8LQgBAzz2ftOG05XZ12U8E/lrSSC3w1zAA+BL+zSeiaiakDlAkIR4CHyupUIdV85tZYFij2umc7MfD
+ VtAe1ub5sBQ5NKEKc2YIOar2I/jz2/D/REhS44NSRRadWwnXrEbPtMikIbFKkKe/Zvbw+TAI8LQTPRAN
+ 3RiXGgC0JiXwGF4hW/C0lI7LAgBgOvxjKy67gywBHQT4LrHacelWAANAFY1j1E631pSsgFgs4WSfR6/3
+ 4K0Lfemp7NNQ0gGAA3/DrnWg8w9aR1+x1beIRrw1/2hZfakDgMJdgNd8iMDGX5EWJKujiO5Ds46wFHeH
+ rYhAoIWDBheZpc8X0nMzS0RWXYJLrCVJ2kdg/tWb8L62FJ5XdiD4rT+8SKeRM05ml1gqFEOwR4CAVxom
+ AYBylOAJrEExBqR0XJYAAFOPdVaMuScPFQc0k5fviptOolp3A3hw0csjVTfAknBzUKzLF0HEt4f4sOJG
+ D3zpquzTUOIVXJpmJ91jR/819rplP97qq1X4tcYV4FR3AkYb7HK9Q3O/VO0naFH7CkRWGEonkbvx9Svw
+ PDgP7hV7oHCeQSaq9Ua6BMKasUn/FoSme3gYWhQnNZ46SBEsxAocj9+mdFwWAQBTz7dtGLXAiXZVWlsr
+ tRAHoMcCguod6Uf3LE8HgIa4APz3tiMCWEim/4FU23gZQXQKbTdYcN5sJzrUhkz/UIXf+IKcDgDYSfN8
+ F/GXE41K9QpD7CCL3zbmspXAJ/CvGgPXTT9C4eVgsfaeKZdAAIEMAGIa8XkEYBoAYH9lFD2uIxCwpLBJ
+ J8sAgH/zmDdtGD3fida1VtU+41lRpcYCNCvgcGgmcrTNQYkEn8ePZUEsml+L7UeZY2WLA3+DZzpw5Oe2
+ Ou0vMv60Qh/pB4Dwvf8KPiAuM6/L9FTjZghfcjSKGAT+Dv/T4+G68ScovOSYSRAA6m+MDJ1aCAjE34ac
+ QLLkQAuaGwuwlBzhIUkflW0AAG2h/9g1NlwyPw8t/RraufUYAAMA37E+JBr2CCsgkfbn124n+bqz3Pjg
+ XL+xMztZopPq9oIVZy52qIG/9nWBP7nCr7EAsIfm+L9I0bHpz6OF3lTUoTPIaDYRCPjfhG/pRLjurA5t
+ OsrU3nxLxHOUOxT2nPYfTpZYDorRCUdhER5EB/RM6qgsBAARjjnuaZv/5AccB0thcXIHGDqdvGooVrYE
+ jlZ9VVtM4Y8UfBXKCVleGePFM5O9CDbFen8UKtgHnD/RiS57Qmv+ZXrGnz0KADAl3+cvMQAwfUSOFbtW
+ h+navxjh5cUzQX4orkWouWEhvKugBd+aAgRikSnyAPjzWtHMX+FY3EuPduie8KhsBQCmIBT7s9hquR8b
+ rIrqi9kcxAOSXWcv2NpMQ8FxdrXwaXwXQAT9Ng3w47673fAWNNF1RRKBXP+ldpzwjBb446h/Gz3fX2z1
+ TcYCSLQEGM9K+IFO4lOStRIp+FeE8OYimSKy8vZeDddFr8LHjWkztiuvqaghvGW9xcqhlGbLEVhMDkEn
+ UobxvimbAYCJ9+auxCYsx3p6zVpBDdzQR5x3o+C8HrC1FysC8ZKBvm8bxLyHa/BzmUnmE51G6VYLhpP2
+ bx+W8RcefDMSAPgkPiKWsqTJwT9eFLFnyPyPZAq5IxvPRNXF30HZg/S3oTcVNYS3fAyDgNZAoy264Q+4
+ k/7fN6EH05BfMgMAMPlJ9FfgfTxO8zVYV5ba0R+2rjehYLhVr4EYCwRq8hTc8VANdqa7nHdjLpGuYvAN
+ Dhy10aZrfy3w1zxC+xoJALsR8H2GgJVMfxtr/5K6pT8Eg6GhkHnOCT2Kl16Sg+6pglJzAMEafu2C4quk
+ UUv/Rpek8Gufzn7SVHYCFGc5rIVksbXtCltre5zuPYI+hO+R0aieUx2+C/GQA4GGgisfJ/qnl9LjV5iP
+ 35MdMCDqis2hAABMHpoID+F1PId/6gVH2QrIJytgXDfYO0dbDmSz30fQ8NgNHvxthAHlvBtBnd624txb
+ HKrWb6/X+Its7SWX6GoMAEQT/gCUwHVwvbMNQTcJZ6sCWAJcQ9IDxUMWgbuaXru01z4SdvcBKO7K8Nz4
+ WJ6XTCLpxk5WTf4s5J8whUYiEKAv8z8N963TUfuQGdt6p4saMx1lEChBK3TGdfQ4HeeS7Rge3jpUAIDJ
+ TTCwEM9gLTbSNGTT0Hk0bN1uQ8HVFn1SCcHX1m8UvHWBD4/f6FV3GZmFeNnv/HFOHL5bE/52er4/m3XR
+ C300ZBUg/jGkZXdcguqXXCFfW2TAiWU4IeiywEd7L1YcVpya2I2XTyBQtAyFQ4bDeayoxhOL6N7V3oya
+ Kx6Gdw1M1tY7XdRYfSTcAQ0E8mguTcYEjMRoNU9G0KEEAExVqMZirMSb+FRfoS0kzTK2Lxx6E1GlbpZs
+ PSqAexfVoqqkia4jBh37kA0nPW6v0/5t9GW/2Pn+6QUA1vITUf3UG/BvhSb48hBl3GVhjxT8aKAAhM8Y
+ /qnIgp1F5GqU/QXNLj8KtopEKUbkVuyejOqRr8LPtQmaqmGNYZQOg1SAgFZBx4G2uAyjMBZXEcuL1E8c
+ agDAVEmP27EC/wBPYFtHWDv+HoXTaJYVilm5r3UQixe68XV38/j9TC22WzBssgMdK236mr9FL/SRWmuv
+ xgDAq/B+NAWup72ajy26QbHwR9P+qQh/JACI6lVyea4Wx8LW5Tk0G18Ka/N4vFKDtwh8OgJVo7ZB+QaH
+ WFAwXR6pQFpmcjHBQTmG4jxcTS5BC5QekgDAtB8HcCuBwCbs4hWB0XCeMwzOM/mUqwkGHprnxienBEzl
+ 93Pg75Tb7Dj2XXtYxl/8Cr+WJIQ9+eP2I3jwYlQv/kIrgMkAwIk3ojdEsgIf+RqIPlsEAKiNayCV674A
+ jn7LUTQmXiNP7UsV5VMEXrkU1VP2aunCmWpXbzilc2oKEGDTn1dyDsNvcBJuwRy1FHhDv9HMAMB0AAcx
+ HY/gS3zfApaWc1FwZVuLpf0LV3rx0pU+48t5p0gV71kx+DYHKryhjL8SfdktVr5/ojTgVACAG2M+APfz
+ d9FA/Yawso8tzKZIXz+a7w9E983Fz4qW9aKFl9rDj/6hbCbyz7wJBeckzsJRAu/B99CVcN1WGV5DMqtB
+ IN26STBcbRIKZvTh6IW7MQ8d0aNB32Z2AGDaix8xBQ9jN6p6w9ZjwIn20Svu8Dg8RU107jHISaI2eJoD
+ 3f4TWvYr0wN/DsQ22RsLALLFsBn+/w5H1d2VvAIYKvcl92lgihfcS5RwGUlyIQ7RtENt5w2tpXfrpSgc
+ eSHy+ifiXwCK+zHU3nozPH/0y92sshgEjDJOhdml1dZvQzBwJ27D0WQTpPKb2QIAfI7fYA+ux1OW5iiy
+ LcFYf2kKFZMyQXSORz1hwynL7WinhJb9QhV+lThr9umJAXDgbzQJ/3oEOMuOC36Ict/sAoiOONG42xgS
+ Py9Kcola/QIEDiMelD+OoktPgr17oqCgH0rVLagd/zA8axECgXScZ5OQkd6pWH7R6usX0ZybgxsxCOcg
+ 2Z2E2QIAgr7GPtSSadidrtVkVLzDgvOucaDTfq3IR9u6Cr/azYgEgMYHAcOP4Vp/98H9zAK4X0Co1j+X
+ ++IYgGz+G0HxXAHu+1BGPOmwCs3GHQl7+0S33g1l9wRUj1wbvjKQA4AoJJjO2rCl6nJOxeW4COMIGhKX
+ wMg2ADApceDvhLvt6LvWrgp++yitvRoDAMlo/w/g3XQJXPcFNOEXrb5Y+8uNWYwuxCGUEgerRUCwTAxy
+ 37r+GUWXdZDadsWib+H/+AK4LtmJ4LfI4pWBTEzz8GVCm7pCMASTcQ15YyUJj8wBQOOI+NduvQWD5zhR
+ 4dESfsqlfH9rXeQ/PgCkXgsw9F27Efh+BKrmfwOFW7KJSr+y6Z8p4RGBarEsyCDAc1CAQKvTYe+5DEUX
+ t4G1ZaIv+xf8z/0W1dftg8KWTFauDGRqmsvLhJxvUo5+OA2zcC2po4q4R+UAoFHkqATOnO5Aj3/bVOFv
+ W6/QhxDYWADQuEKgZC7XTkL1A3+DfwNCpj8H/kSp70xvuZVBgC1TDgoyCAh3oPRs2I9ZiqKLWiXOEVD+
+ Avcdk1G7JJil6cKZnObCEuCYAKNtxZGdrWNrpmPcrn5BS8wjcgDQcCLe9VhtxcD7HWirhLS/CPyFJ/3E
+ CgImtwIQLWjoh+JbiNpnl8OzNqA1+RBlvuXkn0wLjAwCopOvAAFhCZQOg6MPgcBIcpPibtwOQqmZg5rR
+ j8D7DrIwXTjTAFBnBXSCpdcU5P9fTUt0eulaL/51dqB+VdwcADSKinYDQyY60eknTfhFcw9R6CNceGNb
+ AA0BAF7vXwHPG/eg9nlvSPjZ9OeuzLyO3pTBs8iVAQYB0cpbrA6UjoSj/xIUXViYoPJwJYI7hqHqnC+0
+ eEBWBQUz6QLwUFcFiJutZiL/zl6wX1QNxfJDXhBrx/qw7nJ/+IaZHAA0nMgmHXCXHX3X2FSzvx1hLwf+
+ ihGe8ZeMC5B84K+Obcor8H44GzUrq4HvEAr6sekvsv6aWlPKKwMyCHBL+Fb6KB0BRz+yBEbkw+KM9UW8
+ 8+NzBJ4dgaqpB7WchqyJB2QqCCi0v5qOOQSOoZOQdz+X1+KZwHX399sUrDvbh1dn+uDPl47MAUCD6LDP
+ LBg61YnygEVf87epGX/1C32kNwZApLwB3wYS/qcOQGGNyD4/a36R8GN4v7sUSF4ZiAoCFh0E7idLIB4I
+ cGffZXDPuAPux012jQkZkInfqMvEItuq4gEUrSZN1FXkdbLN5NKLbb7Y27v73fn+UjQnVyEHAA07dZp6
+ 50xwoNtWDvxZVO1fFjXwlygGkHwGoO69KW/B98l0uB6v5D009YVfLPmZSTvKICB2DIa5AzoI9E0EAlVQ
+ dl+MqmEbEPgPsqScmNHTXDb9C+hFixnImzkIjmvkD/FsIMgMvkZm4xPw/j3YBS1xNy5AJ1JchypnDKSu
+ z1kxaLFDDfjFD/wlcgGSBwBO9CHh33QDap5whbr6Rgq/Wf3jSBAQuwblmEDJUDiOvR+FF5LyKoxe90bB
+ FgRevQDVV+3nwkSh7EazXW/YhRv9/cL0b3YMbL3vQgFNT4RlydfQf0/C89qr8K3Xl1MCaEMgcAsuRV/0
+ 1JXWocUZg6iARG/YFU502B/a7NNKLbGt9XGP7ccnBwDRrAcO+P0Vvo0zyed3hZb6hM/PEX+xecbMabNi
+ rgp3IBIEeJScBfvRS1A4vA1sLaNNEXIFvEvhvukuuB/LhqVBI6e5mC/qeiv9r3QJCh7pDNsp8of2Qtn7
+ INzPf4zAF9CSQxg5PerxzckXm4GxOAOD61UZymbOGEWkW3+z0I5+L9nqov6tYY251TdZAIgXA/DQhH8U
+ nreWwP26X9P4IsVXFn5Z85tSEBC645EFRGQQ4NhASX/Yfn0fgUB32MqjVRWqQvDrMai++EME/g2TuwJG
+ TXN5mYUZWTwcjguvQt4S1LmLULYh8NVSeFbvQHAXtAnDE0dkiLHplEdHl+EqXIIRGE1/ZW6DTRYCQJuP
+ LRh8owPt3da6pB8utZ0PS9zGnpqQRwJAYvN/D4I/LUTtyy/D97GiCT9rfSH8bPaz8Jsh4p8sJQKBUn20
+ 7AhLu8UoGjoQ9h7WKCDwEXyrR6H6+iqNF2aLe9S7YCO+VwT+mpXD0pHMptXkh3aBxgluxbT+T/C8TL4S
+ LxGx0IuJwxaAS2caf0czgpHWOBvnYRqmkjpLmKdtas4YRHYSt0EzHTjiM5ta4SdU4y924C++BRAbAGge
+ Bz+B/6t5qH1xK4Lbod07Ifxif7/Q/KY2gaNQLBAQewdUK4AHoULpbBScNg55J3DTGPlLyBVwE38mPQjP
+ SwitCpirNBSMmeZy4I81dvNZyJtzKhyT+H1yiqqeI8F/Cb51bm2isMAfREj4eeII34lJ1BYowwCciFn0
+ aIOOWckZA6nr81acusSBdgGtxJcI/OXF6Opb/734ACA+T+atayW86/4Mz/sHyH1DyHLjwfdPDvhlm/AL
+ igQBnoMibVisEKiWAH2g+Ug4e92JgiGlsBbLX0IW0paLUXXRZs3CNWUA1CgAqEuu6ANbv1tR8CT9UfI9
+ gjsegOfRzxDYpWioyJPlZ30If5Hfl1siy7UFytAFR2Ee5qIbemUdZwyiwu+Bwdc60eVbYfrLNf6SXceX
+ AaD+MYqu9e+D+6+bENgWCIE2DxG7YctNLPVlq/ALkkFAzGdVoUEDAVFajJ+LjoOt470oHNED9g7iC/jC
+ X4HnvkmoudMXShAyFU/SPc3l5ZSCAmLUXSh4sAdsgzfAv/Z+uFcdCEWE+bkSIa0h/MXIfuhyMJEjs6XE
+ /i4EAtPJIjgjazhjFJFR2WeZDcetsusZf9aIjL/kmnNGAoD8/k4Ev3sU7g/WwPdpTcjMlwffPxZ+GbxN
+ NdEbQZEZg3JxUQECDAiF7WEpmY/CIYPh6G/VS8T7oVSPRfXQv8K/CeEJQqYgIwCAGaVG/ofAfs545P/h
+ GXhWkMn/d4924QGEtL8YrDXkopCIwqTwAiMFqMBUXIHhuIT+Jf0rBFkCAKVbLDhnmgMV1ZFbfS1xavwl
+ tgD4eScC362A54M34P2iJhTVF6AtrDYWfBm8Iwt1Hgokg4AoMMogIKyBEv11IU3OvMnIH3AD8ofn6xuJ
+ diHw7vGoHO3T+Gaq3IB0TvOwDRatYCmbiby5L8L3+gYEvtXf54sW2t+FkNYQ/lEixtQlFUHUFhhGj+sw
+ jbC5mWk5YxBZSeROvsWOXuu0fH95q28i7R8DABS6Eb5NZOo/Bc/69fBv94aEvCrKEPEaUc/fsD72JiB5
+ fovgoOwStNBf59OHLANhq1iMogkdYe3M/FiM2kn3wLMaJksTNgIA1KBJBSyt6UqdP5LvCFFzUhNy1hQ8
+ aSJN/mQZIi8vMtMPw4l6cPCwBlYfNpozRhBx6rD3LL7Bcx2WDkGrtQJWa7ne3CPU2isRACjqiowLinsb
+ At+8Df+X78P35fdagQtxj1j4qyOG8PXl+3coC78geV+LHBcQdQaL9b/5fYVcMetCFI45G45zSeJ/PAuV
+ p24mdwomCggaBgDSsOsME9rfow/RCKIhJqO4CaEVgh44BrNxE7qjZ1quy+wA8DPxbjI+bbYDlSz8nWB1
+ 9oK9eRdYW3IhiyJYnMR4LnivVuPmBpvE7ABH8Q9AqeRU1S8Q2Pctgvs+h/+bytAuPdZQtagPAMLUr0XI
+ ahMumym0WYZIxlCe66K6kMgXaKb/zfM+SMz3TIXzN9ej4PoN8L98OVyzvaFYSZPzzSgAEEMIPxNPFJ4w
+ kR1g0EAmRAYHW5HzezjmkkNwPAbRvzSuIr+ZAYC59TD+g0exGeGBOLXABjHFWkL+J6kiB1kDdu6w6yb5
+ /5k0vSvkg/r1Icx3AcwCAGqk52iC/0vR+rFIzD+R71LXekwfTv3fVau3N92SpSia8kd4lq2Edz1M4jIZ
+ FQOw6xcv4k0C6cSkS2eUuC7dGLxCwNWHr8Z4DMfFdGsSFx7NBGfSTTtxEBPwJulkecMNC2kQoYkpeM8k
+ N9XgwfyXAYCFWgYA2QpwI2SxiWMSdeT9pZDsEoi4QIE0RHCaeeZuC4syGs5Oy+FZX2OSPoNGAIA8+WJN
+ wHRPHrn6cAu6HW1I/C/CREyiW9K8Qd9oVgDgdsOz8QY+wBaE19b36J+woT4AaEeGVmGiAYAMAvIQ1lpk
+ kPaXLvyC5Hkv4gL5+rOwAoTFJYPsIQkAMkPk747Vvjnd1xIeHDyDXIHrMYOcg7ZNypl00npspyt6nqbU
+ Hmh77hkE2D8PIKSNBAgkYwHIICA/i+CebK3lhD42ySAgYgP8LLZhCBAQ7lZkvkuTnXQmv8voC5WDgxyQ
+ KUNP9MUczELnFFuTmREAakk4J+Jx/FfV/typlttrsQsQTfuLTVeyCxZEOAjwEBNRds9y2r5hFLlKIGJg
+ YjZFgu8hBQBmITk4qPUnLEd3/A4zcQxOzGrOPI1/YBleo+myC1AHLymx+e9HaOLJ5f5kigYCYkJGc81y
+ Qt8wki1g+X5EA+IcABh4XTxEQ0hOH+6k9iEYiCFIpsCI2TizFwcwASvI4OeW2txg43/Qim+w+S8mUCw3
+ LFZzzUSNNXPUcKq/iTIEAkymsLDMNs3TTXJwsIRetcGVGItL1dZkceu9m4ozHPibj1fxMt6DpvkZANj8
+ F9o/J7zmpGRnUQ4ADL7GUGsyDg6eh7MwDTNQHKe2gJk4s4kE/kasRI0q+DuhaX8O/nE02XR7zHOUPWSm
+ aW70dYrahFpwsA+Ow624BeUxaguYhTMuEvIbsQqfgFtqs/Dvghb9540lpkgnzVH2klmmeaaulV0CkT7c
+ Ch1wJG7HLByBvvV4YQbOsGi/gA24Fy+SqLPWZwDg6L+I/OeEP0eNIjNM80xfr9hWrNUW4BIj09Xg4GBY
+ pPRhM3BmDw5gKh4jb38rQtqfq/CIdf8c5ahRZIZp3hQkQEALDhaRLXA5LsMojKkLDjY1ZwLk2z+It/AU
+ 3gTqlv14WzUH/kRTzRzlqFHU1NO8KUls5GAQaAk7ynE+hmASpqjlyJuSMyzan5LGn4EnUVsX+PsaWtqv
+ yPnPUY4aTb9kABDXLzoWF6vVtI7DSZiFmTGDg5mgn8nEvxZPYJu6209E/Tnwx0U4cst+OUob/dIBgEnE
+ BdTGpeAVgk44Er/DbPRA74xziE3/xViDF/ABNMHfBW3Nn4t0cOAvp/1zlDbKAYBG9QuPtiQLYB7m4HgM
+ hCVDfOKEn4fI71+J9+gVR/sZAESHXTb9c4G/HKWVcgAQTnJwsJTgoByTcSVG4lJ619nI745PLtLuj+Ad
+ rMI6aOY++/xC+HOmf44MoRwA1CeRPhzKHDwdg8gnvwZtUJF2a4C1/nbswSKsxefqch8v87Hgi/baLPyi
+ ik+OcpRWygFAdAoPDnJcoC1+jXG4BKeSS9BCrb3ZON5xL+n9qMZL2IjnsB4H1f39vLmHBZ9BgFttcZmv
+ nN+fI8MoBwCxSQ4OanEBi5o21AODcRpOxgC0J1hwqEV4kycfmfLfkXC/j814HZ9hl+rrc4CPs/tEa20u
+ 8cXJPjnNnyNDKQcA8UnOHBS94dTGkGQDlBMYdCUgOAadcTg6kqvQHEUEF/nkQGiNIgP08JAQu1BLHv0B
+ bMP/8CEZ/DsJAn5SBZ7Ne9EYVTTX5PdEb8Sc8OfIUMoBQHIkkobk/nDFEGWgrTS4JnEB/e0kELDpteCC
+ 9PDRw02PH0mw/XUFNkW5bbnTjmi0YZqa8Tk69CkHAMmTXPVY1IIvlAb/LQpBiqrIogCEXBJdAIA8RDdd
+ udR2jnJkOOUAIHWSq8CK/geiCYpcCFLuSyAXhJSr7/5Sm2vkyCSUA4DGUWT9N1EDzobwUlCiBpwQ9lyl
+ 3RyZgv4fwxUHs6QSBV4AAAAASUVORK5CYIIoAAAAgAAAAAABAAABACAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAAAAoAAAATAAAAGgAA
+ AB4AAAAeAAAAFwAAAA4AAAAGAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAABQAAABMAAAApAAAAQAAMAFgAEgBoABMAbAAOAGYAAQBYAAAASAAAADMAAAAcAAAACQAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAsAAAAmACMAYABqAKwAowDfAL4A9QDG
+ AP0AxgD+AL8A+ACkAOUAbAC/ACIAhgAAAFgAAAAzAAAAEwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAAQABAAPQCCALgAwwD6AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AwwD8AHcAygAL
+ AHYAAABBAAAAFwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFQApAFgAsADlAMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AKkA6wAXAIMAAABAAAAAEQAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAA
+ ABwAQgB0AL0A8wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AKYA6AAJAHIAAAAxAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAgAkAGAAkwDDAPoAyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AG8AxQAAAFgAAAAdAAAAAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAALAAcALgB/
+ ALIAxgD+AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AwQD7ACQAjQAAAD8AAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAACAAAADwASAD0AmADMAMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AkwDcAAIAZgAA
+ ACYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABQAJgBUAK0A4gDH
+ AP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8ARQCnAAAASgAAABMAAAACAAAAAQAAAAIAAAADAAAAAwAA
+ AAIAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAAAgAAAAMAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAUAAAAZADoAbAC7APAAxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCv
+ AO8ACQB2AAAAOAAAABcAAAAWAAAAGwAAAB4AAAAeAAAAHAAAABgAAAATAAAADQAAAAcAAAADAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAAAMAAAADQAAAAgAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAABgAAAAYAAAADAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAIABXAIgAwgD5AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wBlAMYAAAByAAAATAAAAEEAAABFAAAASQAA
+ AEkAAABHAAAAQgAAADoAAAAxAAAAJgAAABkAAAAOAAAABgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAQAAAAOAAAAGwAAACAAAAAaAAAADQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAgAAAAkAAAAQAAAAEwAAABAAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAACgAEACoAdACmAMYA/QDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AL8A+wAbALEAAACIAAAAdAAAAHIAAAx6AQARfQAACXcAAABvAAAAaAAAAF4AAABRAAAAQQAA
+ AC8AAAAdAAAADgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAFAAAACgAAAA2AAAAMwQAQ08DADYmAAAAAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAADCAAAAAmAAAAJgAA
+ ABkAAAAKAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAA4ADgA4AJAAxADHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AIoF7wQAQtwIAH/kDACw8w0A
+ vvkOAML6DgDB+QwAtu8LAJ/fBwB2xAQAPZoAAAZwAAAAWwAAAEUAAAAuAAAAGQAAAAoAAAADAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACQAA
+ ABkAAAAyAAAASAAABU4IAH6YCwClogAAAQkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAAJAwA5TAUAT3wAAAFAAAAANwAAACEAAAAOAAAABAAAAAAAAAAAAAAAAAAA
+ AAIAAAASACAATQCnANwAxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AxgD/BDlG/wkAi/8MALb/DgDF/w8AyP8PAMr/DwDM/w8Azv8PAND/DgDS/w4A
+ xPMIAHS+AQAXfAAAAFgAAAA+AAAAIwAAABAAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAA0AAAAgAAAAPAAAAFcCACBzDAC40w8A5O4BAB8lAAAAAwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAIVCQCJuwcA
+ ebsAAAxdAAAARAAAACgAAAASAAAABQAAAAEAAAAEAAAAGAA0AGYAuADuAMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8ApQ//Bwdr/wsA
+ oP8NAMD/DwDH/w8Ayf8PAMv/DwDN/w8A0P8OANL/DwDU/xAA1v8PAND4BwB3vQAADm4AAABKAAAALAAA
+ ABQAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAPAAAAJQAA
+ AEMAAABiBABFlg8A2vERAOz/BwB0dQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAoCACNACwCy9goAm+QCACR+AAAATgAAAC4AAAAWAAAADQAB
+ ACAATwCCAMEA+ADHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8DWDT/CQCD/wwAsf8OAMX/DwDI/w8Ayv8PAM3/DwDP/w4A
+ 0f8PANP/EADV/xAA1/8QANr/DQC96gMAOI4AAABSAAAAMQAAABYAAAAGAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAAEAAAAEgAAACkAAABKAAADbAcAcbYQAOj8EQDt/w0AxcoAAAoSAAAAAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA
+ ABIGAGiUDAC2/wsArPYEAD2YAAAAVQAAADoAAwA7AG4AowDFAPwAxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wC6
+ Bf8GFl3/CgCY/w4Avf8PAMf/DwDK/w8AzP8PAM7/DgDR/w8A0/8PANX/EADX/xAA2f8QANv/DwDX+gcA
+ Z6wAAAFWAAAAMgAAABYAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAAABIAAAArAAAATgAA
+ DXUKAJ7READs/xEA7f8QAOn4AwA/QAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAADCQKAKXhDAC2/wwAs/wFAFe2AAgAegCG
+ AMoAxgD+AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wJ/If8IAHr/DACr/w4AxP8PAMn/DwDL/w8A
+ zv8OAND/DwDS/w8A1P8QANb/EADY/xAA2/8QAN3/DwDe/ggAhsAAAAJXAAAAMQAAABQAAAAFAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAQAAAARAAAAKwAAAE4BABN6DAC54BEA7P8RAO3/EADs/wkAj4wAAAAIAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACAAAADAQAQmMMALT9CwCq/wkThP8BnBH2AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMcA/wUwTP8JAI//DQC5/w4AyP8PAMv/DwDN/w4Az/8PANH/DwDU/xAA1v8QANj/EADa/xAA
+ 3P8QAN7/EADg/wkAicAAAARUAAAALAAAABAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACoAAABOAQAVfA0A
+ wuYRAO3/EQDt/xEA7f8OAM3SAAANFAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABGAcAc7QIJXT/Aa0Q/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AaER/wcEb/8LAKP/DgDD/w8A
+ yv8PAM3/DgDP/w8A0f8PANP/EADV/xAA1/8QANn/EADc/xAA3v8QAOD/EADi/wgAgLgAAAFMAAAAJQAA
+ AAwAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAwAAAA4AAAAoAAAATAEAFXoNAMLmEQDt/xEA7f8RAO3/EADp9gMAPjsAAAAEAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAYAAAAiAEAKjgC6CP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AxwD/A1U3/wkAhv8NALX/DgDI/w8AzP8OAM7/DwDQ/w8A0/8QANX/EADX/xAA
+ 2f8QANv/EADd/xAA4P8QAOL/EADi/gYAY6AAAABBAAAAHQAAAAcAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAMAAAAJQAAAEkBABJ2DQC94hEA
+ 7f8RAO3/EQDt/xEA7P8HAHp0AAAABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAIQBgAJIAwwD7AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AuAb/BxRh/wsA
+ m/8NAMH/DwDL/w4Azv8PAND/DwDS/w8A1P8QANf/EADZ/xAA2/8QAN3/EADf/xAA4f8RAOP/EADe+QMA
+ MnkAAAA0AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAACgAAACAAAABEAAAMcAwAtd0RAO3/EQDt/xEA7f8RAO3/CwCnpgAABQwAAAABAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAACgAFACoAfACuAMYA/gDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AxwD/AI0A1wCRAdwAyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8CeiT/CAB9/wwAr/8OAMn/DgDO/w8A0P8PANL/DwDU/xAA
+ 1v8QANj/EADa/xAA3P8QAN//EADh/xAA4/8RAOX/DgDI5wAADlcAAAAnAAAACwAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAbAAAAPQAAA2YKAJ7QEQDs/xEA
+ 7f8RAO3/EQDt/w4AyMoBABIVAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAwADgA2AJEAxADHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCWANkABgN9Bw9y4AGrFv8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDE
+ Af8FLU//CgCU/w0Av/8OAM3/DwDP/w8A0f8PANT/EADW/xAA2P8QANr/EADc/xAA3v8QAOD/EADi/xEA
+ 5P8RAOf/CQCLuAAAAEQAAAAkAAAAFgAAABMAAAARAAAADgAAAA0AAAALAAAACQAAAAgAAAAHAAAABgAA
+ AAcAAAALAAAAGQAAADgAAABeCACBvREA7f8RAO3/EQDt/xEA7f8PANvhAQAnJgAAAAMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAAPABoARQCkANgAxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AyAD/AMgA/wDI
+ AP8AnADbAAwAcQUARqoMAKj/CSqB/wC+B/8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wGcE/8IA3T/DACp/w4AyP8PAM//DwDR/w8A
+ 0/8QANX/EADX/xAA2v8QANz/EADe/xAA4P8QAOL/EQDk/xEA5v8QAOT7AwAzggAAAFAAAABCAAAAPAAA
+ ADgAAAA1AAAAMgAAAC8AAAAtAAAAKgAAACkAAAAoAAAAKAAAAC4AAAA/AAAAXAUAVqQQAOv+EQDt/xEA
+ 7f8RAO3/EADm8gMAPj4AAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAEQAnAFQAsADkAMgA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMgA/wDIAP8AyAD/AKMA4gATAHQAAAt2CwCd8gwAqv8MAKj/Bkxk/wDH
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wRNPf8JAIz/DQC7/w4Azv8PANH/DwDT/xAA1f8QANf/EADZ/xAA2/8QAN7/EADg/xAA
+ 4v8RAOT/EQDm/xEA6P8MALHcAAACfgAAAHQAAABrAAAAZgAAAGMAAABgAAAAXQAAAFoAAABYAAAAVgAA
+ AFUAAABVAAAAWgAAAGkCAC2RDwDh+BEA7f8RAO3/EQDt/xAA7P0GAGVgAAAABQAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
+ ABIAMwBeALwA8ADIAP8AyAD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AyAD/AMgA/wCr
+ AO0AFwCMAAAAfAYAWsENAKz/DQCr/w0Aqv8MAKf/BHhA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/ALUI/wcNaf8LAKL/DgDH/w8A
+ 0P8PANP/EADV/xAA1/8QANn/EADb/xAA3f8QAN//EADh/xEA4/8RAOb/EQDo/xAA6f4IAH3YCgCQ4QoA
+ m9oKAJfQCQCLxwcAeb4HAGe1BgBZqwUATaIEAEGdAwA5mgMAM5gDADueBQBYsA4Az+8RAO3/EQDt/xEA
+ 7f8RAO3/CQCPiAAAAQgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANADoAYwC/APQAyAD/AMgA/wDIAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDIAP8AsQH0ABsDpgAABJoAABOoCwCk+A0Arv8NAKz/DQCr/w0A
+ qv8MBqP/Ap0i/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AxwD/A3Aq/wkAhP8MALb/DgDO/w8A0/8QANX/EADX/xAA2f8QANv/EADd/xAA
+ 3/8QAOH/EQDj/xEA5v8RAOj/EQDq/w8A2P8MALL/DwDW/xAA6f8RAOz/EQDt/xEA7f8RAO3/EQDt/xEA
+ 7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/EQDt/wwAvbwAAAYOAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAx
+ AEgAwAD0AMgA/wDIAP8AyAD/AMgA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/ALMM/wgc
+ dPkKAJL5CQCE/gkAjv8NALH/DQCv/w0Arf8NAKz/DQCs/w0Aq/8KGJT/AbQQ/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AwgL/BSNY/woA
+ m/8NAMX/DwDS/xAA1f8QANb/EADZ/xAA2v8QAN3/EADf/xAA4f8RAOP/EQDl/xEA5/8RAOr/EQDs/wwA
+ t/8OAMj/EADk/xEA7P8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA
+ 7f8PANrfAQAgIgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAIAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAJ0AwADIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wC1C/8IJXb/CwCk/woAl/8IAHv/DACq/w0Asv8NALD/DQCv/w0A
+ rv8NAK3/DQCt/w0ArP8JNnv/AMIE/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8BkBr/CAJ7/wwAsP8OAM7/EADU/xAA1v8QANj/EADa/xAA
+ 3f8QAN//EADh/xEA4/8RAOX/EQDn/xEA6f8RAOz/DgDU/wwAuv8PANz/EADr/xEA7f8RAO3/EQDt/xEA
+ 7f8RAO3/EQDt/xEA7f8RAO3/EQDt/xEA7f8RAO3/DwDf5gMANTYAAAAEAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAIAAAACAAAAAYAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX
+ AAcAwADgAMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AuQj/Byty/wsA
+ qP8LAKf/CQCN/wkAh/8MALX/DQCz/w0Asv8NALD/DQCv/w0Arv8NAK7/DQCu/wwArf8GYVb/AMcA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDG
+ AP8EQkb/CgCT/w0Awv8QANP/EADW/xAA2P8QANr/EADd/xAA3/8QAOH/EADj/xEA5f8RAOf/EQDp/xEA
+ 6/8QAOz/CQCOzAsAp8YNAMTSDwDk3xAA6u0QAOz4EQDt/xEA7f8RAO3/EQDt/xEA7f8RAOz9EADn5gsA
+ o5wCAC0lAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAAIAAAAEgAAABgAAAAVAAAADAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAgCbALIAyAD/AMgA/wDIAP8AyAD/AMgA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/ALsH/wcub/8LAKn/DACx/wsAof8IAIL/CwCg/w0Atv8NALT/DQCz/w0A
+ sv8NALH/DQCw/w0Ar/8NAK//DQCv/wwCrP8DijT/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wCtDP8HCXD/CwCq/w8Azv8QANb/EADY/xAA
+ 2v8QANz/EADe/xAA4P8QAOL/EQDl/xEA5/8RAOn/EQDr/xEA7f8IAHeeAAAAKwAAAgwAAA4IAAARDQAA
+ DRIBAB4XAwA8IgQAQCsEAEArBAA/JgIAJBcAAAwKAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAAAABsAAAAqAAAALAAACyQCACUfAAAAAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAACwAKgC9AOYAyAD/AMgA/wDIAP8AyAD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDBAPkEMUfJCAB3tggA
+ f6MHAHOUBQBMlAQARaYNALX+DQC3/w0Atv8NALT/DQCz/w0Asv8NALH/DQCx/w0Asf8NALH/DQCx/wsO
+ ov8BrRb/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AxwD/AMgA/wNkMv8JAIv/DQC+/w8A1P8QANj/EADa/xAA3P8QAN7/EADg/xAA4v8RAOX/EQDn/xEA
+ 6f8RAOv/EQDt/w0AxtoAAAA3AAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAA
+ ABAAAAAkAAAAOwAAAEUCAClTDACupwEAEBQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACACIAKwGKEMIAwgX/AMgA/wDI
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AwAD0AD0AaAAAABQAAAAEAAAAAgAAABEAAAA3BQBKmA4Auv8OALj/DQC3/w0A
+ tv8NALT/DQCz/w0As/8NALL/DQCy/w0Asv8NALL/DQCy/wonjf8Avgj/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8AyAD/AMAD/wYaYv8LAKL/DgDM/xAA
+ 2P8QANr/EADc/xAA3v8QAOD/EADi/xEA5P8RAOf/EQDp/xEA6/8RAO3/EADs/AIAKFkAAAAaAAAAAwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAAAAUAAAALAAAAEgAAAJaBgBfjxAA5PEGAFhVAAAABgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAAHAQAVKgwZqewGXlrpAJgE2AC8APIAxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/ALgA6wA4AFwAAAAQAAAAAgAA
+ AAAAAAACAAAAGQAAAEMJAIPKDgC7/w4Auf8OALj/DQC3/w0Atv8NALX/DQC0/w0AtP8NALP/DQCz/w0A
+ tP8NALT/DQC0/wdHcf8AxgH/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMcA/wDIAP8AyAD/Aogf/wkAgv8NALj/DwDV/xAA2v8QANz/EADe/xAA4P8QAOL/EQDk/xEA
+ 5v8RAOn/EQDr/xEA7f8RAO//BwBskgAAACQAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAJAAAAGQAA
+ ADQAAABTAAAMbgoAmcIRAO/+DAC1sAAAAAoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAPBgBfeA8A
+ 0/4KAJXNAQsQcwApAGoATgB4AGsAiACMAKQAngDCAL0A3wDGAPgAxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/gCaAMEAIQA8AAAACwAAAAIAAAAAAAAAAAAAAAUAAAAiAAAFUQ0As/IOALz/DgC7/w4A
+ uf8OALj/DQC3/w0Atv8NALX/DQC1/w0Atf8NALX/DQC1/w0Atf8NALX/DAG0/wVvTv8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDIAP8AxgD/BThO/wsA
+ mv8OAMn/DwDZ/xAA3P8QAN7/EADg/xAA4v8RAOT/EQDm/xEA6f8RAOv/EQDt/xEA7/8MAK/GAAAALgAA
+ AAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAB0AAAA6AAAAWwIAIoQNAL/gEgDx/xEA6PACACgrAAAAAwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAUcDACw0BAA1P8NALTmAgAhfAAAAEsAAAArAAAAEwAA
+ AAcABgAIABYAEQAyAC8ATQBUAGUAdgCAAJMAkACkAI8ApAB1AIwAOABGAAIADwAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAACQAAACoCACp0DgC//w4Avf8OALz/DgC7/w4Auf8OALj/DQC3/w0At/8NALb/DQC2/w0A
+ tv8NALb/DQC2/w0At/8NALf/DQaw/wKYKf8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDHAP8AyAD/AMgA/wDIAP8BphD/CAZ4/wwAsf8PANT/EADc/xAA3v8QAOD/EADi/xEA
+ 5P8RAOb/EQDp/xEA6/8RAOz/EQDv/xAA4O4AAAw8AAAAEAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAsAAAAfAAAAPgAA
+ AGEEAEadEADe8xIA8f8RAPD/CAB5dAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAoDADZMDwDQ+Q8A0/8OAMb1BABAlAAAAFAAAAAtAAAAEwAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAMwUAVZwOAMD/DgC//w4A
+ vf8OALz/DgC7/w4Auv8OALn/DgC4/w4AuP8OALj/DQC3/w0At/8OALj/DgC4/w4Auf8OALn/DBSk/wGz
+ Ev8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDIAP8AyAD/AMgA/wDI
+ AP8DWzn/CgCR/w4Axf8PANv/EADe/xAA4P8QAOL/EQDk/xEA5v8RAOn/EQDr/xEA7P8RAO//EQDx/gMA
+ N2AAAAAXAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAIAAAALAAAAIAAAAEAAAABlBwBpsREA7fwSAPH/EgDx/w4AxMQAAAgQAAAAAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABIJAIOeDwDT/w8A0/8OAM/8BgBapgAA
+ AFIAAAAuAAAAEwAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAABMAAAA7CAB/wA4Awv8OAMD/DgC//w4Avf8OALz/DgC7/w4Auv8OALr/DgC5/w4A
+ uf8OALn/DgC5/w4Auf8OALn/DgC6/w4Auv8OALv/CjGK/wDCBP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wC6Bv8HF2j/CwCp/w8A0/8QAN7/EADg/xAA
+ 4v8RAOT/EQDm/xEA6f8RAOv/EQDs/xEA7/8RAPH/BwBmiAAAAB0AAAADAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAB8AAABAAAACZggA
+ eroRAO/+EgDx/xIA8f8RAOryAwA1NQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAABwEAEygNAMDjDwDT/w8A0/8PAND9BwBlrQAAAVIAAAAsAAAAEgAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAGAAAAEILAKXfDgDD/w4A
+ wf8OAMD/DgC//w4Avf8OALz/DgC8/w4Au/8OALr/DgC6/w4Auv8OALr/DgC6/w4Auv8OALv/DgC7/w4A
+ vP8NALz/B1pl/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wJ/Jf8JAIj/DQC//w8A2/8QAOD/EADi/xEA5P8RAOb/EQDp/xEA6/8RAOz/EQDv/xEA
+ 8f8KAJGsAAAAIwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAkAAAAdAAAAPgAAAGQIAH+9EQDw/hIA8f8SAPH/EQDw/ggAfXcAAAAGAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAUATGAPANL8DwDT/w8A
+ 0/8PANH+BwBmrAAAAE4AAAAqAAAAEAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAMAAAAeAAAFSw0Av/gOAMT/DgDD/w4Awf8OAMD/DgC//w4Avv8OAL3/DgC8/w4A
+ vP8OALv/DgC7/w4Au/8OALv/DgC7/w4AvP8OALz/DgC9/w4Avv8NArv/BIU9/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMYA/wUwVf8LAKH/DgDQ/xAA
+ 4P8QAOL/EQDk/xEA5v8RAOn/EQDr/xEA7P8RAO//EQDx/w0AvcsAAAAoAAAACAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAGgAAADoAAABhCAB3uBEA
+ 8P4SAPH/EgDx/xIA8f8NALezAAADDAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAAAEQkAiJ8PANP/DwDT/w8A0/8PANL+BgBbowAAAEoAAAAmAAAADQAA
+ AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACICACJkDgDG/g4A
+ xf8OAMT/DgDD/w4Awf8OAMD/DgC//w4Avv8OAL7/DgC9/w4Avf8OALz/DgC8/w4AvP8OAL3/DgC9/w4A
+ vf8OAL7/DgC//w4AwP8MDLP/Aace/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AaIS/wgCf/8MALn/DwDb/xAA4v8RAOX/EQDn/xEA6f8RAOv/EQDs/xEA
+ 7/8RAPH/DwDV5AAABC8AAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAABQAAABcAAAA2AAAAXQcAa7ARAO/+EgDx/xIA8f8SAPH/EADc3gEAGR0AAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAKHQwA
+ tdMPANP/DwDT/w8A0/8OAND8BQBKlgAAAEUAAAAhAAAACgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAGAAAAJgQAN3gPAMj/DwDH/w4Axf8OAMT/DgDD/w4Awv8OAMH/DgDA/w4A
+ v/8OAL//DgC+/w4Avv8OAL7/DgC+/w4Avv8OAL7/DgC//w4Av/8OAMD/DgDB/w4Awv8LIp7/ALwK/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/BFRA/woA
+ mP8OAMz/EADh/xEA5f8RAOf/EQDp/xEA6/8RAO3/EQDv/xEA8f8RAO31AQAQOwAAAAwAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAASAAAAMAAAAFgFAFKhEQDt/BIA
+ 8f8SAPH/EgDx/xEA6/IDAD48AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAgApOw4AyO0PANP/DwDT/w8A0/8OAMv4AwA4hQAA
+ AD4AAAAcAAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAqBQBQjA8A
+ yf8PAMj/DwDH/w4Axf8OAMT/DgDD/w4Awv8OAMH/DgDA/w4AwP8OAL//DgC//w4Av/8OAL//DgC//w4A
+ v/8OAMD/DgDA/w4Awf8OAML/DgDD/w4Aw/8IRH7/AMYB/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8Atwj/CBFw/wwAsf8PANr/EQDl/xEA5/8RAOn/EQDr/xEA
+ 7f8RAO//EgDx/xIA8/8CACFMAAAAFQAAAAcAAAAGAAAABQAAAAQAAAADAAAAAgAAAAIAAAABAAAAAQAA
+ AAEAAAAEAAAAEAAAACoAAABQBAA8kREA5/gSAPH/EgDx/xIA8f8RAO/7BgBnYQAAAAYAAAABAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAALBQBQYQ8A0foPANP/DwDT/w8A0/8NAL7uAQAdcAAAADYAAAAWAAAABgAAAAEAAAAAAAAAAAAA
+ AAAAAAABAAAAAQAAAAIAAAACAAAADAAAADAGAGCgDwDK/w8Ayf8PAMj/DwDH/w4Axf8OAMT/DgDD/w4A
+ wv8OAML/DgDB/w4Awf8OAMD/DgDA/w4AwP8OAMD/DgDB/w4Awf8OAMH/DgDC/w4Aw/8OAMT/DgDF/w4A
+ xf8GbVb/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8Cdiv/CgCP/w4Ax/8QAOP/EQDn/xEA6f8RAOv/EQDt/xEA7/8SAPH/EgDz/wQAO20AAAA0AAAAKAAA
+ ACYAAAAkAAAAIAAAAB4AAAAcAAAAGgAAABgAAAAYAAAAGAAAAB0AAAAuAAAATQEAHHwPANfvEgDx/xIA
+ 8f8SAPH/EQDw/gkAioQAAAIIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAEPCAB1ig8A0/8PANP/DwDT/w8A
+ 0/8MAK/hAAAKXgAAADQAAAAcAAAAEwAAABEAAAARAAAAEwAAABQAAAAWAAAAGgAAABwAAAAnAAAASQgA
+ dLYPAMz/DwDK/w8Ayf8PAMj/DwDH/w4Axf8OAMX/DgDE/w4Aw/8OAML/DgDC/w4Awv8OAML/DgDC/w4A
+ wv8OAML/DgDC/w4Aw/8OAMP/DgDE/w4Axf8OAMb/DwDG/w4Fwf8DkzL/AMgA/wDIAP8AyAD/AMgA/wDH
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDCAv8GKV7/DACp/w8A2f8RAOf/EQDp/xEA
+ 6/8RAO3/EQDv/xIA8f8SAPP/BQBFkAAAAF4AAABVAAAAUwAAAFAAAABMAAAASQAAAEYAAABEAAAAQgAA
+ AEIAAABCAAAASAAAAFgAAAh0DQC84BIA8f8SAPH/EgDx/xIA8f8MALCpAAAFCwAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAQAAAYVCgCZsw8A0/8PANP/DwDT/w8A0/8JAIXEAAAAXAAAAEYAAAA7AAAAOQAA
+ ADkAAAA7AAAAPgAAAEAAAABDAAAARwAAAFIAAABuCAB8yg8Azf8PAMz/DwDK/w8Ayf8PAMj/DwDH/w4A
+ xv8OAMX/DgDF/w4AxP8OAMP/DgDD/w4Aw/8OAMP/DgDD/w4Aw/8OAMP/DgDE/w4AxP8OAMX/DgDG/w8A
+ x/8PAMj/DwDJ/w0StP8Brxf/AMgA/wDIAP8AyAD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wGWGv8JAob/DQDB/xAA4/8RAOn/EQDr/xEA7f8RAO//EgDx/xIA8/8HAGa4BQBJqAQA
+ QZ4DADeXAgApjAEAFYAAAAZ6AAAFdgAAA3IAAAFwAAAAbwAAAHAAAAF0AAAHgQsAnNERAPD/EgDx/xIA
+ 8f8SAPH/DgDQzgEAEBUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYAABAhDQC31g8A
+ 0/8PANP/DwDT/w8A0v8GAFywAAAAcgAAAGkAAABnAAAAaAAAAGoAAABsAAAAbgAAAXIAAAZ3AAALggAA
+ DJgJAIjeDwDP/w8Azf8PAMz/DwDK/w8Ayf8PAMj/DwDH/w8Ax/8PAMb/DgDF/w4Axf8OAMX/DgDE/w4A
+ xP8OAMT/DgDF/w4Axf8OAMX/DgDG/w8Axv8PAMf/DwDI/w8AyP8PAMr/DwDK/wstmv8Avwf/AMgA/wDI
+ AP8AxwD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMcA/wVGSv8LAKH/DwDV/xAA
+ 6f8RAOz/EQDt/xEA8P8SAPH/EgDz/w8A0v8QAN//EgDw/xIA8f8SAPH/EgDx/xEA7fwQAOT2DwDX7w4A
+ y+oOAMToDgC+5g4AxukQAOD1EQDw/xIA8f8SAPH/EgDx/xAA5+wCAC4uAAAAAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgCACs/DwDL8Q8A0/8PANP/DwDT/w4A0P0LAKPgCQCI0gkA
+ f84JAIfRCQCO1AoAm9sMAKjkDACy7A0Av/INAMH4DACq/QwAuP8PAND/DwDP/w8Azf8PAMz/DwDL/w8A
+ yv8PAMn/DwDI/w8Ax/8PAMf/DwDG/w8Axv8OAMb/DgDG/w4Axv8OAMb/DwDG/w8Axv8PAMf/DwDH/w8A
+ yP8PAMn/DwDJ/w8Ayv8PAMz/DwDM/whSdv8AxwD/AMgA/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/ALEL/wgKev8NALr/EADj/xEA7P8RAO7/EQDw/xIA8v8SAPP/DwDT/xAA
+ 3/8SAPD/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA
+ 8f8RAO/7BgBbVgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
+ AA0GAF5yDwDS/g8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w4A
+ y/8MAK3/DAC5/w8A0f8PAND/DwDP/w8Azv8PAMz/DwDL/w8Ayv8PAMn/DwDJ/w8AyP8PAMf/DwDH/w8A
+ x/8PAMf/DwDH/w8Ax/8PAMf/DwDH/w8AyP8PAMj/DwDJ/w8Ayv8PAMr/DwDL/w8Azf8PAM7/DgHM/wV9
+ Sv8AyAD/AMcA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/A2g1/woA
+ mP8OAND/EADq/xEA7v8RAPD/EgDy/xIA9P8PANT/EADg/xIA8P8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA
+ 8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EQDw/gkAiIIAAAEIAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAhAJAI2eDwDT/w8A0/8PANP/DwDT/w8A
+ 0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DgDM/wwAr/8NALr/DwDS/w8A0f8PAND/DwDP/w8A
+ zv8PAM3/DwDM/w8Ay/8PAMr/DwDJ/w8Ayf8PAMj/DwDI/w8AyP8PAMj/DwDI/w8AyP8PAMn/DwDJ/w8A
+ yf8PAMr/DwDL/w8Ay/8PAM3/DwDO/w8Az/8PAND/DgjF/wKkI/8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AwQP/Bx1q/wwAsv8PAOH/EQDu/xEA8P8SAPL/EgD0/wwA
+ rc4QANrnEgDw/hIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPH/EgDx/xEA
+ 7fQIAH9wAAAEBwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAACAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAABAAABxEKAJCcDwDS/A8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A0/8PANP/DwDT/w8A
+ 0/8PAM3/DQCy/w0AuP8PANT/DwDS/w8A0f8PAND/DwDP/w8Azv8PAM3/DwDM/w8Ay/8PAMv/DwDK/w8A
+ yv8PAMr/DwDJ/w8Ayf8PAMn/DwDJ/w8Ayv8PAMr/DwDL/w8Ay/8PAMz/DwDN/w8Azv8PAM//DwDQ/w8A
+ 0f8PANL/DB6v/wC6DP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8CjCD/CQCP/w4Ayv8QAOr/EQDx/xIA8v8SAPT/BQBLagAAARIBACAQBAA3KgQAREEGAGhSCABvYggA
+ cnIJAIWCCwCjjgsAp5YMAKeWCwCmkgkAhn8IAG5dAgAgFwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAUAAAAJAAAACgAAAAgAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAMAAAAEAAAABAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYEAD09CQCEigsA
+ orINALnBDQC6xA0AuL8MALS6CgCVrAkAi5oJAIiLCAB1eQYAV2gEAEJnCAB9sxAA1f8PANT/DwDT/w8A
+ 0f8PAND/DwDP/w8Az/8PAM7/DwDN/w8Azf8PAMz/DwDL/w8Ay/8PAMv/DwDL/w8Ay/8PAMv/DwDL/w8A
+ y/8PAMz/DwDN/w8Azf8PAM7/DwDP/w8A0P8PANH/DwDS/w8A0/8PANP/CkCM/wDEA/8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDGAP8FPVP/CwCp/w8A3f8RAPD/EgDz/xIA
+ 9P8EAERZAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAALAAAAFgAAABwAAAAYAAAADQAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAwAAAAPAAAADAAA
+ AAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAIAAAACAAAAAgAAAAIAAAABAAAAAQAA
+ AAAAAAAAAAAABAAAACAGAFyMEADW/xAA1f8PANT/DwDT/w8A0v8PANH/DwDQ/w8Az/8PAM7/DwDO/w8A
+ zf8PAM3/DwDM/w8AzP8PAMz/DwDM/w8AzP8PAMz/DwDN/w8Azf8PAM7/DwDO/w8Az/8PAND/DwDR/w8A
+ 0v8PANL/DwDU/xAA1f8PANT/B2dk/wDHAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wGpEP8ICIH/DQDC/xEA6v8SAPP/EgD1/wMAM0UAAAAJAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAEQAA
+ ACMAAAAxAAAAMAEAEisDADcoAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAIAAAAJAAAAFgAAACAAAAAhAAAAFgAAAAgAAAACAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAGwUATHcQANj/EADW/xAA
+ 1f8PANT/DwDT/w8A0v8PANH/DwDQ/w8A0P8PAM//DwDP/w8Azv8PAM7/DwDO/w8Azv8PAM7/DwDO/w8A
+ zv8PAM7/DwDO/w8Az/8PAM//DwDQ/w8A0f8PANL/DwDS/w8A0/8QANT/EADW/w8A1/8PBNH/BI87/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wNgPP8LAJ//DwDZ/xEA
+ 8f8RAPP6AQAUMwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAACAAAACQAAABgAAAAvAAAARAAAAEkEAElrDAC9sgEAERMAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgFAFJGAwAwTwAA
+ ADoAAAAzAAAAHwAAAA0AAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAAWAwAsXg8A2f4QANj/EADX/xAA1f8PANT/DwDT/w8A0/8PANL/DwDR/w8A
+ 0P8PAND/DwDQ/w8Az/8PAM//DwDP/w8Az/8PAM//DwDP/w8Az/8PAND/DwDQ/w8A0P8PANH/DwDS/w8A
+ 0/8PANP/EADU/xAA1f8QANb/DwDX/xAA2f8OEMX/Aa4Z/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AL0F/wgYcf8NALv/EQDp/xAA5+oAAAwmAAAABAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA4AAAAgAAAAOgAA
+ AFQBABBmCgCXthEA8PgEAEZFAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABxcMAL3CBwB2mwAAB1QAAABCAAAAKAAAABMAAAAGAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBABRADwDY/BAA
+ 2f8QANj/EADX/xAA1v8QANX/DwDU/w8A0/8PANP/DwDS/w8A0v8PANH/DwDR/w8A0f8PANH/DwDQ/w8A
+ 0P8PANH/DwDR/w8A0f8PANH/DwDS/w8A0v8PANP/DwDU/xAA1f8QANX/EADW/xAA1/8PANj/EADa/xAA
+ 2/8MKav/AMAH/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AoMm/woA
+ lv8PANP/DQDG0QAAABoAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAYAAAASAAAAKQAAAEYAAABiBAA7jg8A1ekSAPT/CgCWjgAAAAgAAAABAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACQMA
+ NEQPAOb2DAC72AIAJncAAABPAAAAMgAAABkAAAAJAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAOAMrnEADa/xAA2f8QANj/EADX/xAA1v8QANX/EADV/w8A
+ 1P8PANP/DwDT/w8A0v8PANL/DwDS/w8A0v8PANL/DwDS/w8A0v8PANL/DwDS/w8A0/8PANP/DwDT/w8A
+ 1P8QANX/EADW/xAA1v8QANf/EADY/w8A2f8QANr/EADc/w8A3P8JT4L/AMYB/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxgD/BjJd/wwAsf8KAJizAAAAFQAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAHAAAAFgAAADAAAABQAAAFbwgA
+ d7YRAO77EgD0/w4A0s8BAA8UAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAEAgAhY8QAOz/DwDe9AUAVJwAAABaAAAAOgAA
+ AB4AAAAMAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAJwsA
+ osYQANz/EADb/xAA2f8QANn/EADX/xAA1/8QANb/EADV/xAA1f8PANT/DwDU/w8A0/8PANP/DwDT/w8A
+ 0/8PANP/DwDT/w8A0/8PANP/DwDU/w8A1P8QANX/EADV/xAA1v8QANf/EADX/xAA2P8QANn/DwDa/xAA
+ 2/8QANz/EADe/w8B3P8FeVX/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8BohX/CgWL/wYAYZoAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACAAAACAAAABkAAAA1AAAAVwEAF4AMALLaEQDz/xIA9P8RAO30AwA7OwAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAGAAAMHw0Ax9AQAOz/EADq/gkAj8MAAApnAAAAQQAAACIAAAANAAAAAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAeCAB6nxAA3f8QANz/EADb/xAA2v8QANn/EADY/xAA
+ 1/8QANf/EADW/xAA1f8QANX/EADV/xAA1P8QANT/EADU/xAA1P8QANT/EADU/xAA1f8QANX/EADV/xAA
+ 1v8QANb/EADX/xAA2P8QANj/EADZ/xAA2v8PANv/EADc/xAA3f8QAN//EADg/w8I1P8Cni3/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDHAP8EVEb/AwAsjAAAAB8AAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAkAAAAbAAAAOAAAAFwDADSSDwDX7hIA
+ 9P8SAPT/EQDz/ggAgnsAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAKAwA3Rg8A5/cQAOz/EADs/w0A
+ v+ECAB93AAAARgAAACQAAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
+ ABUFAEpwEADe/xAA3f8QANz/EADb/xAA2v8QANr/EADZ/xAA2P8QANf/EADX/xAA1v8QANb/EADW/xAA
+ 1v8QANX/EADV/xAA1f8QANb/EADW/xAA1v8QANb/EADX/xAA1/8QANj/EADZ/xAA2f8QANr/EADb/w8A
+ 3P8QAN3/EADe/xAA3/8QAOH/EADi/w4awf8BuBD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wC3CP4AFAaTAAAAOgAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAAJAAAAHAAAADoAAABeBQBInRAA5/gSAPT/EgD0/xIA8/8NAL65AAAIDQAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAIAAAAPCAB+hRAA7P8QAOz/EADs/w4A1vADAC+CAAAASAAAACYAAAAPAAAABAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAFD0PAN36EADf/xAA3v8QAN3/EADc/xAA
+ 2/8QANr/EADZ/xAA2f8QANj/EADY/xAA2P8QANf/EADX/xAA1/8QANf/EADX/xAA1/8QANf/EADX/xAA
+ 2P8QANj/EADZ/xAA2f8QANr/EADb/xAA2/8QANz/DwDd/xAA3v8QAN//EADg/xAA4f8RAOP/EQDk/ws4
+ oP8AxAP/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wB8ANAAAABeAAAAIAAA
+ AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACAAAABwAAAA7AAAAYAYAV6YRAO78EgD0/xIA
+ 9P8SAPT/EADg4AIAHx8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAYXDAC8whAA
+ 7P8QAOz/EADs/w8A3PQDADqJAAAASAAAACUAAAAOAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAHAAABJg0Au9UQAOD/EADf/xAA3v8QAN3/EADc/xAA2/8QANv/EADa/xAA2v8QANn/EADZ/xAA
+ 2f8QANj/EADY/xAA2P8QANj/EADY/xAA2P8QANn/EADZ/xAA2f8QANr/EADa/xAA2/8QANz/EADc/xAA
+ 3f8PAN7/EADf/xAA4P8QAOH/EADi/xEA4/8RAOX/EADl/whhc/8AxwD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMQA/AAuAJUAAABCAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAcAAAAaAAAAOQAAAF8GAF+qEQDu/BIA9P8SAPT/EgD0/xEA7PIEAEM9AAAABAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAYBAB8tDwDa5BAA7P8QAOz/EADs/w8A4PYEAD+MAAAARwAA
+ ACQAAAAMAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAaCAB9mxAA4f8QAOD/EADf/xAA
+ 3v8QAN3/EADd/xAA3P8QANv/EADb/xAA2v8QANr/EADa/xAA2v8QANn/EADZ/xAA2f8QANn/EADa/xAA
+ 2v8QANr/EADa/xAA2/8QANv/EADc/xAA3f8QAN3/EADe/w8A3/8QAOD/EADh/xAA4v8RAOP/EQDk/xEA
+ 5f8RAOf/EAPi/wWKRf8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AJwA4gAD
+ AGgAAAAoAAAABQAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAFwAAADYAAABdBgBbpxEA7/wSAPT/EgD0/xIA
+ 9P8RAPL6BgBmWgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAoEAENODwDn9hAA7P8QAOz/EADs/w8A4PYEAD2JAAAARAAAACEAAAAKAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAA8DADRWEADi/hAA4v8QAOH/EADg/xAA3/8QAN7/EADd/xAA3f8QANz/EADc/xAA
+ 2/8QANv/EADb/xAA2/8QANv/EADb/xAA2/8QANv/EADb/xAA2/8QANz/EADc/xAA3P8QAN3/EADe/xAA
+ 3v8QAN//DwDg/xAA4f8QAOL/EQDj/xEA5P8RAOX/EQDm/xEA5/8RAOn/Dw/U/wKqIP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AxwD/AEsArAAAAEwAAAAVAAAAAQAAAAAAAAABAAAABQAA
+ ABQAAAAyAAAAWQUAU6ERAO77EgD0/xIA9P8SAPT/EQDz/AgAfHIAAAEGAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAwHAGpwEADr/BAA7P8QAOz/EADs/w8A
+ 3fQDADGAAAAAQAAAAB0AAAAJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAABicOAMfcEQDj/xAA
+ 4v8QAOH/EADg/xAA4P8QAN//EADe/xAA3v8QAN3/EADd/xAA3P8QANz/EADc/xAA3P8QANz/EADc/xAA
+ 3P8QANz/EADc/xAA3f8QAN3/EADe/xAA3v8QAN//EADf/xAA4P8PAOH/EADi/xEA4/8RAOT/EQDl/xEA
+ 5v8RAOf/EQDo/xEA6v8RAOv/DSi5/wC+Cv8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AtADyAAwAfgAAADwAAAAUAAAADQAAAA8AAAAaAAAAMgAAAFUDADyTEQDt+hIA9P8SAPT/EgD0/xEA
+ 8/4JAJKIAAAACAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAwAAAA4IAIiLEADr/hAA7P8QAOz/EADs/w4A2PACACV0AAAAOgAAABoAAAAIAAAAAgAA
+ AAEAAAABAAAAAgAAAAIAAAAFAAAAGggAeZYRAOT/EQDj/xAA4/8QAOL/EADh/xAA4P8QAOD/EADf/xAA
+ 3/8QAN7/EADe/xAA3v8QAN7/EADd/xAA3f8QAN3/EADe/xAA3v8QAN7/EADe/xAA3v8QAN//EADf/xAA
+ 4P8QAOH/EADh/xAA4v8RAOP/EQDk/xEA5f8RAOb/EQDn/xEA6P8RAOn/EQDr/xEA7P8RAO3/CkyP/wDG
+ Af8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AbADPAAAAeQAAAEkAAAA0AAAANQAA
+ AEIAAABaAgAoiBAA4PQSAPT/EgD0/xIA9P8RAPT/CwConAAABQkAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABBIKAKClEADs/xAA
+ 7P8QAOz/EADs/w0AyOYBABNnAAAAPAAAACQAAAAaAAAAGAAAABgAAAAaAAAAGwAAAB4AAAAqAgAkXRAA
+ 4PoRAOX/EQDk/xEA4/8QAOL/EADi/xAA4f8QAOD/EADg/xAA4P8QAN//EADf/xAA3/8QAN//EADf/xAA
+ 3/8QAN//EADf/xAA3/8QAN//EADg/xAA4P8QAOH/EADh/xAA4v8QAOL/EADj/xEA5P8RAOX/EQDm/xEA
+ 5/8RAOj/EQDp/xEA6v8RAOz/EQDt/xEA7v8QAO3/BnZf/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wC/APwAHwC2AAAAhgAAAGgAAABkAAAAbQEAGYgPANLsEgD0/xIA9P8SAPT/EgD0/wwA
+ tLAAAAgOAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAACxgMALe9EADs/xAA7P8QAOz/EADs/wsAr9YAAAdoAAAATwAA
+ AEQAAABCAAAAQgAAAEMAAABGAAAASAAAAE8AAABhCwCh0hEA5v8RAOX/EQDk/xEA5P8RAOP/EADi/xAA
+ 4v8QAOH/EADh/xAA4f8QAOD/EADg/xAA4P8QAOD/EADg/xAA4P8QAOD/EADg/xAA4P8QAOH/EADh/xAA
+ 4v8QAOL/EQDj/xEA4/8QAOT/EQDl/xEA5v8RAOf/EQDo/xEA6f8RAOr/EQDr/xEA7P8RAO3/EQDv/xEA
+ 8P8QB+b/A5s0/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCKCvEEAUTUBgBdwggA
+ dr0JAIvIDwDR7RIA9P8SAPT/EgD0/xIA9P8OAM7IAQAWFwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgEA
+ FiQNAMjTEADs/xAA7P8QAOz/EADs/wkAj8gAAAZ7AAAAcAAAAG8AAABvAAAAcAAAAHIAAAB1AAAKfAEA
+ G4sFAFm6EADn/xEA5v8RAOb/EQDl/xEA5P8RAOT/EQDj/xEA4/8QAOL/EADi/xAA4f8QAOH/EADh/xAA
+ 4f8QAOH/EADh/xAA4f8QAOH/EADi/xAA4v8QAOL/EQDj/xEA4/8RAOT/EQDk/xAA5f8RAOb/EQDn/xEA
+ 6P8RAOn/EQDq/xEA6/8RAOz/EQDt/xEA7v8RAO//EQDx/xIA8v8PGNL/AbUV/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMYA/wY5Wf8MAK7/EADi/xIA8v8SAPT/EgD0/xIA9P8SAPT/EADk5AIA
+ JCYAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACAIAKzcPAN/rEADs/xAA7P8QAOz/EADs/w8A
+ 4PcNAMnqDQC/5g0AxOgNAMzrDwDX8Q8A5foQAOv+EADn/g8A1P8PAN3/EQDo/xEA5/8RAOb/EQDm/xEA
+ 5f8RAOX/EQDk/xEA5P8RAOP/EQDj/xEA4/8QAOL/EADi/xAA4v8QAOL/EADi/xEA4/8RAOP/EQDj/xEA
+ 4/8RAOT/EQDk/xEA5f8RAOb/EADm/xEA5/8RAOj/EQDp/xEA6v8RAOv/EQDs/xEA7f8RAO7/EQDv/xEA
+ 8P8SAPH/EgDz/xIA9P8MNq3/AMMF/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AacR/wkG
+ hv8OAMf/EQDt/xIA8/8SAPT/EgD0/xAA6/EEAEI+AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACAAAACgUAU1gPAOj4EADs/xAA7P8QAOz/EADs/xAA7P8QAOz/EADs/xAA7P8RAO3/EQDt/xEA
+ 7f8RAOv/DwDi/w4A0f8QAOn/EQDp/xEA6P8RAOf/EQDn/xEA5v8RAOX/EQDl/xEA5f8RAOT/EQDk/xEA
+ 5P8RAOT/EQDk/xEA5P8RAOT/EQDk/xEA5P8RAOT/EQDl/xEA5f8RAOb/EQDm/xEA5/8QAOf/EQDo/xEA
+ 6f8RAOr/EQDr/xEA7P8RAO3/EQDu/xEA7/8RAPD/EgDx/xIA8v8SAPT/EgD1/xEA8PkIYHD9AMcA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/BFxA/wsAo/8PANv/EQDx/xIA9P8QAOrqBABUSQAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAcAc3UQAOv9EADs/xAA
+ 7P8QAOz/EADs/xAA7P8QAOz/EADs/xEA7f8RAO3/EQDt/xEA7P8QAOj/DwDZ/w8A3f8RAOr/EQDp/xEA
+ 6f8RAOj/EQDn/xEA5/8RAOb/EQDm/xEA5v8RAOX/EQDl/xEA5f8RAOX/EQDl/xEA5f8RAOX/EQDl/xEA
+ 5v8RAOb/EQDm/xEA5/8RAOf/EQDo/xAA6P8RAOn/EQDq/xEA6/8RAOz/EQDt/xEA7v8RAO//EQDw/xIA
+ 8f8SAPL/EgDz/xIA9P8SAPb/CAB+fAMDNjgAnAW7AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AvQX/BxVu9gsApOUNAMLECQCLgAIAJh4AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAACAAACCgcAb2oPAOPtEADs/xAA7P8QAOz/EADs/xAA7P8QAOz/EQDt/xEA
+ 7f8RAO3/EQDt/xEA6/8QAOX/DgDS9xAA6PsRAOv/EQDq/xEA6f8RAOn/EQDo/xEA6P8RAOf/EQDn/xEA
+ 5/8RAOf/EQDm/xEA5v8RAOb/EQDm/xEA5v8RAOf/EQDn/xEA5/8RAOj/EQDo/xEA6P8RAOn/EADq/xEA
+ 6/8RAOv/EQDs/xEA7f8RAO7/EQDv/xEA8P8RAPH/EgDy/xIA8/8SAPT/EgD1/w8A1tIAAAwUAAAAAgAZ
+ ABYAuwDdAMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AhALWAAABYQAAACMAAAAEAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAEA
+ GxUGAF5VCACDggsAp5ULAKmYCgClkgkAlY0IAHl/BwB3bgcAcl0FAFNMBABAOAMAOCMAAAwaBwBzfhAA
+ 7P8RAOv/EQDr/xEA6v8RAOr/EQDp/xEA6f8RAOj/EQDo/xEA6P8RAOj/EQDo/xEA6P8RAOj/EQDo/xEA
+ 6P8RAOj/EQDo/xEA6f8RAOn/EQDq/xEA6v8QAOv/EQDs/xEA7P8RAO3/EQDu/xEA7/8RAPD/EQDw/xIA
+ 8v8SAPP/EgD0/xIA9f8RAPT6BABJRAAAAAQAAAAAAAAAAAA9ADYAxgD0AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDFAP4ANACaAAAARAAAABAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAUWDAC2vBEA7f8RAOz/EQDr/xAA6v8QAOn/EADo/xAA
+ 6P8RAOn/EQDp/xEA6f8RAOn/EQDp/xEA6f8RAOn/EQDp/xEA6v8RAOr/EQDq/xEA6/8RAOv/EQDs/xAA
+ 7P8RAO3/EQDs/xAA6v8PAOb/EADk/xAA5f8QAOr/EQDv/xIA8/8SAPX/EQD2/wkAj4QAAAAHAAAAAQAA
+ AAAAAAAAAAAAAABiAGIAxwD9AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCjAOcABgBtAAAAKwAA
+ AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAYBAB4sDgDZ4RAA7P8PAOX/DwDd/w4A1f8OANL/DwDX/w8A3/8QAOb/EQDp/xEA6/8RAOv/EQDr/xEA
+ 6/8RAOv/EQDr/xEA6/8RAOz/EQDs/xEA7P8RAO3/EADt/xAA6/8PAOX/DwDY/w4Ay/8OAML/DgDE/w8A
+ 0P8QAOD/EQDt/xIA9P8NAMK6AAAKDgAAAAEAAAAAAAAAAAAAAAAAAAAAAAQAAwCJAJgAxwD/AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMcA/wBWALMAAABQAAAAFgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgDADpGDwDc8g4A0/8NAL//DACw/wsA
+ rP8MALX/DgDH/w8A2f8QAOb/EQDr/xEA7P8RAOz/EQDs/xEA7P8RAOz/EQDs/xEA7f8RAO3/EQDt/xEA
+ 7v8QAO3/DwDl/w4A0/8NALr/CwCj/woAmP8KAJr/DACq/w4AxP8PAN7/DgDT2AIAISAAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAABUADACtAMYAyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/ALgA9AAT
+ AH4AAAA1AAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAgAAABIFAEhsDACy+AoAmf8JAIj/CQCK/wkAjv8LAKX/DQDC/w8A3P8QAOr/EQDt/xEA
+ 7f8RAO3/EQDt/xEA7f8RAO7/EQDu/xEA7v8RAO//EQDv/xAA6/8PANn/DQC7/wsAmP8JAI3/CwCh/wwA
+ rf8LAKb/CwCl/wwAtOYCACs9AAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYAIgDA
+ AOkAyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AHcAygAAAFoAAAAeAAAAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAFQAAAD0DADKXCgCS/QwA
+ sP8NAML/DgDK/wwAtP8LAKr/DgDN/w8A5v8RAO7/EQDu/xEA7v8RAO//EQDv/xEA7/8RAO//EQDv/xEA
+ 8P8RAPD/EADn/w4Ay/8LAKP/CgCY/wwArf8NALr/DgDI/w8A1f8OAMz8AgArcAAAACIAAAAGAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE4ASADHAPsAyAD/AMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AxAD8ACcAkAAAAD8AAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAQAAAAfAAAASwcAasMMAKv/DQC0/w4AwP8OAM7/EADb/w0Ayf8NAL//EADh/xEA
+ 8P8RAPD/EQDw/xEA8P8RAPD/EQDw/xEA8f8RAPH/EgDx/xIA8f8QAOT/DQDB/wsApf8MAK//DQCx/w0A
+ uv8OAMb/DwDT/xAA4P8JAI+wAAAAKgAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAQABAHcAewDHAP4AyAD/AMgA/wDIAP8AyAD/AMgA/wDIAP8AlwDgAAEAZgAAACcAAAAFAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAACYCAClvDQC3/g0A
+ tP8NALj/DgDC/w4Azf8QANr/EADl/w4Axf8QAN7/EgDx/xIA8f8SAPH/EgDx/xIA8f8SAPL/EgDy/xIA
+ 8v8SAPL/EgDy/xAA5P8NAL//DQC5/w0Au/8NALr/DgC//w4AyP8PANP/EADf/w8A3/AAABA0AAAACQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAGAJwArgDIAP8AyAD/AMgA/wDI
+ AP8AyAD/AMgA/wDHAP8ARQCnAAAASgAAABMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAGAAAAJAYAYJkOAMP/DgC//w4AwP8OAMf/DwDQ/xAA2/8QAOf/DwDX/xAA
+ 4f8SAPL/EgDy/xIA8v8SAPL/EgDz/xIA8/8SAPP/EgDz/xIA8/8SAPT/EADo/w4Axv8OAMr/DgDG/w4A
+ xP8OAMf/DwDN/w8A1/8QAOH/EADs/AIAHToAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAGwAVALQA2ADIAP8AyAD/AMgA/wDIAP8AyAD/AMgA/wCuAO4ACwB0AAAAMAAA
+ AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAbBwBwnA4A
+ zv8OAMr/DgDK/w8Azv8PANb/EADf/xAA6f8QAOD+EADn/xIA8/8SAPT/EgD0/xIA9P8SAPT/EgD0/xIA
+ 9P8SAPT/EgD1/xIA9f8RAO7/DwDW/w8A1P8PANL/DwDQ/w8A0P8PANX/DwDc/xAA5f8QAO33AQAbKgAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQAyAMQA8wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/AMcA/wBmAL4AAABVAAAAGgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAABAGAFdvDwDa/w8A1v8PANX/DwDX/w8A3P8QAOT/EQDt/wgA
+ dHUHAHBzDQDDxBEA7vQRAPT+EgD1/xIA9f8SAPX/EgD1/xIA9f8RAPX+EQDt8QwAubYGAF5oCQCQoBAA
+ 3v8QANv/EADb/xAA3v8QAOP/EQDr/w0AxcMAAAMMAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAZgBiAMcA/gDIAP8AyAD/AMgA/wDIAP8AyAD/AL8A+QAd
+ AIcAAAA7AAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAA
+ ESAOANLhEADh/xAA4P8QAOH/EADl/xEA6/8PAN/fAQAUGwAAABYAAAAoAQEdPAQLkpYHAGdlBwBscAcA
+ bHMHAGxwBgBhZwMNnKYAABE5AAAAIwAAABABABslDgDV3hAA5v8QAOb/EADn/xEA7P8QAOzxBABEPAAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAkACcAMgA/wDIAP8AyAD/AMgA/wDIAP8AyAD/AIgA1gABAGEAAAAiAAAABAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwQAREAPAN7kEQDr/xEA6/8RAO7/DwDm5gQA
+ Sj4AAAAOAAAAJAAAADcADm2PAAtYawAAAAkAAAAAAAAAAAAAAAQAAAAaABB7mAAMYokAAAA2AAAAGgAA
+ AAoCACIjDACvpBAA6OgRAO/sDQDIvwQAQzcAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAwArwDKAMgA/wDIAP8AyAD/AMgA/wDI
+ AP8AxgD+ADYAnAAAAEUAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAABAEAIBkIAHVqCgCMjwgAf20CACYbAAAABwAAABkAAAA5AAMdWgAczuwABCM3AAAABQAA
+ AAAAAAAAAAAAAQAAABQACERmABzQ8wAEImIAAAAvAAAAEQAAAAQAAAACAgAmCwMALw4AAAcCAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAApACYAwADqAMgA/wDIAP8AyAD/AMgA/wDIAP8ApgDpAAQAbAAAACwAAAAGAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAAOAAAALAAAAE4AFJXBABrB3AAABBoAAAACAAAAAAAAAAAAAAAAAAAADQABDzcAHdn5ABWk0AAA
+ BEwAAAAkAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSAE0AxwD6AMgA/wDI
+ AP8AyAD/AMgA/wDIAP8AVwC0AAAAUAAAABcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAB0AAABEAAg+hgAd2v4AEo6nAAAAEAAA
+ AAEAAAAAAAAAAAAAAAAAAAAHAAAAJQAXsNAAHdv/AAxhnwAAAD4AAAAZAAAABgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQB5AH4AxwD+AMgA/wDIAP8AyAD/AMgA/wC6APYAEgB+AAAANgAA
+ AAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAARAAAAMwAABV4AGLbiAB7b/wALVm0AAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAaAA5xlgAd
+ 2/8AHNH2AAQkbgAAADAAAAAQAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABQCi
+ ALUAyAD/AMgA/wDIAP8AyAD/AMgA/wB5AMsAAABbAAAAHwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACIAAABKAAxdpQAd2v8AHdf4AAQfMgAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABAABjFXAB3b/gAe3P8AFqjVAAADTQAAACQAAAAKAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAFwC7AN4AyAD/AMgA/wDIAP8AyAD/AMMA/AAs
+ AJMAAABAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAMAAAAUAAAAOAACEWsAGsfwAB7b/wAZudQAAAAVAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAA
+ BiwAGsflAB7c/wAd2/8ADGKgAAAAPQAAABgAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEAAPADGAPUAyAD/AMgA/wDIAP8AyAD/AJgA4AADAGgAAAAoAAAABAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACgAAACYAAABQAA94uQAe2/8AHtv/ABB8lAAA
+ AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGwASiKgAHtz/AB7c/wAc0fYABCJrAAAALwAA
+ ABAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG0AbADHAP4AyAD/AMgA/wDI
+ AP8AxwD/AEcAqQAAAEsAAAAUAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAQAAAAWAAAAPAAEInkAHNP5AB7b/wAd2v4ABztLAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAAQAAg+XwAd2/4AHtz/AB7c/wAWptQAAANLAAAAIgAAAAkAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAABgADAJEAoADHAP8AyAD/AMgA/wDIAP8AsgDwAAsAdgAAADEAAAAIAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACwAAACgAAABUABOQygAe2/8AHtv/ABvJ4gAA
+ BBYAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAQgpABrF4gAe3P8AHtz/AB3b/gAM
+ WpgAAAA6AAAAFgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgAOALAAzQDI
+ AP8AyAD/AMgA/wDIAP8AawDCAAAAVgAAABsAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAQAAAAYAAAAPgAFLIEAHdj8AB7b/wAe2/8AEYSXAAAACwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAwAAABYAD3eVAB7c/wAe3P8AHtz/ABvL8QADGWMAAAAsAAAADgAAAAIAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALQAoAMIA7gDIAP8AyAD/AMgA/wDBAPoAHgCIAAAAPAAA
+ AAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAADAAAACsAAABWABSc0gAe2/8AHtv/AB3a/gAG
+ MUAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACgAEI0AAHdb4AB7c/wAe
+ 3P8AHtz/ABOWyAAAAUcAAAAgAAAACAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAVwBSAMcA/ADIAP8AyAD/AMgA/wCLANcAAABhAAAAIwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAUAAAAbAAAAQgAHOowAHdr+AB7b/wAe2/8AGLfMAAACEQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAUl7IAHtz/AB7c/wAe3P8AHdv+AAlJjAAAADgAAAAWAAAABAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAIAfgCIAMcA/wDIAP8AyAD/AMYA/gA6
+ AJ4AAABGAAAAEQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADwAAADAAAAJbABet3gAe2/8AHtv/AB7b/wAL
+ WWoAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAMAAY0TAAd
+ 2v0AHtz/AB7c/wAe3P8AGsXsAAIRXgAAACwAAAAOAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAARAAgAowC6AMgA/wDIAP8AyAD/AKcA6gAHAG8AAAAtAAAABgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAgAAAAgAAAASAAKTJoAHdr+AB7b/wAe2/8AG8nkAAENGgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAWABSbtAAe3P8AHtz/AB7c/wAe3P8AE5HFAAAASgAA
+ ACIAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkABwAuQDgAMgA/wDI
+ AP8AyAD/AFsAtgAAAFIAAAAYAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAADcAAQpmABm76QAe2/8AHtv/AB7b/wAO
+ b4AAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAkABSc+AB3X9gAe3P8AHtz/AB7c/wAd2v4ACUqRAAAAPwAAABwAAAAHAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAD8AxQD3AMgA/wDIAP8AugD2ABYAgAAAADcAAAAKAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA
+ AAwAAAAoAAAAUgAObbQAHdr/AB7b/wAe2/8AHM7oAAIVIAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABIAEIKZAB7c/wAe3P8AHtz/AB7c/wAb
+ y/IAAx5wAAAANgAAABYAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBx
+ AHAAyAD/AMgA/wDIAP8AfQDOAAAAXQAAACAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAHQAAAEMABCF+ABzQ+AAe2/8AHtv/AB3a/wAO
+ bn4AAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAABgACEycAGsjiAB7c/wAe3P8AHtz/AB7c/wAXsN4AAQteAAAAMAAAABMAAAAFAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgCZAKYAyAD/AMgA/wDGAP4ALgCWAAAAQgAA
+ AA8AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA
+ ABUAAAA2AAACYQAVodcAHtv/AB7b/wAe2/8AG8vlAAIPGwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADAAJTF8AHdr8AB7c/wAe
+ 3P8AHtz/AB7c/wATjsYAAAJUAAAALQAAABIAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAABwAEAC0ANIAyAD/AMgA/wCeAOQAAwBpAAAAKQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAALgAAAFUADFuqAB7a/wAe2/8AHtv/AB7b/wAN
+ Y24AAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAACEgASj6EAHtv/AB7c/wAe3P8AHtz/AB3b/wAOa68AAABQAAAALAAA
+ ABIAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIALgDDAO8AyAD/AMcA/wBP
+ AK4AAABNAAAAFQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAA
+ ACgAAABNAAUnhgAc0fgAHtv/AB7b/wAe2/8AGbvOAAAEEAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAIPIAAZ
+ vNQAHtz/AB7c/wAe3P8AHtz/AB3Z/QALWqIAAABQAAAALAAAABMAAAAFAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAF0AWgDHAPwAyAD/ALMA8gAOAHgAAAAyAAAACAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA
+ AAQAAAAEAAAAAgAAAAEAAAACAAAABAAAABAAAAAnAAAASQABDXQAGLXmAB7b/wAe2/8AHtv/AB3a+gAH
+ PUQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAUtPAAd1/MAHtz/AB7c/wAe3P8AHtz/AB3Y/AAL
+ WaIAAABSAAAAMQAAABYAAAAIAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgACAIUAkADH
+ AP8AyAD/AG0AwwAAAFgAAAAcAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAgAAAATAAAAHAAAACAAAAAbAAAAFgAAABYAAAAeAAAAMAAA
+ AE4AAAdxABWb1wAd2v8AHtv/AB7b/wAd2v8AEoyWAAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAAKAApSYAAd2foAHtz/AB7c/wAe3P8AHtz/AB3Z/AAMW6YAAABZAAAAOQAAAB4AAAAOAAAABAAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAIAKwAxADIAP8AwQD6ACIAigAAADwAAAAMAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFgAA
+ AC4AAABDAAAASwAAAEYAAABAAAAAQAAAAEgAAABbAAEHdwATkNAAHtv/AB7b/wAe2/8AHtv/ABnA1AAC
+ EhgAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAANAA5wegAd2/0AHtz/AB7c/wAe
+ 3P8AHtz/AB3a/gAPdLkAAARkAAAARgAAAC0AAAAbAAAADwAAAAoAAAAIAAAACQAAAAwAAAAMAAAACQAA
+ AAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAJgAgAMAA5wDIAP8AjQDWAAEAYgAAACQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAmAAABSwAGMYQABi+OAAEIdgAAAG0AAABsAAAAdAAF
+ JpIAFqfgAB7b/wAe2/8AHtv/AB7b/wAc1fMABzo+AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAMAAAIPABGBjwAd2/4AHtz/AB7c/wAe3P8AHtz/AB3b/wAUnNUAAhZ6AAAAWAAA
+ AEQAAAA1AAAALQAAACoAAAAsAAAAMAAAADAAAAAlAAAAFgAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASgBHAMcA+QDHAP4APACcAAAARgAA
+ ABEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAA
+ ADEACk6OABzX/AAd2v4AG8jzABWg3QASjdMAFqjiABzV/AAe2/8AHtv/AB7b/wAe2/8AHdr+AA1naQAA
+ AAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAIQABGKmAAd
+ 2/8AHtz/AB7c/wAe3P8AHtz/AB7c/wAayPIADFutAAAGcgAAAGIAAABaAAAAWAAAAFoAAABeAAAAXAAA
+ AEsAAAAwAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAACAAEAdwB6AMcA/wCqAOkABgBqAAAALQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAALgAWp9AAHdr/AB7b/wAe2/8AHtv/AB7b/wAe
+ 2/8AHtv/AB7b/wAe2/8AHtv/AB7a/wASjpUAAAEIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAMOABGEjwAd2/4AHtz/AB7c/wAe3P8AHtz/AB7c/wAd
+ 2/8AGb/tAA93wgAJRaQABjOaAAhAogAMW7IAEH3EAA94tAACFFUAAAAiAAAABgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAYAmgCwAMcA/wBd
+ AK8AAABPAAAAGAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAgAAAAgABez2AAd2v8AHtv/AB7b/wAe2/8AHtv/AB7b/wAe2/8AHtv/AB7b/wAd2v4AFJqfAAAICgAA
+ AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAEMAA5ydgAd2PgAHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe
+ 3P8AHtz/ABarzQAAAyoAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiABQAtwDZAL0A9QAZAHMAAAA2AAAACgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABAAE5ekAB3a/wAe2/8AHtv/AB7b/wAe
+ 2/8AHtv/AB7b/wAe2/8AHdr7ABGEiAAABQkAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAlJTQAbzOQAHtz/AB7c/wAe
+ 3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHdv8AAQiNgAAAAcAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3
+ ADQAxQD0AIIAwgAAAFIAAAAgAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAABAADHyAAE5OaABzT6wAd2v8AHtv/AB7b/wAe2/8AHdr/ABnBzgAJTUsAAAIEAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAAFAAQhJgAWpLAAHtv+AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe
+ 3P8AHtz/AB7c/wAd2/sABCQqAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAGMAxAD6ADIAewAAADsAAAAOAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAhQRAAlIQgAP
+ dHMAD3eCAA90cwAIRjsAAAYIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAADCQAK
+ UlAAGbrFAB3b/gAe3P8AHtz/AB7c/wAe3P8AHtz/AB7c/wAe3P8AHtz/ABaprgAABAoAAAABAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAUAAwCQAJsAoADUAAQASwAAACQAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgcABzo0ABB+gwAXr7oAHNPdABzU6AAc
+ 0tsAGLbAABKJjAALVU0AAQkJAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcADACrAMoAUwCEAAAANwAA
+ ABIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAADAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAC4AJwCwANMADwBAAAAAIwAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFUAUQB1
+ AJMAAAAoAAAAEgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAHwAfQAmADsAAAAYAAAABgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAEAAHAHYAbAACABMAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJQAYAD8AKQAAAAYAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAALQAMAAQAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/////8AH//////////////////+AAf/////////////////+AA
+ D//////////////////AAAf/////////////////gAAD/////////////////wAAA///////////////
+ //4AAAH////////////////4AAAB////////////////8AAAAP///////////////+AAAAAA///////g
+ ///////AAAAAAA//////wP///4H/gAAAAAAD/////wD///+A/gAAAAAAAP////4A////gHwAAAAAAAB/
+ ///8AP///4A4AAAAAAAAH///+AH////AAAAAAAAAAA////AD////wAAAAAAAAAAH///AA////+AAAAAA
+ AAAAA///gAf////wAAAAAAAAAAP//4AH////8AAAAAAAAAAB//8AD/////gAAAAAAAAAAP/+AB/////4
+ AAAAAAAAAAB//AAf////8AAAAAAAAAAAf/gAP////+AAAAAAAAAAAD/wAH////+AAAAAAAAAAAAAAAD/
+ ////AAAAAAAAAAAAAAAB/////gAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAP////8AAAAAAAAAAAA
+ AAAH////+AAAAAAAAAAAAAAAD/+H//gAAAAAAAAAAAAAAB/+B//4AAAAAAAAAAAAAAA//Af/+AAAAAAA
+ AAAAAAAA//gH//wAAAAAAAAAAAAD///gB//8AAAAAAAAAAAAA///wA///AAAAEAAAAAAAAP//4AP//4A
+ AADAAAAAAAAD//8AH///AAADwAAAAAAAAf/+AD///wAPH8AAAAAAAAH//AA///+AB/+AAAAAAAAB//gA
+ f///wAf/gAAAAAAAAf/wAH///8AD/4AAAAAAAAH/4AD////gAf+AAAAAAAAB/8AB////8AD/gAAAAAAA
+ Af/AA/////AAf4AAAAAAAAAAAAP////4ADgAAAAAAAAAAAAH/////AAAAAAAAAAAAAAAD/////4AAAAA
+ AAAAAAAAAB/////+AAAAAAAAAAAAAAA//////wAAAAAAAAAAAAAAf/////+AAAAAAAAAAAAAAH//////
+ wAAAAAAAAAAAAADw/////+AAAAAAAAAAAAADwP///+DwAAAAAAAAAAH//4D////gPgGAAAAAAAAB//4A
+ ////4B//gAAAAAAAAf/8AP///+AH/4AAAAAAAAH/+AH////wA//AAAAAAAAB/+AB////8AH/wAAAAAAA
+ Af/AA/////gA/8AAAAAAAAP/gAf////8AH/AAAAAAAAB/wAH/////AA/wAAAAAAAAf4AD/////4AH+AA
+ AAAAAAD8AB//////AA/gAAAAAAAA+AA//////wAH4AAAAAAAAHAAP/////+AA+AAAAAAAAAgAH//////
+ wAHwAAAAAAAAAAD//////+AAAAAAAAAAAAAB///////wAAAAAAAAAAAAA///////+AAAAAAAAAAAAAf/
+ //////gAAAAAAAAAAAAP///////8AAAAAAAAAAAAH////////gAAAAAAAAAAAD////////8AAAAAAAAA
+ AAB/////////gAAAAAAAAAAB/////////8AAAAAAAADAAP///////////4AAAAAA4AD///////////+A
+ AAAAAeAAf///////////wAAAAAPwAH///////////+AAAAAH+AA////////////gAAAAB/wAP///////
+ ////4AAAAAf8AB///////////+AAAAAH/gAP///////////gAAAAB/8AD///////////4AAAAAf/gAf/
+ /////////+AAAAAH/4AH///////////wAAAAD//AA///////////8AAYAB//4AH///////////gAGAA/
+ //AB////////////4BwD///4AP///////////+AcA///+AD////////////APAH///wAf///////////
+ wDwA///+AH///////////4A+AP///wA///////////8AfgB///+AH///////////AH4AP///gB//////
+ /////gB/AD///8AP//////////4AfwAf///gD//////////8AP8AD///8Af//////////AD/gA////AD
+ //////////gB/4AH///4A//////////wAf/AA////AH/////////8AP/wAH///4B/////////+AD/+AA
+ ///+AP/////////AA//wAP///wB/////////wAf/8AB///+Af////////4AP//gAH///wD////////8A
+ D//8AA///+A///////8AAB///AAH///gH//////+AAAf//4AAf//8B///////gAAP///AAAB//gP////
+ //4AAH///4AAAP/8B//////+AAB////AAAD//Af//////gAA////4AAA//4D//////4AAf////AAAP//
+ A//////+AAP////4AAD//4H//////gAH/////AAA///B//////+AH/////8AAP//wP//////////////
+ wAH//+B///////////////gP///wf///////////////////+D////////////////////g/////////
+ ///////////8H////////////////////h////////////////////8f////////////////////////
+ ////////////////////////////////////////KAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACAA0AIAAuAF8ANQBwABEARgAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAUARQBqALUA7ADHAP8AxwD/AMAA+gBhAK4AAQAhAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAEACQBlAJEAxQD8AMcA/wDHAP8AxwD/AMcA/wDHAP8ASQCVAAAACgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAXAIIAswDGAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8AswDxAA0ARgAAAAUAAAAHAAAABQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAIAAAAMAAAABQAAAAAAAAAAAAAAAQAaACkAmgDOAMYA/wDGAP8AxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AG4AyAAACmYBABtsAQATYAAAAT8AAAAbAAAABQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA4AAAcsAQAVGgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAC9QAAALPwAAAAwAAAACACgAQgCuAOUAxgD/AMYA/wDG
+ AP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMMA/gcgbvwOAMP+DgDI/QwAtOsHAGitAAALRwAA
+ AA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAGAIAH2QKAJOrAAATCwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABEdCQCN0gIAH2gAPgBtALwA9ADG
+ AP8AxgD/AMYA/wDGAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wGQHf8MAaj/DgDK/w4A
+ 0P8PANb/DQC/7AMALWwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAfBAA/hg8A
+ 2PAEAENEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBABDbQVX
+ T/kAwwD9AMYA/wDGAP8AxgD/AMYA/wDGAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMcA/wDH
+ AP8FQVb/DgDC/w4Az/8PANT/DwDa/w4A0fUDADJpAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AB0FAEmOEADk+gkAjJQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAABwAQAHYAqADGAP8AxwD/AMYA/wDGAP8AxgD/AMYA/wDGAP8AxwD/AMcA/wC4APUAxwD/AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8ArQ3/CgmW/w4Azf8PANP/DwDZ/xAA3/8OAMvtAQAVQgAAAAIAAAAAAAAAAAAA
+ AAAAAAAAAAAAFQQAPoIQAOT6DQC/ygAAEgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAATABwAkADCAMYA/wDGAP8AxwD/AMYA/wDGAP8AxgD/AMYA/wDGAP8AxwD/AK8A7AQY
+ PbQEeEH/AMcA/wDHAP8AxwD/AMcA/wDHAP8AxwD/BGY5/w0Avv8PANL/DwDY/w8A3v8QAOP/CgCZxAAA
+ AEAAAAAyAAAAKwAAACYAAAApAgAjbA8A3fYPANTiAgAmHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAABgAHwCgANQAxwD/AMYA/wDGAP8AxwD/AMYA/wDGAP8AxgD/AMYA/wDG
+ AP8Aswb5AR8UrQsAme8MB6P/Ap0j/wDHAP8AxwD/AMcA/wDHAP8AxwD/AMED/wgbgP8OAND/DwDX/w8A
+ 3f8QAOL/EADn/goAmeILAKraCwCc0AoAkMcJAIzHDgDM7RAA5fYEAEA7AAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwApADHAP8AxwD/AMYA/wDGAP8AxwD/AMYA/wDG
+ AP8AxgD/AMYA/wC3C/8IJID/CgCT/wwAsf8MAK7/CxiW/wC4DP8AxwD/AMcA/wDHAP8AxwD/AMcA/wKI
+ JP8MALb/DwDW/w8A3P8QAOL/EADn/w4A1PsOANHsEADr+RAA7P8QAOz/EADh7QYAXlsAAAABAAAAAAAA
+ AAAAAAAAAAAAAgAAAAsAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF4AaQDEAfwAxwD/AMYA/wDG
+ AP8AxwD/AMYA/wDGAP8AxgD/ALoA8gQoSKgGAGKhCwCf8g0AtP8MALH/DACw/wk5ff8AxAL/AMcA/wDH
+ AP8AxwD/AMcA/wDGAP8GOWT/DwDR/w8A3P8QAOH/EADn/xAA5PcBABMxAAAKBQMAMgwDAD4PAAARAwAA
+ AAAAAAAAAAAAAAAAAAAAAAAFAAAAJgQAOl8BABUTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgUe
+ TowEWjjPAIIAtQCfAMgAtgDlAMUA+wDGAP8AqQDZADAAQAAAAAEBABFADQC2+g0AuP8NALX/DAC0/wwA
+ tP8GYVz/AMcA/wDHAP8AxwD/AMcA/wDHAP8BphL/DAao/w8A2/8QAOH/EADm/xAA7f8FAFJxAAAAAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAM7CAB2rQkAf4QAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAEADxUNALPbBgBanQAAACAACQAGAFMAEgBOABwAGgAHAAAAAAAAAAMEADpyDQC//w0A
+ u/8NALn/DQC4/w0AuP8NArb/BIo4/wDHAP8AxwD/AMcA/wDHAP8AxwD/BFtI/w4A0P8QAOH/EADm/xAA
+ 7P8KAI+pAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACUYLAKLPDwDP2AEAEg0AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAEBTDgDQ/AcAZ6YAAAAeAAAAAQAAAAAAAAAAAAAAAAAA
+ AAcGAGGcDgDC/w0Av/8NALz/DQC7/w0Au/8NALz/DAyx/wGrGv8AxwD/AMcA/wDHAP8AxwD/AL0F/woU
+ kv8QAOD/EADn/xAA7P8NALvQAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAGAAAHQQwArdURAOr3BAA/OwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCAB4kw4A0f4GAFiWAAAAFQAA
+ AAAAAAAAAAAAAAAAAAsJAH23DgDG/w0Awv8NAMD/DQC//w0Avv8NAL//DQDB/wsmnP8Avgn/AMcA/wDH
+ AP8AxwD/AMcA/wOALf8OAMj/EADn/xAA7f8PANjoAAAFGAAAAAUAAAADAAAAAgAAAAUAAAIzCwCcyREA
+ 8P4HAGtsAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICwsA
+ oMIOAM77AwA4dwAAACAAAAAdAAAAIQAAADMKAJHQDgDJ/w4Axv8OAMT/DQDC/w0Awv8NAML/DgDD/w4A
+ xv8JSXz/AMYB/wDHAP8AxwD/AMcA/wDFAf8IL3b/EADj/xAA7f8QAOX2AgAfcgEAD10AAAJQAAAASgAA
+ AFAIAHWxEQDw/woAkZYAAAcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAEAGB4NALzjDQDB9AcAarkHAGi2CAB0vwgAfM0MALP2DgDN/w4Ayv8OAMf/DgDG/w4A
+ xf8OAMX/DgDH/w4AyP8OAMr/BnJW/wDHAP8AxwD/AMcA/wDHAP8Bnxj/DQO8/xEA7f8RAPD/EADg/xEA
+ 8P8RAO39EADi9xAA4fcRAPD/DQC8xAAACggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDADdADQDD6A8A0v8OANL/DgDS/Q4AxfgNAMH7DgDQ/w4A
+ zf8OAMv/DgDJ/w4Ayf8OAMn/DgDK/w4Ay/8OAM7/DgXK/wObLv8AxwD/AMcA/wDHAP8AxwD/BVBY/xAA
+ 4/8RAOr4CAB7hQwAqZYNALqnDQC1tQ0AurYLAKOQAgAoFQAAAAAAAAAFAAAABAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAAAUAAAAAAgApDAcAaicHAGwnBQBPGwIA
+ HhYKAI66DwDU/w4A0f8OAM//DgDN/w4Azf8OAMz/DgDN/w4Azv8OAND/DwDT/w0Xu/8BtRP/AMcA/wDH
+ AP8AxwD/ALcJ/wsOqf8QAN7rAAAODwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAABgBABM+AQAeIAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIEBQBZbwEAEkgAAAAPAAAAAQAA
+ AAAAAAAAAAAAAAAAAAQIAHSbDwDX/w8A1f8PANP/DwDR/w4A0P8OAND/DgDQ/w8A0f8PANP/DwDV/w8A
+ 2P8LM6H/AMMF/wDHAP8AxwD/AMcA/wR1Of8MALHUAAABBwAAAAAAAAAAAAAAAAAAAAAAAAAFAAAALAUA
+ SYsLAKCrAAAKBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAhKg0A
+ wt0DADh2AAAAGAAAAAEAAAAAAAAAAAAAAAEFAFFwDwDb/w8A2P8PANb/DwDV/w8A1P8PANP/DwDU/w8A
+ 1P8PANb/DwDY/w8A2/8PAN3/CFt3/wDHAP8AxwD/AMcA/wDDAv8EJ0S8AAAABgAAAAAAAAAAAAAAAAAA
+ AAcAAAQ8CQCCuRAA4usCACwkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQYAYGwPAOX6BQBYkgAAABsAAAABAAAAAAAAAAACACM4DwDd/Q8A3P8PANr/DwDY/w8A
+ 1/8PANf/DwDX/w8A2P8PANn/DwDb/w8A3f8QAOD/EAHh/wWGSf8AxwD/AMcA/wDHAP8AlwDfAAIAKQAA
+ AAAAAAAAAAAABgAABkALAKDMEQDy/QYAWlUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwUKAJajDwDq/gYAXZQAAAAYAAAAAQAAAAAAAAINDQC/3BAA
+ 4P8PAN3/DwDc/w8A2/8PANr/DwDa/w8A2/8PANz/DwDe/w8A4P8QAOL/EADl/w8L2v8CpyX/AMcA/wDH
+ AP8AxwD/AEcAlAAAAAsAAAAGAAADOAsAo80RAPP+CAB6eQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4PCwCzwQ8A5/wFAE2EAAAAGgAA
+ ABAAAAAVCABymBAA4/8QAOH/EADg/xAA3/8QAN7/EADe/xAA3v8QAN//EADh/xAA4v8QAOX/EADn/xAA
+ 6/8NIsP/ALwN/wDHAP8AxwD/ALEA8gAJAXQAAAVWCQCKvhEA8/8KAJGRAAAKAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAXGQ0A
+ ytoPAN/3BgBeowQASZIFAFObCAB0uxAA5f8RAOX/EADj/xAA4v8QAOH/EADh/xAA4f8QAOL/EADj/xAA
+ 5f8QAOf/EADq/xAA7f8RAPD/C0Se/wDHAP8AxwD/AMcA/wRmPPoPANL2EQDz/wwArbEAAA8GAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAIALTAOANnoEADs/xAA7P8QAOz/EADq/w8A3/4RAOn/EQDn/xEA5v8RAOX/EQDl/xEA
+ 5f8RAOb/EADn/xAA6P8QAOr/EADt/xEA7/8RAPL/DgDM0wF0GKsAxwD/AMcA/wDABP8IHXbdCgCNhwEA
+ HAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADMXCQCRUAkAmVcKAJtMCAB/OwMANzMOAMvbEADq/xAA
+ 5/8QAOj/EQDo/xEA6P8RAOn/EADq/xAA6/8QAOr/EADn/xEA7v8RAPD4BABCPQAoAAgApQDCAMcA/wDH
+ AP8AiwDTAAEAIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAADADE7DQC98gsAqf8OAMn/EADp/xEA7P8RAOz/EADt/xAA6/8NAMH/CwCm/w0Avv4HAG1yAAACAQAA
+ AAAASAAdALgA5gDHAP8AxgD+ADoAhQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAUBwBnvQ0Avv8OAMj/DwDh/xEA7/8RAPD/EQDw/xAA4v8MAKz/DQC9/w0A
+ xe4AAA0iAAAAAAAAAAAAAAAAAGAAQADFAPkAxwD/AKoA6wAFADYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVDQC57w4Ayv8QAOH+EADh+BIA8/8SAPP/EQD0/xAA
+ 5/0OAMj6DgDN/xAA4f4CAC0xAAAAAAAAAAAAAAAAAAAAAAB6AHQAxwD/AMcA/wBbAKcAAAAOAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCgCYqRAA4/8NALvDAQAaNAUF
+ eokJAIlqBgR8iQIBOFQGAGFuEADh8gsAqa4AAAwGAAAAAAAAAAAAAAAAAAAAAAAoAAMAmwCsAMcA/wC7
+ APYAFQBSAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAlBAkA
+ ii4AAA0SAAYyagAKTV4AAAAAAAENHwARhbMAAAAZAgArBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAARQAQAK8A1gDHAP8AfQDHAAAAGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAMwABeq2QADHCIAAAAAAAAACQAWpsoACEJ3AAAACQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAE4ALQDBAPMAxQD9AC0AdQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AClCPABiy0QAAAAUAAAAAAAAAAQANZYQAGsLrAAIPOQAA
+ AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2AF0AxwD+AJ0A4QABACoAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgABCDwAGr/rAA5rgQAAAAAAAAAAAAAAAAAD
+ HS0AHdb5ABGEtwAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAEAigCTAMcA/wBM
+ AJkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEwANYqAAHdX4AAUnJgAA
+ AAAAAAAAAAAAAAAAAAUAE5OxAB3a/gAHOG0AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAALgAJAKcAxQCzAPEADgBGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAIQTAAb
+ yvMAE5GpAAACAgAAAAAAAAAAAAAAAAAAAAAABSg2AB3W+AAZvecAAQ08AAAAAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAEgAHgC7AOoAbgC5AAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAAnABKGwgAd1vgABSsvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAA92jQAd2/8AFJbJAAADKwAA
+ AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjAEYAvwD2ACIAZwAAAAMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAIAAAADAAAAAwAAAB0ACUiQAB3Z/gARgZUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJDQAX
+ r8sAHdv/ABF/uAAAASsAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfgB8AI8A1gAA
+ ACIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAgAAAzAAAQtUAAAASgAIPpAAHM/4ABm/3AACFhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAEICMAGsLgAB3b/wASicMAAQhGAAAAGgAAABQAAAATAAAABAAAAAAAAAAAAAAAAAAA
+ AAAAJgAEAJwAsgA8AIYAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAOaZUAHdb8ABrC8QAd2v8AHNDwAAYzNAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCYrABrB3gAd2/8AGbzrAA1irQAKT54ADF+gAAEJIwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAADkAEgCVAMcACAA2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAJS1cAG8jjAB3a+wAYt88ABz03AAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMcGwAVoLYAHdv+AB3b/wAd
+ 2/8AHdv/AAg/TgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfADUAWgCVAAAADgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSsGAAxkEgAC
+ GAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
+ DQMAC1c/ABSXhwAWo5IAEYBnAAMdCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZABaABcAPgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAFAABAEUASgAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAC4ACAARAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4H/////////AP////
+ ////4Af////////AAH//P///4wAAH/w////gAAAP+D////AAAAfwf///8AAAA+B////wAAAB4P///+AA
+ AAAB////wAAAAAP////AAAAAA4///8AAAAAPD///wAAAAH4P///gEAAAfB///+BwAAB4P///8HAAAAA/
+ ///4AAAAAH////wAAAAA/////AAAAAE////xAAAAfD////BwAAB4P///+DAAAHB////4GAAAYP////wI
+ AAAA/////gAAAAH/////AAAAA/////+AAAAH/////8AAAA///////wACB///////AAcH//////8AB4P/
+ /////wAHgf//////gh/B///////CH+D//////8IP8P//////hw/wf/////+HB/g//////weD/D/////+
+ D4H+H/////APwP8f////4B/gDw/////gP/APj////+B/+A/H////+P/8D+P/////////4//////////z
+ /////////////ygAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEANgBHAGQAmQBRAIoACwAmAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAEAGUAhQDGAP0AyAD/AMgA/wCaANwAAwAaAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAA0ADQCAAKsAxwD/AMgA/wDIAP8AyAD/AMgA/wBR
+ AJQAAAAZAAAAGAAAAAkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgsBABY8AAAABQAdAB4AmADKAMcA/wDHAP8AyAD/AMgA/wDI
+ AP8AyAD/ALgA+QcOZtkKAJTYBwBurwEAF0cAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAMA
+ LmIDADo4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQUAW4sCICiPAK0A4wDHAP8AxwD/AMcA/wDI
+ AP8AyAD/AMgA/wDIAP8AyAD/A3U0/w4Awv8PANH/DwDN9gQAQXQAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
+ AA8FAFGLCwCkswAAAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAD0IYQC6CP8AxwD/AMcA/wDH
+ AP8AxwD/AMgA/wDAAPoAyAD/AMgA/wDIAP8AxQH/CSZ//w4Az/8PANj/DwDa+gMAM1oAAAABAAAAAAAA
+ AAAAAAAKBQBQiA8A1eYDADAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBWAHAAwwD7AMcA/wDH
+ AP8AxwD/AMcA/wDHAP8AngDiBxhl1wGuFf8AyAD/AMgA/wDIAP8BmRv/DQC8/w8A1v8QAN//DgDD5QIA
+ JGkBABxVAQAPSQQAO3sPAODzBQBLOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbQBWAMcA/gDH
+ AP8AxwD/AMcA/wDHAP8AxwD/AaMb/wcOcOwMAK7/CiaK/wDBBf8AyAD/AMgA/wDHAP8GSGD/DwDU/xAA
+ 3v8QAOb/DgDQ+BAA6fkRAO3/EADo9wcAbWEAAAAAAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAAAAAABH
+ ADABohPpAMYA/gDHAP8AxwD/AMcA/wCnANoEFEBwCQCC0Q0AtP8NALH/B0xt/wDHAP8AyAD/AMgA/wCz
+ C/8MCq//EADd/xAA5f8MALHLAAAECQMANgkBACAFAAAAAAAAAAAAAAADAAAKMwQARlgAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAUAU2QGDlijAC0ARQCAAFkAgQBhACEAEgAAAA8LAJ7gDQC6/w0At/8NALf/BXdJ/wDI
+ AP8AyAD/AMcA/wRrQv8PANj/EADl/xAA6PoBABEaAAAAAAAAAAAAAAAAAAAABAIAHVANALbTAwAtGwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAADBAsAm74HAGWeAAAADAAAAAAAAAAAAAAIHw4AwfwOAL//DgC8/w4A
+ vP8NBbj/Ap4n/wDIAP8AxwD/AMMC/wofl/8QAOX/EQDu/wQAREIAAAAAAAAAAAAAAAIBABtKDwDS7AcA
+ ZVcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAfGw0AvOQFAEyCAAAAFQAAABUBABxLDgDJ/w4A
+ xP8OAML/DgDB/w4Awv8MF63/AbcP/wDHAP8AyAD/ApAm/w8A1/8RAO7/BgBWhwAACD8AAAA0AAALSA4A
+ w+IKAI6IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA6PQ4Ax/QJAIzPCgCR0woA
+ meUPAM7/DwDK/w4Ax/8OAMb/DgDH/w8Ayv8KNZb/AMUC/wDIAP8AxwD/CD14/xEA7v8QAOP6EQDw/xEA
+ 6fsRAOr7DACvswAACQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAADBgBXNwsA
+ nHAKAJBpBwBldA8A1P8PAND/DwDN/w8Ay/8PAMz/DwDO/w8A0v8IX27/AMgA/wDIAP8BrRH/DgbM/wYA
+ XlcFAFQSBwBuIggAcyAAAAUCAAAAFwEAFiIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwA5QwMA
+ MF8AAAAJAAAAAAAAAAAAAAcTDwDU+g8A1f8PANL/DwDR/w8A0f8PANP/DwDV/w8B2P8EikP/AMgA/wDI
+ AP8GYVX/BABFNwAAAAAAAAAAAAAAAwAADToKAI6zAwAzHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAIDCwCitAYAXI0AAAANAAAAAAAAAAUMALHTEADb/xAA2P8QANb/EADW/xAA1/8QANr/DwDd/w8M
+ 0/8CqiD/AMgA/wC/BP8AHANLAAAAAAAAAAMBABpLDgDK5QcAaFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAACAB8YDQDN3gYAYpAAAAAJAAAAAQgAdI0QAOD/EADd/xAA3P8QANv/EADc/xAA
+ 3v8QAOH/EADl/w0jv/8Avwn/AMgA/wCFAMoAAAAbAQAURA8A0OkJAIqAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADADMsDgDa7QYAXJQDADJuBgBbmRAA5f8QAOP/EADh/xAA
+ 4P8QAOH/EADi/xAA5f8RAOn/EQDt/wtHmv8AxwD/AMcA/wQyRtQOAMvpCwCfnQAAAgEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAExFDQDK1g4A1+MOAMjUDQDE2hEA
+ 6P8RAOb/EQDm/xEA5v8RAOf/EADp/xEA7f8RAPH/DgDCyQCEC6EAyAD/AaQV/AcDZHoBABUFAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAABABgRDAC32A0Awf8QAOX/EQDr/xEA7P8QAOb/DQC8/w4Ayu8EAD4oADMABgCqAMcAyAD/AFYAlgAA
+ AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEGAFWWDgDG/w8A2/8RAPD/EQDx/w8A1P8NALz/CgCXvAAAAAIAAAAAAFoAHAC5
+ AOkAugD2ABQAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAcYYQAN/9CAB3iAoCpqkLAaqqBwBrgg4AzucJAIyRAAAAAAAA
+ AAAAAAAAAG8AQwDGAPwAdwC7AAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAgMAMxoABzZlAAg/NQABCREADmqXAAAECQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAIsAeQDFAP4AKgBbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHQAVnsoAAAUGAAAAAgAU
+ lLYABi5VAAAAAQAAAAAAAAAAAAAAAAAAAAAAFAABAKQAsQCYANoAAQAVAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMACk+EABKFmwAA
+ AAAAAAAAAApQXQAYtN4AAAUaAAAAAAAAAAAAAAAAAAAAAAAAAAAASgAQALIA3ABHAIQAAAABAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIKgAa
+ vuoACD0yAAAAAAAAAAAAAAYIABm42AAObp4AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAZgAwAKwA5gAM
+ ACsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AA8AD3KsABSWrQAAAAEAAAAAAAAAAAAAAAAACEJFAB3X+gAIP3EAAAAGAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAgQBgAGgArAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ BisAAAA0AApKjQAbzO4ABi8gAAAAAAAAAAAAAAAAAAAAAAAAAAEADm57ABzT+QAIQXoAAAAXAAAADgAA
+ AAUAAAAAAAAAAAAAAAAAkQCWAB8ASgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACABORtgAczvgAHdX3AApQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAD3SAAB3Z/QAU
+ mdIAEYLBAAg/YAAAAAAAAAAAAAAAAAA5AAgAbACXAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAABzwcABWiWgAKUSYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAC1ZAABampQAYsrEAC1dEAAAAAAAAAAAAAAAAAAAAAABcACAALgBQAAAAAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+ACUABgAIAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ
+ AAEAAAAA/wf///4D///MAD/PwAAfj8AADw/AAAYfgAAAP4AAAGeAAADHwAADh8MAAw/gAAAf8AAAH+AA
+ AA/jAAMP4QACH/AAAD/4AAA//AAAf//AAH//wAh//+AcP//gPj//8B4f/+MfD//jD4//w4fH/geA5/4P
+ wOP/H/Dx////+f////0oAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAEAAQB0AHMAkQDIAEYARwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAwSABAACQCOAKAAxwD/AMgA/wCmAOMFBEx4AwAyQAAAAAEAAAAAAAAAAAAAAAMCACApAAAAAAAA
+ AAAAAAAAAhgtOwCTDNwAxwD/AMcA/wDGAP4AyAD/Blhd/w8A0f0GAF90AAAAAAAAAAIHAGSCBwBrNAAA
+ AAAAAAAAAFYAFgCsANoAxwD/AMcA/wKFIvMIO2z1AMYB/wC8Bv8MErL/DwDZ+AgAfqwJAIiuCQCNZAAA
+ AAAAAAACAAAAAAA+AAwDXy+8AJEApwCZAJMHBWSMDQC2/wZjW/8AyAD/BHw//xAA4P8JAIV6AgAsAwAA
+ AAEEAEJWAwA3HQAAAAAAAAAABgBYNwcAY4QAAAALCAB2mQ4AwP8NAb7/BI05/wDGAP8LK57/CwCksgAA
+ BB0FAEddCgCScwAAAAAAAAAAAAAAAAAAAAMHAGlbCgCSngwAq9YOAMv/DgDJ/w0NwP8CrRz/Ap4i/w4B
+ w9QPAM6LDACodAAACg8AAAAAAAAAAAAAAAACACcSBQBUagAAAAMJAIZ5DwDW/w8A1P8PANb/DCWz/wDA
+ CP8CWiegAAAAAQUASFsHAGpLAAAAAAAAAAAAAAAAAAAAAAcAbkkHAHGHBQBPZRAA4f8QAN7/EADf/xAA
+ 5f8KSpT/ALcA8gUNT4cLAJ+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQCPRw4Aym4MAK+xDwDd/xEA
+ 6f8PAN7/DQC6uACjA5sCcx3DAAALAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQBTRw0A
+ vuEOAc3UDACy2ggAelQAWgAHALIAxwA9AD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAACEdZAAMaEwALU2sAAAAAAAAAAAB9AB8AjQC5AAEABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAULABB5jwAAAAAAEYKHAAYvMAAAAAAAAAAAAJEARwBXAGYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAMYAA5qjQANZDMAAAAAAAc0EQAUlrgAAx0mAAAABQAAAAAAegBoABYAFAAAAAAAAAAAAAAAAAAA
+ AAAAAAABABWciQASiFoAAAAAAAAAAAAAAAAAC1MhABairQAPc4UAAAAAADkAAgBBAEUAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAJAAkAAuH/
+ rEGAM6xBgCOsQQAFrEEAAaxBgAOsQYADrEGAA6xBwAesQeAHrEH4B6xB/GOsQfkzrEHxCaxB44msQf/8
+ rEE=
+</value>
+ </data>
</root> \ No newline at end of file
diff --git a/Source/ModelViewer/ModelViewer.csproj b/Source/ModelViewer/ModelViewer.csproj
index 50ca7c1c..78601afd 100644
--- a/Source/ModelViewer/ModelViewer.csproj
+++ b/Source/ModelViewer/ModelViewer.csproj
@@ -1,212 +1,212 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.ModelViewer</RootNamespace>
- <AssemblyName>ModelViewer</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- <FileAlignment>512</FileAlignment>
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
- <PlatformTarget>AnyCPU</PlatformTarget>
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup>
- <ApplicationIcon>bvdicon.ico</ApplicationIcon>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>..\..\Binaries\BVD.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup>
- <StartupObject />
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|x86'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Data" />
- <Reference Include="System.Numerics" />
- <Reference Include="System.Deployment" />
- <Reference Include="System.Drawing" />
- <Reference Include="System.Windows.Forms" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="BaseProvider.cs" />
- <Compile Include="BCTProvider.cs" />
- <Compile Include="DafnyProvider.cs" />
- <Compile Include="DataModel.cs" />
- <Compile Include="Main.cs">
- <SubType>Form</SubType>
- </Compile>
- <Compile Include="Main.Designer.cs">
- <DependentUpon>Main.cs</DependentUpon>
- </Compile>
- <Compile Include="Namer.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="SourceView.cs">
- <SubType>Form</SubType>
- </Compile>
- <Compile Include="SourceView.Designer.cs">
- <DependentUpon>SourceView.cs</DependentUpon>
- </Compile>
- <Compile Include="TreeSkeleton.cs" />
- <Compile Include="VccProvider.cs" />
- <EmbeddedResource Include="Main.resx">
- <DependentUpon>Main.cs</DependentUpon>
- <SubType>Designer</SubType>
- </EmbeddedResource>
- <EmbeddedResource Include="Properties\Resources.resx">
- <Generator>ResXFileCodeGenerator</Generator>
- <LastGenOutput>Resources.Designer.cs</LastGenOutput>
- <SubType>Designer</SubType>
- </EmbeddedResource>
- <Compile Include="Properties\Resources.Designer.cs">
- <AutoGen>True</AutoGen>
- <DependentUpon>Resources.resx</DependentUpon>
- <DesignTime>True</DesignTime>
- </Compile>
- <EmbeddedResource Include="SourceView.resx">
- <DependentUpon>SourceView.cs</DependentUpon>
- </EmbeddedResource>
- <None Include="Properties\Settings.settings">
- <Generator>SettingsSingleFileGenerator</Generator>
- <LastGenOutput>Settings.Designer.cs</LastGenOutput>
- </None>
- <Compile Include="Properties\Settings.Designer.cs">
- <AutoGen>True</AutoGen>
- <DependentUpon>Settings.settings</DependentUpon>
- <DesignTimeSharedInput>True</DesignTimeSharedInput>
- </Compile>
- <Compile Include="..\version.cs" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
- <Visible>False</Visible>
- <ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <ItemGroup>
- <Content Include="bvdicon.ico" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Model\Model.csproj">
- <Project>{acef88d5-dadd-46da-bae1-2144d63f4c83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- </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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie.ModelViewer</RootNamespace>
+ <AssemblyName>BoogieModelViewer</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup>
+ <ApplicationIcon>bvdicon.ico</ApplicationIcon>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\BVD.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject />
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Numerics" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BaseProvider.cs" />
+ <Compile Include="BCTProvider.cs" />
+ <Compile Include="DafnyProvider.cs" />
+ <Compile Include="DataModel.cs" />
+ <Compile Include="Main.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="Main.Designer.cs">
+ <DependentUpon>Main.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Namer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SourceView.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="SourceView.Designer.cs">
+ <DependentUpon>SourceView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="TreeSkeleton.cs" />
+ <Compile Include="VccProvider.cs" />
+ <EmbeddedResource Include="Main.resx">
+ <DependentUpon>Main.cs</DependentUpon>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Resources.resx</DependentUpon>
+ <DesignTime>True</DesignTime>
+ </Compile>
+ <EmbeddedResource Include="SourceView.resx">
+ <DependentUpon>SourceView.cs</DependentUpon>
+ </EmbeddedResource>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <Compile Include="..\version.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="bvdicon.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Model\Model.csproj">
+ <Project>{acef88d5-dadd-46da-bae1-2144d63f4c83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ </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/ModelViewer/Namer.cs b/Source/ModelViewer/Namer.cs
index 0eb2418e..3adf0a11 100644
--- a/Source/ModelViewer/Namer.cs
+++ b/Source/ModelViewer/Namer.cs
@@ -1,580 +1,580 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Numerics;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- public enum NameSeqSuffix
- {
- None,
- WhenNonZero,
- Always
- }
-
- public abstract class LanguageModel : ILanguageSpecificModel
- {
- protected Dictionary<string, int> baseNameUse = new Dictionary<string, int>();
- protected Dictionary<Model.Element, string> canonicalName = new Dictionary<Model.Element, string>();
- protected Dictionary<string, Model.Element> invCanonicalName = new Dictionary<string, Model.Element>();
- protected Dictionary<Model.Element, string> localValue = new Dictionary<Model.Element, string>();
- protected Dictionary<string, SourceViewState> sourceLocations = new Dictionary<string, SourceViewState>();
- public readonly Model model;
-
- protected virtual bool UseLocalsForCanonicalNames
- {
- get { return false; }
- }
-
- public readonly ViewOptions viewOpts;
- public LanguageModel(Model model, ViewOptions opts)
- {
- this.model = model;
- viewOpts = opts;
- }
-
- public string AsPow2(Model.Integer elt)
- {
- var n = BigInteger.Parse(elt.Numeral);
- var pow = new BigInteger(4096*4);
- var k = 14;
- var neg = false;
-
- if (n < 0) {
- n = -n;
- neg = true;
- }
-
- while (k < 150) {
- var diff = pow / 1000;
- if (pow - diff < n && n < pow + diff) {
- diff = n - pow;
- var res = string.Format("2^{0}{1}{2}", k, diff >= 0 ? "+" : "", diff);
- if (neg) res = "-(" + res + ")";
- return res;
- }
- if (n < pow) break;
- k++;
- pow *= 2;
- }
-
- return elt.ToString();
- }
-
- // Elements (other than integers and Booleans) get canonical names of the form
- // "<base>'<idx>", where <base> is returned by this function, and <idx> is given
- // starting with 0, and incrementing when there are conflicts between bases.
- //
- // This function needs to return an appropriate base name for the element. It is given
- // the element.
- //
- // A reasonable strategy is to check if it's a name of the local, and if so return it,
- // and otherwise use the type of element (e.g., return "seq" for elements representing
- // sequences). It is also possible to return "" in such cases.
- //
- // The suff output parameter specifies whether the number sequence suffix should be
- // always added, only when it's non-zero, or never.
- protected virtual string CanonicalBaseName(Model.Element elt, out NameSeqSuffix suff)
- {
- string res;
- if (elt is Model.Integer || elt is Model.Boolean) {
- suff = NameSeqSuffix.None;
- return elt.ToString();
- }
- suff = NameSeqSuffix.Always;
- if (UseLocalsForCanonicalNames) {
- if (localValue.TryGetValue(elt, out res))
- return res;
- }
- return "";
- }
-
- public virtual void RegisterLocalValue(string name, Model.Element elt)
- {
- string curr;
- if (localValue.TryGetValue(elt, out curr) && CompareFieldNames(name, curr) >= 0)
- return;
- localValue[elt] = name;
- }
-
- protected virtual string AppendSuffix(string baseName, int id)
- {
- return baseName + "'" + id.ToString();
- }
-
- public virtual string CanonicalName(Model.Element elt)
- {
- string res;
- if (elt == null) return "?";
- if (canonicalName.TryGetValue(elt, out res)) return res;
- NameSeqSuffix suff;
- var baseName = CanonicalBaseName(elt, out suff);
- if (baseName == "")
- suff = NameSeqSuffix.Always;
-
- if (viewOpts.DebugMode && !(elt is Model.Boolean) && !(elt is Model.Number)) {
- baseName += string.Format("({0})", elt);
- suff = NameSeqSuffix.WhenNonZero;
- }
-
- int cnt;
- if (!baseNameUse.TryGetValue(baseName, out cnt))
- cnt = -1;
- cnt++;
-
- if (suff == NameSeqSuffix.Always || (cnt > 0 && suff == NameSeqSuffix.WhenNonZero))
- res = AppendSuffix(baseName, cnt);
- else
- res = baseName;
-
- baseNameUse[baseName] = cnt;
- canonicalName.Add(elt, res);
- invCanonicalName[res.Replace(" ", "")] = elt;
- return res;
- }
-
- public virtual Model.Element FindElement(string canonicalName)
- {
- Model.Element res;
- if (invCanonicalName.TryGetValue(canonicalName.Replace(" ", ""), out res))
- return res;
- return null;
- }
-
- public virtual string PathName(IEnumerable<IDisplayNode> path)
- {
- return path.Select(n => n.Name).Concat(".");
- }
-
- public abstract IEnumerable<IState> States { get; }
-
- /// <summary>
- /// Walks each input tree in BFS order, and force evaluation of Name and Value properties
- /// (to get reasonable numbering of canonical values).
- /// </summary>
- public void Flush(IEnumerable<IDisplayNode> roots)
- {
- var workList = new Queue<IDisplayNode>();
-
- Action<IEnumerable<IDisplayNode>> addList = (IEnumerable<IDisplayNode> nodes) =>
- {
- var ch = new Dictionary<string, IDisplayNode>();
- foreach (var x in nodes) {
- if (ch.ContainsKey(x.Name)) {
- // throw new System.InvalidOperationException("duplicated model entry: " + x.Name);
- }
- ch[x.Name] = x;
- }
- foreach (var k in SortFields(nodes))
- workList.Enqueue(ch[k]);
- };
-
- addList(roots);
-
- var visited = new HashSet<Model.Element>();
- while (workList.Count > 0) {
- var n = workList.Dequeue();
-
- var dummy1 = n.Name;
- var dummy2 = n.Value;
-
- if (n.Element != null) {
- if (visited.Contains(n.Element))
- continue;
- visited.Add(n.Element);
- }
-
- addList(n.Children);
- }
- }
-
- #region field name sorting
- /*
- static bool HasSpecialChars(string s)
- {
- for (int i = 0; i < s.Length; ++i)
- switch (s[i]) {
- case '[':
- case '<':
- case '>':
- case ']':
- case '#':
- case '\\':
- case '(':
- case ')':
- return true;
- }
- return false;
- }
- */
-
- static ulong GetNumber(string s, int beg)
- {
- ulong res = 0;
- while (beg < s.Length) {
- var c = s[beg];
- if ('0' <= c && c <= '9') {
- res *= 10;
- res += (uint)c - (uint)'0';
- }
- beg++;
- }
- return res;
- }
-
- public virtual int CompareFieldNames(string f1, string f2)
- {
- /*
- bool s1 = HasSpecialChars(f1);
- bool s2 = HasSpecialChars(f2);
- if (s1 && !s2)
- return 1;
- if (!s1 && s2)
- return -1; */
- var len = Math.Min(f1.Length, f2.Length);
- var numberPos = -1;
- for (int i = 0; i < len; ++i) {
- var c1 = f1[i];
- var c2 = f2[i];
- if ('0' <= c1 && c1 <= '9' && '0' <= c2 && c2 <= '9') {
- numberPos = i;
- break;
- }
- if (c1 != c2)
- break;
- }
-
- if (numberPos >= 0) {
- var v1 = GetNumber(f1, numberPos);
- var v2 = GetNumber(f2, numberPos);
-
- if (v1 < v2) return -1;
- else if (v1 > v2) return 1;
- }
-
- return string.CompareOrdinal(f1, f2);
- }
-
- public virtual int CompareFields(IDisplayNode n1, IDisplayNode n2)
- {
- var diff = (int)n1.Category - (int)n2.Category;
- if (diff != 0) return diff;
- else return CompareFieldNames(n1.Name, n2.Name);
- }
-
- public virtual IEnumerable<string> SortFields(IEnumerable<IDisplayNode> fields_)
- {
- var fields = new List<IDisplayNode>(fields_);
- fields.Sort(CompareFields);
- return fields.Select(f => f.Name);
- }
- #endregion
-
- #region Displaying source code
- class Position : IComparable<Position>
- {
- public int Line, Column, Index;
- public int CharPos;
- public string Name;
-
- public int CompareTo(Position other)
- {
- if (this.Line == other.Line)
- return this.Column - other.Column;
- return this.Line - other.Line;
- }
- }
-
- public class SourceLocation
- {
- public string Filename;
- public string AddInfo;
- public int Line;
- public int Column;
- }
-
- public SourceViewState GetSourceLocation(string name)
- {
- SourceViewState res;
- sourceLocations.TryGetValue(name, out res);
- return res;
- }
-
- // example parsed token: @"c:\users\foo\bar.c(12,10) : random string"
- // the ": random string" part is optional
- public virtual SourceLocation TryParseSourceLocation(string name)
- {
- var par = name.LastIndexOf('(');
- if (par <= 0) return null;
-
- var res = new SourceLocation() { Filename = name.Substring(0, par) };
-
- var words = name.Substring(par + 1).Split(',', ')', ':').Where(x => x != "").ToArray();
- if (words.Length < 2) return null;
-
- if (!int.TryParse(words[0], out res.Line) || !int.TryParse(words[1], out res.Column)) return null;
-
- var colon = name.IndexOf(':', par);
- if (colon > 0)
- res.AddInfo = name.Substring(colon + 1).Trim();
- else
- res.AddInfo = "";
-
- return res;
- }
-
- static char[] dirSeps = new char[] { '\\', '/' };
- public virtual string ShortenToken(string tok, int fnLimit, bool addAddInfo)
- {
- var loc = TryParseSourceLocation(tok);
-
- if (loc != null) {
- var fn = loc.Filename;
- var idx = fn.LastIndexOfAny(dirSeps);
- if (idx > 0)
- fn = fn.Substring(idx + 1);
- if (fn.Length > fnLimit) {
- fn = fn.Substring(0, fnLimit) + "..";
- }
- var addInfo = addAddInfo ? loc.AddInfo : "";
- if (addInfo != "")
- addInfo = ":" + addInfo;
- return string.Format("{0}({1},{2}){3}", fn, loc.Line, loc.Column, addInfo);
- } else {
- return tok;
- }
- }
-
- protected virtual void RtfAppend(StringBuilder sb, char c, ref int pos)
- {
- pos++;
- switch (c) {
- case '\r': pos--; break;
- case '\\': sb.Append("\\\\"); break;
- case '\n': sb.Append("\\par\n"); break;
- case '{': sb.Append("\\{"); break;
- case '}': sb.Append("\\}"); break;
- default: sb.Append(c); break;
- }
- }
-
- protected virtual void RtfAppendStateIdx(StringBuilder sb, string label, ref int pos)
- {
- label += ".";
- pos += label.Length;
- sb.Append(@"{\sub\cf5\highlight4 ").Append(label).Append("}");
- }
-
- protected virtual void RtfAppendLineNo(StringBuilder sb, int num, ref int pos)
- {
- string n = string.Format("{0:0000}: ", num);
- pos += n.Length;
- sb.Append(@"{\cf6 ").Append(n).Append("}");
- }
-
- protected virtual void GenerateSourceLocations(IEnumerable<NamedState> states)
- {
- sourceLocations = new Dictionary<string, SourceViewState>();
-
- var files = new Dictionary<string, List<Position>>();
- var sIdx = -1;
-
- foreach (var s in states) {
- var sn = s.CapturedStateName;
- sIdx++;
- var loc = TryParseSourceLocation(sn);
- if (loc == null) continue;
-
- List<Position> positions;
- if (!files.TryGetValue(loc.Filename, out positions)) {
- positions = new List<Position>();
- files[loc.Filename] = positions;
- }
- positions.Add(new Position() { Name = sn, Line = loc.Line, Column = loc.Column, Index = sIdx });
- }
-
- foreach (var kv in files) {
- var positions = kv.Value;
- positions.Sort();
-
- string content = "";
- if (System.IO.File.Exists(kv.Key)) {
- try {
- content = System.IO.File.ReadAllText(kv.Key);
- } catch {
- continue;
- }
- } else {
- continue;
- }
-
- var pos = new Position() { Line = 1, Column = 1 };
- var currPosIdx = 0;
- var output = new StringBuilder();
- RtfAppendLineNo(output, pos.Line, ref pos.CharPos);
-
- foreach (var c in content) {
- if (c == '\n') {
- pos.Column = int.MaxValue; // flush remaining positions in this line
- }
-
- while (currPosIdx < positions.Count && pos.CompareTo(positions[currPosIdx]) >= 0) {
- positions[currPosIdx].CharPos = pos.CharPos;
- RtfAppendStateIdx(output, positions[currPosIdx].Index.ToString(), ref pos.CharPos);
- currPosIdx++;
- }
-
- RtfAppend(output, c, ref pos.CharPos);
-
- if (c == '\n') {
- pos.Line++;
- pos.Column = 1;
- RtfAppendLineNo(output, pos.Line, ref pos.CharPos);
- } else {
- pos.Column++;
- }
- }
-
- var resStr = output.ToString();
- foreach (var p in positions) {
- sourceLocations[p.Name] = new SourceViewState() { Header = p.Name, Location = p.CharPos, RichTextContent = resStr };
- }
- }
- }
- #endregion
- }
-
- public abstract class NamedState : IState
- {
- protected Model.CapturedState state;
- private LanguageModel langModel; // no point making it protected - they will need VccModel, DafnyModel
-
- public NamedState(Model.CapturedState s, LanguageModel lm)
- {
- this.state = s;
- this.langModel = lm;
- }
-
- public Model.CapturedState State
- {
- get { return state; }
- }
-
- public virtual string Name
- {
- get
- {
- return langModel.ShortenToken(state.Name, 20, true);
- }
- }
-
- // by overriding this, one state can masqureade another
- public virtual string CapturedStateName
- {
- get { return State.Name; }
- }
-
- public virtual SourceViewState ShowSource()
- {
- return langModel.GetSourceLocation(CapturedStateName);
- }
-
- public abstract IEnumerable<IDisplayNode> Nodes { get; }
- }
-
- public class EdgeName
- {
- ILanguageSpecificModel langModel;
- string format;
- string cachedName;
- Model.Element[] args;
-
- public EdgeName(ILanguageSpecificModel n, string format, params Model.Element[] args)
- {
- this.langModel = n;
- this.format = format;
- this.args = args.ToArray();
- }
-
- public EdgeName(string name) : this(null, name)
- {
- Util.Assert(name != null);
- }
-
- public override string ToString()
- {
- if (cachedName != null)
- return cachedName;
- cachedName = Format();
- return cachedName;
- }
-
- public override int GetHashCode()
- {
- int res = format.GetHashCode();
- foreach (var c in args) {
- res += c.GetHashCode();
- res *= 13;
- }
- return res;
- }
-
- public override bool Equals(object obj)
- {
- EdgeName e = obj as EdgeName;
- if (e == null) return false;
- if (e == this) return true;
- if (e.format != this.format || e.args.Length != this.args.Length)
- return false;
- for (int i = 0; i < this.args.Length; ++i)
- if (this.args[i] != e.args[i])
- return false;
- return true;
- }
-
- protected virtual string Format()
- {
- if (args == null || args.Length == 0)
- return format;
-
- var res = new StringBuilder(format.Length);
- for (int i = 0; i < format.Length; ++i) {
- var c = format[i];
-
- /*
- var canonical = false;
- if (c == '%' && i < format.Length - 1) {
- if (format[i + 1] == 'c') {
- ++i;
- canonical = true;
- }
- }
- */
-
- if (c == '%' && i < format.Length - 1) {
- var j = i + 1;
- while (j < format.Length && char.IsDigit(format[j]))
- j++;
- var len = j - i - 1;
- if (len > 0) {
- var idx = int.Parse(format.Substring(i + 1, len));
- res.Append(langModel.CanonicalName(args[idx]));
- i = j - 1;
- continue;
- }
- }
-
- res.Append(c);
- }
-
- return res.ToString();
- }
-
- public virtual IEnumerable<Model.Element> Dependencies
- {
- get { return args; }
- }
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Numerics;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ public enum NameSeqSuffix
+ {
+ None,
+ WhenNonZero,
+ Always
+ }
+
+ public abstract class LanguageModel : ILanguageSpecificModel
+ {
+ protected Dictionary<string, int> baseNameUse = new Dictionary<string, int>();
+ protected Dictionary<Model.Element, string> canonicalName = new Dictionary<Model.Element, string>();
+ protected Dictionary<string, Model.Element> invCanonicalName = new Dictionary<string, Model.Element>();
+ protected Dictionary<Model.Element, string> localValue = new Dictionary<Model.Element, string>();
+ protected Dictionary<string, SourceViewState> sourceLocations = new Dictionary<string, SourceViewState>();
+ public readonly Model model;
+
+ protected virtual bool UseLocalsForCanonicalNames
+ {
+ get { return false; }
+ }
+
+ public readonly ViewOptions viewOpts;
+ public LanguageModel(Model model, ViewOptions opts)
+ {
+ this.model = model;
+ viewOpts = opts;
+ }
+
+ public string AsPow2(Model.Integer elt)
+ {
+ var n = BigInteger.Parse(elt.Numeral);
+ var pow = new BigInteger(4096*4);
+ var k = 14;
+ var neg = false;
+
+ if (n < 0) {
+ n = -n;
+ neg = true;
+ }
+
+ while (k < 150) {
+ var diff = pow / 1000;
+ if (pow - diff < n && n < pow + diff) {
+ diff = n - pow;
+ var res = string.Format("2^{0}{1}{2}", k, diff >= 0 ? "+" : "", diff);
+ if (neg) res = "-(" + res + ")";
+ return res;
+ }
+ if (n < pow) break;
+ k++;
+ pow *= 2;
+ }
+
+ return elt.ToString();
+ }
+
+ // Elements (other than integers and Booleans) get canonical names of the form
+ // "<base>'<idx>", where <base> is returned by this function, and <idx> is given
+ // starting with 0, and incrementing when there are conflicts between bases.
+ //
+ // This function needs to return an appropriate base name for the element. It is given
+ // the element.
+ //
+ // A reasonable strategy is to check if it's a name of the local, and if so return it,
+ // and otherwise use the type of element (e.g., return "seq" for elements representing
+ // sequences). It is also possible to return "" in such cases.
+ //
+ // The suff output parameter specifies whether the number sequence suffix should be
+ // always added, only when it's non-zero, or never.
+ protected virtual string CanonicalBaseName(Model.Element elt, out NameSeqSuffix suff)
+ {
+ string res;
+ if (elt is Model.Integer || elt is Model.Boolean) {
+ suff = NameSeqSuffix.None;
+ return elt.ToString();
+ }
+ suff = NameSeqSuffix.Always;
+ if (UseLocalsForCanonicalNames) {
+ if (localValue.TryGetValue(elt, out res))
+ return res;
+ }
+ return "";
+ }
+
+ public virtual void RegisterLocalValue(string name, Model.Element elt)
+ {
+ string curr;
+ if (localValue.TryGetValue(elt, out curr) && CompareFieldNames(name, curr) >= 0)
+ return;
+ localValue[elt] = name;
+ }
+
+ protected virtual string AppendSuffix(string baseName, int id)
+ {
+ return baseName + "'" + id.ToString();
+ }
+
+ public virtual string CanonicalName(Model.Element elt)
+ {
+ string res;
+ if (elt == null) return "?";
+ if (canonicalName.TryGetValue(elt, out res)) return res;
+ NameSeqSuffix suff;
+ var baseName = CanonicalBaseName(elt, out suff);
+ if (baseName == "")
+ suff = NameSeqSuffix.Always;
+
+ if (viewOpts.DebugMode && !(elt is Model.Boolean) && !(elt is Model.Number)) {
+ baseName += string.Format("({0})", elt);
+ suff = NameSeqSuffix.WhenNonZero;
+ }
+
+ int cnt;
+ if (!baseNameUse.TryGetValue(baseName, out cnt))
+ cnt = -1;
+ cnt++;
+
+ if (suff == NameSeqSuffix.Always || (cnt > 0 && suff == NameSeqSuffix.WhenNonZero))
+ res = AppendSuffix(baseName, cnt);
+ else
+ res = baseName;
+
+ baseNameUse[baseName] = cnt;
+ canonicalName.Add(elt, res);
+ invCanonicalName[res.Replace(" ", "")] = elt;
+ return res;
+ }
+
+ public virtual Model.Element FindElement(string canonicalName)
+ {
+ Model.Element res;
+ if (invCanonicalName.TryGetValue(canonicalName.Replace(" ", ""), out res))
+ return res;
+ return null;
+ }
+
+ public virtual string PathName(IEnumerable<IDisplayNode> path)
+ {
+ return path.Select(n => n.Name).Concat(".");
+ }
+
+ public abstract IEnumerable<IState> States { get; }
+
+ /// <summary>
+ /// Walks each input tree in BFS order, and force evaluation of Name and Value properties
+ /// (to get reasonable numbering of canonical values).
+ /// </summary>
+ public void Flush(IEnumerable<IDisplayNode> roots)
+ {
+ var workList = new Queue<IDisplayNode>();
+
+ Action<IEnumerable<IDisplayNode>> addList = (IEnumerable<IDisplayNode> nodes) =>
+ {
+ var ch = new Dictionary<string, IDisplayNode>();
+ foreach (var x in nodes) {
+ if (ch.ContainsKey(x.Name)) {
+ // throw new System.InvalidOperationException("duplicated model entry: " + x.Name);
+ }
+ ch[x.Name] = x;
+ }
+ foreach (var k in SortFields(nodes))
+ workList.Enqueue(ch[k]);
+ };
+
+ addList(roots);
+
+ var visited = new HashSet<Model.Element>();
+ while (workList.Count > 0) {
+ var n = workList.Dequeue();
+
+ var dummy1 = n.Name;
+ var dummy2 = n.Value;
+
+ if (n.Element != null) {
+ if (visited.Contains(n.Element))
+ continue;
+ visited.Add(n.Element);
+ }
+
+ addList(n.Children);
+ }
+ }
+
+ #region field name sorting
+ /*
+ static bool HasSpecialChars(string s)
+ {
+ for (int i = 0; i < s.Length; ++i)
+ switch (s[i]) {
+ case '[':
+ case '<':
+ case '>':
+ case ']':
+ case '#':
+ case '\\':
+ case '(':
+ case ')':
+ return true;
+ }
+ return false;
+ }
+ */
+
+ static ulong GetNumber(string s, int beg)
+ {
+ ulong res = 0;
+ while (beg < s.Length) {
+ var c = s[beg];
+ if ('0' <= c && c <= '9') {
+ res *= 10;
+ res += (uint)c - (uint)'0';
+ }
+ beg++;
+ }
+ return res;
+ }
+
+ public virtual int CompareFieldNames(string f1, string f2)
+ {
+ /*
+ bool s1 = HasSpecialChars(f1);
+ bool s2 = HasSpecialChars(f2);
+ if (s1 && !s2)
+ return 1;
+ if (!s1 && s2)
+ return -1; */
+ var len = Math.Min(f1.Length, f2.Length);
+ var numberPos = -1;
+ for (int i = 0; i < len; ++i) {
+ var c1 = f1[i];
+ var c2 = f2[i];
+ if ('0' <= c1 && c1 <= '9' && '0' <= c2 && c2 <= '9') {
+ numberPos = i;
+ break;
+ }
+ if (c1 != c2)
+ break;
+ }
+
+ if (numberPos >= 0) {
+ var v1 = GetNumber(f1, numberPos);
+ var v2 = GetNumber(f2, numberPos);
+
+ if (v1 < v2) return -1;
+ else if (v1 > v2) return 1;
+ }
+
+ return string.CompareOrdinal(f1, f2);
+ }
+
+ public virtual int CompareFields(IDisplayNode n1, IDisplayNode n2)
+ {
+ var diff = (int)n1.Category - (int)n2.Category;
+ if (diff != 0) return diff;
+ else return CompareFieldNames(n1.Name, n2.Name);
+ }
+
+ public virtual IEnumerable<string> SortFields(IEnumerable<IDisplayNode> fields_)
+ {
+ var fields = new List<IDisplayNode>(fields_);
+ fields.Sort(CompareFields);
+ return fields.Select(f => f.Name);
+ }
+ #endregion
+
+ #region Displaying source code
+ class Position : IComparable<Position>
+ {
+ public int Line, Column, Index;
+ public int CharPos;
+ public string Name;
+
+ public int CompareTo(Position other)
+ {
+ if (this.Line == other.Line)
+ return this.Column - other.Column;
+ return this.Line - other.Line;
+ }
+ }
+
+ public class SourceLocation
+ {
+ public string Filename;
+ public string AddInfo;
+ public int Line;
+ public int Column;
+ }
+
+ public SourceViewState GetSourceLocation(string name)
+ {
+ SourceViewState res;
+ sourceLocations.TryGetValue(name, out res);
+ return res;
+ }
+
+ // example parsed token: @"c:\users\foo\bar.c(12,10) : random string"
+ // the ": random string" part is optional
+ public virtual SourceLocation TryParseSourceLocation(string name)
+ {
+ var par = name.LastIndexOf('(');
+ if (par <= 0) return null;
+
+ var res = new SourceLocation() { Filename = name.Substring(0, par) };
+
+ var words = name.Substring(par + 1).Split(',', ')', ':').Where(x => x != "").ToArray();
+ if (words.Length < 2) return null;
+
+ if (!int.TryParse(words[0], out res.Line) || !int.TryParse(words[1], out res.Column)) return null;
+
+ var colon = name.IndexOf(':', par);
+ if (colon > 0)
+ res.AddInfo = name.Substring(colon + 1).Trim();
+ else
+ res.AddInfo = "";
+
+ return res;
+ }
+
+ static char[] dirSeps = new char[] { '\\', '/' };
+ public virtual string ShortenToken(string tok, int fnLimit, bool addAddInfo)
+ {
+ var loc = TryParseSourceLocation(tok);
+
+ if (loc != null) {
+ var fn = loc.Filename;
+ var idx = fn.LastIndexOfAny(dirSeps);
+ if (idx > 0)
+ fn = fn.Substring(idx + 1);
+ if (fn.Length > fnLimit) {
+ fn = fn.Substring(0, fnLimit) + "..";
+ }
+ var addInfo = addAddInfo ? loc.AddInfo : "";
+ if (addInfo != "")
+ addInfo = ":" + addInfo;
+ return string.Format("{0}({1},{2}){3}", fn, loc.Line, loc.Column, addInfo);
+ } else {
+ return tok;
+ }
+ }
+
+ protected virtual void RtfAppend(StringBuilder sb, char c, ref int pos)
+ {
+ pos++;
+ switch (c) {
+ case '\r': pos--; break;
+ case '\\': sb.Append("\\\\"); break;
+ case '\n': sb.Append("\\par\n"); break;
+ case '{': sb.Append("\\{"); break;
+ case '}': sb.Append("\\}"); break;
+ default: sb.Append(c); break;
+ }
+ }
+
+ protected virtual void RtfAppendStateIdx(StringBuilder sb, string label, ref int pos)
+ {
+ label += ".";
+ pos += label.Length;
+ sb.Append(@"{\sub\cf5\highlight4 ").Append(label).Append("}");
+ }
+
+ protected virtual void RtfAppendLineNo(StringBuilder sb, int num, ref int pos)
+ {
+ string n = string.Format("{0:0000}: ", num);
+ pos += n.Length;
+ sb.Append(@"{\cf6 ").Append(n).Append("}");
+ }
+
+ protected virtual void GenerateSourceLocations(IEnumerable<NamedState> states)
+ {
+ sourceLocations = new Dictionary<string, SourceViewState>();
+
+ var files = new Dictionary<string, List<Position>>();
+ var sIdx = -1;
+
+ foreach (var s in states) {
+ var sn = s.CapturedStateName;
+ sIdx++;
+ var loc = TryParseSourceLocation(sn);
+ if (loc == null) continue;
+
+ List<Position> positions;
+ if (!files.TryGetValue(loc.Filename, out positions)) {
+ positions = new List<Position>();
+ files[loc.Filename] = positions;
+ }
+ positions.Add(new Position() { Name = sn, Line = loc.Line, Column = loc.Column, Index = sIdx });
+ }
+
+ foreach (var kv in files) {
+ var positions = kv.Value;
+ positions.Sort();
+
+ string content = "";
+ if (System.IO.File.Exists(kv.Key)) {
+ try {
+ content = System.IO.File.ReadAllText(kv.Key);
+ } catch {
+ continue;
+ }
+ } else {
+ continue;
+ }
+
+ var pos = new Position() { Line = 1, Column = 1 };
+ var currPosIdx = 0;
+ var output = new StringBuilder();
+ RtfAppendLineNo(output, pos.Line, ref pos.CharPos);
+
+ foreach (var c in content) {
+ if (c == '\n') {
+ pos.Column = int.MaxValue; // flush remaining positions in this line
+ }
+
+ while (currPosIdx < positions.Count && pos.CompareTo(positions[currPosIdx]) >= 0) {
+ positions[currPosIdx].CharPos = pos.CharPos;
+ RtfAppendStateIdx(output, positions[currPosIdx].Index.ToString(), ref pos.CharPos);
+ currPosIdx++;
+ }
+
+ RtfAppend(output, c, ref pos.CharPos);
+
+ if (c == '\n') {
+ pos.Line++;
+ pos.Column = 1;
+ RtfAppendLineNo(output, pos.Line, ref pos.CharPos);
+ } else {
+ pos.Column++;
+ }
+ }
+
+ var resStr = output.ToString();
+ foreach (var p in positions) {
+ sourceLocations[p.Name] = new SourceViewState() { Header = p.Name, Location = p.CharPos, RichTextContent = resStr };
+ }
+ }
+ }
+ #endregion
+ }
+
+ public abstract class NamedState : IState
+ {
+ protected Model.CapturedState state;
+ private LanguageModel langModel; // no point making it protected - they will need VccModel, DafnyModel
+
+ public NamedState(Model.CapturedState s, LanguageModel lm)
+ {
+ this.state = s;
+ this.langModel = lm;
+ }
+
+ public Model.CapturedState State
+ {
+ get { return state; }
+ }
+
+ public virtual string Name
+ {
+ get
+ {
+ return langModel.ShortenToken(state.Name, 20, true);
+ }
+ }
+
+ // by overriding this, one state can masqureade another
+ public virtual string CapturedStateName
+ {
+ get { return State.Name; }
+ }
+
+ public virtual SourceViewState ShowSource()
+ {
+ return langModel.GetSourceLocation(CapturedStateName);
+ }
+
+ public abstract IEnumerable<IDisplayNode> Nodes { get; }
+ }
+
+ public class EdgeName
+ {
+ ILanguageSpecificModel langModel;
+ string format;
+ string cachedName;
+ Model.Element[] args;
+
+ public EdgeName(ILanguageSpecificModel n, string format, params Model.Element[] args)
+ {
+ this.langModel = n;
+ this.format = format;
+ this.args = args.ToArray();
+ }
+
+ public EdgeName(string name) : this(null, name)
+ {
+ Util.Assert(name != null);
+ }
+
+ public override string ToString()
+ {
+ if (cachedName != null)
+ return cachedName;
+ cachedName = Format();
+ return cachedName;
+ }
+
+ public override int GetHashCode()
+ {
+ int res = format.GetHashCode();
+ foreach (var c in args) {
+ res += c.GetHashCode();
+ res *= 13;
+ }
+ return res;
+ }
+
+ public override bool Equals(object obj)
+ {
+ EdgeName e = obj as EdgeName;
+ if (e == null) return false;
+ if (e == this) return true;
+ if (e.format != this.format || e.args.Length != this.args.Length)
+ return false;
+ for (int i = 0; i < this.args.Length; ++i)
+ if (this.args[i] != e.args[i])
+ return false;
+ return true;
+ }
+
+ protected virtual string Format()
+ {
+ if (args == null || args.Length == 0)
+ return format;
+
+ var res = new StringBuilder(format.Length);
+ for (int i = 0; i < format.Length; ++i) {
+ var c = format[i];
+
+ /*
+ var canonical = false;
+ if (c == '%' && i < format.Length - 1) {
+ if (format[i + 1] == 'c') {
+ ++i;
+ canonical = true;
+ }
+ }
+ */
+
+ if (c == '%' && i < format.Length - 1) {
+ var j = i + 1;
+ while (j < format.Length && char.IsDigit(format[j]))
+ j++;
+ var len = j - i - 1;
+ if (len > 0) {
+ var idx = int.Parse(format.Substring(i + 1, len));
+ res.Append(langModel.CanonicalName(args[idx]));
+ i = j - 1;
+ continue;
+ }
+ }
+
+ res.Append(c);
+ }
+
+ return res.ToString();
+ }
+
+ public virtual IEnumerable<Model.Element> Dependencies
+ {
+ get { return args; }
+ }
+ }
+
+}
diff --git a/Source/ModelViewer/Properties/AssemblyInfo.cs b/Source/ModelViewer/Properties/AssemblyInfo.cs
index 0cb39b63..033d856d 100644
--- a/Source/ModelViewer/Properties/AssemblyInfo.cs
+++ b/Source/ModelViewer/Properties/AssemblyInfo.cs
@@ -1,25 +1,25 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ModelViewer")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft")]
-[assembly: AssemblyProduct("ModelViewer")]
-[assembly: AssemblyCopyright("Copyright © Microsoft 2010-2011")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("fb95289d-cd57-47f2-aafa-d9e39f46555e")]
-
-
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ModelViewer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("ModelViewer")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010-2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fb95289d-cd57-47f2-aafa-d9e39f46555e")]
+
+
diff --git a/Source/ModelViewer/Properties/Resources.Designer.cs b/Source/ModelViewer/Properties/Resources.Designer.cs
index 2a56d355..933cc4bf 100644
--- a/Source/ModelViewer/Properties/Resources.Designer.cs
+++ b/Source/ModelViewer/Properties/Resources.Designer.cs
@@ -1,63 +1,63 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.1
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie.ModelViewer.Properties {
- using System;
-
-
- /// <summary>
- /// A strongly-typed resource class, for looking up localized strings, etc.
- /// </summary>
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
- }
-
- /// <summary>
- /// Returns the cached ResourceManager instance used by this class.
- /// </summary>
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Boogie.ModelViewer.Properties.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- /// <summary>
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- /// </summary>
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
- }
-}
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie.ModelViewer.Properties {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Boogie.ModelViewer.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Source/ModelViewer/Properties/Resources.resx b/Source/ModelViewer/Properties/Resources.resx
index ffecec85..af7dbebb 100644
--- a/Source/ModelViewer/Properties/Resources.resx
+++ b/Source/ModelViewer/Properties/Resources.resx
@@ -1,117 +1,117 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
- <!--
- Microsoft ResX Schema
-
- Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
- associated with the data types.
-
- Example:
-
- ... ado.net/XML headers & schema ...
- <resheader name="resmimetype">text/microsoft-resx</resheader>
- <resheader name="version">2.0</resheader>
- <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
- <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
- <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
- <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
- <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
- <value>[base64 mime encoded serialized .NET Framework object]</value>
- </data>
- <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
- <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
- <comment>This is a comment</comment>
- </data>
-
- There are any number of "resheader" rows that contain simple
- name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
- mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
- extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
- read any of the formats listed below.
-
- mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
- : System.Serialization.Formatters.Binary.BinaryFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
- : using a System.ComponentModel.TypeConverter
- : and then encoded with base64 encoding.
- -->
- <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xsd:element name="root" msdata:IsDataSet="true">
- <xsd:complexType>
- <xsd:choice maxOccurs="unbounded">
- <xsd:element name="metadata">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" />
- <xsd:attribute name="type" type="xsd:string" />
- <xsd:attribute name="mimetype" type="xsd:string" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="assembly">
- <xsd:complexType>
- <xsd:attribute name="alias" type="xsd:string" />
- <xsd:attribute name="name" type="xsd:string" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="data">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
- <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
- <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="resheader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" />
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>
- <resheader name="resmimetype">
- <value>text/microsoft-resx</value>
- </resheader>
- <resheader name="version">
- <value>2.0</value>
- </resheader>
- <resheader name="reader">
- <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <resheader name="writer">
- <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
</root> \ No newline at end of file
diff --git a/Source/ModelViewer/Properties/Settings.Designer.cs b/Source/ModelViewer/Properties/Settings.Designer.cs
index d210a94e..4b60c7cc 100644
--- a/Source/ModelViewer/Properties/Settings.Designer.cs
+++ b/Source/ModelViewer/Properties/Settings.Designer.cs
@@ -1,26 +1,26 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.1
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie.ModelViewer.Properties {
-
-
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
-
- private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default {
- get {
- return defaultInstance;
- }
- }
- }
-}
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.1
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Boogie.ModelViewer.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Source/ModelViewer/Properties/Settings.settings b/Source/ModelViewer/Properties/Settings.settings
index abf36c5d..39645652 100644
--- a/Source/ModelViewer/Properties/Settings.settings
+++ b/Source/ModelViewer/Properties/Settings.settings
@@ -1,7 +1,7 @@
-<?xml version='1.0' encoding='utf-8'?>
-<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
- <Profiles>
- <Profile Name="(Default)" />
- </Profiles>
- <Settings />
-</SettingsFile>
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
diff --git a/Source/ModelViewer/SourceView.Designer.cs b/Source/ModelViewer/SourceView.Designer.cs
index 55ca2e37..30bc5408 100644
--- a/Source/ModelViewer/SourceView.Designer.cs
+++ b/Source/ModelViewer/SourceView.Designer.cs
@@ -1,63 +1,63 @@
-namespace Microsoft.Boogie.ModelViewer
-{
- partial class SourceView
- {
- /// <summary>
- /// Required designer variable.
- /// </summary>
- private System.ComponentModel.IContainer components = null;
-
- /// <summary>
- /// Clean up any resources being used.
- /// </summary>
- /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- /// <summary>
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- /// </summary>
- private void InitializeComponent()
- {
- this.richTextBox1 = new System.Windows.Forms.RichTextBox();
- this.SuspendLayout();
- //
- // richTextBox1
- //
- this.richTextBox1.DetectUrls = false;
- this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.richTextBox1.Font = new System.Drawing.Font("Lucida Sans Typewriter", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.richTextBox1.HideSelection = false;
- this.richTextBox1.Location = new System.Drawing.Point(0, 0);
- this.richTextBox1.Name = "richTextBox1";
- this.richTextBox1.ReadOnly = true;
- this.richTextBox1.Size = new System.Drawing.Size(715, 582);
- this.richTextBox1.TabIndex = 0;
- this.richTextBox1.Text = "#include <vcc.h>\n\nint main()\n{\n\\foo\n}";
- this.richTextBox1.WordWrap = false;
- //
- // SourceView
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(715, 582);
- this.Controls.Add(this.richTextBox1);
- this.Name = "SourceView";
- this.Text = "SourceView";
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.RichTextBox richTextBox1;
- }
+namespace Microsoft.Boogie.ModelViewer
+{
+ partial class SourceView
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+ this.SuspendLayout();
+ //
+ // richTextBox1
+ //
+ this.richTextBox1.DetectUrls = false;
+ this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.richTextBox1.Font = new System.Drawing.Font("Lucida Sans Typewriter", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.richTextBox1.HideSelection = false;
+ this.richTextBox1.Location = new System.Drawing.Point(0, 0);
+ this.richTextBox1.Name = "richTextBox1";
+ this.richTextBox1.ReadOnly = true;
+ this.richTextBox1.Size = new System.Drawing.Size(715, 582);
+ this.richTextBox1.TabIndex = 0;
+ this.richTextBox1.Text = "#include <vcc.h>\n\nint main()\n{\n\\foo\n}";
+ this.richTextBox1.WordWrap = false;
+ //
+ // SourceView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(715, 582);
+ this.Controls.Add(this.richTextBox1);
+ this.Name = "SourceView";
+ this.Text = "SourceView";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.RichTextBox richTextBox1;
+ }
} \ No newline at end of file
diff --git a/Source/ModelViewer/SourceView.cs b/Source/ModelViewer/SourceView.cs
index d520ede5..a40950b6 100644
--- a/Source/ModelViewer/SourceView.cs
+++ b/Source/ModelViewer/SourceView.cs
@@ -1,52 +1,52 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- public partial class SourceView : Form
- {
- public bool largeFont;
- bool prevLarge;
-
- public SourceView()
- {
- InitializeComponent();
- //richTextBox1.Font = new Font(richTextBox1.Font.FontFamily, fontSize, richTextBox1.Font.Unit);
- richTextBox1.BackColor = Color.White;
- }
-
- string prevRtf;
-
- string prefix =
- @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Lucida Sans Typewriter;}}\r\n" +
- @"{\colortbl;\red0\green0\blue0;\red255\green0\blue0;\red0\green255\blue0;\red255\green255\blue0;\red0\green0\blue0;\red160\green160\blue160;}" +
- @"\viewkind4\uc1\pard\f0";
-
- internal void SetSourceLocation(SourceViewState r)
- {
- if (r.RichTextContent != prevRtf || prevLarge != largeFont) {
- richTextBox1.Rtf = prefix + (largeFont ? "\\fs30 " : "\\fs17 ") + r.RichTextContent + "\r\n}\r\n";
- prevRtf = r.RichTextContent;
- prevLarge = largeFont;
- }
-
- richTextBox1.Select(r.Location, 9);
-
- this.Text = r.Header;
- this.Show();
- }
-
- protected override void OnClosing(CancelEventArgs e)
- {
- base.OnClosing(e);
- e.Cancel = true;
- Hide();
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ public partial class SourceView : Form
+ {
+ public bool largeFont;
+ bool prevLarge;
+
+ public SourceView()
+ {
+ InitializeComponent();
+ //richTextBox1.Font = new Font(richTextBox1.Font.FontFamily, fontSize, richTextBox1.Font.Unit);
+ richTextBox1.BackColor = Color.White;
+ }
+
+ string prevRtf;
+
+ string prefix =
+ @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Lucida Sans Typewriter;}}\r\n" +
+ @"{\colortbl;\red0\green0\blue0;\red255\green0\blue0;\red0\green255\blue0;\red255\green255\blue0;\red0\green0\blue0;\red160\green160\blue160;}" +
+ @"\viewkind4\uc1\pard\f0";
+
+ internal void SetSourceLocation(SourceViewState r)
+ {
+ if (r.RichTextContent != prevRtf || prevLarge != largeFont) {
+ richTextBox1.Rtf = prefix + (largeFont ? "\\fs30 " : "\\fs17 ") + r.RichTextContent + "\r\n}\r\n";
+ prevRtf = r.RichTextContent;
+ prevLarge = largeFont;
+ }
+
+ richTextBox1.Select(r.Location, 9);
+
+ this.Text = r.Header;
+ this.Show();
+ }
+
+ protected override void OnClosing(CancelEventArgs e)
+ {
+ base.OnClosing(e);
+ e.Cancel = true;
+ Hide();
+ }
+ }
+}
diff --git a/Source/ModelViewer/SourceView.resx b/Source/ModelViewer/SourceView.resx
index 29dcb1b3..1af7de15 100644
--- a/Source/ModelViewer/SourceView.resx
+++ b/Source/ModelViewer/SourceView.resx
@@ -1,120 +1,120 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
- <!--
- Microsoft ResX Schema
-
- Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
- associated with the data types.
-
- Example:
-
- ... ado.net/XML headers & schema ...
- <resheader name="resmimetype">text/microsoft-resx</resheader>
- <resheader name="version">2.0</resheader>
- <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
- <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
- <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
- <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
- <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
- <value>[base64 mime encoded serialized .NET Framework object]</value>
- </data>
- <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
- <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
- <comment>This is a comment</comment>
- </data>
-
- There are any number of "resheader" rows that contain simple
- name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
- mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
- extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
- read any of the formats listed below.
-
- mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
- : using a System.ComponentModel.TypeConverter
- : and then encoded with base64 encoding.
- -->
- <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
- <xsd:element name="root" msdata:IsDataSet="true">
- <xsd:complexType>
- <xsd:choice maxOccurs="unbounded">
- <xsd:element name="metadata">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" />
- </xsd:sequence>
- <xsd:attribute name="name" use="required" type="xsd:string" />
- <xsd:attribute name="type" type="xsd:string" />
- <xsd:attribute name="mimetype" type="xsd:string" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="assembly">
- <xsd:complexType>
- <xsd:attribute name="alias" type="xsd:string" />
- <xsd:attribute name="name" type="xsd:string" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="data">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
- <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
- <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="resheader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" />
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>
- <resheader name="resmimetype">
- <value>text/microsoft-resx</value>
- </resheader>
- <resheader name="version">
- <value>2.0</value>
- </resheader>
- <resheader name="reader">
- <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <resheader name="writer">
- <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
</root> \ No newline at end of file
diff --git a/Source/ModelViewer/TreeSkeleton.cs b/Source/ModelViewer/TreeSkeleton.cs
index 543788a8..c3dee44f 100644
--- a/Source/ModelViewer/TreeSkeleton.cs
+++ b/Source/ModelViewer/TreeSkeleton.cs
@@ -1,205 +1,205 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Microsoft.Boogie.ModelViewer
-{
- internal class SkeletonItem
- {
- readonly string name;
- readonly List<SkeletonItem> children = new List<SkeletonItem>();
- internal readonly IDisplayNode[] displayNodes;
- internal bool[] isPrimary;
- internal readonly SkeletonItem parent;
- internal readonly Main main;
- internal readonly int level;
- internal bool expanded, wasExpanded;
- internal bool isMatch;
-
- public void Iter(Action<SkeletonItem> handler)
- {
- handler(this);
- children.ForEach(u => u.Iter(handler));
- }
-
- public IEnumerable<SkeletonItem> RecChildren
- {
- get
- {
- if (expanded) {
- foreach (var c in children) {
- yield return c;
- foreach (var ch in c.RecChildren)
- yield return ch;
- }
- }
- }
- }
-
- public SkeletonItem[] PopulateRoot(IEnumerable<IState> states)
- {
- var i = 0;
- foreach (var s in states) {
- displayNodes[i++] = new ContainerNode<IDisplayNode>(this.name, x => x, s.Nodes);
- }
-
- return BfsExpand(this);
- }
-
- public SkeletonItem(Main m, int stateCount)
- {
- name = "";
- main = m;
- displayNodes = new IDisplayNode[stateCount];
- isPrimary = new bool[stateCount];
- }
-
- internal SkeletonItem(string n, SkeletonItem par)
- : this(par.main, par.displayNodes.Length)
- {
- parent = par;
- name = n;
- level = par.level + 1;
- }
-
- public bool Expandable
- {
- get {
- if (wasExpanded)
- return children.Count > 0;
- return displayNodes.Any(d => d != null && d.Children.Count() > 0);
- }
- }
-
- public bool Expanded
- {
- get { return expanded; }
- set
- {
- expanded = value;
- if (expanded)
- ComputeChildren();
- }
- }
-
- static SkeletonItem[] BfsExpand(SkeletonItem skel)
- {
- for (int i = 0; i < skel.displayNodes.Length; ++i)
- BfsExpandCore(skel, i);
-
- var workItems = new Stack<SkeletonItem>();
- var allNodes = new List<SkeletonItem>();
- workItems.Push(skel);
-
- while (workItems.Count > 0) {
- var s = workItems.Pop();
- if (!s.isPrimary.Any())
- continue;
- allNodes.Add(s);
- s.children.Iter(workItems.Push);
- }
-
- return allNodes.ToArray();
- }
-
- static void BfsExpandCore(SkeletonItem skel, int idx)
- {
- var visited = new HashSet<Model.Element>();
- var workItems = new Queue<SkeletonItem>();
-
- workItems.Enqueue(skel);
- while (workItems.Count > 0) {
- var s = workItems.Dequeue();
- if (s.displayNodes[idx] == null)
- continue;
- var e = s.displayNodes[idx].Element;
- s.isPrimary[idx] = true;
- if (e != null) {
- if (visited.Contains(e))
- continue;
- visited.Add(e);
- }
- s.ComputeChildren();
- s.children.Iter(workItems.Enqueue);
- }
- }
-
- private void ComputeChildren()
- {
- if (wasExpanded) return;
- wasExpanded = true;
-
- var created = new Dictionary<string, SkeletonItem>();
- var names = new List<IDisplayNode>();
- for (int i = 0; i < displayNodes.Length; ++i) {
- var dn = displayNodes[i];
- if (dn == null) continue;
- foreach (var child in dn.Children) {
- if (child.ViewLevel > main.viewOpts.ViewLevel)
- continue;
- SkeletonItem skelChild;
- var name = child.Name;
- if (!created.TryGetValue(name, out skelChild)) {
- skelChild = new SkeletonItem(child.Name, this);
- created.Add(name, skelChild);
- names.Add(child);
- }
- skelChild.displayNodes[i] = child;
- }
- }
-
- foreach (var name in main.LangModel.SortFields(names)) {
- children.Add(created[name]);
- }
- }
-
- public bool MatchesWords(string[] words, Model.Element[] elts, Model.Element eq, int stateId)
- {
- var node = displayNodes[stateId];
- if (node == null)
- return false;
- var s1 = LongName(stateId).ToLower();
- var s2 = node.Value.ToLower();
-
- if (eq != null && node.Element != eq)
- return false;
-
- foreach (var w in words) {
- if (!s1.Contains(w) && !s2.Contains(w))
- return false;
- }
-
- foreach (var e in elts) {
- if (!node.References.Contains(e))
- return false;
- }
-
- return true;
- }
-
- public string LongName(int stateId)
- {
- var parents = new List<IDisplayNode>();
- for (var curr = this; curr != null; curr = curr.parent) {
- if (curr.parent != null) // skip the root
- parents.Add(curr.displayNodes[stateId]);
- }
- parents.Reverse();
- return main.LangModel.PathName(parents);
- }
-
- public void SyncWith(Dictionary<SkeletonItem, SkeletonItem> mapping, SkeletonItem old)
- {
- mapping[old] = this;
- Expanded = old.Expanded;
- var oldCh = old.children.ToDictionary(c => c.name);
- foreach (var c in children) {
- SkeletonItem oc;
- if (oldCh.TryGetValue(c.name, out oc))
- c.SyncWith(mapping, oc);
- }
- }
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Boogie.ModelViewer
+{
+ internal class SkeletonItem
+ {
+ readonly string name;
+ readonly List<SkeletonItem> children = new List<SkeletonItem>();
+ internal readonly IDisplayNode[] displayNodes;
+ internal bool[] isPrimary;
+ internal readonly SkeletonItem parent;
+ internal readonly Main main;
+ internal readonly int level;
+ internal bool expanded, wasExpanded;
+ internal bool isMatch;
+
+ public void Iter(Action<SkeletonItem> handler)
+ {
+ handler(this);
+ children.ForEach(u => u.Iter(handler));
+ }
+
+ public IEnumerable<SkeletonItem> RecChildren
+ {
+ get
+ {
+ if (expanded) {
+ foreach (var c in children) {
+ yield return c;
+ foreach (var ch in c.RecChildren)
+ yield return ch;
+ }
+ }
+ }
+ }
+
+ public SkeletonItem[] PopulateRoot(IEnumerable<IState> states)
+ {
+ var i = 0;
+ foreach (var s in states) {
+ displayNodes[i++] = new ContainerNode<IDisplayNode>(this.name, x => x, s.Nodes);
+ }
+
+ return BfsExpand(this);
+ }
+
+ public SkeletonItem(Main m, int stateCount)
+ {
+ name = "";
+ main = m;
+ displayNodes = new IDisplayNode[stateCount];
+ isPrimary = new bool[stateCount];
+ }
+
+ internal SkeletonItem(string n, SkeletonItem par)
+ : this(par.main, par.displayNodes.Length)
+ {
+ parent = par;
+ name = n;
+ level = par.level + 1;
+ }
+
+ public bool Expandable
+ {
+ get {
+ if (wasExpanded)
+ return children.Count > 0;
+ return displayNodes.Any(d => d != null && d.Children.Count() > 0);
+ }
+ }
+
+ public bool Expanded
+ {
+ get { return expanded; }
+ set
+ {
+ expanded = value;
+ if (expanded)
+ ComputeChildren();
+ }
+ }
+
+ static SkeletonItem[] BfsExpand(SkeletonItem skel)
+ {
+ for (int i = 0; i < skel.displayNodes.Length; ++i)
+ BfsExpandCore(skel, i);
+
+ var workItems = new Stack<SkeletonItem>();
+ var allNodes = new List<SkeletonItem>();
+ workItems.Push(skel);
+
+ while (workItems.Count > 0) {
+ var s = workItems.Pop();
+ if (!s.isPrimary.Any())
+ continue;
+ allNodes.Add(s);
+ s.children.Iter(workItems.Push);
+ }
+
+ return allNodes.ToArray();
+ }
+
+ static void BfsExpandCore(SkeletonItem skel, int idx)
+ {
+ var visited = new HashSet<Model.Element>();
+ var workItems = new Queue<SkeletonItem>();
+
+ workItems.Enqueue(skel);
+ while (workItems.Count > 0) {
+ var s = workItems.Dequeue();
+ if (s.displayNodes[idx] == null)
+ continue;
+ var e = s.displayNodes[idx].Element;
+ s.isPrimary[idx] = true;
+ if (e != null) {
+ if (visited.Contains(e))
+ continue;
+ visited.Add(e);
+ }
+ s.ComputeChildren();
+ s.children.Iter(workItems.Enqueue);
+ }
+ }
+
+ private void ComputeChildren()
+ {
+ if (wasExpanded) return;
+ wasExpanded = true;
+
+ var created = new Dictionary<string, SkeletonItem>();
+ var names = new List<IDisplayNode>();
+ for (int i = 0; i < displayNodes.Length; ++i) {
+ var dn = displayNodes[i];
+ if (dn == null) continue;
+ foreach (var child in dn.Children) {
+ if (child.ViewLevel > main.viewOpts.ViewLevel)
+ continue;
+ SkeletonItem skelChild;
+ var name = child.Name;
+ if (!created.TryGetValue(name, out skelChild)) {
+ skelChild = new SkeletonItem(child.Name, this);
+ created.Add(name, skelChild);
+ names.Add(child);
+ }
+ skelChild.displayNodes[i] = child;
+ }
+ }
+
+ foreach (var name in main.LangModel.SortFields(names)) {
+ children.Add(created[name]);
+ }
+ }
+
+ public bool MatchesWords(string[] words, Model.Element[] elts, Model.Element eq, int stateId)
+ {
+ var node = displayNodes[stateId];
+ if (node == null)
+ return false;
+ var s1 = LongName(stateId).ToLower();
+ var s2 = node.Value.ToLower();
+
+ if (eq != null && node.Element != eq)
+ return false;
+
+ foreach (var w in words) {
+ if (!s1.Contains(w) && !s2.Contains(w))
+ return false;
+ }
+
+ foreach (var e in elts) {
+ if (!node.References.Contains(e))
+ return false;
+ }
+
+ return true;
+ }
+
+ public string LongName(int stateId)
+ {
+ var parents = new List<IDisplayNode>();
+ for (var curr = this; curr != null; curr = curr.parent) {
+ if (curr.parent != null) // skip the root
+ parents.Add(curr.displayNodes[stateId]);
+ }
+ parents.Reverse();
+ return main.LangModel.PathName(parents);
+ }
+
+ public void SyncWith(Dictionary<SkeletonItem, SkeletonItem> mapping, SkeletonItem old)
+ {
+ mapping[old] = this;
+ Expanded = old.Expanded;
+ var oldCh = old.children.ToDictionary(c => c.name);
+ foreach (var c in children) {
+ SkeletonItem oc;
+ if (oldCh.TryGetValue(c.name, out oc))
+ c.SyncWith(mapping, oc);
+ }
+ }
+ }
+
+}
diff --git a/Source/ModelViewer/VccProvider.cs b/Source/ModelViewer/VccProvider.cs
index ae062c93..345dfda5 100644
--- a/Source/ModelViewer/VccProvider.cs
+++ b/Source/ModelViewer/VccProvider.cs
@@ -1,1526 +1,1526 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Microsoft.Boogie.ModelViewer.Vcc
-{
- public class Provider : ILanguageProvider
- {
- public static Provider Instance = new Provider();
- private Provider() { }
-
- public bool IsMyModel(Model m)
- {
- return m.TryGetFunc("$is_ghost_field") != null && m.TryGetFunc("$fk_vol_version") != null;
- }
-
- public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts)
- {
- var vm = new VccModel(m, opts);
- return vm;
- }
- }
-
- enum DataKind
- {
- Flat,
- PhysPtr,
- SpecPtr,
- Object,
- Ptrset,
- Map
- }
-
- class VccModel : LanguageModel
- {
- public readonly Model.Func f_ptr_to, f_phys_ptr_cast, f_spec_ptr_cast, f_mathint, f_local_value_is, f_spec_ptr_to, f_heap, f_select_field,
- f_select_value, f_field, f_field_type, f_int_to_ptr, f_ptr_to_int, f_ptr, f_map_t, f_select_ptr,
- f_owners, f_closed, f_roots, f_timestamps, f_select_bool, f_select_int, f_is_null, f_good_state,
- f_int_to_version, f_int_to_ptrset, f_set_in0, f_is_ghost_field, f_is_phys_field, f_idx,
- f_is_sequential_field, f_is_volatile_field, f_type_project_0, f_array, f_active_option, f_int_to_field,
- f_blob_type, f_array_emb, f_addr, f_address_root, f_base, f_field_arr_size, f_field_arr_root, f_field_arr_index,
- f_dot, f_prim_emb;
- public readonly Model.Element tp_object, tp_mathint, tp_bool, tp_state, tp_ptrset, tp_heaptp;
- public readonly Model.Element elt_me, elt_null;
- Dictionary<Model.Element, string> typeName = new Dictionary<Model.Element, string>();
- Dictionary<Model.Element, string> literalName = new Dictionary<Model.Element, string>();
- Dictionary<Model.Element, Model.Element> guessedType = new Dictionary<Model.Element,Model.Element>();
- public List<StateNode> states = new List<StateNode>();
- public Dictionary<string, string> localVariableNames = new Dictionary<string, string>();
-
- Dictionary<Model.Element, string> datatypeLongName = new Dictionary<Model.Element, string>();
-
- Dictionary<int, string> fileNameMapping = new Dictionary<int, string>();
-
- public const string selfMarker = "\\self";
- public const int maxDatatypeNameLength = 5;
-
- public VccModel(Model m, ViewOptions opts)
- : base(m, opts)
- {
- f_ptr_to = m.MkFunc("$ptr_to", 1);
- f_spec_ptr_to = m.MkFunc("$spec_ptr_to", 1);
- f_phys_ptr_cast = m.MkFunc("$phys_ptr_cast", 2);
- f_spec_ptr_cast = m.MkFunc("$spec_ptr_cast", 2);
- f_mathint = m.MkFunc("^^mathint", 0);
- f_local_value_is = m.MkFunc("$local_value_is", 5);
- f_heap = m.MkFunc("$heap", 1);
- f_select_field = m.MkFunc("Select_[$field][$ptr]$int", 2);
- f_select_value = m.MkFunc("Select_[$ptr]$int", 2);
- f_select_ptr = m.MkFunc("Select_[$ptr]$ptr", 2);
- f_select_int = m.MkFunc("Select_[$ptr]$int", 2);
- f_select_bool = m.MkFunc("Select_[$ptr]$bool", 2);
- f_owners = m.MkFunc("$f_owner", 1);
- f_closed = m.MkFunc("$f_closed", 1);
- f_roots = m.MkFunc("$roots", 1);
- f_timestamps = m.MkFunc("$f_timestamp", 1);
- f_active_option = m.MkFunc("$f_active_option", 1);
- f_field = m.MkFunc("$field", 1);
- f_field_type = m.MkFunc("$field_type", 1);
- f_int_to_ptr = m.MkFunc("$int_to_ptr", 1);
- f_ptr_to_int = m.MkFunc("$ptr_to_int", 1);
- f_ptr = m.MkFunc("$ptr", 2);
- f_dot = m.MkFunc("$dot", 2);
- f_map_t = m.MkFunc("$map_t", 2);
- f_is_null = m.MkFunc("$is_null", 1);
- f_good_state = m.MkFunc("$good_state", 1);
- f_int_to_version = m.MkFunc("$int_to_version", 1);
- f_int_to_ptrset = m.MkFunc("$int_to_ptrset", 1);
- f_int_to_field = m.MkFunc("$int_to_field", 1);
- f_set_in0 = m.MkFunc("$set_in0", 2);
- f_is_ghost_field = m.MkFunc("$is_ghost_field", 1);
- f_is_phys_field = m.MkFunc("$is_phys_field", 1);
- f_idx = m.MkFunc("$idx", 2);
- f_is_sequential_field = m.MkFunc("$is_sequential_field", 1);
- f_is_volatile_field = m.MkFunc("$is_volatile_field", 1);
- f_type_project_0 = m.MkFunc("$type_project_0", 1);
- f_array = m.MkFunc("$array", 2);
- f_blob_type = m.MkFunc("$blob_type", 1);
- f_array_emb = m.MkFunc("$array_emb", 2);
- f_addr = m.MkFunc("$addr", 1);
- f_base = m.MkFunc("$base", 1);
- f_prim_emb = m.MkFunc("$prim_emb", 1);
- f_address_root = m.MkFunc("$address_root", 2);
- f_field_arr_index = m.MkFunc("$field_arr_index", 1);
- f_field_arr_size = m.MkFunc("$field_arr_size", 1);
- f_field_arr_root = m.MkFunc("$field_arr_root", 1);
-
- tp_bool = m.GetFunc("^^bool").GetConstant();
- tp_mathint = m.GetFunc("^^mathint").GetConstant();
- tp_object = m.GetFunc("^^object").GetConstant();
- tp_state = m.GetFunc("^$#state_t").GetConstant();
- tp_ptrset = m.GetFunc("^$#ptrset").GetConstant();
-
- tp_heaptp = m.MkFunc("$heap_type", 0).GetConstant();
-
- elt_me = m.GetFunc("$me").GetConstant();
- elt_null = m.GetFunc("$null").GetConstant();
-
- literalName[elt_me] = "\\me";
- literalName[elt_null] = "NULL";
- foreach (var tpl in f_phys_ptr_cast.Apps) {
- if (tpl.Args[0] == elt_null)
- literalName[tpl.Result] = "(" + TypeName(tpl.Args[1]) + "*)NULL";
- }
- foreach (var tpl in f_spec_ptr_cast.Apps) {
- if (tpl.Args[0] == elt_null)
- literalName[tpl.Result] = "(" + TypeName(tpl.Args[1]) + "^)NULL";
- }
- foreach (var fn in model.Functions) {
- if (fn.Arity == 0 && fn.Name.StartsWith("l#"))
- literalName[fn.GetConstant()] = ":" + fn.Name.Substring(2);
- }
-
- DecodeFileNames();
- ComputeLocalVariableNames();
-
- foreach (var s in m.States) {
- var sn = new StateNode(this, s);
- sn.SetupVars();
- states.Add(sn);
- }
-
- var allStates = states.ToArray();
- if (allStates.Length == 1 && allStates[0].vars.Count == 0) {
- throw new Exception("This VCC model doesn't contain any variables. Was it saved with the -bvd option?");
- }
- states.Clear();
- var i = 0;
- while (i < allStates.Length) {
- var lastGoodName = allStates[i].State.Name;
-
- var userVars = new HashSet<string>(allStates[i].State.Variables.Where(localVariableNames.ContainsKey));
- i++;
- while (i < allStates.Length) {
- foreach (var v in allStates[i].State.Variables) {
- if (v == "$s" || userVars.Contains(v)) goto stop;
- if (localVariableNames.ContainsKey(v))
- userVars.Add(v);
- }
-
- var curName = TryParseSourceLocation(allStates[i].State.Name);
- if (!IsBadName(curName))
- lastGoodName = allStates[i].State.Name;
- i++;
- }
-
- stop:
-
- var lastState = allStates[i - 1];
- lastState.capturedStateName = lastGoodName;
- lastState.index = states.Count;
- states.Add(lastState);
- lastState.SetupVars();
- }
-
- foreach (var s in states) {
- var elt = s.State.TryGet("$s");
- if (elt != null)
- literalName[elt] = "\\state'" + s.index;
- }
-
- GenerateSourceLocations(states);
- }
-
-
- bool IsBadName(SourceLocation l)
- {
- return l == null || l.Filename.StartsWith("<");
- }
-
- private void ComputeLocalVariableNames()
- {
- var vars = model.States.SelectMany(s => s.Variables).Where(v => v != null).Distinct();
- Func<string, string> simpleName = s => { string dummy; return GetUserVariableNameCore(s, out dummy); };
- var userVars = vars.Where(s => simpleName(s) != null);
- var conflictsName = Conflicts(userVars, simpleName).ToArray();
- Func<string, string> qName = s => { string kind, n = GetUserVariableNameCore(s, out kind); return n + " (" + kind + ")"; };
- var conflictsKind = Conflicts(conflictsName, qName).ToArray();
-
- var conflictsNameH = new HashSet<string>(conflictsName);
- var conflictsKindH = new HashSet<string>(conflictsKind);
-
- foreach (var v in userVars) {
- if (conflictsKindH.Contains(v)) continue;
- if (conflictsNameH.Contains(v))
- localVariableNames[v] = qName(v);
- else
- localVariableNames[v] = simpleName(v);
- }
-
- var idx = 0;
- foreach (var v in conflictsKind) {
- localVariableNames[v] = string.Format("{0} #{1}", qName(v), idx++);
- }
- }
-
- static IEnumerable<A> Conflicts<A, B>(IEnumerable<A> input, Func<A, B> f)
- {
- var revMap = new Dictionary<B, A>();
- var reported = new HashSet<A>();
-
- foreach (var k in input) {
- if (reported.Contains(k)) continue;
- var v = f(k);
- A tmp;
- if (revMap.TryGetValue(v, out tmp) && !tmp.Equals(k)) {
- if (!reported.Contains(tmp)) {
- yield return tmp;
- reported.Add(tmp);
- }
- yield return k;
- reported.Add(k);
- } else {
- revMap[v] = k;
- }
- }
- }
-
- #region Function name scoring
- static string[][] prefixes = new string[][] {
- new string[] { "F#", "$eq.$map", "Q#", },
- new string[] { "F#lambda", },
- new string[] { "$int_to_", "lambda@", "distinct-aux-f", "Select_","Store_", "$select.", "$store.", },
- };
-
- static string[][] totals = new string[][] {
- new string[] {
- "$current_timestamp",
- "$full_stop", "$function_entry", "$ptr_to_i4",
- "$ptr_to_i8", "$ptr_to_u4", "$ptr_to_u8",
- "$span", "$sizeof", "$in_domain",
- "$inv2",
- "$is_claimable",
- "$set_cardinality", "$set_difference", "$set_union",
- "$thread_local", "$unchecked", "$writes_at",
- "$array_range", "$arrays_disjoint",
- "$byte_ptr_subtraction",
- },
-
- new string[] {
- "$addr", "$dot", "$emb0", "$fetch_from_domain", "$in_range_phys_ptr",
- "$in_range_spec_ptr", "$is_sequential_field", "$is_volatile_field",
- "$is_ghost_field", "$is_phys_field", "$is_math_type", "$invok_state",
- "$is_primitive",
- "$spec_ptr_cast",
- "$phys_ptr_cast",
- "$is_null",
- "$in_domain_lab",
- "$inv_lab",
- "$set_in0",
- },
-
- new string[] {
- "$_pow2", "$as_composite_field", "$as_field_with_type", "$as_in_range_t",
- "$as_primitive_field", "$base", "$call_transition", "tickleBool", "Ctor",
- "$mv_state", "$field", "$field_arr_root", "$field_kind", "$field_offset",
- "$field_parent_type", "$field_type", "$file_name_is", "$good_state",
- "$good_state_ext", "$function_arg_type", "$has_field_at0", "$map_domain",
- "$map_range", "$map_t", "$ptr_to", "$ptr_to_i1", "$ptr_to_i2",
- "$ptr_to_u1", "$ptr_to_u2", "$is_unwrapped", "$is_unwrapped_dynamic",
- "$heap", "$closed", "$owner", "$owns", "$modifies", "$post_unwrap",
- "$pow2", "$pre_unwrap", "$ptr", "$is", "$in_range_t", "$roots",
- "$timestamp", "$type_branch", "$type_code_is", "$type_project_0",
- "$typemap", "$set_in_pos", "$updated_owns", "$ver_domain", "$vs_state",
- "$set_singleton",
- "$f_owner", "$f_closed", "$f_timestamps",
- "$local_value_is",
- "$field_arr_ctor",
- "$idx",
- },
- };
-
- string[] state_props = new string[] { };
-
- Dictionary<string, int> functionScores = new Dictionary<string, int>();
-
- int FunctionScore(string name)
- {
- if (functionScores.Count == 0) {
- for (int i = 0; i < totals.Length; ++i)
- foreach (var s in totals[i])
- functionScores[s] = i;
- }
-
- int res;
- if (functionScores.TryGetValue(name, out res))
- return res;
-
- res = -1;
- if (name[0] == '$' && name.EndsWith("_to_int"))
- res = 1;
- else if (name.EndsWith("#frame"))
- res = 2;
- else if (name.Contains("#limited#"))
- res = 2;
- else {
- for (int i = 0; i < prefixes.Length; ++i)
- foreach (var p in prefixes[i])
- if (name.StartsWith(p)) {
- res = i;
- //goto stop;
- }
- //stop: ;
- }
-
- if (res == -1)
- res = 1; // default
-
- functionScores[name] = res;
- return res;
- }
- #endregion
-
- private void DecodeFileNames()
- {
- var fis = model.GetFunc("$file_name_is");
- foreach (var f in model.Functions) {
- if (f.Arity == 0 && f.Name.StartsWith("#file^")) {
- var sb = new StringBuilder();
- var idx = 6;
- var name = f.Name;
- while (idx < name.Length) {
- if (name[idx] == '?') {
- var c = (char)Int32.Parse(name.Substring(idx + 1, 2), System.Globalization.NumberStyles.HexNumber);
- sb.Append(c);
- idx += 3;
- } else {
- sb.Append(name[idx++]);
- }
- }
- name = sb.ToString();
-
- foreach (var app in fis.AppsWithArg(1, f.GetConstant()))
- fileNameMapping[app.Args[0].AsInt()] = name;
- }
- }
- }
-
- private Model.Element DecodeDT(string dt)
- {
- if (dt.StartsWith("dt")) {
- var tpName = dt.Replace("dt", "#distTp");
- var f = model.TryGetFunc(tpName);
- if (f != null) {
- return f.GetConstant();
- //var res = f_type_project_0.TryEval(ptr);
- //if (res != null)
- // tp = res;
- }
- }
- return null;
- }
-
- private string DecodeToken(string name, ref Model.Element tp)
- {
- var idx = name.LastIndexOf("$");
- if (idx < 0) return null;
- var words = name.Substring(idx + 1).Split('.', '^', '!', '#', '@');
- if (words.Length > 3)
- tp = DecodeDT(words[3]);
- return string.Format("{0}({1},{2})", fileNameMapping[int.Parse(words[0])], words[1], words[2]);
- }
-
- public string GetUserVariableName(string name)
- {
- string res;
- localVariableNames.TryGetValue(name, out res);
- return res;
- }
-
-
- string GetUserVariableNameCore(string name, out string kind)
- {
- if (name.StartsWith("L#")) {
- kind = "local";
- return name.Substring(2);
- }
-
- if (name.StartsWith("P#")) {
- kind = "in-param";
- return name.Substring(2);
- }
-
- if (name.StartsWith("OP#")) {
- kind = "out-param";
- return name.Substring(3);
- }
-
- if (name.StartsWith("SL#")) {
- kind = "spec local";
- return name.Substring(3);
- }
-
- if (name.StartsWith("SP#")) {
- kind = "spec in-param";
- return name.Substring(3);
- }
-
- if (name.StartsWith("local.")) {
- kind = "param copied to local";
- return name.Substring(6);
- }
-
- if (name.StartsWith("addr.")) {
- kind = "stack-allocated struct";
- return name.Substring(5);
- }
-
- if (name == "$result") {
- kind = "function return value";
- return "\\result";
- }
-
- if (name.StartsWith("res__") && viewOpts.ViewLevel >= 1) {
- kind = "call result";
- return name;
- }
-
- if (name == "$s" && viewOpts.ViewLevel >= 1) {
- kind = "current state";
- return "\\now";
- }
-
- kind = null;
- return null;
- }
-
-
- private string LiteralName(Model.Element elt)
- {
- string r;
-
- if (literalName.TryGetValue(elt, out r))
- return r;
-
- r = TryTypeName(elt);
- if (r != null) {
- literalName[elt] = r;
- return r;
- }
-
- var i = elt as Model.Integer;
- if (i != null)
- return AsPow2(i);
-
- var bv = elt as Model.BitVector;
- if (bv != null)
- return bv.Numeral + "bv" + bv.Size.ToString();
-
- return null;
- }
-
- public Model.Element LocalType(string localName)
- {
- string dummy;
- var v = GetUserVariableNameCore(localName, out dummy);
- if (v == null) v = localName;
- var c = model.TryGetFunc("#loc." + v);
- if (c != null) {
- var localIs = f_local_value_is.AppWithArg(2, c.GetConstant());
- if (localIs != null)
- return localIs.Args[4];
- }
- foreach (var s in model.States.Reverse()) {
- var val = s.TryGet(localName);
- var tp = GuessType(val);
- if (tp != tp_mathint)
- return tp;
- }
- return tp_mathint;
- }
-
- public Model.Element Image(Model.Element elt, Model.Func f)
- {
- var r = f.AppWithResult(elt);
- if (r != null)
- return r.Args[0];
- return null;
- }
-
- string TypeNameCore(Model.Element elt)
- {
- var deref = Image(elt, f_ptr_to);
- if (deref != null)
- return TypeName(deref) + "*";
- deref = Image(elt, f_spec_ptr_to);
- if (deref != null)
- return TypeName(deref) + "^";
- deref = Image(elt, f_blob_type);
- if (deref != null)
- return "_(blob " + CanonicalName(deref) + ")";
- var mapt = f_map_t.AppWithResult(elt);
- if (mapt != null)
- return string.Format("{1}[{0}]", TypeName(mapt.Args[0]), TypeName(mapt.Args[1]));
-
- var arr = f_array.AppWithResult(elt);
- if (arr != null) {
- return string.Format("{0}[{1}]", TypeName(arr.Args[0]), arr.Args[1].ToString());
- }
-
- foreach (var app in elt.Names)
- if (app.Func.Arity == 0 && app.Func.Name.StartsWith("^")) {
- var n = app.Func.Name.Substring(1);
- switch (n) {
- case "^i1": return "int8_t";
- case "^u1": return "uint8_t";
- case "^i2": return "int16_t";
- case "^u2": return "uint16_t";
- case "^i4": return "int32_t";
- case "^u4": return "uint32_t";
- case "^i8": return "int64_t";
- case "^u8": return "uint64_t";
- case "^bool": return "bool";
- default:
- var pref = "_vcc_math_type_";
- if (n.StartsWith(pref)) n = n.Substring(pref.Length);
- return n;
- }
- }
-
- return null;
- }
-
- public string TypeName(Model.Element elt)
- {
- var r = TryTypeName(elt);
- if (r == null)
- return elt.ToString();
- else return r;
- }
-
- public string TryTypeName(Model.Element elt)
- {
- string res;
- if (!typeName.TryGetValue(elt, out res)) {
- typeName[elt] = elt.ToString(); // avoid infinite recursion
- res = TypeNameCore(elt);
- typeName[elt] = res;
- }
- return res;
- }
-
- public static readonly string[] synthethic_fields = new string[] { "$f_owns", "$f_ref_cnt", "$f_vol_version", "$f_root", "$f_group_root", "$f_active_option" };
-
- public string ConstantFieldName(Model.Element elt)
- {
- string res;
- IsConstantField(elt, out res);
- return res;
- }
-
- public bool IsConstantField(Model.Element elt)
- {
- string dummy;
- return IsConstantField(elt, out dummy);
- }
-
- public bool IsConstantField(Model.Element elt, out string theName)
- {
- var bestScore = int.MinValue;
- string bestName = null;
-
- foreach (var t in elt.Names) {
- var score = int.MinValue;
- string name = null;
- if (t.Args.Length == 0) {
- name = t.Func.Name;
- score = 0;
- var dotIdx = name.IndexOf('.');
- if (dotIdx > 0) {
- score += 10;
- name = name.Substring(dotIdx + 1);
- }
- if (name.Contains('#')) score -= 1;
- } else if (t.Func.Name.StartsWith("$f_") && synthethic_fields.Contains(t.Func.Name)) {
- name = string.Format("{0}<{1}>", t.Func.Name.Substring(3).Replace("root", "alloc_root"), TypeName(t.Args[0]));
- score = 6;
- } else if (t.Func == f_array_emb) {
- name = string.Format("[0] (of {0}[{1}])", TypeName(t.Args[0]), t.Args[1].ToString());
- score = 5;
- }
- if (score > bestScore) {
- bestScore = score;
- bestName = name;
- }
- }
-
- theName = bestName;
- return bestScore >= 5;
- }
-
- bool IsSomeState(Model.Element elt)
- {
- var tp = GuessType(elt);
- return tp == tp_state || tp == tp_heaptp;
- }
-
- bool IsThisState(Model.Element st, Model.Element elt)
- {
- return elt == st || elt == f_heap.TryEval(st);
- }
-
- Model.Element GuessType(Model.Element element)
- {
- Model.Element res;
- if (!guessedType.TryGetValue(element, out res)) {
- res = GuessTypeCore(element);
- guessedType[element] = res;
- }
- return res;
- }
-
- Model.Element GuessTypeCore(Model.Element element)
- {
- if (element is Model.Boolean)
- return tp_bool;
-
- var fld = f_field.TryEval(element);
- if (fld != null) {
- var tp = f_field_type.TryEval(fld);
- if (tp != null) {
- var ptp = f_ptr_to.TryEval(tp);
- if (ptp != null)
- return ptp;
- ptp = f_spec_ptr_to.TryEval(tp);
- if (ptp != null)
- return ptp;
- }
- return tp_object;
- }
-
- foreach (var tpl in element.References) {
- if (element == tpl.Result) {
- if (tpl.Func == f_ptr)
- return tp_object;
- if (tpl.Func == f_heap)
- return tp_heaptp;
- }
-
- if (tpl.Args.Length >= 1 && tpl.Args[0] == element) {
- if (tpl.Func == f_heap || tpl.Func == f_closed || tpl.Func == f_good_state)
- return tp_state;
- }
-
- if (tpl.Func == f_select_bool)
- if (tpl.Args[0] == element)
- return tp_ptrset;
- else if (tpl.Args[1] == element)
- return tp_object;
-
- var fname = tpl.Func.Name;
-
- if (tpl.Args.Length == 2 && tpl.Args[0] == element && fname.StartsWith("$select.$map_t")) {
- var mt = model.TryGetFunc("MT#" + fname);
- if (mt != null && mt.Arity == 0)
- return mt.GetConstant();
- var t1 = GuessType(tpl.Args[1]);
- var t2 = GuessType(tpl.Result);
- var t = f_map_t.TryEval(t1, t2);
- if (t != null)
- return t;
- }
-
- var tpName = DataTypeName(element, tpl);
- if (tpName != null) {
- var tp = model.TryGetFunc("^$#" + tpName);
- if (tp != null)
- return tp.GetConstant();
- }
- }
-
- return tp_mathint;
- }
-
- string DataTypeName(Model.Element elt, Model.FuncTuple tpl)
- {
- var fname = tpl.Func.Name;
- if (tpl.Args.Length == 1 && tpl.Args[0] == elt && fname.StartsWith("RF#")) {
- var fldName = tpl.Func.Name.Substring(3);
- var idx = fldName.LastIndexOf('.');
- if (idx > 0) {
- return fldName.Substring(0, idx).Replace("_vcc_math_type_", "");
- }
- }
-
- if (tpl.Args.Length == 1 && tpl.Args[0] == elt && (fname.StartsWith("DSZ#") || fname.StartsWith("RSZ#") || fname.StartsWith("DGH#"))) {
- return fname.Substring(4).Replace("_vcc_math_type_", "");
- }
- return null;
- }
-
- public DataKind GetKind(Model.Element tp, out Model.FuncTuple tpl)
- {
- tpl = null;
-
- if (tp == tp_object)
- return DataKind.Object;
- else if (tp == tp_ptrset)
- return DataKind.Ptrset;
-
- tpl = f_ptr_to.AppWithResult(tp);
- if (tpl != null) return DataKind.PhysPtr;
- tpl = f_spec_ptr_to.AppWithResult(tp);
- if (tpl != null) return DataKind.SpecPtr;
- tpl = f_map_t.AppWithResult(tp);
- if (tpl != null) return DataKind.Map;
-
- return DataKind.Flat;
- }
-
- public DataKind GetKind(Model.Element tp)
- {
- Model.FuncTuple dummy;
- return GetKind(tp, out dummy);
- }
-
-
- public Model.Element WrapForUse(Model.Element elt, Model.Element tp)
- {
- Model.FuncTuple tpl;
- var kind = GetKind(tp, out tpl);
-
- if (kind == DataKind.Flat) {
- if (elt.Kind == Model.ElementKind.Integer) {
- var tpname = TypeName(tp);
- if(tpname.StartsWith("$")) tpname = tpname.Substring(1);
- if (tpname.StartsWith("#")) {
- foreach (var tupl in elt.References) {
- if (tupl.Args.Length == 1 && tupl.Args[0] == elt && tupl.Func.Name.StartsWith("$int_to_") && tupl.Func.Name.EndsWith(tpname)) {
- return tupl.Result;
- }
- }
- }
- }
- return elt;
- }
-
- if (kind == DataKind.Map) {
- if (elt.Kind == Model.ElementKind.Integer) {
- Model.Element theMap = null;
- foreach (var conv in model.Functions)
- // really, we should reconstruct the name of this function, but this is painful
- if (conv.Arity == 1 && conv.Name.StartsWith("$int_to_map_t")) {
- var app = conv.AppWithArg(0, elt);
- if (app != null) {
- theMap = app.Result;
- break;
- }
- }
- if (theMap == null) return elt;
- return theMap;
- }
- return elt;
- } else if (kind == DataKind.Ptrset) {
- var tmp = f_int_to_ptrset.TryEval(elt);
- if (tmp != null)
- return tmp;
- return elt;
- }
-
- if (kind == DataKind.PhysPtr || kind == DataKind.SpecPtr || kind == DataKind.Object) {
- if (elt.Kind == Model.ElementKind.Integer) {
- var tmp = f_int_to_ptr.TryEval(elt);
- if (tmp != null)
- elt = tmp;
- }
- }
-
- if (kind == DataKind.Object)
- return elt;
-
- if (kind == DataKind.PhysPtr)
- return Util.OrElse(f_phys_ptr_cast.TryEval(elt, tpl.Args[0]), elt);
-
- if (kind == DataKind.SpecPtr)
- return Util.OrElse(f_spec_ptr_cast.TryEval(elt, tpl.Args[0]), elt);
-
- Util.Assert(false);
- return elt;
- }
-
- void AddSpecialField(StateNode state, Model.Element elt, List<ElementNode> res, string name, Model.Func select_map)
- {
- if (elt == null) return;
-
- var map = state.State.TryGet("$s");
- if (map != null)
- map = select_map.TryEval(map);
- if (map != null) {
- var model = elt.Model;
- Model.Element val = f_select_bool.TryEval(map, elt);
- Model.Element tp = tp_bool;
- if (val == null) {
- val = f_select_ptr.TryEval(map, elt);
- tp = tp_object;
- }
- if (val == null) {
- val = f_select_int.TryEval(map, elt);
- tp = tp_mathint;
- }
- if (val != null) {
- res.Add(new FieldNode(state, new EdgeName(name), val, tp) { Category = NodeCategory.MethodologyProperty });
- }
- }
- }
-
- void AddPointerFunction(StateNode state, Model.Element elt, List<ElementNode> res, string name, Model.Func fn, Model.Element tp)
- {
- if (elt == null) return;
-
- var val = fn.TryEval(elt);
- if (val != null) {
- res.Add(new FieldNode(state, new EdgeName(name), val, tp) { Category = NodeCategory.MethodologyProperty });
- }
- }
-
- void AddPtrType(StateNode state, Model.Element elt, List<ElementNode> res)
- {
- var f = f_field.TryEval(elt);
- if (f == null) return;
-
- var tp = f_field_type.TryEval(f);
-
- var seq = "";
-
- var is_seq = f_is_sequential_field.TryEval(f) as Model.Boolean;
- var is_vol = f_is_volatile_field.TryEval(f) as Model.Boolean;
-
- if (is_seq != null && is_vol != null && is_seq.Value == is_vol.Value) {
- seq = " (volatile/sequential mismatch)";
- } else if ((is_seq != null && is_seq.Value) || (is_vol != null && !is_vol.Value)) {
- seq = " (sequential)";
- } else if ((is_seq != null && !is_seq.Value) || (is_vol != null && is_vol.Value)) {
- seq = " (volatile)";
- }
-
- if (tp != null || seq != "") {
- res.Add(new FieldNode(state, new EdgeName("\\typeof" + seq), tp, tp_mathint) { Category = NodeCategory.MethodologyProperty });
- }
- }
-
- string SkolemName(Model.Func f, ref Model.Element tp)
- {
- if (f.Name.IndexOf('!') > 0) {
- var tok = DecodeToken(f.Name, ref tp);
- if (tok != null) {
- var baseName = f.Name.Substring(0, f.Name.LastIndexOf('$'));
- if (baseName.StartsWith("Q#"))
- baseName = baseName.Substring(2);
- return string.Format("{0}@{1}", baseName, ShortenToken(tok, 10, false));
- }
- }
- return null;
- }
-
- string GlobalName(Model.Func f, ref Model.Element tp)
- {
- if (f.Name.StartsWith("G#")) {
- var idx = f.Name.LastIndexOf("#dt");
- if (idx < 0) return null;
- var name = f.Name.Substring(2, idx - 2);
- tp = DecodeDT(f.Name.Substring(idx + 1));
- return string.Format("::{0}", name);
- }
- return null;
- }
-
-
- public IEnumerable<ElementNode> CommonNodes(StateNode state)
- {
- var skolems = new List<ElementNode>();
-
- Model.Element tp = null;
-
- foreach (var f in model.Functions) {
- if (f.Arity != 0) continue;
- var s = SkolemName(f, ref tp);
- if (s == null)
- s = GlobalName(f, ref tp);
- if (s != null) {
- if (tp == null)
- tp = GuessType(f.GetConstant());
- var val = WrapForUse(f.GetConstant(), tp);
- skolems.Add(new VariableNode(state, s, val, tp));
- }
- }
-
- return skolems;
- }
-
- private Model.Element GuessPtrTo(Model.Element tp)
- {
- var p = f_ptr_to.TryEval(tp);
- if (p != null) return p;
- p = f_spec_ptr_to.TryEval(tp);
- if (p != null) return p;
- var nm = model.MkFunc("*ptrto_" + TypeName(tp), 0).GetConstant();
- f_ptr_to.AddApp(nm, tp);
- return f_ptr_to.TryEval(tp);
- }
-
- private Model.Element PtrTo(Model.Element tp, Model.Func f_ptr_to)
- {
- var p = f_ptr_to.TryEval(tp);
- if (p != null) return p;
- var nm = model.MkFunc("*" + f_ptr_to.Name + "_" + TypeName(tp), 0).GetConstant();
- f_ptr_to.AddApp(nm, tp);
- return f_ptr_to.TryEval(tp);
- }
-
- private bool IsArrayField(Model.Element ptr)
- {
- return ptr != null && f_idx.TryEval(ptr, model.TryMkElement("0")) != null;
- }
-
- public IEnumerable<ElementNode> GetExpansion(StateNode state, Model.Element elt, Model.Element tp)
- {
- List<ElementNode> result = new List<ElementNode>();
- Model.FuncTuple tpl;
-
- if (elt == null) return result;
-
- var kind = GetKind(tp, out tpl);
- if (kind == DataKind.PhysPtr || kind == DataKind.SpecPtr || kind == DataKind.Object) {
- var heap = state.State.TryGet("$s");
- if (heap != null)
- heap = f_heap.TryEval(heap);
- var addresses = new HashSet<Model.Element>();
-
- if (heap != null) {
- var basePtr = f_base.TryEval(elt);
- foreach (var fld in f_select_field.AppsWithArg(0, heap)) {
- var val = f_select_value.TryEval(fld.Result, elt);
- if (val != null) {
- var field = fld.Args[1];
- if (!IsConstantField(field) && viewOpts.ViewLevel <= 2)
- continue;
- var addr = f_dot.TryEval(elt, field);
- if (addr != null) addresses.Add(addr);
- var node = ComputeUnionActiveOption(state, elt, val, field);
- if (node != null)
- result.Add(node);
- else
- BuildFieldNode(result, state, addr, field, val, addr);
- }
- }
- //result.Sort(CompareFields);
- }
-
- {
- foreach (var app in f_idx.AppsWithArg(0, elt)) {
- var addr = app.Result;
- Model.Element val = null, atp = tp;
-
- addresses.Add(addr);
-
- foreach (var papp in f_dot.AppsWithResult(addr)) {
- var tmp = f_select_value.OptEval(f_select_field.OptEval(heap, papp.Args[1]), papp.Args[0]);
- if (tmp != null) {
- val = tmp;
- var tt = f_field_type.TryEval(papp.Args[1]);
- if (tt != null) atp = tt;
- }
- }
-
- if (val != null)
- val = WrapForUse(val, atp);
- result.Add(new MapletNode(state, new EdgeName(this, "[%0]", app.Args[1]), val, atp) { Category = NodeCategory.Maplet });
- if (addr != null)
- result.Add(new MapletNode(state, new EdgeName(this, "&[%0]", app.Args[1]), addr, GuessPtrTo(atp)) { Category = NodeCategory.Maplet });
- }
- }
-
- foreach (var ptr in f_dot.AppsWithArg(0, elt)) {
- if (addresses.Contains(ptr.Result)) continue;
- var fld = ptr.Args[1];
- var idx = f_field_arr_index.TryEval(fld);
- if (idx != null) {
- var xtp = f_field_type.TryEval(fld);
- result.Add(new MapletNode(state, new EdgeName(this, "&[%0] of %1", idx, f_field_arr_size.TryEval(fld)), ptr.Result, GuessPtrTo(xtp)) { Category = NodeCategory.Maplet });
- }
- if (!IsConstantField(ptr.Args[1])) continue;
- BuildFieldNode(result, state, ptr.Result, ptr.Args[1], null, ptr.Result);
- }
-
- AddSpecialField(state, elt, result, "\\closed", f_closed);
- AddSpecialField(state, elt, result, "\\owner", f_owners);
- AddSpecialField(state, elt, result, "\\root", f_roots);
- AddSpecialField(state, elt, result, "\\timestamp", f_timestamps);
- AddPointerFunction(state, elt, result, "\\embedding", f_prim_emb, tp_object);
- AddPointerFunction(state, elt, result, "\\addr", f_addr, tp_mathint);
-
- if (viewOpts.ViewLevel >= 1) {
- AddPtrType(state, elt, result);
- AddCasts(state, elt, result);
- var sets = new SetsNode(state, elt);
- if (!sets.IsEmpty)
- result.Add(sets);
- }
-
- } else if (kind == DataKind.Map) {
- var elTp = tpl.Args[1];
- foreach (var sel in model.Functions)
- if (sel.Arity == 2 && sel.Name.StartsWith("$select.$map_t")) {
- foreach (var app in sel.AppsWithArg(0, elt)) {
- var val = WrapForUse(app.Result, elTp);
- var edgname = new EdgeName(this, "[%0]", app.Args[1]);
- result.Add(new MapletNode(state, edgname, val, elTp) { Category = NodeCategory.Maplet });
- }
- }
- } else if (kind == DataKind.Ptrset) {
- foreach (var sel in f_select_bool.AppsWithArg(0, elt)) {
- var edgname = new EdgeName(this, "[%0]", sel.Args[1]);
- result.Add(new MapletNode(state, edgname, sel.Result, tp_bool) { Category = NodeCategory.Maplet });
- }
- } else if (kind == DataKind.Flat) {
- foreach (var tupl in elt.References) {
- if (tupl.Args.Length == 1 && tupl.Args[0] == elt) {
- var fname = tupl.Func.Name;
- var idx = fname.LastIndexOf('.');
- if (fname.StartsWith("RF#") && idx > 0) {
- fname = fname.Substring(idx + 1);
- } else if (fname.StartsWith("DP#p")) {
- fname = fname.Substring(4);
- idx = fname.IndexOf('#');
- if (idx > 0)
- fname = fname.Substring(idx + 1) + "#" + fname.Substring(0, idx);
- } else {
- fname = null;
- }
-
- if (fname != null)
- result.Add(new FieldNode(state, new EdgeName(fname), tupl.Result, GuessType(tupl.Result)) { Category = NodeCategory.SpecField });
- }
- }
- }
-
- if (!(elt is Model.Boolean)) {
- var curState = state.State.TryGet("$s");
-
- foreach (var tupl in elt.References) {
- {
- var seenSelf = false;
- var seenState = false;
- var seenThisState = false;
- var args = tupl.Args;
- for (int i = 0; i < args.Length; ++i) {
- if (args[i] == elt) seenSelf = true;
- if (IsThisState(curState, args[i])) seenThisState = true;
- else if (IsSomeState(args[i])) seenState = true;
- }
- if (!seenSelf) continue; // not looking for aliases (maybe we should?)
- if (seenState && !seenThisState) continue;
- }
-
- var argsFmt = new StringBuilder();
- var name = tupl.Func.Name;
-
- var score = FunctionScore(name);
- if (score >= viewOpts.ViewLevel)
- continue;
-
- var retTp = GuessType(tupl.Result);
- var retVal = tupl.Result;
-
- var cat = NodeCategory.MethodologyProperty;
- if (name.StartsWith("F#")) {
- name = name.Substring(2);
- cat = NodeCategory.UserFunction;
- }
-
- if (name.StartsWith("DF#")) {
- name = name.Substring(3);
- cat = NodeCategory.UserFunction;
- }
-
- if (name.StartsWith("$eq.$"))
- name = "EQ";
-
- {
- Model.Element sktp = null;
- var sk = SkolemName(tupl.Func, ref sktp);
- if (sk != null) {
- name = sk;
- if (sktp != null)
- retVal = WrapForUse(tupl.Result, sktp);
- cat = NodeCategory.Maplet;
- }
- }
-
- {
- argsFmt.Append(name).Append("(");
- var args = new List<Model.Element>();
- foreach (var a in tupl.Args) {
- if (IsThisState(curState, a))
- argsFmt.Append("\\now, ");
- else if (a == elt)
- argsFmt.Append(selfMarker + ", ");
- else {
- argsFmt.AppendFormat("%{0}, ", args.Count);
- args.Add(a);
- }
- }
- argsFmt.Length -= 2;
- argsFmt.Append(")");
- var edgeName = new EdgeName(this, argsFmt.ToString(), args.ToArray());
- result.Add(new MapletNode(state, edgeName, retVal, retTp) { ViewLevel = score, Category = cat });
- }
-
- }
- }
-
- return result;
- }
-
- private FieldNode ComputeUnionActiveOption(StateNode state, Model.Element elt, Model.Element val, Model.Element field)
- {
- if (f_active_option.AppsWithResult(field).FirstOrDefault() != null) {
- var activeOpt = f_dot.OptEval(elt, f_int_to_field.OptEval(val));
- if (activeOpt != null) {
- var nm = ConstantFieldName(field);
- var fieldNode = new FieldNode(state, new EdgeName(nm), activeOpt, GuessType(activeOpt)) { Category = NodeCategory.MethodologyProperty };
- return fieldNode;
- }
- }
- return null;
- }
-
- private void AddCasts(StateNode state, Model.Element elt, List<ElementNode> result)
- {
- foreach (var app in f_phys_ptr_cast.AppsWithArg(0, elt)) {
- if (app.Result != elt)
- result.Add(new MapletNode(state, new EdgeName(this, "(" + TypeName(app.Args[1]) + "*)..."), app.Result, PtrTo(app.Args[1], f_ptr_to)));
- }
- foreach (var app in f_spec_ptr_cast.AppsWithArg(0, elt)) {
- if (app.Result != elt)
- result.Add(new MapletNode(state, new EdgeName(this, "(" + TypeName(app.Args[1]) + "^)..."), app.Result, PtrTo(app.Args[1], f_spec_ptr_to)));
- }
- var addr = f_addr.TryEval(elt);
- if (addr != null) {
- foreach (var app in f_blob_type.Apps) {
- var blob = f_address_root.TryEval(addr, app.Result);
- if (blob != null) {
- result.Add(new MapletNode(state, new EdgeName(this, TypeName(app.Result) + "..."), blob, app.Result));
- }
- }
- }
- }
-
- private void BuildFieldNode(List<ElementNode> result, StateNode state, Model.Element ptr, Model.Element field, Model.Element val, Model.Element addr)
- {
- var ftp = f_field_type.TryEval(field);
- if (val != null)
- val = WrapForUse(val, ftp);
-
- if (IsArrayField(ptr)) {
- val = addr;
- addr = null;
- ftp = GuessPtrTo(ftp);
- }
-
- var nm = ConstantFieldName(field);
- var edgname = nm == null ? field.ToString() : nm;
-
- var cat = NodeCategory.PhysField;
- if (f_is_ghost_field.IsTrue(field))
- cat = NodeCategory.SpecField;
- if (nm != null && nm.Contains("<"))
- cat = NodeCategory.MethodologyProperty;
-
- var fieldNode = new FieldNode(state, new EdgeName(edgname), val, ftp) { Category = cat};
- result.Add(fieldNode);
-
- if (addr != null) {
- result.Add(new FieldNode(state, new EdgeName("&" + edgname), addr, GuessPtrTo(ftp)) { Category = cat });
- }
- }
-
- public override IEnumerable<IState> States
- {
- get
- {
- return states;
- }
- }
-
- private int DataTypeToString(StringBuilder sb, int level, Model.Element elt)
- {
- Model.FuncTuple ctor = null;
- int len = 1;
- string dataTypeType = null;
- foreach (var app in elt.References) {
- var n = app.Func.Name;
- if (app.Result == elt && n.StartsWith("DF#")) {
- ctor = app;
- }
- var tmp = DataTypeName(elt, app);
- if (tmp != null) dataTypeType = tmp;
- }
-
- if (dataTypeType != null) {
- if (ctor != null)
- sb.Append(ctor.Func.Name.Substring(3));
- else
- sb.Append(DataTypeShortName(elt, dataTypeType));
- if (ctor != null && ctor.Args.Length > 0) {
- if (level <= 0) sb.Append("(...)");
- else {
- sb.Append("(");
- for (int i = 0; i < ctor.Args.Length; ++i) {
- if (i != 0) sb.Append(", ");
- len += DataTypeToString(sb, level - 1, ctor.Args[i]);
- }
- sb.Append(")");
- }
- }
- } else {
- sb.Append(CanonicalName(elt));
- }
- return len;
- }
-
- private string DataTypeShortName(Model.Element elt, string tp)
- {
- var baseName = tp;
-
- var hd = model.MkFunc("DGH#" + tp, 1).TryEval(elt);
- if (hd != null) {
- foreach (var nm in hd.References) {
- if (nm.Func.Arity == 0 && nm.Func.Name.StartsWith("DH#"))
- baseName = nm.Func.Name.Substring(3);
- }
- }
-
- return baseName;
- }
-
- private string CanonicalBaseNameCore(string name, Model.Element elt, bool doDatatypes, ref NameSeqSuffix suff)
- {
- var vm = this;
-
- if (name.Contains("[") || name.Contains("'"))
- name = "";
-
- if (name != "")
- return name;
-
- var isNull = false;
- foreach (var tpl in elt.References) {
- var fn = tpl.Func;
- if (fn.Name.StartsWith("$select.$map_t") && fn.Arity == 2 && tpl.Args[0] == elt)
- return "map";
- if (fn.Name.StartsWith("$int_to_map_t") && tpl.Result == elt)
- return "map";
-
- if (fn.Arity >= 1 && tpl.Args[0] == elt) {
- if (fn == f_select_bool)
- return "ptrset";
- }
-
- if (tpl.Result == elt)
- if (fn == f_int_to_version)
- return "version";
-
- if (fn == f_is_null && tpl.Result == model.True)
- isNull = true;
-
- var dtpName = DataTypeName(elt, tpl);
- if (dtpName != null) {
- var sb = new StringBuilder();
- string prev = null;
- datatypeLongName[elt] = "*SELF*"; // in case we recurse (but this shouldn't happen)
- for (int lev = 0; lev < 10; lev++) {
- sb.Length = 0;
- var len = DataTypeToString(sb, lev, elt);
- if (prev == null || len <= maxDatatypeNameLength)
- prev = sb.ToString();
- }
-
- datatypeLongName[elt] = prev;
- suff = NameSeqSuffix.WhenNonZero;
- return prev;
- }
- }
-
- var fld = vm.f_field.TryEval(elt);
- if (fld != null) {
- var tp = vm.f_field_type.TryEval(fld);
- if (tp != null) {
- var n = vm.TryTypeName(tp);
- if (n != null) {
- if (isNull)
- return "(" + n + "*)NULL";
- return n;
- }
- }
- }
-
- return "";
- }
-
- protected override string CanonicalBaseName(Model.Element elt, out NameSeqSuffix suff)
- {
- var lit = this.LiteralName(elt);
- if (lit != null) {
- suff = NameSeqSuffix.None;
- return lit;
- }
- if (datatypeLongName.TryGetValue(elt, out lit)) {
- suff = NameSeqSuffix.WhenNonZero;
- return lit;
- }
-
- var name = base.CanonicalBaseName(elt, out suff);
- name = CanonicalBaseNameCore(name, elt, true, ref suff);
-
- return name;
- }
-
- public override string PathName(IEnumerable<IDisplayNode> path)
- {
- var sb = new StringBuilder();
- foreach (var d in path) {
- var name = d.Name;
- if (name == "") continue; // can that happen?
- if (name.Contains("(") && name.Contains(selfMarker)) {
- var repl = name.Replace(selfMarker, sb.ToString());
- sb.Length = 0;
- sb.Append(repl);
- } else {
- if (sb.Length > 0 && name[0] != '[')
- sb.Append("->");
- sb.Append(d.Name);
- }
- }
-
- return sb.ToString();
- }
- }
-
- class StateNode : NamedState
- {
- internal VccModel vm;
- internal List<VariableNode> vars;
- internal List<ElementNode> commons;
- internal int index;
- internal string capturedStateName;
-
- public StateNode(VccModel parent, Model.CapturedState s)
- : base(s, parent)
- {
- this.capturedStateName = s.Name;
- this.vm = parent;
- }
-
- internal void SetupVars()
- {
- if (vars != null) return;
- vars = new List<VariableNode>();
-
- var names = Util.Empty<string>();
-
- if (vm.states.Count > 0) {
- var prev = vm.states.Last();
- names = prev.vars.Map(v => v.realName);
- }
-
- names = names.Concat(state.Variables).Distinct();
-
- var curVars = state.Variables.ToDictionary(x => x);
- foreach (var v in names) {
- var localName = vm.GetUserVariableName(v);
- if (localName != null) {
- var tp = vm.LocalType(v);
- var val = state.TryGet(v);
- val = vm.WrapForUse(val, tp);
- var vn = new VariableNode(this, v, val, tp) { ShortName = localName };
- vn.updatedHere = vm.states.Count > 0 && curVars.ContainsKey(v);
- if (curVars.ContainsKey(v))
- vm.RegisterLocalValue(vn.Name, val);
- vars.Add(vn);
- }
- }
-
- vm.Flush(vars);
-
- commons = new List<ElementNode>();
- commons.AddRange(vm.CommonNodes(this));
- }
-
- public override IEnumerable<IDisplayNode> Nodes
- {
- get {
- return vars.Concat(commons);
- }
- }
-
- public override string CapturedStateName
- {
- get
- {
- return this.capturedStateName;
- }
- }
- }
-
- class ElementNode : DisplayNode
- {
- protected StateNode stateNode;
- protected Model.Element tp;
- protected VccModel vm { get { return stateNode.vm; } }
-
- public ElementNode(StateNode st, EdgeName name, Model.Element elt, Model.Element tp)
- : base(st.vm, name, elt)
- {
- this.stateNode = st;
- this.tp = tp;
- }
-
- protected override void ComputeChildren()
- {
- children.AddRange(vm.GetExpansion(stateNode, element, tp));
- }
-
- public override string ToolTip
- {
- get
- {
- var sb = new StringBuilder();
- if (tp != null)
- sb.AppendFormat("Type: {0}\n", vm.TypeName(tp));
- var i = element as Model.Integer;
- if (i != null) {
- var n = System.Numerics.BigInteger.Parse(i.Numeral);
- sb.AppendFormat("Value: {0} (0x{1:x})\n", n, n);
- } else if (element != null) {
- sb.AppendFormat("Value: {0}\n", element);
- }
- return sb.ToString();
- }
- }
- }
-
- class SetsNode : ElementNode
- {
- List<Model.Element> refs = new List<Model.Element>();
-
- public SetsNode(StateNode par, Model.Element elt)
- : base(par, new EdgeName("\\in ..."), null, null)
- {
- children = new List<IDisplayNode>();
- foreach (var app in vm.f_select_bool.AppsWithArg(1, elt)) {
- children.Add(
- new MapletNode(par, new EdgeName(vm, VccModel.selfMarker + " \\in %0", app.Args[0]), app.Result, vm.tp_bool) { Category = NodeCategory.MethodologyProperty });
- refs.Add(app.Args[0]);
- }
- Category = NodeCategory.MethodologyProperty;
- }
-
- public override IEnumerable<Model.Element> References
- {
- get
- {
- return refs;
- }
- }
-
- public bool IsEmpty { get { return children.Count == 0; } }
- }
-
-
- class FieldNode : ElementNode
- {
- public FieldNode(StateNode par, EdgeName realName, Model.Element elt, Model.Element tp)
- : base(par, realName, elt, tp)
- {
- }
- }
-
- class MapletNode : ElementNode
- {
- public MapletNode(StateNode par, EdgeName realName, Model.Element elt, Model.Element tp)
- : base(par, realName, elt, tp)
- {
- }
- }
-
- class VariableNode : ElementNode
- {
- public bool updatedHere;
- public string realName;
-
- public VariableNode(StateNode par, string realName, Model.Element elt, Model.Element tp)
- : base(par, new EdgeName(realName), elt, tp)
- {
- this.realName = realName;
- }
-
- public override string ShortName
- {
- set { this.name = new EdgeName(value); }
- get { return this.name.ToString(); }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Boogie.ModelViewer.Vcc
+{
+ public class Provider : ILanguageProvider
+ {
+ public static Provider Instance = new Provider();
+ private Provider() { }
+
+ public bool IsMyModel(Model m)
+ {
+ return m.TryGetFunc("$is_ghost_field") != null && m.TryGetFunc("$fk_vol_version") != null;
+ }
+
+ public ILanguageSpecificModel GetLanguageSpecificModel(Model m, ViewOptions opts)
+ {
+ var vm = new VccModel(m, opts);
+ return vm;
+ }
+ }
+
+ enum DataKind
+ {
+ Flat,
+ PhysPtr,
+ SpecPtr,
+ Object,
+ Ptrset,
+ Map
+ }
+
+ class VccModel : LanguageModel
+ {
+ public readonly Model.Func f_ptr_to, f_phys_ptr_cast, f_spec_ptr_cast, f_mathint, f_local_value_is, f_spec_ptr_to, f_heap, f_select_field,
+ f_select_value, f_field, f_field_type, f_int_to_ptr, f_ptr_to_int, f_ptr, f_map_t, f_select_ptr,
+ f_owners, f_closed, f_roots, f_timestamps, f_select_bool, f_select_int, f_is_null, f_good_state,
+ f_int_to_version, f_int_to_ptrset, f_set_in0, f_is_ghost_field, f_is_phys_field, f_idx,
+ f_is_sequential_field, f_is_volatile_field, f_type_project_0, f_array, f_active_option, f_int_to_field,
+ f_blob_type, f_array_emb, f_addr, f_address_root, f_base, f_field_arr_size, f_field_arr_root, f_field_arr_index,
+ f_dot, f_prim_emb;
+ public readonly Model.Element tp_object, tp_mathint, tp_bool, tp_state, tp_ptrset, tp_heaptp;
+ public readonly Model.Element elt_me, elt_null;
+ Dictionary<Model.Element, string> typeName = new Dictionary<Model.Element, string>();
+ Dictionary<Model.Element, string> literalName = new Dictionary<Model.Element, string>();
+ Dictionary<Model.Element, Model.Element> guessedType = new Dictionary<Model.Element,Model.Element>();
+ public List<StateNode> states = new List<StateNode>();
+ public Dictionary<string, string> localVariableNames = new Dictionary<string, string>();
+
+ Dictionary<Model.Element, string> datatypeLongName = new Dictionary<Model.Element, string>();
+
+ Dictionary<int, string> fileNameMapping = new Dictionary<int, string>();
+
+ public const string selfMarker = "\\self";
+ public const int maxDatatypeNameLength = 5;
+
+ public VccModel(Model m, ViewOptions opts)
+ : base(m, opts)
+ {
+ f_ptr_to = m.MkFunc("$ptr_to", 1);
+ f_spec_ptr_to = m.MkFunc("$spec_ptr_to", 1);
+ f_phys_ptr_cast = m.MkFunc("$phys_ptr_cast", 2);
+ f_spec_ptr_cast = m.MkFunc("$spec_ptr_cast", 2);
+ f_mathint = m.MkFunc("^^mathint", 0);
+ f_local_value_is = m.MkFunc("$local_value_is", 5);
+ f_heap = m.MkFunc("$heap", 1);
+ f_select_field = m.MkFunc("Select_[$field][$ptr]$int", 2);
+ f_select_value = m.MkFunc("Select_[$ptr]$int", 2);
+ f_select_ptr = m.MkFunc("Select_[$ptr]$ptr", 2);
+ f_select_int = m.MkFunc("Select_[$ptr]$int", 2);
+ f_select_bool = m.MkFunc("Select_[$ptr]$bool", 2);
+ f_owners = m.MkFunc("$f_owner", 1);
+ f_closed = m.MkFunc("$f_closed", 1);
+ f_roots = m.MkFunc("$roots", 1);
+ f_timestamps = m.MkFunc("$f_timestamp", 1);
+ f_active_option = m.MkFunc("$f_active_option", 1);
+ f_field = m.MkFunc("$field", 1);
+ f_field_type = m.MkFunc("$field_type", 1);
+ f_int_to_ptr = m.MkFunc("$int_to_ptr", 1);
+ f_ptr_to_int = m.MkFunc("$ptr_to_int", 1);
+ f_ptr = m.MkFunc("$ptr", 2);
+ f_dot = m.MkFunc("$dot", 2);
+ f_map_t = m.MkFunc("$map_t", 2);
+ f_is_null = m.MkFunc("$is_null", 1);
+ f_good_state = m.MkFunc("$good_state", 1);
+ f_int_to_version = m.MkFunc("$int_to_version", 1);
+ f_int_to_ptrset = m.MkFunc("$int_to_ptrset", 1);
+ f_int_to_field = m.MkFunc("$int_to_field", 1);
+ f_set_in0 = m.MkFunc("$set_in0", 2);
+ f_is_ghost_field = m.MkFunc("$is_ghost_field", 1);
+ f_is_phys_field = m.MkFunc("$is_phys_field", 1);
+ f_idx = m.MkFunc("$idx", 2);
+ f_is_sequential_field = m.MkFunc("$is_sequential_field", 1);
+ f_is_volatile_field = m.MkFunc("$is_volatile_field", 1);
+ f_type_project_0 = m.MkFunc("$type_project_0", 1);
+ f_array = m.MkFunc("$array", 2);
+ f_blob_type = m.MkFunc("$blob_type", 1);
+ f_array_emb = m.MkFunc("$array_emb", 2);
+ f_addr = m.MkFunc("$addr", 1);
+ f_base = m.MkFunc("$base", 1);
+ f_prim_emb = m.MkFunc("$prim_emb", 1);
+ f_address_root = m.MkFunc("$address_root", 2);
+ f_field_arr_index = m.MkFunc("$field_arr_index", 1);
+ f_field_arr_size = m.MkFunc("$field_arr_size", 1);
+ f_field_arr_root = m.MkFunc("$field_arr_root", 1);
+
+ tp_bool = m.GetFunc("^^bool").GetConstant();
+ tp_mathint = m.GetFunc("^^mathint").GetConstant();
+ tp_object = m.GetFunc("^^object").GetConstant();
+ tp_state = m.GetFunc("^$#state_t").GetConstant();
+ tp_ptrset = m.GetFunc("^$#ptrset").GetConstant();
+
+ tp_heaptp = m.MkFunc("$heap_type", 0).GetConstant();
+
+ elt_me = m.GetFunc("$me").GetConstant();
+ elt_null = m.GetFunc("$null").GetConstant();
+
+ literalName[elt_me] = "\\me";
+ literalName[elt_null] = "NULL";
+ foreach (var tpl in f_phys_ptr_cast.Apps) {
+ if (tpl.Args[0] == elt_null)
+ literalName[tpl.Result] = "(" + TypeName(tpl.Args[1]) + "*)NULL";
+ }
+ foreach (var tpl in f_spec_ptr_cast.Apps) {
+ if (tpl.Args[0] == elt_null)
+ literalName[tpl.Result] = "(" + TypeName(tpl.Args[1]) + "^)NULL";
+ }
+ foreach (var fn in model.Functions) {
+ if (fn.Arity == 0 && fn.Name.StartsWith("l#"))
+ literalName[fn.GetConstant()] = ":" + fn.Name.Substring(2);
+ }
+
+ DecodeFileNames();
+ ComputeLocalVariableNames();
+
+ foreach (var s in m.States) {
+ var sn = new StateNode(this, s);
+ sn.SetupVars();
+ states.Add(sn);
+ }
+
+ var allStates = states.ToArray();
+ if (allStates.Length == 1 && allStates[0].vars.Count == 0) {
+ throw new Exception("This VCC model doesn't contain any variables. Was it saved with the -bvd option?");
+ }
+ states.Clear();
+ var i = 0;
+ while (i < allStates.Length) {
+ var lastGoodName = allStates[i].State.Name;
+
+ var userVars = new HashSet<string>(allStates[i].State.Variables.Where(localVariableNames.ContainsKey));
+ i++;
+ while (i < allStates.Length) {
+ foreach (var v in allStates[i].State.Variables) {
+ if (v == "$s" || userVars.Contains(v)) goto stop;
+ if (localVariableNames.ContainsKey(v))
+ userVars.Add(v);
+ }
+
+ var curName = TryParseSourceLocation(allStates[i].State.Name);
+ if (!IsBadName(curName))
+ lastGoodName = allStates[i].State.Name;
+ i++;
+ }
+
+ stop:
+
+ var lastState = allStates[i - 1];
+ lastState.capturedStateName = lastGoodName;
+ lastState.index = states.Count;
+ states.Add(lastState);
+ lastState.SetupVars();
+ }
+
+ foreach (var s in states) {
+ var elt = s.State.TryGet("$s");
+ if (elt != null)
+ literalName[elt] = "\\state'" + s.index;
+ }
+
+ GenerateSourceLocations(states);
+ }
+
+
+ bool IsBadName(SourceLocation l)
+ {
+ return l == null || l.Filename.StartsWith("<");
+ }
+
+ private void ComputeLocalVariableNames()
+ {
+ var vars = model.States.SelectMany(s => s.Variables).Where(v => v != null).Distinct();
+ Func<string, string> simpleName = s => { string dummy; return GetUserVariableNameCore(s, out dummy); };
+ var userVars = vars.Where(s => simpleName(s) != null);
+ var conflictsName = Conflicts(userVars, simpleName).ToArray();
+ Func<string, string> qName = s => { string kind, n = GetUserVariableNameCore(s, out kind); return n + " (" + kind + ")"; };
+ var conflictsKind = Conflicts(conflictsName, qName).ToArray();
+
+ var conflictsNameH = new HashSet<string>(conflictsName);
+ var conflictsKindH = new HashSet<string>(conflictsKind);
+
+ foreach (var v in userVars) {
+ if (conflictsKindH.Contains(v)) continue;
+ if (conflictsNameH.Contains(v))
+ localVariableNames[v] = qName(v);
+ else
+ localVariableNames[v] = simpleName(v);
+ }
+
+ var idx = 0;
+ foreach (var v in conflictsKind) {
+ localVariableNames[v] = string.Format("{0} #{1}", qName(v), idx++);
+ }
+ }
+
+ static IEnumerable<A> Conflicts<A, B>(IEnumerable<A> input, Func<A, B> f)
+ {
+ var revMap = new Dictionary<B, A>();
+ var reported = new HashSet<A>();
+
+ foreach (var k in input) {
+ if (reported.Contains(k)) continue;
+ var v = f(k);
+ A tmp;
+ if (revMap.TryGetValue(v, out tmp) && !tmp.Equals(k)) {
+ if (!reported.Contains(tmp)) {
+ yield return tmp;
+ reported.Add(tmp);
+ }
+ yield return k;
+ reported.Add(k);
+ } else {
+ revMap[v] = k;
+ }
+ }
+ }
+
+ #region Function name scoring
+ static string[][] prefixes = new string[][] {
+ new string[] { "F#", "$eq.$map", "Q#", },
+ new string[] { "F#lambda", },
+ new string[] { "$int_to_", "lambda@", "distinct-aux-f", "Select_","Store_", "$select.", "$store.", },
+ };
+
+ static string[][] totals = new string[][] {
+ new string[] {
+ "$current_timestamp",
+ "$full_stop", "$function_entry", "$ptr_to_i4",
+ "$ptr_to_i8", "$ptr_to_u4", "$ptr_to_u8",
+ "$span", "$sizeof", "$in_domain",
+ "$inv2",
+ "$is_claimable",
+ "$set_cardinality", "$set_difference", "$set_union",
+ "$thread_local", "$unchecked", "$writes_at",
+ "$array_range", "$arrays_disjoint",
+ "$byte_ptr_subtraction",
+ },
+
+ new string[] {
+ "$addr", "$dot", "$emb0", "$fetch_from_domain", "$in_range_phys_ptr",
+ "$in_range_spec_ptr", "$is_sequential_field", "$is_volatile_field",
+ "$is_ghost_field", "$is_phys_field", "$is_math_type", "$invok_state",
+ "$is_primitive",
+ "$spec_ptr_cast",
+ "$phys_ptr_cast",
+ "$is_null",
+ "$in_domain_lab",
+ "$inv_lab",
+ "$set_in0",
+ },
+
+ new string[] {
+ "$_pow2", "$as_composite_field", "$as_field_with_type", "$as_in_range_t",
+ "$as_primitive_field", "$base", "$call_transition", "tickleBool", "Ctor",
+ "$mv_state", "$field", "$field_arr_root", "$field_kind", "$field_offset",
+ "$field_parent_type", "$field_type", "$file_name_is", "$good_state",
+ "$good_state_ext", "$function_arg_type", "$has_field_at0", "$map_domain",
+ "$map_range", "$map_t", "$ptr_to", "$ptr_to_i1", "$ptr_to_i2",
+ "$ptr_to_u1", "$ptr_to_u2", "$is_unwrapped", "$is_unwrapped_dynamic",
+ "$heap", "$closed", "$owner", "$owns", "$modifies", "$post_unwrap",
+ "$pow2", "$pre_unwrap", "$ptr", "$is", "$in_range_t", "$roots",
+ "$timestamp", "$type_branch", "$type_code_is", "$type_project_0",
+ "$typemap", "$set_in_pos", "$updated_owns", "$ver_domain", "$vs_state",
+ "$set_singleton",
+ "$f_owner", "$f_closed", "$f_timestamps",
+ "$local_value_is",
+ "$field_arr_ctor",
+ "$idx",
+ },
+ };
+
+ string[] state_props = new string[] { };
+
+ Dictionary<string, int> functionScores = new Dictionary<string, int>();
+
+ int FunctionScore(string name)
+ {
+ if (functionScores.Count == 0) {
+ for (int i = 0; i < totals.Length; ++i)
+ foreach (var s in totals[i])
+ functionScores[s] = i;
+ }
+
+ int res;
+ if (functionScores.TryGetValue(name, out res))
+ return res;
+
+ res = -1;
+ if (name[0] == '$' && name.EndsWith("_to_int"))
+ res = 1;
+ else if (name.EndsWith("#frame"))
+ res = 2;
+ else if (name.Contains("#limited#"))
+ res = 2;
+ else {
+ for (int i = 0; i < prefixes.Length; ++i)
+ foreach (var p in prefixes[i])
+ if (name.StartsWith(p)) {
+ res = i;
+ //goto stop;
+ }
+ //stop: ;
+ }
+
+ if (res == -1)
+ res = 1; // default
+
+ functionScores[name] = res;
+ return res;
+ }
+ #endregion
+
+ private void DecodeFileNames()
+ {
+ var fis = model.GetFunc("$file_name_is");
+ foreach (var f in model.Functions) {
+ if (f.Arity == 0 && f.Name.StartsWith("#file^")) {
+ var sb = new StringBuilder();
+ var idx = 6;
+ var name = f.Name;
+ while (idx < name.Length) {
+ if (name[idx] == '?') {
+ var c = (char)Int32.Parse(name.Substring(idx + 1, 2), System.Globalization.NumberStyles.HexNumber);
+ sb.Append(c);
+ idx += 3;
+ } else {
+ sb.Append(name[idx++]);
+ }
+ }
+ name = sb.ToString();
+
+ foreach (var app in fis.AppsWithArg(1, f.GetConstant()))
+ fileNameMapping[app.Args[0].AsInt()] = name;
+ }
+ }
+ }
+
+ private Model.Element DecodeDT(string dt)
+ {
+ if (dt.StartsWith("dt")) {
+ var tpName = dt.Replace("dt", "#distTp");
+ var f = model.TryGetFunc(tpName);
+ if (f != null) {
+ return f.GetConstant();
+ //var res = f_type_project_0.TryEval(ptr);
+ //if (res != null)
+ // tp = res;
+ }
+ }
+ return null;
+ }
+
+ private string DecodeToken(string name, ref Model.Element tp)
+ {
+ var idx = name.LastIndexOf("$");
+ if (idx < 0) return null;
+ var words = name.Substring(idx + 1).Split('.', '^', '!', '#', '@');
+ if (words.Length > 3)
+ tp = DecodeDT(words[3]);
+ return string.Format("{0}({1},{2})", fileNameMapping[int.Parse(words[0])], words[1], words[2]);
+ }
+
+ public string GetUserVariableName(string name)
+ {
+ string res;
+ localVariableNames.TryGetValue(name, out res);
+ return res;
+ }
+
+
+ string GetUserVariableNameCore(string name, out string kind)
+ {
+ if (name.StartsWith("L#")) {
+ kind = "local";
+ return name.Substring(2);
+ }
+
+ if (name.StartsWith("P#")) {
+ kind = "in-param";
+ return name.Substring(2);
+ }
+
+ if (name.StartsWith("OP#")) {
+ kind = "out-param";
+ return name.Substring(3);
+ }
+
+ if (name.StartsWith("SL#")) {
+ kind = "spec local";
+ return name.Substring(3);
+ }
+
+ if (name.StartsWith("SP#")) {
+ kind = "spec in-param";
+ return name.Substring(3);
+ }
+
+ if (name.StartsWith("local.")) {
+ kind = "param copied to local";
+ return name.Substring(6);
+ }
+
+ if (name.StartsWith("addr.")) {
+ kind = "stack-allocated struct";
+ return name.Substring(5);
+ }
+
+ if (name == "$result") {
+ kind = "function return value";
+ return "\\result";
+ }
+
+ if (name.StartsWith("res__") && viewOpts.ViewLevel >= 1) {
+ kind = "call result";
+ return name;
+ }
+
+ if (name == "$s" && viewOpts.ViewLevel >= 1) {
+ kind = "current state";
+ return "\\now";
+ }
+
+ kind = null;
+ return null;
+ }
+
+
+ private string LiteralName(Model.Element elt)
+ {
+ string r;
+
+ if (literalName.TryGetValue(elt, out r))
+ return r;
+
+ r = TryTypeName(elt);
+ if (r != null) {
+ literalName[elt] = r;
+ return r;
+ }
+
+ var i = elt as Model.Integer;
+ if (i != null)
+ return AsPow2(i);
+
+ var bv = elt as Model.BitVector;
+ if (bv != null)
+ return bv.Numeral + "bv" + bv.Size.ToString();
+
+ return null;
+ }
+
+ public Model.Element LocalType(string localName)
+ {
+ string dummy;
+ var v = GetUserVariableNameCore(localName, out dummy);
+ if (v == null) v = localName;
+ var c = model.TryGetFunc("#loc." + v);
+ if (c != null) {
+ var localIs = f_local_value_is.AppWithArg(2, c.GetConstant());
+ if (localIs != null)
+ return localIs.Args[4];
+ }
+ foreach (var s in model.States.Reverse()) {
+ var val = s.TryGet(localName);
+ var tp = GuessType(val);
+ if (tp != tp_mathint)
+ return tp;
+ }
+ return tp_mathint;
+ }
+
+ public Model.Element Image(Model.Element elt, Model.Func f)
+ {
+ var r = f.AppWithResult(elt);
+ if (r != null)
+ return r.Args[0];
+ return null;
+ }
+
+ string TypeNameCore(Model.Element elt)
+ {
+ var deref = Image(elt, f_ptr_to);
+ if (deref != null)
+ return TypeName(deref) + "*";
+ deref = Image(elt, f_spec_ptr_to);
+ if (deref != null)
+ return TypeName(deref) + "^";
+ deref = Image(elt, f_blob_type);
+ if (deref != null)
+ return "_(blob " + CanonicalName(deref) + ")";
+ var mapt = f_map_t.AppWithResult(elt);
+ if (mapt != null)
+ return string.Format("{1}[{0}]", TypeName(mapt.Args[0]), TypeName(mapt.Args[1]));
+
+ var arr = f_array.AppWithResult(elt);
+ if (arr != null) {
+ return string.Format("{0}[{1}]", TypeName(arr.Args[0]), arr.Args[1].ToString());
+ }
+
+ foreach (var app in elt.Names)
+ if (app.Func.Arity == 0 && app.Func.Name.StartsWith("^")) {
+ var n = app.Func.Name.Substring(1);
+ switch (n) {
+ case "^i1": return "int8_t";
+ case "^u1": return "uint8_t";
+ case "^i2": return "int16_t";
+ case "^u2": return "uint16_t";
+ case "^i4": return "int32_t";
+ case "^u4": return "uint32_t";
+ case "^i8": return "int64_t";
+ case "^u8": return "uint64_t";
+ case "^bool": return "bool";
+ default:
+ var pref = "_vcc_math_type_";
+ if (n.StartsWith(pref)) n = n.Substring(pref.Length);
+ return n;
+ }
+ }
+
+ return null;
+ }
+
+ public string TypeName(Model.Element elt)
+ {
+ var r = TryTypeName(elt);
+ if (r == null)
+ return elt.ToString();
+ else return r;
+ }
+
+ public string TryTypeName(Model.Element elt)
+ {
+ string res;
+ if (!typeName.TryGetValue(elt, out res)) {
+ typeName[elt] = elt.ToString(); // avoid infinite recursion
+ res = TypeNameCore(elt);
+ typeName[elt] = res;
+ }
+ return res;
+ }
+
+ public static readonly string[] synthethic_fields = new string[] { "$f_owns", "$f_ref_cnt", "$f_vol_version", "$f_root", "$f_group_root", "$f_active_option" };
+
+ public string ConstantFieldName(Model.Element elt)
+ {
+ string res;
+ IsConstantField(elt, out res);
+ return res;
+ }
+
+ public bool IsConstantField(Model.Element elt)
+ {
+ string dummy;
+ return IsConstantField(elt, out dummy);
+ }
+
+ public bool IsConstantField(Model.Element elt, out string theName)
+ {
+ var bestScore = int.MinValue;
+ string bestName = null;
+
+ foreach (var t in elt.Names) {
+ var score = int.MinValue;
+ string name = null;
+ if (t.Args.Length == 0) {
+ name = t.Func.Name;
+ score = 0;
+ var dotIdx = name.IndexOf('.');
+ if (dotIdx > 0) {
+ score += 10;
+ name = name.Substring(dotIdx + 1);
+ }
+ if (name.Contains('#')) score -= 1;
+ } else if (t.Func.Name.StartsWith("$f_") && synthethic_fields.Contains(t.Func.Name)) {
+ name = string.Format("{0}<{1}>", t.Func.Name.Substring(3).Replace("root", "alloc_root"), TypeName(t.Args[0]));
+ score = 6;
+ } else if (t.Func == f_array_emb) {
+ name = string.Format("[0] (of {0}[{1}])", TypeName(t.Args[0]), t.Args[1].ToString());
+ score = 5;
+ }
+ if (score > bestScore) {
+ bestScore = score;
+ bestName = name;
+ }
+ }
+
+ theName = bestName;
+ return bestScore >= 5;
+ }
+
+ bool IsSomeState(Model.Element elt)
+ {
+ var tp = GuessType(elt);
+ return tp == tp_state || tp == tp_heaptp;
+ }
+
+ bool IsThisState(Model.Element st, Model.Element elt)
+ {
+ return elt == st || elt == f_heap.TryEval(st);
+ }
+
+ Model.Element GuessType(Model.Element element)
+ {
+ Model.Element res;
+ if (!guessedType.TryGetValue(element, out res)) {
+ res = GuessTypeCore(element);
+ guessedType[element] = res;
+ }
+ return res;
+ }
+
+ Model.Element GuessTypeCore(Model.Element element)
+ {
+ if (element is Model.Boolean)
+ return tp_bool;
+
+ var fld = f_field.TryEval(element);
+ if (fld != null) {
+ var tp = f_field_type.TryEval(fld);
+ if (tp != null) {
+ var ptp = f_ptr_to.TryEval(tp);
+ if (ptp != null)
+ return ptp;
+ ptp = f_spec_ptr_to.TryEval(tp);
+ if (ptp != null)
+ return ptp;
+ }
+ return tp_object;
+ }
+
+ foreach (var tpl in element.References) {
+ if (element == tpl.Result) {
+ if (tpl.Func == f_ptr)
+ return tp_object;
+ if (tpl.Func == f_heap)
+ return tp_heaptp;
+ }
+
+ if (tpl.Args.Length >= 1 && tpl.Args[0] == element) {
+ if (tpl.Func == f_heap || tpl.Func == f_closed || tpl.Func == f_good_state)
+ return tp_state;
+ }
+
+ if (tpl.Func == f_select_bool)
+ if (tpl.Args[0] == element)
+ return tp_ptrset;
+ else if (tpl.Args[1] == element)
+ return tp_object;
+
+ var fname = tpl.Func.Name;
+
+ if (tpl.Args.Length == 2 && tpl.Args[0] == element && fname.StartsWith("$select.$map_t")) {
+ var mt = model.TryGetFunc("MT#" + fname);
+ if (mt != null && mt.Arity == 0)
+ return mt.GetConstant();
+ var t1 = GuessType(tpl.Args[1]);
+ var t2 = GuessType(tpl.Result);
+ var t = f_map_t.TryEval(t1, t2);
+ if (t != null)
+ return t;
+ }
+
+ var tpName = DataTypeName(element, tpl);
+ if (tpName != null) {
+ var tp = model.TryGetFunc("^$#" + tpName);
+ if (tp != null)
+ return tp.GetConstant();
+ }
+ }
+
+ return tp_mathint;
+ }
+
+ string DataTypeName(Model.Element elt, Model.FuncTuple tpl)
+ {
+ var fname = tpl.Func.Name;
+ if (tpl.Args.Length == 1 && tpl.Args[0] == elt && fname.StartsWith("RF#")) {
+ var fldName = tpl.Func.Name.Substring(3);
+ var idx = fldName.LastIndexOf('.');
+ if (idx > 0) {
+ return fldName.Substring(0, idx).Replace("_vcc_math_type_", "");
+ }
+ }
+
+ if (tpl.Args.Length == 1 && tpl.Args[0] == elt && (fname.StartsWith("DSZ#") || fname.StartsWith("RSZ#") || fname.StartsWith("DGH#"))) {
+ return fname.Substring(4).Replace("_vcc_math_type_", "");
+ }
+ return null;
+ }
+
+ public DataKind GetKind(Model.Element tp, out Model.FuncTuple tpl)
+ {
+ tpl = null;
+
+ if (tp == tp_object)
+ return DataKind.Object;
+ else if (tp == tp_ptrset)
+ return DataKind.Ptrset;
+
+ tpl = f_ptr_to.AppWithResult(tp);
+ if (tpl != null) return DataKind.PhysPtr;
+ tpl = f_spec_ptr_to.AppWithResult(tp);
+ if (tpl != null) return DataKind.SpecPtr;
+ tpl = f_map_t.AppWithResult(tp);
+ if (tpl != null) return DataKind.Map;
+
+ return DataKind.Flat;
+ }
+
+ public DataKind GetKind(Model.Element tp)
+ {
+ Model.FuncTuple dummy;
+ return GetKind(tp, out dummy);
+ }
+
+
+ public Model.Element WrapForUse(Model.Element elt, Model.Element tp)
+ {
+ Model.FuncTuple tpl;
+ var kind = GetKind(tp, out tpl);
+
+ if (kind == DataKind.Flat) {
+ if (elt.Kind == Model.ElementKind.Integer) {
+ var tpname = TypeName(tp);
+ if(tpname.StartsWith("$")) tpname = tpname.Substring(1);
+ if (tpname.StartsWith("#")) {
+ foreach (var tupl in elt.References) {
+ if (tupl.Args.Length == 1 && tupl.Args[0] == elt && tupl.Func.Name.StartsWith("$int_to_") && tupl.Func.Name.EndsWith(tpname)) {
+ return tupl.Result;
+ }
+ }
+ }
+ }
+ return elt;
+ }
+
+ if (kind == DataKind.Map) {
+ if (elt.Kind == Model.ElementKind.Integer) {
+ Model.Element theMap = null;
+ foreach (var conv in model.Functions)
+ // really, we should reconstruct the name of this function, but this is painful
+ if (conv.Arity == 1 && conv.Name.StartsWith("$int_to_map_t")) {
+ var app = conv.AppWithArg(0, elt);
+ if (app != null) {
+ theMap = app.Result;
+ break;
+ }
+ }
+ if (theMap == null) return elt;
+ return theMap;
+ }
+ return elt;
+ } else if (kind == DataKind.Ptrset) {
+ var tmp = f_int_to_ptrset.TryEval(elt);
+ if (tmp != null)
+ return tmp;
+ return elt;
+ }
+
+ if (kind == DataKind.PhysPtr || kind == DataKind.SpecPtr || kind == DataKind.Object) {
+ if (elt.Kind == Model.ElementKind.Integer) {
+ var tmp = f_int_to_ptr.TryEval(elt);
+ if (tmp != null)
+ elt = tmp;
+ }
+ }
+
+ if (kind == DataKind.Object)
+ return elt;
+
+ if (kind == DataKind.PhysPtr)
+ return Util.OrElse(f_phys_ptr_cast.TryEval(elt, tpl.Args[0]), elt);
+
+ if (kind == DataKind.SpecPtr)
+ return Util.OrElse(f_spec_ptr_cast.TryEval(elt, tpl.Args[0]), elt);
+
+ Util.Assert(false);
+ return elt;
+ }
+
+ void AddSpecialField(StateNode state, Model.Element elt, List<ElementNode> res, string name, Model.Func select_map)
+ {
+ if (elt == null) return;
+
+ var map = state.State.TryGet("$s");
+ if (map != null)
+ map = select_map.TryEval(map);
+ if (map != null) {
+ var model = elt.Model;
+ Model.Element val = f_select_bool.TryEval(map, elt);
+ Model.Element tp = tp_bool;
+ if (val == null) {
+ val = f_select_ptr.TryEval(map, elt);
+ tp = tp_object;
+ }
+ if (val == null) {
+ val = f_select_int.TryEval(map, elt);
+ tp = tp_mathint;
+ }
+ if (val != null) {
+ res.Add(new FieldNode(state, new EdgeName(name), val, tp) { Category = NodeCategory.MethodologyProperty });
+ }
+ }
+ }
+
+ void AddPointerFunction(StateNode state, Model.Element elt, List<ElementNode> res, string name, Model.Func fn, Model.Element tp)
+ {
+ if (elt == null) return;
+
+ var val = fn.TryEval(elt);
+ if (val != null) {
+ res.Add(new FieldNode(state, new EdgeName(name), val, tp) { Category = NodeCategory.MethodologyProperty });
+ }
+ }
+
+ void AddPtrType(StateNode state, Model.Element elt, List<ElementNode> res)
+ {
+ var f = f_field.TryEval(elt);
+ if (f == null) return;
+
+ var tp = f_field_type.TryEval(f);
+
+ var seq = "";
+
+ var is_seq = f_is_sequential_field.TryEval(f) as Model.Boolean;
+ var is_vol = f_is_volatile_field.TryEval(f) as Model.Boolean;
+
+ if (is_seq != null && is_vol != null && is_seq.Value == is_vol.Value) {
+ seq = " (volatile/sequential mismatch)";
+ } else if ((is_seq != null && is_seq.Value) || (is_vol != null && !is_vol.Value)) {
+ seq = " (sequential)";
+ } else if ((is_seq != null && !is_seq.Value) || (is_vol != null && is_vol.Value)) {
+ seq = " (volatile)";
+ }
+
+ if (tp != null || seq != "") {
+ res.Add(new FieldNode(state, new EdgeName("\\typeof" + seq), tp, tp_mathint) { Category = NodeCategory.MethodologyProperty });
+ }
+ }
+
+ string SkolemName(Model.Func f, ref Model.Element tp)
+ {
+ if (f.Name.IndexOf('!') > 0) {
+ var tok = DecodeToken(f.Name, ref tp);
+ if (tok != null) {
+ var baseName = f.Name.Substring(0, f.Name.LastIndexOf('$'));
+ if (baseName.StartsWith("Q#"))
+ baseName = baseName.Substring(2);
+ return string.Format("{0}@{1}", baseName, ShortenToken(tok, 10, false));
+ }
+ }
+ return null;
+ }
+
+ string GlobalName(Model.Func f, ref Model.Element tp)
+ {
+ if (f.Name.StartsWith("G#")) {
+ var idx = f.Name.LastIndexOf("#dt");
+ if (idx < 0) return null;
+ var name = f.Name.Substring(2, idx - 2);
+ tp = DecodeDT(f.Name.Substring(idx + 1));
+ return string.Format("::{0}", name);
+ }
+ return null;
+ }
+
+
+ public IEnumerable<ElementNode> CommonNodes(StateNode state)
+ {
+ var skolems = new List<ElementNode>();
+
+ Model.Element tp = null;
+
+ foreach (var f in model.Functions) {
+ if (f.Arity != 0) continue;
+ var s = SkolemName(f, ref tp);
+ if (s == null)
+ s = GlobalName(f, ref tp);
+ if (s != null) {
+ if (tp == null)
+ tp = GuessType(f.GetConstant());
+ var val = WrapForUse(f.GetConstant(), tp);
+ skolems.Add(new VariableNode(state, s, val, tp));
+ }
+ }
+
+ return skolems;
+ }
+
+ private Model.Element GuessPtrTo(Model.Element tp)
+ {
+ var p = f_ptr_to.TryEval(tp);
+ if (p != null) return p;
+ p = f_spec_ptr_to.TryEval(tp);
+ if (p != null) return p;
+ var nm = model.MkFunc("*ptrto_" + TypeName(tp), 0).GetConstant();
+ f_ptr_to.AddApp(nm, tp);
+ return f_ptr_to.TryEval(tp);
+ }
+
+ private Model.Element PtrTo(Model.Element tp, Model.Func f_ptr_to)
+ {
+ var p = f_ptr_to.TryEval(tp);
+ if (p != null) return p;
+ var nm = model.MkFunc("*" + f_ptr_to.Name + "_" + TypeName(tp), 0).GetConstant();
+ f_ptr_to.AddApp(nm, tp);
+ return f_ptr_to.TryEval(tp);
+ }
+
+ private bool IsArrayField(Model.Element ptr)
+ {
+ return ptr != null && f_idx.TryEval(ptr, model.TryMkElement("0")) != null;
+ }
+
+ public IEnumerable<ElementNode> GetExpansion(StateNode state, Model.Element elt, Model.Element tp)
+ {
+ List<ElementNode> result = new List<ElementNode>();
+ Model.FuncTuple tpl;
+
+ if (elt == null) return result;
+
+ var kind = GetKind(tp, out tpl);
+ if (kind == DataKind.PhysPtr || kind == DataKind.SpecPtr || kind == DataKind.Object) {
+ var heap = state.State.TryGet("$s");
+ if (heap != null)
+ heap = f_heap.TryEval(heap);
+ var addresses = new HashSet<Model.Element>();
+
+ if (heap != null) {
+ var basePtr = f_base.TryEval(elt);
+ foreach (var fld in f_select_field.AppsWithArg(0, heap)) {
+ var val = f_select_value.TryEval(fld.Result, elt);
+ if (val != null) {
+ var field = fld.Args[1];
+ if (!IsConstantField(field) && viewOpts.ViewLevel <= 2)
+ continue;
+ var addr = f_dot.TryEval(elt, field);
+ if (addr != null) addresses.Add(addr);
+ var node = ComputeUnionActiveOption(state, elt, val, field);
+ if (node != null)
+ result.Add(node);
+ else
+ BuildFieldNode(result, state, addr, field, val, addr);
+ }
+ }
+ //result.Sort(CompareFields);
+ }
+
+ {
+ foreach (var app in f_idx.AppsWithArg(0, elt)) {
+ var addr = app.Result;
+ Model.Element val = null, atp = tp;
+
+ addresses.Add(addr);
+
+ foreach (var papp in f_dot.AppsWithResult(addr)) {
+ var tmp = f_select_value.OptEval(f_select_field.OptEval(heap, papp.Args[1]), papp.Args[0]);
+ if (tmp != null) {
+ val = tmp;
+ var tt = f_field_type.TryEval(papp.Args[1]);
+ if (tt != null) atp = tt;
+ }
+ }
+
+ if (val != null)
+ val = WrapForUse(val, atp);
+ result.Add(new MapletNode(state, new EdgeName(this, "[%0]", app.Args[1]), val, atp) { Category = NodeCategory.Maplet });
+ if (addr != null)
+ result.Add(new MapletNode(state, new EdgeName(this, "&[%0]", app.Args[1]), addr, GuessPtrTo(atp)) { Category = NodeCategory.Maplet });
+ }
+ }
+
+ foreach (var ptr in f_dot.AppsWithArg(0, elt)) {
+ if (addresses.Contains(ptr.Result)) continue;
+ var fld = ptr.Args[1];
+ var idx = f_field_arr_index.TryEval(fld);
+ if (idx != null) {
+ var xtp = f_field_type.TryEval(fld);
+ result.Add(new MapletNode(state, new EdgeName(this, "&[%0] of %1", idx, f_field_arr_size.TryEval(fld)), ptr.Result, GuessPtrTo(xtp)) { Category = NodeCategory.Maplet });
+ }
+ if (!IsConstantField(ptr.Args[1])) continue;
+ BuildFieldNode(result, state, ptr.Result, ptr.Args[1], null, ptr.Result);
+ }
+
+ AddSpecialField(state, elt, result, "\\closed", f_closed);
+ AddSpecialField(state, elt, result, "\\owner", f_owners);
+ AddSpecialField(state, elt, result, "\\root", f_roots);
+ AddSpecialField(state, elt, result, "\\timestamp", f_timestamps);
+ AddPointerFunction(state, elt, result, "\\embedding", f_prim_emb, tp_object);
+ AddPointerFunction(state, elt, result, "\\addr", f_addr, tp_mathint);
+
+ if (viewOpts.ViewLevel >= 1) {
+ AddPtrType(state, elt, result);
+ AddCasts(state, elt, result);
+ var sets = new SetsNode(state, elt);
+ if (!sets.IsEmpty)
+ result.Add(sets);
+ }
+
+ } else if (kind == DataKind.Map) {
+ var elTp = tpl.Args[1];
+ foreach (var sel in model.Functions)
+ if (sel.Arity == 2 && sel.Name.StartsWith("$select.$map_t")) {
+ foreach (var app in sel.AppsWithArg(0, elt)) {
+ var val = WrapForUse(app.Result, elTp);
+ var edgname = new EdgeName(this, "[%0]", app.Args[1]);
+ result.Add(new MapletNode(state, edgname, val, elTp) { Category = NodeCategory.Maplet });
+ }
+ }
+ } else if (kind == DataKind.Ptrset) {
+ foreach (var sel in f_select_bool.AppsWithArg(0, elt)) {
+ var edgname = new EdgeName(this, "[%0]", sel.Args[1]);
+ result.Add(new MapletNode(state, edgname, sel.Result, tp_bool) { Category = NodeCategory.Maplet });
+ }
+ } else if (kind == DataKind.Flat) {
+ foreach (var tupl in elt.References) {
+ if (tupl.Args.Length == 1 && tupl.Args[0] == elt) {
+ var fname = tupl.Func.Name;
+ var idx = fname.LastIndexOf('.');
+ if (fname.StartsWith("RF#") && idx > 0) {
+ fname = fname.Substring(idx + 1);
+ } else if (fname.StartsWith("DP#p")) {
+ fname = fname.Substring(4);
+ idx = fname.IndexOf('#');
+ if (idx > 0)
+ fname = fname.Substring(idx + 1) + "#" + fname.Substring(0, idx);
+ } else {
+ fname = null;
+ }
+
+ if (fname != null)
+ result.Add(new FieldNode(state, new EdgeName(fname), tupl.Result, GuessType(tupl.Result)) { Category = NodeCategory.SpecField });
+ }
+ }
+ }
+
+ if (!(elt is Model.Boolean)) {
+ var curState = state.State.TryGet("$s");
+
+ foreach (var tupl in elt.References) {
+ {
+ var seenSelf = false;
+ var seenState = false;
+ var seenThisState = false;
+ var args = tupl.Args;
+ for (int i = 0; i < args.Length; ++i) {
+ if (args[i] == elt) seenSelf = true;
+ if (IsThisState(curState, args[i])) seenThisState = true;
+ else if (IsSomeState(args[i])) seenState = true;
+ }
+ if (!seenSelf) continue; // not looking for aliases (maybe we should?)
+ if (seenState && !seenThisState) continue;
+ }
+
+ var argsFmt = new StringBuilder();
+ var name = tupl.Func.Name;
+
+ var score = FunctionScore(name);
+ if (score >= viewOpts.ViewLevel)
+ continue;
+
+ var retTp = GuessType(tupl.Result);
+ var retVal = tupl.Result;
+
+ var cat = NodeCategory.MethodologyProperty;
+ if (name.StartsWith("F#")) {
+ name = name.Substring(2);
+ cat = NodeCategory.UserFunction;
+ }
+
+ if (name.StartsWith("DF#")) {
+ name = name.Substring(3);
+ cat = NodeCategory.UserFunction;
+ }
+
+ if (name.StartsWith("$eq.$"))
+ name = "EQ";
+
+ {
+ Model.Element sktp = null;
+ var sk = SkolemName(tupl.Func, ref sktp);
+ if (sk != null) {
+ name = sk;
+ if (sktp != null)
+ retVal = WrapForUse(tupl.Result, sktp);
+ cat = NodeCategory.Maplet;
+ }
+ }
+
+ {
+ argsFmt.Append(name).Append("(");
+ var args = new List<Model.Element>();
+ foreach (var a in tupl.Args) {
+ if (IsThisState(curState, a))
+ argsFmt.Append("\\now, ");
+ else if (a == elt)
+ argsFmt.Append(selfMarker + ", ");
+ else {
+ argsFmt.AppendFormat("%{0}, ", args.Count);
+ args.Add(a);
+ }
+ }
+ argsFmt.Length -= 2;
+ argsFmt.Append(")");
+ var edgeName = new EdgeName(this, argsFmt.ToString(), args.ToArray());
+ result.Add(new MapletNode(state, edgeName, retVal, retTp) { ViewLevel = score, Category = cat });
+ }
+
+ }
+ }
+
+ return result;
+ }
+
+ private FieldNode ComputeUnionActiveOption(StateNode state, Model.Element elt, Model.Element val, Model.Element field)
+ {
+ if (f_active_option.AppsWithResult(field).FirstOrDefault() != null) {
+ var activeOpt = f_dot.OptEval(elt, f_int_to_field.OptEval(val));
+ if (activeOpt != null) {
+ var nm = ConstantFieldName(field);
+ var fieldNode = new FieldNode(state, new EdgeName(nm), activeOpt, GuessType(activeOpt)) { Category = NodeCategory.MethodologyProperty };
+ return fieldNode;
+ }
+ }
+ return null;
+ }
+
+ private void AddCasts(StateNode state, Model.Element elt, List<ElementNode> result)
+ {
+ foreach (var app in f_phys_ptr_cast.AppsWithArg(0, elt)) {
+ if (app.Result != elt)
+ result.Add(new MapletNode(state, new EdgeName(this, "(" + TypeName(app.Args[1]) + "*)..."), app.Result, PtrTo(app.Args[1], f_ptr_to)));
+ }
+ foreach (var app in f_spec_ptr_cast.AppsWithArg(0, elt)) {
+ if (app.Result != elt)
+ result.Add(new MapletNode(state, new EdgeName(this, "(" + TypeName(app.Args[1]) + "^)..."), app.Result, PtrTo(app.Args[1], f_spec_ptr_to)));
+ }
+ var addr = f_addr.TryEval(elt);
+ if (addr != null) {
+ foreach (var app in f_blob_type.Apps) {
+ var blob = f_address_root.TryEval(addr, app.Result);
+ if (blob != null) {
+ result.Add(new MapletNode(state, new EdgeName(this, TypeName(app.Result) + "..."), blob, app.Result));
+ }
+ }
+ }
+ }
+
+ private void BuildFieldNode(List<ElementNode> result, StateNode state, Model.Element ptr, Model.Element field, Model.Element val, Model.Element addr)
+ {
+ var ftp = f_field_type.TryEval(field);
+ if (val != null)
+ val = WrapForUse(val, ftp);
+
+ if (IsArrayField(ptr)) {
+ val = addr;
+ addr = null;
+ ftp = GuessPtrTo(ftp);
+ }
+
+ var nm = ConstantFieldName(field);
+ var edgname = nm == null ? field.ToString() : nm;
+
+ var cat = NodeCategory.PhysField;
+ if (f_is_ghost_field.IsTrue(field))
+ cat = NodeCategory.SpecField;
+ if (nm != null && nm.Contains("<"))
+ cat = NodeCategory.MethodologyProperty;
+
+ var fieldNode = new FieldNode(state, new EdgeName(edgname), val, ftp) { Category = cat};
+ result.Add(fieldNode);
+
+ if (addr != null) {
+ result.Add(new FieldNode(state, new EdgeName("&" + edgname), addr, GuessPtrTo(ftp)) { Category = cat });
+ }
+ }
+
+ public override IEnumerable<IState> States
+ {
+ get
+ {
+ return states;
+ }
+ }
+
+ private int DataTypeToString(StringBuilder sb, int level, Model.Element elt)
+ {
+ Model.FuncTuple ctor = null;
+ int len = 1;
+ string dataTypeType = null;
+ foreach (var app in elt.References) {
+ var n = app.Func.Name;
+ if (app.Result == elt && n.StartsWith("DF#")) {
+ ctor = app;
+ }
+ var tmp = DataTypeName(elt, app);
+ if (tmp != null) dataTypeType = tmp;
+ }
+
+ if (dataTypeType != null) {
+ if (ctor != null)
+ sb.Append(ctor.Func.Name.Substring(3));
+ else
+ sb.Append(DataTypeShortName(elt, dataTypeType));
+ if (ctor != null && ctor.Args.Length > 0) {
+ if (level <= 0) sb.Append("(...)");
+ else {
+ sb.Append("(");
+ for (int i = 0; i < ctor.Args.Length; ++i) {
+ if (i != 0) sb.Append(", ");
+ len += DataTypeToString(sb, level - 1, ctor.Args[i]);
+ }
+ sb.Append(")");
+ }
+ }
+ } else {
+ sb.Append(CanonicalName(elt));
+ }
+ return len;
+ }
+
+ private string DataTypeShortName(Model.Element elt, string tp)
+ {
+ var baseName = tp;
+
+ var hd = model.MkFunc("DGH#" + tp, 1).TryEval(elt);
+ if (hd != null) {
+ foreach (var nm in hd.References) {
+ if (nm.Func.Arity == 0 && nm.Func.Name.StartsWith("DH#"))
+ baseName = nm.Func.Name.Substring(3);
+ }
+ }
+
+ return baseName;
+ }
+
+ private string CanonicalBaseNameCore(string name, Model.Element elt, bool doDatatypes, ref NameSeqSuffix suff)
+ {
+ var vm = this;
+
+ if (name.Contains("[") || name.Contains("'"))
+ name = "";
+
+ if (name != "")
+ return name;
+
+ var isNull = false;
+ foreach (var tpl in elt.References) {
+ var fn = tpl.Func;
+ if (fn.Name.StartsWith("$select.$map_t") && fn.Arity == 2 && tpl.Args[0] == elt)
+ return "map";
+ if (fn.Name.StartsWith("$int_to_map_t") && tpl.Result == elt)
+ return "map";
+
+ if (fn.Arity >= 1 && tpl.Args[0] == elt) {
+ if (fn == f_select_bool)
+ return "ptrset";
+ }
+
+ if (tpl.Result == elt)
+ if (fn == f_int_to_version)
+ return "version";
+
+ if (fn == f_is_null && tpl.Result == model.True)
+ isNull = true;
+
+ var dtpName = DataTypeName(elt, tpl);
+ if (dtpName != null) {
+ var sb = new StringBuilder();
+ string prev = null;
+ datatypeLongName[elt] = "*SELF*"; // in case we recurse (but this shouldn't happen)
+ for (int lev = 0; lev < 10; lev++) {
+ sb.Length = 0;
+ var len = DataTypeToString(sb, lev, elt);
+ if (prev == null || len <= maxDatatypeNameLength)
+ prev = sb.ToString();
+ }
+
+ datatypeLongName[elt] = prev;
+ suff = NameSeqSuffix.WhenNonZero;
+ return prev;
+ }
+ }
+
+ var fld = vm.f_field.TryEval(elt);
+ if (fld != null) {
+ var tp = vm.f_field_type.TryEval(fld);
+ if (tp != null) {
+ var n = vm.TryTypeName(tp);
+ if (n != null) {
+ if (isNull)
+ return "(" + n + "*)NULL";
+ return n;
+ }
+ }
+ }
+
+ return "";
+ }
+
+ protected override string CanonicalBaseName(Model.Element elt, out NameSeqSuffix suff)
+ {
+ var lit = this.LiteralName(elt);
+ if (lit != null) {
+ suff = NameSeqSuffix.None;
+ return lit;
+ }
+ if (datatypeLongName.TryGetValue(elt, out lit)) {
+ suff = NameSeqSuffix.WhenNonZero;
+ return lit;
+ }
+
+ var name = base.CanonicalBaseName(elt, out suff);
+ name = CanonicalBaseNameCore(name, elt, true, ref suff);
+
+ return name;
+ }
+
+ public override string PathName(IEnumerable<IDisplayNode> path)
+ {
+ var sb = new StringBuilder();
+ foreach (var d in path) {
+ var name = d.Name;
+ if (name == "") continue; // can that happen?
+ if (name.Contains("(") && name.Contains(selfMarker)) {
+ var repl = name.Replace(selfMarker, sb.ToString());
+ sb.Length = 0;
+ sb.Append(repl);
+ } else {
+ if (sb.Length > 0 && name[0] != '[')
+ sb.Append("->");
+ sb.Append(d.Name);
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
+
+ class StateNode : NamedState
+ {
+ internal VccModel vm;
+ internal List<VariableNode> vars;
+ internal List<ElementNode> commons;
+ internal int index;
+ internal string capturedStateName;
+
+ public StateNode(VccModel parent, Model.CapturedState s)
+ : base(s, parent)
+ {
+ this.capturedStateName = s.Name;
+ this.vm = parent;
+ }
+
+ internal void SetupVars()
+ {
+ if (vars != null) return;
+ vars = new List<VariableNode>();
+
+ var names = Util.Empty<string>();
+
+ if (vm.states.Count > 0) {
+ var prev = vm.states.Last();
+ names = prev.vars.Map(v => v.realName);
+ }
+
+ names = names.Concat(state.Variables).Distinct();
+
+ var curVars = state.Variables.ToDictionary(x => x);
+ foreach (var v in names) {
+ var localName = vm.GetUserVariableName(v);
+ if (localName != null) {
+ var tp = vm.LocalType(v);
+ var val = state.TryGet(v);
+ val = vm.WrapForUse(val, tp);
+ var vn = new VariableNode(this, v, val, tp) { ShortName = localName };
+ vn.updatedHere = vm.states.Count > 0 && curVars.ContainsKey(v);
+ if (curVars.ContainsKey(v))
+ vm.RegisterLocalValue(vn.Name, val);
+ vars.Add(vn);
+ }
+ }
+
+ vm.Flush(vars);
+
+ commons = new List<ElementNode>();
+ commons.AddRange(vm.CommonNodes(this));
+ }
+
+ public override IEnumerable<IDisplayNode> Nodes
+ {
+ get {
+ return vars.Concat(commons);
+ }
+ }
+
+ public override string CapturedStateName
+ {
+ get
+ {
+ return this.capturedStateName;
+ }
+ }
+ }
+
+ class ElementNode : DisplayNode
+ {
+ protected StateNode stateNode;
+ protected Model.Element tp;
+ protected VccModel vm { get { return stateNode.vm; } }
+
+ public ElementNode(StateNode st, EdgeName name, Model.Element elt, Model.Element tp)
+ : base(st.vm, name, elt)
+ {
+ this.stateNode = st;
+ this.tp = tp;
+ }
+
+ protected override void ComputeChildren()
+ {
+ children.AddRange(vm.GetExpansion(stateNode, element, tp));
+ }
+
+ public override string ToolTip
+ {
+ get
+ {
+ var sb = new StringBuilder();
+ if (tp != null)
+ sb.AppendFormat("Type: {0}\n", vm.TypeName(tp));
+ var i = element as Model.Integer;
+ if (i != null) {
+ var n = System.Numerics.BigInteger.Parse(i.Numeral);
+ sb.AppendFormat("Value: {0} (0x{1:x})\n", n, n);
+ } else if (element != null) {
+ sb.AppendFormat("Value: {0}\n", element);
+ }
+ return sb.ToString();
+ }
+ }
+ }
+
+ class SetsNode : ElementNode
+ {
+ List<Model.Element> refs = new List<Model.Element>();
+
+ public SetsNode(StateNode par, Model.Element elt)
+ : base(par, new EdgeName("\\in ..."), null, null)
+ {
+ children = new List<IDisplayNode>();
+ foreach (var app in vm.f_select_bool.AppsWithArg(1, elt)) {
+ children.Add(
+ new MapletNode(par, new EdgeName(vm, VccModel.selfMarker + " \\in %0", app.Args[0]), app.Result, vm.tp_bool) { Category = NodeCategory.MethodologyProperty });
+ refs.Add(app.Args[0]);
+ }
+ Category = NodeCategory.MethodologyProperty;
+ }
+
+ public override IEnumerable<Model.Element> References
+ {
+ get
+ {
+ return refs;
+ }
+ }
+
+ public bool IsEmpty { get { return children.Count == 0; } }
+ }
+
+
+ class FieldNode : ElementNode
+ {
+ public FieldNode(StateNode par, EdgeName realName, Model.Element elt, Model.Element tp)
+ : base(par, realName, elt, tp)
+ {
+ }
+ }
+
+ class MapletNode : ElementNode
+ {
+ public MapletNode(StateNode par, EdgeName realName, Model.Element elt, Model.Element tp)
+ : base(par, realName, elt, tp)
+ {
+ }
+ }
+
+ class VariableNode : ElementNode
+ {
+ public bool updatedHere;
+ public string realName;
+
+ public VariableNode(StateNode par, string realName, Model.Element elt, Model.Element tp)
+ : base(par, new EdgeName(realName), elt, tp)
+ {
+ this.realName = realName;
+ }
+
+ public override string ShortName
+ {
+ set { this.name = new EdgeName(value); }
+ get { return this.name.ToString(); }
+ }
+ }
+}
diff --git a/Source/ParserHelper/ParserHelper.cs b/Source/ParserHelper/ParserHelper.cs
index 111b836b..81644b7f 100644
--- a/Source/ParserHelper/ParserHelper.cs
+++ b/Source/ParserHelper/ParserHelper.cs
@@ -1,244 +1,244 @@
-using System.Text;
-using System.Collections.Generic;
-using System.IO;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie {
-
- [Immutable]
- public interface IToken {
- int kind {
- get;
- set;
- } // token kind
- string filename {
- get;
- set;
- } // token file
- int pos {
- get;
- set;
- } // token position in the source text (starting at 0)
- int col {
- get;
- set;
- } // token column (starting at 0)
- int line {
- get;
- set;
- } // token line (starting at 1)
- string/*!*/ val {
- get;
- set;
- } // token value
-
- bool IsValid {
- get;
- }
- }
-
- [Immutable]
- public class Token : IToken {
- public int _kind; // token kind
- string _filename; // token file
- public int _pos; // token position in the source text (starting at 0)
- public int _col; // token column (starting at 1)
- public int _line; // token line (starting at 1)
- public string/*!*/ _val; // token value
- public Token next; // ML 2005-03-11 Tokens are kept in linked list
-
- public static readonly IToken/*!*/ NoToken = new Token();
-
- public Token() {
- this._val = "anything so that it is nonnull";
- }
- public Token(int linenum, int colnum)
- : base() {
- this._line = linenum;
- this._col = colnum;
- this._val = "anything so that it is nonnull";
- }
-
- public int kind {
- get {
- return this._kind;
- }
- set {
- this._kind = value;
- }
- }
-
- public string filename {
- get {
- return this._filename;
- }
- set {
- this._filename = value;
- }
- }
-
- public int pos {
- get {
- return this._pos;
- }
- set {
- this._pos = value;
- }
- }
-
- public int col {
- get {
- return this._col;
- }
- set {
- this._col = value;
- }
- }
-
- public int line {
- get {
- return this._line;
- }
- set {
- this._line = value;
- }
- }
-
- public string/*!*/ val {
- get {
- return this._val;
- }
- set {
- this._val = value;
- }
- }
-
- public bool IsValid {
- get {
- return this._filename != null;
- }
- }
-
-
- }
-
- public static class ParserHelper {
- struct ReadState {
- public bool hasSeenElse;
- public bool mayStillIncludeAnotherAlternative;
- public ReadState(bool hasSeenElse, bool mayStillIncludeAnotherAlternative) {
- this.hasSeenElse = hasSeenElse;
- this.mayStillIncludeAnotherAlternative = mayStillIncludeAnotherAlternative;
- }
- }
- // "arg" is assumed to be trimmed
- private static bool IfdefConditionSaysToInclude(string arg, List<string/*!*/>/*!*/ defines) {
- Contract.Requires(arg != null);
- Contract.Requires(cce.NonNullElements(defines));
- bool sense = true;
- while (arg.StartsWith("!")) {
- sense = !sense;
- arg = arg.Substring(1).TrimStart();
- }
- return defines.Contains(arg) == sense;
- }
-
- public static string Fill(Stream stream, List<string/*!*/>/*!*/ defines) {
- Contract.Requires(stream != null);
- Contract.Requires(cce.NonNullElements(defines));
- Contract.Ensures(Contract.Result<string>() != null);
- StreamReader/*!*/ reader = new StreamReader(stream);
- return Fill(reader, defines);
- }
- public static string Fill(TextReader reader, List<string/*!*/>/*!*/ defines) {
- Contract.Requires(reader != null);
- Contract.Requires(cce.NonNullElements(defines));
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- List<ReadState>/*!*/ readState = new List<ReadState>(); // readState.Count is the current nesting level of #if's
- int ignoreCutoff = -1; // -1 means we're not ignoring; for 0<=n, n means we're ignoring because of something at nesting level n
- while (true)
- //invariant -1 <= ignoreCutoff && ignoreCutoff < readState.Count;
- {
- string s = reader.ReadLine();
- if (s == null) {
- if (readState.Count != 0) {
- sb.AppendLine("#MalformedInput: missing #endif");
- }
- break;
- }
- string t = s.Trim();
- if (t.StartsWith("#if")) {
- ReadState rs = new ReadState(false, false);
- if (ignoreCutoff != -1) {
- // we're already in a state of ignoring, so continue to ignore
- } else if (IfdefConditionSaysToInclude(t.Substring(3).TrimStart(), defines)) {
- // include this branch
- } else {
- ignoreCutoff = readState.Count; // start ignoring
- rs.mayStillIncludeAnotherAlternative = true; // allow some later "elsif" or "else" branch to be included
- }
- readState.Add(rs);
- sb.AppendLine(); // ignore the #if line
-
- } else if (t.StartsWith("#elsif")) {
- ReadState rs;
- if (readState.Count == 0 || (rs = readState[readState.Count - 1]).hasSeenElse) {
- sb.AppendLine("#MalformedInput: misplaced #elsif"); // malformed input
- break;
- }
- if (ignoreCutoff == -1) {
- // we had included the previous branch
- //Contract.Assert(!rs.mayStillIncludeAnotherAlternative);
- ignoreCutoff = readState.Count - 1; // start ignoring
- } else if (rs.mayStillIncludeAnotherAlternative && IfdefConditionSaysToInclude(t.Substring(6).TrimStart(), defines)) {
- // include this branch, but no subsequent branch at this level
- ignoreCutoff = -1;
- rs.mayStillIncludeAnotherAlternative = false;
- readState[readState.Count - 1] = rs;
- }
- sb.AppendLine(); // ignore the #elsif line
-
- } else if (t == "#else") {
- ReadState rs;
- if (readState.Count == 0 || (rs = readState[readState.Count - 1]).hasSeenElse) {
- sb.AppendLine("#MalformedInput: misplaced #else"); // malformed input
- break;
- }
- rs.hasSeenElse = true;
- if (ignoreCutoff == -1) {
- // we had included the previous branch
- //Contract.Assert(!rs.mayStillIncludeAnotherAlternative);
- ignoreCutoff = readState.Count - 1; // start ignoring
- } else if (rs.mayStillIncludeAnotherAlternative) {
- // include this branch
- ignoreCutoff = -1;
- rs.mayStillIncludeAnotherAlternative = false;
- }
- readState[readState.Count - 1] = rs;
- sb.AppendLine(); // ignore the #else line
-
- } else if (t == "#endif") {
- if (readState.Count == 0) {
- sb.AppendLine("#MalformedInput: misplaced #endif"); // malformed input
- break;
- }
- readState.RemoveAt(readState.Count - 1); // pop
- if (ignoreCutoff == readState.Count) {
- // we had ignored the branch that ends here; so, now we start including again
- ignoreCutoff = -1;
- }
- sb.AppendLine(); // ignore the #endif line
-
- } else if (ignoreCutoff == -1) {
- sb.AppendLine(s); // included line
-
- } else {
- sb.AppendLine(); // ignore the line
- }
- }
-
- return sb.ToString();
- }
- }
+using System.Text;
+using System.Collections.Generic;
+using System.IO;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie {
+
+ [Immutable]
+ public interface IToken {
+ int kind {
+ get;
+ set;
+ } // token kind
+ string filename {
+ get;
+ set;
+ } // token file
+ int pos {
+ get;
+ set;
+ } // token position in the source text (starting at 0)
+ int col {
+ get;
+ set;
+ } // token column (starting at 0)
+ int line {
+ get;
+ set;
+ } // token line (starting at 1)
+ string/*!*/ val {
+ get;
+ set;
+ } // token value
+
+ bool IsValid {
+ get;
+ }
+ }
+
+ [Immutable]
+ public class Token : IToken {
+ public int _kind; // token kind
+ string _filename; // token file
+ public int _pos; // token position in the source text (starting at 0)
+ public int _col; // token column (starting at 1)
+ public int _line; // token line (starting at 1)
+ public string/*!*/ _val; // token value
+ public Token next; // ML 2005-03-11 Tokens are kept in linked list
+
+ public static readonly IToken/*!*/ NoToken = new Token();
+
+ public Token() {
+ this._val = "anything so that it is nonnull";
+ }
+ public Token(int linenum, int colnum)
+ : base() {
+ this._line = linenum;
+ this._col = colnum;
+ this._val = "anything so that it is nonnull";
+ }
+
+ public int kind {
+ get {
+ return this._kind;
+ }
+ set {
+ this._kind = value;
+ }
+ }
+
+ public string filename {
+ get {
+ return this._filename;
+ }
+ set {
+ this._filename = value;
+ }
+ }
+
+ public int pos {
+ get {
+ return this._pos;
+ }
+ set {
+ this._pos = value;
+ }
+ }
+
+ public int col {
+ get {
+ return this._col;
+ }
+ set {
+ this._col = value;
+ }
+ }
+
+ public int line {
+ get {
+ return this._line;
+ }
+ set {
+ this._line = value;
+ }
+ }
+
+ public string/*!*/ val {
+ get {
+ return this._val;
+ }
+ set {
+ this._val = value;
+ }
+ }
+
+ public bool IsValid {
+ get {
+ return this._filename != null;
+ }
+ }
+
+
+ }
+
+ public static class ParserHelper {
+ struct ReadState {
+ public bool hasSeenElse;
+ public bool mayStillIncludeAnotherAlternative;
+ public ReadState(bool hasSeenElse, bool mayStillIncludeAnotherAlternative) {
+ this.hasSeenElse = hasSeenElse;
+ this.mayStillIncludeAnotherAlternative = mayStillIncludeAnotherAlternative;
+ }
+ }
+ // "arg" is assumed to be trimmed
+ private static bool IfdefConditionSaysToInclude(string arg, List<string/*!*/>/*!*/ defines) {
+ Contract.Requires(arg != null);
+ Contract.Requires(cce.NonNullElements(defines));
+ bool sense = true;
+ while (arg.StartsWith("!")) {
+ sense = !sense;
+ arg = arg.Substring(1).TrimStart();
+ }
+ return defines.Contains(arg) == sense;
+ }
+
+ public static string Fill(Stream stream, List<string/*!*/>/*!*/ defines) {
+ Contract.Requires(stream != null);
+ Contract.Requires(cce.NonNullElements(defines));
+ Contract.Ensures(Contract.Result<string>() != null);
+ StreamReader/*!*/ reader = new StreamReader(stream);
+ return Fill(reader, defines);
+ }
+ public static string Fill(TextReader reader, List<string/*!*/>/*!*/ defines) {
+ Contract.Requires(reader != null);
+ Contract.Requires(cce.NonNullElements(defines));
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringBuilder sb = new StringBuilder();
+ List<ReadState>/*!*/ readState = new List<ReadState>(); // readState.Count is the current nesting level of #if's
+ int ignoreCutoff = -1; // -1 means we're not ignoring; for 0<=n, n means we're ignoring because of something at nesting level n
+ while (true)
+ //invariant -1 <= ignoreCutoff && ignoreCutoff < readState.Count;
+ {
+ string s = reader.ReadLine();
+ if (s == null) {
+ if (readState.Count != 0) {
+ sb.AppendLine("#MalformedInput: missing #endif");
+ }
+ break;
+ }
+ string t = s.Trim();
+ if (t.StartsWith("#if")) {
+ ReadState rs = new ReadState(false, false);
+ if (ignoreCutoff != -1) {
+ // we're already in a state of ignoring, so continue to ignore
+ } else if (IfdefConditionSaysToInclude(t.Substring(3).TrimStart(), defines)) {
+ // include this branch
+ } else {
+ ignoreCutoff = readState.Count; // start ignoring
+ rs.mayStillIncludeAnotherAlternative = true; // allow some later "elsif" or "else" branch to be included
+ }
+ readState.Add(rs);
+ sb.AppendLine(); // ignore the #if line
+
+ } else if (t.StartsWith("#elsif")) {
+ ReadState rs;
+ if (readState.Count == 0 || (rs = readState[readState.Count - 1]).hasSeenElse) {
+ sb.AppendLine("#MalformedInput: misplaced #elsif"); // malformed input
+ break;
+ }
+ if (ignoreCutoff == -1) {
+ // we had included the previous branch
+ //Contract.Assert(!rs.mayStillIncludeAnotherAlternative);
+ ignoreCutoff = readState.Count - 1; // start ignoring
+ } else if (rs.mayStillIncludeAnotherAlternative && IfdefConditionSaysToInclude(t.Substring(6).TrimStart(), defines)) {
+ // include this branch, but no subsequent branch at this level
+ ignoreCutoff = -1;
+ rs.mayStillIncludeAnotherAlternative = false;
+ readState[readState.Count - 1] = rs;
+ }
+ sb.AppendLine(); // ignore the #elsif line
+
+ } else if (t == "#else") {
+ ReadState rs;
+ if (readState.Count == 0 || (rs = readState[readState.Count - 1]).hasSeenElse) {
+ sb.AppendLine("#MalformedInput: misplaced #else"); // malformed input
+ break;
+ }
+ rs.hasSeenElse = true;
+ if (ignoreCutoff == -1) {
+ // we had included the previous branch
+ //Contract.Assert(!rs.mayStillIncludeAnotherAlternative);
+ ignoreCutoff = readState.Count - 1; // start ignoring
+ } else if (rs.mayStillIncludeAnotherAlternative) {
+ // include this branch
+ ignoreCutoff = -1;
+ rs.mayStillIncludeAnotherAlternative = false;
+ }
+ readState[readState.Count - 1] = rs;
+ sb.AppendLine(); // ignore the #else line
+
+ } else if (t == "#endif") {
+ if (readState.Count == 0) {
+ sb.AppendLine("#MalformedInput: misplaced #endif"); // malformed input
+ break;
+ }
+ readState.RemoveAt(readState.Count - 1); // pop
+ if (ignoreCutoff == readState.Count) {
+ // we had ignored the branch that ends here; so, now we start including again
+ ignoreCutoff = -1;
+ }
+ sb.AppendLine(); // ignore the #endif line
+
+ } else if (ignoreCutoff == -1) {
+ sb.AppendLine(s); // included line
+
+ } else {
+ sb.AppendLine(); // ignore the line
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
} \ No newline at end of file
diff --git a/Source/ParserHelper/ParserHelper.csproj b/Source/ParserHelper/ParserHelper.csproj
index f3424531..b5ed2744 100644
--- a/Source/ParserHelper/ParserHelper.csproj
+++ b/Source/ParserHelper/ParserHelper.csproj
@@ -1,142 +1,142 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>ParserHelper</RootNamespace>
- <AssemblyName>ParserHelper</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\Binaries\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>True</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>False</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>True</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
- <CodeContractsContainerAnalysis>True</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile>..\..\baseline.xml</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>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>..\..\Binaries\ParserHelper.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>TRACE;DEBUG</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="ParserHelper.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ParserHelper</RootNamespace>
+ <AssemblyName>BoogieParserHelper</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Binaries\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>True</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>False</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>True</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+ <CodeContractsContainerAnalysis>True</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile>..\..\baseline.xml</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>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\ParserHelper.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="ParserHelper.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ </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/Predication/Predication.csproj b/Source/Predication/Predication.csproj
index 382a8aca..1319d7f7 100644
--- a/Source/Predication/Predication.csproj
+++ b/Source/Predication/Predication.csproj
@@ -1,174 +1,174 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Predication</RootNamespace>
- <AssemblyName>Predication</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
- <ProductVersion>12.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </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>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
- <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
- <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
- <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
- <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
- <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
- <CodeContractsInferRequires>True</CodeContractsInferRequires>
- <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
- <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
- <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
- <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
- <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
- <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
- <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
- <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
- <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsSQLServerOption />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
- <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
- <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </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>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
- <CodeContractsInferRequires>True</CodeContractsInferRequires>
- <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
- <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
- <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
- <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
- <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsSQLServerOption />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="SmartBlockPredicator.cs" />
- <Compile Include="UniformityAnalyser.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</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>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{AFAA5CE1-C41B-44F0-88F8-FD8A43826D44}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Predication</RootNamespace>
+ <AssemblyName>BoogiePredication</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ <ProductVersion>12.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </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>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+ <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
+ <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
+ <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
+ <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+ <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
+ <CodeContractsInferRequires>True</CodeContractsInferRequires>
+ <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+ <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
+ <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+ <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+ <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
+ <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
+ <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
+ <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+ <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsSQLServerOption />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+ <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
+ <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+ <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </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>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+ <CodeContractsInferRequires>True</CodeContractsInferRequires>
+ <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+ <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+ <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+ <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
+ <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsSQLServerOption />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+ <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="SmartBlockPredicator.cs" />
+ <Compile Include="UniformityAnalyser.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</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/Predication/SmartBlockPredicator.cs b/Source/Predication/SmartBlockPredicator.cs
index 739f0e2b..0f848152 100644
--- a/Source/Predication/SmartBlockPredicator.cs
+++ b/Source/Predication/SmartBlockPredicator.cs
@@ -1,637 +1,637 @@
-using Microsoft.Boogie.GraphUtil;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.Linq;
-
-namespace Microsoft.Boogie {
-
-public class SmartBlockPredicator {
-
- Program prog;
- Implementation impl;
- Graph<Block> blockGraph;
- List<Tuple<Block, bool>> sortedBlocks;
-
- Func<Procedure, bool> useProcedurePredicates;
-
- Dictionary<Block, Variable> predMap, defMap;
- Dictionary<Block, HashSet<Variable>> ownedMap;
- Dictionary<Block, Block> parentMap;
- Dictionary<Block, PartInfo> partInfo;
-
- IdentifierExpr fp;
- Dictionary<Microsoft.Boogie.Type, IdentifierExpr> havocVars =
- new Dictionary<Microsoft.Boogie.Type, IdentifierExpr>();
- HashSet<Block> doneBlocks = new HashSet<Block>();
- bool myUseProcedurePredicates;
- UniformityAnalyser uni;
-
- SmartBlockPredicator(Program p, Implementation i, Func<Procedure, bool> upp, UniformityAnalyser u) {
- prog = p;
- impl = i;
- useProcedurePredicates = upp;
- myUseProcedurePredicates = useProcedurePredicates(i.Proc);
- uni = u;
- }
-
- void PredicateCmd(Expr p, Expr pDom, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) {
- var cCmd = cmd as CallCmd;
- if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) {
- if (p == null) {
- block.Cmds.Add(cmd);
- nextBlock = block;
- return;
- }
-
- var trueBlock = new Block();
- blocks.Add(trueBlock);
- trueBlock.Label = block.Label + ".call.true";
- trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p));
- trueBlock.Cmds.Add(cmd);
-
- var falseBlock = new Block();
- blocks.Add(falseBlock);
- falseBlock.Label = block.Label + ".call.false";
- falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p)));
-
- var contBlock = new Block();
- blocks.Add(contBlock);
- contBlock.Label = block.Label + ".call.cont";
-
- block.TransferCmd =
- new GotoCmd(Token.NoToken, new List<Block> { trueBlock, falseBlock });
- trueBlock.TransferCmd = falseBlock.TransferCmd =
- new GotoCmd(Token.NoToken, new List<Block> { contBlock });
- nextBlock = contBlock;
- } else {
- PredicateCmd(p, pDom, block.Cmds, cmd);
- nextBlock = block;
- }
- }
-
- void PredicateCmd(Expr p, Expr pDom, List<Cmd> cmdSeq, Cmd cmd) {
- if (cmd is CallCmd) {
- var cCmd = (CallCmd)cmd;
- Debug.Assert(useProcedurePredicates(cCmd.Proc));
- cCmd.Ins.Insert(0, p != null ? p : Expr.True);
- cmdSeq.Add(cCmd);
- } else if (p == null) {
- new EnabledReplacementVisitor(Expr.True, pDom).Visit(cmd);
- cmdSeq.Add(cmd);
- } else if (cmd is AssignCmd) {
- var aCmd = (AssignCmd)cmd;
- cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss,
- new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) =>
- new NAryExpr(Token.NoToken,
- new IfThenElse(Token.NoToken),
- new List<Expr> { p, rhs, lhs.AsExpr })))));
- } else if (cmd is AssertCmd) {
- var aCmd = (AssertCmd)cmd;
- Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr);
- aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr);
- cmdSeq.Add(aCmd);
- } else if (cmd is AssumeCmd) {
- var aCmd = (AssumeCmd)cmd;
- Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr);
- aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr);
- cmdSeq.Add(aCmd);
- } else if (cmd is HavocCmd) {
- var hCmd = (HavocCmd)cmd;
- foreach (IdentifierExpr v in hCmd.Vars) {
- Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type;
- Contract.Assert(type != null);
-
- IdentifierExpr havocTempExpr;
- if (havocVars.ContainsKey(type)) {
- havocTempExpr = havocVars[type];
- } else {
- var havocVar = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken,
- "_HAVOC_" + type.ToString(), type));
- impl.LocVars.Add(havocVar);
- havocVars[type] = havocTempExpr =
- new IdentifierExpr(Token.NoToken, havocVar);
- }
- cmdSeq.Add(new HavocCmd(Token.NoToken,
- new List<IdentifierExpr> { havocTempExpr }));
- cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v,
- new NAryExpr(Token.NoToken,
- new IfThenElse(Token.NoToken),
- new List<Expr> { p, havocTempExpr, v })));
- }
- } else if (cmd is CommentCmd) {
- // skip
- } else if (cmd is StateCmd) {
- var sCmd = (StateCmd)cmd;
- var newCmdSeq = new List<Cmd>();
- foreach (Cmd c in sCmd.Cmds)
- PredicateCmd(p, pDom, newCmdSeq, c);
- sCmd.Cmds = newCmdSeq;
- cmdSeq.Add(sCmd);
- } else {
- Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
- }
- }
-
- // hasPredicatedRegion is true iff the block or its targets are predicated
- // (i.e. we enter, stay within or exit a predicated region).
- void PredicateTransferCmd(Expr p, Block src, List<Cmd> cmdSeq, TransferCmd cmd, out bool hasPredicatedRegion) {
- hasPredicatedRegion = predMap.ContainsKey(src);
-
- if (cmd is GotoCmd) {
- var gCmd = (GotoCmd)cmd;
-
- hasPredicatedRegion = hasPredicatedRegion ||
- gCmd.labelTargets.Cast<Block>().Any(b => predMap.ContainsKey(b));
-
- if (gCmd.labelTargets.Count == 1) {
- if (defMap.ContainsKey(gCmd.labelTargets[0])) {
- PredicateCmd(p, Expr.True, cmdSeq,
- Cmd.SimpleAssign(Token.NoToken,
- Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True));
- }
- } else {
- Debug.Assert(gCmd.labelTargets.Count > 1);
- Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => uni.IsUniform(impl.Name, t) ||
- partInfo.ContainsKey(t)));
- foreach (Block target in gCmd.labelTargets) {
- if (!partInfo.ContainsKey(target))
- continue;
-
- // In this case we not only predicate with the current predicate p,
- // but also with the "part predicate"; this ensures that we do not
- // update a predicate twice when it occurs in both parts.
- var part = partInfo[target];
- if (defMap.ContainsKey(part.realDest)) {
- PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq,
- Cmd.SimpleAssign(Token.NoToken,
- Expr.Ident(predMap[part.realDest]), part.pred));
- }
- var predsExitingLoop = new Dictionary<Block, List<Expr>>();
- foreach (Block exit in LoopsExited(src, target)) {
- List<Expr> predList;
- if (!predsExitingLoop.ContainsKey(exit))
- predList = predsExitingLoop[exit] = new List<Expr>();
- else
- predList = predsExitingLoop[exit];
- predList.Add(part.pred);
- }
- foreach (var pred in predsExitingLoop) {
- PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq,
- Cmd.SimpleAssign(Token.NoToken,
- Expr.Ident(predMap[pred.Key]),
- Expr.Not(pred.Value.Aggregate(Expr.Or))));
- }
- }
- }
- } else if (cmd is ReturnCmd) {
- // Blocks which end in a return will never share a predicate with a block
- // which appears after it. Furthermore, such a block cannot be part of a
- // loop. So it is safe to do nothing here.
- } else {
- Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
- }
- }
-
- Variable FreshPredicate(ref int predCount) {
- var pVar = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken,
- "p" + predCount++,
- Microsoft.Boogie.Type.Bool));
- impl.LocVars.Add(pVar);
- return pVar;
- }
-
- void AssignPredicates(Graph<Block> blockGraph,
- DomRelation<Block> dom,
- DomRelation<Block> pdom,
- IEnumerable<Block> headerDominance,
- IEnumerator<Tuple<Block, bool>> i,
- Variable headPredicate,
- ref int predCount) {
- var header = i.Current.Item1;
- var regionPreds = new List<Tuple<Block, Variable>>();
- var ownedPreds = new HashSet<Variable>();
- ownedMap[header] = ownedPreds;
-
- if (headPredicate != null) {
- predMap[header] = headPredicate;
- defMap[header] = headPredicate;
- regionPreds.Add(new Tuple<Block, Variable>(header, headPredicate));
- }
-
- while (i.MoveNext()) {
- var block = i.Current;
-
- if (block.Item2) {
- if (block.Item1 == header) {
- return;
- }
- }
-
- if (uni != null && uni.IsUniform(impl.Name, block.Item1)) {
- if (blockGraph.Headers.Contains(block.Item1)) {
- parentMap[block.Item1] = header;
- AssignPredicates(blockGraph, dom, pdom, headerDominance, i, headPredicate, ref predCount);
- }
- continue;
- }
-
- if (!block.Item2) {
- if (blockGraph.Headers.Contains(block.Item1)) {
- parentMap[block.Item1] = header;
- var loopPred = FreshPredicate(ref predCount);
- ownedPreds.Add(loopPred);
- AssignPredicates(blockGraph, dom, pdom, headerDominance, i, loopPred, ref predCount);
- } else {
- bool foundExisting = false;
- foreach (var regionPred in regionPreds) {
- if (dom.DominatedBy(block.Item1, regionPred.Item1) &&
- pdom.DominatedBy(regionPred.Item1, block.Item1)) {
- predMap[block.Item1] = regionPred.Item2;
- foundExisting = true;
- break;
- }
- }
- if (!foundExisting) {
- var condPred = FreshPredicate(ref predCount);
- predMap[block.Item1] = condPred;
- defMap[block.Item1] = condPred;
- var headerIterator = headerDominance.GetEnumerator();
- // Add the predicate to the loop header H that dominates the node (if one
- // exists) such that H does not dominate another header which also dominates
- // the node. Since predicates are owned by loop headers (or the program entry
- // node), this is the block 'closest' to block to which we are assigning a
- // that can be made to own the predicate.
- Block node = null;
- while (headerIterator.MoveNext()) {
- var current = headerIterator.Current;
- if (dom.DominatedBy(block.Item1, current)) {
- node = current;
- break;
- }
- }
- if (node != null) {
- ownedMap[node].Add(condPred);
- } else {
- // In this case the header is the program entry node.
- ownedPreds.Add(condPred);
- }
- regionPreds.Add(new Tuple<Block, Variable>(block.Item1, condPred));
- }
- }
- }
- }
- }
-
- void AssignPredicates() {
- DomRelation<Block> dom = blockGraph.DominatorMap;
-
- Graph<Block> dualGraph = blockGraph.Dual(new Block());
- DomRelation<Block> pdom = dualGraph.DominatorMap;
- IEnumerable<Block> headerDominance = blockGraph.SortHeadersByDominance();
-
- var iter = sortedBlocks.GetEnumerator();
- if (!iter.MoveNext()) {
- predMap = defMap = null;
- ownedMap = null;
- return;
- }
-
- int predCount = 0;
- predMap = new Dictionary<Block, Variable>();
- defMap = new Dictionary<Block, Variable>();
- ownedMap = new Dictionary<Block, HashSet<Variable>>();
- parentMap = new Dictionary<Block, Block>();
- AssignPredicates(blockGraph, dom, pdom, headerDominance, iter,
- myUseProcedurePredicates ? impl.InParams[0] : null,
- ref predCount);
- }
-
- IEnumerable<Block> LoopsExited(Block src, Block dest) {
- var i = sortedBlocks.GetEnumerator();
- while (i.MoveNext()) {
- var b = i.Current;
- if (b.Item1 == src) {
- return LoopsExitedForwardEdge(dest, i);
- } else if (b.Item1 == dest) {
- return LoopsExitedBackEdge(src, i);
- }
- }
- Debug.Assert(false);
- return null;
- }
-
- private IEnumerable<Block> LoopsExitedBackEdge(Block src, IEnumerator<Tuple<Block, bool>> i) {
- var headsSeen = new HashSet<Block>();
- while (i.MoveNext()) {
- var b = i.Current;
- if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
- headsSeen.Add(b.Item1);
- else if (b.Item2)
- headsSeen.Remove(b.Item1);
- if (b.Item1 == src)
- return headsSeen;
- }
- Debug.Assert(false);
- return null;
- }
-
- private IEnumerable<Block> LoopsExitedForwardEdge(Block dest, IEnumerator<Tuple<Block, bool>> i) {
- var headsSeen = new HashSet<Block>();
- while (i.MoveNext()) {
- var b = i.Current;
- if (b.Item1 == dest)
- yield break;
- else if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
- headsSeen.Add(b.Item1);
- else if (b.Item2 && !headsSeen.Contains(b.Item1))
- yield return b.Item1;
- }
- Debug.Assert(false);
- }
-
- class PartInfo {
- public PartInfo(Expr p, Block r) { pred = p; realDest = r; }
- public Expr pred;
- public Block realDest;
- }
-
- Dictionary<Block, PartInfo> BuildPartitionInfo() {
- var partInfo = new Dictionary<Block, PartInfo>();
- foreach (var block in blockGraph.Nodes) {
- if (uni.IsUniform(impl.Name, block))
- continue;
-
- var parts = block.Cmds.Cast<Cmd>().TakeWhile(
- c => c is AssumeCmd &&
- QKeyValue.FindBoolAttribute(((AssumeCmd)c).Attributes, "partition"));
-
- Expr pred = null;
- if (parts.Count() > 0) {
- pred = parts.Select(a => ((AssumeCmd)a).Expr).Aggregate(Expr.And);
- block.Cmds =
- new List<Cmd>(block.Cmds.Cast<Cmd>().Skip(parts.Count()).ToArray());
- } else {
- continue;
- }
-
- Block realDest = block;
- if (block.Cmds.Count == 0) {
- var gc = block.TransferCmd as GotoCmd;
- if (gc != null && gc.labelTargets.Count == 1)
- realDest = gc.labelTargets[0];
- }
- partInfo[block] = new PartInfo(pred, realDest);
- }
-
- return partInfo;
- }
-
- Block FindImmediateDominator(Block block) {
- Block predecessor = null;
- foreach(var pred in blockGraph.Predecessors(block)) {
- if (!blockGraph.DominatorMap.DominatedBy(pred, block)) {
- if (predecessor == null)
- predecessor = pred;
- else
- predecessor = blockGraph.DominatorMap.LeastCommonAncestor(pred, predecessor);
- }
- }
- return predecessor;
- }
-
- void PredicateImplementation() {
- blockGraph = prog.ProcessLoops(impl);
- sortedBlocks = blockGraph.LoopyTopSort();
-
- AssignPredicates();
- partInfo = BuildPartitionInfo();
-
- if (myUseProcedurePredicates)
- fp = Expr.Ident(impl.InParams[0]);
-
- var newBlocks = new List<Block>();
- Block prevBlock = null;
- foreach (var n in sortedBlocks) {
- if (predMap.ContainsKey(n.Item1)) {
- var p = predMap[n.Item1];
- var pExpr = Expr.Ident(p);
-
- if (n.Item2) {
- var dominator = FindImmediateDominator(n.Item1);
- if (dominator != null && predMap.ContainsKey(dominator)) {
- AssumeCmd aCmd = new AssumeCmd(Token.NoToken, Expr.True);
- aCmd.Attributes = new QKeyValue(Token.NoToken, "dominator_predicate", new List<object>() { predMap[dominator].ToString() }, aCmd.Attributes);
- aCmd.Attributes = new QKeyValue(Token.NoToken, "predicate", new List<object>() { predMap[n.Item1].ToString() }, aCmd.Attributes);
- n.Item1.Cmds.Insert(0, aCmd);
- }
-
- var backedgeBlock = new Block();
- newBlocks.Add(backedgeBlock);
-
- backedgeBlock.Label = n.Item1.Label + ".backedge";
- backedgeBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, pExpr,
- new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)) };
- backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new List<Block> { n.Item1 });
-
- var tailBlock = new Block();
- newBlocks.Add(tailBlock);
-
- tailBlock.Label = n.Item1.Label + ".tail";
- tailBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken,
- Expr.Not(pExpr)) };
-
- if (uni != null && !uni.IsUniform(impl.Name, n.Item1)) {
- uni.AddNonUniform(impl.Name, backedgeBlock);
- uni.AddNonUniform(impl.Name, tailBlock);
- }
-
- if (prevBlock != null)
- prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new List<Block> { backedgeBlock, tailBlock });
- prevBlock = tailBlock;
- } else {
- PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock);
- }
- } else {
- if (!n.Item2) {
- PredicateBlock(null, n.Item1, newBlocks, ref prevBlock);
- }
- }
- }
-
- if (prevBlock != null)
- prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);
-
- impl.Blocks = newBlocks;
- }
-
- private void PredicateBlock(Expr pExpr, Block block, List<Block> newBlocks, ref Block prevBlock) {
- var firstBlock = block;
-
- var oldCmdSeq = block.Cmds;
- block.Cmds = new List<Cmd>();
- newBlocks.Add(block);
- if (prevBlock != null && !((prevBlock.TransferCmd is ReturnCmd) && uni != null && uni.IsUniform(impl.Name, block))) {
- prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { block });
- }
-
- Block currentBlock = block;
- Expr pCurrentExpr = pExpr;
- while (parentMap.ContainsKey(currentBlock)) {
- Block parent = parentMap[currentBlock];
- Expr pParentExpr = null;
- if (predMap.ContainsKey(parent)) {
- var parentPred = predMap[parent];
- if (parentPred != null) {
- pParentExpr = Expr.Ident(parentPred);
- block.Cmds.Add(new AssertCmd(Token.NoToken,
- pCurrentExpr != null ? (Expr)Expr.Imp(pCurrentExpr, pParentExpr)
- : pParentExpr));
- }
- }
- currentBlock = parent;
- pCurrentExpr = pParentExpr;
- }
-
- Block dominator = FindImmediateDominator(block);
- Expr pDomExpr = Expr.True;
- if (dominator != null && predMap.ContainsKey(dominator))
- pDomExpr = new IdentifierExpr(Token.NoToken, predMap[dominator]);
- var transferCmd = block.TransferCmd;
- foreach (Cmd cmd in oldCmdSeq)
- PredicateCmd(pExpr, pDomExpr, newBlocks, block, cmd, out block);
-
- if (ownedMap.ContainsKey(firstBlock)) {
- var owned = ownedMap[firstBlock];
- foreach (var v in owned)
- block.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False));
- }
-
- bool hasPredicatedRegion;
- PredicateTransferCmd(pExpr, block, block.Cmds, transferCmd, out hasPredicatedRegion);
-
- if (hasPredicatedRegion)
- prevBlock = block;
- else
- prevBlock = null;
-
- doneBlocks.Add(block);
- }
-
- private Expr CreateIfFPThenElse(Expr then, Expr eElse) {
- if (myUseProcedurePredicates) {
- return new NAryExpr(Token.NoToken,
- new IfThenElse(Token.NoToken),
- new List<Expr> { fp, then, eElse });
- } else {
- return then;
- }
- }
-
- public static void Predicate(Program p,
- Func<Procedure, bool> useProcedurePredicates = null,
- UniformityAnalyser uni = null) {
- useProcedurePredicates = useProcedurePredicates ?? (proc => false);
- if (uni != null) {
- var oldUPP = useProcedurePredicates;
- useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name);
- }
-
- foreach (var decl in p.TopLevelDeclarations.ToList()) {
- if (decl is Procedure || decl is Implementation) {
- var proc = decl as Procedure;
- Implementation impl = null;
- if (proc == null) {
- impl = (Implementation)decl;
- proc = impl.Proc;
- }
-
- bool upp = useProcedurePredicates(proc);
- if (upp) {
- var dwf = (DeclWithFormals)decl;
- var fpVar = new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "_P",
- Microsoft.Boogie.Type.Bool),
- /*incoming=*/true);
- dwf.InParams = new List<Variable>(
- (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>()))
- .ToArray());
-
- if (impl == null) {
- var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar);
- foreach (Requires r in proc.Requires) {
- new EnabledReplacementVisitor(fpIdentifierExpr, Expr.True).VisitExpr(r.Condition);
- if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) {
- r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition);
- }
- }
- foreach (Ensures e in proc.Ensures) {
- new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar), Expr.True).VisitExpr(e.Condition);
- if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) {
- e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition);
- }
- }
- }
- } else {
- if (impl == null) {
- foreach (Requires r in proc.Requires) {
- new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(r.Condition);
- }
- foreach (Ensures e in proc.Ensures) {
- new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(e.Condition);
- }
- }
- }
-
- if (impl != null) {
- try {
- new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation();
- } catch (Program.IrreducibleLoopException) { }
- }
- }
- }
- }
-
- public static void Predicate(Program p, Implementation impl) {
- try {
- new SmartBlockPredicator(p, impl, proc => false, null).PredicateImplementation();
- }
- catch (Program.IrreducibleLoopException) { }
- }
-
-}
-
-class EnabledReplacementVisitor : StandardVisitor
-{
- private Expr pExpr;
- private Expr pDomExpr;
-
- internal EnabledReplacementVisitor(Expr pExpr, Expr pDomExpr)
- {
- this.pExpr = pExpr;
- this.pDomExpr = pDomExpr;
- }
-
- public override Expr VisitExpr(Expr node)
- {
- if (node is IdentifierExpr)
- {
- IdentifierExpr iExpr = node as IdentifierExpr;
- if (iExpr.Decl is Constant && QKeyValue.FindBoolAttribute(iExpr.Decl.Attributes, "__enabled"))
- {
- return pExpr;
- } else if (iExpr.Decl is Constant && QKeyValue.FindBoolAttribute(iExpr.Decl.Attributes, "__dominator_enabled"))
- {
- return pDomExpr;
- }
- }
- return base.VisitExpr(node);
- }
-}
-
-}
+using Microsoft.Boogie.GraphUtil;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Linq;
+
+namespace Microsoft.Boogie {
+
+public class SmartBlockPredicator {
+
+ Program prog;
+ Implementation impl;
+ Graph<Block> blockGraph;
+ List<Tuple<Block, bool>> sortedBlocks;
+
+ Func<Procedure, bool> useProcedurePredicates;
+
+ Dictionary<Block, Variable> predMap, defMap;
+ Dictionary<Block, HashSet<Variable>> ownedMap;
+ Dictionary<Block, Block> parentMap;
+ Dictionary<Block, PartInfo> partInfo;
+
+ IdentifierExpr fp;
+ Dictionary<Microsoft.Boogie.Type, IdentifierExpr> havocVars =
+ new Dictionary<Microsoft.Boogie.Type, IdentifierExpr>();
+ HashSet<Block> doneBlocks = new HashSet<Block>();
+ bool myUseProcedurePredicates;
+ UniformityAnalyser uni;
+
+ SmartBlockPredicator(Program p, Implementation i, Func<Procedure, bool> upp, UniformityAnalyser u) {
+ prog = p;
+ impl = i;
+ useProcedurePredicates = upp;
+ myUseProcedurePredicates = useProcedurePredicates(i.Proc);
+ uni = u;
+ }
+
+ void PredicateCmd(Expr p, Expr pDom, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) {
+ var cCmd = cmd as CallCmd;
+ if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) {
+ if (p == null) {
+ block.Cmds.Add(cmd);
+ nextBlock = block;
+ return;
+ }
+
+ var trueBlock = new Block();
+ blocks.Add(trueBlock);
+ trueBlock.Label = block.Label + ".call.true";
+ trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p));
+ trueBlock.Cmds.Add(cmd);
+
+ var falseBlock = new Block();
+ blocks.Add(falseBlock);
+ falseBlock.Label = block.Label + ".call.false";
+ falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p)));
+
+ var contBlock = new Block();
+ blocks.Add(contBlock);
+ contBlock.Label = block.Label + ".call.cont";
+
+ block.TransferCmd =
+ new GotoCmd(Token.NoToken, new List<Block> { trueBlock, falseBlock });
+ trueBlock.TransferCmd = falseBlock.TransferCmd =
+ new GotoCmd(Token.NoToken, new List<Block> { contBlock });
+ nextBlock = contBlock;
+ } else {
+ PredicateCmd(p, pDom, block.Cmds, cmd);
+ nextBlock = block;
+ }
+ }
+
+ void PredicateCmd(Expr p, Expr pDom, List<Cmd> cmdSeq, Cmd cmd) {
+ if (cmd is CallCmd) {
+ var cCmd = (CallCmd)cmd;
+ Debug.Assert(useProcedurePredicates(cCmd.Proc));
+ cCmd.Ins.Insert(0, p != null ? p : Expr.True);
+ cmdSeq.Add(cCmd);
+ } else if (p == null) {
+ new EnabledReplacementVisitor(Expr.True, pDom).Visit(cmd);
+ cmdSeq.Add(cmd);
+ } else if (cmd is AssignCmd) {
+ var aCmd = (AssignCmd)cmd;
+ cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss,
+ new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) =>
+ new NAryExpr(Token.NoToken,
+ new IfThenElse(Token.NoToken),
+ new List<Expr> { p, rhs, lhs.AsExpr })))));
+ } else if (cmd is AssertCmd) {
+ var aCmd = (AssertCmd)cmd;
+ Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr);
+ aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr);
+ cmdSeq.Add(aCmd);
+ } else if (cmd is AssumeCmd) {
+ var aCmd = (AssumeCmd)cmd;
+ Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr);
+ aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr);
+ cmdSeq.Add(aCmd);
+ } else if (cmd is HavocCmd) {
+ var hCmd = (HavocCmd)cmd;
+ foreach (IdentifierExpr v in hCmd.Vars) {
+ Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type;
+ Contract.Assert(type != null);
+
+ IdentifierExpr havocTempExpr;
+ if (havocVars.ContainsKey(type)) {
+ havocTempExpr = havocVars[type];
+ } else {
+ var havocVar = new LocalVariable(Token.NoToken,
+ new TypedIdent(Token.NoToken,
+ "_HAVOC_" + type.ToString(), type));
+ impl.LocVars.Add(havocVar);
+ havocVars[type] = havocTempExpr =
+ new IdentifierExpr(Token.NoToken, havocVar);
+ }
+ cmdSeq.Add(new HavocCmd(Token.NoToken,
+ new List<IdentifierExpr> { havocTempExpr }));
+ cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v,
+ new NAryExpr(Token.NoToken,
+ new IfThenElse(Token.NoToken),
+ new List<Expr> { p, havocTempExpr, v })));
+ }
+ } else if (cmd is CommentCmd) {
+ // skip
+ } else if (cmd is StateCmd) {
+ var sCmd = (StateCmd)cmd;
+ var newCmdSeq = new List<Cmd>();
+ foreach (Cmd c in sCmd.Cmds)
+ PredicateCmd(p, pDom, newCmdSeq, c);
+ sCmd.Cmds = newCmdSeq;
+ cmdSeq.Add(sCmd);
+ } else {
+ Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
+ }
+ }
+
+ // hasPredicatedRegion is true iff the block or its targets are predicated
+ // (i.e. we enter, stay within or exit a predicated region).
+ void PredicateTransferCmd(Expr p, Block src, List<Cmd> cmdSeq, TransferCmd cmd, out bool hasPredicatedRegion) {
+ hasPredicatedRegion = predMap.ContainsKey(src);
+
+ if (cmd is GotoCmd) {
+ var gCmd = (GotoCmd)cmd;
+
+ hasPredicatedRegion = hasPredicatedRegion ||
+ gCmd.labelTargets.Cast<Block>().Any(b => predMap.ContainsKey(b));
+
+ if (gCmd.labelTargets.Count == 1) {
+ if (defMap.ContainsKey(gCmd.labelTargets[0])) {
+ PredicateCmd(p, Expr.True, cmdSeq,
+ Cmd.SimpleAssign(Token.NoToken,
+ Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True));
+ }
+ } else {
+ Debug.Assert(gCmd.labelTargets.Count > 1);
+ Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => uni.IsUniform(impl.Name, t) ||
+ partInfo.ContainsKey(t)));
+ foreach (Block target in gCmd.labelTargets) {
+ if (!partInfo.ContainsKey(target))
+ continue;
+
+ // In this case we not only predicate with the current predicate p,
+ // but also with the "part predicate"; this ensures that we do not
+ // update a predicate twice when it occurs in both parts.
+ var part = partInfo[target];
+ if (defMap.ContainsKey(part.realDest)) {
+ PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq,
+ Cmd.SimpleAssign(Token.NoToken,
+ Expr.Ident(predMap[part.realDest]), part.pred));
+ }
+ var predsExitingLoop = new Dictionary<Block, List<Expr>>();
+ foreach (Block exit in LoopsExited(src, target)) {
+ List<Expr> predList;
+ if (!predsExitingLoop.ContainsKey(exit))
+ predList = predsExitingLoop[exit] = new List<Expr>();
+ else
+ predList = predsExitingLoop[exit];
+ predList.Add(part.pred);
+ }
+ foreach (var pred in predsExitingLoop) {
+ PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq,
+ Cmd.SimpleAssign(Token.NoToken,
+ Expr.Ident(predMap[pred.Key]),
+ Expr.Not(pred.Value.Aggregate(Expr.Or))));
+ }
+ }
+ }
+ } else if (cmd is ReturnCmd) {
+ // Blocks which end in a return will never share a predicate with a block
+ // which appears after it. Furthermore, such a block cannot be part of a
+ // loop. So it is safe to do nothing here.
+ } else {
+ Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
+ }
+ }
+
+ Variable FreshPredicate(ref int predCount) {
+ var pVar = new LocalVariable(Token.NoToken,
+ new TypedIdent(Token.NoToken,
+ "p" + predCount++,
+ Microsoft.Boogie.Type.Bool));
+ impl.LocVars.Add(pVar);
+ return pVar;
+ }
+
+ void AssignPredicates(Graph<Block> blockGraph,
+ DomRelation<Block> dom,
+ DomRelation<Block> pdom,
+ IEnumerable<Block> headerDominance,
+ IEnumerator<Tuple<Block, bool>> i,
+ Variable headPredicate,
+ ref int predCount) {
+ var header = i.Current.Item1;
+ var regionPreds = new List<Tuple<Block, Variable>>();
+ var ownedPreds = new HashSet<Variable>();
+ ownedMap[header] = ownedPreds;
+
+ if (headPredicate != null) {
+ predMap[header] = headPredicate;
+ defMap[header] = headPredicate;
+ regionPreds.Add(new Tuple<Block, Variable>(header, headPredicate));
+ }
+
+ while (i.MoveNext()) {
+ var block = i.Current;
+
+ if (block.Item2) {
+ if (block.Item1 == header) {
+ return;
+ }
+ }
+
+ if (uni != null && uni.IsUniform(impl.Name, block.Item1)) {
+ if (blockGraph.Headers.Contains(block.Item1)) {
+ parentMap[block.Item1] = header;
+ AssignPredicates(blockGraph, dom, pdom, headerDominance, i, headPredicate, ref predCount);
+ }
+ continue;
+ }
+
+ if (!block.Item2) {
+ if (blockGraph.Headers.Contains(block.Item1)) {
+ parentMap[block.Item1] = header;
+ var loopPred = FreshPredicate(ref predCount);
+ ownedPreds.Add(loopPred);
+ AssignPredicates(blockGraph, dom, pdom, headerDominance, i, loopPred, ref predCount);
+ } else {
+ bool foundExisting = false;
+ foreach (var regionPred in regionPreds) {
+ if (dom.DominatedBy(block.Item1, regionPred.Item1) &&
+ pdom.DominatedBy(regionPred.Item1, block.Item1)) {
+ predMap[block.Item1] = regionPred.Item2;
+ foundExisting = true;
+ break;
+ }
+ }
+ if (!foundExisting) {
+ var condPred = FreshPredicate(ref predCount);
+ predMap[block.Item1] = condPred;
+ defMap[block.Item1] = condPred;
+ var headerIterator = headerDominance.GetEnumerator();
+ // Add the predicate to the loop header H that dominates the node (if one
+ // exists) such that H does not dominate another header which also dominates
+ // the node. Since predicates are owned by loop headers (or the program entry
+ // node), this is the block 'closest' to block to which we are assigning a
+ // that can be made to own the predicate.
+ Block node = null;
+ while (headerIterator.MoveNext()) {
+ var current = headerIterator.Current;
+ if (dom.DominatedBy(block.Item1, current)) {
+ node = current;
+ break;
+ }
+ }
+ if (node != null) {
+ ownedMap[node].Add(condPred);
+ } else {
+ // In this case the header is the program entry node.
+ ownedPreds.Add(condPred);
+ }
+ regionPreds.Add(new Tuple<Block, Variable>(block.Item1, condPred));
+ }
+ }
+ }
+ }
+ }
+
+ void AssignPredicates() {
+ DomRelation<Block> dom = blockGraph.DominatorMap;
+
+ Graph<Block> dualGraph = blockGraph.Dual(new Block());
+ DomRelation<Block> pdom = dualGraph.DominatorMap;
+ IEnumerable<Block> headerDominance = blockGraph.SortHeadersByDominance();
+
+ var iter = sortedBlocks.GetEnumerator();
+ if (!iter.MoveNext()) {
+ predMap = defMap = null;
+ ownedMap = null;
+ return;
+ }
+
+ int predCount = 0;
+ predMap = new Dictionary<Block, Variable>();
+ defMap = new Dictionary<Block, Variable>();
+ ownedMap = new Dictionary<Block, HashSet<Variable>>();
+ parentMap = new Dictionary<Block, Block>();
+ AssignPredicates(blockGraph, dom, pdom, headerDominance, iter,
+ myUseProcedurePredicates ? impl.InParams[0] : null,
+ ref predCount);
+ }
+
+ IEnumerable<Block> LoopsExited(Block src, Block dest) {
+ var i = sortedBlocks.GetEnumerator();
+ while (i.MoveNext()) {
+ var b = i.Current;
+ if (b.Item1 == src) {
+ return LoopsExitedForwardEdge(dest, i);
+ } else if (b.Item1 == dest) {
+ return LoopsExitedBackEdge(src, i);
+ }
+ }
+ Debug.Assert(false);
+ return null;
+ }
+
+ private IEnumerable<Block> LoopsExitedBackEdge(Block src, IEnumerator<Tuple<Block, bool>> i) {
+ var headsSeen = new HashSet<Block>();
+ while (i.MoveNext()) {
+ var b = i.Current;
+ if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
+ headsSeen.Add(b.Item1);
+ else if (b.Item2)
+ headsSeen.Remove(b.Item1);
+ if (b.Item1 == src)
+ return headsSeen;
+ }
+ Debug.Assert(false);
+ return null;
+ }
+
+ private IEnumerable<Block> LoopsExitedForwardEdge(Block dest, IEnumerator<Tuple<Block, bool>> i) {
+ var headsSeen = new HashSet<Block>();
+ while (i.MoveNext()) {
+ var b = i.Current;
+ if (b.Item1 == dest)
+ yield break;
+ else if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
+ headsSeen.Add(b.Item1);
+ else if (b.Item2 && !headsSeen.Contains(b.Item1))
+ yield return b.Item1;
+ }
+ Debug.Assert(false);
+ }
+
+ class PartInfo {
+ public PartInfo(Expr p, Block r) { pred = p; realDest = r; }
+ public Expr pred;
+ public Block realDest;
+ }
+
+ Dictionary<Block, PartInfo> BuildPartitionInfo() {
+ var partInfo = new Dictionary<Block, PartInfo>();
+ foreach (var block in blockGraph.Nodes) {
+ if (uni.IsUniform(impl.Name, block))
+ continue;
+
+ var parts = block.Cmds.Cast<Cmd>().TakeWhile(
+ c => c is AssumeCmd &&
+ QKeyValue.FindBoolAttribute(((AssumeCmd)c).Attributes, "partition"));
+
+ Expr pred = null;
+ if (parts.Count() > 0) {
+ pred = parts.Select(a => ((AssumeCmd)a).Expr).Aggregate(Expr.And);
+ block.Cmds =
+ new List<Cmd>(block.Cmds.Cast<Cmd>().Skip(parts.Count()).ToArray());
+ } else {
+ continue;
+ }
+
+ Block realDest = block;
+ if (block.Cmds.Count == 0) {
+ var gc = block.TransferCmd as GotoCmd;
+ if (gc != null && gc.labelTargets.Count == 1)
+ realDest = gc.labelTargets[0];
+ }
+ partInfo[block] = new PartInfo(pred, realDest);
+ }
+
+ return partInfo;
+ }
+
+ Block FindImmediateDominator(Block block) {
+ Block predecessor = null;
+ foreach(var pred in blockGraph.Predecessors(block)) {
+ if (!blockGraph.DominatorMap.DominatedBy(pred, block)) {
+ if (predecessor == null)
+ predecessor = pred;
+ else
+ predecessor = blockGraph.DominatorMap.LeastCommonAncestor(pred, predecessor);
+ }
+ }
+ return predecessor;
+ }
+
+ void PredicateImplementation() {
+ blockGraph = prog.ProcessLoops(impl);
+ sortedBlocks = blockGraph.LoopyTopSort();
+
+ AssignPredicates();
+ partInfo = BuildPartitionInfo();
+
+ if (myUseProcedurePredicates)
+ fp = Expr.Ident(impl.InParams[0]);
+
+ var newBlocks = new List<Block>();
+ Block prevBlock = null;
+ foreach (var n in sortedBlocks) {
+ if (predMap.ContainsKey(n.Item1)) {
+ var p = predMap[n.Item1];
+ var pExpr = Expr.Ident(p);
+
+ if (n.Item2) {
+ var dominator = FindImmediateDominator(n.Item1);
+ if (dominator != null && predMap.ContainsKey(dominator)) {
+ AssumeCmd aCmd = new AssumeCmd(Token.NoToken, Expr.True);
+ aCmd.Attributes = new QKeyValue(Token.NoToken, "dominator_predicate", new List<object>() { predMap[dominator].ToString() }, aCmd.Attributes);
+ aCmd.Attributes = new QKeyValue(Token.NoToken, "predicate", new List<object>() { predMap[n.Item1].ToString() }, aCmd.Attributes);
+ n.Item1.Cmds.Insert(0, aCmd);
+ }
+
+ var backedgeBlock = new Block();
+ newBlocks.Add(backedgeBlock);
+
+ backedgeBlock.Label = n.Item1.Label + ".backedge";
+ backedgeBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, pExpr,
+ new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)) };
+ backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
+ new List<Block> { n.Item1 });
+
+ var tailBlock = new Block();
+ newBlocks.Add(tailBlock);
+
+ tailBlock.Label = n.Item1.Label + ".tail";
+ tailBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken,
+ Expr.Not(pExpr)) };
+
+ if (uni != null && !uni.IsUniform(impl.Name, n.Item1)) {
+ uni.AddNonUniform(impl.Name, backedgeBlock);
+ uni.AddNonUniform(impl.Name, tailBlock);
+ }
+
+ if (prevBlock != null)
+ prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
+ new List<Block> { backedgeBlock, tailBlock });
+ prevBlock = tailBlock;
+ } else {
+ PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock);
+ }
+ } else {
+ if (!n.Item2) {
+ PredicateBlock(null, n.Item1, newBlocks, ref prevBlock);
+ }
+ }
+ }
+
+ if (prevBlock != null)
+ prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);
+
+ impl.Blocks = newBlocks;
+ }
+
+ private void PredicateBlock(Expr pExpr, Block block, List<Block> newBlocks, ref Block prevBlock) {
+ var firstBlock = block;
+
+ var oldCmdSeq = block.Cmds;
+ block.Cmds = new List<Cmd>();
+ newBlocks.Add(block);
+ if (prevBlock != null && !((prevBlock.TransferCmd is ReturnCmd) && uni != null && uni.IsUniform(impl.Name, block))) {
+ prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { block });
+ }
+
+ Block currentBlock = block;
+ Expr pCurrentExpr = pExpr;
+ while (parentMap.ContainsKey(currentBlock)) {
+ Block parent = parentMap[currentBlock];
+ Expr pParentExpr = null;
+ if (predMap.ContainsKey(parent)) {
+ var parentPred = predMap[parent];
+ if (parentPred != null) {
+ pParentExpr = Expr.Ident(parentPred);
+ block.Cmds.Add(new AssertCmd(Token.NoToken,
+ pCurrentExpr != null ? (Expr)Expr.Imp(pCurrentExpr, pParentExpr)
+ : pParentExpr));
+ }
+ }
+ currentBlock = parent;
+ pCurrentExpr = pParentExpr;
+ }
+
+ Block dominator = FindImmediateDominator(block);
+ Expr pDomExpr = Expr.True;
+ if (dominator != null && predMap.ContainsKey(dominator))
+ pDomExpr = new IdentifierExpr(Token.NoToken, predMap[dominator]);
+ var transferCmd = block.TransferCmd;
+ foreach (Cmd cmd in oldCmdSeq)
+ PredicateCmd(pExpr, pDomExpr, newBlocks, block, cmd, out block);
+
+ if (ownedMap.ContainsKey(firstBlock)) {
+ var owned = ownedMap[firstBlock];
+ foreach (var v in owned)
+ block.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False));
+ }
+
+ bool hasPredicatedRegion;
+ PredicateTransferCmd(pExpr, block, block.Cmds, transferCmd, out hasPredicatedRegion);
+
+ if (hasPredicatedRegion)
+ prevBlock = block;
+ else
+ prevBlock = null;
+
+ doneBlocks.Add(block);
+ }
+
+ private Expr CreateIfFPThenElse(Expr then, Expr eElse) {
+ if (myUseProcedurePredicates) {
+ return new NAryExpr(Token.NoToken,
+ new IfThenElse(Token.NoToken),
+ new List<Expr> { fp, then, eElse });
+ } else {
+ return then;
+ }
+ }
+
+ public static void Predicate(Program p,
+ Func<Procedure, bool> useProcedurePredicates = null,
+ UniformityAnalyser uni = null) {
+ useProcedurePredicates = useProcedurePredicates ?? (proc => false);
+ if (uni != null) {
+ var oldUPP = useProcedurePredicates;
+ useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name);
+ }
+
+ foreach (var decl in p.TopLevelDeclarations.ToList()) {
+ if (decl is Procedure || decl is Implementation) {
+ var proc = decl as Procedure;
+ Implementation impl = null;
+ if (proc == null) {
+ impl = (Implementation)decl;
+ proc = impl.Proc;
+ }
+
+ bool upp = useProcedurePredicates(proc);
+ if (upp) {
+ var dwf = (DeclWithFormals)decl;
+ var fpVar = new Formal(Token.NoToken,
+ new TypedIdent(Token.NoToken, "_P",
+ Microsoft.Boogie.Type.Bool),
+ /*incoming=*/true);
+ dwf.InParams = new List<Variable>(
+ (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>()))
+ .ToArray());
+
+ if (impl == null) {
+ var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar);
+ foreach (Requires r in proc.Requires) {
+ new EnabledReplacementVisitor(fpIdentifierExpr, Expr.True).VisitExpr(r.Condition);
+ if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) {
+ r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition);
+ }
+ }
+ foreach (Ensures e in proc.Ensures) {
+ new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar), Expr.True).VisitExpr(e.Condition);
+ if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) {
+ e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition);
+ }
+ }
+ }
+ } else {
+ if (impl == null) {
+ foreach (Requires r in proc.Requires) {
+ new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(r.Condition);
+ }
+ foreach (Ensures e in proc.Ensures) {
+ new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(e.Condition);
+ }
+ }
+ }
+
+ if (impl != null) {
+ try {
+ new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation();
+ } catch (Program.IrreducibleLoopException) { }
+ }
+ }
+ }
+ }
+
+ public static void Predicate(Program p, Implementation impl) {
+ try {
+ new SmartBlockPredicator(p, impl, proc => false, null).PredicateImplementation();
+ }
+ catch (Program.IrreducibleLoopException) { }
+ }
+
+}
+
+class EnabledReplacementVisitor : StandardVisitor
+{
+ private Expr pExpr;
+ private Expr pDomExpr;
+
+ internal EnabledReplacementVisitor(Expr pExpr, Expr pDomExpr)
+ {
+ this.pExpr = pExpr;
+ this.pDomExpr = pDomExpr;
+ }
+
+ public override Expr VisitExpr(Expr node)
+ {
+ if (node is IdentifierExpr)
+ {
+ IdentifierExpr iExpr = node as IdentifierExpr;
+ if (iExpr.Decl is Constant && QKeyValue.FindBoolAttribute(iExpr.Decl.Attributes, "__enabled"))
+ {
+ return pExpr;
+ } else if (iExpr.Decl is Constant && QKeyValue.FindBoolAttribute(iExpr.Decl.Attributes, "__dominator_enabled"))
+ {
+ return pDomExpr;
+ }
+ }
+ return base.VisitExpr(node);
+ }
+}
+
+}
diff --git a/Source/Predication/UniformityAnalyser.cs b/Source/Predication/UniformityAnalyser.cs
index ff298942..5ab2589f 100644
--- a/Source/Predication/UniformityAnalyser.cs
+++ b/Source/Predication/UniformityAnalyser.cs
@@ -1,541 +1,541 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using System.Diagnostics;
-using Microsoft.Boogie.GraphUtil;
-
-namespace Microsoft.Boogie
-{
-
- public class UniformityAnalyser
- {
- private Program prog;
-
- private bool doAnalysis;
-
- private ISet<Implementation> entryPoints;
-
- private IEnumerable<Variable> nonUniformVars;
-
- private bool ProcedureChanged;
-
- private Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>> uniformityInfo;
-
- private Dictionary<string, HashSet<int>> nonUniformLoops;
-
- private Dictionary<string, HashSet<Block>> nonUniformBlocks;
-
- private Dictionary<string, HashSet<int>> loopsWithNonuniformReturn;
-
- private Dictionary<string, List<string>> inParameters;
-
- private Dictionary<string, List<string>> outParameters;
-
- /// <summary>
- /// Simplifies the CFG of the given implementation impl by merging each
- /// basic block with a single predecessor into that predecessor if the
- /// predecessor has a single successor. If a uniformity analyser is
- /// being used then blocks will only be merged if they are both uniform
- /// or both non-uniform
- /// </summary>
- public static void MergeBlocksIntoPredecessors(Program prog, Implementation impl, UniformityAnalyser uni)
- {
- var blockGraph = prog.ProcessLoops(impl);
- var predMap = new Dictionary<Block, Block>();
- foreach (var block in blockGraph.Nodes)
- {
- try
- {
- var pred = blockGraph.Predecessors(block).Single();
- if (blockGraph.Successors(pred).Single() == block &&
- (uni == null ||
- (uni.IsUniform(impl.Name, pred) && uni.IsUniform(impl.Name, block)) ||
- (!uni.IsUniform(impl.Name, pred) && !uni.IsUniform(impl.Name, block))))
- {
- Block predMapping;
- while (predMap.TryGetValue(pred, out predMapping))
- pred = predMapping;
- pred.Cmds.AddRange(block.Cmds);
- pred.TransferCmd = block.TransferCmd;
- impl.Blocks.Remove(block);
- predMap[block] = pred;
- }
- // If Single throws an exception above (i.e. not exactly one pred/succ), skip this block.
- }
- catch (InvalidOperationException) { }
- }
- }
-
- public UniformityAnalyser(Program prog, bool doAnalysis, ISet<Implementation> entryPoints, IEnumerable<Variable> nonUniformVars)
- {
- this.prog = prog;
- this.doAnalysis = doAnalysis;
- this.entryPoints = entryPoints;
- this.nonUniformVars = nonUniformVars;
- uniformityInfo = new Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>>();
- nonUniformLoops = new Dictionary<string, HashSet<int>>();
- nonUniformBlocks = new Dictionary<string, HashSet<Block>>();
- loopsWithNonuniformReturn = new Dictionary<string, HashSet<int>>();
- inParameters = new Dictionary<string, List<string>>();
- outParameters = new Dictionary<string, List<string>>();
- }
-
- public void Analyse()
- {
- var impls = prog.Implementations;
-
- foreach (var Impl in impls)
- {
- bool uniformProcedure = doAnalysis || entryPoints.Contains(Impl);
-
- uniformityInfo.Add(Impl.Name, new KeyValuePair<bool, Dictionary<string, bool>>
- (uniformProcedure, new Dictionary<string, bool> ()));
-
- nonUniformLoops.Add(Impl.Name, new HashSet<int>());
- loopsWithNonuniformReturn.Add(Impl.Name, new HashSet<int>());
-
- foreach (var v in nonUniformVars)
- SetNonUniform(Impl.Name, v.Name);
-
- foreach (Variable v in Impl.LocVars)
- {
- if (doAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- inParameters[Impl.Name] = new List<string>();
-
- foreach (Variable v in Impl.InParams)
- {
- inParameters[Impl.Name].Add(v.Name);
- if (doAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- outParameters[Impl.Name] = new List<string>();
- foreach (Variable v in Impl.OutParams)
- {
- outParameters[Impl.Name].Add(v.Name);
- if (doAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- ProcedureChanged = true;
- }
-
- var procs = prog.Procedures;
-
- foreach (var Proc in procs) {
-
- if (uniformityInfo.ContainsKey(Proc.Name)) {
- continue;
- }
-
- bool uniformProcedure = doAnalysis;
-
- uniformityInfo.Add(Proc.Name, new KeyValuePair<bool, Dictionary<string, bool>>
- (uniformProcedure, new Dictionary<string, bool>()));
-
- inParameters[Proc.Name] = new List<string>();
-
- foreach (Variable v in Proc.InParams) {
- inParameters[Proc.Name].Add(v.Name);
- if (doAnalysis) {
- SetUniform(Proc.Name, v.Name);
- }
- else {
- SetNonUniform(Proc.Name, v.Name);
- }
- }
-
- outParameters[Proc.Name] = new List<string>();
- foreach (Variable v in Proc.OutParams) {
- outParameters[Proc.Name].Add(v.Name);
- // We do not have a body for the procedure,
- // so we must assume it produces non-uniform
- // results
- SetNonUniform(Proc.Name, v.Name);
- }
-
- ProcedureChanged = true;
- }
-
-
- if (doAnalysis)
- {
- while (ProcedureChanged)
- {
- ProcedureChanged = false;
-
- foreach (var Impl in impls)
- {
- Analyse(Impl, uniformityInfo[Impl.Name].Key);
- }
- }
- }
-
- foreach (var Proc in procs)
- {
- if (!IsUniform (Proc.Name))
- {
- List<string> newIns = new List<String>();
- newIns.Add("_P");
- foreach (string s in inParameters[Proc.Name])
- {
- newIns.Add(s);
- }
- inParameters[Proc.Name] = newIns;
- }
- }
- }
-
- private void Analyse(Implementation Impl, bool ControlFlowIsUniform)
- {
- if (!ControlFlowIsUniform)
- {
- nonUniformBlocks[Impl.Name] = new HashSet<Block>(Impl.Blocks);
-
- foreach (Variable v in Impl.LocVars) {
- if (IsUniform(Impl.Name, v.Name)) {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- foreach (Variable v in Impl.InParams) {
- if (IsUniform(Impl.Name, v.Name)) {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- foreach (Variable v in Impl.OutParams) {
- if (IsUniform(Impl.Name, v.Name)) {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- foreach (Block b in Impl.Blocks) {
- Analyse(Impl, b.Cmds, false);
- }
-
- return;
- }
-
- Graph<Block> blockGraph = prog.ProcessLoops(Impl);
- var ctrlDep = blockGraph.ControlDependence();
-
- // Compute transitive closure of control dependence info.
- ctrlDep.TransitiveClosure();
-
- var nonUniformBlockSet = new HashSet<Block>();
- nonUniformBlocks[Impl.Name] = nonUniformBlockSet;
-
- bool changed;
- do {
- changed = false;
- foreach (var block in Impl.Blocks) {
- bool uniform = !nonUniformBlockSet.Contains(block);
- bool newUniform = Analyse(Impl, block.Cmds, uniform);
- if (uniform && !newUniform) {
- changed = true;
- nonUniformBlockSet.Add(block);
- Block pred = blockGraph.Predecessors(block).Single();
- if (ctrlDep.ContainsKey(pred))
- nonUniformBlockSet.UnionWith(ctrlDep[pred]);
- }
- }
- } while (changed);
- }
-
- private Procedure GetProcedure(string procedureName)
- {
- foreach (var p in prog.Procedures)
- {
- if (p.Name == procedureName)
- {
- return p;
- }
- }
- Debug.Assert(false);
- return null;
- }
-
- private bool Analyse(Implementation impl, List<Cmd> cmdSeq, bool ControlFlowIsUniform)
- {
- foreach (Cmd c in cmdSeq)
- {
- if (c is AssignCmd)
- {
- AssignCmd assignCmd = c as AssignCmd;
- foreach (var a in assignCmd.Lhss.Zip(assignCmd.Rhss))
- {
-
- if (a.Item1 is SimpleAssignLhs)
- {
- SimpleAssignLhs lhs = a.Item1 as SimpleAssignLhs;
- Expr rhs = a.Item2;
- if (IsUniform(impl.Name, lhs.AssignedVariable.Name) &&
- (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs)))
- {
- SetNonUniform(impl.Name, lhs.AssignedVariable.Name);
- }
-
- }
- }
- }
- else if (c is HavocCmd)
- {
- HavocCmd havocCmd = c as HavocCmd;
- foreach(IdentifierExpr ie in havocCmd.Vars)
- {
- if(IsUniform(impl.Name, ie.Decl.Name)) {
- SetNonUniform(impl.Name, ie.Decl.Name);
- }
- }
- }
- else if (c is CallCmd)
- {
- CallCmd callCmd = c as CallCmd;
- DeclWithFormals Callee = GetProcedure(callCmd.callee);
- Debug.Assert(Callee != null);
-
- if (!ControlFlowIsUniform)
- {
- if (IsUniform(callCmd.callee))
- {
- SetNonUniform(callCmd.callee);
- }
- }
- for (int i = 0; i < Callee.InParams.Count; i++)
- {
- if (IsUniform(callCmd.callee, Callee.InParams[i].Name)
- && !IsUniform(impl.Name, callCmd.Ins[i]))
- {
- SetNonUniform(callCmd.callee, Callee.InParams[i].Name);
- }
- }
-
- for (int i = 0; i < Callee.OutParams.Count; i++)
- {
- if (IsUniform(impl.Name, callCmd.Outs[i].Name)
- && !IsUniform(callCmd.callee, Callee.OutParams[i].Name))
- {
- SetNonUniform(impl.Name, callCmd.Outs[i].Name);
- }
- }
-
- }
- else if (c is AssumeCmd)
- {
- var ac = (AssumeCmd)c;
- if (ControlFlowIsUniform && QKeyValue.FindBoolAttribute(ac.Attributes, "partition") &&
- !IsUniform(impl.Name, ac.Expr))
- {
- ControlFlowIsUniform = false;
- }
- }
- }
-
- return ControlFlowIsUniform;
- }
-
- private int GetLoopId(WhileCmd wc)
- {
- AssertCmd inv = wc.Invariants[0] as AssertCmd;
- Debug.Assert(inv.Attributes.Key.Contains("loophead_"));
- return Convert.ToInt32(inv.Attributes.Key.Substring("loophead_".Length));
- }
-
- private void SetNonUniform(string procedureName)
- {
- uniformityInfo[procedureName] = new KeyValuePair<bool,Dictionary<string,bool>>
- (false, uniformityInfo[procedureName].Value);
- RecordProcedureChanged();
- }
-
- private void SetNonUniform(string procedureName, WhileCmd wc)
- {
- nonUniformLoops[procedureName].Add(GetLoopId(wc));
- RecordProcedureChanged();
- }
-
- public bool IsUniform(string procedureName)
- {
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
- return uniformityInfo[procedureName].Key;
- }
-
- public bool IsUniform(string procedureName, Block b)
- {
- if (!nonUniformBlocks.ContainsKey(procedureName))
- {
- return false;
- }
- return !nonUniformBlocks[procedureName].Contains(b);
- }
-
- class UniformExpressionAnalysisVisitor : ReadOnlyVisitor {
-
- private bool isUniform = true;
- private Dictionary<string, bool> uniformityInfo;
-
- public UniformExpressionAnalysisVisitor(Dictionary<string, bool> uniformityInfo) {
- this.uniformityInfo = uniformityInfo;
- }
-
- public override Variable VisitVariable(Variable v) {
- if (!uniformityInfo.ContainsKey(v.Name)) {
- isUniform = isUniform && (v is Constant);
- } else if (!uniformityInfo[v.Name]) {
- isUniform = false;
- }
-
- return v;
- }
-
- internal bool IsUniform() {
- return isUniform;
- }
- }
-
- public bool IsUniform(string procedureName, Expr expr)
- {
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
-
- UniformExpressionAnalysisVisitor visitor = new UniformExpressionAnalysisVisitor(uniformityInfo[procedureName].Value);
- visitor.VisitExpr(expr);
- return visitor.IsUniform();
- }
-
- public bool IsUniform(string procedureName, string v)
- {
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
-
- if (!uniformityInfo[procedureName].Value.ContainsKey(v))
- {
- return false;
- }
- return uniformityInfo[procedureName].Value[v];
- }
-
- private void SetUniform(string procedureName, string v)
- {
- uniformityInfo[procedureName].Value[v] = true;
- RecordProcedureChanged();
- }
-
- private void RecordProcedureChanged()
- {
- ProcedureChanged = true;
- }
-
- private void SetNonUniform(string procedureName, string v)
- {
- uniformityInfo[procedureName].Value[v] = false;
- RecordProcedureChanged();
- }
-
- public void dump()
- {
- foreach (string p in uniformityInfo.Keys)
- {
- Console.WriteLine("Procedure " + p + ": "
- + (uniformityInfo[p].Key ? "uniform" : "nonuniform"));
- foreach (string v in uniformityInfo[p].Value.Keys)
- {
- Console.WriteLine(" " + v + ": " +
- (uniformityInfo[p].Value[v] ? "uniform" : "nonuniform"));
- }
- Console.Write("Ins [");
- for (int i = 0; i < inParameters[p].Count; i++)
- {
- Console.Write((i == 0 ? "" : ", ") + inParameters[p][i]);
- }
- Console.WriteLine("]");
- Console.Write("Outs [");
- for (int i = 0; i < outParameters[p].Count; i++)
- {
- Console.Write((i == 0 ? "" : ", ") + outParameters[p][i]);
- }
- Console.WriteLine("]");
- if (nonUniformLoops.ContainsKey(p)) {
- Console.Write("Non-uniform loops:");
- foreach (int l in nonUniformLoops[p]) {
- Console.Write(" " + l);
- }
- Console.WriteLine();
- }
- if (nonUniformBlocks.ContainsKey(p)) {
- Console.Write("Non-uniform blocks:");
- foreach (Block b in nonUniformBlocks[p]) {
- Console.Write(" " + b.Label);
- }
- Console.WriteLine();
- }
- }
- }
-
-
- public string GetInParameter(string procName, int i)
- {
- return inParameters[procName][i];
- }
-
- public string GetOutParameter(string procName, int i)
- {
- return outParameters[procName][i];
- }
-
-
- public bool knowsOf(string p)
- {
- return uniformityInfo.ContainsKey(p);
- }
-
- public void AddNonUniform(string proc, string v)
- {
- if (uniformityInfo.ContainsKey(proc))
- {
- Debug.Assert(!uniformityInfo[proc].Value.ContainsKey(v));
- uniformityInfo[proc].Value[v] = false;
- }
- }
-
- public void AddNonUniform(string proc, Block b) {
- if (nonUniformBlocks.ContainsKey(proc)) {
- Debug.Assert(!nonUniformBlocks[proc].Contains(b));
- nonUniformBlocks[proc].Add(b);
- }
- }
-
- }
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+using Microsoft.Boogie.GraphUtil;
+
+namespace Microsoft.Boogie
+{
+
+ public class UniformityAnalyser
+ {
+ private Program prog;
+
+ private bool doAnalysis;
+
+ private ISet<Implementation> entryPoints;
+
+ private IEnumerable<Variable> nonUniformVars;
+
+ private bool ProcedureChanged;
+
+ private Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>> uniformityInfo;
+
+ private Dictionary<string, HashSet<int>> nonUniformLoops;
+
+ private Dictionary<string, HashSet<Block>> nonUniformBlocks;
+
+ private Dictionary<string, HashSet<int>> loopsWithNonuniformReturn;
+
+ private Dictionary<string, List<string>> inParameters;
+
+ private Dictionary<string, List<string>> outParameters;
+
+ /// <summary>
+ /// Simplifies the CFG of the given implementation impl by merging each
+ /// basic block with a single predecessor into that predecessor if the
+ /// predecessor has a single successor. If a uniformity analyser is
+ /// being used then blocks will only be merged if they are both uniform
+ /// or both non-uniform
+ /// </summary>
+ public static void MergeBlocksIntoPredecessors(Program prog, Implementation impl, UniformityAnalyser uni)
+ {
+ var blockGraph = prog.ProcessLoops(impl);
+ var predMap = new Dictionary<Block, Block>();
+ foreach (var block in blockGraph.Nodes)
+ {
+ try
+ {
+ var pred = blockGraph.Predecessors(block).Single();
+ if (blockGraph.Successors(pred).Single() == block &&
+ (uni == null ||
+ (uni.IsUniform(impl.Name, pred) && uni.IsUniform(impl.Name, block)) ||
+ (!uni.IsUniform(impl.Name, pred) && !uni.IsUniform(impl.Name, block))))
+ {
+ Block predMapping;
+ while (predMap.TryGetValue(pred, out predMapping))
+ pred = predMapping;
+ pred.Cmds.AddRange(block.Cmds);
+ pred.TransferCmd = block.TransferCmd;
+ impl.Blocks.Remove(block);
+ predMap[block] = pred;
+ }
+ // If Single throws an exception above (i.e. not exactly one pred/succ), skip this block.
+ }
+ catch (InvalidOperationException) { }
+ }
+ }
+
+ public UniformityAnalyser(Program prog, bool doAnalysis, ISet<Implementation> entryPoints, IEnumerable<Variable> nonUniformVars)
+ {
+ this.prog = prog;
+ this.doAnalysis = doAnalysis;
+ this.entryPoints = entryPoints;
+ this.nonUniformVars = nonUniformVars;
+ uniformityInfo = new Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>>();
+ nonUniformLoops = new Dictionary<string, HashSet<int>>();
+ nonUniformBlocks = new Dictionary<string, HashSet<Block>>();
+ loopsWithNonuniformReturn = new Dictionary<string, HashSet<int>>();
+ inParameters = new Dictionary<string, List<string>>();
+ outParameters = new Dictionary<string, List<string>>();
+ }
+
+ public void Analyse()
+ {
+ var impls = prog.Implementations;
+
+ foreach (var Impl in impls)
+ {
+ bool uniformProcedure = doAnalysis || entryPoints.Contains(Impl);
+
+ uniformityInfo.Add(Impl.Name, new KeyValuePair<bool, Dictionary<string, bool>>
+ (uniformProcedure, new Dictionary<string, bool> ()));
+
+ nonUniformLoops.Add(Impl.Name, new HashSet<int>());
+ loopsWithNonuniformReturn.Add(Impl.Name, new HashSet<int>());
+
+ foreach (var v in nonUniformVars)
+ SetNonUniform(Impl.Name, v.Name);
+
+ foreach (Variable v in Impl.LocVars)
+ {
+ if (doAnalysis)
+ {
+ SetUniform(Impl.Name, v.Name);
+ }
+ else
+ {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ inParameters[Impl.Name] = new List<string>();
+
+ foreach (Variable v in Impl.InParams)
+ {
+ inParameters[Impl.Name].Add(v.Name);
+ if (doAnalysis)
+ {
+ SetUniform(Impl.Name, v.Name);
+ }
+ else
+ {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ outParameters[Impl.Name] = new List<string>();
+ foreach (Variable v in Impl.OutParams)
+ {
+ outParameters[Impl.Name].Add(v.Name);
+ if (doAnalysis)
+ {
+ SetUniform(Impl.Name, v.Name);
+ }
+ else
+ {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ ProcedureChanged = true;
+ }
+
+ var procs = prog.Procedures;
+
+ foreach (var Proc in procs) {
+
+ if (uniformityInfo.ContainsKey(Proc.Name)) {
+ continue;
+ }
+
+ bool uniformProcedure = doAnalysis;
+
+ uniformityInfo.Add(Proc.Name, new KeyValuePair<bool, Dictionary<string, bool>>
+ (uniformProcedure, new Dictionary<string, bool>()));
+
+ inParameters[Proc.Name] = new List<string>();
+
+ foreach (Variable v in Proc.InParams) {
+ inParameters[Proc.Name].Add(v.Name);
+ if (doAnalysis) {
+ SetUniform(Proc.Name, v.Name);
+ }
+ else {
+ SetNonUniform(Proc.Name, v.Name);
+ }
+ }
+
+ outParameters[Proc.Name] = new List<string>();
+ foreach (Variable v in Proc.OutParams) {
+ outParameters[Proc.Name].Add(v.Name);
+ // We do not have a body for the procedure,
+ // so we must assume it produces non-uniform
+ // results
+ SetNonUniform(Proc.Name, v.Name);
+ }
+
+ ProcedureChanged = true;
+ }
+
+
+ if (doAnalysis)
+ {
+ while (ProcedureChanged)
+ {
+ ProcedureChanged = false;
+
+ foreach (var Impl in impls)
+ {
+ Analyse(Impl, uniformityInfo[Impl.Name].Key);
+ }
+ }
+ }
+
+ foreach (var Proc in procs)
+ {
+ if (!IsUniform (Proc.Name))
+ {
+ List<string> newIns = new List<String>();
+ newIns.Add("_P");
+ foreach (string s in inParameters[Proc.Name])
+ {
+ newIns.Add(s);
+ }
+ inParameters[Proc.Name] = newIns;
+ }
+ }
+ }
+
+ private void Analyse(Implementation Impl, bool ControlFlowIsUniform)
+ {
+ if (!ControlFlowIsUniform)
+ {
+ nonUniformBlocks[Impl.Name] = new HashSet<Block>(Impl.Blocks);
+
+ foreach (Variable v in Impl.LocVars) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ foreach (Variable v in Impl.InParams) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ foreach (Variable v in Impl.OutParams) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
+ }
+
+ foreach (Block b in Impl.Blocks) {
+ Analyse(Impl, b.Cmds, false);
+ }
+
+ return;
+ }
+
+ Graph<Block> blockGraph = prog.ProcessLoops(Impl);
+ var ctrlDep = blockGraph.ControlDependence();
+
+ // Compute transitive closure of control dependence info.
+ ctrlDep.TransitiveClosure();
+
+ var nonUniformBlockSet = new HashSet<Block>();
+ nonUniformBlocks[Impl.Name] = nonUniformBlockSet;
+
+ bool changed;
+ do {
+ changed = false;
+ foreach (var block in Impl.Blocks) {
+ bool uniform = !nonUniformBlockSet.Contains(block);
+ bool newUniform = Analyse(Impl, block.Cmds, uniform);
+ if (uniform && !newUniform) {
+ changed = true;
+ nonUniformBlockSet.Add(block);
+ Block pred = blockGraph.Predecessors(block).Single();
+ if (ctrlDep.ContainsKey(pred))
+ nonUniformBlockSet.UnionWith(ctrlDep[pred]);
+ }
+ }
+ } while (changed);
+ }
+
+ private Procedure GetProcedure(string procedureName)
+ {
+ foreach (var p in prog.Procedures)
+ {
+ if (p.Name == procedureName)
+ {
+ return p;
+ }
+ }
+ Debug.Assert(false);
+ return null;
+ }
+
+ private bool Analyse(Implementation impl, List<Cmd> cmdSeq, bool ControlFlowIsUniform)
+ {
+ foreach (Cmd c in cmdSeq)
+ {
+ if (c is AssignCmd)
+ {
+ AssignCmd assignCmd = c as AssignCmd;
+ foreach (var a in assignCmd.Lhss.Zip(assignCmd.Rhss))
+ {
+
+ if (a.Item1 is SimpleAssignLhs)
+ {
+ SimpleAssignLhs lhs = a.Item1 as SimpleAssignLhs;
+ Expr rhs = a.Item2;
+ if (IsUniform(impl.Name, lhs.AssignedVariable.Name) &&
+ (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs)))
+ {
+ SetNonUniform(impl.Name, lhs.AssignedVariable.Name);
+ }
+
+ }
+ }
+ }
+ else if (c is HavocCmd)
+ {
+ HavocCmd havocCmd = c as HavocCmd;
+ foreach(IdentifierExpr ie in havocCmd.Vars)
+ {
+ if(IsUniform(impl.Name, ie.Decl.Name)) {
+ SetNonUniform(impl.Name, ie.Decl.Name);
+ }
+ }
+ }
+ else if (c is CallCmd)
+ {
+ CallCmd callCmd = c as CallCmd;
+ DeclWithFormals Callee = GetProcedure(callCmd.callee);
+ Debug.Assert(Callee != null);
+
+ if (!ControlFlowIsUniform)
+ {
+ if (IsUniform(callCmd.callee))
+ {
+ SetNonUniform(callCmd.callee);
+ }
+ }
+ for (int i = 0; i < Callee.InParams.Count; i++)
+ {
+ if (IsUniform(callCmd.callee, Callee.InParams[i].Name)
+ && !IsUniform(impl.Name, callCmd.Ins[i]))
+ {
+ SetNonUniform(callCmd.callee, Callee.InParams[i].Name);
+ }
+ }
+
+ for (int i = 0; i < Callee.OutParams.Count; i++)
+ {
+ if (IsUniform(impl.Name, callCmd.Outs[i].Name)
+ && !IsUniform(callCmd.callee, Callee.OutParams[i].Name))
+ {
+ SetNonUniform(impl.Name, callCmd.Outs[i].Name);
+ }
+ }
+
+ }
+ else if (c is AssumeCmd)
+ {
+ var ac = (AssumeCmd)c;
+ if (ControlFlowIsUniform && QKeyValue.FindBoolAttribute(ac.Attributes, "partition") &&
+ !IsUniform(impl.Name, ac.Expr))
+ {
+ ControlFlowIsUniform = false;
+ }
+ }
+ }
+
+ return ControlFlowIsUniform;
+ }
+
+ private int GetLoopId(WhileCmd wc)
+ {
+ AssertCmd inv = wc.Invariants[0] as AssertCmd;
+ Debug.Assert(inv.Attributes.Key.Contains("loophead_"));
+ return Convert.ToInt32(inv.Attributes.Key.Substring("loophead_".Length));
+ }
+
+ private void SetNonUniform(string procedureName)
+ {
+ uniformityInfo[procedureName] = new KeyValuePair<bool,Dictionary<string,bool>>
+ (false, uniformityInfo[procedureName].Value);
+ RecordProcedureChanged();
+ }
+
+ private void SetNonUniform(string procedureName, WhileCmd wc)
+ {
+ nonUniformLoops[procedureName].Add(GetLoopId(wc));
+ RecordProcedureChanged();
+ }
+
+ public bool IsUniform(string procedureName)
+ {
+ if (!uniformityInfo.ContainsKey(procedureName))
+ {
+ return false;
+ }
+ return uniformityInfo[procedureName].Key;
+ }
+
+ public bool IsUniform(string procedureName, Block b)
+ {
+ if (!nonUniformBlocks.ContainsKey(procedureName))
+ {
+ return false;
+ }
+ return !nonUniformBlocks[procedureName].Contains(b);
+ }
+
+ class UniformExpressionAnalysisVisitor : ReadOnlyVisitor {
+
+ private bool isUniform = true;
+ private Dictionary<string, bool> uniformityInfo;
+
+ public UniformExpressionAnalysisVisitor(Dictionary<string, bool> uniformityInfo) {
+ this.uniformityInfo = uniformityInfo;
+ }
+
+ public override Variable VisitVariable(Variable v) {
+ if (!uniformityInfo.ContainsKey(v.Name)) {
+ isUniform = isUniform && (v is Constant);
+ } else if (!uniformityInfo[v.Name]) {
+ isUniform = false;
+ }
+
+ return v;
+ }
+
+ internal bool IsUniform() {
+ return isUniform;
+ }
+ }
+
+ public bool IsUniform(string procedureName, Expr expr)
+ {
+ if (!uniformityInfo.ContainsKey(procedureName))
+ {
+ return false;
+ }
+
+ UniformExpressionAnalysisVisitor visitor = new UniformExpressionAnalysisVisitor(uniformityInfo[procedureName].Value);
+ visitor.VisitExpr(expr);
+ return visitor.IsUniform();
+ }
+
+ public bool IsUniform(string procedureName, string v)
+ {
+ if (!uniformityInfo.ContainsKey(procedureName))
+ {
+ return false;
+ }
+
+ if (!uniformityInfo[procedureName].Value.ContainsKey(v))
+ {
+ return false;
+ }
+ return uniformityInfo[procedureName].Value[v];
+ }
+
+ private void SetUniform(string procedureName, string v)
+ {
+ uniformityInfo[procedureName].Value[v] = true;
+ RecordProcedureChanged();
+ }
+
+ private void RecordProcedureChanged()
+ {
+ ProcedureChanged = true;
+ }
+
+ private void SetNonUniform(string procedureName, string v)
+ {
+ uniformityInfo[procedureName].Value[v] = false;
+ RecordProcedureChanged();
+ }
+
+ public void dump()
+ {
+ foreach (string p in uniformityInfo.Keys)
+ {
+ Console.WriteLine("Procedure " + p + ": "
+ + (uniformityInfo[p].Key ? "uniform" : "nonuniform"));
+ foreach (string v in uniformityInfo[p].Value.Keys)
+ {
+ Console.WriteLine(" " + v + ": " +
+ (uniformityInfo[p].Value[v] ? "uniform" : "nonuniform"));
+ }
+ Console.Write("Ins [");
+ for (int i = 0; i < inParameters[p].Count; i++)
+ {
+ Console.Write((i == 0 ? "" : ", ") + inParameters[p][i]);
+ }
+ Console.WriteLine("]");
+ Console.Write("Outs [");
+ for (int i = 0; i < outParameters[p].Count; i++)
+ {
+ Console.Write((i == 0 ? "" : ", ") + outParameters[p][i]);
+ }
+ Console.WriteLine("]");
+ if (nonUniformLoops.ContainsKey(p)) {
+ Console.Write("Non-uniform loops:");
+ foreach (int l in nonUniformLoops[p]) {
+ Console.Write(" " + l);
+ }
+ Console.WriteLine();
+ }
+ if (nonUniformBlocks.ContainsKey(p)) {
+ Console.Write("Non-uniform blocks:");
+ foreach (Block b in nonUniformBlocks[p]) {
+ Console.Write(" " + b.Label);
+ }
+ Console.WriteLine();
+ }
+ }
+ }
+
+
+ public string GetInParameter(string procName, int i)
+ {
+ return inParameters[procName][i];
+ }
+
+ public string GetOutParameter(string procName, int i)
+ {
+ return outParameters[procName][i];
+ }
+
+
+ public bool knowsOf(string p)
+ {
+ return uniformityInfo.ContainsKey(p);
+ }
+
+ public void AddNonUniform(string proc, string v)
+ {
+ if (uniformityInfo.ContainsKey(proc))
+ {
+ Debug.Assert(!uniformityInfo[proc].Value.ContainsKey(v));
+ uniformityInfo[proc].Value[v] = false;
+ }
+ }
+
+ public void AddNonUniform(string proc, Block b) {
+ if (nonUniformBlocks.ContainsKey(proc)) {
+ Debug.Assert(!nonUniformBlocks[proc].Contains(b));
+ nonUniformBlocks[proc].Add(b);
+ }
+ }
+
+ }
+
+}
diff --git a/Source/Provers/SMTLib/CVC4.cs b/Source/Provers/SMTLib/CVC4.cs
index 0ac2ec20..999ac7b5 100644
--- a/Source/Provers/SMTLib/CVC4.cs
+++ b/Source/Provers/SMTLib/CVC4.cs
@@ -1,71 +1,71 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.Boogie.SMTLib
-{
- class CVC4
- {
- static string _proverPath;
-
- static string CodebaseString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
- }
-
- public static string ExecutablePath()
- {
- if (_proverPath == null)
- FindExecutable();
- return _proverPath;
- }
-
- static void FindExecutable()
- // throws ProverException, System.IO.FileNotFoundException;
- {
- Contract.Ensures(_proverPath != null);
-
- // Command line option 'cvc4exe' always has priority if set
- if (CommandLineOptions.Clo.CVC4ExecutablePath != null)
- {
- _proverPath = CommandLineOptions.Clo.CVC4ExecutablePath;
- if (!File.Exists(_proverPath))
- {
- throw new ProverException("Cannot find prover specified with cvc4exe: " + _proverPath);
- }
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
-
- var proverExe = "cvc4.exe";
-
- if (_proverPath == null)
- {
- // Initialize '_proverPath'
- _proverPath = Path.Combine(CodebaseString(), proverExe);
- string firstTry = _proverPath;
-
- if (File.Exists(firstTry))
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
- else
- {
- throw new ProverException("Cannot find executable: " + firstTry);
- }
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ class CVC4
+ {
+ static string _proverPath;
+
+ static string CodebaseString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
+ }
+
+ public static string ExecutablePath()
+ {
+ if (_proverPath == null)
+ FindExecutable();
+ return _proverPath;
+ }
+
+ static void FindExecutable()
+ // throws ProverException, System.IO.FileNotFoundException;
+ {
+ Contract.Ensures(_proverPath != null);
+
+ // Command line option 'cvc4exe' always has priority if set
+ if (CommandLineOptions.Clo.CVC4ExecutablePath != null)
+ {
+ _proverPath = CommandLineOptions.Clo.CVC4ExecutablePath;
+ if (!File.Exists(_proverPath))
+ {
+ throw new ProverException("Cannot find prover specified with cvc4exe: " + _proverPath);
+ }
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("[TRACE] Using prover: " + _proverPath);
+ }
+ return;
+ }
+
+ var proverExe = "cvc4.exe";
+
+ if (_proverPath == null)
+ {
+ // Initialize '_proverPath'
+ _proverPath = Path.Combine(CodebaseString(), proverExe);
+ string firstTry = _proverPath;
+
+ if (File.Exists(firstTry))
+ {
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("[TRACE] Using prover: " + _proverPath);
+ }
+ return;
+ }
+ else
+ {
+ throw new ProverException("Cannot find executable: " + firstTry);
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Provers/SMTLib/Inspector.cs b/Source/Provers/SMTLib/Inspector.cs
index 362502f3..13a2076e 100644
--- a/Source/Provers/SMTLib/Inspector.cs
+++ b/Source/Provers/SMTLib/Inspector.cs
@@ -1,157 +1,157 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-//using util;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.SMTLib
-{
- internal class FindLabelsVisitor : TraversingVCExprVisitor<bool, bool> {
- public HashSet<string/*!*/>/*!*/ Labels = new HashSet<string/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNull(Labels));
- }
-
-
- public static HashSet<string/*!*/>/*!*/ FindLabels(VCExpr/*!*/ expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(cce.NonNull(Contract.Result<HashSet<string/*!*/>/*!*/>()));
-
- FindLabelsVisitor visitor = new FindLabelsVisitor();
- visitor.Traverse(expr, true);
- return visitor.Labels;
- }
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node!=null);
- VCExprNAry nary = node as VCExprNAry;
- if (nary != null) {
- VCExprLabelOp lab = nary.Op as VCExprLabelOp;
- if (lab != null) {
- Labels.Add(lab.label);
- }
- }
- return true;
- }
- }
-
- internal class Inspector {
- [Rep] protected readonly Process inspector;
- [Rep] readonly TextReader fromInspector;
- [Rep] readonly TextWriter toInspector;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(inspector!=null);
- Contract.Invariant(fromInspector!=null);
- Contract.Invariant(toInspector != null);
- }
-
-
- public Inspector(SMTLibProverOptions opts)
- {
- Contract.Requires(opts != null);
- ProcessStartInfo psi = new ProcessStartInfo(opts.Inspector);
- Contract.Assert(psi!=null);
- psi.CreateNoWindow = true;
- psi.UseShellExecute = false;
- psi.RedirectStandardInput = true;
- psi.RedirectStandardOutput = true;
- psi.RedirectStandardError = false;
-
- try
- {
- Process inspector = Process.Start(psi);
- this.inspector = inspector;
- fromInspector = inspector.StandardOutput;
- toInspector = inspector.StandardInput;
- }
- catch (System.ComponentModel.Win32Exception e)
- {
- throw new Exception(string.Format("Unable to start the inspector process {0}: {1}", opts.Inspector, e.Message));
- }
- }
-
- public void NewProblem(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler)
- {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(vc != null);
- Contract.Requires(handler != null);
- HashSet<string/*!*/>/*!*/ labels = FindLabelsVisitor.FindLabels(vc);
- Contract.Assert(labels!=null);
- toInspector.WriteLine("PROBLEM " + descriptiveName);
- toInspector.WriteLine("TOKEN BEGIN");
- foreach (string lab in labels) {
- Contract.Assert(lab!=null);
- string no = lab.Substring(1);
- Absy absy = handler.Label2Absy(no);
-
- IToken tok = absy.tok;
- AssertCmd assrt = absy as AssertCmd;
- Block blk = absy as Block;
- string val = tok.val; // might require computation, so cache it
- if (val == "foo" || tok.filename == null) continue; // no token
-
- toInspector.Write("TOKEN ");
- toInspector.Write(lab);
- toInspector.Write(" ");
-
- if (assrt != null) {
- toInspector.Write("ASSERT");
- string errData = assrt.ErrorData as string;
- if (errData != null) {
- val = errData;
- } else if (assrt.ErrorMessage != null) {
- val = assrt.ErrorMessage;
- }
- } else if (blk != null) {
- toInspector.Write("BLOCK ");
- toInspector.Write(blk.Label);
- } else {
- Contract.Assume( false);
- }
- if (val == null || val == "assert" || val == "ensures") { val = ""; }
-
- if (absy is LoopInitAssertCmd) {
- val += " (loop entry)";
- } else if (absy is LoopInvMaintainedAssertCmd) {
- val += " (loop body)";
- } else if (val.IndexOf("#VCCERR") >= 0) {
- // skip further transformations
- } else if (absy is AssertRequiresCmd) {
- AssertRequiresCmd req = (AssertRequiresCmd)absy;
- IToken t2 = req.Requires.tok;
- string tval = t2.val;
- if (tval == "requires")
- tval = string.Format("{0}({1},{2}))", t2.filename, t2.line, t2.col);
- string call = "";
- if (val != "call") call = " in call to " + val;
- val = string.Format("precondition {0}{1}", tval, call);
- }
-
- val = val.Replace("\r", "").Replace("\n", " ");
-
- toInspector.WriteLine(string.Format(" {0} {1} :@:{2}:@:{3}", tok.line, tok.col, tok.filename, val));
- }
- toInspector.WriteLine("TOKEN END");
- }
-
- public void StatsLine(string line)
- {
- Contract.Requires(line != null);
- toInspector.WriteLine(line);
- toInspector.Flush();
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+//using util;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ internal class FindLabelsVisitor : TraversingVCExprVisitor<bool, bool> {
+ public HashSet<string/*!*/>/*!*/ Labels = new HashSet<string/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNull(Labels));
+ }
+
+
+ public static HashSet<string/*!*/>/*!*/ FindLabels(VCExpr/*!*/ expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(cce.NonNull(Contract.Result<HashSet<string/*!*/>/*!*/>()));
+
+ FindLabelsVisitor visitor = new FindLabelsVisitor();
+ visitor.Traverse(expr, true);
+ return visitor.Labels;
+ }
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node!=null);
+ VCExprNAry nary = node as VCExprNAry;
+ if (nary != null) {
+ VCExprLabelOp lab = nary.Op as VCExprLabelOp;
+ if (lab != null) {
+ Labels.Add(lab.label);
+ }
+ }
+ return true;
+ }
+ }
+
+ internal class Inspector {
+ [Rep] protected readonly Process inspector;
+ [Rep] readonly TextReader fromInspector;
+ [Rep] readonly TextWriter toInspector;
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(inspector!=null);
+ Contract.Invariant(fromInspector!=null);
+ Contract.Invariant(toInspector != null);
+ }
+
+
+ public Inspector(SMTLibProverOptions opts)
+ {
+ Contract.Requires(opts != null);
+ ProcessStartInfo psi = new ProcessStartInfo(opts.Inspector);
+ Contract.Assert(psi!=null);
+ psi.CreateNoWindow = true;
+ psi.UseShellExecute = false;
+ psi.RedirectStandardInput = true;
+ psi.RedirectStandardOutput = true;
+ psi.RedirectStandardError = false;
+
+ try
+ {
+ Process inspector = Process.Start(psi);
+ this.inspector = inspector;
+ fromInspector = inspector.StandardOutput;
+ toInspector = inspector.StandardInput;
+ }
+ catch (System.ComponentModel.Win32Exception e)
+ {
+ throw new Exception(string.Format("Unable to start the inspector process {0}: {1}", opts.Inspector, e.Message));
+ }
+ }
+
+ public void NewProblem(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler)
+ {
+ Contract.Requires(descriptiveName != null);
+ Contract.Requires(vc != null);
+ Contract.Requires(handler != null);
+ HashSet<string/*!*/>/*!*/ labels = FindLabelsVisitor.FindLabels(vc);
+ Contract.Assert(labels!=null);
+ toInspector.WriteLine("PROBLEM " + descriptiveName);
+ toInspector.WriteLine("TOKEN BEGIN");
+ foreach (string lab in labels) {
+ Contract.Assert(lab!=null);
+ string no = lab.Substring(1);
+ Absy absy = handler.Label2Absy(no);
+
+ IToken tok = absy.tok;
+ AssertCmd assrt = absy as AssertCmd;
+ Block blk = absy as Block;
+ string val = tok.val; // might require computation, so cache it
+ if (val == "foo" || tok.filename == null) continue; // no token
+
+ toInspector.Write("TOKEN ");
+ toInspector.Write(lab);
+ toInspector.Write(" ");
+
+ if (assrt != null) {
+ toInspector.Write("ASSERT");
+ string errData = assrt.ErrorData as string;
+ if (errData != null) {
+ val = errData;
+ } else if (assrt.ErrorMessage != null) {
+ val = assrt.ErrorMessage;
+ }
+ } else if (blk != null) {
+ toInspector.Write("BLOCK ");
+ toInspector.Write(blk.Label);
+ } else {
+ Contract.Assume( false);
+ }
+ if (val == null || val == "assert" || val == "ensures") { val = ""; }
+
+ if (absy is LoopInitAssertCmd) {
+ val += " (loop entry)";
+ } else if (absy is LoopInvMaintainedAssertCmd) {
+ val += " (loop body)";
+ } else if (val.IndexOf("#VCCERR") >= 0) {
+ // skip further transformations
+ } else if (absy is AssertRequiresCmd) {
+ AssertRequiresCmd req = (AssertRequiresCmd)absy;
+ IToken t2 = req.Requires.tok;
+ string tval = t2.val;
+ if (tval == "requires")
+ tval = string.Format("{0}({1},{2}))", t2.filename, t2.line, t2.col);
+ string call = "";
+ if (val != "call") call = " in call to " + val;
+ val = string.Format("precondition {0}{1}", tval, call);
+ }
+
+ val = val.Replace("\r", "").Replace("\n", " ");
+
+ toInspector.WriteLine(string.Format(" {0} {1} :@:{2}:@:{3}", tok.line, tok.col, tok.filename, val));
+ }
+ toInspector.WriteLine("TOKEN END");
+ }
+
+ public void StatsLine(string line)
+ {
+ Contract.Requires(line != null);
+ toInspector.WriteLine(line);
+ toInspector.Flush();
+ }
+ }
+}
diff --git a/Source/Provers/SMTLib/ProverInterface.cs b/Source/Provers/SMTLib/ProverInterface.cs
index 868b9ee3..300fbc10 100644
--- a/Source/Provers/SMTLib/ProverInterface.cs
+++ b/Source/Provers/SMTLib/ProverInterface.cs
@@ -1,2424 +1,2651 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-//using ExternalProver;
-using System.Linq;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Clustering;
-using Microsoft.Boogie.TypeErasure;
-using System.Text;
-
-using RPFP = Microsoft.Boogie.RPFP;
-
-namespace Microsoft.Boogie.SMTLib
-{
- public class SMTLibProcessTheoremProver : ProverInterface
- {
- private readonly SMTLibProverContext ctx;
- private VCExpressionGenerator gen;
- private readonly SMTLibProverOptions options;
- private bool usingUnsatCore;
- private RPFP rpfp = null;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(ctx != null);
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Namer != null);
- Contract.Invariant(DeclCollector != null);
- Contract.Invariant(cce.NonNullElements(Axioms));
- Contract.Invariant(cce.NonNullElements(TypeDecls));
- Contract.Invariant(_backgroundPredicates != null);
-
- }
-
-
- [NotDelayed]
- public SMTLibProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
- SMTLibProverContext ctx)
- {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
-
- InitializeGlobalInformation();
-
- this.options = (SMTLibProverOptions)options;
- this.ctx = ctx;
- this.gen = gen;
- this.usingUnsatCore = false;
-
- SetupAxiomBuilder(gen);
-
- Namer = new SMTLibNamer();
- ctx.parent = this;
- this.DeclCollector = new TypeDeclCollector((SMTLibProverOptions)options, Namer);
-
- if (CommandLineOptions.Clo.PrintFixedPoint != null || CommandLineOptions.Clo.PrintConjectures != null)
- {
- declHandler = new MyDeclHandler();
- DeclCollector.SetDeclHandler(declHandler);
- }
-
- SetupProcess();
-
- if (CommandLineOptions.Clo.StratifiedInlining > 0 || CommandLineOptions.Clo.ContractInfer
- || CommandLineOptions.Clo.SecureVcGen != null)
- {
- // Prepare for ApiChecker usage
- if (options.LogFilename != null && currentLogFile == null)
- {
- currentLogFile = OpenOutputFile("");
- }
- PrepareCommon();
- }
- }
-
- private void SetupAxiomBuilder(VCExpressionGenerator gen)
- {
- switch (CommandLineOptions.Clo.TypeEncodingMethod)
- {
- case CommandLineOptions.TypeEncoding.Arguments:
- AxBuilder = new TypeAxiomBuilderArguments(gen);
- AxBuilder.Setup();
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- AxBuilder = new TypeAxiomBuilderPremisses(gen);
- break;
- default:
- AxBuilder = new TypeAxiomBuilderPremisses(gen);
- AxBuilder.Setup();
- break;
- }
- }
-
- ProcessStartInfo ComputeProcessStartInfo()
- {
- var path = this.options.ProverPath;
- switch (options.Solver) {
- case SolverKind.Z3:
- if (path == null)
- path = Z3.ExecutablePath();
- return SMTLibProcess.ComputerProcessStartInfo(path, "AUTO_CONFIG=false -smt2 -in");
- case SolverKind.CVC4:
- if (path == null)
- path = CVC4.ExecutablePath();
- return SMTLibProcess.ComputerProcessStartInfo(path, "--lang=smt --no-strict-parsing --no-condense-function-values --incremental");
- default:
- Debug.Assert(false);
- return null;
- }
- }
-
- void SetupProcess()
- {
- if (Process != null) return;
-
- var psi = ComputeProcessStartInfo();
- Process = new SMTLibProcess(psi, this.options);
- Process.ErrorHandler += this.HandleProverError;
- }
-
-
- void PossiblyRestart()
- {
- if (Process != null && Process.NeedsRestart) {
- Process.Close();
- Process = null;
- SetupProcess();
- Process.Send(common.ToString());
- }
- }
-
- public override ProverContext Context
- {
- get
- {
- Contract.Ensures(Contract.Result<ProverContext>() != null);
-
- return ctx;
- }
- }
-
- internal TypeAxiomBuilder AxBuilder { get; private set; }
- internal readonly UniqueNamer Namer;
- readonly TypeDeclCollector DeclCollector;
- protected SMTLibProcess Process;
- readonly List<string> proverErrors = new List<string>();
- readonly List<string> proverWarnings = new List<string>();
- readonly StringBuilder common = new StringBuilder();
- protected TextWriter currentLogFile;
- protected volatile ErrorHandler currentErrorHandler;
-
- private void FeedTypeDeclsToProver()
- {
- foreach (string s in DeclCollector.GetNewDeclarations()) {
- Contract.Assert(s != null);
- AddTypeDecl(s);
- }
- }
-
- private string Sanitize(string msg)
- {
- var idx = msg.IndexOf('\n');
- if (idx > 0)
- msg = msg.Replace("\r", "").Replace("\n", "\r\n");
- return msg;
- }
-
- public override void LogComment(string comment)
- {
- SendCommon("; " + comment);
- }
-
- private void SendCommon(string s)
- {
- Send(s, true);
- }
-
- protected void SendThisVC(string s)
- {
- Send(s, false);
- }
-
- private void Send(string s, bool isCommon)
- {
- s = Sanitize(s);
-
- if (isCommon)
- common.Append(s).Append("\r\n");
-
- if (Process != null)
- Process.Send(s);
- if (currentLogFile != null) {
- currentLogFile.WriteLine(s);
- currentLogFile.Flush();
- }
- }
-
- private void FindDependentTypes(Type type, List<CtorType> dependentTypes)
- {
- MapType mapType = type as MapType;
- if (mapType != null)
- {
- foreach (Type t in mapType.Arguments)
- {
- FindDependentTypes(t, dependentTypes);
- }
- FindDependentTypes(mapType.Result, dependentTypes);
- }
- CtorType ctorType = type as CtorType;
- if (ctorType != null && ctx.KnownDatatypeConstructors.ContainsKey(ctorType))
- {
- dependentTypes.Add(ctorType);
- }
- }
-
- private void PrepareCommon()
- {
- if (common.Length == 0)
- {
- SendCommon("(set-option :print-success false)");
- SendCommon("(set-info :smt-lib-version 2.0)");
- if (options.ProduceModel())
- SendCommon("(set-option :produce-models true)");
- foreach (var opt in options.SmtOptions)
- {
- SendCommon("(set-option :" + opt.Option + " " + opt.Value + ")");
- }
-
- if (!string.IsNullOrEmpty(options.Logic))
- {
- SendCommon("(set-logic " + options.Logic + ")");
- }
-
- // Set produce-unsat-cores last. It seems there's a bug in Z3 where if we set it earlier its value
- // gets reset by other set-option commands ( https://z3.codeplex.com/workitem/188 )
- if (CommandLineOptions.Clo.ContractInfer && (CommandLineOptions.Clo.UseUnsatCoreForContractInfer || CommandLineOptions.Clo.ExplainHoudini))
- {
- SendThisVC("(set-option :produce-unsat-cores true)");
- this.usingUnsatCore = true;
- }
-
- SendCommon("; done setting options\n");
- SendCommon(_backgroundPredicates);
-
- if (options.UseTickleBool)
- {
- SendCommon("(declare-fun tickleBool (Bool) Bool)");
- SendCommon("(assert (and (tickleBool true) (tickleBool false)))");
- }
-
- if (ctx.KnownDatatypeConstructors.Count > 0)
- {
- GraphUtil.Graph<CtorType> dependencyGraph = new GraphUtil.Graph<CtorType>();
- foreach (CtorType datatype in ctx.KnownDatatypeConstructors.Keys)
- {
- dependencyGraph.AddSource(datatype);
- foreach (Function f in ctx.KnownDatatypeConstructors[datatype])
- {
- List<CtorType> dependentTypes = new List<CtorType>();
- foreach (Variable v in f.InParams)
- {
- FindDependentTypes(v.TypedIdent.Type, dependentTypes);
- }
- foreach (CtorType result in dependentTypes)
- {
- dependencyGraph.AddEdge(datatype, result);
- }
- }
- }
- GraphUtil.StronglyConnectedComponents<CtorType> sccs = new GraphUtil.StronglyConnectedComponents<CtorType>(dependencyGraph.Nodes, dependencyGraph.Predecessors, dependencyGraph.Successors);
- sccs.Compute();
- foreach (GraphUtil.SCC<CtorType> scc in sccs)
- {
- string datatypeString = "";
- foreach (CtorType datatype in scc)
- {
- datatypeString += "(" + SMTLibExprLineariser.TypeToString(datatype) + " ";
- foreach (Function f in ctx.KnownDatatypeConstructors[datatype])
- {
- string quotedConstructorName = Namer.GetQuotedName(f, f.Name);
- if (f.InParams.Count == 0)
- {
- datatypeString += quotedConstructorName + " ";
- }
- else
- {
- datatypeString += "(" + quotedConstructorName + " ";
- foreach (Variable v in f.InParams)
- {
- string quotedSelectorName = Namer.GetQuotedName(v, v.Name + "#" + f.Name);
- datatypeString += "(" + quotedSelectorName + " " + DeclCollector.TypeToStringReg(v.TypedIdent.Type) + ") ";
- }
- datatypeString += ") ";
- }
- }
- datatypeString += ") ";
- }
- List<string> decls = DeclCollector.GetNewDeclarations();
- foreach (string decl in decls)
- {
- SendCommon(decl);
- }
- SendCommon("(declare-datatypes () (" + datatypeString + "))");
- }
- }
- }
-
- if (!AxiomsAreSetup)
- {
- var axioms = ctx.Axioms;
- var nary = axioms as VCExprNAry;
- if (nary != null && nary.Op == VCExpressionGenerator.AndOp)
- foreach (var expr in nary.UniformArguments)
- {
- var str = VCExpr2String(expr, -1);
- if (str != "true")
- AddAxiom(str);
- }
- else
- AddAxiom(VCExpr2String(axioms, -1));
- AxiomsAreSetup = true;
- }
- }
-
- public override int FlushAxiomsToTheoremProver()
- {
- // we feed the axioms when begincheck is called.
- return 0;
- }
-
- private void FlushAxioms()
- {
- TypeDecls.Iter(SendCommon);
- TypeDecls.Clear();
- foreach (string s in Axioms) {
- Contract.Assert(s != null);
- if (s != "true")
- SendCommon("(assert " + s + ")");
- }
- Axioms.Clear();
- //FlushPushedAssertions();
- }
-
- private void CloseLogFile()
- {
- if (currentLogFile != null) {
- currentLogFile.Close();
- currentLogFile = null;
- }
- }
-
- private void FlushLogFile()
- {
- if (currentLogFile != null) {
- currentLogFile.Flush();
- }
- }
-
- public override void Close()
- {
- base.Close();
- CloseLogFile();
- if (Process != null)
- Process.Close();
- }
-
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
- {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- rpfp = null;
-
- if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen
-
- if (options.LogFilename != null && currentLogFile == null)
- {
- currentLogFile = OpenOutputFile(descriptiveName);
- currentLogFile.Write(common.ToString());
- }
-
- PrepareCommon();
- string vcString = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))";
- FlushAxioms();
-
- PossiblyRestart();
-
- SendThisVC("(push 1)");
- SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")");
- SendThisVC(vcString);
- FlushLogFile();
-
- if (Process != null) {
- Process.PingPong(); // flush any errors
-
- if (Process.Inspector != null)
- Process.Inspector.NewProblem(descriptiveName, vc, handler);
- }
-
- SendThisVC("(check-sat)");
- FlushLogFile();
- }
-
- public override void Reset(VCExpressionGenerator gen)
- {
- if (options.Solver == SolverKind.Z3)
- {
- this.gen = gen;
- SendThisVC("(reset)");
-
- if (0 < common.Length)
- {
- var c = common.ToString();
- Process.Send(c);
- if (currentLogFile != null)
- {
- currentLogFile.WriteLine(c);
- }
- }
- }
- }
-
- public override void FullReset(VCExpressionGenerator gen)
- {
- if (options.Solver == SolverKind.Z3)
- {
- this.gen = gen;
- Namer.Reset();
- common.Clear();
- SetupAxiomBuilder(gen);
- Axioms.Clear();
- TypeDecls.Clear();
- AxiomsAreSetup = false;
- ctx.Reset();
- ctx.KnownDatatypeConstructors.Clear();
- ctx.parent = this;
- DeclCollector.Reset();
- SendThisVC("; doing a full reset...");
- }
- }
-
-
-
- private string StripCruft(string name){
- if(name.Contains("@@"))
- return name.Remove(name.LastIndexOf ("@@"));
- return name;
- }
-
- private class BadExprFromProver : Exception
- {
- };
-
- private delegate VCExpr ArgGetter (int pos);
-
- private delegate VCExpr[] ArgsGetter ();
-
- private delegate VCExprVar[] VarsGetter ();
-
- private VCExprOp VCStringToVCOp (string op)
- {
- switch (op) {
- case "+" :
- return VCExpressionGenerator.AddIOp;
- case "-" :
- return VCExpressionGenerator.SubIOp;
- case "*" :
- return VCExpressionGenerator.MulIOp;
- case "div" :
- return VCExpressionGenerator.DivIOp;
- case "=" :
- return VCExpressionGenerator.EqOp;
- case "<=" :
- return VCExpressionGenerator.LeOp;
- case "<" :
- return VCExpressionGenerator.LtOp;
- case ">=" :
- return VCExpressionGenerator.GeOp;
- case ">" :
- return VCExpressionGenerator.GtOp;
- case "and" :
- return VCExpressionGenerator.AndOp;
- case "or" :
- return VCExpressionGenerator.OrOp;
- case "not" :
- return VCExpressionGenerator.NotOp;
- case "ite" :
- return VCExpressionGenerator.IfThenElseOp;
- default:
- return null;
- }
- }
-
- private class MyDeclHandler : TypeDeclCollector.DeclHandler {
- public Dictionary<string,VCExprVar> var_map = new Dictionary<string, VCExprVar>();
- public Dictionary<string,Function> func_map = new Dictionary<string, Function>();
- public override void VarDecl(VCExprVar v){
- var_map[v.Name] = v;
- }
- public override void FuncDecl(Function f){
- func_map[f.Name] = f;
- }
- public MyDeclHandler() {
- }
- }
-
- private MyDeclHandler declHandler = null;
-
- private VCExprVar SExprToVar (SExpr e)
- {
- if(e.Arguments.Count() != 1){
- HandleProverError ("Prover error: bad quantifier syntax");
- throw new BadExprFromProver ();
- }
- string vname = StripCruft(e.Name);
- SExpr vtype = e[0];
- switch(vtype.Name){
- case "Int":
- return gen.Variable(vname,Type.Int);
- case "Bool":
- return gen.Variable (vname,Type.Bool);
- case "Array":{
- // TODO: handle more general array types
- var idxType = Type.Int; // well, could be something else
- var valueType =
- (vtype.Arguments[1].Name == "Int") ? Type.Int : Type.Bool;
- var types = new List<Type>();
- types.Add(idxType);
- return gen.Variable (vname, new MapType(Token.NoToken,new List<TypeVariable>(),types,valueType));
- }
- default: {
- HandleProverError ("Prover error: bad type: " + vtype.Name);
- throw new BadExprFromProver ();
- }
- }
- }
-
- private VCExpr MakeBinary(VCExprOp op, VCExpr [] args)
- {
- if (args.Count() == 0)
- {
- // with zero args we need the identity of the op
- if (op == VCExpressionGenerator.AndOp)
- return VCExpressionGenerator.True;
- if (op == VCExpressionGenerator.OrOp)
- return VCExpressionGenerator.False;
- if (op == VCExpressionGenerator.AddIOp)
- {
- Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.ZERO;
- return gen.Integer(x);
- }
- HandleProverError("Prover error: bad expression ");
- throw new BadExprFromProver();
- }
- var temp = args[0];
- for (int i = 1; i < args.Count(); i++)
- temp = gen.Function(op, temp, args[i]);
- return temp;
- }
-
- protected VCExpr SExprToVCExpr (SExpr e, Dictionary<string,VCExpr> bound)
- {
- if (e.Arguments.Count() == 0) {
- var name = StripCruft(e.Name);
- if (name [0] >= '0' && name [0] <= '9') {
- Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.FromString(name);
- return gen.Integer (x);
- }
- if (bound.ContainsKey (name)) {
- return bound [name];
- }
- if(name == "true")
- return VCExpressionGenerator.True;
- if(name == "false")
- return VCExpressionGenerator.False;
- if(declHandler.var_map.ContainsKey(name))
- return declHandler.var_map[name];
- HandleProverError ("Prover error: unknown symbol:" + name);
- throw new BadExprFromProver ();
- }
- ArgGetter g = i => SExprToVCExpr (e [i], bound);
- ArgsGetter ga = () => e.Arguments.Select (x => SExprToVCExpr (x, bound)).ToArray ();
- VarsGetter gb = () => e [0].Arguments.Select (x => SExprToVar (x)).ToArray ();
- switch (e.Name) {
- case "select" :
- return gen.Select (ga ());
- case "store" :
- return gen.Store (ga ());
- case "forall":
- case "exists":
- {
- var binds = e.Arguments[0];
- var vcbinds = new List<VCExprVar>();
- for (int i = 0; i < binds.Arguments.Count(); i++)
- {
- var bind = binds.Arguments[i];
- var symb = bind.Name;
- var vcv = SExprToVar(bind);
- vcbinds.Add(vcv);
- bound[symb] = vcv;
- }
- var body = g(1);
- if (e.Name == "forall")
- body = gen.Forall(vcbinds, new List<VCTrigger>(), body);
- else
- body = gen.Exists(vcbinds, new List<VCTrigger>(), body);
- for (int i = 0; i < binds.Arguments.Count(); i++)
- {
- var bind = binds.Arguments[i];
- var symb = bind.Name;
- bound.Remove(symb);
- }
- return body;
- }
- case "-" : // have to deal with unary case
- {
- if(e.ArgCount == 1){
- var args = new VCExpr[2];
- args[0] = gen.Integer (Microsoft.Basetypes.BigNum.ZERO);
- args[1] = g(0);
- return gen.Function(VCStringToVCOp("-"),args);
- }
- return gen.Function(VCStringToVCOp("-"),ga());
- }
- case "!" : // this is commentary
- return g(0);
- case "let" : {
- // we expand lets exponentially since there is no let binding in Boogie surface syntax
- bool expand_lets = true;
- var binds = e.Arguments[0];
- var vcbinds = new List<VCExprLetBinding>();
- for(int i = 0; i < binds.Arguments.Count(); i++){
- var bind = binds.Arguments[i];
- var symb = bind.Name;
- var def = bind.Arguments[0];
- var vce = SExprToVCExpr(def, bound);
- var vcv = gen.Variable(symb,vce.Type);
- var vcb = gen.LetBinding(vcv,vce);
- vcbinds.Add (vcb);
- bound[symb] = expand_lets ? vce : vcv;
- }
- var body = g(1);
- if(!expand_lets)
- body = gen.Let(vcbinds,body);
- for(int i = 0; i < binds.Arguments.Count(); i++){
- var bind = binds.Arguments[i];
- var symb = bind.Name;
- bound.Remove (symb);
- }
- return body;
- }
-
- default: {
- var op = VCStringToVCOp (e.Name);
- if (op == null) {
- var name = StripCruft(e.Name);
- if(declHandler.func_map.ContainsKey(name)){
- Function f = declHandler.func_map[name];
- return gen.Function (f, ga());
- }
- HandleProverError ("Prover error: unknown operator:" + e.Name);
- throw new BadExprFromProver ();
- }
- if(op.Arity == 2)
- return MakeBinary (op, ga ());
- return gen.Function(op, ga());
- }
- }
- }
-
- private void SExprToSoln (SExpr resp,
- Dictionary<int,Dictionary<string,string>> varSubst)
- {
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node> ();
-
- foreach (var node in rpfp.nodes)
- pmap.Add ((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
-
- var lines = resp.Arguments;
-
- // get all the predicate definitions
- for (int i = 0; i < lines.Length; i++) {
- var line = lines [i];
- string pname;
- RPFP.Transformer annot;
- GetDefun(line, out pname, out annot);
-
- if(pmap.ContainsKey(pname)){
- var node = pmap[pname];
- node.Annotation = annot;
- }
- else if(pname[0] != '@'){ // if not an internal symbol
- HandleProverError ("Prover error: got unknown predicate:" + pname);
- throw new BadExprFromProver ();
- }
- }
-
- }
-
- private void GetDefun(SExpr line, out string pname, out RPFP.Transformer annot)
- {
- if (line.Name != "define-fun")
- {
- HandleProverError("Prover error: expected define-fun but got:" + line.Name);
- throw new BadExprFromProver();
- }
- if (line.ArgCount != 4)
- {
- HandleProverError("Prover error: define-fun has wrong number of arguments");
- throw new BadExprFromProver();
- }
- pname = StripCruft(line.Arguments[0].Name);
- var pvars = line.Arguments[1];
- var pbody = line.Arguments[3]; // range has to be Bool
- var binding = new Dictionary<string, VCExpr>();
- var pvs = new List<VCExpr>();
- foreach (var b in pvars.Arguments)
- {
- var e = SExprToVar(b);
- pvs.Add(e);
- binding.Add(StripCruft(b.Name), e);
- }
- VCExpr bexpr = SExprToVCExpr(pbody, binding);
-
- annot = rpfp.CreateRelation(pvs.ToArray(), bexpr);
- }
-
- private RPFP.Node SExprToCex(SExpr resp, ErrorHandler handler,
- Dictionary<int,Dictionary<string,string>> varSubst)
- {
- Dictionary<string, RPFP.Node> nmap = new Dictionary<string,RPFP.Node>();
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node>();
-
- foreach(var node in rpfp.nodes)
- pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name,node);
-
- RPFP.Node topnode = null;
- var lines = resp.Arguments;
-
- // last line of derivation is from query, skip it
- for (int i = 0; i < lines.Length-1; i++)
- {
- var line = lines[i];
- if (line.ArgCount != 6)
- {
- HandleProverError("bad derivation line from prover: " + line.ToString());
- return null;
- }
- var name = line[0];
- var conseq = line[1];
- var rule = line[2];
- var subst = line[3];
- var labs = line[4];
- var refs = line[5];
- var predName = conseq.Name;
- {
- string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it!
- int pos = predName.LastIndexOf(spacer);
- if (pos >= 0)
- predName = predName.Substring(0, pos);
- }
- RPFP.Node node = null;
- if (!pmap.TryGetValue(predName, out node))
- {
- HandleProverError("unknown predicate from prover: " + predName.ToString());
- return null;
- }
- RPFP.Node cexnode = rpfp.CloneNode(node);
- cexnode.map = node;
- nmap.Add(name.Name, cexnode);
- List<RPFP.Node> Chs = new List<RPFP.Node>();
-
- if (refs.Name != "ref")
- {
- HandleProverError("bad references from prover: " + refs.ToString());
- return null;
- }
- foreach (var c in refs.Arguments)
- {
- if (c.Name == "true")
- Chs.Add(null);
- else
- {
- RPFP.Node ch = null;
- if (!nmap.TryGetValue(c.Name, out ch))
- {
- HandleProverError("unknown reference from prover: " + c.ToString());
- return null;
- }
- Chs.Add(ch);
- }
- }
-
- if (!rule.Name.StartsWith("rule!"))
- {
- HandleProverError("bad rule name from prover: " + refs.ToString());
- return null;
- }
- int ruleNum = Convert.ToInt32(rule.Name.Substring(5)) - 1;
- if (ruleNum < 0 || ruleNum > rpfp.edges.Count)
- {
- HandleProverError("bad rule name from prover: " + refs.ToString());
- return null;
- }
- RPFP.Edge orig_edge = rpfp.edges[ruleNum];
- RPFP.Edge e = rpfp.CreateEdge(cexnode, orig_edge.F, Chs.ToArray());
- e.map = orig_edge;
- topnode = cexnode;
-
- if (labs.Name != "labels")
- {
- HandleProverError("bad labels from prover: " + labs.ToString());
- return null;
- }
- e.labels = new HashSet<string>();
- foreach (var l in labs.Arguments)
- e.labels.Add(l.Name);
-
- if (subst.Name != "subst")
- {
- HandleProverError("bad subst from prover: " + subst.ToString());
- return null;
- }
- Dictionary<string, string> dict = new Dictionary<string, string>();
- varSubst[e.number] = dict;
- foreach (var s in subst.Arguments)
- {
- if (s.Name != "=" || s.Arguments.Length != 2)
- {
- HandleProverError("bad equation from prover: " + s.ToString());
- return null;
- }
- string uniqueName = s.Arguments[0].Name;
- string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it!
- int pos = uniqueName.LastIndexOf(spacer);
- if (pos >= 0)
- uniqueName = uniqueName.Substring(0, pos);
- dict.Add(uniqueName, s.Arguments[1].ToString());
- }
-
- }
- if (topnode == null)
- {
- HandleProverError("empty derivation from prover: " + resp.ToString());
- }
- return topnode;
- }
-
- private Model SExprToModel(SExpr resp, ErrorHandler handler)
- {
- // Concatenate all the arguments
- string modelString = resp[0].Name;
- // modelString = modelString.Substring(7, modelString.Length - 8); // remove "(model " and final ")"
- var models = Model.ParseModels(new StringReader("Error model: \n" + modelString));
- if (models == null || models.Count == 0)
- {
- HandleProverError("no model from prover: " + resp.ToString());
- }
- return models[0];
- }
-
- private string QuantifiedVCExpr2String(VCExpr x)
- {
- return VCExpr2String(x, 1);
-#if false
- if (!(x is VCExprQuantifier))
- return VCExpr2String(x, 1);
- VCExprQuantifier node = (x as VCExprQuantifier);
- if(node.BoundVars.Count == 0)
- return VCExpr2String(x, 1);
-
- StringWriter wr = new StringWriter();
-
- string kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
- wr.Write("({0} (", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++)
- {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var != null);
- string printedName = Namer.GetQuotedName(var, var.Name);
- Contract.Assert(printedName != null);
- wr.Write("({0} {1}) ", printedName, SMTLibExprLineariser.TypeToString(var.Type));
- }
-
- wr.Write(") ");
- wr.Write(VCExpr2String(node.Body, 1));
- wr.Write(")");
- string res = wr.ToString();
- return res;
-#endif
- }
-
- public override Outcome CheckRPFP(string descriptiveName, RPFP _rpfp, ErrorHandler handler,
- out RPFP.Node cex,
- Dictionary<int, Dictionary<string, string>> varSubst,
- Dictionary<string, int> extra_bound)
- {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- rpfp = _rpfp;
- cex = null;
-
-
- if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen
-
- if (options.LogFilename != null && currentLogFile == null)
- {
- currentLogFile = OpenOutputFile(descriptiveName);
- currentLogFile.Write(common.ToString());
- }
-
- PrepareCommon();
-
- Push();
- SendThisVC("(fixedpoint-push)");
- foreach (var node in rpfp.nodes)
- {
- DeclCollector.RegisterRelation((node.Name as VCExprBoogieFunctionOp).Func);
- }
-
- LineariserOptions.Default.LabelsBelowQuantifiers = true;
- List<string> ruleStrings = new List<string>();
- var recursion_bound = CommandLineOptions.Clo.RecursionBound;
- foreach (var edge in rpfp.edges)
- {
- string node_name = (edge.Parent.Name as VCExprBoogieFunctionOp).Func.Name;
- string rule_name = "rule_" + edge.number.ToString();
- string rec_bound = "";
- if(extra_bound != null && extra_bound.ContainsKey(node_name))
- rec_bound = (recursion_bound + extra_bound[node_name]).ToString();
- string ruleString = "(rule " + QuantifiedVCExpr2String(rpfp.GetRule(edge)) + " " + rule_name + " " + rec_bound + "\n)";
- ruleStrings.Add(ruleString);
- }
- string queryString = "(query " + QuantifiedVCExpr2String(rpfp.GetQuery()) + "\n :engine duality\n :print-certificate true\n";
-
-#if true
- if (CommandLineOptions.Clo.StratifiedInlining != 0)
- queryString += " :stratified-inlining true\n";
- if (CommandLineOptions.Clo.RecursionBound > 0)
- queryString += " :recursion-bound " + Convert.ToString(CommandLineOptions.Clo.RecursionBound) + "\n";
-#endif
- queryString += ")";
- LineariserOptions.Default.LabelsBelowQuantifiers = false;
- FlushAxioms();
-
- PossiblyRestart();
-
- SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")");
- foreach(var rs in ruleStrings)
- SendThisVC(rs);
- FlushLogFile();
-
- if (Process != null)
- {
- Process.PingPong(); // flush any errors
-
-#if false
- // TODO: this is not going to work
- if (Process.Inspector != null)
- Process.Inspector.NewProblem(descriptiveName, vc, handler);
-#endif
- }
-
- SendThisVC(queryString);
- FlushLogFile();
-
- var result = Outcome.Undetermined;
-
- if (Process != null)
- {
-
- var resp = Process.GetProverResponse();
-
- if (proverErrors.Count > 0)
- {
- result = Outcome.Undetermined;
- foreach (var err in proverErrors)
- {
- if (err.Contains("canceled"))
- {
- result = Outcome.TimeOut;
- }
- }
- }
- else if(resp == null)
- HandleProverError("Prover did not respond");
- else switch (resp.Name)
- {
- case "unsat":
- result = Outcome.Valid;
- break;
- case "sat":
- result = Outcome.Invalid;
- break;
- case "unknown":
- result = Outcome.Invalid;
- break;
- case "error":
- if (resp.ArgCount > 0 && resp.Arguments[0].Name.Contains("canceled"))
- {
- result = Outcome.TimeOut;
- }
- else
- {
- HandleProverError("Prover error: " + resp.Arguments[0]);
- result = Outcome.Undetermined;
- }
- break;
- default:
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
-
- switch (result)
- {
- case Outcome.Invalid:
- {
- resp = Process.GetProverResponse();
- if (resp.Name == "derivation")
- {
- cex = SExprToCex(resp, handler,varSubst);
- }
- else
- HandleProverError("Unexpected prover response: " + resp.ToString());
- resp = Process.GetProverResponse();
- if (resp.Name == "model")
- {
- var model = SExprToModel(resp, handler);
- cex.owner.SetBackgroundModel(model);
- }
- else
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- case Outcome.Valid:
- {
- resp = Process.GetProverResponse();
- if (resp.Name == "fixedpoint")
- {
- // only get the response if we need it
- if(CommandLineOptions.Clo.PrintFixedPoint != null)
- SExprToSoln(resp, varSubst);
- }
- else
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- default:
- break;
- }
-
-#if false
- while (true)
- {
- resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
- HandleProverError("Unexpected prover response: " + resp.ToString());
- }
-#endif
- }
- SendThisVC("(fixedpoint-pop)");
- Pop();
- AxiomsAreSetup = false;
-
- if (CommandLineOptions.Clo.PrintConjectures != null)
- {
- ReadConjectures(CommandLineOptions.Clo.PrintConjectures);
- }
-
- return result;
- }
-
- class MyFileParser : SExpr.Parser
- {
- SMTLibProcessTheoremProver parent;
-
- public MyFileParser(System.IO.StreamReader _sr, SMTLibProcessTheoremProver _parent)
- : base(_sr)
- {
- parent = _parent;
- }
- public override void ParseError(string msg)
- {
- parent.HandleProverError("Error in conjecture file from prover: " + msg);
- }
- }
-
- void ReadConjectures(string filename)
- {
- try
- {
- System.IO.StreamReader sr = new StreamReader(filename + ".tmp");
- SExpr.Parser p = new MyFileParser(sr, this);
- var sexps = p.ParseSExprs(false);
- Dictionary<string, RPFP.Node> pmap = GetNodeMap();
- foreach (var e in sexps)
- {
- string pname;
- RPFP.Transformer annot;
- GetDefun(e, out pname, out annot);
-
- if (pmap.ContainsKey(pname))
- {
- var c = new RPFP.Conjecture();
- c.node = pmap[pname];
- c.bound = annot;
- rpfp.conjectures.Add(c);
- }
- else if (pname[0] != '@')
- { // if not an internal symbol
- HandleProverError("Prover error: got unknown predicate:" + pname);
- throw new BadExprFromProver();
- }
- }
- sr.Close();
- }
- catch (Exception)
- {
- HandleProverError("No conjecture file from prover");
- throw new BadExprFromProver();
- }
- }
-
- private Dictionary<string, RPFP.Node> GetNodeMap()
- {
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string, RPFP.Node>();
- foreach (var node in rpfp.nodes)
- pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
- return pmap;
- }
-
- private static HashSet<string> usedLogNames = new HashSet<string>();
-
- private TextWriter OpenOutputFile(string descriptiveName)
- {
- Contract.Requires(descriptiveName != null);
- Contract.Ensures(Contract.Result<TextWriter>() != null);
-
- string filename = options.LogFilename;
- filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
- var curFilename = filename;
-
- lock (usedLogNames) {
- int n = 1;
- while (usedLogNames.Contains(curFilename)) {
- curFilename = filename + "." + n++;
- }
- usedLogNames.Add(curFilename);
- }
-
- return new StreamWriter(curFilename, false);
- }
-
- private void FlushProverWarnings()
- {
- var handler = currentErrorHandler;
- if (handler != null) {
- lock (proverWarnings) {
- proverWarnings.Iter(handler.OnProverWarning);
- proverWarnings.Clear();
- }
- }
- }
-
- protected void HandleProverError(string s)
- {
- s = s.Replace("\r", "");
- lock (proverWarnings) {
- while (s.StartsWith("WARNING: ")) {
- var idx = s.IndexOf('\n');
- var warn = s;
- if (idx > 0) {
- warn = s.Substring(0, idx);
- s = s.Substring(idx + 1);
- } else {
- s = "";
- }
- warn = warn.Substring(9);
- proverWarnings.Add(warn);
- }
- }
-
- FlushProverWarnings();
-
- if (s == "") return;
-
- lock (proverErrors) {
- proverErrors.Add(s);
- Console.WriteLine("Prover error: " + s);
- }
- }
-
- [NoDefaultContract]
- public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1)
- {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- var result = CheckOutcomeCore(handler, taskID: taskID);
- SendThisVC("(pop 1)");
- FlushLogFile();
-
- return result;
- }
-
- [NoDefaultContract]
- public override Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1)
- {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- var result = Outcome.Undetermined;
-
- if (Process == null)
- return result;
-
- try {
- currentErrorHandler = handler;
- FlushProverWarnings();
-
- int errorsLeft;
- if (CommandLineOptions.Clo.ConcurrentHoudini) {
- Contract.Assert(taskID >= 0);
- errorsLeft = CommandLineOptions.Clo.Cho[taskID].ProverCCLimit;
- } else {
- errorsLeft = CommandLineOptions.Clo.ProverCCLimit;
- }
-
- if (errorsLeft < 1)
- errorsLeft = 1;
-
- var globalResult = Outcome.Undetermined;
-
- while (true) {
- errorsLeft--;
- string[] labels = null;
-
- result = GetResponse();
- if (globalResult == Outcome.Undetermined)
- globalResult = result;
-
- if (result == Outcome.Invalid || result == Outcome.TimeOut || result == Outcome.OutOfMemory) {
- IList<string> xlabels;
- if (CommandLineOptions.Clo.UseLabels) {
- labels = GetLabelsInfo();
- if (labels == null)
- {
- xlabels = new string[] { };
- }
- else
- {
- xlabels = labels.Select(a => a.Replace("@", "").Replace("+", "")).ToList();
- }
- }
- else if(CommandLineOptions.Clo.SIBoolControlVC) {
- labels = new string[0];
- xlabels = labels;
- } else {
- labels = CalculatePath(handler.StartingProcId());
- xlabels = labels;
- }
- Model model = (result == Outcome.TimeOut || result == Outcome.OutOfMemory) ? null :
- GetErrorModel();
- handler.OnModel(xlabels, model, result);
- }
-
- if (labels == null || !labels.Any() || errorsLeft == 0) break;
-
- if (CommandLineOptions.Clo.UseLabels) {
- var negLabels = labels.Where(l => l.StartsWith("@")).ToArray();
- var posLabels = labels.Where(l => !l.StartsWith("@"));
- Func<string, string> lbl = (s) => SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(s));
- if (!options.MultiTraces)
- posLabels = Enumerable.Empty<string>();
- var conjuncts = posLabels.Select(s => "(not " + lbl(s) + ")").Concat(negLabels.Select(lbl)).ToArray();
- string expr = conjuncts.Length == 1 ? conjuncts[0] : ("(or " + conjuncts.Concat(" ") + ")"); ;
- if (!conjuncts.Any())
- {
- expr = "false";
- }
- SendThisVC("(assert " + expr + ")");
- SendThisVC("(check-sat)");
- }
- else {
- string source = labels[labels.Length - 2];
- string target = labels[labels.Length - 1];
- SendThisVC("(assert (not (= (ControlFlow 0 " + source + ") (- " + target + "))))");
- SendThisVC("(check-sat)");
- }
- }
-
- FlushLogFile();
-
- if (CommandLineOptions.Clo.RestartProverPerVC && Process != null)
- Process.NeedsRestart = true;
-
- return globalResult;
-
- } finally {
- currentErrorHandler = null;
- }
- }
-
- public override string[] CalculatePath(int controlFlowConstant) {
- SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " 0)))");
- var path = new List<string>();
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null) break;
- if (!(resp.Name == "" && resp.ArgCount == 1)) break;
- resp = resp.Arguments[0];
- if (!(resp.Name == "" && resp.ArgCount == 2)) break;
- resp = resp.Arguments[1];
- var v = resp.Name;
- if (v == "-" && resp.ArgCount == 1) {
- v = resp.Arguments[0].Name;
- path.Add(v);
- break;
- }
- else if (resp.ArgCount != 0)
- break;
- path.Add(v);
- SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " " + v + ")))");
- }
- return path.ToArray();
- }
-
-
- private class SMTErrorModelConverter {
- private struct SMTDataType {
- public string Constructor;
- public List<SExpr> Types;
- }
-
- private List<SExpr> ErrorModelTodo;
- private SMTLibProcessTheoremProver Parent;
- private StringBuilder ErrorModel = new StringBuilder();
- private HashSet<SExpr> TopLevelProcessed = new HashSet<SExpr>();
- private int NumNewArrays = 0;
- private Dictionary<string, int> SortSet = new Dictionary<string, int>();
- private Dictionary<string, SMTDataType> DataTypes = new Dictionary<string, SMTDataType>();
- private Dictionary<string, SExpr> Functions = new Dictionary<string, SExpr>();
-
- public SMTErrorModelConverter(SExpr _ErrorModel, SMTLibProcessTheoremProver _Parent) {
- ErrorModelTodo = _ErrorModel.Arguments.ToList();;
- Parent = _Parent;
- }
-
- public string Convert() {
- ConvertErrorModel(ErrorModel);
- return ErrorModel.ToString();
- }
-
- bool isConstArray(SExpr element, SExpr type) {
- if (type.Name != "Array")
- return false;
-
- if (element.Name == "__array_store_all__") // CVC4 1.4
- return true;
- else if (element.Name == "" && element[0].Name == "as" &&
- element[0][0].Name == "const") // CVC4 > 1.4
- return true;
-
- return false;
- }
-
- SExpr getConstArrayElement(SExpr element) {
- if (element.Name == "__array_store_all__") // CVC4 1.4
- return element[1];
- else if (element.Name == "" && element[0].Name == "as" &&
- element[0][0].Name == "const") // CVC4 > 1.4
- return element[1];
-
- Parent.HandleProverError("Unexpected value: " + element);
- throw new BadExprFromProver ();
- }
-
- void ConstructComplexValue(SExpr element, SExpr type, StringBuilder m) {
- if (type.Name == "Array") {
- if (element.Name == "store" || isConstArray(element, type)) {
- NumNewArrays++;
- m.Append("as-array[k!" + NumNewArrays + ']');
- SExpr[] args = {new SExpr("k!" + NumNewArrays), new SExpr(""), type, element};
- var newElement = new SExpr("define-fun", args);
- TopLevelProcessed.Add(newElement);
- ErrorModelTodo.Add(newElement);
- return;
- }
- }
-
- ConstructSimpleValue(element, type, m);
- }
-
- void ConstructSimpleValue(SExpr element, SExpr type, StringBuilder m) {
- if (type.Name == "Bool" && element.ArgCount == 0) {
- m.Append(element.ToString());
- return;
- }
-
- if (type.Name == "Int") {
- if (element.ArgCount == 0) {
- m.Append(element.ToString());
- return;
- } else if (element.Name == "-" && element.ArgCount == 1) {
- m.Append(element.ToString());
- return;
- }
- }
-
- if (type.Name == "_" && type.ArgCount == 2 && type[0].Name == "BitVec") {
- if (element.Name == "_" && element.ArgCount == 2 &&
- element[0].Name.StartsWith("bv") && element[0].ArgCount == 0 &&
- element[1].Name == type.Arguments[1].Name && element[1].ArgCount == 0) {
- m.Append(element[0].Name + '[' + element[1].Name + ']');
- return;
- }
- }
-
- if (type.Name == "Array") {
- while (element.Name == "store") {
- ConstructComplexValue(element[1], type[0], m);
- m.Append(" -> ");
- ConstructComplexValue(element[2], type[1], m);
- m.Append("\n ");
- if (element[0].Name != "store") {
- m.Append("else -> ");
- }
- element = element[0];
- }
-
- if (isConstArray(element, type)) {
- ConstructComplexValue(getConstArrayElement(element), type[1], m);
- return;
- } else if (element.Name == "_" && element.ArgCount == 2 &&
- element[0].Name == "as-array") {
- m.Append("as-array[" + element[1].Name + ']');
- return;
- }
- }
-
- if (SortSet.ContainsKey(type.Name) && SortSet[type.Name] == 0) {
- var prefix = "@uc_T_" + type.Name.Substring(2) + "_";
- if (element.Name.StartsWith(prefix)) {
- m.Append(type.Name + "!val!" + element.Name.Substring(prefix.Length));
- return;
- }
- }
-
- if (Functions.ContainsKey(element.Name) &&
- type.Name == Functions[element.Name].Name) {
- m.Append(element.Name);
- return;
- }
-
- if (DataTypes.ContainsKey(type.Name) &&
- DataTypes[type.Name].Constructor == element.Name &&
- element.ArgCount == DataTypes[type.Name].Types.Count) {
- m.Append("(" + element.Name);
- for (int i = 0; i < element.ArgCount; ++i) {
- m.Append(" ");
- ConstructComplexValue(element[i], DataTypes[type.Name].Types[i], m);
- }
- m.Append(")");
- return;
- }
-
- Parent.HandleProverError("Unexpected value: " + element);
- throw new BadExprFromProver ();
- }
-
- void ConstructFunctionArguments(SExpr arguments, List<SExpr> argTypes, StringBuilder[] argValues) {
- if (arguments.Name == "and") {
- ConstructFunctionArguments(arguments[0], argTypes, argValues);
- ConstructFunctionArguments(arguments[1], argTypes, argValues);
- } else if (arguments.Name == "=" &&
- (arguments[0].Name.StartsWith("_ufmt_") || arguments[0].Name.StartsWith("x!"))) {
- int argNum;
- if (arguments[0].Name.StartsWith("_ufmt_"))
- argNum = System.Convert.ToInt32(arguments[0].Name.Substring("_uftm_".Length)) - 1;
- else /* if (arguments[0].Name.StartsWith("x!")) */
- argNum = System.Convert.ToInt32(arguments[0].Name.Substring("x!".Length)) - 1;
- if (argNum < 0 || argNum >= argTypes.Count) {
- Parent.HandleProverError("Unexpected function argument: " + arguments[0]);
- throw new BadExprFromProver ();
- }
- if (argValues[argNum] != null) {
- Parent.HandleProverError("Function argument defined multiple times: " + arguments[0]);
- throw new BadExprFromProver ();
- }
- argValues[argNum] = new StringBuilder();
- ConstructComplexValue(arguments[1], argTypes[argNum], argValues[argNum]);
- } else {
- Parent.HandleProverError("Unexpected function argument: " + arguments);
- throw new BadExprFromProver ();
- }
- }
-
- void ConstructFunctionElements(SExpr element, List<SExpr> argTypes, SExpr outType, StringBuilder m) {
- while (element.Name == "ite") {
- StringBuilder[] argValues = new StringBuilder[argTypes.Count];
- ConstructFunctionArguments(element[0], argTypes, argValues);
- foreach (var s in argValues)
- m.Append(s + " ");
- m.Append("-> ");
- ConstructComplexValue(element[1], outType, m);
- m.Append("\n ");
- if (element[2].Name != "ite")
- m.Append("else -> ");
- element = element[2];
- }
-
- ConstructComplexValue(element, outType, m);
- }
-
- void ConstructFunction(SExpr element, SExpr inType, SExpr outType, StringBuilder m) {
- List<SExpr> argTypes = new List<SExpr>();
-
- for (int i = 0; i < inType.ArgCount; ++i) {
- if (inType[i].Name != "_ufmt_" + (i + 1) && inType[i].Name != "x!" + (i + 1) &&
- !inType[i].Name.StartsWith("BOUND_VARIABLE_")) {
- Parent.HandleProverError("Unexpected function argument: " + inType[i].Name);
- throw new BadExprFromProver ();
- }
- argTypes.Add(inType[i][0]);
- }
-
- ConstructFunctionElements(element, argTypes, outType, m);
- }
-
- void ConstructDefine(SExpr element, StringBuilder m) {
- Debug.Assert(element.Name == "define-fun");
-
- if (element[1].ArgCount != 0)
- TopLevelProcessed.Add(element);
-
- m.Append(element[0] + " -> ");
- if (TopLevelProcessed.Contains(element))
- m.Append("{\n ");
-
- if (element[1].ArgCount == 0 && element[2].Name == "Array" && !TopLevelProcessed.Contains(element)) {
- ConstructComplexValue(element[3], element[2], m);
- } else if (element[1].ArgCount == 0) {
- ConstructSimpleValue(element[3], element[2], m);
- } else {
- ConstructFunction(element[3], element[1], element[2], m);
- }
-
- if (TopLevelProcessed.Contains(element))
- m.Append("\n}");
- m.Append("\n");
- }
-
- void ExtractDataType(SExpr datatypes) {
- Debug.Assert(datatypes.Name == "declare-datatypes");
-
- if (datatypes[0].Name != "" || datatypes[1].Name != "" || datatypes[1].ArgCount != 1) {
- Parent.HandleProverError("Unexpected datatype: " + datatypes);
- throw new BadExprFromProver ();
- }
-
- SMTDataType dt = new SMTDataType();
- SExpr typeDef = datatypes[1][0];
-
- if (typeDef.ArgCount != 1) {
- Parent.HandleProverError("Unexpected datatype: " + datatypes);
- throw new BadExprFromProver ();
- }
-
- dt.Constructor = typeDef[0].Name;
- dt.Types = new List<SExpr>();
-
- for (int i = 0; i < typeDef[0].ArgCount; ++i) {
- if (typeDef[0][i].ArgCount != 1) {
- Parent.HandleProverError("Unexpected datatype constructor: " + typeDef[0]);
- throw new BadExprFromProver ();
- }
- dt.Types.Add(typeDef[0][i][0]);
- }
-
- DataTypes[typeDef.Name] = dt;
- }
-
- private void ConvertErrorModel(StringBuilder m) {
- if (Parent.options.Solver == SolverKind.Z3) {
- // Datatype declarations are not returned by Z3, so parse common
- // instead. This is not very efficient, but currently not an issue,
- // as this not the normal way of interfacing with Z3.
- var ms = new MemoryStream(Encoding.ASCII.GetBytes(Parent.common.ToString()));
- var sr = new StreamReader(ms);
- SExpr.Parser p = new MyFileParser(sr, null);
- var sexprs = p.ParseSExprs(false);
- foreach (var e in sexprs) {
- switch (e.Name) {
- case "declare-datatypes":
- ExtractDataType(e);
- break;
- }
- }
- }
-
- while (ErrorModelTodo.Count > 0) {
- var e = ErrorModelTodo[0];
- ErrorModelTodo.RemoveAt(0);
-
- switch (e.Name) {
- case "define-fun":
- ConstructDefine(e, m);
- break;
- case "declare-sort":
- SortSet[e[0].Name] = System.Convert.ToInt32(e[1].Name);
- break;
- case "declare-datatypes":
- ExtractDataType(e);
- break;
- case "declare-fun":
- if (e[1].Name != "" || e[1].ArgCount > 0 || e[2].ArgCount > 0 ||
- e[2].Name == "Bool" || e[2].Name == "Int") {
- Parent.HandleProverError("Unexpected top level model element: " + e.Name);
- throw new BadExprFromProver ();
- }
- Functions[e[0].Name] = e[2];
- break;
- case "forall":
- // ignore
- break;
- default:
- Parent.HandleProverError("Unexpected top level model element: " + e.Name);
- throw new BadExprFromProver ();
- }
- }
- }
- }
-
- private Model GetErrorModel() {
- if (!options.ExpectingModel())
- return null;
- SendThisVC("(get-model)");
- Process.Ping();
- Model theModel = null;
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
- if (theModel != null)
- HandleProverError("Expecting only one model but got many");
-
- string modelStr = null;
- if (resp.Name == "model" && resp.ArgCount >= 1) {
- var converter = new SMTErrorModelConverter(resp, this);
- modelStr = converter.Convert();
- }
- else if (resp.ArgCount == 0 && resp.Name.Contains("->")) {
- modelStr = resp.Name;
- }
- else {
- HandleProverError("Unexpected prover response getting model: " + resp.ToString());
- }
-
- List<Model> models = null;
- try {
- switch (options.Solver) {
- case SolverKind.Z3:
- case SolverKind.CVC4:
- models = Model.ParseModels(new StringReader("Error model: \n" + modelStr));
- break;
- default:
- Debug.Assert(false);
- return null;
- }
- }
- catch (ArgumentException exn) {
- HandleProverError("Model parsing error: " + exn.Message);
- }
- if (models == null)
- HandleProverError("Could not parse any models");
- else if (models.Count == 0)
- HandleProverError("Could not parse any models");
- else if (models.Count > 1)
- HandleProverError("Expecting only one model but got many");
- else
- theModel = models[0];
- }
- return theModel;
- }
-
- private string[] GetLabelsInfo()
- {
- SendThisVC("(labels)");
- Process.Ping();
-
- string[] res = null;
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
- if (res != null)
- HandleProverError("Expecting only one sequence of labels but got many");
- if (resp.Name == "labels" && resp.ArgCount >= 1) {
- res = resp.Arguments.Select(a => a.Name.Replace("|", "")).ToArray();
- }
- else {
- HandleProverError("Unexpected prover response getting labels: " + resp.ToString());
- }
- }
- return res;
- }
-
- private Outcome GetResponse()
- {
- var result = Outcome.Undetermined;
- var wasUnknown = false;
-
- Process.Ping();
-
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- switch (resp.Name) {
- case "unsat":
- result = Outcome.Valid;
- break;
- case "sat":
- result = Outcome.Invalid;
- break;
- case "unknown":
- result = Outcome.Invalid;
- wasUnknown = true;
- break;
- default:
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- }
-
- if (wasUnknown) {
- SendThisVC("(get-info :reason-unknown)");
- Process.Ping();
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- if (resp.ArgCount == 1 && resp.Name == ":reason-unknown") {
- switch (resp[0].Name) {
- case "memout":
- currentErrorHandler.OnResourceExceeded("memory");
- result = Outcome.OutOfMemory;
- Process.NeedsRestart = true;
- break;
- case "timeout": case "canceled":
- currentErrorHandler.OnResourceExceeded("timeout");
- result = Outcome.TimeOut;
- break;
- default:
- break;
- }
- } else {
- HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString());
- }
- }
-
- }
-
- return result;
- }
-
- protected string VCExpr2String(VCExpr expr, int polarity)
- {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- lock (gen)
- {
- DateTime start = DateTime.UtcNow;
- //if (CommandLineOptions.Clo.Trace)
- // Console.Write("Linearising ... ");
-
- // handle the types in the VCExpr
- TypeEraser eraser;
- switch (CommandLineOptions.Clo.TypeEncodingMethod)
- {
- case CommandLineOptions.TypeEncoding.Arguments:
- eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, gen);
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- eraser = null;
- break;
- default:
- eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen);
- break;
- }
- VCExpr exprWithoutTypes = eraser == null ? expr : eraser.Erase(expr, polarity);
- Contract.Assert(exprWithoutTypes != null);
-
- LetBindingSorter letSorter = new LetBindingSorter(gen);
- Contract.Assert(letSorter != null);
- VCExpr sortedExpr = letSorter.Mutate(exprWithoutTypes, true);
- Contract.Assert(sortedExpr != null);
- VCExpr sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true);
- Contract.Assert(sortedAxioms != null);
-
- DeclCollector.Collect(sortedAxioms);
- DeclCollector.Collect(sortedExpr);
- FeedTypeDeclsToProver();
-
-
-
- AddAxiom(SMTLibExprLineariser.ToString(sortedAxioms, Namer, options));
- string res = SMTLibExprLineariser.ToString(sortedExpr, Namer, options);
- Contract.Assert(res != null);
-
- if (CommandLineOptions.Clo.Trace)
- {
- DateTime end = DateTime.UtcNow;
- TimeSpan elapsed = end - start;
- if (elapsed.TotalSeconds > 0.5)
- Console.WriteLine("Linearising [{0} s]", elapsed.TotalSeconds);
- }
- return res;
- }
- }
-
- // the list of all known axioms, where have to be included in each
- // verification condition
- private readonly List<string/*!>!*/> Axioms = new List<string/*!*/>();
- private bool AxiomsAreSetup = false;
-
-
-
-
- // similarly, a list of function/predicate declarations
- private readonly List<string/*!>!*/> TypeDecls = new List<string/*!*/>();
-
- protected void AddAxiom(string axiom)
- {
- Contract.Requires(axiom != null);
- Axioms.Add(axiom);
- // if (thmProver != null) {
- // LogActivity(":assume " + axiom);
- // thmProver.AddAxioms(axiom);
- // }
- }
-
- protected void AddTypeDecl(string decl)
- {
- Contract.Requires(decl != null);
- TypeDecls.Add(decl);
- // if (thmProver != null) {
- // LogActivity(decl);
- // thmProver.Feed(decl, 0);
- // }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private static string _backgroundPredicates;
-
- static void InitializeGlobalInformation()
- {
- Contract.Ensures(_backgroundPredicates != null);
- //throws ProverException, System.IO.FileNotFoundException;
- if (_backgroundPredicates == null) {
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic)
- {
- _backgroundPredicates = "";
- }
- else
- {
- _backgroundPredicates = @"
-(set-info :category ""industrial"")
-(declare-sort |T@U| 0)
-(declare-sort |T@T| 0)
-(declare-fun real_pow (Real Real) Real)
-(declare-fun UOrdering2 (|T@U| |T@U|) Bool)
-(declare-fun UOrdering3 (|T@T| |T@U| |T@U|) Bool)";
- }
- }
- }
-
- public override VCExpressionGenerator VCExprGen
- {
- get { return this.gen; }
- }
-
- //// Push/pop interface
-
- //List<string> pushedAssertions = new List<string>();
- //int numRealPushes;
- public override string VCExpressionToString(VCExpr vc)
- {
- return VCExpr2String(vc, 1);
- }
-
- public override void PushVCExpression(VCExpr vc)
- {
- throw new NotImplementedException();
-
- }
-
- public override void Pop()
- {
- SendThisVC("(pop 1)");
- DeclCollector.Pop();
- }
-
- public override int NumAxiomsPushed()
- {
- throw new NotImplementedException();
- //return numRealPushes + pushedAssertions.Count;
- }
-
- private void FlushPushedAssertions()
- {
- throw new NotImplementedException();
- }
-
- public override void Assert(VCExpr vc, bool polarity)
- {
- string a = "";
- if (polarity)
- {
- a = "(assert " + VCExpr2String(vc, 1) + ")";
- }
- else
- {
- a = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))";
- }
- AssertAxioms();
- SendThisVC(a);
- }
-
- public override void DefineMacro(Macro f, VCExpr vc) {
- DeclCollector.AddFunction(f);
- string printedName = Namer.GetQuotedName(f, f.Name);
- var argTypes = f.InParams.Cast<Variable>().MapConcat(p => DeclCollector.TypeToStringReg(p.TypedIdent.Type), " ");
- string decl = "(define-fun " + printedName + " (" + argTypes + ") " + DeclCollector.TypeToStringReg(f.OutParams[0].TypedIdent.Type) + " " + VCExpr2String(vc, 1) + ")";
- AssertAxioms();
- SendThisVC(decl);
- }
-
- public override void AssertAxioms()
- {
- FlushAxioms();
- }
-
- public override void Check()
- {
- PrepareCommon();
- SendThisVC("(check-sat)");
- FlushLogFile();
- }
-
- public override void SetTimeOut(int ms)
- {
- if (options.Solver == SolverKind.Z3) {
- var name = Z3.SetTimeoutOption();
- var value = ms.ToString();
- options.TimeLimit = ms;
- options.SmtOptions.RemoveAll(ov => ov.Option == name);
- options.AddSmtOption(name, value);
- SendThisVC(string.Format("(set-option :{0} {1})", name, value));
- }
- }
-
- public override object Evaluate(VCExpr expr)
- {
- string vcString = VCExpr2String(expr, 1);
- SendThisVC("(get-value (" + vcString + "))");
- var resp = Process.GetProverResponse();
- if (resp == null) throw new VCExprEvaluationException();
- if (!(resp.Name == "" && resp.ArgCount == 1)) throw new VCExprEvaluationException();
- resp = resp.Arguments[0];
- if (resp.Name == "")
- {
- // evaluating an expression
- if (resp.ArgCount == 2)
- resp = resp.Arguments[1];
- else
- throw new VCExprEvaluationException();
- }
- else
- {
- // evaluating a variable
- if (resp.ArgCount == 1)
- resp = resp.Arguments[0];
- else
- throw new VCExprEvaluationException();
- }
- if (resp.Name == "-" && resp.ArgCount == 1) // negative int
- return Microsoft.Basetypes.BigNum.FromString("-" + resp.Arguments[0].Name);
- if (resp.Name == "_" && resp.ArgCount == 2 && resp.Arguments[0].Name.StartsWith("bv")) // bitvector
- return new BvConst(Microsoft.Basetypes.BigNum.FromString(resp.Arguments[0].Name.Substring("bv".Length)),
- int.Parse(resp.Arguments[1].Name));
- if (resp.ArgCount != 0)
- throw new VCExprEvaluationException();
- if (expr.Type.Equals(Boogie.Type.Bool))
- return bool.Parse(resp.Name);
- else if (expr.Type.Equals(Boogie.Type.Int))
- return Microsoft.Basetypes.BigNum.FromString(resp.Name);
- else
- return resp.Name;
- }
-
- /// <summary>
- /// Extra state for ApiChecker (used by stratifiedInlining)
- /// </summary>
- static int nameCounter = 0;
-
- public override Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
- {
- unsatCore = new List<int>();
-
- Push();
- // Name the assumptions
- var nameToAssumption = new Dictionary<string, int>();
- int i = 0;
- foreach (var vc in assumptions)
- {
- var name = "a" + nameCounter.ToString();
- nameCounter++;
- nameToAssumption.Add(name, i);
-
- string vcString = VCExpr2String(vc, 1);
- AssertAxioms();
- SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name));
- i++;
- }
- Check();
-
- var outcome = CheckOutcomeCore(handler);
-
- if (outcome != Outcome.Valid) {
- Pop();
- return outcome;
- }
-
- Contract.Assert(usingUnsatCore, "SMTLib prover not setup for computing unsat cores");
- SendThisVC("(get-unsat-core)");
- var resp = Process.GetProverResponse();
- unsatCore = new List<int>();
- if (resp.Name != "") unsatCore.Add(nameToAssumption[resp.Name]);
- foreach (var s in resp.Arguments) unsatCore.Add(nameToAssumption[s.Name]);
-
- FlushLogFile();
- Pop();
- return outcome;
- }
-
- public override void Push()
- {
- SendThisVC("(push 1)");
- DeclCollector.Push();
- }
-
- public override Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) {
- unsatisfiedSoftAssumptions = new List<int>();
-
- // First, convert both hard and soft assumptions to SMTLIB strings
- List<string> hardAssumptionStrings = new List<string>();
- foreach (var a in hardAssumptions) {
- hardAssumptionStrings.Add(VCExpr2String(a, 1));
- }
- List<string> currAssumptionStrings = new List<string>();
- foreach (var a in softAssumptions) {
- currAssumptionStrings.Add(VCExpr2String(a, 1));
- }
-
- Push();
- AssertAxioms();
- foreach (var a in hardAssumptionStrings) {
- SendThisVC("(assert " + a + ")");
- }
- Check();
- Outcome outcome = GetResponse();
- if (outcome != Outcome.Invalid) {
- Pop();
- return outcome;
- }
-
- int k = 0;
- List<string> relaxVars = new List<string>();
- while (true) {
- Push();
- foreach (var a in currAssumptionStrings) {
- SendThisVC("(assert " + a + ")");
- }
- Check();
- outcome = CheckOutcomeCore(handler);
- if (outcome != Outcome.Valid)
- break;
- Pop();
- string relaxVar = "relax_" + k;
- relaxVars.Add(relaxVar);
- SendThisVC("(declare-fun " + relaxVar + " () Int)");
- List<string> nextAssumptionStrings = new List<string>();
- for (int i = 0; i < currAssumptionStrings.Count; i++) {
- string constraint = "(= " + relaxVar + " " + i + ")";
- nextAssumptionStrings.Add("(or " + currAssumptionStrings[i] + " " + constraint + ")");
- }
- currAssumptionStrings = nextAssumptionStrings;
- k++;
- }
-
- if (outcome == Outcome.Invalid) {
- foreach (var relaxVar in relaxVars) {
- SendThisVC("(get-value (" + relaxVar + "))");
- FlushLogFile();
- var resp = Process.GetProverResponse();
- if (resp == null) break;
- if (!(resp.Name == "" && resp.ArgCount == 1)) break;
- resp = resp.Arguments[0];
- if (!(resp.Name != "" && resp.ArgCount == 1)) break;
- resp = resp.Arguments[0];
- if (resp.ArgCount != 0)
- break;
- int v;
- if (int.TryParse(resp.Name, out v))
- unsatisfiedSoftAssumptions.Add(v);
- else
- break;
- }
- Pop();
- }
-
- Pop();
- return outcome;
- }
- }
-
- public class SMTLibInterpolatingProcessTheoremProver : SMTLibProcessTheoremProver
- {
- public SMTLibInterpolatingProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
- SMTLibProverContext ctx)
- : base(AddInterpOption(options), gen, ctx)
- {
-
- }
-
- private static ProverOptions AddInterpOption(ProverOptions options)
- {
- var opts = (SMTLibProverOptions)options;
- opts.AddSmtOption("produce-interpolants", "true");
- if (CommandLineOptions.Clo.PrintFixedPoint == null)
- CommandLineOptions.Clo.PrintFixedPoint = "itp.fixedpoint.bpl";
- return opts;
- }
-
- public override void AssertNamed(VCExpr vc, bool polarity, string name)
- {
- string vcString;
- if (polarity)
- {
- vcString = VCExpr2String(vc, 1);
- }
- else
- {
- vcString = "(not " + VCExpr2String(vc, 1) + ")";
- }
- AssertAxioms();
- SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name));
- }
-
- public override VCExpr ComputeInterpolant(VCExpr A, VCExpr B)
- {
- string A_str = VCExpr2String(A, 1);
- string B_str = VCExpr2String(B, 1);
-
- AssertAxioms();
- SendThisVC("(compute-interpolant " + A_str + " " + B_str + ")");
-
- SExpr interpolant;
- Outcome result = GetInterpolantResponse(out interpolant);
-
- if (result != Outcome.Valid)
- return null;
-
- VCExpr interpolantVC = SExprToVCExpr(interpolant, new Dictionary<string, VCExpr>());
- return interpolantVC;
- }
-
- private Outcome GetInterpolantResponse(out SExpr interpolant)
- {
- var result = Outcome.Undetermined;
- var wasUnknown = false;
- interpolant = null;
-
- Process.Ping();
- bool onlyOnce = false;
-
- while (true)
- {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- switch (resp.Name)
- {
- case "unsat":
- result = Outcome.Valid;
- break;
- case "sat":
- result = Outcome.Invalid;
- break;
- case "unknown":
- result = Outcome.Invalid;
- wasUnknown = true;
- break;
- default:
- if (result == Outcome.Valid)
- {
- interpolant = resp as SExpr;
-
- Contract.Assert(onlyOnce == false);
- onlyOnce = true;
- continue;
- }
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- }
-
- if (wasUnknown)
- {
- SendThisVC("(get-info :reason-unknown)");
- Process.Ping();
-
- while (true)
- {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- if (resp.ArgCount == 1 && resp.Name == ":reason-unknown")
- {
- switch (resp[0].Name)
- {
- case "memout":
- currentErrorHandler.OnResourceExceeded("memory");
- result = Outcome.OutOfMemory;
- Process.NeedsRestart = true;
- break;
- case "timeout":
- case "canceled":
- currentErrorHandler.OnResourceExceeded("timeout");
- result = Outcome.TimeOut;
- break;
- default:
- break;
- }
- }
- else
- {
- HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString());
- }
- }
- }
-
- return result;
- }
-
- public override List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves)
- {
- List<VCExpr> result = new List<VCExpr>();
-
- string vcStr = "true";
- foreach (string str in root)
- vcStr = vcStr + " " + str;
- foreach (string str in leaves)
- vcStr = vcStr + "\r\n (interp " + str + ")";
-
- vcStr = "(get-interpolant (and\r\n" + vcStr + "\r\n))";
- SendThisVC(vcStr);
- if(currentLogFile != null) currentLogFile.Flush();
-
- List<SExpr> interpolantList;
- GetTreeInterpolantResponse(out interpolantList);
-
- Dictionary<string, VCExpr> bound = new Dictionary<string, VCExpr>();
- foreach (SExpr sexpr in interpolantList)
- {
- VCExpr interpolantVC = SExprToVCExpr(sexpr, bound);
- result.Add(interpolantVC);
- }
-
- return result;
- }
-
- private void GetTreeInterpolantResponse(out List<SExpr> interpolantList)
- {
- interpolantList = new List<SExpr>();
-
- Process.Ping();
-
- while (true)
- {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- SExpr interpolant = resp as SExpr;
- if(interpolant == null)
- HandleProverError("Unexpected prover response: got null for interpolant!");
- interpolantList.Add(interpolant);
- }
- }
- }
-
- public class SMTLibProverContext : DeclFreeProverContext
- {
- internal SMTLibProcessTheoremProver parent;
-
- public readonly Dictionary<CtorType, List<Function>> KnownDatatypeConstructors = new Dictionary<CtorType, List<Function>>();
-
- public SMTLibProverContext(VCExpressionGenerator gen,
- VCGenerationOptions genOptions)
- : base(gen, genOptions)
- {
- }
-
- protected SMTLibProverContext(SMTLibProverContext par)
- : base(par)
- {
- }
-
- public override object Clone()
- {
- return new SMTLibProverContext(this);
- }
-
- public override string Lookup(VCExprVar var)
- {
- VCExprVar v = parent.AxBuilder.TryTyped2Untyped(var);
- if (v != null) {
- var = v;
- }
- return parent.Namer.Lookup(var);
- }
-
- public override void DeclareFunction(Function f, string attributes) {
- if (f is DatatypeConstructor) {
- CtorType datatype = (CtorType) f.OutParams[0].TypedIdent.Type;
- if (!KnownDatatypeConstructors.ContainsKey(datatype))
- KnownDatatypeConstructors[datatype] = new List<Function>();
- KnownDatatypeConstructors[datatype].Add(f);
- }
- base.DeclareFunction(f, attributes);
- }
- }
-
- public class Factory : ProverFactory
- {
- // Set programmatically
- public static bool UseInterpolation = false;
-
- public override object SpawnProver(ProverOptions options, object ctxt)
- {
- //Contract.Requires(ctxt != null);
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- return this.SpawnProver(options,
- cce.NonNull((SMTLibProverContext)ctxt).ExprGen,
- cce.NonNull((SMTLibProverContext)ctxt));
- }
-
- public override object NewProverContext(ProverOptions options)
- {
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- VCExpressionGenerator gen = new VCExpressionGenerator();
- List<string>/*!>!*/ proverCommands = new List<string/*!*/>();
- proverCommands.Add("smtlib");
- var opts = (SMTLibProverOptions)options ;
- if (opts.Solver == SolverKind.Z3)
- proverCommands.Add("z3");
- else
- proverCommands.Add("external");
- VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands);
- return new SMTLibProverContext(gen, genOptions);
- }
-
- public override ProverOptions BlankProverOptions()
- {
- return new SMTLibProverOptions();
- }
-
- protected virtual SMTLibProcessTheoremProver SpawnProver(ProverOptions options,
- VCExpressionGenerator gen,
- SMTLibProverContext ctx)
- {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
- Contract.Ensures(Contract.Result<SMTLibProcessTheoremProver>() != null);
-
- if (UseInterpolation)
- return new SMTLibInterpolatingProcessTheoremProver(options, gen, ctx);
-
- return new SMTLibProcessTheoremProver(options, gen, ctx);
- }
-
- public override bool SupportsLabels(ProverOptions options)
- {
- return ((SMTLibProverOptions)options).SupportsLabels;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+//using ExternalProver;
+using System.Linq;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Boogie.Clustering;
+using Microsoft.Boogie.TypeErasure;
+using System.Text;
+
+using RPFP = Microsoft.Boogie.RPFP;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ public class SMTLibProcessTheoremProver : ProverInterface
+ {
+ private readonly SMTLibProverContext ctx;
+ private VCExpressionGenerator gen;
+ private readonly SMTLibProverOptions options;
+ private bool usingUnsatCore;
+ private RPFP rpfp = null;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(ctx != null);
+ Contract.Invariant(AxBuilder != null);
+ Contract.Invariant(Namer != null);
+ Contract.Invariant(DeclCollector != null);
+ Contract.Invariant(cce.NonNullElements(Axioms));
+ Contract.Invariant(cce.NonNullElements(TypeDecls));
+ Contract.Invariant(_backgroundPredicates != null);
+
+ }
+
+
+ [NotDelayed]
+ public SMTLibProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
+ SMTLibProverContext ctx)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(ctx != null);
+
+ InitializeGlobalInformation();
+
+ this.options = (SMTLibProverOptions)options;
+ this.ctx = ctx;
+ this.gen = gen;
+ this.usingUnsatCore = false;
+
+ SetupAxiomBuilder(gen);
+
+ Namer = new SMTLibNamer();
+ ctx.parent = this;
+ this.DeclCollector = new TypeDeclCollector((SMTLibProverOptions)options, Namer);
+
+ if (CommandLineOptions.Clo.PrintFixedPoint != null || CommandLineOptions.Clo.PrintConjectures != null)
+ {
+ declHandler = new MyDeclHandler();
+ DeclCollector.SetDeclHandler(declHandler);
+ }
+
+ SetupProcess();
+
+ if (CommandLineOptions.Clo.StratifiedInlining > 0 || CommandLineOptions.Clo.ContractInfer
+ || CommandLineOptions.Clo.SecureVcGen != null)
+ {
+ // Prepare for ApiChecker usage
+ if (options.LogFilename != null && currentLogFile == null)
+ {
+ currentLogFile = OpenOutputFile("");
+ }
+ PrepareCommon();
+ }
+ }
+
+ public override void AssertNamed(VCExpr vc, bool polarity, string name)
+ {
+ string vcString;
+ if (polarity)
+ {
+ vcString = VCExpr2String(vc, 1);
+ }
+ else
+ {
+ vcString = "(not " + VCExpr2String(vc, 1) + ")";
+ }
+ AssertAxioms();
+ SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name));
+ }
+
+ private void SetupAxiomBuilder(VCExpressionGenerator gen)
+ {
+ switch (CommandLineOptions.Clo.TypeEncodingMethod)
+ {
+ case CommandLineOptions.TypeEncoding.Arguments:
+ AxBuilder = new TypeAxiomBuilderArguments(gen);
+ AxBuilder.Setup();
+ break;
+ case CommandLineOptions.TypeEncoding.Monomorphic:
+ AxBuilder = new TypeAxiomBuilderPremisses(gen);
+ break;
+ default:
+ AxBuilder = new TypeAxiomBuilderPremisses(gen);
+ AxBuilder.Setup();
+ break;
+ }
+ }
+
+ ProcessStartInfo ComputeProcessStartInfo()
+ {
+ var path = this.options.ProverPath;
+ switch (options.Solver) {
+ case SolverKind.Z3:
+ if (path == null)
+ path = Z3.ExecutablePath();
+ return SMTLibProcess.ComputerProcessStartInfo(path, "AUTO_CONFIG=false -smt2 -in");
+ case SolverKind.CVC4:
+ if (path == null)
+ path = CVC4.ExecutablePath();
+ return SMTLibProcess.ComputerProcessStartInfo(path, "--lang=smt --no-strict-parsing --no-condense-function-values --incremental");
+ default:
+ Debug.Assert(false);
+ return null;
+ }
+ }
+
+ void SetupProcess()
+ {
+ if (Process != null) return;
+
+ var psi = ComputeProcessStartInfo();
+ Process = new SMTLibProcess(psi, this.options);
+ Process.ErrorHandler += this.HandleProverError;
+ }
+
+
+ void PossiblyRestart()
+ {
+ if (Process != null && Process.NeedsRestart) {
+ Process.Close();
+ Process = null;
+ SetupProcess();
+ Process.Send(common.ToString());
+ }
+ }
+
+ public override ProverContext Context
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<ProverContext>() != null);
+
+ return ctx;
+ }
+ }
+
+ internal TypeAxiomBuilder AxBuilder { get; private set; }
+ internal readonly UniqueNamer Namer;
+ readonly TypeDeclCollector DeclCollector;
+ protected SMTLibProcess Process;
+ readonly List<string> proverErrors = new List<string>();
+ readonly List<string> proverWarnings = new List<string>();
+ readonly StringBuilder common = new StringBuilder();
+ protected TextWriter currentLogFile;
+ protected volatile ErrorHandler currentErrorHandler;
+
+ private void FeedTypeDeclsToProver()
+ {
+ foreach (string s in DeclCollector.GetNewDeclarations()) {
+ Contract.Assert(s != null);
+ AddTypeDecl(s);
+ }
+ }
+
+ private string Sanitize(string msg)
+ {
+ var idx = msg.IndexOf('\n');
+ if (idx > 0)
+ msg = msg.Replace("\r", "").Replace("\n", "\r\n");
+ return msg;
+ }
+
+ public override void LogComment(string comment)
+ {
+ SendCommon("; " + comment);
+ }
+
+ private void SendCommon(string s)
+ {
+ Send(s, true);
+ }
+
+ protected void SendThisVC(string s)
+ {
+ Send(s, false);
+ }
+
+ private void Send(string s, bool isCommon)
+ {
+ s = Sanitize(s);
+
+ if (isCommon)
+ common.Append(s).Append("\r\n");
+
+ if (Process != null)
+ Process.Send(s);
+ if (currentLogFile != null) {
+ currentLogFile.WriteLine(s);
+ currentLogFile.Flush();
+ }
+ }
+
+ private void FindDependentTypes(Type type, List<CtorType> dependentTypes)
+ {
+ MapType mapType = type as MapType;
+ if (mapType != null)
+ {
+ foreach (Type t in mapType.Arguments)
+ {
+ FindDependentTypes(t, dependentTypes);
+ }
+ FindDependentTypes(mapType.Result, dependentTypes);
+ }
+ CtorType ctorType = type as CtorType;
+ if (ctorType != null && ctx.KnownDatatypeConstructors.ContainsKey(ctorType))
+ {
+ dependentTypes.Add(ctorType);
+ }
+ }
+
+ private void PrepareCommon()
+ {
+ if (common.Length == 0)
+ {
+ SendCommon("(set-option :print-success false)");
+ SendCommon("(set-info :smt-lib-version 2.0)");
+ if (options.ProduceModel())
+ SendCommon("(set-option :produce-models true)");
+ foreach (var opt in options.SmtOptions)
+ {
+ SendCommon("(set-option :" + opt.Option + " " + opt.Value + ")");
+ }
+
+ if (!string.IsNullOrEmpty(options.Logic))
+ {
+ SendCommon("(set-logic " + options.Logic + ")");
+ }
+
+ // Set produce-unsat-cores last. It seems there's a bug in Z3 where if we set it earlier its value
+ // gets reset by other set-option commands ( https://z3.codeplex.com/workitem/188 )
+ if (CommandLineOptions.Clo.PrintNecessaryAssumes || (CommandLineOptions.Clo.ContractInfer && (CommandLineOptions.Clo.UseUnsatCoreForContractInfer || CommandLineOptions.Clo.ExplainHoudini)))
+ {
+ SendCommon("(set-option :produce-unsat-cores true)");
+ this.usingUnsatCore = true;
+ }
+
+ SendCommon("; done setting options\n");
+ SendCommon(_backgroundPredicates);
+
+ if (options.UseTickleBool)
+ {
+ SendCommon("(declare-fun tickleBool (Bool) Bool)");
+ SendCommon("(assert (and (tickleBool true) (tickleBool false)))");
+ }
+
+ if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout)
+ {
+ SendCommon("(declare-fun timeoutDiagnostics (Int) Bool)");
+ }
+
+ if (ctx.KnownDatatypeConstructors.Count > 0)
+ {
+ GraphUtil.Graph<CtorType> dependencyGraph = new GraphUtil.Graph<CtorType>();
+ foreach (CtorType datatype in ctx.KnownDatatypeConstructors.Keys)
+ {
+ dependencyGraph.AddSource(datatype);
+ foreach (Function f in ctx.KnownDatatypeConstructors[datatype])
+ {
+ List<CtorType> dependentTypes = new List<CtorType>();
+ foreach (Variable v in f.InParams)
+ {
+ FindDependentTypes(v.TypedIdent.Type, dependentTypes);
+ }
+ foreach (CtorType result in dependentTypes)
+ {
+ dependencyGraph.AddEdge(datatype, result);
+ }
+ }
+ }
+ GraphUtil.StronglyConnectedComponents<CtorType> sccs = new GraphUtil.StronglyConnectedComponents<CtorType>(dependencyGraph.Nodes, dependencyGraph.Predecessors, dependencyGraph.Successors);
+ sccs.Compute();
+ foreach (GraphUtil.SCC<CtorType> scc in sccs)
+ {
+ string datatypeString = "";
+ foreach (CtorType datatype in scc)
+ {
+ datatypeString += "(" + SMTLibExprLineariser.TypeToString(datatype) + " ";
+ foreach (Function f in ctx.KnownDatatypeConstructors[datatype])
+ {
+ string quotedConstructorName = Namer.GetQuotedName(f, f.Name);
+ if (f.InParams.Count == 0)
+ {
+ datatypeString += quotedConstructorName + " ";
+ }
+ else
+ {
+ datatypeString += "(" + quotedConstructorName + " ";
+ foreach (Variable v in f.InParams)
+ {
+ string quotedSelectorName = Namer.GetQuotedName(v, v.Name + "#" + f.Name);
+ datatypeString += "(" + quotedSelectorName + " " + DeclCollector.TypeToStringReg(v.TypedIdent.Type) + ") ";
+ }
+ datatypeString += ") ";
+ }
+ }
+ datatypeString += ") ";
+ }
+ List<string> decls = DeclCollector.GetNewDeclarations();
+ foreach (string decl in decls)
+ {
+ SendCommon(decl);
+ }
+ SendCommon("(declare-datatypes () (" + datatypeString + "))");
+ }
+ }
+ if (CommandLineOptions.Clo.ProverPreamble != null)
+ SendCommon("(include \"" + CommandLineOptions.Clo.ProverPreamble + "\")");
+ }
+
+ if (!AxiomsAreSetup)
+ {
+ var axioms = ctx.Axioms;
+ var nary = axioms as VCExprNAry;
+ if (nary != null && nary.Op == VCExpressionGenerator.AndOp)
+ foreach (var expr in nary.UniformArguments)
+ {
+ var str = VCExpr2String(expr, -1);
+ if (str != "true")
+ AddAxiom(str);
+ }
+ else
+ AddAxiom(VCExpr2String(axioms, -1));
+ AxiomsAreSetup = true;
+ }
+ }
+
+ public override int FlushAxiomsToTheoremProver()
+ {
+ // we feed the axioms when begincheck is called.
+ return 0;
+ }
+
+ private void FlushAxioms()
+ {
+ TypeDecls.Iter(SendCommon);
+ TypeDecls.Clear();
+ foreach (string s in Axioms) {
+ Contract.Assert(s != null);
+ if (s != "true")
+ SendCommon("(assert " + s + ")");
+ }
+ Axioms.Clear();
+ //FlushPushedAssertions();
+ }
+
+ private void CloseLogFile()
+ {
+ if (currentLogFile != null) {
+ currentLogFile.Close();
+ currentLogFile = null;
+ }
+ }
+
+ private void FlushLogFile()
+ {
+ if (currentLogFile != null) {
+ currentLogFile.Flush();
+ }
+ }
+
+ public override void Close()
+ {
+ base.Close();
+ CloseLogFile();
+ if (Process != null)
+ Process.Close();
+ }
+
+ public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
+ {
+ //Contract.Requires(descriptiveName != null);
+ //Contract.Requires(vc != null);
+ //Contract.Requires(handler != null);
+ rpfp = null;
+
+ if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen
+
+ if (options.LogFilename != null && currentLogFile == null)
+ {
+ currentLogFile = OpenOutputFile(descriptiveName);
+ currentLogFile.Write(common.ToString());
+ }
+
+ PrepareCommon();
+
+ OptimizationRequests.Clear();
+
+ string vcString = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))";
+ FlushAxioms();
+
+ PossiblyRestart();
+
+ SendThisVC("(push 1)");
+ SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")");
+
+ SendThisVC(vcString);
+
+ SendOptimizationRequests();
+
+ FlushLogFile();
+
+ if (Process != null) {
+ Process.PingPong(); // flush any errors
+
+ if (Process.Inspector != null)
+ Process.Inspector.NewProblem(descriptiveName, vc, handler);
+ }
+
+ SendCheckSat();
+ FlushLogFile();
+ }
+
+ private void SendOptimizationRequests()
+ {
+ if (options.Solver == SolverKind.Z3 && 0 < OptimizationRequests.Count)
+ {
+ foreach (var r in OptimizationRequests)
+ {
+ SendThisVC(r);
+ }
+ }
+ }
+
+ public override void Reset(VCExpressionGenerator gen)
+ {
+ if (options.Solver == SolverKind.Z3)
+ {
+ this.gen = gen;
+ SendThisVC("(reset)");
+
+ if (0 < common.Length)
+ {
+ var c = common.ToString();
+ Process.Send(c);
+ if (currentLogFile != null)
+ {
+ currentLogFile.WriteLine(c);
+ }
+ }
+ }
+ }
+
+ public override void FullReset(VCExpressionGenerator gen)
+ {
+ if (options.Solver == SolverKind.Z3)
+ {
+ this.gen = gen;
+ SendThisVC("(reset)");
+ Namer.Reset();
+ common.Clear();
+ SetupAxiomBuilder(gen);
+ Axioms.Clear();
+ TypeDecls.Clear();
+ AxiomsAreSetup = false;
+ ctx.Reset();
+ ctx.KnownDatatypeConstructors.Clear();
+ ctx.parent = this;
+ DeclCollector.Reset();
+ NamedAssumes.Clear();
+ UsedNamedAssumes = null;
+ SendThisVC("; did a full reset");
+ }
+ }
+
+
+
+ private string StripCruft(string name){
+ if(name.Contains("@@"))
+ return name.Remove(name.LastIndexOf ("@@"));
+ return name;
+ }
+
+ private class BadExprFromProver : Exception
+ {
+ };
+
+ private delegate VCExpr ArgGetter (int pos);
+
+ private delegate VCExpr[] ArgsGetter ();
+
+ private delegate VCExprVar[] VarsGetter ();
+
+ private VCExprOp VCStringToVCOp (string op)
+ {
+ switch (op) {
+ case "+" :
+ return VCExpressionGenerator.AddIOp;
+ case "-" :
+ return VCExpressionGenerator.SubIOp;
+ case "*" :
+ return VCExpressionGenerator.MulIOp;
+ case "div" :
+ return VCExpressionGenerator.DivIOp;
+ case "=" :
+ return VCExpressionGenerator.EqOp;
+ case "<=" :
+ return VCExpressionGenerator.LeOp;
+ case "<" :
+ return VCExpressionGenerator.LtOp;
+ case ">=" :
+ return VCExpressionGenerator.GeOp;
+ case ">" :
+ return VCExpressionGenerator.GtOp;
+ case "and" :
+ return VCExpressionGenerator.AndOp;
+ case "or" :
+ return VCExpressionGenerator.OrOp;
+ case "not" :
+ return VCExpressionGenerator.NotOp;
+ case "ite" :
+ return VCExpressionGenerator.IfThenElseOp;
+ default:
+ return null;
+ }
+ }
+
+ private class MyDeclHandler : TypeDeclCollector.DeclHandler {
+ public Dictionary<string,VCExprVar> var_map = new Dictionary<string, VCExprVar>();
+ public Dictionary<string,Function> func_map = new Dictionary<string, Function>();
+ public override void VarDecl(VCExprVar v){
+ var_map[v.Name] = v;
+ }
+ public override void FuncDecl(Function f){
+ func_map[f.Name] = f;
+ }
+ public MyDeclHandler() {
+ }
+ }
+
+ private MyDeclHandler declHandler = null;
+
+ private VCExprVar SExprToVar (SExpr e)
+ {
+ if(e.Arguments.Count() != 1){
+ HandleProverError ("Prover error: bad quantifier syntax");
+ throw new BadExprFromProver ();
+ }
+ string vname = StripCruft(e.Name);
+ SExpr vtype = e[0];
+ switch(vtype.Name){
+ case "Int":
+ return gen.Variable(vname,Type.Int);
+ case "Bool":
+ return gen.Variable (vname,Type.Bool);
+ case "Array":{
+ // TODO: handle more general array types
+ var idxType = Type.Int; // well, could be something else
+ var valueType =
+ (vtype.Arguments[1].Name == "Int") ? Type.Int : Type.Bool;
+ var types = new List<Type>();
+ types.Add(idxType);
+ return gen.Variable (vname, new MapType(Token.NoToken,new List<TypeVariable>(),types,valueType));
+ }
+ default: {
+ HandleProverError ("Prover error: bad type: " + vtype.Name);
+ throw new BadExprFromProver ();
+ }
+ }
+ }
+
+ private VCExpr MakeBinary(VCExprOp op, VCExpr [] args)
+ {
+ if (args.Count() == 0)
+ {
+ // with zero args we need the identity of the op
+ if (op == VCExpressionGenerator.AndOp)
+ return VCExpressionGenerator.True;
+ if (op == VCExpressionGenerator.OrOp)
+ return VCExpressionGenerator.False;
+ if (op == VCExpressionGenerator.AddIOp)
+ {
+ Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.ZERO;
+ return gen.Integer(x);
+ }
+ HandleProverError("Prover error: bad expression ");
+ throw new BadExprFromProver();
+ }
+ var temp = args[0];
+ for (int i = 1; i < args.Count(); i++)
+ temp = gen.Function(op, temp, args[i]);
+ return temp;
+ }
+
+ protected VCExpr SExprToVCExpr (SExpr e, Dictionary<string,VCExpr> bound)
+ {
+ if (e.Arguments.Count() == 0) {
+ var name = StripCruft(e.Name);
+ if (name [0] >= '0' && name [0] <= '9') {
+ Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.FromString(name);
+ return gen.Integer (x);
+ }
+ if (bound.ContainsKey (name)) {
+ return bound [name];
+ }
+ if(name == "true")
+ return VCExpressionGenerator.True;
+ if(name == "false")
+ return VCExpressionGenerator.False;
+ if(declHandler.var_map.ContainsKey(name))
+ return declHandler.var_map[name];
+ HandleProverError ("Prover error: unknown symbol:" + name);
+ //throw new BadExprFromProver ();
+ var v = gen.Variable(name, Type.Int);
+ bound.Add(name, v);
+ return v;
+ }
+ ArgGetter g = i => SExprToVCExpr (e [i], bound);
+ ArgsGetter ga = () => e.Arguments.Select (x => SExprToVCExpr (x, bound)).ToArray ();
+ VarsGetter gb = () => e [0].Arguments.Select (x => SExprToVar (x)).ToArray ();
+ switch (e.Name) {
+ case "select" :
+ return gen.Select (ga ());
+ case "store" :
+ return gen.Store (ga ());
+ case "forall":
+ case "exists":
+ {
+ var binds = e.Arguments[0];
+ var vcbinds = new List<VCExprVar>();
+ var bound_copy = new Dictionary<string, VCExpr>(bound);
+ for (int i = 0; i < binds.Arguments.Count(); i++)
+ {
+ var bind = binds.Arguments[i];
+ var symb = StripCruft(bind.Name);
+ var vcv = SExprToVar(bind);
+ vcbinds.Add(vcv);
+ bound[symb] = vcv;
+ }
+ var body = g(1);
+ if (e.Name == "forall")
+ body = gen.Forall(vcbinds, new List<VCTrigger>(), body);
+ else
+ body = gen.Exists(vcbinds, new List<VCTrigger>(), body);
+ bound = bound_copy;
+ return body;
+ }
+ case "-" : // have to deal with unary case
+ {
+ if(e.ArgCount == 1){
+ var args = new VCExpr[2];
+ args[0] = gen.Integer (Microsoft.Basetypes.BigNum.ZERO);
+ args[1] = g(0);
+ return gen.Function(VCStringToVCOp("-"),args);
+ }
+ return gen.Function(VCStringToVCOp("-"),ga());
+ }
+ case "!" : // this is commentary
+ return g(0);
+ case "let" : {
+ // we expand lets exponentially since there is no let binding in Boogie surface syntax
+ bool expand_lets = true;
+ var binds = e.Arguments[0];
+ var vcbinds = new List<VCExprLetBinding>();
+ var bound_copy = new Dictionary<string, VCExpr>(bound);
+ for(int i = 0; i < binds.Arguments.Count(); i++){
+ var bind = binds.Arguments[i];
+ var symb = bind.Name;
+ var def = bind.Arguments[0];
+ var vce = SExprToVCExpr(def, bound);
+ var vcv = gen.Variable(symb,vce.Type);
+ var vcb = gen.LetBinding(vcv,vce);
+ vcbinds.Add (vcb);
+ bound[symb] = expand_lets ? vce : vcv;
+ }
+ var body = g(1);
+ if(!expand_lets)
+ body = gen.Let(vcbinds,body);
+ bound = bound_copy;
+ return body;
+ }
+
+ default: {
+ var op = VCStringToVCOp (e.Name);
+ if (op == null) {
+ var name = StripCruft(e.Name);
+ if(declHandler.func_map.ContainsKey(name)){
+ Function f = declHandler.func_map[name];
+ return gen.Function (f, ga());
+ }
+ HandleProverError ("Prover error: unknown operator:" + e.Name);
+ throw new BadExprFromProver ();
+ }
+ if(op.Arity == 2)
+ return MakeBinary (op, ga ());
+ return gen.Function(op, ga());
+ }
+ }
+ }
+
+ private void SExprToSoln (SExpr resp,
+ Dictionary<int,Dictionary<string,string>> varSubst)
+ {
+ Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node> ();
+
+ foreach (var node in rpfp.nodes)
+ pmap.Add ((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
+
+ var lines = resp.Arguments;
+
+ // get all the predicate definitions
+ for (int i = 0; i < lines.Length; i++) {
+ var line = lines [i];
+ string pname;
+ RPFP.Transformer annot;
+ GetDefun(line, out pname, out annot);
+
+ if(pmap.ContainsKey(pname)){
+ var node = pmap[pname];
+ node.Annotation = annot;
+ }
+ else if(pname[0] != '@'){ // if not an internal symbol
+ HandleProverError ("Prover error: got unknown predicate:" + pname);
+ throw new BadExprFromProver ();
+ }
+ }
+
+ }
+
+ private void GetDefun(SExpr line, out string pname, out RPFP.Transformer annot)
+ {
+ if (line.Name != "define-fun")
+ {
+ HandleProverError("Prover error: expected define-fun but got:" + line.Name);
+ throw new BadExprFromProver();
+ }
+ if (line.ArgCount != 4)
+ {
+ HandleProverError("Prover error: define-fun has wrong number of arguments");
+ throw new BadExprFromProver();
+ }
+ pname = StripCruft(line.Arguments[0].Name);
+ var pvars = line.Arguments[1];
+ var pbody = line.Arguments[3]; // range has to be Bool
+ var binding = new Dictionary<string, VCExpr>();
+ var pvs = new List<VCExpr>();
+ foreach (var b in pvars.Arguments)
+ {
+ var e = SExprToVar(b);
+ pvs.Add(e);
+ binding.Add(StripCruft(b.Name), e);
+ }
+ VCExpr bexpr = SExprToVCExpr(pbody, binding);
+
+ annot = rpfp.CreateRelation(pvs.ToArray(), bexpr);
+ }
+
+ private RPFP.Node SExprToCex(SExpr resp, ErrorHandler handler,
+ Dictionary<int,Dictionary<string,string>> varSubst)
+ {
+ Dictionary<string, RPFP.Node> nmap = new Dictionary<string,RPFP.Node>();
+ Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node>();
+
+ foreach(var node in rpfp.nodes)
+ pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name,node);
+
+ RPFP.Node topnode = null;
+ var lines = resp.Arguments;
+
+ // last line of derivation is from query, skip it
+ for (int i = 0; i < lines.Length-1; i++)
+ {
+ var line = lines[i];
+ if (line.ArgCount != 6)
+ {
+ HandleProverError("bad derivation line from prover: " + line.ToString());
+ return null;
+ }
+ var name = line[0];
+ var conseq = line[1];
+ var rule = line[2];
+ var subst = line[3];
+ var labs = line[4];
+ var refs = line[5];
+ var predName = conseq.Name;
+ {
+ string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it!
+ int pos = predName.LastIndexOf(spacer);
+ if (pos >= 0)
+ predName = predName.Substring(0, pos);
+ }
+ RPFP.Node node = null;
+ if (!pmap.TryGetValue(predName, out node))
+ {
+ HandleProverError("unknown predicate from prover: " + predName.ToString());
+ return null;
+ }
+ RPFP.Node cexnode = rpfp.CloneNode(node);
+ cexnode.map = node;
+ nmap.Add(name.Name, cexnode);
+ List<RPFP.Node> Chs = new List<RPFP.Node>();
+
+ if (refs.Name != "ref")
+ {
+ HandleProverError("bad references from prover: " + refs.ToString());
+ return null;
+ }
+ foreach (var c in refs.Arguments)
+ {
+ if (c.Name == "true")
+ Chs.Add(null);
+ else
+ {
+ RPFP.Node ch = null;
+ if (!nmap.TryGetValue(c.Name, out ch))
+ {
+ HandleProverError("unknown reference from prover: " + c.ToString());
+ return null;
+ }
+ Chs.Add(ch);
+ }
+ }
+
+ if (!rule.Name.StartsWith("rule!"))
+ {
+ HandleProverError("bad rule name from prover: " + refs.ToString());
+ return null;
+ }
+ int ruleNum = Convert.ToInt32(rule.Name.Substring(5)) - 1;
+ if (ruleNum < 0 || ruleNum > rpfp.edges.Count)
+ {
+ HandleProverError("bad rule name from prover: " + refs.ToString());
+ return null;
+ }
+ RPFP.Edge orig_edge = rpfp.edges[ruleNum];
+ RPFP.Edge e = rpfp.CreateEdge(cexnode, orig_edge.F, Chs.ToArray());
+ e.map = orig_edge;
+ topnode = cexnode;
+
+ if (labs.Name != "labels")
+ {
+ HandleProverError("bad labels from prover: " + labs.ToString());
+ return null;
+ }
+ e.labels = new HashSet<string>();
+ foreach (var l in labs.Arguments)
+ e.labels.Add(l.Name);
+
+ if (subst.Name != "subst")
+ {
+ HandleProverError("bad subst from prover: " + subst.ToString());
+ return null;
+ }
+ Dictionary<string, string> dict = new Dictionary<string, string>();
+ varSubst[e.number] = dict;
+ foreach (var s in subst.Arguments)
+ {
+ if (s.Name != "=" || s.Arguments.Length != 2)
+ {
+ HandleProverError("bad equation from prover: " + s.ToString());
+ return null;
+ }
+ string uniqueName = s.Arguments[0].Name;
+ string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it!
+ int pos = uniqueName.LastIndexOf(spacer);
+ if (pos >= 0)
+ uniqueName = uniqueName.Substring(0, pos);
+ dict.Add(uniqueName, s.Arguments[1].ToString());
+ }
+
+ }
+ if (topnode == null)
+ {
+ HandleProverError("empty derivation from prover: " + resp.ToString());
+ }
+ return topnode;
+ }
+
+ private Model SExprToModel(SExpr resp, ErrorHandler handler)
+ {
+ // Concatenate all the arguments
+ string modelString = resp[0].Name;
+ // modelString = modelString.Substring(7, modelString.Length - 8); // remove "(model " and final ")"
+ var models = Model.ParseModels(new StringReader("Error model: \n" + modelString));
+ if (models == null || models.Count == 0)
+ {
+ HandleProverError("no model from prover: " + resp.ToString());
+ }
+ return models[0];
+ }
+
+ private string QuantifiedVCExpr2String(VCExpr x)
+ {
+ return VCExpr2String(x, 1);
+#if false
+ if (!(x is VCExprQuantifier))
+ return VCExpr2String(x, 1);
+ VCExprQuantifier node = (x as VCExprQuantifier);
+ if(node.BoundVars.Count == 0)
+ return VCExpr2String(x, 1);
+
+ StringWriter wr = new StringWriter();
+
+ string kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
+ wr.Write("({0} (", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++)
+ {
+ VCExprVar var = node.BoundVars[i];
+ Contract.Assert(var != null);
+ string printedName = Namer.GetQuotedName(var, var.Name);
+ Contract.Assert(printedName != null);
+ wr.Write("({0} {1}) ", printedName, SMTLibExprLineariser.TypeToString(var.Type));
+ }
+
+ wr.Write(") ");
+ wr.Write(VCExpr2String(node.Body, 1));
+ wr.Write(")");
+ string res = wr.ToString();
+ return res;
+#endif
+ }
+
+ public override Outcome CheckRPFP(string descriptiveName, RPFP _rpfp, ErrorHandler handler,
+ out RPFP.Node cex,
+ Dictionary<int, Dictionary<string, string>> varSubst,
+ Dictionary<string, int> extra_bound)
+ {
+ //Contract.Requires(descriptiveName != null);
+ //Contract.Requires(vc != null);
+ //Contract.Requires(handler != null);
+ rpfp = _rpfp;
+ cex = null;
+
+
+ if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen
+
+ if (options.LogFilename != null && currentLogFile == null)
+ {
+ currentLogFile = OpenOutputFile(descriptiveName);
+ currentLogFile.Write(common.ToString());
+ }
+
+ PrepareCommon();
+
+ Push();
+ SendThisVC("(fixedpoint-push)");
+ foreach (var node in rpfp.nodes)
+ {
+ DeclCollector.RegisterRelation((node.Name as VCExprBoogieFunctionOp).Func);
+ }
+
+ LineariserOptions.Default.LabelsBelowQuantifiers = true;
+ List<string> ruleStrings = new List<string>();
+ var recursion_bound = CommandLineOptions.Clo.RecursionBound;
+ foreach (var edge in rpfp.edges)
+ {
+ string node_name = (edge.Parent.Name as VCExprBoogieFunctionOp).Func.Name;
+ string rule_name = "rule_" + edge.number.ToString();
+ string rec_bound = "";
+ if(extra_bound != null && extra_bound.ContainsKey(node_name))
+ rec_bound = (recursion_bound + extra_bound[node_name]).ToString();
+ string ruleString = "(rule " + QuantifiedVCExpr2String(rpfp.GetRule(edge)) + " " + rule_name + " " + rec_bound + "\n)";
+ ruleStrings.Add(ruleString);
+ }
+ string queryString = "(query " + QuantifiedVCExpr2String(rpfp.GetQuery()) + "\n :engine duality\n :print-certificate true\n";
+
+#if true
+ if (CommandLineOptions.Clo.StratifiedInlining != 0)
+ queryString += " :stratified-inlining true\n";
+ if (CommandLineOptions.Clo.RecursionBound > 0)
+ queryString += " :recursion-bound " + Convert.ToString(CommandLineOptions.Clo.RecursionBound) + "\n";
+#endif
+ queryString += ")";
+ LineariserOptions.Default.LabelsBelowQuantifiers = false;
+ FlushAxioms();
+
+ PossiblyRestart();
+
+ SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")");
+ foreach(var rs in ruleStrings)
+ SendThisVC(rs);
+ FlushLogFile();
+
+ if (Process != null)
+ {
+ Process.PingPong(); // flush any errors
+
+#if false
+ // TODO: this is not going to work
+ if (Process.Inspector != null)
+ Process.Inspector.NewProblem(descriptiveName, vc, handler);
+#endif
+ }
+
+ SendThisVC(queryString);
+ FlushLogFile();
+
+ var result = Outcome.Undetermined;
+
+ if (Process != null)
+ {
+
+ var resp = Process.GetProverResponse();
+
+ if (proverErrors.Count > 0)
+ {
+ result = Outcome.Undetermined;
+ foreach (var err in proverErrors)
+ {
+ if (err.Contains("canceled"))
+ {
+ result = Outcome.TimeOut;
+ }
+ }
+ }
+ else if(resp == null)
+ HandleProverError("Prover did not respond");
+ else switch (resp.Name)
+ {
+ case "unsat":
+ result = Outcome.Valid;
+ break;
+ case "sat":
+ result = Outcome.Invalid;
+ break;
+ case "unknown":
+ result = Outcome.Invalid;
+ break;
+ case "bounded":
+ result = Outcome.Bounded;
+ break;
+ case "error":
+ if (resp.ArgCount > 0 && resp.Arguments[0].Name.Contains("canceled"))
+ {
+ result = Outcome.TimeOut;
+ }
+ else
+ {
+ HandleProverError("Prover error: " + resp.Arguments[0]);
+ result = Outcome.Undetermined;
+ }
+ break;
+ default:
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ break;
+ }
+
+ switch (result)
+ {
+ case Outcome.Invalid:
+ {
+ resp = Process.GetProverResponse();
+ if (resp.Name == "derivation")
+ {
+ cex = SExprToCex(resp, handler,varSubst);
+ }
+ else
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ resp = Process.GetProverResponse();
+ if (resp.Name == "model")
+ {
+ var model = SExprToModel(resp, handler);
+ cex.owner.SetBackgroundModel(model);
+ }
+ else
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ break;
+ }
+ case Outcome.Valid:
+ case Outcome.Bounded:
+ {
+ resp = Process.GetProverResponse();
+ if (resp.Name == "fixedpoint")
+ {
+ // only get the response if we need it
+ if(CommandLineOptions.Clo.PrintFixedPoint != null)
+ SExprToSoln(resp, varSubst);
+ }
+ else
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ break;
+ }
+ default:
+ break;
+ }
+
+#if false
+ while (true)
+ {
+ resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ }
+#endif
+ }
+ SendThisVC("(fixedpoint-pop)");
+ Pop();
+ AxiomsAreSetup = false;
+
+ if (CommandLineOptions.Clo.PrintConjectures != null)
+ {
+ ReadConjectures(CommandLineOptions.Clo.PrintConjectures);
+ }
+
+ return result;
+ }
+
+ class MyFileParser : SExpr.Parser
+ {
+ SMTLibProcessTheoremProver parent;
+
+ public MyFileParser(System.IO.StreamReader _sr, SMTLibProcessTheoremProver _parent)
+ : base(_sr)
+ {
+ parent = _parent;
+ }
+ public override void ParseError(string msg)
+ {
+ parent.HandleProverError("Error in conjecture file from prover: " + msg);
+ }
+ }
+
+ void ReadConjectures(string filename)
+ {
+ try
+ {
+ System.IO.StreamReader sr = new StreamReader(filename + ".tmp");
+ SExpr.Parser p = new MyFileParser(sr, this);
+ var sexps = p.ParseSExprs(false);
+ Dictionary<string, RPFP.Node> pmap = GetNodeMap();
+ foreach (var e in sexps)
+ {
+ string pname;
+ RPFP.Transformer annot;
+ GetDefun(e, out pname, out annot);
+
+ if (pmap.ContainsKey(pname))
+ {
+ var c = new RPFP.Conjecture();
+ c.node = pmap[pname];
+ c.bound = annot;
+ rpfp.conjectures.Add(c);
+ }
+ else if (pname[0] != '@')
+ { // if not an internal symbol
+ HandleProverError("Prover error: got unknown predicate:" + pname);
+ throw new BadExprFromProver();
+ }
+ }
+ sr.Close();
+ }
+ catch (Exception)
+ {
+ HandleProverError("No conjecture file from prover");
+ throw new BadExprFromProver();
+ }
+ }
+
+ private Dictionary<string, RPFP.Node> GetNodeMap()
+ {
+ Dictionary<string, RPFP.Node> pmap = new Dictionary<string, RPFP.Node>();
+ foreach (var node in rpfp.nodes)
+ pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
+ return pmap;
+ }
+
+ private static HashSet<string> usedLogNames = new HashSet<string>();
+
+ private TextWriter OpenOutputFile(string descriptiveName)
+ {
+ Contract.Requires(descriptiveName != null);
+ Contract.Ensures(Contract.Result<TextWriter>() != null);
+
+ string filename = options.LogFilename;
+ filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
+ var curFilename = filename;
+
+ lock (usedLogNames) {
+ int n = 1;
+ while (usedLogNames.Contains(curFilename)) {
+ curFilename = filename + "." + n++;
+ }
+ usedLogNames.Add(curFilename);
+ }
+
+ return new StreamWriter(curFilename, false);
+ }
+
+ private void FlushProverWarnings()
+ {
+ var handler = currentErrorHandler;
+ if (handler != null) {
+ lock (proverWarnings) {
+ proverWarnings.Iter(handler.OnProverWarning);
+ proverWarnings.Clear();
+ }
+ }
+ }
+
+ protected void HandleProverError(string s)
+ {
+ s = s.Replace("\r", "");
+ lock (proverWarnings) {
+ while (s.StartsWith("WARNING: ")) {
+ var idx = s.IndexOf('\n');
+ var warn = s;
+ if (idx > 0) {
+ warn = s.Substring(0, idx);
+ s = s.Substring(idx + 1);
+ } else {
+ s = "";
+ }
+ warn = warn.Substring(9);
+ proverWarnings.Add(warn);
+ }
+ }
+
+ FlushProverWarnings();
+
+ if (s == "") return;
+
+ lock (proverErrors) {
+ proverErrors.Add(s);
+ Console.WriteLine("Prover error: " + s);
+ }
+ }
+
+ [NoDefaultContract]
+ public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1)
+ {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ var result = CheckOutcomeCore(handler, taskID: taskID);
+ SendThisVC("(pop 1)");
+ FlushLogFile();
+
+ return result;
+ }
+
+ [NoDefaultContract]
+ public override Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1)
+ {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ var result = Outcome.Undetermined;
+
+ if (Process == null)
+ return result;
+
+ try {
+ currentErrorHandler = handler;
+ FlushProverWarnings();
+
+ int errorLimit;
+ if (CommandLineOptions.Clo.ConcurrentHoudini) {
+ Contract.Assert(taskID >= 0);
+ errorLimit = CommandLineOptions.Clo.Cho[taskID].ProverCCLimit;
+ } else {
+ errorLimit = CommandLineOptions.Clo.ProverCCLimit;
+ }
+
+ if (errorLimit < 1)
+ errorLimit = 1;
+
+ int errorsLeft = errorLimit;
+
+ var globalResult = Outcome.Undetermined;
+
+ while (true) {
+ string[] labels = null;
+ bool popLater = false;
+
+ try {
+ errorsLeft--;
+
+ result = GetResponse();
+
+ var reporter = handler as VC.VCGen.ErrorReporter;
+ // TODO(wuestholz): Is the reporter ever null?
+ if (usingUnsatCore && result == Outcome.Valid && reporter != null && 0 < NamedAssumes.Count)
+ {
+ if (usingUnsatCore)
+ {
+ UsedNamedAssumes = new HashSet<string>();
+ SendThisVC("(get-unsat-core)");
+ var resp = Process.GetProverResponse();
+ if (resp.Name != "")
+ {
+ UsedNamedAssumes.Add(resp.Name);
+ if (CommandLineOptions.Clo.PrintNecessaryAssumes)
+ {
+ reporter.AddNecessaryAssume(resp.Name.Substring("aux$$assume$$".Length));
+ }
+ }
+ foreach (var arg in resp.Arguments)
+ {
+ UsedNamedAssumes.Add(arg.Name);
+ if (CommandLineOptions.Clo.PrintNecessaryAssumes)
+ {
+ reporter.AddNecessaryAssume(arg.Name.Substring("aux$$assume$$".Length));
+ }
+ }
+ }
+ else
+ {
+ UsedNamedAssumes = null;
+ }
+ }
+
+ if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout && result == Outcome.TimeOut)
+ {
+ #region Run timeout diagnostics
+
+ if (CommandLineOptions.Clo.TraceDiagnosticsOnTimeout)
+ {
+ Console.Out.WriteLine("Starting timeout diagnostics with initial time limit {0}.", options.TimeLimit);
+ }
+
+ SendThisVC("; begin timeout diagnostics");
+
+ var start = DateTime.UtcNow;
+ var unverified = new SortedSet<int>(ctx.TimeoutDiagnosticIDToAssertion.Keys);
+ var timedOut = new SortedSet<int>();
+ int frac = 2;
+ int queries = 0;
+ int timeLimitPerAssertion = 0 < options.TimeLimit ? (options.TimeLimit / 100) * CommandLineOptions.Clo.TimeLimitPerAssertionInPercent : 1000;
+ while (true)
+ {
+ int rem = unverified.Count;
+ if (rem == 0)
+ {
+ if (0 < timedOut.Count)
+ {
+ result = CheckSplit(timedOut, ref popLater, options.TimeLimit, timeLimitPerAssertion, ref queries);
+ if (result == Outcome.Valid)
+ {
+ timedOut.Clear();
+ }
+ else if (result == Outcome.TimeOut)
+ {
+ // Give up and report which assertions were not verified.
+ var cmds = timedOut.Select(id => ctx.TimeoutDiagnosticIDToAssertion[id]);
+
+ if (cmds.Any())
+ {
+ handler.OnResourceExceeded("timeout after running diagnostics", cmds);
+ }
+ }
+ }
+ else
+ {
+ result = Outcome.Valid;
+ }
+ break;
+ }
+
+ // TODO(wuestholz): Try out different ways for splitting up the work (e.g., randomly).
+ var cnt = Math.Max(1, rem / frac);
+ // It seems like assertions later in the control flow have smaller indexes.
+ var split = new SortedSet<int>(unverified.Where((val, idx) => (rem - idx - 1) < cnt));
+ Contract.Assert(0 < split.Count);
+ var splitRes = CheckSplit(split, ref popLater, timeLimitPerAssertion, timeLimitPerAssertion, ref queries);
+ if (splitRes == Outcome.Valid)
+ {
+ unverified.ExceptWith(split);
+ frac = 1;
+ }
+ else if (splitRes == Outcome.Invalid)
+ {
+ result = splitRes;
+ break;
+ }
+ else if (splitRes == Outcome.TimeOut)
+ {
+ if (2 <= frac && (4 <= (rem / frac)))
+ {
+ frac *= 4;
+ }
+ else if (2 <= (rem / frac))
+ {
+ frac *= 2;
+ }
+ else
+ {
+ timedOut.UnionWith(split);
+ unverified.ExceptWith(split);
+ frac = 1;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ unverified.UnionWith(timedOut);
+
+ var end = DateTime.UtcNow;
+
+ SendThisVC("; end timeout diagnostics");
+
+ if (CommandLineOptions.Clo.TraceDiagnosticsOnTimeout)
+ {
+ Console.Out.WriteLine("Terminated timeout diagnostics after {0:F0} ms and {1} prover queries.", end.Subtract(start).TotalMilliseconds, queries);
+ Console.Out.WriteLine("Outcome: {0}", result);
+ Console.Out.WriteLine("Unverified assertions: {0} (of {1})", unverified.Count, ctx.TimeoutDiagnosticIDToAssertion.Keys.Count);
+
+ string filename = "unknown";
+ var assertion = ctx.TimeoutDiagnosticIDToAssertion.Values.Select(t => t.Item1).FirstOrDefault(a => a.tok != null && a.tok != Token.NoToken && a.tok.filename != null);
+ if (assertion != null)
+ {
+ filename = assertion.tok.filename;
+ }
+ File.AppendAllText("timeouts.csv", string.Format(";{0};{1};{2:F0};{3};{4};{5};{6}\n", filename, options.TimeLimit, end.Subtract(start).TotalMilliseconds, queries, result, unverified.Count, ctx.TimeoutDiagnosticIDToAssertion.Keys.Count));
+ }
+
+ #endregion
+ }
+
+ if (globalResult == Outcome.Undetermined)
+ globalResult = result;
+
+ if (result == Outcome.Invalid || result == Outcome.TimeOut || result == Outcome.OutOfMemory) {
+ IList<string> xlabels;
+ if (CommandLineOptions.Clo.UseLabels) {
+ labels = GetLabelsInfo();
+ if (labels == null)
+ {
+ xlabels = new string[] { };
+ }
+ else
+ {
+ xlabels = labels.Select(a => a.Replace("@", "").Replace("+", "")).ToList();
+ }
+ }
+ else if(CommandLineOptions.Clo.SIBoolControlVC) {
+ labels = new string[0];
+ xlabels = labels;
+ } else {
+ labels = CalculatePath(handler.StartingProcId());
+ xlabels = labels;
+ }
+ Model model = (result == Outcome.TimeOut || result == Outcome.OutOfMemory) ? null :
+ GetErrorModel();
+ handler.OnModel(xlabels, model, result);
+ }
+
+ if (labels == null || !labels.Any() || errorsLeft == 0) break;
+ } finally {
+ if (popLater)
+ {
+ SendThisVC("(pop 1)");
+ }
+ }
+
+ if (CommandLineOptions.Clo.UseLabels) {
+ var negLabels = labels.Where(l => l.StartsWith("@")).ToArray();
+ var posLabels = labels.Where(l => !l.StartsWith("@"));
+ Func<string, string> lbl = (s) => SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(s));
+ if (!options.MultiTraces)
+ posLabels = Enumerable.Empty<string>();
+ var conjuncts = posLabels.Select(s => "(not " + lbl(s) + ")").Concat(negLabels.Select(lbl)).ToArray();
+ string expr = conjuncts.Length == 1 ? conjuncts[0] : ("(or " + conjuncts.Concat(" ") + ")"); ;
+ if (!conjuncts.Any())
+ {
+ expr = "false";
+ }
+ SendThisVC("(assert " + expr + ")");
+ SendCheckSat();
+ }
+ else {
+ string source = labels[labels.Length - 2];
+ string target = labels[labels.Length - 1];
+ SendThisVC("(assert (not (= (ControlFlow 0 " + source + ") (- " + target + "))))");
+ SendCheckSat();
+ }
+ }
+
+ FlushLogFile();
+
+ if (CommandLineOptions.Clo.RestartProverPerVC && Process != null)
+ Process.NeedsRestart = true;
+
+ return globalResult;
+
+ } finally {
+ currentErrorHandler = null;
+ }
+ }
+
+ private Outcome CheckSplit(SortedSet<int> split, ref bool popLater, int timeLimit, int timeLimitPerAssertion, ref int queries)
+ {
+ var tla = timeLimitPerAssertion * split.Count;
+
+ if (popLater)
+ {
+ SendThisVC("(pop 1)");
+ }
+
+ SendThisVC("(push 1)");
+ SendThisVC(string.Format("(set-option :{0} {1})", Z3.SetTimeoutOption(), (0 < tla && tla < timeLimit) ? tla : timeLimit));
+ popLater = true;
+
+ SendThisVC(string.Format("; checking split VC with {0} unverified assertions", split.Count));
+ var expr = VCExpressionGenerator.True;
+ foreach (var i in ctx.TimeoutDiagnosticIDToAssertion.Keys)
+ {
+ var lit = VCExprGen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, VCExprGen.Integer(Microsoft.Basetypes.BigNum.FromInt(i)));
+ if (split.Contains(i)) {
+ lit = VCExprGen.Not(lit);
+ }
+ expr = VCExprGen.AndSimp(expr, lit);
+ }
+ SendThisVC("(assert " + VCExpr2String(expr, 1) + ")");
+ if (options.Solver == SolverKind.Z3)
+ {
+ SendThisVC("(apply (then (using-params propagate-values :max_rounds 1) simplify) :print false)");
+ }
+ FlushLogFile();
+ SendCheckSat();
+ queries++;
+ return GetResponse();
+ }
+
+ public override string[] CalculatePath(int controlFlowConstant) {
+ SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " 0)))");
+ var path = new List<string>();
+ while (true) {
+ var resp = Process.GetProverResponse();
+ if (resp == null) break;
+ if (!(resp.Name == "" && resp.ArgCount == 1)) break;
+ resp = resp.Arguments[0];
+ if (!(resp.Name == "" && resp.ArgCount == 2)) break;
+ resp = resp.Arguments[1];
+ var v = resp.Name;
+ if (v == "-" && resp.ArgCount == 1) {
+ v = resp.Arguments[0].Name;
+ path.Add(v);
+ break;
+ }
+ else if (resp.ArgCount != 0)
+ break;
+ path.Add(v);
+ SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " " + v + ")))");
+ }
+ return path.ToArray();
+ }
+
+
+ private class SMTErrorModelConverter {
+ private struct SMTDataType {
+ public string Constructor;
+ public List<SExpr> Types;
+ }
+
+ private List<SExpr> ErrorModelTodo;
+ private SMTLibProcessTheoremProver Parent;
+ private StringBuilder ErrorModel = new StringBuilder();
+ private HashSet<SExpr> TopLevelProcessed = new HashSet<SExpr>();
+ private int NumNewArrays = 0;
+ private Dictionary<string, int> SortSet = new Dictionary<string, int>();
+ private Dictionary<string, SMTDataType> DataTypes = new Dictionary<string, SMTDataType>();
+ private Dictionary<string, SExpr> Functions = new Dictionary<string, SExpr>();
+
+ public SMTErrorModelConverter(SExpr _ErrorModel, SMTLibProcessTheoremProver _Parent) {
+ ErrorModelTodo = _ErrorModel.Arguments.ToList();;
+ Parent = _Parent;
+ }
+
+ public string Convert() {
+ ConvertErrorModel(ErrorModel);
+ return ErrorModel.ToString();
+ }
+
+ bool isConstArray(SExpr element, SExpr type) {
+ if (type.Name != "Array")
+ return false;
+
+ if (element.Name == "__array_store_all__") // CVC4 1.4
+ return true;
+ else if (element.Name == "" && element[0].Name == "as" &&
+ element[0][0].Name == "const") // CVC4 > 1.4
+ return true;
+
+ return false;
+ }
+
+ SExpr getConstArrayElement(SExpr element) {
+ if (element.Name == "__array_store_all__") // CVC4 1.4
+ return element[1];
+ else if (element.Name == "" && element[0].Name == "as" &&
+ element[0][0].Name == "const") // CVC4 > 1.4
+ return element[1];
+
+ Parent.HandleProverError("Unexpected value: " + element);
+ throw new BadExprFromProver ();
+ }
+
+ void ConstructComplexValue(SExpr element, SExpr type, StringBuilder m) {
+ if (type.Name == "Array") {
+ if (element.Name == "store" || isConstArray(element, type)) {
+ NumNewArrays++;
+ m.Append("as-array[k!" + NumNewArrays + ']');
+ SExpr[] args = {new SExpr("k!" + NumNewArrays), new SExpr(""), type, element};
+ var newElement = new SExpr("define-fun", args);
+ TopLevelProcessed.Add(newElement);
+ ErrorModelTodo.Add(newElement);
+ return;
+ }
+ }
+
+ ConstructSimpleValue(element, type, m);
+ }
+
+ void ConstructSimpleValue(SExpr element, SExpr type, StringBuilder m) {
+ if (type.Name == "Bool" && element.ArgCount == 0) {
+ m.Append(element.ToString());
+ return;
+ }
+
+ if (type.Name == "Int") {
+ if (element.ArgCount == 0) {
+ m.Append(element.ToString());
+ return;
+ } else if (element.Name == "-" && element.ArgCount == 1) {
+ m.Append(element.ToString());
+ return;
+ }
+ }
+
+ if (type.Name == "_" && type.ArgCount == 2 && type[0].Name == "BitVec") {
+ if (element.Name == "_" && element.ArgCount == 2 &&
+ element[0].Name.StartsWith("bv") && element[0].ArgCount == 0 &&
+ element[1].Name == type.Arguments[1].Name && element[1].ArgCount == 0) {
+ m.Append(element[0].Name + '[' + element[1].Name + ']');
+ return;
+ }
+ }
+
+ if (type.Name == "Array") {
+ while (element.Name == "store") {
+ ConstructComplexValue(element[1], type[0], m);
+ m.Append(" -> ");
+ ConstructComplexValue(element[2], type[1], m);
+ m.Append("\n ");
+ if (element[0].Name != "store") {
+ m.Append("else -> ");
+ }
+ element = element[0];
+ }
+
+ if (isConstArray(element, type)) {
+ ConstructComplexValue(getConstArrayElement(element), type[1], m);
+ return;
+ } else if (element.Name == "_" && element.ArgCount == 2 &&
+ element[0].Name == "as-array") {
+ m.Append("as-array[" + element[1].Name + ']');
+ return;
+ }
+ }
+
+ if (SortSet.ContainsKey(type.Name) && SortSet[type.Name] == 0) {
+ var prefix = "@uc_T_" + type.Name.Substring(2) + "_";
+ if (element.Name.StartsWith(prefix)) {
+ m.Append(type.Name + "!val!" + element.Name.Substring(prefix.Length));
+ return;
+ }
+ }
+
+ if (Functions.ContainsKey(element.Name) &&
+ type.Name == Functions[element.Name].Name) {
+ m.Append(element.Name);
+ return;
+ }
+
+ if (DataTypes.ContainsKey(type.Name) &&
+ DataTypes[type.Name].Constructor == element.Name &&
+ element.ArgCount == DataTypes[type.Name].Types.Count) {
+ m.Append("(" + element.Name);
+ for (int i = 0; i < element.ArgCount; ++i) {
+ m.Append(" ");
+ ConstructComplexValue(element[i], DataTypes[type.Name].Types[i], m);
+ }
+ m.Append(")");
+ return;
+ }
+
+ Parent.HandleProverError("Unexpected value: " + element);
+ throw new BadExprFromProver ();
+ }
+
+ void ConstructFunctionArguments(SExpr arguments, List<SExpr> argTypes, StringBuilder[] argValues) {
+ if (arguments.Name == "and") {
+ ConstructFunctionArguments(arguments[0], argTypes, argValues);
+ ConstructFunctionArguments(arguments[1], argTypes, argValues);
+ } else if (arguments.Name == "=" &&
+ (arguments[0].Name.StartsWith("_ufmt_") || arguments[0].Name.StartsWith("x!"))) {
+ int argNum;
+ if (arguments[0].Name.StartsWith("_ufmt_"))
+ argNum = System.Convert.ToInt32(arguments[0].Name.Substring("_uftm_".Length)) - 1;
+ else /* if (arguments[0].Name.StartsWith("x!")) */
+ argNum = System.Convert.ToInt32(arguments[0].Name.Substring("x!".Length)) - 1;
+ if (argNum < 0 || argNum >= argTypes.Count) {
+ Parent.HandleProverError("Unexpected function argument: " + arguments[0]);
+ throw new BadExprFromProver ();
+ }
+ if (argValues[argNum] != null) {
+ Parent.HandleProverError("Function argument defined multiple times: " + arguments[0]);
+ throw new BadExprFromProver ();
+ }
+ argValues[argNum] = new StringBuilder();
+ ConstructComplexValue(arguments[1], argTypes[argNum], argValues[argNum]);
+ } else {
+ Parent.HandleProverError("Unexpected function argument: " + arguments);
+ throw new BadExprFromProver ();
+ }
+ }
+
+ void ConstructFunctionElements(SExpr element, List<SExpr> argTypes, SExpr outType, StringBuilder m) {
+ while (element.Name == "ite") {
+ StringBuilder[] argValues = new StringBuilder[argTypes.Count];
+ ConstructFunctionArguments(element[0], argTypes, argValues);
+ foreach (var s in argValues)
+ m.Append(s + " ");
+ m.Append("-> ");
+ ConstructComplexValue(element[1], outType, m);
+ m.Append("\n ");
+ if (element[2].Name != "ite")
+ m.Append("else -> ");
+ element = element[2];
+ }
+
+ ConstructComplexValue(element, outType, m);
+ }
+
+ void ConstructFunction(SExpr element, SExpr inType, SExpr outType, StringBuilder m) {
+ List<SExpr> argTypes = new List<SExpr>();
+
+ for (int i = 0; i < inType.ArgCount; ++i) {
+ if (inType[i].Name != "_ufmt_" + (i + 1) && inType[i].Name != "x!" + (i + 1) &&
+ !inType[i].Name.StartsWith("BOUND_VARIABLE_")) {
+ Parent.HandleProverError("Unexpected function argument: " + inType[i].Name);
+ throw new BadExprFromProver ();
+ }
+ argTypes.Add(inType[i][0]);
+ }
+
+ ConstructFunctionElements(element, argTypes, outType, m);
+ }
+
+ void ConstructDefine(SExpr element, StringBuilder m) {
+ Debug.Assert(element.Name == "define-fun");
+
+ if (element[1].ArgCount != 0)
+ TopLevelProcessed.Add(element);
+
+ m.Append(element[0] + " -> ");
+ if (TopLevelProcessed.Contains(element))
+ m.Append("{\n ");
+
+ if (element[1].ArgCount == 0 && element[2].Name == "Array" && !TopLevelProcessed.Contains(element)) {
+ ConstructComplexValue(element[3], element[2], m);
+ } else if (element[1].ArgCount == 0) {
+ ConstructSimpleValue(element[3], element[2], m);
+ } else {
+ ConstructFunction(element[3], element[1], element[2], m);
+ }
+
+ if (TopLevelProcessed.Contains(element))
+ m.Append("\n}");
+ m.Append("\n");
+ }
+
+ void ExtractDataType(SExpr datatypes) {
+ Debug.Assert(datatypes.Name == "declare-datatypes");
+
+ if (datatypes[0].Name != "" || datatypes[1].Name != "" || datatypes[1].ArgCount != 1) {
+ Parent.HandleProverError("Unexpected datatype: " + datatypes);
+ throw new BadExprFromProver ();
+ }
+
+ SMTDataType dt = new SMTDataType();
+ SExpr typeDef = datatypes[1][0];
+
+ if (typeDef.ArgCount != 1) {
+ Parent.HandleProverError("Unexpected datatype: " + datatypes);
+ throw new BadExprFromProver ();
+ }
+
+ dt.Constructor = typeDef[0].Name;
+ dt.Types = new List<SExpr>();
+
+ for (int i = 0; i < typeDef[0].ArgCount; ++i) {
+ if (typeDef[0][i].ArgCount != 1) {
+ Parent.HandleProverError("Unexpected datatype constructor: " + typeDef[0]);
+ throw new BadExprFromProver ();
+ }
+ dt.Types.Add(typeDef[0][i][0]);
+ }
+
+ DataTypes[typeDef.Name] = dt;
+ }
+
+ private void ConvertErrorModel(StringBuilder m) {
+ if (Parent.options.Solver == SolverKind.Z3) {
+ // Datatype declarations are not returned by Z3, so parse common
+ // instead. This is not very efficient, but currently not an issue,
+ // as this not the normal way of interfacing with Z3.
+ var ms = new MemoryStream(Encoding.ASCII.GetBytes(Parent.common.ToString()));
+ var sr = new StreamReader(ms);
+ SExpr.Parser p = new MyFileParser(sr, null);
+ var sexprs = p.ParseSExprs(false);
+ foreach (var e in sexprs) {
+ switch (e.Name) {
+ case "declare-datatypes":
+ ExtractDataType(e);
+ break;
+ }
+ }
+ }
+
+ while (ErrorModelTodo.Count > 0) {
+ var e = ErrorModelTodo[0];
+ ErrorModelTodo.RemoveAt(0);
+
+ switch (e.Name) {
+ case "define-fun":
+ ConstructDefine(e, m);
+ break;
+ case "declare-sort":
+ SortSet[e[0].Name] = System.Convert.ToInt32(e[1].Name);
+ break;
+ case "declare-datatypes":
+ ExtractDataType(e);
+ break;
+ case "declare-fun":
+ if (e[1].Name != "" || e[1].ArgCount > 0 || e[2].ArgCount > 0 ||
+ e[2].Name == "Bool" || e[2].Name == "Int") {
+ Parent.HandleProverError("Unexpected top level model element: " + e.Name);
+ throw new BadExprFromProver ();
+ }
+ Functions[e[0].Name] = e[2];
+ break;
+ case "forall":
+ // ignore
+ break;
+ default:
+ Parent.HandleProverError("Unexpected top level model element: " + e.Name);
+ throw new BadExprFromProver ();
+ }
+ }
+ }
+ }
+
+ private Model GetErrorModel() {
+ if (!options.ExpectingModel())
+ return null;
+
+ SendThisVC("(get-model)");
+ Process.Ping();
+ Model theModel = null;
+ while (true) {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+ if (theModel != null)
+ HandleProverError("Expecting only one model but got many");
+
+ string modelStr = null;
+ if (resp.Name == "model" && resp.ArgCount >= 1) {
+ var converter = new SMTErrorModelConverter(resp, this);
+ modelStr = converter.Convert();
+ }
+ else if (resp.ArgCount == 0 && resp.Name.Contains("->")) {
+ modelStr = resp.Name;
+ }
+ else {
+ HandleProverError("Unexpected prover response getting model: " + resp.ToString());
+ }
+
+ List<Model> models = null;
+ try {
+ switch (options.Solver) {
+ case SolverKind.Z3:
+ case SolverKind.CVC4:
+ models = Model.ParseModels(new StringReader("Error model: \n" + modelStr));
+ break;
+ default:
+ Debug.Assert(false);
+ return null;
+ }
+ }
+ catch (ArgumentException exn) {
+ HandleProverError("Model parsing error: " + exn.Message);
+ }
+ if (models == null)
+ HandleProverError("Could not parse any models");
+ else if (models.Count == 0)
+ HandleProverError("Could not parse any models");
+ else if (models.Count > 1)
+ HandleProverError("Expecting only one model but got many");
+ else
+ theModel = models[0];
+ }
+ return theModel;
+ }
+
+ private string[] GetLabelsInfo()
+ {
+ SendThisVC("(labels)");
+ Process.Ping();
+
+ string[] res = null;
+ while (true) {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+ if (res != null)
+ HandleProverError("Expecting only one sequence of labels but got many");
+ if (resp.Name == "labels" && resp.ArgCount >= 1) {
+ res = resp.Arguments.Select(a => a.Name.Replace("|", "")).ToArray();
+ }
+ else {
+ HandleProverError("Unexpected prover response getting labels: " + resp.ToString());
+ }
+ }
+ return res;
+ }
+
+ private Outcome GetResponse()
+ {
+ var result = Outcome.Undetermined;
+ var wasUnknown = false;
+
+ Process.Ping();
+
+ while (true) {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+
+ switch (resp.Name) {
+ case "unsat":
+ result = Outcome.Valid;
+ break;
+ case "sat":
+ result = Outcome.Invalid;
+ break;
+ case "unknown":
+ result = Outcome.Invalid;
+ wasUnknown = true;
+ break;
+ case "objectives":
+ // We ignore this.
+ break;
+ default:
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ break;
+ }
+ }
+
+ if (wasUnknown) {
+ SendThisVC("(get-info :reason-unknown)");
+ Process.Ping();
+ while (true) {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+
+ if (resp.ArgCount == 1 && resp.Name == ":reason-unknown") {
+ switch (resp[0].Name) {
+ case "memout":
+ currentErrorHandler.OnResourceExceeded("memory");
+ result = Outcome.OutOfMemory;
+ Process.NeedsRestart = true;
+ break;
+ case "timeout": case "canceled":
+ currentErrorHandler.OnResourceExceeded("timeout");
+ result = Outcome.TimeOut;
+ break;
+ default:
+ break;
+ }
+ } else {
+ HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString());
+ }
+ }
+
+ }
+
+ return result;
+ }
+
+ readonly IList<string> OptimizationRequests = new List<string>();
+
+ protected string VCExpr2String(VCExpr expr, int polarity)
+ {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ lock (gen)
+ {
+ DateTime start = DateTime.UtcNow;
+ //if (CommandLineOptions.Clo.Trace)
+ // Console.Write("Linearising ... ");
+
+ // handle the types in the VCExpr
+ TypeEraser eraser;
+ switch (CommandLineOptions.Clo.TypeEncodingMethod)
+ {
+ case CommandLineOptions.TypeEncoding.Arguments:
+ eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, gen);
+ break;
+ case CommandLineOptions.TypeEncoding.Monomorphic:
+ eraser = null;
+ break;
+ default:
+ eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen);
+ break;
+ }
+ VCExpr exprWithoutTypes = eraser == null ? expr : eraser.Erase(expr, polarity);
+ Contract.Assert(exprWithoutTypes != null);
+
+ LetBindingSorter letSorter = new LetBindingSorter(gen);
+ Contract.Assert(letSorter != null);
+ VCExpr sortedExpr = letSorter.Mutate(exprWithoutTypes, true);
+ Contract.Assert(sortedExpr != null);
+ VCExpr sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true);
+ Contract.Assert(sortedAxioms != null);
+
+ DeclCollector.Collect(sortedAxioms);
+ DeclCollector.Collect(sortedExpr);
+ FeedTypeDeclsToProver();
+
+ AddAxiom(SMTLibExprLineariser.ToString(sortedAxioms, Namer, options, namedAssumes: NamedAssumes));
+ string res = SMTLibExprLineariser.ToString(sortedExpr, Namer, options, NamedAssumes, OptimizationRequests);
+ Contract.Assert(res != null);
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ DateTime end = DateTime.UtcNow;
+ TimeSpan elapsed = end - start;
+ if (elapsed.TotalSeconds > 0.5)
+ Console.WriteLine("Linearising [{0} s]", elapsed.TotalSeconds);
+ }
+ return res;
+ }
+ }
+
+ // the list of all known axioms, where have to be included in each
+ // verification condition
+ private readonly List<string/*!>!*/> Axioms = new List<string/*!*/>();
+ private bool AxiomsAreSetup = false;
+
+
+
+
+ // similarly, a list of function/predicate declarations
+ private readonly List<string/*!>!*/> TypeDecls = new List<string/*!*/>();
+
+ protected void AddAxiom(string axiom)
+ {
+ Contract.Requires(axiom != null);
+ Axioms.Add(axiom);
+ // if (thmProver != null) {
+ // LogActivity(":assume " + axiom);
+ // thmProver.AddAxioms(axiom);
+ // }
+ }
+
+ protected void AddTypeDecl(string decl)
+ {
+ Contract.Requires(decl != null);
+ TypeDecls.Add(decl);
+ // if (thmProver != null) {
+ // LogActivity(decl);
+ // thmProver.Feed(decl, 0);
+ // }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private static string _backgroundPredicates;
+
+ static void InitializeGlobalInformation()
+ {
+ Contract.Ensures(_backgroundPredicates != null);
+ //throws ProverException, System.IO.FileNotFoundException;
+ if (_backgroundPredicates == null) {
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic)
+ {
+ _backgroundPredicates = "";
+ }
+ else
+ {
+ _backgroundPredicates = @"
+(set-info :category ""industrial"")
+(declare-sort |T@U| 0)
+(declare-sort |T@T| 0)
+(declare-fun real_pow (Real Real) Real)
+(declare-fun UOrdering2 (|T@U| |T@U|) Bool)
+(declare-fun UOrdering3 (|T@T| |T@U| |T@U|) Bool)";
+ }
+ }
+ }
+
+ public override VCExpressionGenerator VCExprGen
+ {
+ get { return this.gen; }
+ }
+
+ //// Push/pop interface
+
+ //List<string> pushedAssertions = new List<string>();
+ //int numRealPushes;
+ public override string VCExpressionToString(VCExpr vc)
+ {
+ return VCExpr2String(vc, 1);
+ }
+
+ public override void PushVCExpression(VCExpr vc)
+ {
+ throw new NotImplementedException();
+
+ }
+
+ public override void Pop()
+ {
+ SendThisVC("(pop 1)");
+ DeclCollector.Pop();
+ }
+
+ public override int NumAxiomsPushed()
+ {
+ throw new NotImplementedException();
+ //return numRealPushes + pushedAssertions.Count;
+ }
+
+ private void FlushPushedAssertions()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Assert(VCExpr vc, bool polarity, bool isSoft = false, int weight = 1)
+ {
+ OptimizationRequests.Clear();
+ string assert = "assert";
+ if (options.Solver == SolverKind.Z3 && isSoft) {
+ assert += "-soft";
+ }
+ var expr = polarity ? VCExpr2String(vc, 1) : "(not\n" + VCExpr2String(vc, 1) + "\n)";
+ if (options.Solver == SolverKind.Z3 && isSoft) {
+ expr += " :weight " + weight;
+ }
+ AssertAxioms();
+ SendThisVC("(" + assert + " " + expr + ")");
+ SendOptimizationRequests();
+ }
+
+ public override void DefineMacro(Macro f, VCExpr vc) {
+ DeclCollector.AddFunction(f);
+ string printedName = Namer.GetQuotedName(f, f.Name);
+ var argTypes = f.InParams.Cast<Variable>().MapConcat(p => DeclCollector.TypeToStringReg(p.TypedIdent.Type), " ");
+ string decl = "(define-fun " + printedName + " (" + argTypes + ") " + DeclCollector.TypeToStringReg(f.OutParams[0].TypedIdent.Type) + " " + VCExpr2String(vc, 1) + ")";
+ AssertAxioms();
+ SendThisVC(decl);
+ }
+
+ public override void AssertAxioms()
+ {
+ FlushAxioms();
+ }
+
+ public override void Check()
+ {
+ PrepareCommon();
+ SendCheckSat();
+ FlushLogFile();
+ }
+
+ public void SendCheckSat()
+ {
+ UsedNamedAssumes = null;
+ SendThisVC("(check-sat)");
+ }
+
+ public override void SetTimeOut(int ms)
+ {
+ if (options.Solver == SolverKind.Z3) {
+ var name = Z3.SetTimeoutOption();
+ var value = ms.ToString();
+ options.TimeLimit = ms;
+ options.SmtOptions.RemoveAll(ov => ov.Option == name);
+ options.AddSmtOption(name, value);
+ SendThisVC(string.Format("(set-option :{0} {1})", name, value));
+ }
+ }
+
+ public override object Evaluate(VCExpr expr)
+ {
+ string vcString = VCExpr2String(expr, 1);
+ SendThisVC("(get-value (" + vcString + "))");
+ var resp = Process.GetProverResponse();
+ if (resp == null) throw new VCExprEvaluationException();
+ if (!(resp.Name == "" && resp.ArgCount == 1)) throw new VCExprEvaluationException();
+ resp = resp.Arguments[0];
+ if (resp.Name == "")
+ {
+ // evaluating an expression
+ if (resp.ArgCount == 2)
+ resp = resp.Arguments[1];
+ else
+ throw new VCExprEvaluationException();
+ }
+ else
+ {
+ // evaluating a variable
+ if (resp.ArgCount == 1)
+ resp = resp.Arguments[0];
+ else
+ throw new VCExprEvaluationException();
+ }
+ if (resp.Name == "-" && resp.ArgCount == 1) // negative int
+ return Microsoft.Basetypes.BigNum.FromString("-" + resp.Arguments[0].Name);
+ if (resp.Name == "_" && resp.ArgCount == 2 && resp.Arguments[0].Name.StartsWith("bv")) // bitvector
+ return new BvConst(Microsoft.Basetypes.BigNum.FromString(resp.Arguments[0].Name.Substring("bv".Length)),
+ int.Parse(resp.Arguments[1].Name));
+ if (resp.ArgCount != 0)
+ throw new VCExprEvaluationException();
+ if (expr.Type.Equals(Boogie.Type.Bool))
+ return bool.Parse(resp.Name);
+ else if (expr.Type.Equals(Boogie.Type.Int))
+ return Microsoft.Basetypes.BigNum.FromString(resp.Name);
+ else
+ return resp.Name;
+ }
+
+ /// <summary>
+ /// Extra state for ApiChecker (used by stratifiedInlining)
+ /// </summary>
+ static int nameCounter = 0;
+
+ public override Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
+ {
+ unsatCore = new List<int>();
+
+ Push();
+ // Name the assumptions
+ var nameToAssumption = new Dictionary<string, int>();
+ int i = 0;
+ foreach (var vc in assumptions)
+ {
+ var name = "a" + nameCounter.ToString();
+ nameCounter++;
+ nameToAssumption.Add(name, i);
+
+ string vcString = VCExpr2String(vc, 1);
+ AssertAxioms();
+ SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name));
+ i++;
+ }
+ Check();
+
+ var outcome = CheckOutcomeCore(handler);
+
+ if (outcome != Outcome.Valid) {
+ Pop();
+ return outcome;
+ }
+
+ Contract.Assert(usingUnsatCore, "SMTLib prover not setup for computing unsat cores");
+ SendThisVC("(get-unsat-core)");
+ var resp = Process.GetProverResponse();
+ unsatCore = new List<int>();
+ if (resp.Name != "") unsatCore.Add(nameToAssumption[resp.Name]);
+ foreach (var s in resp.Arguments) unsatCore.Add(nameToAssumption[s.Name]);
+
+ FlushLogFile();
+ Pop();
+ return outcome;
+ }
+
+ public override void Push()
+ {
+ SendThisVC("(push 1)");
+ DeclCollector.Push();
+ }
+
+ public override Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) {
+ unsatisfiedSoftAssumptions = new List<int>();
+
+ // First, convert both hard and soft assumptions to SMTLIB strings
+ List<string> hardAssumptionStrings = new List<string>();
+ foreach (var a in hardAssumptions) {
+ hardAssumptionStrings.Add(VCExpr2String(a, 1));
+ }
+ List<string> currAssumptionStrings = new List<string>();
+ foreach (var a in softAssumptions) {
+ currAssumptionStrings.Add(VCExpr2String(a, 1));
+ }
+
+ Push();
+ AssertAxioms();
+ foreach (var a in hardAssumptionStrings) {
+ SendThisVC("(assert " + a + ")");
+ }
+ Check();
+ Outcome outcome = GetResponse();
+ if (outcome != Outcome.Invalid) {
+ Pop();
+ return outcome;
+ }
+
+ int k = 0;
+ List<string> relaxVars = new List<string>();
+ while (true) {
+ Push();
+ foreach (var a in currAssumptionStrings) {
+ SendThisVC("(assert " + a + ")");
+ }
+ Check();
+ outcome = CheckOutcomeCore(handler);
+ if (outcome != Outcome.Valid)
+ break;
+ Pop();
+ string relaxVar = "relax_" + k;
+ relaxVars.Add(relaxVar);
+ SendThisVC("(declare-fun " + relaxVar + " () Int)");
+ List<string> nextAssumptionStrings = new List<string>();
+ for (int i = 0; i < currAssumptionStrings.Count; i++) {
+ string constraint = "(= " + relaxVar + " " + i + ")";
+ nextAssumptionStrings.Add("(or " + currAssumptionStrings[i] + " " + constraint + ")");
+ }
+ currAssumptionStrings = nextAssumptionStrings;
+ k++;
+ }
+
+ if (outcome == Outcome.Invalid) {
+ foreach (var relaxVar in relaxVars) {
+ SendThisVC("(get-value (" + relaxVar + "))");
+ FlushLogFile();
+ var resp = Process.GetProverResponse();
+ if (resp == null) break;
+ if (!(resp.Name == "" && resp.ArgCount == 1)) break;
+ resp = resp.Arguments[0];
+ if (!(resp.Name != "" && resp.ArgCount == 1)) break;
+ resp = resp.Arguments[0];
+ if (resp.ArgCount != 0)
+ break;
+ int v;
+ if (int.TryParse(resp.Name, out v))
+ unsatisfiedSoftAssumptions.Add(v);
+ else
+ break;
+ }
+ Pop();
+ }
+
+ Pop();
+ return outcome;
+ }
+ }
+
+ public class SMTLibInterpolatingProcessTheoremProver : SMTLibProcessTheoremProver
+ {
+ public SMTLibInterpolatingProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
+ SMTLibProverContext ctx)
+ : base(AddInterpOption(options), gen, ctx)
+ {
+
+ }
+
+ private static ProverOptions AddInterpOption(ProverOptions options)
+ {
+ var opts = (SMTLibProverOptions)options;
+ opts.AddSmtOption("produce-interpolants", "true");
+ if (CommandLineOptions.Clo.PrintFixedPoint == null)
+ CommandLineOptions.Clo.PrintFixedPoint = "itp.fixedpoint.bpl";
+ return opts;
+ }
+
+ public override VCExpr ComputeInterpolant(VCExpr A, VCExpr B)
+ {
+ string A_str = VCExpr2String(A, 1);
+ string B_str = VCExpr2String(B, 1);
+
+ AssertAxioms();
+ SendThisVC("(compute-interpolant " + A_str + " " + B_str + ")");
+
+ SExpr interpolant;
+ Outcome result = GetInterpolantResponse(out interpolant);
+
+ if (result != Outcome.Valid)
+ return null;
+
+ VCExpr interpolantVC = SExprToVCExpr(interpolant, new Dictionary<string, VCExpr>());
+ return interpolantVC;
+ }
+
+ private Outcome GetInterpolantResponse(out SExpr interpolant)
+ {
+ var result = Outcome.Undetermined;
+ var wasUnknown = false;
+ interpolant = null;
+
+ Process.Ping();
+ bool onlyOnce = false;
+
+ while (true)
+ {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+
+ switch (resp.Name)
+ {
+ case "unsat":
+ result = Outcome.Valid;
+ break;
+ case "sat":
+ result = Outcome.Invalid;
+ break;
+ case "unknown":
+ result = Outcome.Invalid;
+ wasUnknown = true;
+ break;
+ default:
+ if (result == Outcome.Valid)
+ {
+ interpolant = resp as SExpr;
+
+ Contract.Assert(onlyOnce == false);
+ onlyOnce = true;
+ continue;
+ }
+ HandleProverError("Unexpected prover response: " + resp.ToString());
+ break;
+ }
+ }
+
+ if (wasUnknown)
+ {
+ SendThisVC("(get-info :reason-unknown)");
+ Process.Ping();
+
+ while (true)
+ {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+
+ if (resp.ArgCount == 1 && resp.Name == ":reason-unknown")
+ {
+ switch (resp[0].Name)
+ {
+ case "memout":
+ currentErrorHandler.OnResourceExceeded("memory");
+ result = Outcome.OutOfMemory;
+ Process.NeedsRestart = true;
+ break;
+ case "timeout":
+ case "canceled":
+ currentErrorHandler.OnResourceExceeded("timeout");
+ result = Outcome.TimeOut;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString());
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public override List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves)
+ {
+ List<VCExpr> result = new List<VCExpr>();
+
+ string vcStr = "true";
+ foreach (string str in root)
+ vcStr = vcStr + " " + str;
+ foreach (string str in leaves)
+ vcStr = vcStr + "\r\n (interp " + str + ")";
+
+ vcStr = "(get-interpolant (and\r\n" + vcStr + "\r\n))";
+ SendThisVC(vcStr);
+ if(currentLogFile != null) currentLogFile.Flush();
+
+ List<SExpr> interpolantList;
+ GetTreeInterpolantResponse(out interpolantList);
+
+ Dictionary<string, VCExpr> bound = new Dictionary<string, VCExpr>();
+ foreach (SExpr sexpr in interpolantList)
+ {
+ VCExpr interpolantVC = SExprToVCExpr(sexpr, bound);
+ result.Add(interpolantVC);
+ }
+
+ return result;
+ }
+
+ private void GetTreeInterpolantResponse(out List<SExpr> interpolantList)
+ {
+ interpolantList = new List<SExpr>();
+
+ Process.Ping();
+
+ while (true)
+ {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
+ break;
+
+ SExpr interpolant = resp as SExpr;
+ if(interpolant == null)
+ HandleProverError("Unexpected prover response: got null for interpolant!");
+ interpolantList.Add(interpolant);
+ }
+ }
+ }
+
+ public class SMTLibProverContext : DeclFreeProverContext
+ {
+ internal SMTLibProcessTheoremProver parent;
+
+ public readonly Dictionary<CtorType, List<Function>> KnownDatatypeConstructors = new Dictionary<CtorType, List<Function>>();
+
+ public SMTLibProverContext(VCExpressionGenerator gen,
+ VCGenerationOptions genOptions)
+ : base(gen, genOptions)
+ {
+ }
+
+ protected SMTLibProverContext(SMTLibProverContext par)
+ : base(par)
+ {
+ }
+
+ public override object Clone()
+ {
+ return new SMTLibProverContext(this);
+ }
+
+ public override string Lookup(VCExprVar var)
+ {
+ VCExprVar v = parent.AxBuilder.TryTyped2Untyped(var);
+ if (v != null) {
+ var = v;
+ }
+ return parent.Namer.Lookup(var);
+ }
+
+ public override void DeclareFunction(Function f, string attributes) {
+ if (f is DatatypeConstructor) {
+ CtorType datatype = (CtorType) f.OutParams[0].TypedIdent.Type;
+ if (!KnownDatatypeConstructors.ContainsKey(datatype))
+ KnownDatatypeConstructors[datatype] = new List<Function>();
+ KnownDatatypeConstructors[datatype].Add(f);
+ }
+ base.DeclareFunction(f, attributes);
+ }
+ }
+
+ public class Factory : ProverFactory
+ {
+ // Set programmatically
+ public static bool UseInterpolation = false;
+
+ public override object SpawnProver(ProverOptions options, object ctxt)
+ {
+ //Contract.Requires(ctxt != null);
+ //Contract.Requires(options != null);
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ return this.SpawnProver(options,
+ cce.NonNull((SMTLibProverContext)ctxt).ExprGen,
+ cce.NonNull((SMTLibProverContext)ctxt));
+ }
+
+ public override object NewProverContext(ProverOptions options)
+ {
+ //Contract.Requires(options != null);
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ VCExpressionGenerator gen = new VCExpressionGenerator();
+ List<string>/*!>!*/ proverCommands = new List<string/*!*/>();
+ proverCommands.Add("smtlib");
+ var opts = (SMTLibProverOptions)options ;
+ if (opts.Solver == SolverKind.Z3)
+ proverCommands.Add("z3");
+ else
+ proverCommands.Add("external");
+ VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands);
+ return new SMTLibProverContext(gen, genOptions);
+ }
+
+ public override ProverOptions BlankProverOptions()
+ {
+ return new SMTLibProverOptions();
+ }
+
+ protected virtual SMTLibProcessTheoremProver SpawnProver(ProverOptions options,
+ VCExpressionGenerator gen,
+ SMTLibProverContext ctx)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(ctx != null);
+ Contract.Ensures(Contract.Result<SMTLibProcessTheoremProver>() != null);
+
+ if (UseInterpolation)
+ return new SMTLibInterpolatingProcessTheoremProver(options, gen, ctx);
+
+ return new SMTLibProcessTheoremProver(options, gen, ctx);
+ }
+
+ public override bool SupportsLabels(ProverOptions options)
+ {
+ return ((SMTLibProverOptions)options).SupportsLabels;
+ }
+ }
+}
diff --git a/Source/Provers/SMTLib/SExpr.cs b/Source/Provers/SMTLib/SExpr.cs
index ac681b8a..3e9687e1 100644
--- a/Source/Provers/SMTLib/SExpr.cs
+++ b/Source/Provers/SMTLib/SExpr.cs
@@ -1,263 +1,263 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.Globalization;
-
-namespace Microsoft.Boogie
-{
- public class SExpr
- {
- static readonly SExpr[] EmptyArgs = new SExpr[0];
- public readonly string Name;
- public SExpr[] Arguments
- {
- get
- {
- Contract.Ensures(Contract.Result<SExpr[]>() != null);
- Contract.Ensures(Contract.ForAll(Contract.Result<SExpr[]>(), expr => expr != null));
-
- return this.arguments;
- }
- }
-
- public SExpr this[int idx]
- {
- get
- {
- return Arguments[idx];
- }
- }
-
- public int ArgCount
- {
- get { return arguments.Length; }
- }
-
- public bool IsId
- {
- get { return Arguments.Length == 0; }
- }
-
- private readonly SExpr[] arguments;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(this.Name != null);
- Contract.Invariant(this.arguments != null);
- Contract.Invariant(Contract.ForAll(this.arguments, arg => arg != null));
- }
-
- public SExpr(string name, params SExpr[] args)
- : this(name, (IEnumerable<SExpr>)args)
- {
- Contract.Requires(name != null);
- Contract.Requires(args != null);
- Contract.Requires(Contract.ForAll(args, x => x != null));
- }
-
- public SExpr(string name, IEnumerable<SExpr> args)
- {
- Contract.Requires(name != null);
- Contract.Requires(args != null);
- // We don't want to evaluate args twice!
- // Contract.Requires(Contract.ForAll(args, x => x != null));
- Name = name;
- arguments = args.ToArray();
- }
-
- public SExpr(string name)
- : this(name, EmptyArgs)
- {
- Contract.Requires(name != null);
- }
-
- #region pretty-printing
- void WriteTo(StringBuilder sb)
- {
- Contract.Requires(sb != null);
-
- if (Arguments.Length > 0) sb.Append('(');
- if (Name.Any(Char.IsWhiteSpace))
- sb.Append("\"").Append(Name).Append("\"");
- else if (Name.Length == 0)
- sb.Append("()");
- else
- sb.Append(Name);
- foreach (var a in Arguments) {
- sb.Append(' ');
- a.WriteTo(sb);
- }
- if (Arguments.Length > 0) sb.Append(')');
- }
-
- public override string ToString()
- {
- var sb = new StringBuilder();
- this.WriteTo(sb);
- return sb.ToString();
- }
- #endregion
-
- #region parsing
-
- public abstract class Parser
- {
- System.IO.StreamReader sr;
- int linePos = 0;
- string currLine = null;
-
- public Parser(System.IO.StreamReader _sr)
- {
- sr = _sr;
- }
- string Read()
- {
- return sr.ReadLine();
- }
- char SkipWs()
- {
- while (true)
- {
- if (currLine == null)
- {
- currLine = Read();
- if (currLine == null)
- return '\0';
- }
-
- while (linePos < currLine.Length && char.IsWhiteSpace(currLine[linePos]))
- linePos++;
-
- if (linePos < currLine.Length)
- return currLine[linePos];
- else
- {
- currLine = null;
- linePos = 0;
- }
- }
- }
-
- void Shift()
- {
- linePos++;
- }
-
- string ParseId()
- {
- var sb = new StringBuilder();
-
- var beg = SkipWs();
-
- var quoted = beg == '"' || beg == '|';
- if (quoted)
- Shift();
- while (true)
- {
- if (linePos >= currLine.Length)
- {
- if (quoted)
- {
- sb.Append("\n");
- currLine = Read();
- linePos = 0;
- if (currLine == null)
- break;
- }
- else break;
- }
-
- var c = currLine[linePos++];
- if (quoted && c == beg)
- break;
- if (!quoted && (char.IsWhiteSpace(c) || c == '(' || c == ')'))
- {
- linePos--;
- break;
- }
- if (quoted && c == '\\' && linePos < currLine.Length && currLine[linePos] == '"')
- {
- sb.Append('"');
- linePos++;
- continue;
- }
- sb.Append(c);
- }
-
- return sb.ToString();
- }
-
- public abstract void ParseError(string msg);
-
- public IEnumerable<SExpr> ParseSExprs(bool top)
- {
- while (true)
- {
- var c = SkipWs();
- if (c == '\0')
- break;
-
- if (c == ')')
- {
- if (top)
- ParseError("stray ')'");
- break;
- }
-
- string id;
-
- if (c == '(')
- {
- Shift();
- c = SkipWs();
- if (c == '\0')
- {
- ParseError("expecting something after '('");
- break;
- }
- else if (c == '(')
- {
- id = "";
- }
- else
- {
- id = ParseId();
- }
-
- var args = ParseSExprs(false).ToArray();
-
- c = SkipWs();
- if (c == ')')
- {
- Shift();
- }
- else
- {
- ParseError("unclosed '(" + id + "'");
- }
- yield return new SExpr(id, args);
- }
- else
- {
- id = ParseId();
- yield return new SExpr(id);
- }
-
- if (top) break;
- }
- }
- }
- #endregion
- }
-}
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Text;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+
+namespace Microsoft.Boogie
+{
+ public class SExpr
+ {
+ static readonly SExpr[] EmptyArgs = new SExpr[0];
+ public readonly string Name;
+ public SExpr[] Arguments
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<SExpr[]>() != null);
+ Contract.Ensures(Contract.ForAll(Contract.Result<SExpr[]>(), expr => expr != null));
+
+ return this.arguments;
+ }
+ }
+
+ public SExpr this[int idx]
+ {
+ get
+ {
+ return Arguments[idx];
+ }
+ }
+
+ public int ArgCount
+ {
+ get { return arguments.Length; }
+ }
+
+ public bool IsId
+ {
+ get { return Arguments.Length == 0; }
+ }
+
+ private readonly SExpr[] arguments;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(this.Name != null);
+ Contract.Invariant(this.arguments != null);
+ Contract.Invariant(Contract.ForAll(this.arguments, arg => arg != null));
+ }
+
+ public SExpr(string name, params SExpr[] args)
+ : this(name, (IEnumerable<SExpr>)args)
+ {
+ Contract.Requires(name != null);
+ Contract.Requires(args != null);
+ Contract.Requires(Contract.ForAll(args, x => x != null));
+ }
+
+ public SExpr(string name, IEnumerable<SExpr> args)
+ {
+ Contract.Requires(name != null);
+ Contract.Requires(args != null);
+ // We don't want to evaluate args twice!
+ // Contract.Requires(Contract.ForAll(args, x => x != null));
+ Name = name;
+ arguments = args.ToArray();
+ }
+
+ public SExpr(string name)
+ : this(name, EmptyArgs)
+ {
+ Contract.Requires(name != null);
+ }
+
+ #region pretty-printing
+ void WriteTo(StringBuilder sb)
+ {
+ Contract.Requires(sb != null);
+
+ if (Arguments.Length > 0) sb.Append('(');
+ if (Name.Any(Char.IsWhiteSpace))
+ sb.Append("\"").Append(Name).Append("\"");
+ else if (Name.Length == 0)
+ sb.Append("()");
+ else
+ sb.Append(Name);
+ foreach (var a in Arguments) {
+ sb.Append(' ');
+ a.WriteTo(sb);
+ }
+ if (Arguments.Length > 0) sb.Append(')');
+ }
+
+ public override string ToString()
+ {
+ var sb = new StringBuilder();
+ this.WriteTo(sb);
+ return sb.ToString();
+ }
+ #endregion
+
+ #region parsing
+
+ public abstract class Parser
+ {
+ System.IO.StreamReader sr;
+ int linePos = 0;
+ string currLine = null;
+
+ public Parser(System.IO.StreamReader _sr)
+ {
+ sr = _sr;
+ }
+ string Read()
+ {
+ return sr.ReadLine();
+ }
+ char SkipWs()
+ {
+ while (true)
+ {
+ if (currLine == null)
+ {
+ currLine = Read();
+ if (currLine == null)
+ return '\0';
+ }
+
+ while (linePos < currLine.Length && char.IsWhiteSpace(currLine[linePos]))
+ linePos++;
+
+ if (linePos < currLine.Length)
+ return currLine[linePos];
+ else
+ {
+ currLine = null;
+ linePos = 0;
+ }
+ }
+ }
+
+ void Shift()
+ {
+ linePos++;
+ }
+
+ string ParseId()
+ {
+ var sb = new StringBuilder();
+
+ var beg = SkipWs();
+
+ var quoted = beg == '"' || beg == '|';
+ if (quoted)
+ Shift();
+ while (true)
+ {
+ if (linePos >= currLine.Length)
+ {
+ if (quoted)
+ {
+ sb.Append("\n");
+ currLine = Read();
+ linePos = 0;
+ if (currLine == null)
+ break;
+ }
+ else break;
+ }
+
+ var c = currLine[linePos++];
+ if (quoted && c == beg)
+ break;
+ if (!quoted && (char.IsWhiteSpace(c) || c == '(' || c == ')'))
+ {
+ linePos--;
+ break;
+ }
+ if (quoted && c == '\\' && linePos < currLine.Length && currLine[linePos] == '"')
+ {
+ sb.Append('"');
+ linePos++;
+ continue;
+ }
+ sb.Append(c);
+ }
+
+ return sb.ToString();
+ }
+
+ public abstract void ParseError(string msg);
+
+ public IEnumerable<SExpr> ParseSExprs(bool top)
+ {
+ while (true)
+ {
+ var c = SkipWs();
+ if (c == '\0')
+ break;
+
+ if (c == ')')
+ {
+ if (top)
+ ParseError("stray ')'");
+ break;
+ }
+
+ string id;
+
+ if (c == '(')
+ {
+ Shift();
+ c = SkipWs();
+ if (c == '\0')
+ {
+ ParseError("expecting something after '('");
+ break;
+ }
+ else if (c == '(')
+ {
+ id = "";
+ }
+ else
+ {
+ id = ParseId();
+ }
+
+ var args = ParseSExprs(false).ToArray();
+
+ c = SkipWs();
+ if (c == ')')
+ {
+ Shift();
+ }
+ else
+ {
+ ParseError("unclosed '(" + id + "'");
+ }
+ yield return new SExpr(id, args);
+ }
+ else
+ {
+ id = ParseId();
+ yield return new SExpr(id);
+ }
+
+ if (top) break;
+ }
+ }
+ }
+ #endregion
+ }
+}
+
diff --git a/Source/Provers/SMTLib/SMTLib.csproj b/Source/Provers/SMTLib/SMTLib.csproj
index 5e80f4c1..00febc0a 100644
--- a/Source/Provers/SMTLib/SMTLib.csproj
+++ b/Source/Provers/SMTLib/SMTLib.csproj
@@ -1,237 +1,237 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.SMTLib</RootNamespace>
- <AssemblyName>Provers.SMTLib</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for SMTLib.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.SMTLib.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Inspector.cs" />
- <Compile Include="SMTLibProverOptions.cs" />
- <Compile Include="ProverInterface.cs" />
- <Compile Include="SExpr.cs" />
- <Compile Include="SMTLibLineariser.cs" />
- <Compile Include="SMTLibNamer.cs" />
- <Compile Include="SMTLibProcess.cs" />
- <Compile Include="TypeDeclCollector.cs" />
- <Compile Include="..\..\version.cs" />
- <Compile Include="Z3.cs" />
- <Compile Include="CVC4.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie.SMTLib</RootNamespace>
+ <AssemblyName>Provers.SMTLib</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for SMTLib.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Provers.SMTLib.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Inspector.cs" />
+ <Compile Include="SMTLibProverOptions.cs" />
+ <Compile Include="ProverInterface.cs" />
+ <Compile Include="SExpr.cs" />
+ <Compile Include="SMTLibLineariser.cs" />
+ <Compile Include="SMTLibNamer.cs" />
+ <Compile Include="SMTLibProcess.cs" />
+ <Compile Include="TypeDeclCollector.cs" />
+ <Compile Include="..\..\version.cs" />
+ <Compile Include="Z3.cs" />
+ <Compile Include="CVC4.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Model\Model.csproj">
+ <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs
index 96d5b290..99dd849d 100644
--- a/Source/Provers/SMTLib/SMTLibLineariser.cs
+++ b/Source/Provers/SMTLib/SMTLibLineariser.cs
@@ -1,930 +1,955 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Method to turn VCExprs into strings that can be fed into SMT
-// solvers. This is currently quite similar to the
-// SimplifyLikeLineariser (but the code is independent)
-
-namespace Microsoft.Boogie.SMTLib
-{
-
- // Options for the linearisation
- public class LineariserOptions
- {
- public static LineariserOptions Default = new LineariserOptions();
- public bool LabelsBelowQuantifiers = false;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for expressions. The result (bool) is currently not used for anything
- public class SMTLibExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/>
- {
-
- public static string ToString(VCExpr e, UniqueNamer namer, SMTLibProverOptions opts)
- {
- Contract.Requires(e != null);
- Contract.Requires(namer != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- StringWriter sw = new StringWriter();
- SMTLibExprLineariser lin = new SMTLibExprLineariser(sw, namer, opts);
- Contract.Assert(lin != null);
- lin.Linearise(e, LineariserOptions.Default);
- return cce.NonNull(sw.ToString());
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- private readonly TextWriter wr;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(wr != null);
- Contract.Invariant(Namer != null);
- }
-
- private SMTLibOpLineariser OpLinObject = null;
- private IVCExprOpVisitor<bool, LineariserOptions>/*!>!*/ OpLineariser
- {
- get
- {
- Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
-
- if (OpLinObject == null)
- OpLinObject = new SMTLibOpLineariser(this, wr);
- return OpLinObject;
- }
- }
-
- internal readonly UniqueNamer Namer;
- internal int UnderQuantifier = 0;
- internal readonly SMTLibProverOptions ProverOptions;
-
- public SMTLibExprLineariser(TextWriter wr, UniqueNamer namer, SMTLibProverOptions opts)
- {
- Contract.Requires(wr != null); Contract.Requires(namer != null);
- this.wr = wr;
- this.Namer = namer;
- this.ProverOptions = opts;
- }
-
- public void Linearise(VCExpr expr, LineariserOptions options)
- {
- Contract.Requires(expr != null);
- Contract.Requires(options != null);
- expr.Accept<bool, LineariserOptions>(this, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- private static void TypeToStringHelper(Type t, StringBuilder sb)
- {
- Contract.Requires(t != null);
-
- TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
- if (syn != null) {
- TypeToStringHelper(syn.ExpandedType, sb);
- } else {
- if (t.IsMap && CommandLineOptions.Clo.UseArrayTheory) {
- MapType m = t.AsMap;
- // Contract.Assert(m.MapArity == 1);
- sb.Append("(Array ");
- foreach (Type tp in m.Arguments)
- sb.Append(TypeToString(tp)).Append(" ");
- sb.Append(TypeToString(m.Result)).Append(")");
- } else if (t.IsMap) {
- MapType m = t.AsMap;
- sb.Append('[');
- for (int i = 0; i < m.MapArity; ++i) {
- if (i != 0)
- sb.Append(',');
- TypeToStringHelper(m.Arguments[i], sb);
- }
- sb.Append(']');
- TypeToStringHelper(m.Result, sb);
- } else if (t.IsBool || t.IsInt || t.IsReal || t.IsFloat || t.IsBv) {
- sb.Append(TypeToString(t));
- } else {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/false, /*pretty=*/false)) {
- t.Emit(stream);
- }
- sb.Append(buffer.ToString());
- }
- }
-
- }
-
- public static string TypeToString(Type t)
- {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- if (t.IsBool)
- return "Bool";
- else if (t.IsInt)
- return "Int";
- else if (t.IsReal)
- return "Real";
- else if (t.IsFloat)
- return "(_ FloatingPoint " + t.FloatExponent + " " + t.FloatMantissa + ")";
- else if (t.IsBv) {
- return "(_ BitVec " + t.BvBits + ")";
- } else {
- StringBuilder sb = new StringBuilder();
- TypeToStringHelper(t, sb);
- var s = sb.ToString();
- if (s[0] == '(')
- return s;
- else
- return SMTLibNamer.QuoteId("T@" + s);
- }
- }
-
- public static string ExtractBuiltin(Function f)
- {
- Contract.Requires(f != null);
- string retVal = null;
- retVal = f.FindStringAttribute("bvbuiltin");
-
- // It used to be "sign_extend 12" in Simplify, and is "(_ sign_extend 12)" with SMT
- if (retVal != null && (retVal.StartsWith("sign_extend ") || retVal.StartsWith("zero_extend ")))
- return "(_ " + retVal + ")";
-
- if (retVal == null) {
- retVal = f.FindStringAttribute("builtin");
- }
-
- if (retVal != null && !CommandLineOptions.Clo.UseArrayTheory && SMTLibOpLineariser.ArrayOps.Contains(retVal))
- {
- retVal = null;
- }
-
- return retVal;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLiteral node, LineariserOptions options)
- {
- if (node == VCExpressionGenerator.True)
- wr.Write("true");
- else if (node == VCExpressionGenerator.False)
- wr.Write("false");
- else if (node is VCExprIntLit) {
- BigNum lit = ((VCExprIntLit)node).Val;
- if (lit.IsNegative)
- // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
- wr.Write("(- 0 {0})", lit.Abs);
- else
- wr.Write(lit);
- }
- else if (node is VCExprRealLit) {
- BigDec lit = ((VCExprRealLit)node).Val;
- if (lit.IsNegative)
- // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
- wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString());
- else
- wr.Write(lit.ToDecimalString());
- }
- else if (node is VCExprFloatLit)
- {
- BigFloat lit = ((VCExprFloatLit)node).Val;
- wr.Write("(" + lit.ToBVString() + ")");
- }
- else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprNAry node, LineariserOptions options)
- {
- VCExprOp op = node.Op;
- Contract.Assert(op != null);
-
- var booleanOps = new HashSet<VCExprOp>();
- booleanOps.Add(VCExpressionGenerator.NotOp);
- booleanOps.Add(VCExpressionGenerator.ImpliesOp);
- booleanOps.Add(VCExpressionGenerator.AndOp);
- booleanOps.Add(VCExpressionGenerator.OrOp);
- if (booleanOps.Contains(op))
- {
- Stack<VCExpr> exprs = new Stack<VCExpr>();
- exprs.Push(node);
- while (exprs.Count > 0)
- {
- VCExpr expr = exprs.Pop();
- if (expr == null)
- {
- wr.Write(")");
- continue;
- }
- wr.Write(" ");
- VCExprNAry naryExpr = expr as VCExprNAry;
- if (naryExpr == null || !booleanOps.Contains(naryExpr.Op))
- {
- Linearise(expr, options);
- continue;
- }
- else if (naryExpr.Op.Equals(VCExpressionGenerator.NotOp))
- {
- wr.Write("(not");
- }
- else if (naryExpr.Op.Equals(VCExpressionGenerator.ImpliesOp))
- {
- wr.Write("(=>");
- }
- else if (naryExpr.Op.Equals(VCExpressionGenerator.AndOp))
- {
- wr.Write("(and");
- }
- else
- {
- System.Diagnostics.Debug.Assert(naryExpr.Op.Equals(VCExpressionGenerator.OrOp));
- wr.Write("(or");
- }
- exprs.Push(null);
- for (int i = naryExpr.Arity - 1; i >= 0; i--)
- {
- exprs.Push(naryExpr[i]);
- }
- }
- return true;
- }
- return node.Accept<bool, LineariserOptions/*!*/>(OpLineariser, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprVar node, LineariserOptions options)
- {
- wr.Write(Namer.GetQuotedName(node, node.Name));
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprQuantifier node, LineariserOptions options)
- {
- Contract.Assert(node.TypeParameters.Count == 0);
-
- UnderQuantifier++;
- Namer.PushScope(); try {
-
- string kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
- wr.Write("({0} (", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++) {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var != null);
- string printedName = Namer.GetQuotedLocalName(var, var.Name);
- Contract.Assert(printedName != null);
- wr.Write("({0} {1}) ", printedName, TypeToString(var.Type));
- }
-
- wr.Write(") ");
-
- VCQuantifierInfos infos = node.Infos;
- var weight = QKeyValue.FindIntAttribute(infos.attributes, "weight", 1);
- if (!ProverOptions.UseWeights)
- weight = 1;
- var hasAttrs = node.Triggers.Count > 0 || infos.qid != null || weight != 1 || infos.uniqueId != -1;
-
- if (hasAttrs)
- wr.Write("(! ");
-
- Linearise(node.Body, options);
-
- if (hasAttrs) {
- wr.Write("\n");
- if (infos.qid != null)
- wr.Write(" :qid {0}\n", SMTLibNamer.QuoteId(infos.qid));
- if (weight != 1)
- wr.Write(" :weight {0}\n", weight);
- if (infos.uniqueId != -1)
- wr.Write(" :skolemid |{0}|\n", infos.uniqueId);
- WriteTriggers(node.Triggers, options);
-
- wr.Write(")");
- }
-
- wr.Write(")");
-
- return true;
-
- } finally {
- UnderQuantifier--;
- Namer.PopScope();
- }
- }
-
- private void WriteTriggers(List<VCTrigger/*!>!*/> triggers, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(triggers != null);
- // first, count how many neg/pos triggers there are
- int negTriggers = 0;
- int posTriggers = 0;
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- posTriggers++;
- } else {
- negTriggers++;
- }
- }
-
- if (posTriggers > 0) {
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- wr.Write(" :pattern (");
- foreach (VCExpr e in vcTrig.Exprs) {
- Contract.Assert(e != null);
- wr.Write(" ");
- var subPat = e;
- var nary = e as VCExprNAry;
- if (nary != null && (nary.Op == VCExpressionGenerator.NeqOp || nary.Op == VCExpressionGenerator.EqOp)) {
- if (nary[0] is VCExprLiteral)
- subPat = nary[1];
- else if (nary[1] is VCExprLiteral)
- subPat = nary[0];
- }
- Linearise(subPat, options);
- }
- wr.Write(")\n");
- }
- }
- } else if (negTriggers > 0) {
- // if also positive triggers are given, the SMT solver (at least Z3)
- // will ignore the negative patterns and output a warning. Therefore
- // we never specify both negative and positive triggers
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (!vcTrig.Pos) {
- wr.Write(" :no-pattern ");
- Contract.Assert(vcTrig.Exprs.Count == 1);
- Linearise(vcTrig.Exprs[0], options);
- wr.Write("\n");
- }
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLet node, LineariserOptions options)
- {
- Namer.PushScope();
- try {
-
- foreach (VCExprLetBinding b in node) {
- wr.Write("(let (");
- Contract.Assert(b != null);
- wr.Write("({0} ", Namer.GetQuotedName(b.V, b.V.Name));
- Linearise(b.E, options);
- wr.Write("))\n");
- }
- Linearise(node.Body, options);
- foreach (VCExprLetBinding b in node)
- wr.Write(")");
- return true;
- } finally {
- Namer.PopScope();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for operator terms. The result (bool) is currently not used for anything
- internal class SMTLibOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/>
- {
- private readonly SMTLibExprLineariser ExprLineariser;
- private readonly TextWriter wr;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(wr != null);
- Contract.Invariant(ExprLineariser != null);
- }
-
-
- public SMTLibOpLineariser(SMTLibExprLineariser ExprLineariser, TextWriter wr)
- {
- Contract.Requires(ExprLineariser != null);
- Contract.Requires(wr != null);
- this.ExprLineariser = ExprLineariser;
- this.wr = wr;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
- private void WriteApplication(string opName, IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options)
- {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(options != null);
- Contract.Assert(opName != null);
-
- bool hasArgs = false;
- foreach (VCExpr e in args) {
- Contract.Assert(e != null);
- if (!hasArgs)
- wr.Write("({0}", opName);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options);
- hasArgs = true;
- }
-
- if (hasArgs)
- wr.Write(")");
- else
- wr.Write("{0}", opName);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public bool VisitNotOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("not", node, options); // arguments can be both terms and formulas
- return true;
- }
-
- private bool PrintEq(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(node != null);
- Contract.Requires(options != null);
-
- WriteApplication("=", node, options);
-
- return true;
- }
-
- public bool VisitEqOp(VCExprNAry node, LineariserOptions options)
- {
- return PrintEq(node, options);
- }
-
- public bool VisitNeqOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- wr.Write("(not ");
- PrintEq(node, options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitAndOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("and", node, options);
- return true;
- }
-
- public bool VisitOrOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("or", node, options);
- return true;
- }
-
- public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("=>", node, options);
- return true;
- }
-
- public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("ite", node, options);
- return true;
- }
-
- public bool VisitCustomOp(VCExprNAry node, LineariserOptions options)
- {
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- if (!ExprLineariser.ProverOptions.UseTickleBool && op.Name == "tickleBool")
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- else
- WriteApplication(op.Name, node, options);
- return true;
- }
-
- public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- if (node.Length < 2) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- var groupings = node.GroupBy(e => e.Type).Where(g => g.Count() > 1).ToArray();
- if (groupings.Length == 0) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- if (groupings.Length > 1)
- wr.Write("(and ");
-
- foreach (var g in groupings) {
- wr.Write("(distinct");
- foreach (VCExpr e in g) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options);
- }
- wr.Write(")");
- }
-
- if (groupings.Length > 1)
- wr.Write(")");
-
- wr.Write("\n");
- }
- }
-
- return true;
- }
-
- public bool VisitLabelOp(VCExprNAry node, LineariserOptions options)
- {
- if (ExprLineariser.UnderQuantifier > 0 && !options.LabelsBelowQuantifiers) {
- ExprLineariser.Linearise(node[0], options);
- return true;
- }
-
- var op = (VCExprLabelOp)node.Op;
-
- if (CommandLineOptions.Clo.UseLabels)
- {
- // Z3 extension
- //wr.Write("({0} {1} ", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label));
- wr.Write("(! ");
- }
-
- if(!options.LabelsBelowQuantifiers)
- wr.Write("({0} {1} ", op.pos ? "and" : "or", SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(op.label)));
-
- ExprLineariser.Linearise(node[0], options);
-
-
- if (!options.LabelsBelowQuantifiers)
- wr.Write(")");
-
- if (CommandLineOptions.Clo.UseLabels)
- wr.Write(" :{0} {1})", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label));
-
- return true;
- }
-
- public bool VisitSelectOp(VCExprNAry node, LineariserOptions options)
- {
- var name = SimplifyLikeExprLineariser.SelectOpName(node);
- name = ExprLineariser.Namer.GetQuotedName(name, name);
- if (CommandLineOptions.Clo.UseArrayTheory)
- name = "select";
- WriteApplication(name, node, options);
- return true;
- }
-
- public bool VisitStoreOp(VCExprNAry node, LineariserOptions options)
- {
- var name = SimplifyLikeExprLineariser.StoreOpName(node);
- name = ExprLineariser.Namer.GetQuotedName(name, name);
- if (CommandLineOptions.Clo.UseArrayTheory)
- name = "store";
- WriteApplication(name, node, options);
- return true;
- }
-
- public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.add RNE", node, options);
- return true;
- }
-
- public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.sub RNE", node, options);
- return true;
- }
-
- public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.mul RNE", node, options);
- return true;
- }
-
- public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.div RNE", node, options);
- return true;
- }
-
- public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.rem RNE", node, options);
- return true;
- }
-
- public bool VisitFloatMinOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.min", node, options);
- return true;
- }
-
- public bool VisitFloatMaxOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.max", node, options);
- return true;
- }
-
- public bool VisitFloatLeqOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.leq", node, options);
- return true;
- }
-
- public bool VisitFloatLtOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.lt", node, options);
- return true;
- }
-
- public bool VisitFloatGeqOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.geq", node, options);
- return true;
- }
-
- public bool VisitFloatGtOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.gt", node, options);
- return true;
- }
-
- public bool VisitFloatEqOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("fp.eq", node, options);
- return true;
- }
-
- static char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- public bool VisitBvOp(VCExprNAry node, LineariserOptions options)
- {
- var lit = (VCExprIntLit)node[0];
- var bytes = lit.Val.ToByteArray();
- if (node.Type.BvBits % 8 == 0) {
- wr.Write("#x");
- for (var pos = node.Type.BvBits / 8 - 1; pos >= 0; pos--) {
- var k = pos < bytes.Length ? bytes[pos] : (byte)0;
- wr.Write(hex[k >> 4]);
- wr.Write(hex[k & 0xf]);
- }
- } else {
- wr.Write("#b");
- for (var pos = node.Type.BvBits - 1; pos >= 0; pos--) {
- var i = pos >> 3;
- var k = i < bytes.Length ? bytes[i] : (byte)0;
- wr.Write((k & (1 << (pos & 7))) == 0 ? '0' : '1');
- }
- }
- return true;
- }
-
- public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options)
- {
- var op = (VCExprBvExtractOp)node.Op;
- wr.Write("((_ extract {0} {1}) ", op.End - 1, op.Start);
- ExprLineariser.Linearise(node[0], options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("concat", node, options);
- return true;
- }
-
- public bool VisitAddOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("+", node, options);
- return true;
- }
-
- public bool VisitSubOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("-", node, options);
- return true;
- }
-
- public bool VisitMulOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("*", node, options);
- return true;
- }
-
- public bool VisitDivOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("div", node, options);
- return true;
- }
-
- public bool VisitModOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("mod", node, options);
- return true;
- }
-
- public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("/", node, options);
- return true;
- }
-
- public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("real_pow", node, options);
- return true;
- }
-
- public bool VisitLtOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("<", node, options);
- return true;
- }
-
- public bool VisitLeOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("<=", node, options);
- return true;
- }
-
- public bool VisitGtOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication(">", node, options);
- return true;
- }
-
- public bool VisitGeOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication(">=", node, options);
- return true;
- }
-
- public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("UOrdering2", node, options);
- return true;
- }
-
- public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("UOrdering3", node, options);
- return true;
- }
-
- public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("to_int", node, options);
- return true;
- }
-
- public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("to_real", node, options);
- return true;
- }
-
- private string ExtractDatatype(Function func) {
- if (func is DatatypeSelector) {
- DatatypeSelector selector = (DatatypeSelector) func;
- Variable v = selector.constructor.InParams[selector.index];
- return ExprLineariser.Namer.GetQuotedName(v, v.Name + "#" + selector.constructor.Name);
- }
- else if (func is DatatypeMembership) {
- DatatypeMembership membership = (DatatypeMembership)func;
- return ExprLineariser.Namer.GetQuotedName(membership, "is-" + membership.constructor.Name);
- }
- else {
- return null;
- }
- }
-
- public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
- VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op != null);
- string printedName;
-
- var builtin = ExtractBuiltin(op.Func);
- var datatype = ExtractDatatype(op.Func);
- if (builtin != null)
- {
- printedName = CheckMapApply(builtin, node);
- }
- else if (datatype != null)
- {
- printedName = datatype;
- }
- else
- {
- printedName = ExprLineariser.Namer.GetQuotedName(op.Func, op.Func.Name);
- }
- Contract.Assert(printedName != null);
-
- WriteApplication(printedName, node, options);
-
- return true;
- }
-
- private static Type ResultType(Type type) {
- MapType mapType = type as MapType;
- if (mapType != null) {
- return ResultType(mapType.Result);
- }
- else {
- return type;
- }
- }
-
- public static HashSet<string> ArrayOps = new HashSet<string>(new string[] {
- "MapConst", "MapAdd", "MapSub", "MapMul", "MapDiv", "MapMod", "MapEq", "MapIff", "MapGt", "MapGe", "MapLt", "MapLe", "MapOr", "MapAnd", "MapNot", "MapImp", "MapIte" });
-
- private static string CheckMapApply(string name, VCExprNAry node) {
- if (name == "MapConst") {
- Type type = node.Type;
- string s = TypeToString(type);
- return "(as const " + s + ")";
- }
- else if (name == "MapAdd") {
- return "(_ map (+ (Int Int) Int))";
- }
- else if (name == "MapSub") {
- return "(_ map (- (Int Int) Int))";
- }
- else if (name == "MapMul") {
- return "(_ map (* (Int Int) Int))";
- }
- else if (name == "MapDiv") {
- return "(_ map (div (Int Int) Int))";
- }
- else if (name == "MapMod") {
- return "(_ map (mod (Int Int) Int))";
- }
- else if (name == "MapEq") {
- Type type = ResultType(node[0].Type);
- string s = TypeToString(type);
- return "(_ map (= (" + s + " " + s + ") Bool))";
- }
- else if (name == "MapIff") {
- return "(_ map (= (Bool Bool) Bool))";
- }
- else if (name == "MapGt") {
- return "(_ map (> (Int Int) Int))";
- }
- else if (name == "MapGe") {
- return "(_ map (>= (Int Int) Int))";
- }
- else if (name == "MapLt") {
- return "(_ map (< (Int Int) Int))";
- }
- else if (name == "MapLe") {
- return "(_ map (<= (Int Int) Int))";
- }
- else if (name == "MapOr") {
- return "(_ map or)";
- }
- else if (name == "MapAnd") {
- return "(_ map and)";
- }
- else if (name == "MapNot") {
- return "(_ map not)";
- }
- else if (name == "MapImp") {
- return "(_ map =>)";
- }
- else if (name == "MapIte") {
- Type type = ResultType(node.Type);
- string s = TypeToString(type);
- return "(_ map (ite (Bool " + s + " " + s + ") " + s + "))";
- }
- else {
- return name;
- }
- }
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Method to turn VCExprs into strings that can be fed into SMT
+// solvers. This is currently quite similar to the
+// SimplifyLikeLineariser (but the code is independent)
+
+namespace Microsoft.Boogie.SMTLib
+{
+
+ // Options for the linearisation
+ public class LineariserOptions
+ {
+ public static LineariserOptions Default = new LineariserOptions();
+ public bool LabelsBelowQuantifiers = false;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for expressions. The result (bool) is currently not used for anything
+ public class SMTLibExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/>
+ {
+
+ public static string ToString(VCExpr e, UniqueNamer namer, SMTLibProverOptions opts, ISet<VCExprVar> namedAssumes = null, IList<string> optReqs = null, ISet<VCExprVar> tryAssumes = null)
+ {
+ Contract.Requires(e != null);
+ Contract.Requires(namer != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ StringWriter sw = new StringWriter();
+ SMTLibExprLineariser lin = new SMTLibExprLineariser(sw, namer, opts, namedAssumes, optReqs);
+ Contract.Assert(lin != null);
+ lin.Linearise(e, LineariserOptions.Default);
+ return cce.NonNull(sw.ToString());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private readonly TextWriter wr;
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(wr != null);
+ Contract.Invariant(Namer != null);
+ }
+
+ private SMTLibOpLineariser OpLinObject = null;
+ private IVCExprOpVisitor<bool, LineariserOptions>/*!>!*/ OpLineariser
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
+
+ if (OpLinObject == null)
+ OpLinObject = new SMTLibOpLineariser(this, wr);
+ return OpLinObject;
+ }
+ }
+
+ internal readonly UniqueNamer Namer;
+ internal int UnderQuantifier = 0;
+ internal readonly SMTLibProverOptions ProverOptions;
+
+ readonly IList<string> OptimizationRequests;
+ readonly ISet<VCExprVar> NamedAssumes;
+
+ public SMTLibExprLineariser(TextWriter wr, UniqueNamer namer, SMTLibProverOptions opts, ISet<VCExprVar> namedAssumes = null, IList<string> optReqs = null)
+ {
+ Contract.Requires(wr != null); Contract.Requires(namer != null);
+ this.wr = wr;
+ this.Namer = namer;
+ this.ProverOptions = opts;
+ this.OptimizationRequests = optReqs;
+ this.NamedAssumes = namedAssumes;
+ }
+
+ public void Linearise(VCExpr expr, LineariserOptions options)
+ {
+ Contract.Requires(expr != null);
+ Contract.Requires(options != null);
+ expr.Accept<bool, LineariserOptions>(this, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ private static void TypeToStringHelper(Type t, StringBuilder sb)
+ {
+ Contract.Requires(t != null);
+
+ TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
+ if (syn != null) {
+ TypeToStringHelper(syn.ExpandedType, sb);
+ } else {
+ if (t.IsMap && CommandLineOptions.Clo.UseArrayTheory) {
+ MapType m = t.AsMap;
+ // Contract.Assert(m.MapArity == 1);
+ sb.Append("(Array ");
+ foreach (Type tp in m.Arguments)
+ sb.Append(TypeToString(tp)).Append(" ");
+ sb.Append(TypeToString(m.Result)).Append(")");
+ } else if (t.IsMap) {
+ MapType m = t.AsMap;
+ sb.Append('[');
+ for (int i = 0; i < m.MapArity; ++i) {
+ if (i != 0)
+ sb.Append(',');
+ TypeToStringHelper(m.Arguments[i], sb);
+ }
+ sb.Append(']');
+ TypeToStringHelper(m.Result, sb);
+ } else if (t.IsBool || t.IsInt || t.IsReal || t.IsFloat || t.IsBv) {
+ sb.Append(TypeToString(t));
+ } else {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/false, /*pretty=*/false)) {
+ t.Emit(stream);
+ }
+ sb.Append(buffer.ToString());
+ }
+ }
+
+ }
+
+ public static string TypeToString(Type t)
+ {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ if (t.IsBool)
+ return "Bool";
+ else if (t.IsInt)
+ return "Int";
+ else if (t.IsReal)
+ return "Real";
+ else if (t.IsFloat)
+ return "(_ FloatingPoint " + t.FloatExponent + " " + t.FloatMantissa + ")";
+ else if (t.IsBv) {
+ return "(_ BitVec " + t.BvBits + ")";
+ } else {
+ StringBuilder sb = new StringBuilder();
+ TypeToStringHelper(t, sb);
+ var s = sb.ToString();
+ if (s[0] == '(')
+ return s;
+ else
+ return SMTLibNamer.QuoteId("T@" + s);
+ }
+ }
+
+ public static string ExtractBuiltin(Function f)
+ {
+ Contract.Requires(f != null);
+ string retVal = null;
+ retVal = f.FindStringAttribute("bvbuiltin");
+
+ // It used to be "sign_extend 12" in Simplify, and is "(_ sign_extend 12)" with SMT
+ if (retVal != null && (retVal.StartsWith("sign_extend ") || retVal.StartsWith("zero_extend ")))
+ return "(_ " + retVal + ")";
+
+ if (retVal == null) {
+ retVal = f.FindStringAttribute("builtin");
+ }
+
+ if (retVal != null && !CommandLineOptions.Clo.UseArrayTheory && SMTLibOpLineariser.ArrayOps.Contains(retVal))
+ {
+ retVal = null;
+ }
+
+ return retVal;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLiteral node, LineariserOptions options)
+ {
+ if (node == VCExpressionGenerator.True)
+ wr.Write("true");
+ else if (node == VCExpressionGenerator.False)
+ wr.Write("false");
+ else if (node is VCExprIntLit) {
+ BigNum lit = ((VCExprIntLit)node).Val;
+ if (lit.IsNegative)
+ // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
+ wr.Write("(- 0 {0})", lit.Abs);
+ else
+ wr.Write(lit);
+ }
+ else if (node is VCExprRealLit) {
+ BigDec lit = ((VCExprRealLit)node).Val;
+ if (lit.IsNegative)
+ // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
+ wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString());
+ else
+ wr.Write(lit.ToDecimalString());
+ }
+ else if (node is VCExprFloatLit)
+ {
+ BigFloat lit = ((VCExprFloatLit)node).Val;
+ wr.Write("(" + lit.ToBVString() + ")");
+ }
+ else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprNAry node, LineariserOptions options)
+ {
+ VCExprOp op = node.Op;
+ Contract.Assert(op != null);
+
+ var booleanOps = new HashSet<VCExprOp>();
+ booleanOps.Add(VCExpressionGenerator.NotOp);
+ booleanOps.Add(VCExpressionGenerator.ImpliesOp);
+ booleanOps.Add(VCExpressionGenerator.AndOp);
+ booleanOps.Add(VCExpressionGenerator.OrOp);
+ if (booleanOps.Contains(op))
+ {
+ Stack<VCExpr> exprs = new Stack<VCExpr>();
+ exprs.Push(node);
+ while (exprs.Count > 0)
+ {
+ VCExpr expr = exprs.Pop();
+ if (expr == null)
+ {
+ wr.Write(")");
+ continue;
+ }
+ wr.Write(" ");
+ VCExprNAry naryExpr = expr as VCExprNAry;
+ if (naryExpr == null || !booleanOps.Contains(naryExpr.Op))
+ {
+ Linearise(expr, options);
+ continue;
+ }
+ else if (naryExpr.Op.Equals(VCExpressionGenerator.NotOp))
+ {
+ wr.Write("(not");
+ }
+ else if (naryExpr.Op.Equals(VCExpressionGenerator.ImpliesOp))
+ {
+ wr.Write("(=>");
+ }
+ else if (naryExpr.Op.Equals(VCExpressionGenerator.AndOp))
+ {
+ wr.Write("(and");
+ }
+ else
+ {
+ System.Diagnostics.Debug.Assert(naryExpr.Op.Equals(VCExpressionGenerator.OrOp));
+ wr.Write("(or");
+ }
+ exprs.Push(null);
+ for (int i = naryExpr.Arity - 1; i >= 0; i--)
+ {
+ exprs.Push(naryExpr[i]);
+ }
+ }
+ return true;
+ }
+ if (OptimizationRequests != null
+ && (node.Op.Equals(VCExpressionGenerator.MinimizeOp) || node.Op.Equals(VCExpressionGenerator.MaximizeOp)))
+ {
+ string optOp = node.Op.Equals(VCExpressionGenerator.MinimizeOp) ? "minimize" : "maximize";
+ OptimizationRequests.Add(string.Format("({0} {1})", optOp, ToString(node[0], Namer, ProverOptions, NamedAssumes)));
+ Linearise(node[1], options);
+ return true;
+ }
+ if (node.Op is VCExprSoftOp)
+ {
+ Linearise(node[1], options);
+ return true;
+ }
+ if (node.Op.Equals(VCExpressionGenerator.NamedAssumeOp))
+ {
+ var exprVar = node[0] as VCExprVar;
+ NamedAssumes.Add(exprVar);
+ Linearise(node[1], options);
+ return true;
+ }
+ return node.Accept<bool, LineariserOptions/*!*/>(OpLineariser, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprVar node, LineariserOptions options)
+ {
+ wr.Write(Namer.GetQuotedName(node, node.Name));
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprQuantifier node, LineariserOptions options)
+ {
+ Contract.Assert(node.TypeParameters.Count == 0);
+
+ UnderQuantifier++;
+ Namer.PushScope(); try {
+
+ string kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
+ wr.Write("({0} (", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++) {
+ VCExprVar var = node.BoundVars[i];
+ Contract.Assert(var != null);
+ string printedName = Namer.GetQuotedLocalName(var, var.Name);
+ Contract.Assert(printedName != null);
+ wr.Write("({0} {1}) ", printedName, TypeToString(var.Type));
+ }
+
+ wr.Write(") ");
+
+ VCQuantifierInfos infos = node.Infos;
+ var weight = QKeyValue.FindIntAttribute(infos.attributes, "weight", 1);
+ if (!ProverOptions.UseWeights)
+ weight = 1;
+ var hasAttrs = node.Triggers.Count > 0 || infos.qid != null || weight != 1 || infos.uniqueId != -1;
+
+ if (hasAttrs)
+ wr.Write("(! ");
+
+ Linearise(node.Body, options);
+
+ if (hasAttrs) {
+ wr.Write("\n");
+ if (infos.qid != null)
+ wr.Write(" :qid {0}\n", SMTLibNamer.QuoteId(infos.qid));
+ if (weight != 1)
+ wr.Write(" :weight {0}\n", weight);
+ if (infos.uniqueId != -1)
+ wr.Write(" :skolemid |{0}|\n", infos.uniqueId);
+ WriteTriggers(node.Triggers, options);
+
+ wr.Write(")");
+ }
+
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ UnderQuantifier--;
+ Namer.PopScope();
+ }
+ }
+
+ private void WriteTriggers(List<VCTrigger/*!>!*/> triggers, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(triggers != null);
+ // first, count how many neg/pos triggers there are
+ int negTriggers = 0;
+ int posTriggers = 0;
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (vcTrig.Pos) {
+ posTriggers++;
+ } else {
+ negTriggers++;
+ }
+ }
+
+ if (posTriggers > 0) {
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (vcTrig.Pos) {
+ wr.Write(" :pattern (");
+ foreach (VCExpr e in vcTrig.Exprs) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ var subPat = e;
+ var nary = e as VCExprNAry;
+ if (nary != null && (nary.Op == VCExpressionGenerator.NeqOp || nary.Op == VCExpressionGenerator.EqOp)) {
+ if (nary[0] is VCExprLiteral)
+ subPat = nary[1];
+ else if (nary[1] is VCExprLiteral)
+ subPat = nary[0];
+ }
+ Linearise(subPat, options);
+ }
+ wr.Write(")\n");
+ }
+ }
+ } else if (negTriggers > 0) {
+ // if also positive triggers are given, the SMT solver (at least Z3)
+ // will ignore the negative patterns and output a warning. Therefore
+ // we never specify both negative and positive triggers
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (!vcTrig.Pos) {
+ wr.Write(" :no-pattern ");
+ Contract.Assert(vcTrig.Exprs.Count == 1);
+ Linearise(vcTrig.Exprs[0], options);
+ wr.Write("\n");
+ }
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLet node, LineariserOptions options)
+ {
+ Namer.PushScope();
+ try {
+
+ foreach (VCExprLetBinding b in node) {
+ wr.Write("(let (");
+ Contract.Assert(b != null);
+ wr.Write("({0} ", Namer.GetQuotedName(b.V, b.V.Name));
+ Linearise(b.E, options);
+ wr.Write("))\n");
+ }
+ Linearise(node.Body, options);
+ foreach (VCExprLetBinding b in node)
+ wr.Write(")");
+ return true;
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for operator terms. The result (bool) is currently not used for anything
+ internal class SMTLibOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/>
+ {
+ private readonly SMTLibExprLineariser ExprLineariser;
+ private readonly TextWriter wr;
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(wr != null);
+ Contract.Invariant(ExprLineariser != null);
+ }
+
+
+ public SMTLibOpLineariser(SMTLibExprLineariser ExprLineariser, TextWriter wr)
+ {
+ Contract.Requires(ExprLineariser != null);
+ Contract.Requires(wr != null);
+ this.ExprLineariser = ExprLineariser;
+ this.wr = wr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ private void WriteApplication(string opName, IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options)
+ {
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(options != null);
+ Contract.Assert(opName != null);
+
+ bool hasArgs = false;
+ foreach (VCExpr e in args) {
+ Contract.Assert(e != null);
+ if (!hasArgs)
+ wr.Write("({0}", opName);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options);
+ hasArgs = true;
+ }
+
+ if (hasArgs)
+ wr.Write(")");
+ else
+ wr.Write("{0}", opName);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public bool VisitNotOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("not", node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ private bool PrintEq(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(node != null);
+ Contract.Requires(options != null);
+
+ WriteApplication("=", node, options);
+
+ return true;
+ }
+
+ public bool VisitEqOp(VCExprNAry node, LineariserOptions options)
+ {
+ return PrintEq(node, options);
+ }
+
+ public bool VisitNeqOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ wr.Write("(not ");
+ PrintEq(node, options);
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitAndOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("and", node, options);
+ return true;
+ }
+
+ public bool VisitOrOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("or", node, options);
+ return true;
+ }
+
+ public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("=>", node, options);
+ return true;
+ }
+
+ public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("ite", node, options);
+ return true;
+ }
+
+ public bool VisitCustomOp(VCExprNAry node, LineariserOptions options)
+ {
+ VCExprCustomOp op = (VCExprCustomOp)node.Op;
+ if (!ExprLineariser.ProverOptions.UseTickleBool && op.Name == "tickleBool")
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ else
+ WriteApplication(op.Name, node, options);
+ return true;
+ }
+
+ public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ if (node.Length < 2) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ var groupings = node.GroupBy(e => e.Type).Where(g => g.Count() > 1).ToArray();
+ if (groupings.Length == 0) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ if (groupings.Length > 1)
+ wr.Write("(and ");
+
+ foreach (var g in groupings) {
+ wr.Write("(distinct");
+ foreach (VCExpr e in g) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options);
+ }
+ wr.Write(")");
+ }
+
+ if (groupings.Length > 1)
+ wr.Write(")");
+
+ wr.Write("\n");
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitLabelOp(VCExprNAry node, LineariserOptions options)
+ {
+ if (ExprLineariser.UnderQuantifier > 0 && !options.LabelsBelowQuantifiers) {
+ ExprLineariser.Linearise(node[0], options);
+ return true;
+ }
+
+ var op = (VCExprLabelOp)node.Op;
+
+ if (CommandLineOptions.Clo.UseLabels)
+ {
+ // Z3 extension
+ //wr.Write("({0} {1} ", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label));
+ wr.Write("(! ");
+ }
+
+ if(!options.LabelsBelowQuantifiers)
+ wr.Write("({0} {1} ", op.pos ? "and" : "or", SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(op.label)));
+
+ ExprLineariser.Linearise(node[0], options);
+
+
+ if (!options.LabelsBelowQuantifiers)
+ wr.Write(")");
+
+ if (CommandLineOptions.Clo.UseLabels)
+ wr.Write(" :{0} {1})", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label));
+
+ return true;
+ }
+
+ public bool VisitSelectOp(VCExprNAry node, LineariserOptions options)
+ {
+ var name = SimplifyLikeExprLineariser.SelectOpName(node);
+ name = ExprLineariser.Namer.GetQuotedName(name, name);
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ name = "select";
+ WriteApplication(name, node, options);
+ return true;
+ }
+
+ public bool VisitStoreOp(VCExprNAry node, LineariserOptions options)
+ {
+ var name = SimplifyLikeExprLineariser.StoreOpName(node);
+ name = ExprLineariser.Namer.GetQuotedName(name, name);
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ name = "store";
+ WriteApplication(name, node, options);
+ return true;
+ }
+
+ public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.add RNE", node, options);
+ return true;
+ }
+
+ public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.sub RNE", node, options);
+ return true;
+ }
+
+ public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.mul RNE", node, options);
+ return true;
+ }
+
+ public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.div RNE", node, options);
+ return true;
+ }
+
+ public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.rem RNE", node, options);
+ return true;
+ }
+
+ public bool VisitFloatMinOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.min", node, options);
+ return true;
+ }
+
+ public bool VisitFloatMaxOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.max", node, options);
+ return true;
+ }
+
+ public bool VisitFloatLeqOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.leq", node, options);
+ return true;
+ }
+
+ public bool VisitFloatLtOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.lt", node, options);
+ return true;
+ }
+
+ public bool VisitFloatGeqOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.geq", node, options);
+ return true;
+ }
+
+ public bool VisitFloatGtOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.gt", node, options);
+ return true;
+ }
+
+ public bool VisitFloatEqOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("fp.eq", node, options);
+ return true;
+ }
+
+ static char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ public bool VisitBvOp(VCExprNAry node, LineariserOptions options)
+ {
+ var lit = (VCExprIntLit)node[0];
+ var bytes = lit.Val.ToByteArray();
+ if (node.Type.BvBits % 8 == 0) {
+ wr.Write("#x");
+ for (var pos = node.Type.BvBits / 8 - 1; pos >= 0; pos--) {
+ var k = pos < bytes.Length ? bytes[pos] : (byte)0;
+ wr.Write(hex[k >> 4]);
+ wr.Write(hex[k & 0xf]);
+ }
+ } else {
+ wr.Write("#b");
+ for (var pos = node.Type.BvBits - 1; pos >= 0; pos--) {
+ var i = pos >> 3;
+ var k = i < bytes.Length ? bytes[i] : (byte)0;
+ wr.Write((k & (1 << (pos & 7))) == 0 ? '0' : '1');
+ }
+ }
+ return true;
+ }
+
+ public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options)
+ {
+ var op = (VCExprBvExtractOp)node.Op;
+ wr.Write("((_ extract {0} {1}) ", op.End - 1, op.Start);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("concat", node, options);
+ return true;
+ }
+
+ public bool VisitAddOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("+", node, options);
+ return true;
+ }
+
+ public bool VisitSubOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("-", node, options);
+ return true;
+ }
+
+ public bool VisitMulOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("*", node, options);
+ return true;
+ }
+
+ public bool VisitDivOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("div", node, options);
+ return true;
+ }
+
+ public bool VisitModOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("mod", node, options);
+ return true;
+ }
+
+ public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("/", node, options);
+ return true;
+ }
+
+ public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("real_pow", node, options);
+ return true;
+ }
+
+ public bool VisitLtOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("<", node, options);
+ return true;
+ }
+
+ public bool VisitLeOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("<=", node, options);
+ return true;
+ }
+
+ public bool VisitGtOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication(">", node, options);
+ return true;
+ }
+
+ public bool VisitGeOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication(">=", node, options);
+ return true;
+ }
+
+ public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("UOrdering2", node, options);
+ return true;
+ }
+
+ public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options)
+ {
+ WriteApplication("UOrdering3", node, options);
+ return true;
+ }
+
+ public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("to_int", node, options);
+ return true;
+ }
+
+ public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ WriteApplication("to_real", node, options);
+ return true;
+ }
+
+ private string ExtractDatatype(Function func) {
+ if (func is DatatypeSelector) {
+ DatatypeSelector selector = (DatatypeSelector) func;
+ Variable v = selector.constructor.InParams[selector.index];
+ return ExprLineariser.Namer.GetQuotedName(v, v.Name + "#" + selector.constructor.Name);
+ }
+ else if (func is DatatypeMembership) {
+ DatatypeMembership membership = (DatatypeMembership)func;
+ return ExprLineariser.Namer.GetQuotedName(membership, "is-" + membership.constructor.Name);
+ }
+ else {
+ return null;
+ }
+ }
+
+ public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
+ VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
+ Contract.Assert(op != null);
+ string printedName;
+
+ var builtin = ExtractBuiltin(op.Func);
+ var datatype = ExtractDatatype(op.Func);
+ if (builtin != null)
+ {
+ printedName = CheckMapApply(builtin, node);
+ }
+ else if (datatype != null)
+ {
+ printedName = datatype;
+ }
+ else
+ {
+ printedName = ExprLineariser.Namer.GetQuotedName(op.Func, op.Func.Name);
+ }
+ Contract.Assert(printedName != null);
+
+ WriteApplication(printedName, node, options);
+
+ return true;
+ }
+
+ private static Type ResultType(Type type) {
+ MapType mapType = type as MapType;
+ if (mapType != null) {
+ return ResultType(mapType.Result);
+ }
+ else {
+ return type;
+ }
+ }
+
+ public static HashSet<string> ArrayOps = new HashSet<string>(new string[] {
+ "MapConst", "MapAdd", "MapSub", "MapMul", "MapDiv", "MapMod", "MapEq", "MapIff", "MapGt", "MapGe", "MapLt", "MapLe", "MapOr", "MapAnd", "MapNot", "MapImp", "MapIte" });
+
+ private static string CheckMapApply(string name, VCExprNAry node) {
+ if (name == "MapConst") {
+ Type type = node.Type;
+ string s = TypeToString(type);
+ return "(as const " + s + ")";
+ }
+ else if (name == "MapAdd") {
+ return "(_ map (+ (Int Int) Int))";
+ }
+ else if (name == "MapSub") {
+ return "(_ map (- (Int Int) Int))";
+ }
+ else if (name == "MapMul") {
+ return "(_ map (* (Int Int) Int))";
+ }
+ else if (name == "MapDiv") {
+ return "(_ map (div (Int Int) Int))";
+ }
+ else if (name == "MapMod") {
+ return "(_ map (mod (Int Int) Int))";
+ }
+ else if (name == "MapEq") {
+ Type type = ResultType(node[0].Type);
+ string s = TypeToString(type);
+ return "(_ map (= (" + s + " " + s + ") Bool))";
+ }
+ else if (name == "MapIff") {
+ return "(_ map (= (Bool Bool) Bool))";
+ }
+ else if (name == "MapGt") {
+ return "(_ map (> (Int Int) Int))";
+ }
+ else if (name == "MapGe") {
+ return "(_ map (>= (Int Int) Int))";
+ }
+ else if (name == "MapLt") {
+ return "(_ map (< (Int Int) Int))";
+ }
+ else if (name == "MapLe") {
+ return "(_ map (<= (Int Int) Int))";
+ }
+ else if (name == "MapOr") {
+ return "(_ map or)";
+ }
+ else if (name == "MapAnd") {
+ return "(_ map and)";
+ }
+ else if (name == "MapNot") {
+ return "(_ map not)";
+ }
+ else if (name == "MapImp") {
+ return "(_ map =>)";
+ }
+ else if (name == "MapIte") {
+ Type type = ResultType(node.Type);
+ string s = TypeToString(type);
+ return "(_ map (ite (Bool " + s + " " + s + ") " + s + "))";
+ }
+ else {
+ return name;
+ }
+ }
+ }
+ }
+
+}
diff --git a/Source/Provers/SMTLib/SMTLibNamer.cs b/Source/Provers/SMTLib/SMTLibNamer.cs
index 3ef2039b..f1179159 100644
--- a/Source/Provers/SMTLib/SMTLibNamer.cs
+++ b/Source/Provers/SMTLib/SMTLibNamer.cs
@@ -1,142 +1,147 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.SMTLib
-{
- public class SMTLibNamer : UniqueNamer
- {
- // The following Boogie ID characters are not SMT ID characters: `'\#
- const string idCharacters = "~!@$%^&*_-+=<>.?/";
-
-
- static string[] reservedSmtWordsList =
- { // Basic symbols:
- "", "!", "_", "as", "DECIMAL", "exists", "forall", "let", "NUMERAL", "par", "STRING",
- // Commands:
- "assert", "check-sat", "declare-sort", "declare-fun", "define-sort,", "define-fun", "exit",
- "get-assertions", "get-assignment", "get-info", "get-option,", "get-proof", "get-unsat-core",
- "get-value", "pop", "push", "set-logic", "set-info", "set-option",
- // Core theory:
- "and", "or", "not", "iff", "true", "false", "xor", "distinct", "ite", "=", "Bool",
- "=>", // implies (sic!)
- // Integers and reals
- "Int", "Real", "*", "/", "-", "~", "+", "<", "<=", ">", ">=", "div", "mod", "rem",
- "^", "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "pi", "euler",
- "to_real", "to_int", "is_int",
- // Bitvectors
- "extract", "concat",
- "bvnot", "bvneg", "bvand", "bvor", "bvadd", "bvmul", "bvudiv", "bvurem", "bvshl", "bvlshr", "bvult",
- // arrays
- "store", "select", "const", "default", "map", "union", "intersect", "difference", "complement",
- "subset", "array-ext", "as-array", "Array",
- // Z3 (and not only?) extensions to bitvectors
- "bit1", "bit0", "bvsub", "bvsdiv", "bvsrem", "bvsmod", "bvsdiv0", "bvudiv0", "bvsrem0", "bvurem0",
- "bvsmod0", "bvsdiv_i", "bvudiv_i", "bvsrem_i", "bvurem_i", "bvumod_i", "bvule", "bvsle", "bvuge",
- "bvsge", "bvslt", "bvugt", "bvsgt", "bvxor", "bvnand", "bvnor", "bvxnor", "sign_extend", "zero_extend",
- "repeat", "bvredor", "bvredand", "bvcomp", "bvumul_noovfl", "bvsmul_noovfl", "bvsmul_noudfl", "bvashr",
- "rotate_left", "rotate_right", "ext_rotate_left", "ext_rotate_right", "int2bv", "bv2int", "mkbv",
- // floating point (FIXME: Legacy, remove this)
- "plusInfinity", "minusInfinity",
- "+", "-", "/", "*", "==", "<", ">", "<=", ">=",
- "abs", "remainder", "fusedMA", "squareRoot", "roundToIntegral",
- "isZero", "isNZero", "isPZero", "isSignMinus", "min", "max", "asFloat",
- // SMT v1 stuff (FIXME: Legacy, remove this)
- "flet", "implies", "!=", "if_then_else",
- // Z3 extensions
- "lblneg", "lblpos", "lbl-lit",
- "if", "&&", "||", "equals", "equiv", "bool",
- // Boogie-defined
- "real_pow", "UOrdering2", "UOrdering3",
- // Floating point (final draft SMTLIB-v2.5)
- "NaN",
- "roundNearestTiesToEven", "roundNearestTiesToAway", "roundTowardPositive", "roundTowardNegative", "roundTowardZero",
- "RNE", "RNA", "RTP", "RTN", "RTZ",
- "fp.abs", "fp.neg", "fp.add", "fp.sub", "fp.mul", "fp.div", "fp.fma", "fp.sqrt", "fp.rem", "fp.roundToIntegral",
- "fp.min", "fp.max", "fp.leq", "fp.lt", "fp.geq", "fp.gt", "fp.eq",
- "fp.isNormal", "fp.isSubnormal", "fp.isZero", "fp.isInfinite", "fp.isNaN", "fp.isNegative", "fp.isPositive",
- "fp", "fp.to_ubv", "fp.to_sbv", "to_fp",
- };
-
- static HashSet<string> reservedSmtWords;
- static bool[] validIdChar;
- static bool symbolListsInitilized;
-
- static void InitSymbolLists()
- {
- lock (reservedSmtWordsList) {
- // don't move out, c.f. http://en.wikipedia.org/wiki/Double-checked_locking
- if (symbolListsInitilized)
- return;
- reservedSmtWords = new HashSet<string>();
- foreach (var w in reservedSmtWordsList)
- reservedSmtWords.Add(w);
- validIdChar = new bool[255];
- for (int i = 0; i < validIdChar.Length; ++i)
- validIdChar[i] = char.IsLetterOrDigit((char)i) || idCharacters.IndexOf((char)i) >= 0;
- symbolListsInitilized = true;
- }
- }
-
- static string AddQuotes(string s)
- {
- var allGood = true;
-
- foreach (char ch in s) {
- var c = (int)ch;
- if (c >= validIdChar.Length || !validIdChar[c]) {
- allGood = false;
- break;
- }
- }
-
- if (allGood)
- return s;
-
- return "|" + s + "|";
- }
-
- static string NonKeyword(string s)
- {
- if (reservedSmtWords.Contains(s) || char.IsDigit(s[0]))
- s = "q@" + s;
-
- // | and \ are illegal even in quoted identifiers
- if (s.IndexOf('|') >= 0)
- s = s.Replace("|", "_");
-
- if (s.IndexOf('\\') >= 0)
- s = s.Replace("\\", "_");
-
- return s;
- }
-
- public static string LabelVar(string s)
- {
- return "%lbl%" + s;
- }
-
- public static string QuoteId(string s)
- {
- return AddQuotes(NonKeyword(s));
- }
-
- public override string GetQuotedLocalName(object thingie, string inherentName)
- {
- return AddQuotes(base.GetLocalName(thingie, NonKeyword(inherentName)));
- }
-
- public override string GetQuotedName(object thingie, string inherentName)
- {
- return AddQuotes(base.GetName(thingie, NonKeyword(inherentName)));
- }
-
- public SMTLibNamer()
- {
- this.Spacer = "@@";
- InitSymbolLists();
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ public class SMTLibNamer : UniqueNamer
+ {
+ // The following Boogie ID characters are not SMT ID characters: `'\#
+ const string idCharacters = "~!@$%^&*_-+=<>.?/";
+
+
+ static string[] reservedSmtWordsList =
+ { // Basic symbols:
+ "", "!", "_", "as", "DECIMAL", "exists", "forall", "let", "NUMERAL", "par", "STRING",
+ // Commands:
+ "assert", "check-sat", "declare-sort", "declare-fun", "define-sort,", "define-fun", "exit",
+ "get-assertions", "get-assignment", "get-info", "get-option,", "get-proof", "get-unsat-core",
+ "get-value", "pop", "push", "set-logic", "set-info", "set-option",
+ // Core theory:
+ "and", "or", "not", "iff", "true", "false", "xor", "distinct", "ite", "=", "Bool",
+ "=>", // implies (sic!)
+ // Integers and reals
+ "Int", "Real", "*", "/", "-", "~", "+", "<", "<=", ">", ">=", "div", "mod", "rem",
+ "^", "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "pi", "euler",
+ "to_real", "to_int", "is_int",
+ // Bitvectors
+ "extract", "concat",
+ "bvnot", "bvneg", "bvand", "bvor", "bvadd", "bvmul", "bvudiv", "bvurem", "bvshl", "bvlshr", "bvult",
+ // arrays
+ "store", "select", "const", "default", "map", "union", "intersect", "difference", "complement",
+ "subset", "array-ext", "as-array", "Array",
+ // Z3 (and not only?) extensions to bitvectors
+ "bit1", "bit0", "bvsub", "bvsdiv", "bvsrem", "bvsmod", "bvsdiv0", "bvudiv0", "bvsrem0", "bvurem0",
+ "bvsmod0", "bvsdiv_i", "bvudiv_i", "bvsrem_i", "bvurem_i", "bvumod_i", "bvule", "bvsle", "bvuge",
+ "bvsge", "bvslt", "bvugt", "bvsgt", "bvxor", "bvnand", "bvnor", "bvxnor", "sign_extend", "zero_extend",
+ "repeat", "bvredor", "bvredand", "bvcomp", "bvumul_noovfl", "bvsmul_noovfl", "bvsmul_noudfl", "bvashr",
+ "rotate_left", "rotate_right", "ext_rotate_left", "ext_rotate_right", "int2bv", "bv2int", "mkbv",
+ // floating point (FIXME: Legacy, remove this)
+ "plusInfinity", "minusInfinity",
+ "+", "-", "/", "*", "==", "<", ">", "<=", ">=",
+ "abs", "remainder", "fusedMA", "squareRoot", "roundToIntegral",
+ "isZero", "isNZero", "isPZero", "isSignMinus", "min", "max", "asFloat",
+ // SMT v1 stuff (FIXME: Legacy, remove this)
+ "flet", "implies", "!=", "if_then_else",
+ // Z3 extensions
+ "lblneg", "lblpos", "lbl-lit",
+ "if", "&&", "||", "equals", "equiv", "bool", "minimize", "maximize",
+ // Boogie-defined
+ "real_pow", "UOrdering2", "UOrdering3",
+ // Floating point (final draft SMTLIB-v2.5)
+ "NaN",
+ "roundNearestTiesToEven", "roundNearestTiesToAway", "roundTowardPositive", "roundTowardNegative", "roundTowardZero",
+ "RNE", "RNA", "RTP", "RTN", "RTZ",
+ "fp.abs", "fp.neg", "fp.add", "fp.sub", "fp.mul", "fp.div", "fp.fma", "fp.sqrt", "fp.rem", "fp.roundToIntegral",
+ "fp.min", "fp.max", "fp.leq", "fp.lt", "fp.geq", "fp.gt", "fp.eq",
+ "fp.isNormal", "fp.isSubnormal", "fp.isZero", "fp.isInfinite", "fp.isNaN", "fp.isNegative", "fp.isPositive",
+ "fp", "fp.to_ubv", "fp.to_sbv", "to_fp",
+ };
+
+ static HashSet<string> reservedSmtWords;
+ static bool[] validIdChar;
+ static bool symbolListsInitilized;
+
+ static void InitSymbolLists()
+ {
+ lock (reservedSmtWordsList) {
+ // don't move out, c.f. http://en.wikipedia.org/wiki/Double-checked_locking
+ if (symbolListsInitilized)
+ return;
+ reservedSmtWords = new HashSet<string>();
+ foreach (var w in reservedSmtWordsList)
+ reservedSmtWords.Add(w);
+ validIdChar = new bool[255];
+ for (int i = 0; i < validIdChar.Length; ++i)
+ validIdChar[i] = char.IsLetterOrDigit((char)i) || idCharacters.IndexOf((char)i) >= 0;
+ symbolListsInitilized = true;
+ }
+ }
+
+ static string AddQuotes(string s)
+ {
+ var allGood = true;
+
+ foreach (char ch in s) {
+ var c = (int)ch;
+ if (c >= validIdChar.Length || !validIdChar[c]) {
+ allGood = false;
+ break;
+ }
+ }
+
+ if (allGood)
+ return s;
+
+ return "|" + s + "|";
+ }
+
+ static string FilterReserved(string s)
+ {
+ // Note symbols starting with ``.`` and ``@`` are reserved for internal
+ // solver use in SMT-LIBv2 however if we check for the first character
+ // being ``@`` then Boogie's tests fail spectacularly because they are
+ // used for labels so we don't check for it here. It hopefully won't matter
+ // in practice because ``@`` cannot be legally used in Boogie identifiers.
+ if (reservedSmtWords.Contains(s) || char.IsDigit(s[0]) || s[0] == '.')
+ s = "q@" + s;
+
+ // | and \ are illegal even in quoted identifiers
+ if (s.IndexOf('|') >= 0)
+ s = s.Replace("|", "_");
+
+ if (s.IndexOf('\\') >= 0)
+ s = s.Replace("\\", "_");
+
+ return s;
+ }
+
+ public static string LabelVar(string s)
+ {
+ return "%lbl%" + s;
+ }
+
+ public static string QuoteId(string s)
+ {
+ return AddQuotes(FilterReserved(s));
+ }
+
+ public override string GetQuotedLocalName(object thingie, string inherentName)
+ {
+ return AddQuotes(base.GetLocalName(thingie, FilterReserved(inherentName)));
+ }
+
+ public override string GetQuotedName(object thingie, string inherentName)
+ {
+ return AddQuotes(base.GetName(thingie, FilterReserved(inherentName)));
+ }
+
+ public SMTLibNamer()
+ {
+ this.Spacer = "@@";
+ InitSymbolLists();
+ }
+ }
+}
diff --git a/Source/Provers/SMTLib/SMTLibProcess.cs b/Source/Provers/SMTLib/SMTLibProcess.cs
index bc94e253..a2fe4d4e 100644
--- a/Source/Provers/SMTLib/SMTLibProcess.cs
+++ b/Source/Provers/SMTLib/SMTLibProcess.cs
@@ -1,389 +1,398 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using System.IO;
-using System.Threading;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.SMTLib
-{
- public class SMTLibProcess
- {
- readonly Process prover;
- readonly Inspector inspector;
- readonly SMTLibProverOptions options;
- readonly Queue<string> proverOutput = new Queue<string>();
- readonly Queue<string> proverErrors = new Queue<string>();
- readonly TextWriter toProver;
- readonly int smtProcessId;
- static int smtProcessIdSeq = 0;
- ConsoleCancelEventHandler cancelEvent;
- public bool NeedsRestart;
-
- public static ProcessStartInfo ComputerProcessStartInfo(string executable, string options)
- {
- return new ProcessStartInfo(executable, options)
- {
- CreateNoWindow = true,
- UseShellExecute = false,
- RedirectStandardInput = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true
- };
- }
-
- public SMTLibProcess(ProcessStartInfo psi, SMTLibProverOptions options)
- {
- this.options = options;
- this.smtProcessId = smtProcessIdSeq++;
-
- if (options.Inspector != null) {
- this.inspector = new Inspector(options);
- }
-
- foreach (var arg in options.SolverArguments)
- psi.Arguments += " " + arg;
-
- if (cancelEvent == null && CommandLineOptions.Clo.RunningBoogieFromCommandLine) {
- cancelEvent = new ConsoleCancelEventHandler(ControlCHandler);
- Console.CancelKeyPress += cancelEvent;
- }
-
- if (options.Verbosity >= 1) {
- Console.WriteLine("[SMT-{0}] Starting {1} {2}", smtProcessId, psi.FileName, psi.Arguments);
- }
-
-
- try {
- prover = new Process();
- prover.StartInfo = psi;
- prover.ErrorDataReceived += prover_ErrorDataReceived;
- prover.OutputDataReceived += prover_OutputDataReceived;
- prover.Start();
- toProver = prover.StandardInput;
- prover.BeginErrorReadLine();
- prover.BeginOutputReadLine();
- } catch (System.ComponentModel.Win32Exception e) {
- throw new ProverException(string.Format("Unable to start the process {0}: {1}", psi.FileName, e.Message));
- }
- }
-
- [NoDefaultContract] // important, since we have no idea what state the object might be in when this handler is invoked
- void ControlCHandler(object o, ConsoleCancelEventArgs a)
- {
- if (prover != null) {
- prover.Kill();
- }
- }
-
- public void Send(string cmd)
- {
- if (options.Verbosity >= 2) {
- var log = cmd;
- if (log.Length > 50)
- log = log.Substring(0, 50) + "...";
- log = log.Replace("\r", "").Replace("\n", " ");
- Console.WriteLine("[SMT-INP-{0}] {1}", smtProcessId, log);
- }
- //Console.WriteLine(cmd);
- toProver.WriteLine(cmd);
- }
-
- // this is less than perfect; (echo ...) would be better
- public void Ping()
- {
- Send("(get-info :name)");
- }
-
- public bool IsPong(SExpr sx)
- {
- return sx != null && sx.Name == ":name";
- }
-
- public void PingPong()
- {
- Ping();
- while (true) {
- var sx = GetProverResponse();
- if (sx == null) {
- this.NeedsRestart = true;
- HandleError("Prover died");
- return;
- }
-
- if (IsPong(sx))
- return;
- else
- HandleError("Invalid PING response from the prover: " + sx.ToString());
- }
- }
-
- internal Inspector Inspector
- {
- get { return inspector; }
- }
-
- public SExpr GetProverResponse()
- {
- toProver.Flush();
-
- while (true) {
- var exprs = ParseSExprs(true).ToArray();
- Contract.Assert(exprs.Length <= 1);
- if (exprs.Length == 0)
- return null;
- var resp = exprs[0];
- if (resp.Name == "error") {
- if (resp.Arguments.Length == 1 && resp.Arguments[0].IsId)
- HandleError(resp.Arguments[0].Name);
- else
- HandleError(resp.ToString());
- } else if (resp.Name == "progress") {
- if (inspector != null) {
- var sb = new StringBuilder();
- foreach (var a in resp.Arguments) {
- if (a.Name == "labels") {
- sb.Append("STATS LABELS");
- foreach (var x in a.Arguments)
- sb.Append(" ").Append(x.Name);
- } else if (a.Name.StartsWith(":")) {
- sb.Append("STATS NAMED_VALUES ").Append(a.Name);
- foreach (var x in a.Arguments)
- sb.Append(" ").Append(x.Name);
- } else {
- continue;
- }
- inspector.StatsLine(sb.ToString());
- sb.Clear();
- }
- }
- } else if (resp.Name == "unsupported") {
- // Skip -- this may be a benign "unsupported" from a previous command.
- // Of course, this is suboptimal. We should really be using
- // print-success to identify the errant command and determine whether
- // the response is benign.
- } else {
- return resp;
- }
- }
- }
-
- public static System.TimeSpan TotalUserTime = System.TimeSpan.Zero;
-
- public void Close()
- {
- TotalUserTime += prover.UserProcessorTime;
- try {
- prover.Kill();
- } catch {
- }
- DisposeProver();
- }
-
- public event Action<string> ErrorHandler;
- int errorCnt;
-
- private void HandleError(string msg)
- {
- if (options.Verbosity >= 2)
- Console.WriteLine("[SMT-ERR-{0}] Handling error: {1}", smtProcessId, msg);
- if (ErrorHandler != null)
- ErrorHandler(msg);
- }
-
- #region SExpr parsing
- int linePos;
- string currLine;
- char SkipWs()
- {
- while (true) {
- if (currLine == null) {
- currLine = ReadProver();
- if (currLine == null)
- return '\0';
- }
-
-
- while (linePos < currLine.Length && char.IsWhiteSpace(currLine[linePos]))
- linePos++;
-
- if (linePos < currLine.Length && currLine[linePos] != ';')
- return currLine[linePos];
- else {
- currLine = null;
- linePos = 0;
- }
- }
- }
-
- void Shift()
- {
- linePos++;
- }
-
- string ParseId()
- {
- var sb = new StringBuilder();
-
- var beg = SkipWs();
-
- var quoted = beg == '"' || beg == '|';
- if (quoted)
- Shift();
- while (true) {
- if (linePos >= currLine.Length) {
- if (quoted) {
- sb.Append("\n");
- currLine = ReadProver();
- linePos = 0;
- if (currLine == null)
- break;
- } else break;
- }
-
- var c = currLine[linePos++];
- if (quoted && c == beg)
- break;
- if (!quoted && (char.IsWhiteSpace(c) || c == '(' || c == ')')) {
- linePos--;
- break;
- }
- if (quoted && c == '\\' && linePos < currLine.Length && currLine[linePos] == '"') {
- sb.Append('"');
- linePos++;
- continue;
- }
- sb.Append(c);
- }
-
- return sb.ToString();
- }
-
- void ParseError(string msg)
- {
- HandleError("Error parsing prover output: " + msg);
- }
-
- IEnumerable<SExpr> ParseSExprs(bool top)
- {
- while (true) {
- var c = SkipWs();
- if (c == '\0')
- break;
-
- if (c == ')') {
- if (top)
- ParseError("stray ')'");
- break;
- }
-
- string id;
-
- if (c == '(') {
- Shift();
- c = SkipWs();
- if (c == '\0') {
- ParseError("expecting something after '('");
- break;
- } else if (c == '(') {
- id = "";
- } else {
- id = ParseId();
- }
-
- var args = ParseSExprs(false).ToArray();
-
- c = SkipWs();
- if (c == ')') {
- Shift();
- } else {
- ParseError("unclosed '(" + id + "'");
- }
- yield return new SExpr(id, args);
- } else {
- id = ParseId();
- yield return new SExpr(id);
- }
-
- if (top) break;
- }
- }
- #endregion
-
- #region handling input from the prover
- string ReadProver()
- {
- string error = null;
- while (true) {
- if (error != null) {
- HandleError(error);
- errorCnt++;
- error = null;
- }
-
- lock (this) {
- while (proverOutput.Count == 0 && proverErrors.Count == 0 && !prover.HasExited) {
- Monitor.Wait(this, 100);
- }
-
- if (proverErrors.Count > 0) {
- error = proverErrors.Dequeue();
- continue;
- }
-
- if (proverOutput.Count > 0) {
- return proverOutput.Dequeue();
- }
-
- if (prover.HasExited) {
- DisposeProver();
- return null;
- }
- }
- }
- }
-
- void DisposeProver()
- {
- if (cancelEvent != null) {
- Console.CancelKeyPress -= cancelEvent;
- cancelEvent = null;
- }
- }
-
- void prover_OutputDataReceived(object sender, DataReceivedEventArgs e)
- {
- lock (this) {
- if (e.Data != null) {
- if (options.Verbosity >= 2 || (options.Verbosity >= 1 && !e.Data.StartsWith("(:name "))) {
- Console.WriteLine("[SMT-OUT-{0}] {1}", smtProcessId, e.Data);
- }
- proverOutput.Enqueue(e.Data);
- Monitor.Pulse(this);
- }
- }
- }
-
- void prover_ErrorDataReceived(object sender, DataReceivedEventArgs e)
- {
- lock (this) {
- if (e.Data != null) {
- if (options.Verbosity >= 1)
- Console.WriteLine("[SMT-ERR-{0}] {1}", smtProcessId, e.Data);
- proverErrors.Enqueue(e.Data);
- Monitor.Pulse(this);
- }
- }
- }
- #endregion
- }
-}
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ public class SMTLibProcess
+ {
+ readonly Process prover;
+ readonly Inspector inspector;
+ readonly SMTLibProverOptions options;
+ readonly Queue<string> proverOutput = new Queue<string>();
+ readonly Queue<string> proverErrors = new Queue<string>();
+ readonly TextWriter toProver;
+ readonly int smtProcessId;
+ static int smtProcessIdSeq = 0;
+ ConsoleCancelEventHandler cancelEvent;
+ public bool NeedsRestart;
+
+ public static ProcessStartInfo ComputerProcessStartInfo(string executable, string options)
+ {
+ return new ProcessStartInfo(executable, options)
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ RedirectStandardInput = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true
+ };
+ }
+
+ public SMTLibProcess(ProcessStartInfo psi, SMTLibProverOptions options)
+ {
+ this.options = options;
+ this.smtProcessId = smtProcessIdSeq++;
+
+ if (options.Inspector != null) {
+ this.inspector = new Inspector(options);
+ }
+
+ foreach (var arg in options.SolverArguments)
+ psi.Arguments += " " + arg;
+
+ if (cancelEvent == null && CommandLineOptions.Clo.RunningBoogieFromCommandLine) {
+ cancelEvent = new ConsoleCancelEventHandler(ControlCHandler);
+ Console.CancelKeyPress += cancelEvent;
+ }
+
+ if (options.Verbosity >= 1) {
+ Console.WriteLine("[SMT-{0}] Starting {1} {2}", smtProcessId, psi.FileName, psi.Arguments);
+ }
+
+
+ try {
+ prover = new Process();
+ prover.StartInfo = psi;
+ prover.ErrorDataReceived += prover_ErrorDataReceived;
+ prover.OutputDataReceived += prover_OutputDataReceived;
+ prover.Start();
+ toProver = prover.StandardInput;
+ prover.BeginErrorReadLine();
+ prover.BeginOutputReadLine();
+ } catch (System.ComponentModel.Win32Exception e) {
+ throw new ProverException(string.Format("Unable to start the process {0}: {1}", psi.FileName, e.Message));
+ }
+ }
+
+ [NoDefaultContract] // important, since we have no idea what state the object might be in when this handler is invoked
+ void ControlCHandler(object o, ConsoleCancelEventArgs a)
+ {
+ if (prover != null) {
+ TerminateProver();
+ }
+ }
+
+ private void TerminateProver(Int32 timeout = 2000) {
+ try {
+ // Let the prover know that we're done sending input.
+ prover.StandardInput.Close();
+
+ // Give it a chance to exit cleanly (e.g. to flush buffers)
+ if (!prover.WaitForExit(timeout)) {
+ prover.Kill();
+ }
+ } catch { /* Swallow errors */ }
+ }
+
+ public void Send(string cmd)
+ {
+ if (options.Verbosity >= 2) {
+ var log = cmd;
+ if (log.Length > 50)
+ log = log.Substring(0, 50) + "...";
+ log = log.Replace("\r", "").Replace("\n", " ");
+ Console.WriteLine("[SMT-INP-{0}] {1}", smtProcessId, log);
+ }
+ //Console.WriteLine(cmd);
+ toProver.WriteLine(cmd);
+ }
+
+ // this is less than perfect; (echo ...) would be better
+ public void Ping()
+ {
+ Send("(get-info :name)");
+ }
+
+ public bool IsPong(SExpr sx)
+ {
+ return sx != null && sx.Name == ":name";
+ }
+
+ public void PingPong()
+ {
+ Ping();
+ while (true) {
+ var sx = GetProverResponse();
+ if (sx == null) {
+ this.NeedsRestart = true;
+ HandleError("Prover died");
+ return;
+ }
+
+ if (IsPong(sx))
+ return;
+ else
+ HandleError("Invalid PING response from the prover: " + sx.ToString());
+ }
+ }
+
+ internal Inspector Inspector
+ {
+ get { return inspector; }
+ }
+
+ public SExpr GetProverResponse()
+ {
+ toProver.Flush();
+
+ while (true) {
+ var exprs = ParseSExprs(true).ToArray();
+ Contract.Assert(exprs.Length <= 1);
+ if (exprs.Length == 0)
+ return null;
+ var resp = exprs[0];
+ if (resp.Name == "error") {
+ if (resp.Arguments.Length == 1 && resp.Arguments[0].IsId)
+ HandleError(resp.Arguments[0].Name);
+ else
+ HandleError(resp.ToString());
+ } else if (resp.Name == "progress") {
+ if (inspector != null) {
+ var sb = new StringBuilder();
+ foreach (var a in resp.Arguments) {
+ if (a.Name == "labels") {
+ sb.Append("STATS LABELS");
+ foreach (var x in a.Arguments)
+ sb.Append(" ").Append(x.Name);
+ } else if (a.Name.StartsWith(":")) {
+ sb.Append("STATS NAMED_VALUES ").Append(a.Name);
+ foreach (var x in a.Arguments)
+ sb.Append(" ").Append(x.Name);
+ } else {
+ continue;
+ }
+ inspector.StatsLine(sb.ToString());
+ sb.Clear();
+ }
+ }
+ } else if (resp.Name == "unsupported") {
+ // Skip -- this may be a benign "unsupported" from a previous command.
+ // Of course, this is suboptimal. We should really be using
+ // print-success to identify the errant command and determine whether
+ // the response is benign.
+ } else {
+ return resp;
+ }
+ }
+ }
+
+ public static System.TimeSpan TotalUserTime = System.TimeSpan.Zero;
+
+ public void Close()
+ {
+ TotalUserTime += prover.UserProcessorTime;
+ TerminateProver();
+ DisposeProver();
+ }
+
+ public event Action<string> ErrorHandler;
+ int errorCnt;
+
+ private void HandleError(string msg)
+ {
+ if (options.Verbosity >= 2)
+ Console.WriteLine("[SMT-ERR-{0}] Handling error: {1}", smtProcessId, msg);
+ if (ErrorHandler != null)
+ ErrorHandler(msg);
+ }
+
+ #region SExpr parsing
+ int linePos;
+ string currLine;
+ char SkipWs()
+ {
+ while (true) {
+ if (currLine == null) {
+ currLine = ReadProver();
+ if (currLine == null)
+ return '\0';
+ }
+
+
+ while (linePos < currLine.Length && char.IsWhiteSpace(currLine[linePos]))
+ linePos++;
+
+ if (linePos < currLine.Length && currLine[linePos] != ';')
+ return currLine[linePos];
+ else {
+ currLine = null;
+ linePos = 0;
+ }
+ }
+ }
+
+ void Shift()
+ {
+ linePos++;
+ }
+
+ string ParseId()
+ {
+ var sb = new StringBuilder();
+
+ var beg = SkipWs();
+
+ var quoted = beg == '"' || beg == '|';
+ if (quoted)
+ Shift();
+ while (true) {
+ if (linePos >= currLine.Length) {
+ if (quoted) {
+ sb.Append("\n");
+ currLine = ReadProver();
+ linePos = 0;
+ if (currLine == null)
+ break;
+ } else break;
+ }
+
+ var c = currLine[linePos++];
+ if (quoted && c == beg)
+ break;
+ if (!quoted && (char.IsWhiteSpace(c) || c == '(' || c == ')')) {
+ linePos--;
+ break;
+ }
+ if (quoted && c == '\\' && linePos < currLine.Length && currLine[linePos] == '"') {
+ sb.Append('"');
+ linePos++;
+ continue;
+ }
+ sb.Append(c);
+ }
+
+ return sb.ToString();
+ }
+
+ void ParseError(string msg)
+ {
+ HandleError("Error parsing prover output: " + msg);
+ }
+
+ IEnumerable<SExpr> ParseSExprs(bool top)
+ {
+ while (true) {
+ var c = SkipWs();
+ if (c == '\0')
+ break;
+
+ if (c == ')') {
+ if (top)
+ ParseError("stray ')'");
+ break;
+ }
+
+ string id;
+
+ if (c == '(') {
+ Shift();
+ c = SkipWs();
+ if (c == '\0') {
+ ParseError("expecting something after '('");
+ break;
+ } else if (c == '(') {
+ id = "";
+ } else {
+ id = ParseId();
+ }
+
+ var args = ParseSExprs(false).ToArray();
+
+ c = SkipWs();
+ if (c == ')') {
+ Shift();
+ } else {
+ ParseError("unclosed '(" + id + "'");
+ }
+ yield return new SExpr(id, args);
+ } else {
+ id = ParseId();
+ yield return new SExpr(id);
+ }
+
+ if (top) break;
+ }
+ }
+ #endregion
+
+ #region handling input from the prover
+ string ReadProver()
+ {
+ string error = null;
+ while (true) {
+ if (error != null) {
+ HandleError(error);
+ errorCnt++;
+ error = null;
+ }
+
+ lock (this) {
+ while (proverOutput.Count == 0 && proverErrors.Count == 0 && !prover.HasExited) {
+ Monitor.Wait(this, 100);
+ }
+
+ if (proverErrors.Count > 0) {
+ error = proverErrors.Dequeue();
+ continue;
+ }
+
+ if (proverOutput.Count > 0) {
+ return proverOutput.Dequeue();
+ }
+
+ if (prover.HasExited) {
+ DisposeProver();
+ return null;
+ }
+ }
+ }
+ }
+
+ void DisposeProver()
+ {
+ if (cancelEvent != null) {
+ Console.CancelKeyPress -= cancelEvent;
+ cancelEvent = null;
+ }
+ }
+
+ void prover_OutputDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ lock (this) {
+ if (e.Data != null) {
+ if (options.Verbosity >= 2 || (options.Verbosity >= 1 && !e.Data.StartsWith("(:name "))) {
+ Console.WriteLine("[SMT-OUT-{0}] {1}", smtProcessId, e.Data);
+ }
+ proverOutput.Enqueue(e.Data);
+ Monitor.Pulse(this);
+ }
+ }
+ }
+
+ void prover_ErrorDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ lock (this) {
+ if (e.Data != null) {
+ if (options.Verbosity >= 1)
+ Console.WriteLine("[SMT-ERR-{0}] {1}", smtProcessId, e.Data);
+ proverErrors.Enqueue(e.Data);
+ Monitor.Pulse(this);
+ }
+ }
+ }
+ #endregion
+ }
+}
+
diff --git a/Source/Provers/SMTLib/SMTLibProverOptions.cs b/Source/Provers/SMTLib/SMTLibProverOptions.cs
index 0cfa65d8..5c3bed3e 100644
--- a/Source/Provers/SMTLib/SMTLibProverOptions.cs
+++ b/Source/Provers/SMTLib/SMTLibProverOptions.cs
@@ -1,158 +1,158 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.SMTLib
-{
-
- public class OptionValue
- {
- public readonly string Option;
- public readonly string Value;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Option != null);
- Contract.Invariant(Value != null);
- }
-
- public OptionValue(string option, string value)
- {
- Contract.Requires(option != null);
- Contract.Requires(value != null);
- Option = option;
- Value = value;
- }
- }
-
- public enum SolverKind { Z3, CVC4 };
-
- public class SMTLibProverOptions : ProverOptions
- {
- public bool UseWeights = true;
- public bool SupportsLabels { get { return Solver == SolverKind.Z3; } }
- public bool UseTickleBool { get { return Solver == SolverKind.Z3; } }
- public SolverKind Solver = SolverKind.Z3;
- public List<OptionValue> SmtOptions = new List<OptionValue>();
- public List<string> SolverArguments = new List<string>();
- public bool MultiTraces = false;
- public string Logic = "";
-
- // Z3 specific (at the moment; some of them make sense also for other provers)
- public string Inspector = null;
- public bool OptimizeForBv = false;
- public bool SMTLib2Model = false;
-
- public bool ProduceModel() {
- return !CommandLineOptions.Clo.UseLabels || CommandLineOptions.Clo.ExplainHoudini || CommandLineOptions.Clo.UseProverEvaluate ||
- ExpectingModel();
- }
-
- public bool ExpectingModel()
- {
- return CommandLineOptions.Clo.PrintErrorModel >= 1 ||
- CommandLineOptions.Clo.EnhancedErrorMessages == 1 ||
- CommandLineOptions.Clo.ModelViewFile != null ||
- (CommandLineOptions.Clo.StratifiedInlining > 0 && !CommandLineOptions.Clo.StratifiedInliningWithoutModels);
- }
-
- public void AddSolverArgument(string s)
- {
- SolverArguments.Add(s);
- }
-
- public void AddSmtOption(string name, string val)
- {
- SmtOptions.Add(new OptionValue(name, val));
- }
-
- public void AddWeakSmtOption(string name, string val)
- {
- if (!SmtOptions.Any(o => o.Option == name))
- SmtOptions.Add(new OptionValue(name, val));
- }
-
- public void AddSmtOption(string opt)
- {
- var idx = opt.IndexOf('=');
- if (idx <= 0 || idx == opt.Length - 1)
- ReportError("Options to be passed to the prover should have the format: O:<name>=<value>, got '" + opt + "'");
- AddSmtOption(opt.Substring(0, idx), opt.Substring(idx + 1));
- }
-
- protected override bool Parse(string opt)
- {
- string SolverStr = null;
- if (ParseString(opt, "SOLVER", ref SolverStr)) {
- switch (SolverStr) {
- case "Z3":
- case "z3":
- Solver = SolverKind.Z3;
- break;
- case "CVC4":
- case "cvc4":
- Solver = SolverKind.CVC4;
- if (Logic.Equals("")) Logic = "ALL_SUPPORTED";
- break;
- default:
- ReportError("Invalid SOLVER value; must be 'Z3' or 'CVC4'");
- return false;
- }
- return true;
- }
-
- if (opt.StartsWith("O:")) {
- AddSmtOption(opt.Substring(2));
- return true;
- }
-
- if (opt.StartsWith("C:")) {
- AddSolverArgument(opt.Substring(2));
- return true;
- }
-
- return
- ParseBool(opt, "MULTI_TRACES", ref MultiTraces) ||
- ParseBool(opt, "USE_WEIGHTS", ref UseWeights) ||
- ParseString(opt, "INSPECTOR", ref Inspector) ||
- ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
- ParseBool(opt, "SMTLIB2_MODEL", ref SMTLib2Model) ||
- ParseString(opt, "LOGIC", ref Logic) ||
- base.Parse(opt);
- }
-
- public override void PostParse()
- {
- base.PostParse();
- if (Solver == SolverKind.Z3)
- Z3.SetupOptions(this);
- }
-
- public override string Help
- {
- get
- {
- return
-@"
-SMT-specific options:
-~~~~~~~~~~~~~~~~~~~~~
-SOLVER=<string> Use the given SMT solver (z3 or cvc4; default: z3)
-USE_WEIGHTS=<bool> Pass :weight annotations on quantified formulas (default: true)
-VERBOSITY=<int> 1 - print prover output (default: 0)
-O:<name>=<value> Pass (set-option :<name> <value>) to the SMT solver.
-C:<string> Pass <string> to the SMT on the command line.
-LOGIC=<string> Pass (set-logic <string>) to the prover (default: empty, 'ALL_SUPPORTED' for CVC4)
-
-Z3-specific options:
-~~~~~~~~~~~~~~~~~~~~
-MULTI_TRACES=<bool> Report errors with multiple paths leading to the same assertion.
-INSPECTOR=<string> Use the specified Z3Inspector binary.
-OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
-SMTLIB2_MODEL=<bool> Use the SMTLIB2 output model. Defaults to false.
-" + base.Help;
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Boogie.SMTLib
+{
+
+ public class OptionValue
+ {
+ public readonly string Option;
+ public readonly string Value;
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(Option != null);
+ Contract.Invariant(Value != null);
+ }
+
+ public OptionValue(string option, string value)
+ {
+ Contract.Requires(option != null);
+ Contract.Requires(value != null);
+ Option = option;
+ Value = value;
+ }
+ }
+
+ public enum SolverKind { Z3, CVC4 };
+
+ public class SMTLibProverOptions : ProverOptions
+ {
+ public bool UseWeights = true;
+ public bool SupportsLabels { get { return Solver == SolverKind.Z3; } }
+ public bool UseTickleBool { get { return Solver == SolverKind.Z3; } }
+ public SolverKind Solver = SolverKind.Z3;
+ public List<OptionValue> SmtOptions = new List<OptionValue>();
+ public List<string> SolverArguments = new List<string>();
+ public bool MultiTraces = false;
+ public string Logic = "";
+
+ // Z3 specific (at the moment; some of them make sense also for other provers)
+ public string Inspector = null;
+ public bool OptimizeForBv = false;
+ public bool SMTLib2Model = false;
+
+ public bool ProduceModel() {
+ return !CommandLineOptions.Clo.UseLabels || CommandLineOptions.Clo.ExplainHoudini || CommandLineOptions.Clo.UseProverEvaluate ||
+ ExpectingModel();
+ }
+
+ public bool ExpectingModel()
+ {
+ return CommandLineOptions.Clo.PrintErrorModel >= 1 ||
+ CommandLineOptions.Clo.EnhancedErrorMessages == 1 ||
+ CommandLineOptions.Clo.ModelViewFile != null ||
+ (CommandLineOptions.Clo.StratifiedInlining > 0 && !CommandLineOptions.Clo.StratifiedInliningWithoutModels);
+ }
+
+ public void AddSolverArgument(string s)
+ {
+ SolverArguments.Add(s);
+ }
+
+ public void AddSmtOption(string name, string val)
+ {
+ SmtOptions.Add(new OptionValue(name, val));
+ }
+
+ public void AddWeakSmtOption(string name, string val)
+ {
+ if (!SmtOptions.Any(o => o.Option == name))
+ SmtOptions.Add(new OptionValue(name, val));
+ }
+
+ public void AddSmtOption(string opt)
+ {
+ var idx = opt.IndexOf('=');
+ if (idx <= 0 || idx == opt.Length - 1)
+ ReportError("Options to be passed to the prover should have the format: O:<name>=<value>, got '" + opt + "'");
+ AddSmtOption(opt.Substring(0, idx), opt.Substring(idx + 1));
+ }
+
+ protected override bool Parse(string opt)
+ {
+ string SolverStr = null;
+ if (ParseString(opt, "SOLVER", ref SolverStr)) {
+ switch (SolverStr) {
+ case "Z3":
+ case "z3":
+ Solver = SolverKind.Z3;
+ break;
+ case "CVC4":
+ case "cvc4":
+ Solver = SolverKind.CVC4;
+ if (Logic.Equals("")) Logic = "ALL_SUPPORTED";
+ break;
+ default:
+ ReportError("Invalid SOLVER value; must be 'Z3' or 'CVC4'");
+ return false;
+ }
+ return true;
+ }
+
+ if (opt.StartsWith("O:")) {
+ AddSmtOption(opt.Substring(2));
+ return true;
+ }
+
+ if (opt.StartsWith("C:")) {
+ AddSolverArgument(opt.Substring(2));
+ return true;
+ }
+
+ return
+ ParseBool(opt, "MULTI_TRACES", ref MultiTraces) ||
+ ParseBool(opt, "USE_WEIGHTS", ref UseWeights) ||
+ ParseString(opt, "INSPECTOR", ref Inspector) ||
+ ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
+ ParseBool(opt, "SMTLIB2_MODEL", ref SMTLib2Model) ||
+ ParseString(opt, "LOGIC", ref Logic) ||
+ base.Parse(opt);
+ }
+
+ public override void PostParse()
+ {
+ base.PostParse();
+ if (Solver == SolverKind.Z3)
+ Z3.SetupOptions(this);
+ }
+
+ public override string Help
+ {
+ get
+ {
+ return
+@"
+SMT-specific options:
+~~~~~~~~~~~~~~~~~~~~~
+SOLVER=<string> Use the given SMT solver (z3 or cvc4; default: z3)
+USE_WEIGHTS=<bool> Pass :weight annotations on quantified formulas (default: true)
+VERBOSITY=<int> 1 - print prover output (default: 0)
+O:<name>=<value> Pass (set-option :<name> <value>) to the SMT solver.
+C:<string> Pass <string> to the SMT on the command line.
+LOGIC=<string> Pass (set-logic <string>) to the prover (default: empty, 'ALL_SUPPORTED' for CVC4)
+
+Z3-specific options:
+~~~~~~~~~~~~~~~~~~~~
+MULTI_TRACES=<bool> Report errors with multiple paths leading to the same assertion.
+INSPECTOR=<string> Use the specified Z3Inspector binary.
+OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
+SMTLIB2_MODEL=<bool> Use the SMTLIB2 output model. Defaults to false.
+" + base.Help;
+ }
+ }
+ }
+}
diff --git a/Source/Provers/SMTLib/TypeDeclCollector.cs b/Source/Provers/SMTLib/TypeDeclCollector.cs
index 2b053410..d7c56d90 100644
--- a/Source/Provers/SMTLib/TypeDeclCollector.cs
+++ b/Source/Provers/SMTLib/TypeDeclCollector.cs
@@ -1,395 +1,410 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.SMTLib
-{
- // Visitor for collecting the occurring function symbols in a VCExpr,
- // and for creating the corresponding declarations
-
- public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
-
- private readonly UniqueNamer Namer;
- private readonly SMTLibProverOptions Options;
- private HashSet<Function/*!*/>/*!*/ RegisteredRelations = new HashSet<Function>();
-
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(Namer!=null);
- Contract.Invariant(AllDecls != null);
- Contract.Invariant(IncDecls != null);
- Contract.Invariant(KnownFunctions != null);
- Contract.Invariant(KnownVariables != null);
-}
-
-
- public TypeDeclCollector(SMTLibProverOptions opts, UniqueNamer namer) {
- Contract.Requires(namer != null);
- this.Namer = namer;
- this.Options = opts;
- InitializeKnownDecls();
- }
-
- // not used
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true;
- }
-
- private readonly List<string/*!>!*/> AllDecls = new List<string/*!*/> ();
- private readonly List<string/*!>!*/> IncDecls = new List<string/*!*/> ();
-
- // In order to support push/pop interface of the theorem prover, the "known" declarations
- // must be kept in a stack
-
- private HashSet<Function/*!*/>/*!*/ KnownFunctions
- {
- get { return _KnownFunctions.Peek(); }
- }
-
- private HashSet<VCExprVar/*!*/>/*!*/ KnownVariables
- {
- get { return _KnownVariables.Peek(); }
- }
-
- private HashSet<Type/*!*/>/*!*/ KnownTypes
- {
- get { return _KnownTypes.Peek(); }
- }
-
- private HashSet<string/*!*/>/*!*/ KnownStoreFunctions
- {
- get { return _KnownStoreFunctions.Peek(); }
- }
-
- private HashSet<string/*!*/>/*!*/ KnownSelectFunctions
- {
- get { return _KnownSelectFunctions.Peek(); }
- }
-
- private HashSet<string> KnownLBL
- {
- get { return _KnownLBL.Peek(); }
- }
-
- // ------
- private readonly Stack<HashSet<Function/*!*/>/*!*/> _KnownFunctions = new Stack<HashSet<Function/*!*/>>();
- private readonly Stack<HashSet<VCExprVar/*!*/>/*!*/> _KnownVariables = new Stack<HashSet<VCExprVar/*!*/>>();
-
- private readonly Stack<HashSet<Type/*!*/>/*!*/> _KnownTypes = new Stack<HashSet<Type>>();
- private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownStoreFunctions = new Stack<HashSet<string>>();
- private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownSelectFunctions = new Stack<HashSet<string>>();
- private readonly Stack<HashSet<string>> _KnownLBL = new Stack<HashSet<string>>();
-
- // lets RPFP checker capture decls
- public abstract class DeclHandler {
- public abstract void VarDecl(VCExprVar v);
- public abstract void FuncDecl(Function f);
- }
-
- private DeclHandler declHandler = null;
-
- public void SetDeclHandler(DeclHandler _d){
- declHandler = _d;
- }
-
- private void InitializeKnownDecls()
- {
- _KnownFunctions.Push(new HashSet<Function>());
- _KnownVariables.Push(new HashSet<VCExprVar>());
- _KnownTypes.Push(new HashSet<Type>());
- _KnownStoreFunctions.Push(new HashSet<string>());
- _KnownSelectFunctions.Push(new HashSet<string>());
- _KnownLBL.Push(new HashSet<string>());
- }
-
- public void Reset()
- {
- _KnownFunctions.Clear();
- _KnownVariables.Clear();
- _KnownTypes.Clear();
- _KnownStoreFunctions.Clear();
- _KnownSelectFunctions.Clear();
- _KnownLBL.Clear();
- AllDecls.Clear();
- IncDecls.Clear();
- InitializeKnownDecls();
- }
-
- public void Push()
- {
- Contract.Assert(_KnownFunctions.Count > 0);
- _KnownFunctions.Push(new HashSet<Function>(_KnownFunctions.Peek()));
- _KnownVariables.Push(new HashSet<VCExprVar>(_KnownVariables.Peek()));
- _KnownTypes.Push(new HashSet<Type>(_KnownTypes.Peek()));
- _KnownStoreFunctions.Push(new HashSet<string>(_KnownStoreFunctions.Peek()));
- _KnownSelectFunctions.Push(new HashSet<string>(_KnownSelectFunctions.Peek()));
- _KnownLBL.Push(new HashSet<string>(_KnownLBL.Peek()));
- }
-
- public void Pop()
- {
- Contract.Assert(_KnownFunctions.Count > 1);
- _KnownFunctions.Pop();
- _KnownVariables.Pop();
- _KnownTypes.Pop();
- _KnownStoreFunctions.Pop();
- _KnownSelectFunctions.Pop();
- _KnownLBL.Pop();
- }
-
- public List<string/*!>!*/> AllDeclarations { get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
-
- List<string>/*!>!*/ res = new List<string/*!*/> ();
- res.AddRange(AllDecls);
- return res;
- } }
-
- public List<string/*!>!*/> GetNewDeclarations() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
- List<string>/*!>!*/ res = new List<string/*!*/>();
- res.AddRange(IncDecls);
- IncDecls.Clear();
- return res;
- }
-
- private void AddDeclaration(string decl) {
- Contract.Requires(decl != null);
- AllDecls.Add(decl);
- IncDecls.Add(decl);
- }
-
- public void Collect(VCExpr expr) {
- Contract.Requires(expr != null);
- Traverse(expr, true);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- private static string TypeToString(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- return SMTLibExprLineariser.TypeToString(t);
- }
-
- public string TypeToStringReg(Type t)
- {
- RegisterType(t);
- return TypeToString(t);
- }
-
- public void AddFunction(Function func) {
- if (KnownFunctions.Contains(func))
- return;
- KnownFunctions.Add(func);
- if(declHandler != null)
- declHandler.FuncDecl(func);
- }
-
- public void RegisterRelation(Function func)
- {
- if (RegisteredRelations.Contains(func))
- return;
- RegisteredRelations.Add(func);
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
-
- if (node.Op is VCExprStoreOp) RegisterStore(node);
- else if (node.Op is VCExprSelectOp) RegisterSelect(node);
- else {
- VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
- if (op != null &&
- !(op.Func is DatatypeConstructor) && !(op.Func is DatatypeMembership) && !(op.Func is DatatypeSelector) &&
- !KnownFunctions.Contains(op.Func)) {
- Function f = op.Func;
- Contract.Assert(f != null);
-
- var builtin = SMTLibExprLineariser.ExtractBuiltin(f);
- if (builtin == null) {
- string printedName = Namer.GetQuotedName(f, f.Name);
- Contract.Assert(printedName != null);
-
- Contract.Assert(f.OutParams.Count == 1);
- var argTypes = f.InParams.Cast<Variable>().MapConcat(p => TypeToStringReg(p.TypedIdent.Type), " ");
- string decl;
- if(RegisteredRelations.Contains(op.Func))
- decl = "(declare-rel " + printedName + " (" + argTypes + ") " + ")";
- else
- decl = "(declare-fun " + printedName + " (" + argTypes + ") " + TypeToStringReg(f.OutParams[0].TypedIdent.Type) + ")";
- AddDeclaration(decl);
- }
- KnownFunctions.Add(f);
- } else {
- var lab = node.Op as VCExprLabelOp;
- if (lab != null && !KnownLBL.Contains(lab.label)) {
- KnownLBL.Add(lab.label);
- var name = SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(lab.label));
- AddDeclaration("(declare-fun " + name + " () Bool)");
- }
- }
- }
-
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node) && !KnownVariables.Contains(node)) {
- string printedName = Namer.GetQuotedName(node, node.Name);
- Contract.Assert(printedName!=null);
- RegisterType(node.Type);
- string decl =
- "(declare-fun " + printedName + " () " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
- KnownVariables.Add(node);
- if(declHandler != null)
- declHandler.VarDecl(node);
- }
-
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprQuantifier node, bool arg)
- {
- Contract.Requires(node != null);
- foreach (VCExprVar v in node.BoundVars) {
- Contract.Assert(v != null);
- RegisterType(v.Type);
- }
-
- return base.Visit(node, arg);
- }
-
- private void RegisterType(Type type)
- {
- Contract.Requires(type != null);
- if (KnownTypes.Contains(type)) return;
-
- if (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays) {
- KnownTypes.Add(type);
- MapType mapType = type.AsMap;
- Contract.Assert(mapType != null);
-
- foreach (Type t in mapType.Arguments) {
- Contract.Assert(t != null);
- RegisterType(t);
- }
- RegisterType(mapType.Result);
-
- if (!CommandLineOptions.Clo.UseArrayTheory)
- AddDeclaration("(declare-sort " + TypeToString(type) + " 0)");
-
- return;
- }
-
- if (type.IsBool || type.IsInt || type.IsReal || type.IsFloat || type.IsBv)
- return;
-
- CtorType ctorType = type as CtorType;
- if (ctorType != null && ctorType.IsDatatype())
- return;
-
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic) {
- AddDeclaration("(declare-sort " + TypeToString(type) + " 0)");
- KnownTypes.Add(type);
- return;
- }
- }
-
- private void RegisterSelect(VCExprNAry node)
- {
- RegisterType(node[0].Type);
-
- if (CommandLineOptions.Clo.UseArrayTheory)
- return;
-
- string name = SimplifyLikeExprLineariser.SelectOpName(node);
- name = Namer.GetQuotedName(name, name);
-
- if (!KnownSelectFunctions.Contains(name)) {
- string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
- KnownSelectFunctions.Add(name);
- }
- }
-
- private void RegisterStore(VCExprNAry node)
- {
- RegisterType(node.Type); // this is the map type, registering it should register also the index and value types
-
- if (CommandLineOptions.Clo.UseArrayTheory)
- return;
-
- string name = SimplifyLikeExprLineariser.StoreOpName(node);
- name = Namer.GetQuotedName(name, name);
-
- if (!KnownStoreFunctions.Contains(name)) {
- string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
-
- if (CommandLineOptions.Clo.MonomorphicArrays) {
- var sel = SimplifyLikeExprLineariser.SelectOpName(node);
- sel = Namer.GetQuotedName(sel, sel);
-
- if (!KnownSelectFunctions.Contains(sel)) {
- // need to declare it before reference
- var args = node.SkipEnd(1);
- var ret = node.Last();
- string seldecl = "(declare-fun " + sel + " (" + args.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(ret.Type) + ")";
- AddDeclaration(seldecl);
- KnownSelectFunctions.Add(sel);
- }
-
- string ax1 = "(assert (forall (";
- string ax2 = "(assert (forall (";
-
- string argX = "", argY = "";
- string dist = "";
- for (int i = 0; i < node.Arity; i++) {
- var t = " " + TypeToString(node[i].Type);
- var x = " ?x" + i;
- var y = " ?y" + i;
- ax1 += " (" + x + t + ")";
- ax2 += " (" + x + t + ")";
- if (i != 0 && i != node.Arity - 1) {
- argX += x;
- argY += y;
- ax2 += " (" + y + t + ")";
- dist += " (not (=" + x + y + "))";
- }
- }
- string v = " ?x" + (node.Arity - 1);
- ax1 += ") (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argX + ") " + v + ")";
- ax1 += "))";
-
- if (node.Arity > 3)
- dist = "(or " + dist + ")";
- ax2 += ") (=> " + dist + " (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argY + ") (" + sel + " ?x0" + argY + ")))";
- ax2 += "))";
-
- AddDeclaration(ax1);
- AddDeclaration(ax2);
- }
-
- KnownStoreFunctions.Add(name);
- }
- //
- }
-
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ // Visitor for collecting the occurring function symbols in a VCExpr,
+ // and for creating the corresponding declarations
+
+ public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+
+ private readonly UniqueNamer Namer;
+ private readonly SMTLibProverOptions Options;
+ private HashSet<Function/*!*/>/*!*/ RegisteredRelations = new HashSet<Function>();
+
+ [ContractInvariantMethod]
+void ObjectInvariant()
+{
+ Contract.Invariant(Namer!=null);
+ Contract.Invariant(AllDecls != null);
+ Contract.Invariant(IncDecls != null);
+ Contract.Invariant(KnownFunctions != null);
+ Contract.Invariant(KnownVariables != null);
+}
+
+
+ public TypeDeclCollector(SMTLibProverOptions opts, UniqueNamer namer) {
+ Contract.Requires(namer != null);
+ this.Namer = namer;
+ this.Options = opts;
+ InitializeKnownDecls();
+ }
+
+ // not used
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return true;
+ }
+
+ private readonly List<string/*!>!*/> AllDecls = new List<string/*!*/> ();
+ private readonly List<string/*!>!*/> IncDecls = new List<string/*!*/> ();
+
+ // In order to support push/pop interface of the theorem prover, the "known" declarations
+ // must be kept in a stack
+
+ private HashSet<Function/*!*/>/*!*/ KnownFunctions
+ {
+ get { return _KnownFunctions.Peek(); }
+ }
+
+ private HashSet<VCExprVar/*!*/>/*!*/ KnownVariables
+ {
+ get { return _KnownVariables.Peek(); }
+ }
+
+ private HashSet<Type/*!*/>/*!*/ KnownTypes
+ {
+ get { return _KnownTypes.Peek(); }
+ }
+
+ private HashSet<string/*!*/>/*!*/ KnownStoreFunctions
+ {
+ get { return _KnownStoreFunctions.Peek(); }
+ }
+
+ private HashSet<string/*!*/>/*!*/ KnownSelectFunctions
+ {
+ get { return _KnownSelectFunctions.Peek(); }
+ }
+
+ private HashSet<string> KnownLBL
+ {
+ get { return _KnownLBL.Peek(); }
+ }
+
+ // ------
+ private readonly Stack<HashSet<Function/*!*/>/*!*/> _KnownFunctions = new Stack<HashSet<Function/*!*/>>();
+ private readonly Stack<HashSet<VCExprVar/*!*/>/*!*/> _KnownVariables = new Stack<HashSet<VCExprVar/*!*/>>();
+
+ private readonly Stack<HashSet<Type/*!*/>/*!*/> _KnownTypes = new Stack<HashSet<Type>>();
+ private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownStoreFunctions = new Stack<HashSet<string>>();
+ private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownSelectFunctions = new Stack<HashSet<string>>();
+ private readonly Stack<HashSet<string>> _KnownLBL = new Stack<HashSet<string>>();
+
+ // lets RPFP checker capture decls
+ public abstract class DeclHandler {
+ public abstract void VarDecl(VCExprVar v);
+ public abstract void FuncDecl(Function f);
+ }
+
+ private DeclHandler declHandler = null;
+
+ public void SetDeclHandler(DeclHandler _d){
+ declHandler = _d;
+ }
+
+ private void InitializeKnownDecls()
+ {
+ _KnownFunctions.Push(new HashSet<Function>());
+ _KnownVariables.Push(new HashSet<VCExprVar>());
+ _KnownTypes.Push(new HashSet<Type>());
+ _KnownStoreFunctions.Push(new HashSet<string>());
+ _KnownSelectFunctions.Push(new HashSet<string>());
+ _KnownLBL.Push(new HashSet<string>());
+ }
+
+ public void Reset()
+ {
+ _KnownFunctions.Clear();
+ _KnownVariables.Clear();
+ _KnownTypes.Clear();
+ _KnownStoreFunctions.Clear();
+ _KnownSelectFunctions.Clear();
+ _KnownLBL.Clear();
+ AllDecls.Clear();
+ IncDecls.Clear();
+ InitializeKnownDecls();
+ }
+
+ public void Push()
+ {
+ Contract.Assert(_KnownFunctions.Count > 0);
+ _KnownFunctions.Push(new HashSet<Function>(_KnownFunctions.Peek()));
+ _KnownVariables.Push(new HashSet<VCExprVar>(_KnownVariables.Peek()));
+ _KnownTypes.Push(new HashSet<Type>(_KnownTypes.Peek()));
+ _KnownStoreFunctions.Push(new HashSet<string>(_KnownStoreFunctions.Peek()));
+ _KnownSelectFunctions.Push(new HashSet<string>(_KnownSelectFunctions.Peek()));
+ _KnownLBL.Push(new HashSet<string>(_KnownLBL.Peek()));
+ }
+
+ public void Pop()
+ {
+ Contract.Assert(_KnownFunctions.Count > 1);
+ _KnownFunctions.Pop();
+ _KnownVariables.Pop();
+ _KnownTypes.Pop();
+ _KnownStoreFunctions.Pop();
+ _KnownSelectFunctions.Pop();
+ _KnownLBL.Pop();
+ }
+
+ public List<string/*!>!*/> AllDeclarations { get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
+
+ List<string>/*!>!*/ res = new List<string/*!*/> ();
+ res.AddRange(AllDecls);
+ return res;
+ } }
+
+ public List<string/*!>!*/> GetNewDeclarations() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
+ List<string>/*!>!*/ res = new List<string/*!*/>();
+ res.AddRange(IncDecls);
+ IncDecls.Clear();
+ return res;
+ }
+
+ private void AddDeclaration(string decl) {
+ Contract.Requires(decl != null);
+ AllDecls.Add(decl);
+ IncDecls.Add(decl);
+ }
+
+ public void Collect(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Traverse(expr, true);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ private static string TypeToString(Type t) {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return SMTLibExprLineariser.TypeToString(t);
+ }
+
+ public string TypeToStringReg(Type t)
+ {
+ RegisterType(t);
+ return TypeToString(t);
+ }
+
+ public void AddFunction(Function func) {
+ if (KnownFunctions.Contains(func))
+ return;
+ KnownFunctions.Add(func);
+ if(declHandler != null)
+ declHandler.FuncDecl(func);
+ }
+
+ public void RegisterRelation(Function func)
+ {
+ if (RegisteredRelations.Contains(func))
+ return;
+ RegisteredRelations.Add(func);
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+
+ if (node.Op is VCExprStoreOp) RegisterStore(node);
+ else if (node.Op is VCExprSelectOp) RegisterSelect(node);
+ else if (node.Op is VCExprSoftOp) {
+ var exprVar = node[0] as VCExprVar;
+ AddDeclaration(string.Format("(declare-fun {0} () Bool)", exprVar.Name));
+ AddDeclaration(string.Format("(assert-soft {0} :weight {1})", exprVar.Name, ((VCExprSoftOp)node.Op).Weight));
+ } else if (node.Op.Equals(VCExpressionGenerator.NamedAssumeOp)) {
+ var exprVar = node[0] as VCExprVar;
+ AddDeclaration(string.Format("(declare-fun {0} () Bool)", exprVar.Name));
+ if (CommandLineOptions.Clo.PrintNecessaryAssumes)
+ {
+ AddDeclaration(string.Format("(assert (! {0} :named {1}))", exprVar.Name, "aux$$" + exprVar.Name));
+ }
+ } else {
+ VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
+ if (op != null &&
+ !(op.Func is DatatypeConstructor) && !(op.Func is DatatypeMembership) && !(op.Func is DatatypeSelector) &&
+ !KnownFunctions.Contains(op.Func)) {
+ Function f = op.Func;
+ Contract.Assert(f != null);
+
+ var builtin = SMTLibExprLineariser.ExtractBuiltin(f);
+ if (builtin == null) {
+ string printedName = Namer.GetQuotedName(f, f.Name);
+ Contract.Assert(printedName != null);
+
+ Contract.Assert(f.OutParams.Count == 1);
+ var argTypes = f.InParams.Cast<Variable>().MapConcat(p => TypeToStringReg(p.TypedIdent.Type), " ");
+ string decl;
+ if(RegisteredRelations.Contains(op.Func))
+ decl = "(declare-rel " + printedName + " (" + argTypes + ") " + ")";
+ else
+ decl = "(declare-fun " + printedName + " (" + argTypes + ") " + TypeToStringReg(f.OutParams[0].TypedIdent.Type) + ")";
+ AddDeclaration(decl);
+ if (declHandler != null) declHandler.FuncDecl(f);
+ }
+ KnownFunctions.Add(f);
+ } else {
+ var lab = node.Op as VCExprLabelOp;
+ if (lab != null && !KnownLBL.Contains(lab.label)) {
+ KnownLBL.Add(lab.label);
+ var name = SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(lab.label));
+ AddDeclaration("(declare-fun " + name + " () Bool)");
+ }
+ }
+ }
+
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!BoundTermVars.Contains(node) && !KnownVariables.Contains(node)) {
+ string printedName = Namer.GetQuotedName(node, node.Name);
+ Contract.Assert(printedName!=null);
+ RegisterType(node.Type);
+ string decl =
+ "(declare-fun " + printedName + " () " + TypeToString(node.Type) + ")";
+ if (!(printedName.StartsWith("assume$$") || printedName.StartsWith("soft$$") || printedName.StartsWith("try$$")))
+ {
+ AddDeclaration(decl);
+ }
+ KnownVariables.Add(node);
+ if(declHandler != null)
+ declHandler.VarDecl(node);
+ }
+
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprQuantifier node, bool arg)
+ {
+ Contract.Requires(node != null);
+ foreach (VCExprVar v in node.BoundVars) {
+ Contract.Assert(v != null);
+ RegisterType(v.Type);
+ }
+
+ return base.Visit(node, arg);
+ }
+
+ private void RegisterType(Type type)
+ {
+ Contract.Requires(type != null);
+ if (KnownTypes.Contains(type)) return;
+
+ if (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays) {
+ KnownTypes.Add(type);
+ MapType mapType = type.AsMap;
+ Contract.Assert(mapType != null);
+
+ foreach (Type t in mapType.Arguments) {
+ Contract.Assert(t != null);
+ RegisterType(t);
+ }
+ RegisterType(mapType.Result);
+
+ if (!CommandLineOptions.Clo.UseArrayTheory)
+ AddDeclaration("(declare-sort " + TypeToString(type) + " 0)");
+
+ return;
+ }
+
+ if (type.IsBool || type.IsInt || type.IsReal || type.IsFloat || type.IsBv)
+ return;
+
+ CtorType ctorType = type as CtorType;
+ if (ctorType != null && ctorType.IsDatatype())
+ return;
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic) {
+ AddDeclaration("(declare-sort " + TypeToString(type) + " 0)");
+ KnownTypes.Add(type);
+ return;
+ }
+ }
+
+ private void RegisterSelect(VCExprNAry node)
+ {
+ RegisterType(node[0].Type);
+
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ return;
+
+ string name = SimplifyLikeExprLineariser.SelectOpName(node);
+ name = Namer.GetQuotedName(name, name);
+
+ if (!KnownSelectFunctions.Contains(name)) {
+ string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")";
+ AddDeclaration(decl);
+ KnownSelectFunctions.Add(name);
+ }
+ }
+
+ private void RegisterStore(VCExprNAry node)
+ {
+ RegisterType(node.Type); // this is the map type, registering it should register also the index and value types
+
+ if (CommandLineOptions.Clo.UseArrayTheory)
+ return;
+
+ string name = SimplifyLikeExprLineariser.StoreOpName(node);
+ name = Namer.GetQuotedName(name, name);
+
+ if (!KnownStoreFunctions.Contains(name)) {
+ string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")";
+ AddDeclaration(decl);
+
+ if (CommandLineOptions.Clo.MonomorphicArrays) {
+ var sel = SimplifyLikeExprLineariser.SelectOpName(node);
+ sel = Namer.GetQuotedName(sel, sel);
+
+ if (!KnownSelectFunctions.Contains(sel)) {
+ // need to declare it before reference
+ var args = node.SkipEnd(1);
+ var ret = node.Last();
+ string seldecl = "(declare-fun " + sel + " (" + args.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(ret.Type) + ")";
+ AddDeclaration(seldecl);
+ KnownSelectFunctions.Add(sel);
+ }
+
+ string ax1 = "(assert (forall (";
+ string ax2 = "(assert (forall (";
+
+ string argX = "", argY = "";
+ string dist = "";
+ for (int i = 0; i < node.Arity; i++) {
+ var t = " " + TypeToString(node[i].Type);
+ var x = " ?x" + i;
+ var y = " ?y" + i;
+ ax1 += " (" + x + t + ")";
+ ax2 += " (" + x + t + ")";
+ if (i != 0 && i != node.Arity - 1) {
+ argX += x;
+ argY += y;
+ ax2 += " (" + y + t + ")";
+ dist += " (not (=" + x + y + "))";
+ }
+ }
+ string v = " ?x" + (node.Arity - 1);
+ ax1 += ") (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argX + ") " + v + ")";
+ ax1 += "))";
+
+ if (node.Arity > 3)
+ dist = "(or " + dist + ")";
+ ax2 += ") (=> " + dist + " (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argY + ") (" + sel + " ?x0" + argY + ")))";
+ ax2 += "))";
+
+ AddDeclaration(ax1);
+ AddDeclaration(ax2);
+ }
+
+ KnownStoreFunctions.Add(name);
+ }
+ //
+ }
+
+ }
+
} \ No newline at end of file
diff --git a/Source/Provers/SMTLib/Z3.cs b/Source/Provers/SMTLib/Z3.cs
index 250e04c9..f4bbbd6d 100644
--- a/Source/Provers/SMTLib/Z3.cs
+++ b/Source/Provers/SMTLib/Z3.cs
@@ -1,385 +1,387 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.Boogie.SMTLib
-{
- class Z3
- {
- static string _proverPath;
-
- static string CodebaseString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
- }
-
- public static string ExecutablePath()
- {
- if (_proverPath == null)
- FindExecutable();
- return _proverPath;
- }
-
- static void FindExecutable()
- // throws ProverException, System.IO.FileNotFoundException;
- {
- Contract.Ensures(_proverPath != null);
-
- // Command line option 'z3exe' always has priority if set
- if (CommandLineOptions.Clo.Z3ExecutablePath != null)
- {
- _proverPath = CommandLineOptions.Clo.Z3ExecutablePath;
- if (!File.Exists(_proverPath))
- {
- throw new ProverException("Cannot find prover specified with z3exe: " + _proverPath);
- }
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
-
- var proverExe = "z3.exe";
-
- if (_proverPath == null)
- {
- // Initialize '_proverPath'
- _proverPath = Path.Combine(CodebaseString(), proverExe);
- string firstTry = _proverPath;
-
- if (File.Exists(firstTry))
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
-
- List<string> z3Dirs = new List<string>();
- var msrDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Research\");
- if (Directory.Exists(msrDir))
- {
- z3Dirs.AddRange(Directory.GetDirectories(msrDir, "Z3-*"));
- }
- var msrDirX86 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Research\");
- if (Directory.Exists(msrDirX86))
- {
- z3Dirs.AddRange(Directory.GetDirectories(msrDirX86, "Z3-*"));
- }
-
- int minMajor = 3, minMinor = 2;
-
- // Look for the most recent version of Z3.
- int minor = 0, major = 0;
- string winner = null;
- Regex r = new Regex(@"^Z3-(\d+)\.(\d+)$");
- foreach (string d in z3Dirs)
- {
- string name = new DirectoryInfo(d).Name;
- foreach (Match m in r.Matches(name))
- {
- int ma, mi;
- ma = int.Parse(m.Groups[1].ToString());
- mi = int.Parse(m.Groups[2].ToString());
- if (major < ma || (major == ma && minor < mi))
- {
- major = ma;
- minor = mi;
- winner = d;
- }
- }
- }
-
- if (major == 0 && minor == 0)
- {
- throw new ProverException("Cannot find executable: " + firstTry);
- }
-
- Contract.Assert(winner != null);
-
- _proverPath = Path.Combine(Path.Combine(winner, "bin"), proverExe);
- if (!File.Exists(_proverPath))
- {
- throw new ProverException("Cannot find prover: " + _proverPath);
- }
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
-
- if (major < minMajor || (major == minMajor && minor < minMinor))
- {
- throw new ProverException(string.Format("Found version {0}.{1} of Z3. Please install version {2}.{3} or later. " +
- "(More conservative users might opt to supply -prover:Z3 option instead to get the historic Simplify back-end)",
- major, minor, minMajor, minMinor));
- }
- }
- }
-
-
- static int Z3MajorVersion = 0;
- static int Z3MinorVersion = 0;
- static bool Z3VersionObtained = false;
-
- public static void GetVersion(out int major, out int minor)
- {
- if (!Z3VersionObtained)
- {
- var proc = new System.Diagnostics.Process();
- proc.StartInfo.FileName = _proverPath;
- proc.StartInfo.Arguments = "--version";
- proc.StartInfo.RedirectStandardOutput = true;
- proc.StartInfo.RedirectStandardError = true;
- proc.StartInfo.UseShellExecute = false;
- proc.StartInfo.CreateNoWindow = true;
- proc.Start();
- string answer = proc.StandardOutput.ReadToEnd();
- proc.WaitForExit();
- if (proc.ExitCode == 0)
- {
- var firstdot = answer.IndexOf('.');
- if (firstdot >= 0)
- {
- var seconddot = answer.IndexOf('.', firstdot + 1);
- if (seconddot >= firstdot + 1)
- {
- var spacebeforefirstdot = answer.LastIndexOf(' ', firstdot);
- if (spacebeforefirstdot >= 0)
- {
- var majorstr = answer.Substring(spacebeforefirstdot, firstdot - spacebeforefirstdot);
- var minorstr = answer.Substring(firstdot + 1, seconddot - firstdot - 1);
- Z3MajorVersion = Convert.ToInt32(majorstr);
- Z3MinorVersion = Convert.ToInt32(minorstr);
- }
- }
- }
- }
- Z3VersionObtained = true;
- }
- major = Z3MajorVersion;
- minor = Z3MinorVersion;
- }
-
- public static string SetTimeoutOption()
- {
- int major, minor;
- GetVersion(out major, out minor);
- if (major > 4 || major == 4 && minor >= 3)
- return "TIMEOUT";
- else
- return "SOFT_TIMEOUT";
- }
-
- // options that work only on the command line
- static string[] commandLineOnly = { "TRACE", "PROOF_MODE" };
-
-
- public static void SetupOptions(SMTLibProverOptions options)
- {
- FindExecutable();
- int major, minor;
- GetVersion(out major, out minor);
- if (major > 4 || major == 4 && minor >= 3)
- {
-
- bool fp = false; // CommandLineOptions.Clo.FixedPointEngine != null;
-
- // don't bother with auto-config - it would disable explicit settings for eager threshold and so on
- if(!fp) options.AddWeakSmtOption("AUTO_CONFIG", "false");
-
- //options.AddWeakSmtOption("MODEL_PARTIAL", "true");
- //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false");
-
- // options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false"); TODO: what does this do?
-
- // Make sure we get something that is parsable as a bitvector
- options.AddWeakSmtOption("pp.bv_literals", "false");
- if (!CommandLineOptions.Clo.UseSmtOutputFormat)
- {
- options.AddWeakSmtOption("MODEL.V2", "true");
- }
- //options.AddWeakSmtOption("ASYNC_COMMANDS", "false"); TODO: is this needed?
-
- if (!options.OptimizeForBv)
- {
- // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
- // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
- options.AddWeakSmtOption("smt.PHASE_SELECTION", "0");
- options.AddWeakSmtOption("smt.RESTART_STRATEGY", "0");
- options.AddWeakSmtOption("smt.RESTART_FACTOR", "|1.5|");
-
- // Make the integer model more diverse by default, speeds up some benchmarks a lot.
- options.AddWeakSmtOption("smt.ARITH.RANDOM_INITIAL_VALUE", "true");
-
- // The left-to-right structural case-splitting strategy.
- //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now
-
- if (!fp) options.AddWeakSmtOption("smt.CASE_SPLIT", "3");
-
- // In addition delay adding unit conflicts.
- options.AddWeakSmtOption("smt.DELAY_UNITS", "true");
- //options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16"); TODO: what?
- }
-
- // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
- // the foo(x0) will be activated for e-matching when x is skolemized to x0.
- options.AddWeakSmtOption("NNF.SK_HACK", "true");
-
- // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems
- options.AddWeakSmtOption("smt.MBQI", "false");
-
- // More or less like MAM=0.
- options.AddWeakSmtOption("smt.QI.EAGER_THRESHOLD", "100");
- // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
-
- // the following will make the :weight option more usable
- if (!fp) options.AddWeakSmtOption("smt.QI.COST", "|(+ weight generation)|"); // TODO: this doesn't seem to work
-
- //if (options.Inspector != null)
- // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100");
-
- options.AddWeakSmtOption("TYPE_CHECK", "true");
- options.AddWeakSmtOption("smt.BV.REFLECT", "true");
-
- if (options.TimeLimit > 0)
- {
- options.AddWeakSmtOption("TIMEOUT", options.TimeLimit.ToString());
- options.AddWeakSmtOption("fixedpoint.TIMEOUT", options.TimeLimit.ToString());
- // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it.
- // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000);
- }
-
- if (options.Inspector != null)
- options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200");
-
- if (CommandLineOptions.Clo.WeakArrayTheory)
- {
- options.AddWeakSmtOption("smt.array.weak", "true");
- options.AddWeakSmtOption("smt.array.extensional", "false");
- }
-
- if (CommandLineOptions.Clo.PrintConjectures != null)
- {
- options.AddWeakSmtOption("fixedpoint.conjecture_file", CommandLineOptions.Clo.PrintConjectures + ".tmp");
- }
- }
- else
- {
- // don't bother with auto-config - it would disable explicit settings for eager threshold and so on
- options.AddWeakSmtOption("AUTO_CONFIG", "false");
-
- //options.AddWeakSmtOption("MODEL_PARTIAL", "true");
- //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false");
- options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false");
- options.AddWeakSmtOption("ASYNC_COMMANDS", "false");
-
- if (CommandLineOptions.Clo.UseSmtOutputFormat)
- {
- options.AddWeakSmtOption("pp-bv-literals", "false"); ;
- }
- else
- {
- options.AddWeakSmtOption("MODEL_V2", "true");
- }
-
- if (!options.OptimizeForBv)
- {
- // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
- // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
- options.AddWeakSmtOption("PHASE_SELECTION", "0");
- options.AddWeakSmtOption("RESTART_STRATEGY", "0");
- options.AddWeakSmtOption("RESTART_FACTOR", "|1.5|");
-
- // Make the integer model more diverse by default, speeds up some benchmarks a lot.
- options.AddWeakSmtOption("ARITH_RANDOM_INITIAL_VALUE", "true");
-
- // The left-to-right structural case-splitting strategy.
- //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now
- options.AddWeakSmtOption("CASE_SPLIT", "3");
-
- // In addition delay adding unit conflicts.
- options.AddWeakSmtOption("DELAY_UNITS", "true");
- options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16");
- }
-
- // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
- // the foo(x0) will be activated for e-matching when x is skolemized to x0.
- options.AddWeakSmtOption("NNF_SK_HACK", "true");
-
- // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems
- options.AddWeakSmtOption("MBQI", "false");
-
- // More or less like MAM=0.
- options.AddWeakSmtOption("QI_EAGER_THRESHOLD", "100");
- // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
-
- // the following will make the :weight option more usable
- options.AddWeakSmtOption("QI_COST", "|\"(+ weight generation)\"|");
-
- //if (options.Inspector != null)
- // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100");
-
- options.AddWeakSmtOption("TYPE_CHECK", "true");
- options.AddWeakSmtOption("BV_REFLECT", "true");
-
- if (options.TimeLimit > 0)
- {
- options.AddWeakSmtOption("SOFT_TIMEOUT", options.TimeLimit.ToString());
- // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it.
- // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000);
- }
-
- if (options.Inspector != null)
- options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200");
-
- if (CommandLineOptions.Clo.WeakArrayTheory)
- {
- options.AddWeakSmtOption("ARRAY_WEAK", "true");
- options.AddWeakSmtOption("ARRAY_EXTENSIONAL", "false");
- }
-
- options.AddWeakSmtOption("MODEL_ON_TIMEOUT", "true");
-
- }
-
- // KLM: don't add Z3 options here. The options are different in different Z3 versions.
- // Add options in the above condition for the appropriate version.
-
- // legacy option handling
- if (!CommandLineOptions.Clo.z3AtFlag)
- options.MultiTraces = true;
-
-
- foreach (string opt in CommandLineOptions.Clo.Z3Options)
- {
- Contract.Assert(opt != null);
- int eq = opt.IndexOf("=");
- if (eq > 0 && 'A' <= opt[0] && opt[0] <= 'Z' && !commandLineOnly.Contains(opt.Substring(0, eq)))
- {
- options.AddSmtOption(opt.Substring(0, eq), opt.Substring(eq + 1));
- }
- else
- {
- options.AddSolverArgument(opt);
- }
- }
- }
-
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Boogie.SMTLib
+{
+ class Z3
+ {
+ static string _proverPath;
+
+ static string CodebaseString()
+ {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
+ }
+
+ public static string ExecutablePath()
+ {
+ if (_proverPath == null)
+ FindExecutable();
+ return _proverPath;
+ }
+
+ static void FindExecutable()
+ // throws ProverException, System.IO.FileNotFoundException;
+ {
+ Contract.Ensures(_proverPath != null);
+
+ // Command line option 'z3exe' always has priority if set
+ if (CommandLineOptions.Clo.Z3ExecutablePath != null)
+ {
+ _proverPath = CommandLineOptions.Clo.Z3ExecutablePath;
+ if (!File.Exists(_proverPath))
+ {
+ throw new ProverException("Cannot find prover specified with z3exe: " + _proverPath);
+ }
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("[TRACE] Using prover: " + _proverPath);
+ }
+ return;
+ }
+
+ var proverExe = CommandLineOptions.Clo.Z3ExecutableName;
+ proverExe = proverExe == null ? "z3.exe" : proverExe;
+
+ if (_proverPath == null)
+ {
+ // Initialize '_proverPath'
+ _proverPath = Path.Combine(CodebaseString(), proverExe);
+ string firstTry = _proverPath;
+
+ if (File.Exists(firstTry))
+ {
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("[TRACE] Using prover: " + _proverPath);
+ }
+ return;
+ }
+
+ List<string> z3Dirs = new List<string>();
+ var msrDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Research\");
+ if (Directory.Exists(msrDir))
+ {
+ z3Dirs.AddRange(Directory.GetDirectories(msrDir, "Z3-*"));
+ }
+ var msrDirX86 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Research\");
+ if (Directory.Exists(msrDirX86))
+ {
+ z3Dirs.AddRange(Directory.GetDirectories(msrDirX86, "Z3-*"));
+ }
+
+ int minMajor = 3, minMinor = 2;
+
+ // Look for the most recent version of Z3.
+ int minor = 0, major = 0;
+ string winner = null;
+ Regex r = new Regex(@"^Z3-(\d+)\.(\d+)$");
+ foreach (string d in z3Dirs)
+ {
+ string name = new DirectoryInfo(d).Name;
+ foreach (Match m in r.Matches(name))
+ {
+ int ma, mi;
+ ma = int.Parse(m.Groups[1].ToString());
+ mi = int.Parse(m.Groups[2].ToString());
+ if (major < ma || (major == ma && minor < mi))
+ {
+ major = ma;
+ minor = mi;
+ winner = d;
+ }
+ }
+ }
+
+ if (major == 0 && minor == 0)
+ {
+ throw new ProverException("Cannot find executable: " + firstTry);
+ }
+
+ Contract.Assert(winner != null);
+
+ _proverPath = Path.Combine(Path.Combine(winner, "bin"), proverExe);
+ if (!File.Exists(_proverPath))
+ {
+ throw new ProverException("Cannot find prover: " + _proverPath);
+ }
+
+ if (CommandLineOptions.Clo.Trace)
+ {
+ Console.WriteLine("[TRACE] Using prover: " + _proverPath);
+ }
+
+ if (major < minMajor || (major == minMajor && minor < minMinor))
+ {
+ throw new ProverException(string.Format("Found version {0}.{1} of Z3. Please install version {2}.{3} or later. " +
+ "(More conservative users might opt to supply -prover:Z3 option instead to get the historic Simplify back-end)",
+ major, minor, minMajor, minMinor));
+ }
+ }
+ }
+
+
+ static int Z3MajorVersion = 0;
+ static int Z3MinorVersion = 0;
+ static bool Z3VersionObtained = false;
+
+ public static void GetVersion(out int major, out int minor)
+ {
+ if (!Z3VersionObtained)
+ {
+ var proc = new System.Diagnostics.Process();
+ proc.StartInfo.FileName = _proverPath;
+ proc.StartInfo.Arguments = "--version";
+ proc.StartInfo.RedirectStandardOutput = true;
+ proc.StartInfo.RedirectStandardError = true;
+ proc.StartInfo.UseShellExecute = false;
+ proc.StartInfo.CreateNoWindow = true;
+ proc.Start();
+ string answer = proc.StandardOutput.ReadToEnd();
+ proc.WaitForExit();
+ if (proc.ExitCode == 0)
+ {
+ var firstdot = answer.IndexOf('.');
+ if (firstdot >= 0)
+ {
+ var seconddot = answer.IndexOf('.', firstdot + 1);
+ if (seconddot >= firstdot + 1)
+ {
+ var spacebeforefirstdot = answer.LastIndexOf(' ', firstdot);
+ if (spacebeforefirstdot >= 0)
+ {
+ var majorstr = answer.Substring(spacebeforefirstdot, firstdot - spacebeforefirstdot);
+ var minorstr = answer.Substring(firstdot + 1, seconddot - firstdot - 1);
+ Z3MajorVersion = Convert.ToInt32(majorstr);
+ Z3MinorVersion = Convert.ToInt32(minorstr);
+ }
+ }
+ }
+ }
+ Z3VersionObtained = true;
+ }
+ major = Z3MajorVersion;
+ minor = Z3MinorVersion;
+ }
+
+ public static string SetTimeoutOption()
+ {
+ int major, minor;
+ GetVersion(out major, out minor);
+ if (major > 4 || major == 4 && minor >= 3)
+ return "TIMEOUT";
+ else
+ return "SOFT_TIMEOUT";
+ }
+
+ // options that work only on the command line
+ static string[] commandLineOnly = { "TRACE", "PROOF_MODE" };
+
+
+ public static void SetupOptions(SMTLibProverOptions options)
+ {
+ FindExecutable();
+ int major, minor;
+ GetVersion(out major, out minor);
+ if (major > 4 || major == 4 && minor >= 3)
+ {
+
+ bool fp = false; // CommandLineOptions.Clo.FixedPointEngine != null;
+
+ // don't bother with auto-config - it would disable explicit settings for eager threshold and so on
+ if(!fp) options.AddWeakSmtOption("AUTO_CONFIG", "false");
+
+ //options.AddWeakSmtOption("MODEL_PARTIAL", "true");
+ //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false");
+
+ // options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false"); TODO: what does this do?
+
+ // Make sure we get something that is parsable as a bitvector
+ options.AddWeakSmtOption("pp.bv_literals", "false");
+ if (!CommandLineOptions.Clo.UseSmtOutputFormat)
+ {
+ options.AddWeakSmtOption("MODEL.V2", "true");
+ }
+ //options.AddWeakSmtOption("ASYNC_COMMANDS", "false"); TODO: is this needed?
+
+ if (!options.OptimizeForBv)
+ {
+ // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
+ // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
+ options.AddWeakSmtOption("smt.PHASE_SELECTION", "0");
+ options.AddWeakSmtOption("smt.RESTART_STRATEGY", "0");
+ options.AddWeakSmtOption("smt.RESTART_FACTOR", "|1.5|");
+
+ // Make the integer model more diverse by default, speeds up some benchmarks a lot.
+ options.AddWeakSmtOption("smt.ARITH.RANDOM_INITIAL_VALUE", "true");
+
+ // The left-to-right structural case-splitting strategy.
+ //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now
+
+ if (!fp) options.AddWeakSmtOption("smt.CASE_SPLIT", "3");
+
+ // In addition delay adding unit conflicts.
+ options.AddWeakSmtOption("smt.DELAY_UNITS", "true");
+ //options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16"); TODO: what?
+ }
+
+ // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
+ // the foo(x0) will be activated for e-matching when x is skolemized to x0.
+ options.AddWeakSmtOption("NNF.SK_HACK", "true");
+
+ // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems
+ options.AddWeakSmtOption("smt.MBQI", "false");
+
+ // More or less like MAM=0.
+ options.AddWeakSmtOption("smt.QI.EAGER_THRESHOLD", "100");
+ // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
+
+ // the following will make the :weight option more usable
+ // KLM: this QI cost function is the default
+ // if (!fp) options.AddWeakSmtOption("smt.QI.COST", "|(+ weight generation)|"); // TODO: this doesn't seem to work
+
+ //if (options.Inspector != null)
+ // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100");
+
+ options.AddWeakSmtOption("TYPE_CHECK", "true");
+ options.AddWeakSmtOption("smt.BV.REFLECT", "true");
+
+ if (options.TimeLimit > 0)
+ {
+ options.AddWeakSmtOption("TIMEOUT", options.TimeLimit.ToString());
+ options.AddWeakSmtOption("fixedpoint.TIMEOUT", options.TimeLimit.ToString());
+ // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it.
+ // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000);
+ }
+
+ if (options.Inspector != null)
+ options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200");
+
+ if (CommandLineOptions.Clo.WeakArrayTheory)
+ {
+ options.AddWeakSmtOption("smt.array.weak", "true");
+ options.AddWeakSmtOption("smt.array.extensional", "false");
+ }
+
+ if (CommandLineOptions.Clo.PrintConjectures != null)
+ {
+ options.AddWeakSmtOption("fixedpoint.conjecture_file", CommandLineOptions.Clo.PrintConjectures + ".tmp");
+ }
+ }
+ else
+ {
+ // don't bother with auto-config - it would disable explicit settings for eager threshold and so on
+ options.AddWeakSmtOption("AUTO_CONFIG", "false");
+
+ //options.AddWeakSmtOption("MODEL_PARTIAL", "true");
+ //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false");
+ options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false");
+ options.AddWeakSmtOption("ASYNC_COMMANDS", "false");
+
+ if (CommandLineOptions.Clo.UseSmtOutputFormat)
+ {
+ options.AddWeakSmtOption("pp-bv-literals", "false"); ;
+ }
+ else
+ {
+ options.AddWeakSmtOption("MODEL_V2", "true");
+ }
+
+ if (!options.OptimizeForBv)
+ {
+ // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
+ // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
+ options.AddWeakSmtOption("PHASE_SELECTION", "0");
+ options.AddWeakSmtOption("RESTART_STRATEGY", "0");
+ options.AddWeakSmtOption("RESTART_FACTOR", "|1.5|");
+
+ // Make the integer model more diverse by default, speeds up some benchmarks a lot.
+ options.AddWeakSmtOption("ARITH_RANDOM_INITIAL_VALUE", "true");
+
+ // The left-to-right structural case-splitting strategy.
+ //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now
+ options.AddWeakSmtOption("CASE_SPLIT", "3");
+
+ // In addition delay adding unit conflicts.
+ options.AddWeakSmtOption("DELAY_UNITS", "true");
+ options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16");
+ }
+
+ // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
+ // the foo(x0) will be activated for e-matching when x is skolemized to x0.
+ options.AddWeakSmtOption("NNF_SK_HACK", "true");
+
+ // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems
+ options.AddWeakSmtOption("MBQI", "false");
+
+ // More or less like MAM=0.
+ options.AddWeakSmtOption("QI_EAGER_THRESHOLD", "100");
+ // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
+
+ // the following will make the :weight option more usable
+ options.AddWeakSmtOption("QI_COST", "|\"(+ weight generation)\"|");
+
+ //if (options.Inspector != null)
+ // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100");
+
+ options.AddWeakSmtOption("TYPE_CHECK", "true");
+ options.AddWeakSmtOption("BV_REFLECT", "true");
+
+ if (options.TimeLimit > 0)
+ {
+ options.AddWeakSmtOption("SOFT_TIMEOUT", options.TimeLimit.ToString());
+ // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it.
+ // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000);
+ }
+
+ if (options.Inspector != null)
+ options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200");
+
+ if (CommandLineOptions.Clo.WeakArrayTheory)
+ {
+ options.AddWeakSmtOption("ARRAY_WEAK", "true");
+ options.AddWeakSmtOption("ARRAY_EXTENSIONAL", "false");
+ }
+
+ options.AddWeakSmtOption("MODEL_ON_TIMEOUT", "true");
+
+ }
+
+ // KLM: don't add Z3 options here. The options are different in different Z3 versions.
+ // Add options in the above condition for the appropriate version.
+
+ // legacy option handling
+ if (!CommandLineOptions.Clo.z3AtFlag)
+ options.MultiTraces = true;
+
+
+ foreach (string opt in CommandLineOptions.Clo.Z3Options)
+ {
+ Contract.Assert(opt != null);
+ int eq = opt.IndexOf("=");
+ if (eq > 0 && 'A' <= opt[0] && opt[0] <= 'Z' && !commandLineOnly.Contains(opt.Substring(0, eq)))
+ {
+ options.AddSmtOption(opt.Substring(0, eq), opt.Substring(eq + 1));
+ }
+ else
+ {
+ options.AddSolverArgument(opt);
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/Source/Provers/SMTLib/cce.cs b/Source/Provers/SMTLib/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/Provers/SMTLib/cce.cs
+++ b/Source/Provers/SMTLib/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/Provers/TPTP/ProverInterface.cs b/Source/Provers/TPTP/ProverInterface.cs
index b714ed67..669c459f 100644
--- a/Source/Provers/TPTP/ProverInterface.cs
+++ b/Source/Provers/TPTP/ProverInterface.cs
@@ -1,351 +1,351 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.IO;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Clustering;
-using Microsoft.Boogie.TypeErasure;
-using Microsoft.Boogie.Simplify;
-
-namespace Microsoft.Boogie.TPTP
-{
- public class TPTPProverOptions : ProverOptions
- {
- public string Output = "boogie-vc-@PROC@.tptp";
- public bool UsePredicates = false;
-
- protected override bool Parse(string opt)
- {
- return
- ParseString(opt, "OUTPUT", ref Output) ||
- ParseBool(opt, "USE_PREDICATES", ref UsePredicates) ||
- base.Parse(opt);
- }
-
- public override string Help
- {
- get
- {
- return
-@"
-TPTP-specific options:
-~~~~~~~~~~~~~~~~~~~~~~
-OUTPUT=<string> Store VC in named file. Defaults to boogie-vc-@PROC@.tptp.
-USE_PREDICATES=<bool> Try to use SMT predicates for functions returning bool.
-
-" + base.Help;
- // DIST requires non-public binaries
- }
- }
- }
-
- public class TPTPProcessTheoremProver : LogProverInterface
- {
- private readonly DeclFreeProverContext ctx;
- private readonly VCExpressionGenerator Gen;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(ctx != null);
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Namer != null);
- Contract.Invariant(DeclCollector != null);
- Contract.Invariant(cce.NonNullElements(Axioms));
- Contract.Invariant(cce.NonNullElements(TypeDecls));
- Contract.Invariant(_backgroundPredicates != null);
-
- }
-
-
- [NotDelayed]
- public TPTPProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
- DeclFreeProverContext ctx)
- : base(options, "", "", "", "", gen)
- {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
-
- // No bg predicate at the moment
- // InitializeGlobalInformation("UnivBackPred.tptp");
-
- this.ctx = ctx;
- this.Gen = gen;
-
- TypeAxiomBuilder axBuilder;
- switch (CommandLineOptions.Clo.TypeEncodingMethod) {
- case CommandLineOptions.TypeEncoding.Arguments:
- axBuilder = new TypeAxiomBuilderArguments(gen);
- axBuilder.Setup();
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- axBuilder = new TypeAxiomBuilderPremisses(gen);
- break;
- default:
- axBuilder = new TypeAxiomBuilderPremisses(gen);
- axBuilder.Setup();
- break;
- }
- AxBuilder = axBuilder;
- UniqueNamer namer = new UniqueNamer();
- Namer = namer;
- Namer.Spacer = "__";
- this.DeclCollector = new TypeDeclCollector(namer);
-
- }
-
- public override ProverContext Context
- {
- get
- {
- Contract.Ensures(Contract.Result<ProverContext>() != null);
-
- return ctx;
- }
- }
-
- private readonly TypeAxiomBuilder AxBuilder;
- private readonly UniqueNamer Namer;
- private readonly TypeDeclCollector DeclCollector;
-
- private void FeedTypeDeclsToProver()
- {
- foreach (string s in DeclCollector.GetNewDeclarations()) {
- Contract.Assert(s != null);
- AddTypeDecl(s);
- }
- }
-
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
- {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- TextWriter output = OpenOutputFile(descriptiveName);
- Contract.Assert(output != null);
-
- WriteLineAndLog(output, "%------------------------------------------------------------------------------");
- WriteLineAndLog(output, "% Boogie benchmark: " + descriptiveName);
- WriteLineAndLog(output, "%------------------------------------------------------------------------------");
-
- WriteLineAndLog(output, _backgroundPredicates);
-
- if (!AxiomsAreSetup) {
- AddAxiom(VCExpr2String(ctx.Axioms, -1));
- AxiomsAreSetup = true;
- }
-
- string vcString = "fof(vc, conjecture, " + VCExpr2String(vc, 1) + ").";
-
- foreach (string s in TypeDecls) {
- Contract.Assert(s != null);
- WriteLineAndLog(output, s);
- }
- int id = 0;
- foreach (string s in Axioms) {
- Contract.Assert(s != null);
- WriteLineAndLog(output, "fof(ax" + id++ + ", axiom,");
- WriteLineAndLog(output, s);
- WriteLineAndLog(output, ").");
- }
-
- WriteLineAndLog(output, vcString);
-
- output.Close();
- }
-
- public TPTPProverOptions Options
- {
- get { return (TPTPProverOptions)this.options; }
- }
-
- private TextWriter OpenOutputFile(string descriptiveName)
- {
- Contract.Requires(descriptiveName != null);
- Contract.Ensures(Contract.Result<TextWriter>() != null);
-
- string filename = Options.Output;
- filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
- return new StreamWriter(filename, false);
- }
-
- private void WriteLineAndLog(TextWriter output, string msg)
- {
- Contract.Requires(output != null);
- Contract.Requires(msg != null);
- LogActivity(msg);
- output.WriteLine(msg);
- }
-
- [NoDefaultContract]
- public override Outcome CheckOutcome(ErrorHandler handler)
- { //Contract.Requires(handler != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- return Outcome.Undetermined;
- }
-
- protected string VCExpr2String(VCExpr expr, int polarity)
- {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- DateTime start = DateTime.UtcNow;
- if (CommandLineOptions.Clo.Trace)
- Console.Write("Linearising ... ");
-
- // handle the types in the VCExpr
- TypeEraser eraser;
- switch (CommandLineOptions.Clo.TypeEncodingMethod) {
- case CommandLineOptions.TypeEncoding.Arguments:
- eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, gen);
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- eraser = null;
- break;
- default:
- eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen);
- break;
- }
- VCExpr exprWithoutTypes = eraser == null ? expr : eraser.Erase(expr, polarity);
- Contract.Assert(exprWithoutTypes != null);
-
- var letImplier = new Let2ImpliesMutator(Gen);
- var flattener = new TermFormulaFlattener(Gen);
- var exprWithLet = flattener.Flatten(exprWithoutTypes);
- var exprWithoutLet = letImplier.Mutate(exprWithLet);
-
- var axiomsWithLet = flattener.Flatten(AxBuilder.GetNewAxioms());
- var axiomsWithoutLet = letImplier.Mutate(axiomsWithLet);
-
- DeclCollector.Collect(axiomsWithoutLet);
- DeclCollector.Collect(exprWithoutLet);
- FeedTypeDeclsToProver();
-
- AddAxiom(TPTPExprLineariser.ToString(axiomsWithoutLet, Namer, Options));
- string res = TPTPExprLineariser.ToString(exprWithoutLet, Namer, Options);
- Contract.Assert(res != null);
-
- if (CommandLineOptions.Clo.Trace) {
- DateTime end = DateTime.UtcNow;
- TimeSpan elapsed = end - start;
- Console.WriteLine("finished [{0} s]", elapsed.TotalSeconds);
- }
- return res;
- }
-
- // the list of all known axioms, where have to be included in each
- // verification condition
- private readonly List<string/*!>!*/> Axioms = new List<string/*!*/>();
- private bool AxiomsAreSetup = false;
-
-
-
-
- // similarly, a list of function/predicate declarations
- private readonly List<string/*!>!*/> TypeDecls = new List<string/*!*/>();
-
- protected void AddAxiom(string axiom)
- {
- Contract.Requires(axiom != null);
- Axioms.Add(axiom);
- // if (thmProver != null) {
- // LogActivity(":assume " + axiom);
- // thmProver.AddAxioms(axiom);
- // }
- }
-
- protected void AddTypeDecl(string decl)
- {
- Contract.Requires(decl != null);
- TypeDecls.Add(decl);
- // if (thmProver != null) {
- // LogActivity(decl);
- // thmProver.Feed(decl, 0);
- // }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private static string _backgroundPredicates = "";
-
- static void InitializeGlobalInformation(string backgroundPred)
- {
- Contract.Requires(backgroundPred != null);
- Contract.Ensures(_backgroundPredicates != null);
- //throws ProverException, System.IO.FileNotFoundException;
- if (_backgroundPredicates == null) {
- string codebaseString =
- cce.NonNull(Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
-
- // Initialize '_backgroundPredicates'
- string univBackPredPath = Path.Combine(codebaseString, backgroundPred);
- using (StreamReader reader = new System.IO.StreamReader(univBackPredPath)) {
- _backgroundPredicates = reader.ReadToEnd();
- }
- }
- }
- }
-
- public class Factory : ProverFactory
- {
-
- public override object SpawnProver(ProverOptions options, object ctxt)
- {
- //Contract.Requires(ctxt != null);
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- return this.SpawnProver(options,
- cce.NonNull((DeclFreeProverContext)ctxt).ExprGen,
- cce.NonNull((DeclFreeProverContext)ctxt));
- }
-
- public override object NewProverContext(ProverOptions options)
- {
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
- CommandLineOptions.Clo.BracketIdsInVC = 0;
- }
-
- VCExpressionGenerator gen = new VCExpressionGenerator();
- List<string>/*!>!*/ proverCommands = new List<string/*!*/>();
- proverCommands.Add("tptp");
- proverCommands.Add("external");
- VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands);
- Contract.Assert(genOptions != null);
-
- return new DeclFreeProverContext(gen, genOptions);
- }
-
- public override ProverOptions BlankProverOptions()
- {
- return new TPTPProverOptions();
- }
-
- protected virtual TPTPProcessTheoremProver SpawnProver(ProverOptions options,
- VCExpressionGenerator gen,
- DeclFreeProverContext ctx)
- {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
- Contract.Ensures(Contract.Result<TPTPProcessTheoremProver>() != null);
-
- return new TPTPProcessTheoremProver(options, gen, ctx);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Boogie.Clustering;
+using Microsoft.Boogie.TypeErasure;
+using Microsoft.Boogie.Simplify;
+
+namespace Microsoft.Boogie.TPTP
+{
+ public class TPTPProverOptions : ProverOptions
+ {
+ public string Output = "boogie-vc-@PROC@.tptp";
+ public bool UsePredicates = false;
+
+ protected override bool Parse(string opt)
+ {
+ return
+ ParseString(opt, "OUTPUT", ref Output) ||
+ ParseBool(opt, "USE_PREDICATES", ref UsePredicates) ||
+ base.Parse(opt);
+ }
+
+ public override string Help
+ {
+ get
+ {
+ return
+@"
+TPTP-specific options:
+~~~~~~~~~~~~~~~~~~~~~~
+OUTPUT=<string> Store VC in named file. Defaults to boogie-vc-@PROC@.tptp.
+USE_PREDICATES=<bool> Try to use SMT predicates for functions returning bool.
+
+" + base.Help;
+ // DIST requires non-public binaries
+ }
+ }
+ }
+
+ public class TPTPProcessTheoremProver : LogProverInterface
+ {
+ private readonly DeclFreeProverContext ctx;
+ private readonly VCExpressionGenerator Gen;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(ctx != null);
+ Contract.Invariant(AxBuilder != null);
+ Contract.Invariant(Namer != null);
+ Contract.Invariant(DeclCollector != null);
+ Contract.Invariant(cce.NonNullElements(Axioms));
+ Contract.Invariant(cce.NonNullElements(TypeDecls));
+ Contract.Invariant(_backgroundPredicates != null);
+
+ }
+
+
+ [NotDelayed]
+ public TPTPProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
+ DeclFreeProverContext ctx)
+ : base(options, "", "", "", "", gen)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(ctx != null);
+
+ // No bg predicate at the moment
+ // InitializeGlobalInformation("UnivBackPred.tptp");
+
+ this.ctx = ctx;
+ this.Gen = gen;
+
+ TypeAxiomBuilder axBuilder;
+ switch (CommandLineOptions.Clo.TypeEncodingMethod) {
+ case CommandLineOptions.TypeEncoding.Arguments:
+ axBuilder = new TypeAxiomBuilderArguments(gen);
+ axBuilder.Setup();
+ break;
+ case CommandLineOptions.TypeEncoding.Monomorphic:
+ axBuilder = new TypeAxiomBuilderPremisses(gen);
+ break;
+ default:
+ axBuilder = new TypeAxiomBuilderPremisses(gen);
+ axBuilder.Setup();
+ break;
+ }
+ AxBuilder = axBuilder;
+ UniqueNamer namer = new UniqueNamer();
+ Namer = namer;
+ Namer.Spacer = "__";
+ this.DeclCollector = new TypeDeclCollector(namer);
+
+ }
+
+ public override ProverContext Context
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<ProverContext>() != null);
+
+ return ctx;
+ }
+ }
+
+ private readonly TypeAxiomBuilder AxBuilder;
+ private readonly UniqueNamer Namer;
+ private readonly TypeDeclCollector DeclCollector;
+
+ private void FeedTypeDeclsToProver()
+ {
+ foreach (string s in DeclCollector.GetNewDeclarations()) {
+ Contract.Assert(s != null);
+ AddTypeDecl(s);
+ }
+ }
+
+ public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
+ {
+ //Contract.Requires(descriptiveName != null);
+ //Contract.Requires(vc != null);
+ //Contract.Requires(handler != null);
+ TextWriter output = OpenOutputFile(descriptiveName);
+ Contract.Assert(output != null);
+
+ WriteLineAndLog(output, "%------------------------------------------------------------------------------");
+ WriteLineAndLog(output, "% Boogie benchmark: " + descriptiveName);
+ WriteLineAndLog(output, "%------------------------------------------------------------------------------");
+
+ WriteLineAndLog(output, _backgroundPredicates);
+
+ if (!AxiomsAreSetup) {
+ AddAxiom(VCExpr2String(ctx.Axioms, -1));
+ AxiomsAreSetup = true;
+ }
+
+ string vcString = "fof(vc, conjecture, " + VCExpr2String(vc, 1) + ").";
+
+ foreach (string s in TypeDecls) {
+ Contract.Assert(s != null);
+ WriteLineAndLog(output, s);
+ }
+ int id = 0;
+ foreach (string s in Axioms) {
+ Contract.Assert(s != null);
+ WriteLineAndLog(output, "fof(ax" + id++ + ", axiom,");
+ WriteLineAndLog(output, s);
+ WriteLineAndLog(output, ").");
+ }
+
+ WriteLineAndLog(output, vcString);
+
+ output.Close();
+ }
+
+ public TPTPProverOptions Options
+ {
+ get { return (TPTPProverOptions)this.options; }
+ }
+
+ private TextWriter OpenOutputFile(string descriptiveName)
+ {
+ Contract.Requires(descriptiveName != null);
+ Contract.Ensures(Contract.Result<TextWriter>() != null);
+
+ string filename = Options.Output;
+ filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
+ return new StreamWriter(filename, false);
+ }
+
+ private void WriteLineAndLog(TextWriter output, string msg)
+ {
+ Contract.Requires(output != null);
+ Contract.Requires(msg != null);
+ LogActivity(msg);
+ output.WriteLine(msg);
+ }
+
+ [NoDefaultContract]
+ public override Outcome CheckOutcome(ErrorHandler handler)
+ { //Contract.Requires(handler != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ return Outcome.Undetermined;
+ }
+
+ protected string VCExpr2String(VCExpr expr, int polarity)
+ {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ DateTime start = DateTime.UtcNow;
+ if (CommandLineOptions.Clo.Trace)
+ Console.Write("Linearising ... ");
+
+ // handle the types in the VCExpr
+ TypeEraser eraser;
+ switch (CommandLineOptions.Clo.TypeEncodingMethod) {
+ case CommandLineOptions.TypeEncoding.Arguments:
+ eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, gen);
+ break;
+ case CommandLineOptions.TypeEncoding.Monomorphic:
+ eraser = null;
+ break;
+ default:
+ eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen);
+ break;
+ }
+ VCExpr exprWithoutTypes = eraser == null ? expr : eraser.Erase(expr, polarity);
+ Contract.Assert(exprWithoutTypes != null);
+
+ var letImplier = new Let2ImpliesMutator(Gen);
+ var flattener = new TermFormulaFlattener(Gen);
+ var exprWithLet = flattener.Flatten(exprWithoutTypes);
+ var exprWithoutLet = letImplier.Mutate(exprWithLet);
+
+ var axiomsWithLet = flattener.Flatten(AxBuilder.GetNewAxioms());
+ var axiomsWithoutLet = letImplier.Mutate(axiomsWithLet);
+
+ DeclCollector.Collect(axiomsWithoutLet);
+ DeclCollector.Collect(exprWithoutLet);
+ FeedTypeDeclsToProver();
+
+ AddAxiom(TPTPExprLineariser.ToString(axiomsWithoutLet, Namer, Options));
+ string res = TPTPExprLineariser.ToString(exprWithoutLet, Namer, Options);
+ Contract.Assert(res != null);
+
+ if (CommandLineOptions.Clo.Trace) {
+ DateTime end = DateTime.UtcNow;
+ TimeSpan elapsed = end - start;
+ Console.WriteLine("finished [{0} s]", elapsed.TotalSeconds);
+ }
+ return res;
+ }
+
+ // the list of all known axioms, where have to be included in each
+ // verification condition
+ private readonly List<string/*!>!*/> Axioms = new List<string/*!*/>();
+ private bool AxiomsAreSetup = false;
+
+
+
+
+ // similarly, a list of function/predicate declarations
+ private readonly List<string/*!>!*/> TypeDecls = new List<string/*!*/>();
+
+ protected void AddAxiom(string axiom)
+ {
+ Contract.Requires(axiom != null);
+ Axioms.Add(axiom);
+ // if (thmProver != null) {
+ // LogActivity(":assume " + axiom);
+ // thmProver.AddAxioms(axiom);
+ // }
+ }
+
+ protected void AddTypeDecl(string decl)
+ {
+ Contract.Requires(decl != null);
+ TypeDecls.Add(decl);
+ // if (thmProver != null) {
+ // LogActivity(decl);
+ // thmProver.Feed(decl, 0);
+ // }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private static string _backgroundPredicates = "";
+
+ static void InitializeGlobalInformation(string backgroundPred)
+ {
+ Contract.Requires(backgroundPred != null);
+ Contract.Ensures(_backgroundPredicates != null);
+ //throws ProverException, System.IO.FileNotFoundException;
+ if (_backgroundPredicates == null) {
+ string codebaseString =
+ cce.NonNull(Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
+
+ // Initialize '_backgroundPredicates'
+ string univBackPredPath = Path.Combine(codebaseString, backgroundPred);
+ using (StreamReader reader = new System.IO.StreamReader(univBackPredPath)) {
+ _backgroundPredicates = reader.ReadToEnd();
+ }
+ }
+ }
+ }
+
+ public class Factory : ProverFactory
+ {
+
+ public override object SpawnProver(ProverOptions options, object ctxt)
+ {
+ //Contract.Requires(ctxt != null);
+ //Contract.Requires(options != null);
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ return this.SpawnProver(options,
+ cce.NonNull((DeclFreeProverContext)ctxt).ExprGen,
+ cce.NonNull((DeclFreeProverContext)ctxt));
+ }
+
+ public override object NewProverContext(ProverOptions options)
+ {
+ //Contract.Requires(options != null);
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ if (CommandLineOptions.Clo.BracketIdsInVC < 0) {
+ CommandLineOptions.Clo.BracketIdsInVC = 0;
+ }
+
+ VCExpressionGenerator gen = new VCExpressionGenerator();
+ List<string>/*!>!*/ proverCommands = new List<string/*!*/>();
+ proverCommands.Add("tptp");
+ proverCommands.Add("external");
+ VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands);
+ Contract.Assert(genOptions != null);
+
+ return new DeclFreeProverContext(gen, genOptions);
+ }
+
+ public override ProverOptions BlankProverOptions()
+ {
+ return new TPTPProverOptions();
+ }
+
+ protected virtual TPTPProcessTheoremProver SpawnProver(ProverOptions options,
+ VCExpressionGenerator gen,
+ DeclFreeProverContext ctx)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(ctx != null);
+ Contract.Ensures(Contract.Result<TPTPProcessTheoremProver>() != null);
+
+ return new TPTPProcessTheoremProver(options, gen, ctx);
+ }
+ }
+}
diff --git a/Source/Provers/TPTP/TPTP.csproj b/Source/Provers/TPTP/TPTP.csproj
index a3ee1caa..116492d0 100644
--- a/Source/Provers/TPTP/TPTP.csproj
+++ b/Source/Provers/TPTP/TPTP.csproj
@@ -1,131 +1,131 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{A598ED5A-93AD-4125-A555-3921A2F936FA}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.TPTP</RootNamespace>
- <AssemblyName>Provers.TPTP</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </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>
- </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>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.TPTP.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="ProverInterface.cs" />
- <Compile Include="..\..\version.cs" />
- <Compile Include="TPTPLineariser.cs" />
- <Compile Include="TypeDeclCollector.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\AbsInt\AbsInt.csproj">
- <Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
- <Name>AbsInt</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A598ED5A-93AD-4125-A555-3921A2F936FA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie.TPTP</RootNamespace>
+ <AssemblyName>Provers.TPTP</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </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>
+ </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>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Provers.TPTP.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ProverInterface.cs" />
+ <Compile Include="..\..\version.cs" />
+ <Compile Include="TPTPLineariser.cs" />
+ <Compile Include="TypeDeclCollector.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\AbsInt\AbsInt.csproj">
+ <Project>{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}</Project>
+ <Name>AbsInt</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\AIFramework\AIFramework.csproj">
+ <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
+ <Name>AIFramework</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</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/Provers/TPTP/TPTPLineariser.cs b/Source/Provers/TPTP/TPTPLineariser.cs
index a35d43f0..4bdf29b9 100644
--- a/Source/Provers/TPTP/TPTPLineariser.cs
+++ b/Source/Provers/TPTP/TPTPLineariser.cs
@@ -1,740 +1,740 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Method to turn VCExprs into strings that can be fed into TPTP provers.
-// This is currently quite similar to the
-// SimplifyLikeLineariser (but the code is independent)
-
-namespace Microsoft.Boogie.TPTP
-{
-
- // Options for the linearisation
- public class LineariserOptions {
-
- public readonly bool AsTerm;
- public LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- if (newVal)
- return DefaultTerm;
- else
- return Default;
- }
-
- internal LineariserOptions(bool asTerm) {
- this.AsTerm = asTerm;
- }
-
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(Default!=null);
- Contract.Invariant(DefaultTerm!=null);
-}
-
- public static readonly LineariserOptions Default = new LineariserOptions (false);
- internal static readonly LineariserOptions DefaultTerm = new LineariserOptions (true);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for expressions. The result (bool) is currently not used for anything
- public class TPTPExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> {
-
- public static string ToString(VCExpr e, UniqueNamer namer, TPTPProverOptions opts) {
- Contract.Requires(e != null);
- Contract.Requires(namer != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- StringWriter sw = new StringWriter();
- TPTPExprLineariser lin = new TPTPExprLineariser (sw, namer, opts);
- Contract.Assert(lin!=null);
- lin.Linearise(e, LineariserOptions.Default);
- return cce.NonNull(sw.ToString());
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- private readonly TextWriter wr;
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(wr!=null);
- Contract.Invariant(Namer != null);
-}
-
- private TPTPOpLineariser OpLinObject = null;
- private IVCExprOpVisitor<bool, LineariserOptions>/*!>!*/ OpLineariser { get {
- Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool,LineariserOptions>>() !=null);
-
- if (OpLinObject == null)
- OpLinObject = new TPTPOpLineariser(this, wr);
- return OpLinObject;
- } }
-
- internal readonly UniqueNamer Namer;
- internal readonly TPTPProverOptions Options;
-
- public TPTPExprLineariser(TextWriter wr, UniqueNamer namer, TPTPProverOptions opts) {
- Contract.Requires(wr != null);Contract.Requires(namer != null);
- this.wr = wr;
- this.Namer = namer;
- this.Options = opts;
- }
-
- public void Linearise(VCExpr expr, LineariserOptions options) {
- Contract.Requires(expr != null);
- Contract.Requires(options != null);
- expr.Accept<bool, LineariserOptions>(this, options);
- }
-
- public void LineariseAsTerm(VCExpr expr, LineariserOptions options) {
- Contract.Requires(expr != null);
- Contract.Requires(options != null);
- Linearise(expr, options.SetAsTerm(true));
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public static string MakeIdPrintable(string s) {
- Contract.Requires(s != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- // make sure that no keywords are used as identifiers
- switch(s) {
- case andName:
- case orName:
- case notName:
- case impliesName:
- case iffName:
- case eqName:
- case TRUEName:
- case FALSEName:
- case "Array":
- s = "nonkeyword_" + s;
- break;
- }
-
- var res = new StringBuilder();
-
- foreach (char ch in s) {
- if (Char.IsLetterOrDigit(ch))
- res.Append(ch);
- else
- // replace everything else with a _
- res.Append('_');
- }
-
- return res.ToString();
- }
-
- public static string Lowercase(string s)
- {
- if (char.IsLower(s[0])) return MakeIdPrintable(s);
- else return MakeIdPrintable("x" + s);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- internal const string andName = "&"; // conjunction
- internal const string orName = "|"; // disjunction
- internal const string notName = "~"; // negation
- internal const string impliesName = "=>"; // implication
- internal const string iteName = "$itef"; // if-then-else
- internal const string iffName = "<=>"; // logical equivalence
- internal const string eqName = "="; // equality
- internal const string lessName = "lt";
- internal const string greaterName = "gt";
- internal const string atmostName = "le";
- internal const string atleastName = "ge";
- internal const string TRUEName = "$true"; // nullary predicate that is always true
- internal const string FALSEName = "$false"; // nullary predicate that is always false
- internal const string subtypeName = "UOrdering2";
- internal const string subtypeArgsName = "UOrdering3";
-
- internal const string boolTrueName = "boolTrue";
- internal const string boolFalseName = "boolFalse";
- internal const string boolIteName = "ite";
- internal const string intAddName = "intAdd";
- internal const string intSubName = "intSub";
- internal const string intMulName = "intMul";
- internal const string intDivName = "boogieIntDiv";
- internal const string intModName = "boogieIntMod";
-
- internal void AssertAsTerm(string x, LineariserOptions options) {
- Contract.Requires(x != null);
- Contract.Requires(options != null);
- if (!options.AsTerm)
- System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
- }
-
- internal void AssertAsFormula(string x, LineariserOptions options) {
- Contract.Requires(x != null);
- Contract.Requires(options != null);
- if (options.AsTerm)
- System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLiteral node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- if (options.AsTerm) {
-
- if (node == VCExpressionGenerator.True)
- wr.Write("{0}", boolTrueName);
- else if (node == VCExpressionGenerator.False)
- wr.Write("{0}", boolFalseName);
- else if (node is VCExprIntLit) {
- BigNum lit = ((VCExprIntLit)node).Val;
- wr.Write(lit);
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- } else {
-
- if (node == VCExpressionGenerator.True)
- wr.Write("{0}", TRUEName);
- else if (node == VCExpressionGenerator.False)
- wr.Write("{0}", FALSEName);
- else if (node is VCExprIntLit) {
- System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
- } else
- {Contract.Assert(false); throw new cce.UnreachableException();}
-
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- VCExprOp op = node.Op;
- Contract.Assert(op!=null);
-
- if (!options.AsTerm &&
- (op.Equals(VCExpressionGenerator.AndOp) ||
- op.Equals(VCExpressionGenerator.OrOp))) {
- // handle these operators without recursion
-
- var sop = op.Equals(VCExpressionGenerator.AndOp) ? andName : orName;
- wr.Write("(");
- IEnumerator enumerator = new VCExprNAryUniformOpEnumerator (node);
- Contract.Assert(enumerator!=null);
- var cnt = 0;
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(op)) {
- if (cnt > 0)
- wr.Write(" {0} ", sop);
- cnt++;
- Linearise(cce.NonNull((VCExpr)enumerator.Current), options);
- }
- }
-
- wr.Write(")");
-
- return true;
- }
-
- return node.Accept<bool, LineariserOptions/*!*/>(OpLineariser, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprVar node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- string printedName = Namer.GetName(node, MakeIdPrintable(Lowercase(node.Name)));
- Contract.Assert(printedName!=null);
-
- if (options.AsTerm ||
- // formula variables are easy to identify in SMT-Lib
- printedName[0] == '$')
- wr.Write("{0}", printedName);
- else
- wr.Write("({0} = {1})", printedName, boolTrueName);
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprQuantifier node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- AssertAsFormula(node.Quan.ToString(), options);
- Contract.Assert(node.TypeParameters.Count == 0);
-
- Namer.PushScope(); try {
-
- string kind = node.Quan == Quantifier.ALL ? "!" : "?";
- wr.Write("{0} [", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++)
- {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var!=null);
- // ensure that the variable name starts with ?
- string printedName = Namer.GetLocalName(var, "V" + MakeIdPrintable(var.Name));
- Contract.Assert(printedName!=null);
- Contract.Assert(printedName[0] == 'V');
- if (i > 0) wr.Write(",");
- wr.Write("{0}", printedName);
- }
-
- wr.Write("] : (");
-
- /* if (options.QuantifierIds) {
- // only needed for Z3
- VCQuantifierInfos! infos = node.Infos;
- if (infos.qid != null) {
- wr.Write("(QID ");
- wr.Write(infos.qid);
- wr.Write(") ");
- }
- if (0 <= infos.uniqueId) {
- wr.Write("(SKOLEMID ");
- wr.Write(infos.uniqueId);
- wr.Write(") ");
- }
- } */
-
- Linearise(node.Body, options);
-
- // WriteTriggers(node.Triggers, options);
- wr.Write(")");
-
- return true;
-
- } finally {
- Namer.PopScope();
- }
- }
-
-
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLet node, LineariserOptions options) {
- throw new NotImplementedException();
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for operator terms. The result (bool) is currently not used for anything
- internal class TPTPOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> {
- private readonly TPTPExprLineariser ExprLineariser;
- private readonly TextWriter wr;
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(wr!=null);
- Contract.Invariant(ExprLineariser!=null);
-}
-
-
- public TPTPOpLineariser(TPTPExprLineariser ExprLineariser, TextWriter wr) {
- Contract.Requires(ExprLineariser != null);
- Contract.Requires(wr != null);
- this.ExprLineariser = ExprLineariser;
- this.wr = wr;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- private void WriteApplication(string op, IEnumerable<VCExpr/*!>!*/> args,
- LineariserOptions options) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args ));
- Contract.Requires(options != null);
- WriteApplication(op, args, options, options.AsTerm);
- }
-
- private void WriteTermApplication(string op, IEnumerable<VCExpr/*!>!*/> args,
- LineariserOptions options) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args ));
- Contract.Requires(options != null);
- ExprLineariser.AssertAsTerm(op, options);
- WriteApplication(op, args, options, options.AsTerm);
- }
-
-
- private void WriteApplication(string termOp,
- IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options,
- // change the AsTerm option for the arguments?
- bool argsAsTerms) {
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args ));
- Contract.Requires(options != null);
- LineariserOptions newOptions = options.SetAsTerm(argsAsTerms);
- Contract.Assert(newOptions!=null);
-
- var argCnt = 0;
- if (termOp == "~") {
- wr.Write("(~ ");
- foreach (var e in args) {
- ExprLineariser.Linearise(e, newOptions);
- argCnt++;
- }
- Contract.Assert(argCnt == 1);
- wr.Write(")");
- } else if ("&|~=><".IndexOf(termOp[0]) >= 0) {
- wr.Write("(");
- foreach (var e in args) {
- ExprLineariser.Linearise(e, newOptions);
- argCnt++;
- if (argCnt == 1) {
- wr.Write(" {0} ", termOp);
- }
- }
- Contract.Assert(argCnt == 2);
- wr.Write(")");
- } else {
- wr.Write(termOp);
- foreach (var e in args) {
- Contract.Assert(e != null);
- if (argCnt == 0)
- wr.Write("(");
- else
- wr.Write(", ");
- argCnt++;
- ExprLineariser.Linearise(e, newOptions);
- }
-
- if (argCnt > 0)
- wr.Write(")");
- }
- }
-
- // write an application that can only be a term.
- // if the expression is supposed to be printed as a formula,
- // it is turned into an equation (EQ (f args) |@true|)
- private void WriteApplicationTermOnly(string termOp,
- IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options) {
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(options != null);
- if (!options.AsTerm)
- // Write: (EQ (f args) |@true|)
- // where "args" are written as terms
- wr.Write("(", eqName);
-
- WriteApplication(termOp, args, options, true);
-
- if (!options.AsTerm)
- wr.Write(" = {0})", boolTrueName);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public bool VisitNotOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- WriteApplication(notName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- private bool PrintEq(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(node != null);
- Contract.Requires(options != null);
- if (options.AsTerm) {
- throw new NotImplementedException();
- } else {
- if (node[0].Type.IsBool) {
- Contract.Assert(node[1].Type.IsBool);
- // use equivalence
- WriteApplication(iffName, node, options);
- } else {
- // use equality and write the arguments as terms
- WriteApplication(eqName, node, options, true);
- }
- }
-
- return true;
- }
-
- public bool VisitEqOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- return PrintEq(node, options);
- }
-
- public bool VisitNeqOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- wr.Write("(~ ");
- PrintEq(node, options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitAndOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- Contract.Assert(options.AsTerm);
- WriteApplication(andName, node, options);
- return true;
- }
-
- public bool VisitOrOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- Contract.Assert(options.AsTerm);
- WriteApplication(orName, node, options);
- return true;
- }
-
- public bool VisitImpliesOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(impliesName, node, options);
- return true;
- }
-
- public bool VisitIfThenElseOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- throw new NotImplementedException();
- }
-
- public bool VisitCustomOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- WriteApplicationTermOnly(op.Name, node, options);
- return true;
- }
-
- public bool VisitDistinctOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- ExprLineariser.AssertAsFormula("distinct", options);
-
- if (node.Length < 2) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- var bits = 0;
- var cnt = node.Length;
- while (cnt > 0) {
- cnt >>= 1;
- bits++;
- }
-
- wr.Write("($true ");
- foreach (VCExpr e in node) {
- for (var i = 0; i < bits; ++i) {
- var neg = (cnt & (1 << i)) != 0 ? "~" : "";
- wr.Write(" & {0}distinct__f__{1}(", neg, i);
- ExprLineariser.LineariseAsTerm(e, options);
- wr.Write(")");
- }
- wr.WriteLine();
- cnt++;
- }
- wr.Write(")");
- }
-
- return true;
- }
-
- public bool VisitLabelOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- //Contract.Requires(node.Length>=1);
- // VCExprLabelOp! op = (VCExprLabelOp)node.Op;
- // TODO
- // wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
- ExprLineariser.Linearise(node[0], options);
- // wr.Write(")");
- return true;
- }
-
- public bool VisitSelectOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- var name = Lowercase(SimplifyLikeExprLineariser.SelectOpName(node));
- wr.Write(name + "(");
- var cnt = 0;
- foreach (VCExpr/*!*/ e in node) {
- Contract.Assert(e != null);
- if (cnt++ > 0)
- wr.Write(", ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitStoreOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- var name = Lowercase(SimplifyLikeExprLineariser.StoreOpName(node));
- wr.Write(name + "(");
- var cnt = 0;
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- if (cnt++ > 0)
- wr.Write(", ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitBvOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- {Contract.Assert(false); throw new NotImplementedException();} // TODO
- }
-
- public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- {Contract.Assert(false); throw new NotImplementedException();} // TODO
- }
-
- public bool VisitBvConcatOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- {Contract.Assert(false); throw new NotImplementedException();} // TODO
- }
-
- public bool VisitAddOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteTermApplication(intAddName, node, options);
- return true;
- }
-
- public bool VisitSubOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteTermApplication(intSubName, node, options);
- return true;
- }
-
- public bool VisitMulOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteTermApplication(intMulName, node, options);
- return true;
- }
-
- public bool VisitDivOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteTermApplication(intDivName, node, options);
- return true;
- }
-
- public bool VisitModOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteTermApplication(intModName, node, options);
- return true;
- }
-
- public bool VisitLtOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(lessName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitLeOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(atmostName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitGtOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(greaterName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitGeOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(atleastName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitSubtypeOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(subtypeName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitSubtype3Op (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitBoogieFunctionOp (VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op!=null);
- string printedName = ExprLineariser.Namer.GetName(op.Func, Lowercase(op.Func.Name));
- Contract.Assert(printedName!=null);
-
- if (ExprLineariser.Options.UsePredicates && op.Func.OutParams[0].TypedIdent.Type.IsBool)
- WriteApplication(printedName, node, options, true);
- else
- // arguments are always terms
- WriteApplicationTermOnly(printedName, node, options);
- return true;
- }
-
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Method to turn VCExprs into strings that can be fed into TPTP provers.
+// This is currently quite similar to the
+// SimplifyLikeLineariser (but the code is independent)
+
+namespace Microsoft.Boogie.TPTP
+{
+
+ // Options for the linearisation
+ public class LineariserOptions {
+
+ public readonly bool AsTerm;
+ public LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ if (newVal)
+ return DefaultTerm;
+ else
+ return Default;
+ }
+
+ internal LineariserOptions(bool asTerm) {
+ this.AsTerm = asTerm;
+ }
+
+ [ContractInvariantMethod]
+void ObjectInvariant()
+{
+ Contract.Invariant(Default!=null);
+ Contract.Invariant(DefaultTerm!=null);
+}
+
+ public static readonly LineariserOptions Default = new LineariserOptions (false);
+ internal static readonly LineariserOptions DefaultTerm = new LineariserOptions (true);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for expressions. The result (bool) is currently not used for anything
+ public class TPTPExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> {
+
+ public static string ToString(VCExpr e, UniqueNamer namer, TPTPProverOptions opts) {
+ Contract.Requires(e != null);
+ Contract.Requires(namer != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ StringWriter sw = new StringWriter();
+ TPTPExprLineariser lin = new TPTPExprLineariser (sw, namer, opts);
+ Contract.Assert(lin!=null);
+ lin.Linearise(e, LineariserOptions.Default);
+ return cce.NonNull(sw.ToString());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private readonly TextWriter wr;
+ [ContractInvariantMethod]
+void ObjectInvariant()
+{
+ Contract.Invariant(wr!=null);
+ Contract.Invariant(Namer != null);
+}
+
+ private TPTPOpLineariser OpLinObject = null;
+ private IVCExprOpVisitor<bool, LineariserOptions>/*!>!*/ OpLineariser { get {
+ Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool,LineariserOptions>>() !=null);
+
+ if (OpLinObject == null)
+ OpLinObject = new TPTPOpLineariser(this, wr);
+ return OpLinObject;
+ } }
+
+ internal readonly UniqueNamer Namer;
+ internal readonly TPTPProverOptions Options;
+
+ public TPTPExprLineariser(TextWriter wr, UniqueNamer namer, TPTPProverOptions opts) {
+ Contract.Requires(wr != null);Contract.Requires(namer != null);
+ this.wr = wr;
+ this.Namer = namer;
+ this.Options = opts;
+ }
+
+ public void Linearise(VCExpr expr, LineariserOptions options) {
+ Contract.Requires(expr != null);
+ Contract.Requires(options != null);
+ expr.Accept<bool, LineariserOptions>(this, options);
+ }
+
+ public void LineariseAsTerm(VCExpr expr, LineariserOptions options) {
+ Contract.Requires(expr != null);
+ Contract.Requires(options != null);
+ Linearise(expr, options.SetAsTerm(true));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public static string MakeIdPrintable(string s) {
+ Contract.Requires(s != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ // make sure that no keywords are used as identifiers
+ switch(s) {
+ case andName:
+ case orName:
+ case notName:
+ case impliesName:
+ case iffName:
+ case eqName:
+ case TRUEName:
+ case FALSEName:
+ case "Array":
+ s = "nonkeyword_" + s;
+ break;
+ }
+
+ var res = new StringBuilder();
+
+ foreach (char ch in s) {
+ if (Char.IsLetterOrDigit(ch))
+ res.Append(ch);
+ else
+ // replace everything else with a _
+ res.Append('_');
+ }
+
+ return res.ToString();
+ }
+
+ public static string Lowercase(string s)
+ {
+ if (char.IsLower(s[0])) return MakeIdPrintable(s);
+ else return MakeIdPrintable("x" + s);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ internal const string andName = "&"; // conjunction
+ internal const string orName = "|"; // disjunction
+ internal const string notName = "~"; // negation
+ internal const string impliesName = "=>"; // implication
+ internal const string iteName = "$itef"; // if-then-else
+ internal const string iffName = "<=>"; // logical equivalence
+ internal const string eqName = "="; // equality
+ internal const string lessName = "lt";
+ internal const string greaterName = "gt";
+ internal const string atmostName = "le";
+ internal const string atleastName = "ge";
+ internal const string TRUEName = "$true"; // nullary predicate that is always true
+ internal const string FALSEName = "$false"; // nullary predicate that is always false
+ internal const string subtypeName = "UOrdering2";
+ internal const string subtypeArgsName = "UOrdering3";
+
+ internal const string boolTrueName = "boolTrue";
+ internal const string boolFalseName = "boolFalse";
+ internal const string boolIteName = "ite";
+ internal const string intAddName = "intAdd";
+ internal const string intSubName = "intSub";
+ internal const string intMulName = "intMul";
+ internal const string intDivName = "boogieIntDiv";
+ internal const string intModName = "boogieIntMod";
+
+ internal void AssertAsTerm(string x, LineariserOptions options) {
+ Contract.Requires(x != null);
+ Contract.Requires(options != null);
+ if (!options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
+ }
+
+ internal void AssertAsFormula(string x, LineariserOptions options) {
+ Contract.Requires(x != null);
+ Contract.Requires(options != null);
+ if (options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLiteral node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ if (options.AsTerm) {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write("{0}", boolTrueName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write("{0}", boolFalseName);
+ else if (node is VCExprIntLit) {
+ BigNum lit = ((VCExprIntLit)node).Val;
+ wr.Write(lit);
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ } else {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write("{0}", TRUEName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write("{0}", FALSEName);
+ else if (node is VCExprIntLit) {
+ System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
+ } else
+ {Contract.Assert(false); throw new cce.UnreachableException();}
+
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ VCExprOp op = node.Op;
+ Contract.Assert(op!=null);
+
+ if (!options.AsTerm &&
+ (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp))) {
+ // handle these operators without recursion
+
+ var sop = op.Equals(VCExpressionGenerator.AndOp) ? andName : orName;
+ wr.Write("(");
+ IEnumerator enumerator = new VCExprNAryUniformOpEnumerator (node);
+ Contract.Assert(enumerator!=null);
+ var cnt = 0;
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ if (cnt > 0)
+ wr.Write(" {0} ", sop);
+ cnt++;
+ Linearise(cce.NonNull((VCExpr)enumerator.Current), options);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, LineariserOptions/*!*/>(OpLineariser, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprVar node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ string printedName = Namer.GetName(node, MakeIdPrintable(Lowercase(node.Name)));
+ Contract.Assert(printedName!=null);
+
+ if (options.AsTerm ||
+ // formula variables are easy to identify in SMT-Lib
+ printedName[0] == '$')
+ wr.Write("{0}", printedName);
+ else
+ wr.Write("({0} = {1})", printedName, boolTrueName);
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprQuantifier node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ AssertAsFormula(node.Quan.ToString(), options);
+ Contract.Assert(node.TypeParameters.Count == 0);
+
+ Namer.PushScope(); try {
+
+ string kind = node.Quan == Quantifier.ALL ? "!" : "?";
+ wr.Write("{0} [", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++)
+ {
+ VCExprVar var = node.BoundVars[i];
+ Contract.Assert(var!=null);
+ // ensure that the variable name starts with ?
+ string printedName = Namer.GetLocalName(var, "V" + MakeIdPrintable(var.Name));
+ Contract.Assert(printedName!=null);
+ Contract.Assert(printedName[0] == 'V');
+ if (i > 0) wr.Write(",");
+ wr.Write("{0}", printedName);
+ }
+
+ wr.Write("] : (");
+
+ /* if (options.QuantifierIds) {
+ // only needed for Z3
+ VCQuantifierInfos! infos = node.Infos;
+ if (infos.qid != null) {
+ wr.Write("(QID ");
+ wr.Write(infos.qid);
+ wr.Write(") ");
+ }
+ if (0 <= infos.uniqueId) {
+ wr.Write("(SKOLEMID ");
+ wr.Write(infos.uniqueId);
+ wr.Write(") ");
+ }
+ } */
+
+ Linearise(node.Body, options);
+
+ // WriteTriggers(node.Triggers, options);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLet node, LineariserOptions options) {
+ throw new NotImplementedException();
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for operator terms. The result (bool) is currently not used for anything
+ internal class TPTPOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> {
+ private readonly TPTPExprLineariser ExprLineariser;
+ private readonly TextWriter wr;
+ [ContractInvariantMethod]
+void ObjectInvariant()
+{
+ Contract.Invariant(wr!=null);
+ Contract.Invariant(ExprLineariser!=null);
+}
+
+
+ public TPTPOpLineariser(TPTPExprLineariser ExprLineariser, TextWriter wr) {
+ Contract.Requires(ExprLineariser != null);
+ Contract.Requires(wr != null);
+ this.ExprLineariser = ExprLineariser;
+ this.wr = wr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ private void WriteApplication(string op, IEnumerable<VCExpr/*!>!*/> args,
+ LineariserOptions options) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args ));
+ Contract.Requires(options != null);
+ WriteApplication(op, args, options, options.AsTerm);
+ }
+
+ private void WriteTermApplication(string op, IEnumerable<VCExpr/*!>!*/> args,
+ LineariserOptions options) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args ));
+ Contract.Requires(options != null);
+ ExprLineariser.AssertAsTerm(op, options);
+ WriteApplication(op, args, options, options.AsTerm);
+ }
+
+
+ private void WriteApplication(string termOp,
+ IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options,
+ // change the AsTerm option for the arguments?
+ bool argsAsTerms) {
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args ));
+ Contract.Requires(options != null);
+ LineariserOptions newOptions = options.SetAsTerm(argsAsTerms);
+ Contract.Assert(newOptions!=null);
+
+ var argCnt = 0;
+ if (termOp == "~") {
+ wr.Write("(~ ");
+ foreach (var e in args) {
+ ExprLineariser.Linearise(e, newOptions);
+ argCnt++;
+ }
+ Contract.Assert(argCnt == 1);
+ wr.Write(")");
+ } else if ("&|~=><".IndexOf(termOp[0]) >= 0) {
+ wr.Write("(");
+ foreach (var e in args) {
+ ExprLineariser.Linearise(e, newOptions);
+ argCnt++;
+ if (argCnt == 1) {
+ wr.Write(" {0} ", termOp);
+ }
+ }
+ Contract.Assert(argCnt == 2);
+ wr.Write(")");
+ } else {
+ wr.Write(termOp);
+ foreach (var e in args) {
+ Contract.Assert(e != null);
+ if (argCnt == 0)
+ wr.Write("(");
+ else
+ wr.Write(", ");
+ argCnt++;
+ ExprLineariser.Linearise(e, newOptions);
+ }
+
+ if (argCnt > 0)
+ wr.Write(")");
+ }
+ }
+
+ // write an application that can only be a term.
+ // if the expression is supposed to be printed as a formula,
+ // it is turned into an equation (EQ (f args) |@true|)
+ private void WriteApplicationTermOnly(string termOp,
+ IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options) {
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(options != null);
+ if (!options.AsTerm)
+ // Write: (EQ (f args) |@true|)
+ // where "args" are written as terms
+ wr.Write("(", eqName);
+
+ WriteApplication(termOp, args, options, true);
+
+ if (!options.AsTerm)
+ wr.Write(" = {0})", boolTrueName);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public bool VisitNotOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ WriteApplication(notName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ private bool PrintEq(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(node != null);
+ Contract.Requires(options != null);
+ if (options.AsTerm) {
+ throw new NotImplementedException();
+ } else {
+ if (node[0].Type.IsBool) {
+ Contract.Assert(node[1].Type.IsBool);
+ // use equivalence
+ WriteApplication(iffName, node, options);
+ } else {
+ // use equality and write the arguments as terms
+ WriteApplication(eqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitEqOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ return PrintEq(node, options);
+ }
+
+ public bool VisitNeqOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ wr.Write("(~ ");
+ PrintEq(node, options);
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitAndOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ Contract.Assert(options.AsTerm);
+ WriteApplication(andName, node, options);
+ return true;
+ }
+
+ public bool VisitOrOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ Contract.Assert(options.AsTerm);
+ WriteApplication(orName, node, options);
+ return true;
+ }
+
+ public bool VisitImpliesOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(impliesName, node, options);
+ return true;
+ }
+
+ public bool VisitIfThenElseOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ throw new NotImplementedException();
+ }
+
+ public bool VisitCustomOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ VCExprCustomOp op = (VCExprCustomOp)node.Op;
+ WriteApplicationTermOnly(op.Name, node, options);
+ return true;
+ }
+
+ public bool VisitDistinctOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ ExprLineariser.AssertAsFormula("distinct", options);
+
+ if (node.Length < 2) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ var bits = 0;
+ var cnt = node.Length;
+ while (cnt > 0) {
+ cnt >>= 1;
+ bits++;
+ }
+
+ wr.Write("($true ");
+ foreach (VCExpr e in node) {
+ for (var i = 0; i < bits; ++i) {
+ var neg = (cnt & (1 << i)) != 0 ? "~" : "";
+ wr.Write(" & {0}distinct__f__{1}(", neg, i);
+ ExprLineariser.LineariseAsTerm(e, options);
+ wr.Write(")");
+ }
+ wr.WriteLine();
+ cnt++;
+ }
+ wr.Write(")");
+ }
+
+ return true;
+ }
+
+ public bool VisitLabelOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ //Contract.Requires(node.Length>=1);
+ // VCExprLabelOp! op = (VCExprLabelOp)node.Op;
+ // TODO
+ // wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
+ ExprLineariser.Linearise(node[0], options);
+ // wr.Write(")");
+ return true;
+ }
+
+ public bool VisitSelectOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ var name = Lowercase(SimplifyLikeExprLineariser.SelectOpName(node));
+ wr.Write(name + "(");
+ var cnt = 0;
+ foreach (VCExpr/*!*/ e in node) {
+ Contract.Assert(e != null);
+ if (cnt++ > 0)
+ wr.Write(", ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitStoreOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ var name = Lowercase(SimplifyLikeExprLineariser.StoreOpName(node));
+ wr.Write(name + "(");
+ var cnt = 0;
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ if (cnt++ > 0)
+ wr.Write(", ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitBvOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ {Contract.Assert(false); throw new NotImplementedException();} // TODO
+ }
+
+ public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ {Contract.Assert(false); throw new NotImplementedException();} // TODO
+ }
+
+ public bool VisitBvConcatOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ {Contract.Assert(false); throw new NotImplementedException();} // TODO
+ }
+
+ public bool VisitAddOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteTermApplication(intAddName, node, options);
+ return true;
+ }
+
+ public bool VisitSubOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteTermApplication(intSubName, node, options);
+ return true;
+ }
+
+ public bool VisitMulOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteTermApplication(intMulName, node, options);
+ return true;
+ }
+
+ public bool VisitDivOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteTermApplication(intDivName, node, options);
+ return true;
+ }
+
+ public bool VisitModOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteTermApplication(intModName, node, options);
+ return true;
+ }
+
+ public bool VisitLtOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(lessName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitLeOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(atmostName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGtOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(greaterName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGeOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(atleastName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtypeOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(subtypeName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtype3Op (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitBoogieFunctionOp (VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+
+ VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
+ Contract.Assert(op!=null);
+ string printedName = ExprLineariser.Namer.GetName(op.Func, Lowercase(op.Func.Name));
+ Contract.Assert(printedName!=null);
+
+ if (ExprLineariser.Options.UsePredicates && op.Func.OutParams[0].TypedIdent.Type.IsBool)
+ WriteApplication(printedName, node, options, true);
+ else
+ // arguments are always terms
+ WriteApplicationTermOnly(printedName, node, options);
+ return true;
+ }
+
+ }
+ }
+
+}
diff --git a/Source/Provers/TPTP/TypeDeclCollector.cs b/Source/Provers/TPTP/TypeDeclCollector.cs
index b7495659..1daf19a5 100644
--- a/Source/Provers/TPTP/TypeDeclCollector.cs
+++ b/Source/Provers/TPTP/TypeDeclCollector.cs
@@ -1,136 +1,136 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.TPTP
-{
- // Visitor for collecting the occurring function symbols in a VCExpr,
- // and for creating the corresponding declarations
-
- public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
-
- private readonly HashSet<string/*!*/>/*!*/ KnownStoreFunctions = new HashSet<string>();
- private readonly HashSet<string/*!*/>/*!*/ KnownSelectFunctions = new HashSet<string>();
-
- private readonly UniqueNamer Namer;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Namer != null);
- Contract.Invariant(AllDecls != null);
- Contract.Invariant(IncDecls != null);
- Contract.Invariant(cce.NonNull(KnownFunctions));
- Contract.Invariant(cce.NonNull(KnownVariables));
- }
-
-
- public TypeDeclCollector(UniqueNamer namer) {
- Contract.Requires(namer != null);
- this.Namer = namer;
- }
-
- // not used
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true;
- }
-
- private readonly List<string/*!>!*/> AllDecls = new List<string/*!*/> ();
- private readonly List<string/*!>!*/> IncDecls = new List<string/*!*/> ();
-
- private readonly HashSet<Function/*!*/>/*!*/ KnownFunctions = new HashSet<Function/*!*/>();
- private readonly HashSet<VCExprVar/*!*/>/*!*/ KnownVariables = new HashSet<VCExprVar/*!*/>();
-
- public List<string/*!>!*/> AllDeclarations { get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
-
- List<string>/*!>!*/ res = new List<string/*!*/> ();
- res.AddRange(AllDecls);
- return res;
- } }
-
- public List<string/*!>!*/> GetNewDeclarations() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
- List<string>/*!>!*/ res = new List<string/*!*/>();
- res.AddRange(IncDecls);
- IncDecls.Clear();
- return res;
- }
-
- private void AddDeclaration(string decl) {
- Contract.Requires(decl != null);
- AllDecls.Add(decl);
- IncDecls.Add(decl);
- }
-
- public void Collect(VCExpr expr) {
- Contract.Requires(expr != null);
- Traverse(expr, true);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
-
- if (node.Op is VCExprStoreOp) {
- string name = TPTPExprLineariser.Lowercase(SimplifyLikeExprLineariser.StoreOpName(node));
- if (!KnownStoreFunctions.Contains(name)) {
- var id = KnownStoreFunctions.Count;
-
- if (CommandLineOptions.Clo.MonomorphicArrays) {
- var sel = TPTPExprLineariser.Lowercase(SimplifyLikeExprLineariser.SelectOpName(node));
-
- var eq = "=";
- if (node[node.Arity - 1].Type.IsBool)
- eq = "<=>";
-
- string xS = "", yS = "";
- string dist = "";
-
- for (int i = 0; i < node.Arity - 2; i++) {
- if (i != 0) {
- dist += " | ";
- xS += ",";
- yS += ",";
- }
- var x = "X" + i;
- var y = "Y" + i;
- xS += x;
- yS += y;
- dist += string.Format("({0} != {1})", x, y);
- }
-
- string ax1 = "fof(selectEq" + id + ", axiom, ! [M,V," + xS + "] : (" +
- string.Format("{0}({1}(M,{2},V),{2}) {3} V", sel, name, xS, eq) + ")).";
- string ax2 = "fof(selectNeq" + id + ", axiom, ! [M,V," + xS + "," + yS + "] : (" +
- string.Format("( {0} ) => ", dist) +
- string.Format("{0}({1}(M,{2},V),{3}) {4} {0}(M,{3})", sel, name, xS, yS, eq) + ")).";
-
- AddDeclaration(ax1);
- AddDeclaration(ax2);
- }
-
- KnownStoreFunctions.Add(name);
- }
- //
- }
-
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
-
- return base.Visit(node, arg);
- }
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.TPTP
+{
+ // Visitor for collecting the occurring function symbols in a VCExpr,
+ // and for creating the corresponding declarations
+
+ public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+
+ private readonly HashSet<string/*!*/>/*!*/ KnownStoreFunctions = new HashSet<string>();
+ private readonly HashSet<string/*!*/>/*!*/ KnownSelectFunctions = new HashSet<string>();
+
+ private readonly UniqueNamer Namer;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Namer != null);
+ Contract.Invariant(AllDecls != null);
+ Contract.Invariant(IncDecls != null);
+ Contract.Invariant(cce.NonNull(KnownFunctions));
+ Contract.Invariant(cce.NonNull(KnownVariables));
+ }
+
+
+ public TypeDeclCollector(UniqueNamer namer) {
+ Contract.Requires(namer != null);
+ this.Namer = namer;
+ }
+
+ // not used
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return true;
+ }
+
+ private readonly List<string/*!>!*/> AllDecls = new List<string/*!*/> ();
+ private readonly List<string/*!>!*/> IncDecls = new List<string/*!*/> ();
+
+ private readonly HashSet<Function/*!*/>/*!*/ KnownFunctions = new HashSet<Function/*!*/>();
+ private readonly HashSet<VCExprVar/*!*/>/*!*/ KnownVariables = new HashSet<VCExprVar/*!*/>();
+
+ public List<string/*!>!*/> AllDeclarations { get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
+
+ List<string>/*!>!*/ res = new List<string/*!*/> ();
+ res.AddRange(AllDecls);
+ return res;
+ } }
+
+ public List<string/*!>!*/> GetNewDeclarations() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
+ List<string>/*!>!*/ res = new List<string/*!*/>();
+ res.AddRange(IncDecls);
+ IncDecls.Clear();
+ return res;
+ }
+
+ private void AddDeclaration(string decl) {
+ Contract.Requires(decl != null);
+ AllDecls.Add(decl);
+ IncDecls.Add(decl);
+ }
+
+ public void Collect(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Traverse(expr, true);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+
+ if (node.Op is VCExprStoreOp) {
+ string name = TPTPExprLineariser.Lowercase(SimplifyLikeExprLineariser.StoreOpName(node));
+ if (!KnownStoreFunctions.Contains(name)) {
+ var id = KnownStoreFunctions.Count;
+
+ if (CommandLineOptions.Clo.MonomorphicArrays) {
+ var sel = TPTPExprLineariser.Lowercase(SimplifyLikeExprLineariser.SelectOpName(node));
+
+ var eq = "=";
+ if (node[node.Arity - 1].Type.IsBool)
+ eq = "<=>";
+
+ string xS = "", yS = "";
+ string dist = "";
+
+ for (int i = 0; i < node.Arity - 2; i++) {
+ if (i != 0) {
+ dist += " | ";
+ xS += ",";
+ yS += ",";
+ }
+ var x = "X" + i;
+ var y = "Y" + i;
+ xS += x;
+ yS += y;
+ dist += string.Format("({0} != {1})", x, y);
+ }
+
+ string ax1 = "fof(selectEq" + id + ", axiom, ! [M,V," + xS + "] : (" +
+ string.Format("{0}({1}(M,{2},V),{2}) {3} V", sel, name, xS, eq) + ")).";
+ string ax2 = "fof(selectNeq" + id + ", axiom, ! [M,V," + xS + "," + yS + "] : (" +
+ string.Format("( {0} ) => ", dist) +
+ string.Format("{0}({1}(M,{2},V),{3}) {4} {0}(M,{3})", sel, name, xS, yS, eq) + ")).";
+
+ AddDeclaration(ax1);
+ AddDeclaration(ax2);
+ }
+
+ KnownStoreFunctions.Add(name);
+ }
+ //
+ }
+
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+
+ return base.Visit(node, arg);
+ }
+ }
+
} \ No newline at end of file
diff --git a/Source/Provers/Z3api/ContextLayer.cs b/Source/Provers/Z3api/ContextLayer.cs
index ad0c2239..87fd8c17 100644
--- a/Source/Provers/Z3api/ContextLayer.cs
+++ b/Source/Provers/Z3api/ContextLayer.cs
@@ -1,728 +1,728 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Diagnostics;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Z3;
-using Microsoft.Z3;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Basetypes;
-
-using Z3Model = Microsoft.Z3.Model;
-using BoogieModel = Microsoft.Boogie.Model;
-
-namespace Microsoft.Boogie.Z3 {
- public class Z3apiProverContext : DeclFreeProverContext {
- private BacktrackDictionary<string, Symbol> symbols = new BacktrackDictionary<string, Symbol>();
- internal BacktrackDictionary<string, Term> constants = new BacktrackDictionary<string, Term>();
- internal BacktrackDictionary<string, FuncDecl> functions = new BacktrackDictionary<string, FuncDecl>();
- internal BacktrackDictionary<string, Term> labels = new BacktrackDictionary<string, Term>();
- internal BacktrackDictionary<Term, VCExpr> constants_inv = null;
- internal BacktrackDictionary<FuncDecl, Function> functions_inv = null;
-
- public Config config;
- public Context z3;
-
- private Z3TypeCachedBuilder tm;
- private UniqueNamer namer;
- private StreamWriter z3log;
-
- private int counterexamples;
- private string logFilename;
- private List<string> debugTraces;
-
- public Z3apiProverContext(Z3InstanceOptions opts, VCExpressionGenerator gen)
- : base(gen, new VCGenerationOptions(new List<string>())) {
- int timeout = opts.Timeout * 1000;
- config = new Config();
- config.SetParamValue("MODEL", "true");
- config.SetParamValue("MODEL_V2", "true");
- config.SetParamValue("MODEL_COMPLETION", "true");
- config.SetParamValue("MBQI", "false");
- config.SetParamValue("TYPE_CHECK", "true");
- if (0 <= timeout) {
- config.SetParamValue("SOFT_TIMEOUT", timeout.ToString());
- }
-
- if (0 <= CommandLineOptions.Clo.ProverCCLimit) {
- this.counterexamples = CommandLineOptions.Clo.ProverCCLimit;
- }
- if (CommandLineOptions.Clo.SimplifyLogFilePath != null) {
- logFilename = CommandLineOptions.Clo.SimplifyLogFilePath;
- }
- this.debugTraces = new List<string>();
-
- z3 = new Context(config);
- z3.SetPrintMode(PrintMode.Smtlib2Compliant);
- if (logFilename != null)
- {
-#if true
- Z3Log.Open(logFilename);
-#else
- z3.OpenLog(logFilename);
-#endif
- }
- foreach (string tag in debugTraces)
- z3.EnableDebugTrace(tag);
-
- this.z3log = null;
- this.tm = new Z3TypeCachedBuilder(this);
- this.namer = new UniqueNamer();
- }
-
- public Z3apiProverContext(Context ctx, VCExpressionGenerator gen)
- : base(gen, new VCGenerationOptions(new List<string>()))
- {
- z3 = ctx;
-
- this.z3log = null;
- this.tm = new Z3TypeCachedBuilder(this);
- this.namer = new UniqueNamer();
-
- // For external
-
- constants_inv = new BacktrackDictionary<Term, VCExpr>();
- functions_inv = new BacktrackDictionary<FuncDecl, Function>();
- }
-
- public Term VCExprToTerm(VCExpr expr, LineariserOptions linOptions) {
- Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
- return (Term)expr.Accept(visitor, linOptions);
- }
-
-
- private class fromZ3
- {
- private VCExpressionGenerator gen;
- private Dictionary<Term, VCExpr> memo;
- private BacktrackDictionary<Term, VCExpr> constants_inv;
- private BacktrackDictionary<FuncDecl, Function> functions_inv;
- private List<VCExprLetBinding> lets;
- private int let_ctr = 0;
-
- private VCExpr create_let(Term t, VCExpr u)
- {
- var name = "$x" + let_ctr.ToString();
- let_ctr++;
- var sym = gen.Variable(name, u.Type);
- memo.Remove(t);
- memo.Add(t, sym);
- lets.Add(gen.LetBinding(sym, u));
- return sym;
- }
-
- public fromZ3(VCExpressionGenerator _gen,
- BacktrackDictionary<Term, VCExpr> _constants_inv,
- BacktrackDictionary<FuncDecl, Function> _functions_inv)
- {
- gen = _gen;
- constants_inv = _constants_inv;
- functions_inv = _functions_inv;
- memo = new Dictionary<Term, VCExpr>();
- lets = new List<VCExprLetBinding>();
- }
-
- public void clear()
- {
- memo.Clear();
- lets.Clear();
- }
- public VCExpr get(Term arg)
- {
- if (memo.ContainsKey(arg))
- return memo[arg];
- VCExpr res = null;
- switch (arg.GetKind())
- {
- case TermKind.Numeral:
- var numstr = arg.GetNumeralString();
- if (arg.GetSort().GetSortKind() == SortKind.Int) {
- res = gen.Integer(Basetypes.BigNum.FromString(numstr));
- }
- else {
- res = gen.Real(Basetypes.BigDec.FromString(numstr));
- }
- break;
- case TermKind.App:
- var args = arg.GetAppArgs();
- var vcargs = new VCExpr[args.Length];
- for (int i = 0; i < args.Length; i++)
- vcargs[i] = get(args[i]);
-
- switch (arg.GetAppDecl().GetKind())
- {
- case DeclKind.Add:
- if (vcargs.Length == 0) {
- if (arg.GetSort().GetSortKind() == SortKind.Int) {
- res = gen.Integer(Basetypes.BigNum.ZERO);
- }
- else {
- res = gen.Real(Basetypes.BigDec.ZERO);
- }
- }
- else
- {
- res = vcargs[0];
- for (int k = 1; k < vcargs.Length; k++)
- res = gen.Add(res, vcargs[k]);
- }
- break;
- case DeclKind.And:
- res = VCExpressionGenerator.True;
- for (int i = 0; i < vcargs.Length; i++)
- res = gen.AndSimp(res, vcargs[i]);
- break;
- case DeclKind.Div:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.RealDivOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Eq:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Eq(vcargs[0], vcargs[1]);
- break;
- case DeclKind.False:
- res = VCExpressionGenerator.False;
- break;
- case DeclKind.Ge:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.GeOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Gt:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Gt(vcargs[0], vcargs[1]);
- break;
- case DeclKind.IDiv:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.DivOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Iff:
- Debug.Assert(vcargs.Length == 2);
- var l = create_let(args[0], vcargs[0]);
- var r = create_let(args[1], vcargs[1]);
- return gen.And(gen.Implies(l, r), gen.Implies(r, l));
- case DeclKind.Implies:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Implies(vcargs[0], vcargs[1]);
- break;
- case DeclKind.Ite:
- Debug.Assert(vcargs.Length == 3);
- res = gen.Function(VCExpressionGenerator.IfThenElseOp, vcargs[0], vcargs[1], vcargs[2]);
- break;
- case DeclKind.Le:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.LeOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Lt:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.LtOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Mod:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.ModOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Mul:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.MulOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.Not:
- Debug.Assert(vcargs.Length == 1);
- res = gen.Not(vcargs[0]);
- break;
- case DeclKind.Or:
- res = VCExpressionGenerator.False;
- for (int i = 0; i < vcargs.Length; i++)
- res = gen.OrSimp(res, vcargs[i]);
- break;
- case DeclKind.Select:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Select(vcargs[0], vcargs[1]);
- break;
- case DeclKind.Store:
- Debug.Assert(vcargs.Length == 3);
- res = gen.Store(vcargs[0], vcargs[1], vcargs[2]);
- break;
- case DeclKind.Sub:
- Debug.Assert(vcargs.Length == 2);
- res = gen.Function(VCExpressionGenerator.SubOp, vcargs[0], vcargs[1]);
- break;
- case DeclKind.True:
- res = VCExpressionGenerator.True;
- break;
- case DeclKind.Uminus:
- Debug.Assert(vcargs.Length == 1);
- var argzero = null;
- if (vcargs[0].Type.IsInt) {
- argzero = gen.Integer(Basetypes.BigNum.ZERO);
- }
- else {
- argzero = gen.Real(Basetypes.BigDec.ZERO);
- }
- res = gen.Function(VCExpressionGenerator.SubOp, argzero, vcargs[0]);
- break;
- case DeclKind.ToInt:
- Debug.Assert(vcargs.Length == 1);
- res = gen.Function(VCExpressionGenerator.ToIntOp, vcargs[0]);
- break;
- case DeclKind.ToReal:
- Debug.Assert(vcargs.Length == 1);
- res = gen.Function(VCExpressionGenerator.ToRealOp, vcargs[0]);
- break;
- case DeclKind.Uninterpreted:
- var name = arg.GetAppDecl().GetDeclName();
- if (args.Length == 0)
- { // a 0-ary constant is a VCExprVar
- if (!constants_inv.TryGetValue(arg, out res))
- throw new Exception("Z3 returned unknown constant: " + name);
- }
- else
- {
- Function f;
- if (!functions_inv.TryGetValue(arg.GetAppDecl(), out f))
- throw new Exception("Z3 returned unknown function: " + name);
- List<VCExpr> vcargsList = new List<VCExpr>(vcargs);
- res = gen.Function(f, vcargsList);
- }
- break;
- default:
- throw new Exception("Unknown Z3 operator");
- }
- break;
- default:
- Debug.Assert(false);
- throw new Exception("Unknown Z3 AST kind");
- }
-
- memo.Add(arg, res);
- return res;
- }
- public VCExpr add_lets(VCExpr e)
- {
- foreach (var let in lets)
- {
- e = gen.Let(e, let);
- }
- return e;
- }
- }
-
- public VCExpr TermToVCExpr(Term t)
- {
- var fZ = new fromZ3(gen, constants_inv, functions_inv);
- return fZ.add_lets(fZ.get(t));
- }
-
-
-
-
-
- public override void DeclareType(TypeCtorDecl t, string attributes) {
- base.DeclareType(t, attributes);
- log("(declare-sort {0})", t.Name);
- }
-
- public override void DeclareConstant(Constant c, bool uniq, string attributes) {
- base.DeclareConstant(c, uniq, attributes);
- DeclareConstant(c.Name, c.TypedIdent.Type);
- }
-
- public override void DeclareFunction(Function f, string attributes) {
- base.DeclareFunction(f, attributes);
- List<Type> domain = new List<Type>();
- foreach (Variable v in f.InParams) {
- domain.Add(v.TypedIdent.Type);
- }
- if (f.OutParams.Length != 1)
- throw new Exception("Cannot handle functions with " + f.OutParams + " out parameters.");
- Type range = f.OutParams[0].TypedIdent.Type;
-
- string functionName = f.Name;
- Symbol symbolAst = GetSymbol(functionName);
- var domainStr = "";
- List<Sort> domainAst = new List<Sort>();
- foreach (Type domainType in domain) {
- Sort type = tm.GetType(domainType);
- domainAst.Add(type);
- domainStr += type.ToString() + " ";
- }
- Sort rangeAst = tm.GetType(range);
- FuncDecl constDeclAst = z3.MkFuncDecl(symbolAst, domainAst.ToArray(), rangeAst);
- functions.Add(functionName, constDeclAst);
- if(functions_inv != null)functions_inv.Add(constDeclAst, f);
- log("(declare-funs (({0} {1} {2})))", functionName, domainStr, rangeAst);
- }
-
- public override void DeclareGlobalVariable(GlobalVariable v, string attributes) {
- base.DeclareGlobalVariable(v, attributes);
- DeclareConstant(v.Name, v.TypedIdent.Type);
- }
-
- public override string Lookup(VCExprVar var) {
- return namer.Lookup(var);
- }
-
- public void log(string format, params object[] args) {
- // Currently, this is a no-op because z3log is always null
- // We use the default (automatic) tracing facility of z3
- if (z3log != null) {
- var str = string.Format(format, args);
- // Do standard string replacement
- str = str.Replace("array", "Array");
- z3log.WriteLine(str);
- z3log.Flush();
- }
- }
-
- public void CloseLog() {
-#if true
- Z3Log.Close();
-#else
- z3.CloseLog();
-#endif
- if (z3log != null) {
- z3log.Close();
- }
- z3log = null;
- }
-
- public void CreateBacktrackPoint() {
- symbols.CreateBacktrackPoint();
- constants.CreateBacktrackPoint();
- functions.CreateBacktrackPoint();
- labels.CreateBacktrackPoint();
- if(constants_inv != null)constants_inv.CreateBacktrackPoint();
- if(functions_inv != null)functions_inv.CreateBacktrackPoint();
- z3.Push();
- log("(push)");
- }
-
- public void Backtrack() {
- z3.Pop();
- labels.Backtrack();
- functions.Backtrack();
- constants.Backtrack();
- symbols.Backtrack();
- if (constants_inv != null) constants_inv.Backtrack();
- if (functions_inv != null) functions_inv.Backtrack();
- log("(pop)");
- }
-
- public void AddAxiom(VCExpr axiom, LineariserOptions linOptions) {
- Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
- Term term = (Term)axiom.Accept(visitor, linOptions);
- log("(assert {0})", term);
- z3.AssertCnstr(term);
- }
-
- public void AddConjecture(VCExpr vc, LineariserOptions linOptions) {
- VCExpr not_vc = (VCExpr)this.gen.Not(vc);
- Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
- Term term = (Term)not_vc.Accept(visitor, linOptions);
- log("(assert {0})", term);
- z3.AssertCnstr(term);
- }
-
- public void AddSmtlibString(string smtlibString) {
- FuncDecl[] decls;
- Term[] assumptions;
- Term[] terms;
- Sort[] sorts;
- string tmp;
-
- z3.ParseSmtlibString(smtlibString, new Sort[] { }, new FuncDecl[] { },
- out assumptions, out terms, out decls, out sorts, out tmp);
- // TBD: check with Nikolaj about the correct position of assumptions
- foreach (FuncDecl decl in decls) {
- Symbol symbol = z3.GetDeclName(decl);
- string functionName = z3.GetSymbolString(symbol);
- functions.Add(functionName, decl);
- }
- foreach (Term assumption in assumptions) {
- log("(assert {0})", assumption);
- z3.AssertCnstr(assumption);
- }
- }
-
- private List<Sort> GetTypes(List<Type> boogieTypes) {
- List<Sort> z3Types = new List<Sort>();
- foreach (Type boogieType in boogieTypes) {
- Sort type = tm.GetType(boogieType);
- z3Types.Add(type);
- }
- return z3Types;
- }
-
- private static bool Equals(List<string> l, List<string> r) {
- Debug.Assert(l != null);
- if (r == null)
- return false;
-
- if (l.Count != r.Count)
- return false;
-
- for (int i = 0; i < l.Count; i++)
- if (!l[i].Equals(r[i]))
- return false;
- return true;
- }
-
- private void DisplayRelevantLabels(List<string> relevantLabels) {
- foreach (string labelName in relevantLabels) {
- System.Console.Write(labelName + ",");
- }
- System.Console.WriteLine("---");
- }
-
- private void DeclareConstant(string constantName, Type boogieType) {
- Symbol symbolAst = GetSymbol(constantName);
- Sort typeAst = tm.GetType(boogieType);
-
- Term constAst = z3.MkConst(symbolAst, typeAst);
- constants.Add(constantName, constAst);
- log("(declare-funs (({0} {1})))", constAst, typeAst);
- }
-
- public ProverInterface.Outcome Check(out List<Z3ErrorModelAndLabels> boogieErrors) {
- Microsoft.Boogie.Helpers.ExtraTraceInformation("Sending data to the theorem prover");
- boogieErrors = new List<Z3ErrorModelAndLabels>();
- LBool outcome = LBool.Undef;
- Debug.Assert(0 < this.counterexamples);
- while (true) {
- Z3Model z3Model;
- outcome = z3.CheckAndGetModel(out z3Model);
-
- log("(check-sat)");
- if (outcome == LBool.False)
- break;
-
- if (outcome == LBool.Undef && z3Model == null) {
- // Blame this on timeout
- return ProverInterface.Outcome.TimeOut;
- }
-
- Debug.Assert(z3Model != null);
- LabeledLiterals labels = z3.GetRelevantLabels();
- Debug.Assert(labels != null);
-
- List<string> labelStrings = new List<string>();
- uint numLabels = labels.GetNumLabels();
- for (uint i = 0; i < numLabels; ++i) {
- Symbol sym = labels.GetLabel(i);
- string labelName = z3.GetSymbolString(sym);
- if (!labelName.StartsWith("@")) {
- labels.Disable(i);
- }
- labelStrings.Add(labelName);
- }
-
- var sw = new StringWriter();
- sw.WriteLine("*** MODEL");
- z3Model.Display(sw);
- sw.WriteLine("*** END_MODEL");
- var sr = new StringReader(sw.ToString());
- var models = Microsoft.Boogie.Model.ParseModels(sr);
- Z3ErrorModelAndLabels e = new Z3ErrorModelAndLabels(models[0], new List<string>(labelStrings));
- boogieErrors.Add(e);
-
- if (boogieErrors.Count < this.counterexamples) {
- z3.BlockLiterals(labels);
- log("block-literals {0}", labels);
- }
-
- labels.Dispose();
- z3Model.Dispose();
- if (boogieErrors.Count == this.counterexamples)
- break;
- }
-
- if (boogieErrors.Count > 0) {
- return ProverInterface.Outcome.Invalid;
- }
- else if (outcome == LBool.False) {
- return ProverInterface.Outcome.Valid;
- }
- else {
- Debug.Assert(outcome == LBool.Undef);
- return ProverInterface.Outcome.Undetermined;
- }
- }
-
- public ProverInterface.Outcome CheckAssumptions(List<VCExpr> assumptions, LineariserOptions linOptions,
- out List<Z3ErrorModelAndLabels> boogieErrors,
- out List<int> unsatCore) {
- Microsoft.Boogie.Helpers.ExtraTraceInformation("Sending data to the theorem prover");
- boogieErrors = new List<Z3ErrorModelAndLabels>();
- unsatCore = new List<int>();
- LBool outcome = LBool.Undef;
-
- Z3Model z3Model;
- Term proof;
- Term[] core;
- Term[] assumption_terms = new Term[assumptions.Count];
- var logstring = "";
- for (int i = 0; i < assumptions.Count; i++) {
- Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
- Term z3ast = (Term)assumptions[i].Accept(visitor, linOptions);
- assumption_terms[i] = z3ast;
- logstring += string.Format("({0}) ", assumption_terms[i]);
- }
-
- log("(get-core {0})", logstring);
- outcome = z3.CheckAssumptions(out z3Model, assumption_terms, out proof, out core);
-
- if (outcome != LBool.False) {
- Debug.Assert(z3Model != null);
- LabeledLiterals labels = z3.GetRelevantLabels();
- Debug.Assert(labels != null);
-
- List<string> labelStrings = new List<string>();
- uint numLabels = labels.GetNumLabels();
- for (uint i = 0; i < numLabels; ++i) {
- Symbol sym = labels.GetLabel(i);
- string labelName = z3.GetSymbolString(sym);
- if (!labelName.StartsWith("@")) {
- labels.Disable(i);
- }
- labelStrings.Add(labelName);
- }
-
- var sw = new StringWriter();
- sw.WriteLine("*** MODEL");
- z3Model.Display(sw);
- sw.WriteLine("*** END_MODEL");
- var sr = new StringReader(sw.ToString());
- var models = Microsoft.Boogie.Model.ParseModels(sr);
- Z3ErrorModelAndLabels e = new Z3ErrorModelAndLabels(models[0], new List<string>(labelStrings));
- boogieErrors.Add(e);
-
- labels.Dispose();
- z3Model.Dispose();
- }
-
- if (boogieErrors.Count > 0) {
- return ProverInterface.Outcome.Invalid;
- }
- else if (outcome == LBool.False) {
- foreach (Term t in core) {
- for (int i = 0; i < assumption_terms.Length; i++) {
- if (t.Equals(assumption_terms[i]))
- unsatCore.Add(i);
- }
- }
- return ProverInterface.Outcome.Valid;
- }
- else {
- Debug.Assert(outcome == LBool.Undef);
- return ProverInterface.Outcome.Undetermined;
- }
- }
-
- private Symbol GetSymbol(string symbolName) {
- if (!symbols.ContainsKey(symbolName)) {
- Symbol symbolAst = z3.MkSymbol(symbolName);
- symbols.Add(symbolName, symbolAst);
- }
- Symbol result;
- if (!symbols.TryGetValue(symbolName, out result))
- throw new Exception("symbol " + symbolName + " is undefined");
- return result;
- }
-
- public Term GetConstant(string constantName, Type constantType, VCExpr node)
- {
- Term typeSafeTerm;
- if (!constants.ContainsKey(constantName))
- this.DeclareConstant(constantName, constantType);
-
- if (!constants.TryGetValue(constantName, out typeSafeTerm))
- throw new Exception("constant " + constantName + " is not defined");
-
- if (constants_inv != null && !constants_inv.ContainsKey(typeSafeTerm))
- constants_inv.Add(typeSafeTerm, node);
-
- return typeSafeTerm;
- }
-
- public FuncDecl GetFunction(string functionName) {
- FuncDecl f;
- if (!functions.TryGetValue(functionName, out f))
- throw new Exception("function " + functionName + " is undefined");
- return f;
- }
-
- public Term MakeLabel(string labelName, bool pos, Term child) {
- Symbol labelSymbol = this.GetSymbol(labelName);
- Term labeledExpr = z3.MkLabel(labelSymbol, pos, child);
- labels.Add(labelName, labeledExpr);
- return labeledExpr;
- }
-
- public LabeledLiterals GetRelevantLabels() {
- LabeledLiterals safeLiterals = z3.GetRelevantLabels();
- log("get-relevant-labels");
- return safeLiterals;
- }
- }
-
- internal class BacktrackDictionary<K, V> {
- private Dictionary<K, V> dictionary = new Dictionary<K, V>();
- private Stack<List<K>> keyStack = new Stack<List<K>>();
-
- public BacktrackDictionary() {
- CreateBacktrackPoint();
- }
-
- public bool TryGetValue(K key, out V val) {
- return dictionary.TryGetValue(key, out val);
- }
-
- public void Add(K key, V v) {
- if (dictionary.ContainsKey(key)) {
- dictionary.Remove(key);
- }
- dictionary.Add(key, v);
- keyStack.Peek().Add(key);
- }
-
- public bool ContainsKey(K k) {
- return dictionary.ContainsKey(k);
- }
-
- public void CreateBacktrackPoint() {
- keyStack.Push(new List<K>());
- }
-
- public void Backtrack() {
- List<K> keysToErase = keyStack.Pop();
- foreach (K key in keysToErase) {
- dictionary.Remove(key);
- }
- if (keyStack.Count == 0)
- this.CreateBacktrackPoint();
- }
-
- public IEnumerator GetEnumerator() {
- return dictionary.Keys.GetEnumerator();
- }
- }
-
- public class Z3ErrorModelAndLabels {
- private Model _model;
- private List<string> _relevantLabels;
- public Model Model {
- get { return this._model; }
- }
- public List<string> RelevantLabels {
- get { return this._relevantLabels; }
- }
- public Z3ErrorModelAndLabels(Model model, List<string> relevantLabels) {
- this._model = model;
- this._relevantLabels = relevantLabels;
- }
- }
-
-
-
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Z3;
+using Microsoft.Z3;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Basetypes;
+
+using Z3Model = Microsoft.Z3.Model;
+using BoogieModel = Microsoft.Boogie.Model;
+
+namespace Microsoft.Boogie.Z3 {
+ public class Z3apiProverContext : DeclFreeProverContext {
+ private BacktrackDictionary<string, Symbol> symbols = new BacktrackDictionary<string, Symbol>();
+ internal BacktrackDictionary<string, Term> constants = new BacktrackDictionary<string, Term>();
+ internal BacktrackDictionary<string, FuncDecl> functions = new BacktrackDictionary<string, FuncDecl>();
+ internal BacktrackDictionary<string, Term> labels = new BacktrackDictionary<string, Term>();
+ internal BacktrackDictionary<Term, VCExpr> constants_inv = null;
+ internal BacktrackDictionary<FuncDecl, Function> functions_inv = null;
+
+ public Config config;
+ public Context z3;
+
+ private Z3TypeCachedBuilder tm;
+ private UniqueNamer namer;
+ private StreamWriter z3log;
+
+ private int counterexamples;
+ private string logFilename;
+ private List<string> debugTraces;
+
+ public Z3apiProverContext(Z3InstanceOptions opts, VCExpressionGenerator gen)
+ : base(gen, new VCGenerationOptions(new List<string>())) {
+ int timeout = opts.Timeout * 1000;
+ config = new Config();
+ config.SetParamValue("MODEL", "true");
+ config.SetParamValue("MODEL_V2", "true");
+ config.SetParamValue("MODEL_COMPLETION", "true");
+ config.SetParamValue("MBQI", "false");
+ config.SetParamValue("TYPE_CHECK", "true");
+ if (0 <= timeout) {
+ config.SetParamValue("SOFT_TIMEOUT", timeout.ToString());
+ }
+
+ if (0 <= CommandLineOptions.Clo.ProverCCLimit) {
+ this.counterexamples = CommandLineOptions.Clo.ProverCCLimit;
+ }
+ if (CommandLineOptions.Clo.SimplifyLogFilePath != null) {
+ logFilename = CommandLineOptions.Clo.SimplifyLogFilePath;
+ }
+ this.debugTraces = new List<string>();
+
+ z3 = new Context(config);
+ z3.SetPrintMode(PrintMode.Smtlib2Compliant);
+ if (logFilename != null)
+ {
+#if true
+ Z3Log.Open(logFilename);
+#else
+ z3.OpenLog(logFilename);
+#endif
+ }
+ foreach (string tag in debugTraces)
+ z3.EnableDebugTrace(tag);
+
+ this.z3log = null;
+ this.tm = new Z3TypeCachedBuilder(this);
+ this.namer = new UniqueNamer();
+ }
+
+ public Z3apiProverContext(Context ctx, VCExpressionGenerator gen)
+ : base(gen, new VCGenerationOptions(new List<string>()))
+ {
+ z3 = ctx;
+
+ this.z3log = null;
+ this.tm = new Z3TypeCachedBuilder(this);
+ this.namer = new UniqueNamer();
+
+ // For external
+
+ constants_inv = new BacktrackDictionary<Term, VCExpr>();
+ functions_inv = new BacktrackDictionary<FuncDecl, Function>();
+ }
+
+ public Term VCExprToTerm(VCExpr expr, LineariserOptions linOptions) {
+ Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
+ return (Term)expr.Accept(visitor, linOptions);
+ }
+
+
+ private class fromZ3
+ {
+ private VCExpressionGenerator gen;
+ private Dictionary<Term, VCExpr> memo;
+ private BacktrackDictionary<Term, VCExpr> constants_inv;
+ private BacktrackDictionary<FuncDecl, Function> functions_inv;
+ private List<VCExprLetBinding> lets;
+ private int let_ctr = 0;
+
+ private VCExpr create_let(Term t, VCExpr u)
+ {
+ var name = "$x" + let_ctr.ToString();
+ let_ctr++;
+ var sym = gen.Variable(name, u.Type);
+ memo.Remove(t);
+ memo.Add(t, sym);
+ lets.Add(gen.LetBinding(sym, u));
+ return sym;
+ }
+
+ public fromZ3(VCExpressionGenerator _gen,
+ BacktrackDictionary<Term, VCExpr> _constants_inv,
+ BacktrackDictionary<FuncDecl, Function> _functions_inv)
+ {
+ gen = _gen;
+ constants_inv = _constants_inv;
+ functions_inv = _functions_inv;
+ memo = new Dictionary<Term, VCExpr>();
+ lets = new List<VCExprLetBinding>();
+ }
+
+ public void clear()
+ {
+ memo.Clear();
+ lets.Clear();
+ }
+ public VCExpr get(Term arg)
+ {
+ if (memo.ContainsKey(arg))
+ return memo[arg];
+ VCExpr res = null;
+ switch (arg.GetKind())
+ {
+ case TermKind.Numeral:
+ var numstr = arg.GetNumeralString();
+ if (arg.GetSort().GetSortKind() == SortKind.Int) {
+ res = gen.Integer(Basetypes.BigNum.FromString(numstr));
+ }
+ else {
+ res = gen.Real(Basetypes.BigDec.FromString(numstr));
+ }
+ break;
+ case TermKind.App:
+ var args = arg.GetAppArgs();
+ var vcargs = new VCExpr[args.Length];
+ for (int i = 0; i < args.Length; i++)
+ vcargs[i] = get(args[i]);
+
+ switch (arg.GetAppDecl().GetKind())
+ {
+ case DeclKind.Add:
+ if (vcargs.Length == 0) {
+ if (arg.GetSort().GetSortKind() == SortKind.Int) {
+ res = gen.Integer(Basetypes.BigNum.ZERO);
+ }
+ else {
+ res = gen.Real(Basetypes.BigDec.ZERO);
+ }
+ }
+ else
+ {
+ res = vcargs[0];
+ for (int k = 1; k < vcargs.Length; k++)
+ res = gen.Add(res, vcargs[k]);
+ }
+ break;
+ case DeclKind.And:
+ res = VCExpressionGenerator.True;
+ for (int i = 0; i < vcargs.Length; i++)
+ res = gen.AndSimp(res, vcargs[i]);
+ break;
+ case DeclKind.Div:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.RealDivOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Eq:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Eq(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.False:
+ res = VCExpressionGenerator.False;
+ break;
+ case DeclKind.Ge:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.GeOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Gt:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Gt(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.IDiv:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.DivOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Iff:
+ Debug.Assert(vcargs.Length == 2);
+ var l = create_let(args[0], vcargs[0]);
+ var r = create_let(args[1], vcargs[1]);
+ return gen.And(gen.Implies(l, r), gen.Implies(r, l));
+ case DeclKind.Implies:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Implies(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Ite:
+ Debug.Assert(vcargs.Length == 3);
+ res = gen.Function(VCExpressionGenerator.IfThenElseOp, vcargs[0], vcargs[1], vcargs[2]);
+ break;
+ case DeclKind.Le:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.LeOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Lt:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.LtOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Mod:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.ModOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Mul:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.MulOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Not:
+ Debug.Assert(vcargs.Length == 1);
+ res = gen.Not(vcargs[0]);
+ break;
+ case DeclKind.Or:
+ res = VCExpressionGenerator.False;
+ for (int i = 0; i < vcargs.Length; i++)
+ res = gen.OrSimp(res, vcargs[i]);
+ break;
+ case DeclKind.Select:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Select(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Store:
+ Debug.Assert(vcargs.Length == 3);
+ res = gen.Store(vcargs[0], vcargs[1], vcargs[2]);
+ break;
+ case DeclKind.Sub:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.SubOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.True:
+ res = VCExpressionGenerator.True;
+ break;
+ case DeclKind.Uminus:
+ Debug.Assert(vcargs.Length == 1);
+ var argzero = null;
+ if (vcargs[0].Type.IsInt) {
+ argzero = gen.Integer(Basetypes.BigNum.ZERO);
+ }
+ else {
+ argzero = gen.Real(Basetypes.BigDec.ZERO);
+ }
+ res = gen.Function(VCExpressionGenerator.SubOp, argzero, vcargs[0]);
+ break;
+ case DeclKind.ToInt:
+ Debug.Assert(vcargs.Length == 1);
+ res = gen.Function(VCExpressionGenerator.ToIntOp, vcargs[0]);
+ break;
+ case DeclKind.ToReal:
+ Debug.Assert(vcargs.Length == 1);
+ res = gen.Function(VCExpressionGenerator.ToRealOp, vcargs[0]);
+ break;
+ case DeclKind.Uninterpreted:
+ var name = arg.GetAppDecl().GetDeclName();
+ if (args.Length == 0)
+ { // a 0-ary constant is a VCExprVar
+ if (!constants_inv.TryGetValue(arg, out res))
+ throw new Exception("Z3 returned unknown constant: " + name);
+ }
+ else
+ {
+ Function f;
+ if (!functions_inv.TryGetValue(arg.GetAppDecl(), out f))
+ throw new Exception("Z3 returned unknown function: " + name);
+ List<VCExpr> vcargsList = new List<VCExpr>(vcargs);
+ res = gen.Function(f, vcargsList);
+ }
+ break;
+ default:
+ throw new Exception("Unknown Z3 operator");
+ }
+ break;
+ default:
+ Debug.Assert(false);
+ throw new Exception("Unknown Z3 AST kind");
+ }
+
+ memo.Add(arg, res);
+ return res;
+ }
+ public VCExpr add_lets(VCExpr e)
+ {
+ foreach (var let in lets)
+ {
+ e = gen.Let(e, let);
+ }
+ return e;
+ }
+ }
+
+ public VCExpr TermToVCExpr(Term t)
+ {
+ var fZ = new fromZ3(gen, constants_inv, functions_inv);
+ return fZ.add_lets(fZ.get(t));
+ }
+
+
+
+
+
+ public override void DeclareType(TypeCtorDecl t, string attributes) {
+ base.DeclareType(t, attributes);
+ log("(declare-sort {0})", t.Name);
+ }
+
+ public override void DeclareConstant(Constant c, bool uniq, string attributes) {
+ base.DeclareConstant(c, uniq, attributes);
+ DeclareConstant(c.Name, c.TypedIdent.Type);
+ }
+
+ public override void DeclareFunction(Function f, string attributes) {
+ base.DeclareFunction(f, attributes);
+ List<Type> domain = new List<Type>();
+ foreach (Variable v in f.InParams) {
+ domain.Add(v.TypedIdent.Type);
+ }
+ if (f.OutParams.Length != 1)
+ throw new Exception("Cannot handle functions with " + f.OutParams + " out parameters.");
+ Type range = f.OutParams[0].TypedIdent.Type;
+
+ string functionName = f.Name;
+ Symbol symbolAst = GetSymbol(functionName);
+ var domainStr = "";
+ List<Sort> domainAst = new List<Sort>();
+ foreach (Type domainType in domain) {
+ Sort type = tm.GetType(domainType);
+ domainAst.Add(type);
+ domainStr += type.ToString() + " ";
+ }
+ Sort rangeAst = tm.GetType(range);
+ FuncDecl constDeclAst = z3.MkFuncDecl(symbolAst, domainAst.ToArray(), rangeAst);
+ functions.Add(functionName, constDeclAst);
+ if(functions_inv != null)functions_inv.Add(constDeclAst, f);
+ log("(declare-funs (({0} {1} {2})))", functionName, domainStr, rangeAst);
+ }
+
+ public override void DeclareGlobalVariable(GlobalVariable v, string attributes) {
+ base.DeclareGlobalVariable(v, attributes);
+ DeclareConstant(v.Name, v.TypedIdent.Type);
+ }
+
+ public override string Lookup(VCExprVar var) {
+ return namer.Lookup(var);
+ }
+
+ public void log(string format, params object[] args) {
+ // Currently, this is a no-op because z3log is always null
+ // We use the default (automatic) tracing facility of z3
+ if (z3log != null) {
+ var str = string.Format(format, args);
+ // Do standard string replacement
+ str = str.Replace("array", "Array");
+ z3log.WriteLine(str);
+ z3log.Flush();
+ }
+ }
+
+ public void CloseLog() {
+#if true
+ Z3Log.Close();
+#else
+ z3.CloseLog();
+#endif
+ if (z3log != null) {
+ z3log.Close();
+ }
+ z3log = null;
+ }
+
+ public void CreateBacktrackPoint() {
+ symbols.CreateBacktrackPoint();
+ constants.CreateBacktrackPoint();
+ functions.CreateBacktrackPoint();
+ labels.CreateBacktrackPoint();
+ if(constants_inv != null)constants_inv.CreateBacktrackPoint();
+ if(functions_inv != null)functions_inv.CreateBacktrackPoint();
+ z3.Push();
+ log("(push)");
+ }
+
+ public void Backtrack() {
+ z3.Pop();
+ labels.Backtrack();
+ functions.Backtrack();
+ constants.Backtrack();
+ symbols.Backtrack();
+ if (constants_inv != null) constants_inv.Backtrack();
+ if (functions_inv != null) functions_inv.Backtrack();
+ log("(pop)");
+ }
+
+ public void AddAxiom(VCExpr axiom, LineariserOptions linOptions) {
+ Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
+ Term term = (Term)axiom.Accept(visitor, linOptions);
+ log("(assert {0})", term);
+ z3.AssertCnstr(term);
+ }
+
+ public void AddConjecture(VCExpr vc, LineariserOptions linOptions) {
+ VCExpr not_vc = (VCExpr)this.gen.Not(vc);
+ Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
+ Term term = (Term)not_vc.Accept(visitor, linOptions);
+ log("(assert {0})", term);
+ z3.AssertCnstr(term);
+ }
+
+ public void AddSmtlibString(string smtlibString) {
+ FuncDecl[] decls;
+ Term[] assumptions;
+ Term[] terms;
+ Sort[] sorts;
+ string tmp;
+
+ z3.ParseSmtlibString(smtlibString, new Sort[] { }, new FuncDecl[] { },
+ out assumptions, out terms, out decls, out sorts, out tmp);
+ // TBD: check with Nikolaj about the correct position of assumptions
+ foreach (FuncDecl decl in decls) {
+ Symbol symbol = z3.GetDeclName(decl);
+ string functionName = z3.GetSymbolString(symbol);
+ functions.Add(functionName, decl);
+ }
+ foreach (Term assumption in assumptions) {
+ log("(assert {0})", assumption);
+ z3.AssertCnstr(assumption);
+ }
+ }
+
+ private List<Sort> GetTypes(List<Type> boogieTypes) {
+ List<Sort> z3Types = new List<Sort>();
+ foreach (Type boogieType in boogieTypes) {
+ Sort type = tm.GetType(boogieType);
+ z3Types.Add(type);
+ }
+ return z3Types;
+ }
+
+ private static bool Equals(List<string> l, List<string> r) {
+ Debug.Assert(l != null);
+ if (r == null)
+ return false;
+
+ if (l.Count != r.Count)
+ return false;
+
+ for (int i = 0; i < l.Count; i++)
+ if (!l[i].Equals(r[i]))
+ return false;
+ return true;
+ }
+
+ private void DisplayRelevantLabels(List<string> relevantLabels) {
+ foreach (string labelName in relevantLabels) {
+ System.Console.Write(labelName + ",");
+ }
+ System.Console.WriteLine("---");
+ }
+
+ private void DeclareConstant(string constantName, Type boogieType) {
+ Symbol symbolAst = GetSymbol(constantName);
+ Sort typeAst = tm.GetType(boogieType);
+
+ Term constAst = z3.MkConst(symbolAst, typeAst);
+ constants.Add(constantName, constAst);
+ log("(declare-funs (({0} {1})))", constAst, typeAst);
+ }
+
+ public ProverInterface.Outcome Check(out List<Z3ErrorModelAndLabels> boogieErrors) {
+ Microsoft.Boogie.Helpers.ExtraTraceInformation("Sending data to the theorem prover");
+ boogieErrors = new List<Z3ErrorModelAndLabels>();
+ LBool outcome = LBool.Undef;
+ Debug.Assert(0 < this.counterexamples);
+ while (true) {
+ Z3Model z3Model;
+ outcome = z3.CheckAndGetModel(out z3Model);
+
+ log("(check-sat)");
+ if (outcome == LBool.False)
+ break;
+
+ if (outcome == LBool.Undef && z3Model == null) {
+ // Blame this on timeout
+ return ProverInterface.Outcome.TimeOut;
+ }
+
+ Debug.Assert(z3Model != null);
+ LabeledLiterals labels = z3.GetRelevantLabels();
+ Debug.Assert(labels != null);
+
+ List<string> labelStrings = new List<string>();
+ uint numLabels = labels.GetNumLabels();
+ for (uint i = 0; i < numLabels; ++i) {
+ Symbol sym = labels.GetLabel(i);
+ string labelName = z3.GetSymbolString(sym);
+ if (!labelName.StartsWith("@")) {
+ labels.Disable(i);
+ }
+ labelStrings.Add(labelName);
+ }
+
+ var sw = new StringWriter();
+ sw.WriteLine("*** MODEL");
+ z3Model.Display(sw);
+ sw.WriteLine("*** END_MODEL");
+ var sr = new StringReader(sw.ToString());
+ var models = Microsoft.Boogie.Model.ParseModels(sr);
+ Z3ErrorModelAndLabels e = new Z3ErrorModelAndLabels(models[0], new List<string>(labelStrings));
+ boogieErrors.Add(e);
+
+ if (boogieErrors.Count < this.counterexamples) {
+ z3.BlockLiterals(labels);
+ log("block-literals {0}", labels);
+ }
+
+ labels.Dispose();
+ z3Model.Dispose();
+ if (boogieErrors.Count == this.counterexamples)
+ break;
+ }
+
+ if (boogieErrors.Count > 0) {
+ return ProverInterface.Outcome.Invalid;
+ }
+ else if (outcome == LBool.False) {
+ return ProverInterface.Outcome.Valid;
+ }
+ else {
+ Debug.Assert(outcome == LBool.Undef);
+ return ProverInterface.Outcome.Undetermined;
+ }
+ }
+
+ public ProverInterface.Outcome CheckAssumptions(List<VCExpr> assumptions, LineariserOptions linOptions,
+ out List<Z3ErrorModelAndLabels> boogieErrors,
+ out List<int> unsatCore) {
+ Microsoft.Boogie.Helpers.ExtraTraceInformation("Sending data to the theorem prover");
+ boogieErrors = new List<Z3ErrorModelAndLabels>();
+ unsatCore = new List<int>();
+ LBool outcome = LBool.Undef;
+
+ Z3Model z3Model;
+ Term proof;
+ Term[] core;
+ Term[] assumption_terms = new Term[assumptions.Count];
+ var logstring = "";
+ for (int i = 0; i < assumptions.Count; i++) {
+ Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
+ Term z3ast = (Term)assumptions[i].Accept(visitor, linOptions);
+ assumption_terms[i] = z3ast;
+ logstring += string.Format("({0}) ", assumption_terms[i]);
+ }
+
+ log("(get-core {0})", logstring);
+ outcome = z3.CheckAssumptions(out z3Model, assumption_terms, out proof, out core);
+
+ if (outcome != LBool.False) {
+ Debug.Assert(z3Model != null);
+ LabeledLiterals labels = z3.GetRelevantLabels();
+ Debug.Assert(labels != null);
+
+ List<string> labelStrings = new List<string>();
+ uint numLabels = labels.GetNumLabels();
+ for (uint i = 0; i < numLabels; ++i) {
+ Symbol sym = labels.GetLabel(i);
+ string labelName = z3.GetSymbolString(sym);
+ if (!labelName.StartsWith("@")) {
+ labels.Disable(i);
+ }
+ labelStrings.Add(labelName);
+ }
+
+ var sw = new StringWriter();
+ sw.WriteLine("*** MODEL");
+ z3Model.Display(sw);
+ sw.WriteLine("*** END_MODEL");
+ var sr = new StringReader(sw.ToString());
+ var models = Microsoft.Boogie.Model.ParseModels(sr);
+ Z3ErrorModelAndLabels e = new Z3ErrorModelAndLabels(models[0], new List<string>(labelStrings));
+ boogieErrors.Add(e);
+
+ labels.Dispose();
+ z3Model.Dispose();
+ }
+
+ if (boogieErrors.Count > 0) {
+ return ProverInterface.Outcome.Invalid;
+ }
+ else if (outcome == LBool.False) {
+ foreach (Term t in core) {
+ for (int i = 0; i < assumption_terms.Length; i++) {
+ if (t.Equals(assumption_terms[i]))
+ unsatCore.Add(i);
+ }
+ }
+ return ProverInterface.Outcome.Valid;
+ }
+ else {
+ Debug.Assert(outcome == LBool.Undef);
+ return ProverInterface.Outcome.Undetermined;
+ }
+ }
+
+ private Symbol GetSymbol(string symbolName) {
+ if (!symbols.ContainsKey(symbolName)) {
+ Symbol symbolAst = z3.MkSymbol(symbolName);
+ symbols.Add(symbolName, symbolAst);
+ }
+ Symbol result;
+ if (!symbols.TryGetValue(symbolName, out result))
+ throw new Exception("symbol " + symbolName + " is undefined");
+ return result;
+ }
+
+ public Term GetConstant(string constantName, Type constantType, VCExpr node)
+ {
+ Term typeSafeTerm;
+ if (!constants.ContainsKey(constantName))
+ this.DeclareConstant(constantName, constantType);
+
+ if (!constants.TryGetValue(constantName, out typeSafeTerm))
+ throw new Exception("constant " + constantName + " is not defined");
+
+ if (constants_inv != null && !constants_inv.ContainsKey(typeSafeTerm))
+ constants_inv.Add(typeSafeTerm, node);
+
+ return typeSafeTerm;
+ }
+
+ public FuncDecl GetFunction(string functionName) {
+ FuncDecl f;
+ if (!functions.TryGetValue(functionName, out f))
+ throw new Exception("function " + functionName + " is undefined");
+ return f;
+ }
+
+ public Term MakeLabel(string labelName, bool pos, Term child) {
+ Symbol labelSymbol = this.GetSymbol(labelName);
+ Term labeledExpr = z3.MkLabel(labelSymbol, pos, child);
+ labels.Add(labelName, labeledExpr);
+ return labeledExpr;
+ }
+
+ public LabeledLiterals GetRelevantLabels() {
+ LabeledLiterals safeLiterals = z3.GetRelevantLabels();
+ log("get-relevant-labels");
+ return safeLiterals;
+ }
+ }
+
+ internal class BacktrackDictionary<K, V> {
+ private Dictionary<K, V> dictionary = new Dictionary<K, V>();
+ private Stack<List<K>> keyStack = new Stack<List<K>>();
+
+ public BacktrackDictionary() {
+ CreateBacktrackPoint();
+ }
+
+ public bool TryGetValue(K key, out V val) {
+ return dictionary.TryGetValue(key, out val);
+ }
+
+ public void Add(K key, V v) {
+ if (dictionary.ContainsKey(key)) {
+ dictionary.Remove(key);
+ }
+ dictionary.Add(key, v);
+ keyStack.Peek().Add(key);
+ }
+
+ public bool ContainsKey(K k) {
+ return dictionary.ContainsKey(k);
+ }
+
+ public void CreateBacktrackPoint() {
+ keyStack.Push(new List<K>());
+ }
+
+ public void Backtrack() {
+ List<K> keysToErase = keyStack.Pop();
+ foreach (K key in keysToErase) {
+ dictionary.Remove(key);
+ }
+ if (keyStack.Count == 0)
+ this.CreateBacktrackPoint();
+ }
+
+ public IEnumerator GetEnumerator() {
+ return dictionary.Keys.GetEnumerator();
+ }
+ }
+
+ public class Z3ErrorModelAndLabels {
+ private Model _model;
+ private List<string> _relevantLabels;
+ public Model Model {
+ get { return this._model; }
+ }
+ public List<string> RelevantLabels {
+ get { return this._relevantLabels; }
+ }
+ public Z3ErrorModelAndLabels(Model model, List<string> relevantLabels) {
+ this._model = model;
+ this._relevantLabels = relevantLabels;
+ }
+ }
+
+
+
} \ No newline at end of file
diff --git a/Source/Provers/Z3api/ProverLayer.cs b/Source/Provers/Z3api/ProverLayer.cs
index d72705f3..cb7df8d7 100644
--- a/Source/Provers/Z3api/ProverLayer.cs
+++ b/Source/Provers/Z3api/ProverLayer.cs
@@ -1,354 +1,354 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Diagnostics;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Z3;
-using Microsoft.Boogie.VCExprAST;
-using System.Diagnostics.Contracts;
-
-using TypeAst = System.IntPtr;
-using TermAst = System.IntPtr;
-using ConstDeclAst = System.IntPtr;
-using ConstAst = System.IntPtr;
-using Value = System.IntPtr;
-using PatternAst = System.IntPtr;
-
-namespace Microsoft.Boogie.Z3
-{
- public class Z3InstanceOptions : ProverOptions {
- public int Timeout { get { return TimeLimit / 1000; } }
- public int Lets {
- get {
- Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() < 4);
- return CommandLineOptions.Clo.Z3lets;
- }
- }
- public bool DistZ3 = false;
- public string ExeName = "z3.exe";
- public bool InverseImplies = false;
- public string Inspector = null;
- public bool OptimizeForBv = false;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ExeName != null);
- }
-
- protected override bool Parse(string opt) {
- //Contract.Requires(opt!=null);
- return ParseBool(opt, "REVERSE_IMPLIES", ref InverseImplies) ||
- ParseString(opt, "INSPECTOR", ref Inspector) ||
- ParseBool(opt, "DIST", ref DistZ3) ||
- ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
- base.Parse(opt);
- }
-
- public override void PostParse() {
- base.PostParse();
-
- if (DistZ3) {
- ExeName = "z3-dist.exe";
- CommandLineOptions.Clo.RestartProverPerVC = true;
- }
- }
-
- public override string Help {
- get {
- return
-@"
-Z3-specific options:
-~~~~~~~~~~~~~~~~~~~~
-INSPECTOR=<string> Use the specified Z3Inspector binary.
-OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
-
-Obscure options:
-~~~~~~~~~~~~~~~~
-DIST=<bool> Use z3-dist.exe binary.
-REVERSE_IMPLIES=<bool> Encode P==>Q as Q||!P.
-
-" + base.Help;
- // DIST requires non-public binaries
- }
- }
- }
-
- public class Z3LineariserOptions : LineariserOptions {
- private readonly Z3InstanceOptions opts;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(opts != null);
- }
-
-
- public Z3LineariserOptions(bool asTerm, Z3InstanceOptions opts, List<VCExprVar/*!>!*/> letVariables)
- : base(asTerm) {
- Contract.Requires(opts != null);
- Contract.Requires(cce.NonNullElements(letVariables));
-
- this.opts = opts;
- this.LetVariablesAttr = letVariables;
- }
-
- public override bool UseWeights {
- get {
- return true;
- }
- }
-
- public override bool UseTypes {
- get {
- return true;
- }
- }
-
- public override bool QuantifierIds {
- get {
- return true;
- }
- }
-
- public override bool InverseImplies {
- get {
- return opts.InverseImplies;
- }
- }
-
- public override LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- if (newVal == AsTerm)
- return this;
- return new Z3LineariserOptions(newVal, opts, LetVariables);
- }
-
- // variables representing formulas in let-bindings have to be
- // printed in a different way than other variables
- private readonly List<VCExprVar/*!>!*/> LetVariablesAttr;
- public override List<VCExprVar/*!>!*/> LetVariables {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
-
- return LetVariablesAttr;
- }
- }
-
- public override LineariserOptions AddLetVariable(VCExprVar furtherVar) {
- //Contract.Requires(furtherVar != null);
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
- allVars.AddRange(LetVariables);
- allVars.Add(furtherVar);
- return new Z3LineariserOptions(AsTerm, opts, allVars);
- }
-
- public override LineariserOptions AddLetVariables(List<VCExprVar/*!>!*/> furtherVars) {
- //Contract.Requires(furtherVars != null);
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
-
- List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
- allVars.AddRange(LetVariables);
- allVars.AddRange(furtherVars);
- return new Z3LineariserOptions(AsTerm, opts, allVars);
- }
- }
-
- public class Z3apiProcessTheoremProver : ProverInterface
- {
- public Z3apiProcessTheoremProver(Z3InstanceOptions opts, DeclFreeProverContext ctxt)
- {
- this.options = opts;
- this.context = (Z3apiProverContext) ctxt;
- this.numAxiomsPushed = 0;
- }
-
- private Z3InstanceOptions options;
-
- private Z3apiProverContext context;
- public override ProverContext Context
- {
- get { return context; }
- }
-
- public override VCExpressionGenerator VCExprGen
- {
- get { return context.ExprGen; }
- }
-
- private int numAxiomsPushed;
-
- public override void Close()
- {
- base.Close();
- context.CloseLog();
- context.z3.Dispose();
- context.config.Dispose();
- }
-
- public void PushAxiom(VCExpr axiom)
- {
- context.CreateBacktrackPoint();
- LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
- context.AddAxiom(axiom, linOptions);
- }
-
- private void PushConjecture(VCExpr conjecture)
- {
- context.CreateBacktrackPoint();
- LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
- context.AddConjecture(conjecture, linOptions);
- }
-
- public override void PushVCExpression(VCExpr vc)
- {
- PushAxiom(vc);
- numAxiomsPushed++;
- }
-
- public void CreateBacktrackPoint()
- {
- context.CreateBacktrackPoint();
- }
-
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
- {
- LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
- Push();
- context.AddAxiom(context.Axioms, linOptions);
- context.AddConjecture(vc, linOptions);
- outcome = context.Check(out z3LabelModels);
- Pop();
- }
-
- public override void Check()
- {
- outcome = context.Check(out z3LabelModels);
- }
-
- public override ProverInterface.Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
- {
- LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
- return context.CheckAssumptions(assumptions, linOptions, out z3LabelModels, out unsatCore);
- }
-
- public override void Push()
- {
- context.CreateBacktrackPoint();
- }
-
- public override void Pop()
- {
- context.Backtrack();
- }
-
- public override void Assert(VCExpr vc, bool polarity)
- {
- LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
- if (polarity)
- context.AddAxiom(vc, linOptions);
- else
- context.AddConjecture(vc, linOptions);
- }
-
- public override void AssertAxioms()
- {
- LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
- context.AddAxiom(context.Axioms, linOptions);
- }
-
- // Number of axioms pushed since the last call to FlushAxioms
- public override int NumAxiomsPushed()
- {
- return numAxiomsPushed;
- }
-
- public override int FlushAxiomsToTheoremProver()
- {
- var ret = numAxiomsPushed;
- numAxiomsPushed = 0;
- return ret;
- }
-
- private Outcome outcome;
- private List<Z3ErrorModelAndLabels> z3LabelModels = new List<Z3ErrorModelAndLabels>();
-
- [NoDefaultContract]
- public override Outcome CheckOutcome(ErrorHandler handler)
- {
- if (outcome == Outcome.Invalid)
- {
- foreach (Z3ErrorModelAndLabels z3LabelModel in z3LabelModels)
- {
- List<string> unprefixedLabels = RemovePrefixes(z3LabelModel.RelevantLabels);
- handler.OnModel(unprefixedLabels, z3LabelModel.Model);
- }
- }
- return outcome;
- }
-
- public override Outcome CheckOutcomeCore(ErrorHandler handler) {
- if (outcome == Outcome.Invalid) {
- foreach (Z3ErrorModelAndLabels z3LabelModel in z3LabelModels) {
- List<string> unprefixedLabels = RemovePrefixes(z3LabelModel.RelevantLabels);
- handler.OnModel(unprefixedLabels, z3LabelModel.Model);
- }
- }
- return outcome;
- }
-
- private List<string> RemovePrefixes(List<string> labels)
- {
- List<string> result = new List<string>();
- foreach (string label in labels)
- {
- if (label.StartsWith("+"))
- {
- result.Add(label.Substring(1));
- }
- else if (label.StartsWith("|"))
- {
- result.Add(label.Substring(1));
- }
- else if (label.StartsWith("@"))
- {
- result.Add(label.Substring(1));
- }
- else
- throw new Exception("Unknown prefix in label " + label);
- }
- return result;
- }
- }
-}
-
-namespace Microsoft.Boogie.Z3api
-{
- public class Factory : ProverFactory
- {
- public override object SpawnProver(ProverOptions options, object ctxt)
- {
- return new Z3apiProcessTheoremProver((Z3InstanceOptions) options, (Z3apiProverContext) ctxt);
- }
-
- public override object NewProverContext(ProverOptions opts)
- {
- if (CommandLineOptions.Clo.BracketIdsInVC < 0)
- {
- CommandLineOptions.Clo.BracketIdsInVC = 0;
- }
-
- VCExpressionGenerator gen = new VCExpressionGenerator();
- return new Z3apiProverContext((Z3InstanceOptions)opts, gen);
- }
-
- public override ProverOptions BlankProverOptions()
- {
- return new Z3InstanceOptions();
- }
- }
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Z3;
+using Microsoft.Boogie.VCExprAST;
+using System.Diagnostics.Contracts;
+
+using TypeAst = System.IntPtr;
+using TermAst = System.IntPtr;
+using ConstDeclAst = System.IntPtr;
+using ConstAst = System.IntPtr;
+using Value = System.IntPtr;
+using PatternAst = System.IntPtr;
+
+namespace Microsoft.Boogie.Z3
+{
+ public class Z3InstanceOptions : ProverOptions {
+ public int Timeout { get { return TimeLimit / 1000; } }
+ public int Lets {
+ get {
+ Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() < 4);
+ return CommandLineOptions.Clo.Z3lets;
+ }
+ }
+ public bool DistZ3 = false;
+ public string ExeName = "z3.exe";
+ public bool InverseImplies = false;
+ public string Inspector = null;
+ public bool OptimizeForBv = false;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExeName != null);
+ }
+
+ protected override bool Parse(string opt) {
+ //Contract.Requires(opt!=null);
+ return ParseBool(opt, "REVERSE_IMPLIES", ref InverseImplies) ||
+ ParseString(opt, "INSPECTOR", ref Inspector) ||
+ ParseBool(opt, "DIST", ref DistZ3) ||
+ ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
+ base.Parse(opt);
+ }
+
+ public override void PostParse() {
+ base.PostParse();
+
+ if (DistZ3) {
+ ExeName = "z3-dist.exe";
+ CommandLineOptions.Clo.RestartProverPerVC = true;
+ }
+ }
+
+ public override string Help {
+ get {
+ return
+@"
+Z3-specific options:
+~~~~~~~~~~~~~~~~~~~~
+INSPECTOR=<string> Use the specified Z3Inspector binary.
+OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
+
+Obscure options:
+~~~~~~~~~~~~~~~~
+DIST=<bool> Use z3-dist.exe binary.
+REVERSE_IMPLIES=<bool> Encode P==>Q as Q||!P.
+
+" + base.Help;
+ // DIST requires non-public binaries
+ }
+ }
+ }
+
+ public class Z3LineariserOptions : LineariserOptions {
+ private readonly Z3InstanceOptions opts;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(opts != null);
+ }
+
+
+ public Z3LineariserOptions(bool asTerm, Z3InstanceOptions opts, List<VCExprVar/*!>!*/> letVariables)
+ : base(asTerm) {
+ Contract.Requires(opts != null);
+ Contract.Requires(cce.NonNullElements(letVariables));
+
+ this.opts = opts;
+ this.LetVariablesAttr = letVariables;
+ }
+
+ public override bool UseWeights {
+ get {
+ return true;
+ }
+ }
+
+ public override bool UseTypes {
+ get {
+ return true;
+ }
+ }
+
+ public override bool QuantifierIds {
+ get {
+ return true;
+ }
+ }
+
+ public override bool InverseImplies {
+ get {
+ return opts.InverseImplies;
+ }
+ }
+
+ public override LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ if (newVal == AsTerm)
+ return this;
+ return new Z3LineariserOptions(newVal, opts, LetVariables);
+ }
+
+ // variables representing formulas in let-bindings have to be
+ // printed in a different way than other variables
+ private readonly List<VCExprVar/*!>!*/> LetVariablesAttr;
+ public override List<VCExprVar/*!>!*/> LetVariables {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+
+ return LetVariablesAttr;
+ }
+ }
+
+ public override LineariserOptions AddLetVariable(VCExprVar furtherVar) {
+ //Contract.Requires(furtherVar != null);
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
+ allVars.AddRange(LetVariables);
+ allVars.Add(furtherVar);
+ return new Z3LineariserOptions(AsTerm, opts, allVars);
+ }
+
+ public override LineariserOptions AddLetVariables(List<VCExprVar/*!>!*/> furtherVars) {
+ //Contract.Requires(furtherVars != null);
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
+ allVars.AddRange(LetVariables);
+ allVars.AddRange(furtherVars);
+ return new Z3LineariserOptions(AsTerm, opts, allVars);
+ }
+ }
+
+ public class Z3apiProcessTheoremProver : ProverInterface
+ {
+ public Z3apiProcessTheoremProver(Z3InstanceOptions opts, DeclFreeProverContext ctxt)
+ {
+ this.options = opts;
+ this.context = (Z3apiProverContext) ctxt;
+ this.numAxiomsPushed = 0;
+ }
+
+ private Z3InstanceOptions options;
+
+ private Z3apiProverContext context;
+ public override ProverContext Context
+ {
+ get { return context; }
+ }
+
+ public override VCExpressionGenerator VCExprGen
+ {
+ get { return context.ExprGen; }
+ }
+
+ private int numAxiomsPushed;
+
+ public override void Close()
+ {
+ base.Close();
+ context.CloseLog();
+ context.z3.Dispose();
+ context.config.Dispose();
+ }
+
+ public void PushAxiom(VCExpr axiom)
+ {
+ context.CreateBacktrackPoint();
+ LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
+ context.AddAxiom(axiom, linOptions);
+ }
+
+ private void PushConjecture(VCExpr conjecture)
+ {
+ context.CreateBacktrackPoint();
+ LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
+ context.AddConjecture(conjecture, linOptions);
+ }
+
+ public override void PushVCExpression(VCExpr vc)
+ {
+ PushAxiom(vc);
+ numAxiomsPushed++;
+ }
+
+ public void CreateBacktrackPoint()
+ {
+ context.CreateBacktrackPoint();
+ }
+
+ public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
+ {
+ LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
+ Push();
+ context.AddAxiom(context.Axioms, linOptions);
+ context.AddConjecture(vc, linOptions);
+ outcome = context.Check(out z3LabelModels);
+ Pop();
+ }
+
+ public override void Check()
+ {
+ outcome = context.Check(out z3LabelModels);
+ }
+
+ public override ProverInterface.Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
+ {
+ LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
+ return context.CheckAssumptions(assumptions, linOptions, out z3LabelModels, out unsatCore);
+ }
+
+ public override void Push()
+ {
+ context.CreateBacktrackPoint();
+ }
+
+ public override void Pop()
+ {
+ context.Backtrack();
+ }
+
+ public override void Assert(VCExpr vc, bool polarity)
+ {
+ LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
+ if (polarity)
+ context.AddAxiom(vc, linOptions);
+ else
+ context.AddConjecture(vc, linOptions);
+ }
+
+ public override void AssertAxioms()
+ {
+ LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List<VCExprVar>());
+ context.AddAxiom(context.Axioms, linOptions);
+ }
+
+ // Number of axioms pushed since the last call to FlushAxioms
+ public override int NumAxiomsPushed()
+ {
+ return numAxiomsPushed;
+ }
+
+ public override int FlushAxiomsToTheoremProver()
+ {
+ var ret = numAxiomsPushed;
+ numAxiomsPushed = 0;
+ return ret;
+ }
+
+ private Outcome outcome;
+ private List<Z3ErrorModelAndLabels> z3LabelModels = new List<Z3ErrorModelAndLabels>();
+
+ [NoDefaultContract]
+ public override Outcome CheckOutcome(ErrorHandler handler)
+ {
+ if (outcome == Outcome.Invalid)
+ {
+ foreach (Z3ErrorModelAndLabels z3LabelModel in z3LabelModels)
+ {
+ List<string> unprefixedLabels = RemovePrefixes(z3LabelModel.RelevantLabels);
+ handler.OnModel(unprefixedLabels, z3LabelModel.Model);
+ }
+ }
+ return outcome;
+ }
+
+ public override Outcome CheckOutcomeCore(ErrorHandler handler) {
+ if (outcome == Outcome.Invalid) {
+ foreach (Z3ErrorModelAndLabels z3LabelModel in z3LabelModels) {
+ List<string> unprefixedLabels = RemovePrefixes(z3LabelModel.RelevantLabels);
+ handler.OnModel(unprefixedLabels, z3LabelModel.Model);
+ }
+ }
+ return outcome;
+ }
+
+ private List<string> RemovePrefixes(List<string> labels)
+ {
+ List<string> result = new List<string>();
+ foreach (string label in labels)
+ {
+ if (label.StartsWith("+"))
+ {
+ result.Add(label.Substring(1));
+ }
+ else if (label.StartsWith("|"))
+ {
+ result.Add(label.Substring(1));
+ }
+ else if (label.StartsWith("@"))
+ {
+ result.Add(label.Substring(1));
+ }
+ else
+ throw new Exception("Unknown prefix in label " + label);
+ }
+ return result;
+ }
+ }
+}
+
+namespace Microsoft.Boogie.Z3api
+{
+ public class Factory : ProverFactory
+ {
+ public override object SpawnProver(ProverOptions options, object ctxt)
+ {
+ return new Z3apiProcessTheoremProver((Z3InstanceOptions) options, (Z3apiProverContext) ctxt);
+ }
+
+ public override object NewProverContext(ProverOptions opts)
+ {
+ if (CommandLineOptions.Clo.BracketIdsInVC < 0)
+ {
+ CommandLineOptions.Clo.BracketIdsInVC = 0;
+ }
+
+ VCExpressionGenerator gen = new VCExpressionGenerator();
+ return new Z3apiProverContext((Z3InstanceOptions)opts, gen);
+ }
+
+ public override ProverOptions BlankProverOptions()
+ {
+ return new Z3InstanceOptions();
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Provers/Z3api/SafeContext.cs b/Source/Provers/Z3api/SafeContext.cs
index 72192804..b83d6dff 100644
--- a/Source/Provers/Z3api/SafeContext.cs
+++ b/Source/Provers/Z3api/SafeContext.cs
@@ -1,16 +1,16 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Diagnostics;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Z3;
-using Microsoft.Z3;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Z3
-{
-
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Z3;
+using Microsoft.Z3;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.Z3
+{
+
} \ No newline at end of file
diff --git a/Source/Provers/Z3api/StubContext.cs b/Source/Provers/Z3api/StubContext.cs
index b129b378..79f140aa 100644
--- a/Source/Provers/Z3api/StubContext.cs
+++ b/Source/Provers/Z3api/StubContext.cs
@@ -1,75 +1,75 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Diagnostics;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Z3;
-using Microsoft.Z3;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Z3 {
- public class Z3StubContext : Z3Context {
- class Z3StubPatternAst: Z3PatternAst {}
- class Z3StubTermAst: Z3TermAst {}
- class Z3StubLabeledLiterals: Z3LabeledLiterals {}
-
- public void CreateBacktrackPoint(){}
- public void Backtrack(){}
- public void AddAxiom(VCExpr axiom, LineariserOptions linOptions) { }
- public void AddConjecture(VCExpr vc, LineariserOptions linOptions){}
- public void AddSmtlibString(string smtlibString) {}
- public string GetDeclName(Z3ConstDeclAst constDeclAst) {
- return "";
- }
- public Z3PatternAst MakePattern(List<Z3TermAst> exprs) {
- return new Z3StubPatternAst();
- }
- public Z3TermAst MakeQuantifier(bool isForall, uint weight, string qid, int skolemid, List<string> varNames, List<Type> boogieTypes, List<Z3PatternAst> patterns, List<Z3TermAst> no_patterns, Z3TermAst body) {
- return new Z3StubTermAst();
- }
- public ProverInterface.Outcome Check(out List<Z3ErrorModelAndLabels> boogieErrors) {
- boogieErrors = new List<Z3ErrorModelAndLabels>();
- return ProverInterface.Outcome.Undetermined;
- }
- public void TypeCheckBool(Z3TermAst t){}
- public void TypeCheckInt(Z3TermAst t){}
- public void DeclareType(string typeName) {}
- public void DeclareConstant(string constantName, Type boogieType) {}
- public void DeclareFunction(string functionName, List<Type> domain, Type range) {}
- public Z3TermAst GetConstant(string constantName, Type constantType) {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeIntLiteral(string numeral) {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeBvLiteral(int i, uint bvSize) {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeTrue() {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeFalse() {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeLabel(string labelName, bool pos, Z3TermAst child) {
- return new Z3StubTermAst();
- }
- public Z3LabeledLiterals GetRelevantLabels() {
- return new Z3StubLabeledLiterals();
- }
- public Z3TermAst Make(string op, List<Z3TermAst> children) {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeArraySelect(List<Z3TermAst> args)
- {
- return new Z3StubTermAst();
- }
- public Z3TermAst MakeArrayStore(List<Z3TermAst> args)
- {
- return new Z3StubTermAst();
- }
- }
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Z3;
+using Microsoft.Z3;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.Z3 {
+ public class Z3StubContext : Z3Context {
+ class Z3StubPatternAst: Z3PatternAst {}
+ class Z3StubTermAst: Z3TermAst {}
+ class Z3StubLabeledLiterals: Z3LabeledLiterals {}
+
+ public void CreateBacktrackPoint(){}
+ public void Backtrack(){}
+ public void AddAxiom(VCExpr axiom, LineariserOptions linOptions) { }
+ public void AddConjecture(VCExpr vc, LineariserOptions linOptions){}
+ public void AddSmtlibString(string smtlibString) {}
+ public string GetDeclName(Z3ConstDeclAst constDeclAst) {
+ return "";
+ }
+ public Z3PatternAst MakePattern(List<Z3TermAst> exprs) {
+ return new Z3StubPatternAst();
+ }
+ public Z3TermAst MakeQuantifier(bool isForall, uint weight, string qid, int skolemid, List<string> varNames, List<Type> boogieTypes, List<Z3PatternAst> patterns, List<Z3TermAst> no_patterns, Z3TermAst body) {
+ return new Z3StubTermAst();
+ }
+ public ProverInterface.Outcome Check(out List<Z3ErrorModelAndLabels> boogieErrors) {
+ boogieErrors = new List<Z3ErrorModelAndLabels>();
+ return ProverInterface.Outcome.Undetermined;
+ }
+ public void TypeCheckBool(Z3TermAst t){}
+ public void TypeCheckInt(Z3TermAst t){}
+ public void DeclareType(string typeName) {}
+ public void DeclareConstant(string constantName, Type boogieType) {}
+ public void DeclareFunction(string functionName, List<Type> domain, Type range) {}
+ public Z3TermAst GetConstant(string constantName, Type constantType) {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeIntLiteral(string numeral) {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeBvLiteral(int i, uint bvSize) {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeTrue() {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeFalse() {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeLabel(string labelName, bool pos, Z3TermAst child) {
+ return new Z3StubTermAst();
+ }
+ public Z3LabeledLiterals GetRelevantLabels() {
+ return new Z3StubLabeledLiterals();
+ }
+ public Z3TermAst Make(string op, List<Z3TermAst> children) {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeArraySelect(List<Z3TermAst> args)
+ {
+ return new Z3StubTermAst();
+ }
+ public Z3TermAst MakeArrayStore(List<Z3TermAst> args)
+ {
+ return new Z3StubTermAst();
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Provers/Z3api/TypeAdapter.cs b/Source/Provers/Z3api/TypeAdapter.cs
index 879211f7..f2a9a8fd 100644
--- a/Source/Provers/Z3api/TypeAdapter.cs
+++ b/Source/Provers/Z3api/TypeAdapter.cs
@@ -1,197 +1,197 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Diagnostics;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.Z3;
-using Microsoft.Z3;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.Z3
-{
- internal class Z3TypeCachedBuilder
- {
- private class MapTypeComparator : IEqualityComparer<MapType>
- {
- public bool Equals(MapType x, MapType y)
- {
- if (x.MapArity != y.MapArity)
- return false;
- for (int i = 0; i < x.MapArity; i++)
- {
- if (!Equals(x.Arguments[i], y.Arguments[i]))
- return false;
- }
- return Equals(x.Result, y.Result);
-
- }
- public int GetHashCode(MapType mapType)
- {
- return mapType.GetHashCode();
- }
- }
-
- private class BvTypeComparator : IEqualityComparer<BvType>
- {
- public bool Equals(BvType x, BvType y)
- {
- return x.Bits == y.Bits;
- }
- public int GetHashCode(BvType bvType)
- {
- return bvType.Bits;
- }
- }
-
- private class BasicTypeComparator : IEqualityComparer<BasicType>
- {
- public bool Equals(BasicType x, BasicType y)
- {
- return (x.IsBool == y.IsBool) &&
- (x.IsInt == y.IsInt) &&
- (x.IsReal == y.IsReal);
- }
-
- public int GetHashCode(BasicType basicType)
- {
- if (basicType.IsBool)
- return 1;
- else if (basicType.IsInt)
- return 2;
- else if (basicType.IsReal)
- return 3;
- else
- throw new Exception("Basic Type " + basicType.ToString() + " is unkwown");
- }
- }
-
- private class CtorTypeComparator : IEqualityComparer<CtorType> {
- public bool Equals(CtorType x, CtorType y) {
- return (x.Decl.Name == y.Decl.Name);
- }
-
- public int GetHashCode(CtorType ctorType) {
- return ctorType.Decl.Name.GetHashCode();
- }
- }
-
- private Dictionary<MapType, Sort> mapTypes = new Dictionary<MapType, Sort>(new MapTypeComparator());
- private Dictionary<BvType, Sort> bvTypes = new Dictionary<BvType, Sort>(new BvTypeComparator());
- private Dictionary<BasicType, Sort> basicTypes = new Dictionary<BasicType, Sort>(new BasicTypeComparator());
- private Dictionary<CtorType, Sort> ctorTypes = new Dictionary<CtorType, Sort>(new CtorTypeComparator());
-
- private Z3apiProverContext container;
-
- public Z3TypeCachedBuilder(Z3apiProverContext context)
- {
- this.container = context;
- }
-
- private Sort GetMapType(MapType mapType) {
- Context z3 = ((Z3apiProverContext)container).z3;
- if (!mapTypes.ContainsKey(mapType)) {
- Type result = mapType.Result;
- for (int i = mapType.Arguments.Length-1; i > 0; i--) {
- GetType(result);
- result = new MapType(mapType.tok, new TypeVariableSeq(), new TypeSeq(mapType.Arguments[i]), result);
- }
- mapTypes.Add(mapType, BuildMapType(GetType(mapType.Arguments[0]), GetType(result)));
- }
- return mapTypes[mapType];
- }
-
- private Sort GetBvType(BvType bvType)
- {
- if (!bvTypes.ContainsKey(bvType))
- {
- Sort typeAst = BuildBvType(bvType);
- bvTypes.Add(bvType, typeAst);
- }
- Sort result;
- bool containsKey = bvTypes.TryGetValue(bvType, out result);
- Debug.Assert(containsKey);
- return result;
- }
-
- private Sort GetBasicType(BasicType basicType)
- {
- if (!basicTypes.ContainsKey(basicType))
- {
- Sort typeAst = BuildBasicType(basicType);
- basicTypes.Add(basicType, typeAst);
- }
- Sort result;
- bool containsKey = basicTypes.TryGetValue(basicType, out result);
- Debug.Assert(containsKey);
- return result;
- }
-
- private Sort GetCtorType(CtorType ctorType) {
- if (!ctorTypes.ContainsKey(ctorType)) {
- Sort typeAst = BuildCtorType(ctorType);
- ctorTypes.Add(ctorType, typeAst);
- }
- Sort result;
- bool containsKey = ctorTypes.TryGetValue(ctorType, out result);
- Debug.Assert(containsKey);
- return result;
- }
-
- public virtual Sort GetType(Type boogieType) {
- System.Type type = boogieType.GetType();
- if (type.Equals(typeof(BvType)))
- return GetBvType((BvType)boogieType);
- else if (type.Equals(typeof(BasicType)))
- return GetBasicType((BasicType)boogieType);
- else if (type.Equals(typeof(MapType)))
- return GetMapType((MapType)boogieType);
- else if (type.Equals(typeof(CtorType)))
- return GetCtorType((CtorType)boogieType);
- else
- throw new Exception("Boogie Type " + boogieType.GetType() + " is unknown");
- }
-
- public Sort BuildMapType(Sort domain, Sort range)
- {
- Context z3 = ((Z3apiProverContext)container).z3;
- return z3.MkArraySort(domain, range);
- }
-
- public Sort BuildBvType(BvType bvType)
- {
- Context z3 = ((Z3apiProverContext)container).z3;
- return z3.MkBvSort((uint)bvType.Bits);
- }
-
- public Sort BuildBasicType(BasicType basicType)
- {
- Context z3 = ((Z3apiProverContext)container).z3;
- Sort typeAst;
- if (basicType.IsBool)
- {
- typeAst = z3.MkBoolSort();
- }
- else if (basicType.IsInt)
- {
- typeAst = z3.MkIntSort();
- }
- else if (basicType.IsReal)
- {
- typeAst = z3.MkRealSort();
- }
- else
- throw new Exception("Unknown Basic Type " + basicType.ToString());
- return typeAst;
- }
-
- public Sort BuildCtorType(CtorType ctorType) {
- Context z3 = ((Z3apiProverContext)container).z3;
- if (ctorType.Arguments.Length > 0)
- throw new Exception("Type constructor of non-zero arity are not handled");
- return z3.MkSort(ctorType.Decl.Name);
- }
- }
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Diagnostics;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie;
+using Microsoft.Boogie.Z3;
+using Microsoft.Z3;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie.Z3
+{
+ internal class Z3TypeCachedBuilder
+ {
+ private class MapTypeComparator : IEqualityComparer<MapType>
+ {
+ public bool Equals(MapType x, MapType y)
+ {
+ if (x.MapArity != y.MapArity)
+ return false;
+ for (int i = 0; i < x.MapArity; i++)
+ {
+ if (!Equals(x.Arguments[i], y.Arguments[i]))
+ return false;
+ }
+ return Equals(x.Result, y.Result);
+
+ }
+ public int GetHashCode(MapType mapType)
+ {
+ return mapType.GetHashCode();
+ }
+ }
+
+ private class BvTypeComparator : IEqualityComparer<BvType>
+ {
+ public bool Equals(BvType x, BvType y)
+ {
+ return x.Bits == y.Bits;
+ }
+ public int GetHashCode(BvType bvType)
+ {
+ return bvType.Bits;
+ }
+ }
+
+ private class BasicTypeComparator : IEqualityComparer<BasicType>
+ {
+ public bool Equals(BasicType x, BasicType y)
+ {
+ return (x.IsBool == y.IsBool) &&
+ (x.IsInt == y.IsInt) &&
+ (x.IsReal == y.IsReal);
+ }
+
+ public int GetHashCode(BasicType basicType)
+ {
+ if (basicType.IsBool)
+ return 1;
+ else if (basicType.IsInt)
+ return 2;
+ else if (basicType.IsReal)
+ return 3;
+ else
+ throw new Exception("Basic Type " + basicType.ToString() + " is unkwown");
+ }
+ }
+
+ private class CtorTypeComparator : IEqualityComparer<CtorType> {
+ public bool Equals(CtorType x, CtorType y) {
+ return (x.Decl.Name == y.Decl.Name);
+ }
+
+ public int GetHashCode(CtorType ctorType) {
+ return ctorType.Decl.Name.GetHashCode();
+ }
+ }
+
+ private Dictionary<MapType, Sort> mapTypes = new Dictionary<MapType, Sort>(new MapTypeComparator());
+ private Dictionary<BvType, Sort> bvTypes = new Dictionary<BvType, Sort>(new BvTypeComparator());
+ private Dictionary<BasicType, Sort> basicTypes = new Dictionary<BasicType, Sort>(new BasicTypeComparator());
+ private Dictionary<CtorType, Sort> ctorTypes = new Dictionary<CtorType, Sort>(new CtorTypeComparator());
+
+ private Z3apiProverContext container;
+
+ public Z3TypeCachedBuilder(Z3apiProverContext context)
+ {
+ this.container = context;
+ }
+
+ private Sort GetMapType(MapType mapType) {
+ Context z3 = ((Z3apiProverContext)container).z3;
+ if (!mapTypes.ContainsKey(mapType)) {
+ Type result = mapType.Result;
+ for (int i = mapType.Arguments.Length-1; i > 0; i--) {
+ GetType(result);
+ result = new MapType(mapType.tok, new TypeVariableSeq(), new TypeSeq(mapType.Arguments[i]), result);
+ }
+ mapTypes.Add(mapType, BuildMapType(GetType(mapType.Arguments[0]), GetType(result)));
+ }
+ return mapTypes[mapType];
+ }
+
+ private Sort GetBvType(BvType bvType)
+ {
+ if (!bvTypes.ContainsKey(bvType))
+ {
+ Sort typeAst = BuildBvType(bvType);
+ bvTypes.Add(bvType, typeAst);
+ }
+ Sort result;
+ bool containsKey = bvTypes.TryGetValue(bvType, out result);
+ Debug.Assert(containsKey);
+ return result;
+ }
+
+ private Sort GetBasicType(BasicType basicType)
+ {
+ if (!basicTypes.ContainsKey(basicType))
+ {
+ Sort typeAst = BuildBasicType(basicType);
+ basicTypes.Add(basicType, typeAst);
+ }
+ Sort result;
+ bool containsKey = basicTypes.TryGetValue(basicType, out result);
+ Debug.Assert(containsKey);
+ return result;
+ }
+
+ private Sort GetCtorType(CtorType ctorType) {
+ if (!ctorTypes.ContainsKey(ctorType)) {
+ Sort typeAst = BuildCtorType(ctorType);
+ ctorTypes.Add(ctorType, typeAst);
+ }
+ Sort result;
+ bool containsKey = ctorTypes.TryGetValue(ctorType, out result);
+ Debug.Assert(containsKey);
+ return result;
+ }
+
+ public virtual Sort GetType(Type boogieType) {
+ System.Type type = boogieType.GetType();
+ if (type.Equals(typeof(BvType)))
+ return GetBvType((BvType)boogieType);
+ else if (type.Equals(typeof(BasicType)))
+ return GetBasicType((BasicType)boogieType);
+ else if (type.Equals(typeof(MapType)))
+ return GetMapType((MapType)boogieType);
+ else if (type.Equals(typeof(CtorType)))
+ return GetCtorType((CtorType)boogieType);
+ else
+ throw new Exception("Boogie Type " + boogieType.GetType() + " is unknown");
+ }
+
+ public Sort BuildMapType(Sort domain, Sort range)
+ {
+ Context z3 = ((Z3apiProverContext)container).z3;
+ return z3.MkArraySort(domain, range);
+ }
+
+ public Sort BuildBvType(BvType bvType)
+ {
+ Context z3 = ((Z3apiProverContext)container).z3;
+ return z3.MkBvSort((uint)bvType.Bits);
+ }
+
+ public Sort BuildBasicType(BasicType basicType)
+ {
+ Context z3 = ((Z3apiProverContext)container).z3;
+ Sort typeAst;
+ if (basicType.IsBool)
+ {
+ typeAst = z3.MkBoolSort();
+ }
+ else if (basicType.IsInt)
+ {
+ typeAst = z3.MkIntSort();
+ }
+ else if (basicType.IsReal)
+ {
+ typeAst = z3.MkRealSort();
+ }
+ else
+ throw new Exception("Unknown Basic Type " + basicType.ToString());
+ return typeAst;
+ }
+
+ public Sort BuildCtorType(CtorType ctorType) {
+ Context z3 = ((Z3apiProverContext)container).z3;
+ if (ctorType.Arguments.Length > 0)
+ throw new Exception("Type constructor of non-zero arity are not handled");
+ return z3.MkSort(ctorType.Decl.Name);
+ }
+ }
} \ No newline at end of file
diff --git a/Source/Provers/Z3api/VCExprVisitor.cs b/Source/Provers/Z3api/VCExprVisitor.cs
index e56a7950..52c7d8fd 100644
--- a/Source/Provers/Z3api/VCExprVisitor.cs
+++ b/Source/Provers/Z3api/VCExprVisitor.cs
@@ -1,649 +1,649 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Z3;
-
-namespace Microsoft.Boogie.Z3
-{
- using System.Numerics.BigInteger;
-
- public class Z3apiExprLineariser : IVCExprVisitor<Term, LineariserOptions>
- {
- private Z3apiOpLineariser opLineariser = null;
- private IVCExprOpVisitor<Term, LineariserOptions> OpLineariser
- {
- get
- {
- Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
- if (opLineariser == null)
- opLineariser = new Z3apiOpLineariser(this);
- return opLineariser;
- }
- }
-
- internal readonly UniqueNamer namer;
- internal readonly Dictionary<VCExprVar, Term> letBindings;
- protected Z3apiProverContext cm;
-
- public Z3apiExprLineariser(Z3apiProverContext cm, UniqueNamer namer)
- {
- this.cm = cm;
- this.namer = namer;
- this.letBindings = new Dictionary<VCExprVar, Term>();
- }
-
- public Term Linearise(VCExpr expr, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(expr != null);
- return expr.Accept<Term, LineariserOptions>(this, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public Term Make(VCExprOp op, List<Term> children) {
- Context z3 = cm.z3;
- Term[] unwrapChildren = children.ToArray();
- VCExprBoogieFunctionOp boogieFunctionOp = op as VCExprBoogieFunctionOp;
- if (boogieFunctionOp != null) {
- FuncDecl f = cm.GetFunction(boogieFunctionOp.Func.Name);
- return z3.MkApp(f, unwrapChildren);
- }
- VCExprDistinctOp distinctOp = op as VCExprDistinctOp;
- if (distinctOp != null) {
- return z3.MkDistinct(unwrapChildren);
- }
-
- if (op == VCExpressionGenerator.AndOp) {
- return z3.MkAnd(unwrapChildren);
- }
-
- if (op == VCExpressionGenerator.OrOp) {
- return z3.MkOr(unwrapChildren);
- }
-
- if (op == VCExpressionGenerator.ImpliesOp) {
- return z3.MkImplies(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.NotOp) {
- return z3.MkNot(unwrapChildren[0]);
- }
-
- if (op == VCExpressionGenerator.EqOp) {
- return z3.MkEq(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.NeqOp) {
- return z3.MkNot(z3.MkEq(unwrapChildren[0], unwrapChildren[1]));
- }
-
- if (op == VCExpressionGenerator.LtOp) {
- return z3.MkLt(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.LeOp) {
- return z3.MkLe(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.GtOp) {
- return z3.MkGt(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.GeOp) {
- return z3.MkGe(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.AddOp) {
- return z3.MkAdd(unwrapChildren);
- }
-
- if (op == VCExpressionGenerator.SubOp) {
- return z3.MkSub(unwrapChildren);
- }
-
- if (op == VCExpressionGenerator.DivOp || op == VCExpressionGenerator.RealDivOp) {
- return z3.MkDiv(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.MulOp) {
- return z3.MkMul(unwrapChildren);
- }
-
- if (op == VCExpressionGenerator.ModOp) {
- return z3.MkMod(unwrapChildren[0], unwrapChildren[1]);
- }
-
- if (op == VCExpressionGenerator.IfThenElseOp) {
- return z3.MkIte(unwrapChildren[0], unwrapChildren[1], unwrapChildren[2]);
- }
-
- if (op == VCExpressionGenerator.ToIntOp) {
- return z3.MkToInt(unwrapChildren[0]);
- }
-
- if (op == VCExpressionGenerator.ToRealOp) {
- return z3.MkToReal(unwrapChildren[0]);
- }
-
- throw new Exception("unhandled boogie operator");
- }
-
- public Term Visit(VCExprLiteral node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
-
- if (node == VCExpressionGenerator.True)
- return cm.z3.MkTrue();
- else if (node == VCExpressionGenerator.False)
- return cm.z3.MkFalse();
- else if (node is VCExprIntLit)
- return cm.z3.MkNumeral(((VCExprIntLit)node).Val.ToInt, cm.z3.MkIntSort());
- else if (node is VCExprRealLit) {
- string m = ((VCExprRealLit)node).Val.Mantissa.ToString();
- BigInteger e = ((VCExprRealLit)node).Val.Exponent;
- string f = BigInteger.Pow(10, e.Abs);
-
- if (e == 0) {
- return cm.z3.MkNumeral(m, cm.z3.MkRealSort());
- }
- else if (((VCExprRealLit)node).Val.Exponent > 0) {
- return cm.z3.MkMul(cm.z3.MkNumeral(m, cm.z3.MkRealSort()), cm.z3.MkNumeral(f, cm.z3.MkRealSort()));
- }
- else {
- return cm.z3.MkDiv(cm.z3.MkNumeral(m, cm.z3.MkRealSort()), cm.z3.MkNumeral(f, cm.z3.MkRealSort()));
- }
- }
- else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- public Term Visit(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- VCExprOp op = node.Op;
- Contract.Assert(op != null);
-
- if (op.Equals(VCExpressionGenerator.AndOp) || op.Equals(VCExpressionGenerator.OrOp))
- {
- // handle these operators without recursion
- List<Term> asts = new List<Term>();
- string opString = op.Equals(VCExpressionGenerator.AndOp) ? "AND" : "OR";
-
- IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
- Contract.Assert(enumerator != null);
- while (enumerator.MoveNext())
- {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(op))
- {
- asts.Add(Linearise(cce.NonNull((VCExpr)enumerator.Current), options));
- }
- }
-
- return Make(op, asts);
- }
-
- return node.Accept<Term, LineariserOptions>(OpLineariser, options);
- }
-
- public Term Visit(VCExprVar node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- if (letBindings.ContainsKey(node))
- {
- return letBindings[node];
- }
- else
- {
- string varName = namer.GetName(node, node.Name);
- return cm.GetConstant(varName, node.Type,node);
- }
- }
-
- public Term Visit(VCExprQuantifier node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- Contract.Assert(node.TypeParameters.Count == 0);
-
- namer.PushScope();
- try
- {
- List<string> varNames;
- List<Type> varTypes;
- VisitBounds(node.BoundVars, out varNames, out varTypes);
- List<Pattern> patterns;
- List<Term> no_patterns;
- VisitTriggers(node.Triggers, options, out patterns, out no_patterns);
- Term body = Linearise(node.Body, options);
- Term result;
- uint weight = 1;
- string qid = "";
- int skolemid = 0;
-
- if (options.QuantifierIds)
- {
- VCQuantifierInfos infos = node.Infos;
- Contract.Assert(infos != null);
- if (infos.qid != null)
- {
- qid = infos.qid;
- }
- if (0 <= infos.uniqueId)
- {
- skolemid = infos.uniqueId;
- }
- }
-
- if (options.UseWeights)
- {
- weight = (uint) QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
- }
-
- switch (node.Quan)
- {
- case Microsoft.Boogie.VCExprAST.Quantifier.ALL:
- result = MakeQuantifier(true, weight, qid, skolemid, varNames, varTypes, patterns, no_patterns, body); break;
- case Microsoft.Boogie.VCExprAST.Quantifier.EX:
- result = MakeQuantifier(false, weight, qid, skolemid, varNames, varTypes, patterns, no_patterns, body); break;
- default:
- throw new Exception("unknown quantifier kind " + node.Quan);
- }
- return result;
- }
- finally
- {
- namer.PopScope();
- }
- }
-
- private Term MakeQuantifier(bool isForall, uint weight, string qid, int skolemid, List<string> varNames, List<Type> boogieTypes, List<Pattern> patterns, List<Term> no_patterns, Term body) {
- List<Term> bound = new List<Term>();
- for (int i = 0; i < varNames.Count; i++) {
- Term t = cm.GetConstant(varNames[i], boogieTypes[i], null);
- bound.Add(t);
- }
-
- Term termAst = cm.z3.MkQuantifier(isForall, weight, cm.z3.MkSymbol(qid), cm.z3.MkSymbol(skolemid.ToString()), patterns.ToArray(), no_patterns.ToArray(), bound.ToArray(), body);
- return termAst;
- }
-
- private void VisitBounds(List<VCExprVar> boundVars, out List<string> varNames, out List<Type> varTypes)
- {
- varNames = new List<string>();
- varTypes = new List<Type>();
- foreach (VCExprVar var in boundVars)
- {
- string varName = namer.GetLocalName(var, var.Name);
- varNames.Add(varName);
- varTypes.Add(var.Type);
- }
- }
-
- private void VisitTriggers(List<VCTrigger> triggers, LineariserOptions options, out List<Pattern> patterns, out List<Term> no_patterns)
- {
- patterns = new List<Pattern>();
- no_patterns = new List<Term>();
- foreach (VCTrigger trigger in triggers)
- {
- List<Term> exprs = new List<Term>();
- foreach (VCExpr expr in trigger.Exprs)
- {
- System.Diagnostics.Debug.Assert(expr != null);
- Term termAst = Linearise(expr, options);
- exprs.Add(termAst);
- }
- if (exprs.Count > 0)
- {
- if (trigger.Pos) {
- Pattern pattern = cm.z3.MkPattern(exprs.ToArray());
- patterns.Add(pattern);
- }
- else {
- System.Diagnostics.Debug.Assert(false, "Z3api currently does not handle nopats");
- foreach (Term expr in exprs)
- no_patterns.Add(expr);
- }
- }
- }
- }
-
- public Term Visit(VCExprLet node, LineariserOptions options)
- {
- foreach (VCExprLetBinding b in node)
- {
- Term defAst = Linearise(b.E, options);
- letBindings.Add(b.V, defAst);
- }
- Term letAst = Linearise(node.Body, options);
- foreach (VCExprLetBinding b in node)
- {
- letBindings.Remove(b.V);
- }
- return letAst;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- internal class Z3apiOpLineariser : IVCExprOpVisitor<Term, LineariserOptions>
- {
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(ExprLineariser != null);
- }
-
- private readonly Z3apiExprLineariser ExprLineariser;
-
- public Z3apiOpLineariser(Z3apiExprLineariser ExprLineariser)
- {
- Contract.Requires(ExprLineariser != null);
- this.ExprLineariser = ExprLineariser;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- private Term WriteApplication(VCExprOp op, IEnumerable<VCExpr> terms, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(terms));
-
- List<Term> args = new List<Term>();
- foreach (VCExpr e in terms)
- {
- Contract.Assert(e != null);
- args.Add(ExprLineariser.Linearise(e, options));
- }
- return ExprLineariser.Make(op, args);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public Term VisitNotOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitEqOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitNeqOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitAndOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitOrOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitImpliesOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitDistinctOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitLabelOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- VCExprLabelOp op = (VCExprLabelOp)node.Op;
- Contract.Assert(op != null);
- return ExprLineariser.cm.MakeLabel(op.label, op.pos, ExprLineariser.Linearise(node[0], options));
- }
-
- public Term VisitSelectOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- List<Term> args = new List<Term>();
- foreach (VCExpr e in node)
- {
- Contract.Assert(e != null);
- args.Add(ExprLineariser.Linearise(e, options));
- }
- System.Diagnostics.Debug.Assert(args.Count >= 2);
-
- Term selectTerm = args[0];
- for (int i = 1; i < args.Count; i++) {
- selectTerm = ExprLineariser.cm.z3.MkArraySelect(selectTerm, args[i]);
- }
- return selectTerm;
- }
-
- private Term ConstructStoreTerm(Term mapTerm, List<Term> args, int index) {
- System.Diagnostics.Debug.Assert(0 < index && index < args.Count - 1);
- if (index == args.Count - 2) {
- return ExprLineariser.cm.z3.MkArrayStore(mapTerm, args[index], args[index + 1]);
- }
- else {
- Term t = ConstructStoreTerm(ExprLineariser.cm.z3.MkArraySelect(mapTerm, args[index]), args, index + 1);
- return ExprLineariser.cm.z3.MkArrayStore(mapTerm, args[index], t);
- }
- }
-
- public Term VisitStoreOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- List<Term> args = new List<Term>();
- foreach (VCExpr e in node)
- {
- Contract.Assert(e != null);
- args.Add(ExprLineariser.Linearise(e, options));
- }
- return ConstructStoreTerm(args[0], args, 1);
- }
-
- public Term VisitBvOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- List<int> args = new List<int>();
- foreach (VCExpr e in node) {
- VCExprIntLit literal = e as VCExprIntLit;
- System.Diagnostics.Debug.Assert(literal != null);
- args.Add(literal.Val.ToInt);
- }
- System.Diagnostics.Debug.Assert(args.Count == 1);
- return ExprLineariser.cm.z3.MkNumeral(args[0], ExprLineariser.cm.z3.MkBvSort((uint)node.Type.BvBits));
- }
-
- public Term VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
-
- VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
- Contract.Assert(op != null);
- System.Diagnostics.Debug.Assert(0 <= op.Start && op.Start < op.End);
-
- List<Term> args = new List<Term>();
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- args.Add(ExprLineariser.Linearise(e, options));
- }
- System.Diagnostics.Debug.Assert(args.Count == 1);
- return ExprLineariser.cm.z3.MkBvExtract((uint) op.End - 1, (uint) op.Start, args[0]);
- }
-
- public Term VisitBvConcatOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
-
- VCExprBvConcatOp op = (VCExprBvConcatOp)node.Op;
- Contract.Assert(op != null);
-
- List<Term> args = new List<Term>();
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- args.Add(ExprLineariser.Linearise(e, options));
- }
- System.Diagnostics.Debug.Assert(args.Count == 2);
- return ExprLineariser.cm.z3.MkBvConcat(args[0], args[1]);
- }
-
- public Term VisitIfThenElseOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitCustomOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(node != null);
- Contract.Requires(options != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitAddOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitSubOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitMulOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitDivOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitModOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitPowOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitLtOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitLeOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitGtOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitGeOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitSubtypeOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitSubtype3Op(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitToIntOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitToRealOp(VCExprNAry node, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
-
- public Term VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(node != null);
- return WriteApplication(node.Op, node, options);
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Z3;
+
+namespace Microsoft.Boogie.Z3
+{
+ using System.Numerics.BigInteger;
+
+ public class Z3apiExprLineariser : IVCExprVisitor<Term, LineariserOptions>
+ {
+ private Z3apiOpLineariser opLineariser = null;
+ private IVCExprOpVisitor<Term, LineariserOptions> OpLineariser
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
+ if (opLineariser == null)
+ opLineariser = new Z3apiOpLineariser(this);
+ return opLineariser;
+ }
+ }
+
+ internal readonly UniqueNamer namer;
+ internal readonly Dictionary<VCExprVar, Term> letBindings;
+ protected Z3apiProverContext cm;
+
+ public Z3apiExprLineariser(Z3apiProverContext cm, UniqueNamer namer)
+ {
+ this.cm = cm;
+ this.namer = namer;
+ this.letBindings = new Dictionary<VCExprVar, Term>();
+ }
+
+ public Term Linearise(VCExpr expr, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(expr != null);
+ return expr.Accept<Term, LineariserOptions>(this, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public Term Make(VCExprOp op, List<Term> children) {
+ Context z3 = cm.z3;
+ Term[] unwrapChildren = children.ToArray();
+ VCExprBoogieFunctionOp boogieFunctionOp = op as VCExprBoogieFunctionOp;
+ if (boogieFunctionOp != null) {
+ FuncDecl f = cm.GetFunction(boogieFunctionOp.Func.Name);
+ return z3.MkApp(f, unwrapChildren);
+ }
+ VCExprDistinctOp distinctOp = op as VCExprDistinctOp;
+ if (distinctOp != null) {
+ return z3.MkDistinct(unwrapChildren);
+ }
+
+ if (op == VCExpressionGenerator.AndOp) {
+ return z3.MkAnd(unwrapChildren);
+ }
+
+ if (op == VCExpressionGenerator.OrOp) {
+ return z3.MkOr(unwrapChildren);
+ }
+
+ if (op == VCExpressionGenerator.ImpliesOp) {
+ return z3.MkImplies(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.NotOp) {
+ return z3.MkNot(unwrapChildren[0]);
+ }
+
+ if (op == VCExpressionGenerator.EqOp) {
+ return z3.MkEq(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.NeqOp) {
+ return z3.MkNot(z3.MkEq(unwrapChildren[0], unwrapChildren[1]));
+ }
+
+ if (op == VCExpressionGenerator.LtOp) {
+ return z3.MkLt(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.LeOp) {
+ return z3.MkLe(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.GtOp) {
+ return z3.MkGt(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.GeOp) {
+ return z3.MkGe(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.AddOp) {
+ return z3.MkAdd(unwrapChildren);
+ }
+
+ if (op == VCExpressionGenerator.SubOp) {
+ return z3.MkSub(unwrapChildren);
+ }
+
+ if (op == VCExpressionGenerator.DivOp || op == VCExpressionGenerator.RealDivOp) {
+ return z3.MkDiv(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.MulOp) {
+ return z3.MkMul(unwrapChildren);
+ }
+
+ if (op == VCExpressionGenerator.ModOp) {
+ return z3.MkMod(unwrapChildren[0], unwrapChildren[1]);
+ }
+
+ if (op == VCExpressionGenerator.IfThenElseOp) {
+ return z3.MkIte(unwrapChildren[0], unwrapChildren[1], unwrapChildren[2]);
+ }
+
+ if (op == VCExpressionGenerator.ToIntOp) {
+ return z3.MkToInt(unwrapChildren[0]);
+ }
+
+ if (op == VCExpressionGenerator.ToRealOp) {
+ return z3.MkToReal(unwrapChildren[0]);
+ }
+
+ throw new Exception("unhandled boogie operator");
+ }
+
+ public Term Visit(VCExprLiteral node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+
+ if (node == VCExpressionGenerator.True)
+ return cm.z3.MkTrue();
+ else if (node == VCExpressionGenerator.False)
+ return cm.z3.MkFalse();
+ else if (node is VCExprIntLit)
+ return cm.z3.MkNumeral(((VCExprIntLit)node).Val.ToInt, cm.z3.MkIntSort());
+ else if (node is VCExprRealLit) {
+ string m = ((VCExprRealLit)node).Val.Mantissa.ToString();
+ BigInteger e = ((VCExprRealLit)node).Val.Exponent;
+ string f = BigInteger.Pow(10, e.Abs);
+
+ if (e == 0) {
+ return cm.z3.MkNumeral(m, cm.z3.MkRealSort());
+ }
+ else if (((VCExprRealLit)node).Val.Exponent > 0) {
+ return cm.z3.MkMul(cm.z3.MkNumeral(m, cm.z3.MkRealSort()), cm.z3.MkNumeral(f, cm.z3.MkRealSort()));
+ }
+ else {
+ return cm.z3.MkDiv(cm.z3.MkNumeral(m, cm.z3.MkRealSort()), cm.z3.MkNumeral(f, cm.z3.MkRealSort()));
+ }
+ }
+ else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ public Term Visit(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ VCExprOp op = node.Op;
+ Contract.Assert(op != null);
+
+ if (op.Equals(VCExpressionGenerator.AndOp) || op.Equals(VCExpressionGenerator.OrOp))
+ {
+ // handle these operators without recursion
+ List<Term> asts = new List<Term>();
+ string opString = op.Equals(VCExpressionGenerator.AndOp) ? "AND" : "OR";
+
+ IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
+ Contract.Assert(enumerator != null);
+ while (enumerator.MoveNext())
+ {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op))
+ {
+ asts.Add(Linearise(cce.NonNull((VCExpr)enumerator.Current), options));
+ }
+ }
+
+ return Make(op, asts);
+ }
+
+ return node.Accept<Term, LineariserOptions>(OpLineariser, options);
+ }
+
+ public Term Visit(VCExprVar node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ if (letBindings.ContainsKey(node))
+ {
+ return letBindings[node];
+ }
+ else
+ {
+ string varName = namer.GetName(node, node.Name);
+ return cm.GetConstant(varName, node.Type,node);
+ }
+ }
+
+ public Term Visit(VCExprQuantifier node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ Contract.Assert(node.TypeParameters.Count == 0);
+
+ namer.PushScope();
+ try
+ {
+ List<string> varNames;
+ List<Type> varTypes;
+ VisitBounds(node.BoundVars, out varNames, out varTypes);
+ List<Pattern> patterns;
+ List<Term> no_patterns;
+ VisitTriggers(node.Triggers, options, out patterns, out no_patterns);
+ Term body = Linearise(node.Body, options);
+ Term result;
+ uint weight = 1;
+ string qid = "";
+ int skolemid = 0;
+
+ if (options.QuantifierIds)
+ {
+ VCQuantifierInfos infos = node.Infos;
+ Contract.Assert(infos != null);
+ if (infos.qid != null)
+ {
+ qid = infos.qid;
+ }
+ if (0 <= infos.uniqueId)
+ {
+ skolemid = infos.uniqueId;
+ }
+ }
+
+ if (options.UseWeights)
+ {
+ weight = (uint) QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
+ }
+
+ switch (node.Quan)
+ {
+ case Microsoft.Boogie.VCExprAST.Quantifier.ALL:
+ result = MakeQuantifier(true, weight, qid, skolemid, varNames, varTypes, patterns, no_patterns, body); break;
+ case Microsoft.Boogie.VCExprAST.Quantifier.EX:
+ result = MakeQuantifier(false, weight, qid, skolemid, varNames, varTypes, patterns, no_patterns, body); break;
+ default:
+ throw new Exception("unknown quantifier kind " + node.Quan);
+ }
+ return result;
+ }
+ finally
+ {
+ namer.PopScope();
+ }
+ }
+
+ private Term MakeQuantifier(bool isForall, uint weight, string qid, int skolemid, List<string> varNames, List<Type> boogieTypes, List<Pattern> patterns, List<Term> no_patterns, Term body) {
+ List<Term> bound = new List<Term>();
+ for (int i = 0; i < varNames.Count; i++) {
+ Term t = cm.GetConstant(varNames[i], boogieTypes[i], null);
+ bound.Add(t);
+ }
+
+ Term termAst = cm.z3.MkQuantifier(isForall, weight, cm.z3.MkSymbol(qid), cm.z3.MkSymbol(skolemid.ToString()), patterns.ToArray(), no_patterns.ToArray(), bound.ToArray(), body);
+ return termAst;
+ }
+
+ private void VisitBounds(List<VCExprVar> boundVars, out List<string> varNames, out List<Type> varTypes)
+ {
+ varNames = new List<string>();
+ varTypes = new List<Type>();
+ foreach (VCExprVar var in boundVars)
+ {
+ string varName = namer.GetLocalName(var, var.Name);
+ varNames.Add(varName);
+ varTypes.Add(var.Type);
+ }
+ }
+
+ private void VisitTriggers(List<VCTrigger> triggers, LineariserOptions options, out List<Pattern> patterns, out List<Term> no_patterns)
+ {
+ patterns = new List<Pattern>();
+ no_patterns = new List<Term>();
+ foreach (VCTrigger trigger in triggers)
+ {
+ List<Term> exprs = new List<Term>();
+ foreach (VCExpr expr in trigger.Exprs)
+ {
+ System.Diagnostics.Debug.Assert(expr != null);
+ Term termAst = Linearise(expr, options);
+ exprs.Add(termAst);
+ }
+ if (exprs.Count > 0)
+ {
+ if (trigger.Pos) {
+ Pattern pattern = cm.z3.MkPattern(exprs.ToArray());
+ patterns.Add(pattern);
+ }
+ else {
+ System.Diagnostics.Debug.Assert(false, "Z3api currently does not handle nopats");
+ foreach (Term expr in exprs)
+ no_patterns.Add(expr);
+ }
+ }
+ }
+ }
+
+ public Term Visit(VCExprLet node, LineariserOptions options)
+ {
+ foreach (VCExprLetBinding b in node)
+ {
+ Term defAst = Linearise(b.E, options);
+ letBindings.Add(b.V, defAst);
+ }
+ Term letAst = Linearise(node.Body, options);
+ foreach (VCExprLetBinding b in node)
+ {
+ letBindings.Remove(b.V);
+ }
+ return letAst;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ internal class Z3apiOpLineariser : IVCExprOpVisitor<Term, LineariserOptions>
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(ExprLineariser != null);
+ }
+
+ private readonly Z3apiExprLineariser ExprLineariser;
+
+ public Z3apiOpLineariser(Z3apiExprLineariser ExprLineariser)
+ {
+ Contract.Requires(ExprLineariser != null);
+ this.ExprLineariser = ExprLineariser;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ private Term WriteApplication(VCExprOp op, IEnumerable<VCExpr> terms, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(terms));
+
+ List<Term> args = new List<Term>();
+ foreach (VCExpr e in terms)
+ {
+ Contract.Assert(e != null);
+ args.Add(ExprLineariser.Linearise(e, options));
+ }
+ return ExprLineariser.Make(op, args);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public Term VisitNotOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitEqOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitNeqOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitAndOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitOrOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitImpliesOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitDistinctOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitLabelOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ VCExprLabelOp op = (VCExprLabelOp)node.Op;
+ Contract.Assert(op != null);
+ return ExprLineariser.cm.MakeLabel(op.label, op.pos, ExprLineariser.Linearise(node[0], options));
+ }
+
+ public Term VisitSelectOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ List<Term> args = new List<Term>();
+ foreach (VCExpr e in node)
+ {
+ Contract.Assert(e != null);
+ args.Add(ExprLineariser.Linearise(e, options));
+ }
+ System.Diagnostics.Debug.Assert(args.Count >= 2);
+
+ Term selectTerm = args[0];
+ for (int i = 1; i < args.Count; i++) {
+ selectTerm = ExprLineariser.cm.z3.MkArraySelect(selectTerm, args[i]);
+ }
+ return selectTerm;
+ }
+
+ private Term ConstructStoreTerm(Term mapTerm, List<Term> args, int index) {
+ System.Diagnostics.Debug.Assert(0 < index && index < args.Count - 1);
+ if (index == args.Count - 2) {
+ return ExprLineariser.cm.z3.MkArrayStore(mapTerm, args[index], args[index + 1]);
+ }
+ else {
+ Term t = ConstructStoreTerm(ExprLineariser.cm.z3.MkArraySelect(mapTerm, args[index]), args, index + 1);
+ return ExprLineariser.cm.z3.MkArrayStore(mapTerm, args[index], t);
+ }
+ }
+
+ public Term VisitStoreOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ List<Term> args = new List<Term>();
+ foreach (VCExpr e in node)
+ {
+ Contract.Assert(e != null);
+ args.Add(ExprLineariser.Linearise(e, options));
+ }
+ return ConstructStoreTerm(args[0], args, 1);
+ }
+
+ public Term VisitBvOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ List<int> args = new List<int>();
+ foreach (VCExpr e in node) {
+ VCExprIntLit literal = e as VCExprIntLit;
+ System.Diagnostics.Debug.Assert(literal != null);
+ args.Add(literal.Val.ToInt);
+ }
+ System.Diagnostics.Debug.Assert(args.Count == 1);
+ return ExprLineariser.cm.z3.MkNumeral(args[0], ExprLineariser.cm.z3.MkBvSort((uint)node.Type.BvBits));
+ }
+
+ public Term VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+
+ VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
+ Contract.Assert(op != null);
+ System.Diagnostics.Debug.Assert(0 <= op.Start && op.Start < op.End);
+
+ List<Term> args = new List<Term>();
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ args.Add(ExprLineariser.Linearise(e, options));
+ }
+ System.Diagnostics.Debug.Assert(args.Count == 1);
+ return ExprLineariser.cm.z3.MkBvExtract((uint) op.End - 1, (uint) op.Start, args[0]);
+ }
+
+ public Term VisitBvConcatOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+
+ VCExprBvConcatOp op = (VCExprBvConcatOp)node.Op;
+ Contract.Assert(op != null);
+
+ List<Term> args = new List<Term>();
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ args.Add(ExprLineariser.Linearise(e, options));
+ }
+ System.Diagnostics.Debug.Assert(args.Count == 2);
+ return ExprLineariser.cm.z3.MkBvConcat(args[0], args[1]);
+ }
+
+ public Term VisitIfThenElseOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitCustomOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(node != null);
+ Contract.Requires(options != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitAddOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitSubOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitMulOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitDivOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitModOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitLtOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitLeOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitGtOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitGeOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitSubtypeOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitSubtype3Op(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+
+ public Term VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options)
+ {
+ Contract.Requires(options != null);
+ Contract.Requires(node != null);
+ return WriteApplication(node.Op, node, options);
+ }
+ }
+ }
+}
diff --git a/Source/Provers/Z3api/Z3api.csproj b/Source/Provers/Z3api/Z3api.csproj
index 1627536d..3fb2fe48 100644
--- a/Source/Provers/Z3api/Z3api.csproj
+++ b/Source/Provers/Z3api/Z3api.csproj
@@ -1,189 +1,189 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{966DD87B-A29D-4F3C-9406-F680A61DC0E0}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.Z3api</RootNamespace>
- <AssemblyName>Provers.Z3api</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <StartupObject>
- </StartupObject>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
- </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>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for Z3api.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.Z3api.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <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>
- -->
- <ItemGroup>
- <Reference Include="ManagedAPI">
- <HintPath>..\..\..\..\..\iZ3\win\iZ3\Debug\ManagedAPI.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.XML" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="ContextLayer.cs" />
- <Compile Include="ProverLayer.cs" />
- <Compile Include="TypeAdapter.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="VCExprVisitor.cs" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{966DD87B-A29D-4F3C-9406-F680A61DC0E0}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Boogie.Z3api</RootNamespace>
+ <AssemblyName>Provers.Z3api</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <StartupObject>
+ </StartupObject>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ </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>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for Z3api.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\Provers.Z3api.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ </PropertyGroup>
+ <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>
+ -->
+ <ItemGroup>
+ <Reference Include="ManagedAPI">
+ <HintPath>..\..\..\..\..\iZ3\win\iZ3\Debug\ManagedAPI.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.XML" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Model\Model.csproj">
+ <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
+ <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
+ <Name>VCGeneration</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="ContextLayer.cs" />
+ <Compile Include="ProverLayer.cs" />
+ <Compile Include="TypeAdapter.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="VCExprVisitor.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/Source/Provers/Z3api/cce.cs b/Source/Provers/Z3api/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/Provers/Z3api/cce.cs
+++ b/Source/Provers/Z3api/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/UnitTests/BasetypesTests/BasetypesTests.csproj b/Source/UnitTests/BasetypesTests/BasetypesTests.csproj
index a2056f95..7ace2930 100644
--- a/Source/UnitTests/BasetypesTests/BasetypesTests.csproj
+++ b/Source/UnitTests/BasetypesTests/BasetypesTests.csproj
@@ -1,69 +1,69 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>BasetypesTests</RootNamespace>
- <AssemblyName>BasetypesTests</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- </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>
- </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="nunit.framework">
- <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Numerics" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="BigDecTests.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
- </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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{D00C3F22-1EDA-4781-8F0E-81991E9CB0D9}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>BasetypesTests</RootNamespace>
+ <AssemblyName>BasetypesTests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </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>
+ </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="nunit.framework">
+ <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Numerics" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BigDecTests.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
+ <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </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/UnitTests/BasetypesTests/Properties/AssemblyInfo.cs b/Source/UnitTests/BasetypesTests/Properties/AssemblyInfo.cs
index 4ef7c05c..316282c7 100644
--- a/Source/UnitTests/BasetypesTests/Properties/AssemblyInfo.cs
+++ b/Source/UnitTests/BasetypesTests/Properties/AssemblyInfo.cs
@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("BasetypesTests")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("BasetypesTests")]
-[assembly: AssemblyCopyright("Copyright © 2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("0cca79cc-3251-46d9-87c1-32bc782d9fdd")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BasetypesTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("BasetypesTests")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0cca79cc-3251-46d9-87c1-32bc782d9fdd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/UnitTests/BasetypesTests/packages.config b/Source/UnitTests/BasetypesTests/packages.config
index d4e241a2..ad37a528 100644
--- a/Source/UnitTests/BasetypesTests/packages.config
+++ b/Source/UnitTests/BasetypesTests/packages.config
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="NUnit" version="2.6.3" targetFramework="net45" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/Source/UnitTests/CoreTests/CoreTests.csproj b/Source/UnitTests/CoreTests/CoreTests.csproj
index ddf310be..24fd8c45 100644
--- a/Source/UnitTests/CoreTests/CoreTests.csproj
+++ b/Source/UnitTests/CoreTests/CoreTests.csproj
@@ -1,84 +1,84 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{961B3BCA-2067-43B2-8E43-23C4293F21B9}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>CoreTests</RootNamespace>
- <AssemblyName>CoreTests</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- </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>
- </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="nunit.framework">
- <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="AbsyMetadata.cs" />
- <Compile Include="Duplicator.cs" />
- <Compile Include="ExprEquality.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="ExprTypeChecking.cs" />
- <Compile Include="ExprImmutability.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\TestUtil\TestUtil.csproj">
- <Project>{59118E35-4236-495E-AF6E-0D641302ED2C}</Project>
- <Name>TestUtil</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
- </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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{961B3BCA-2067-43B2-8E43-23C4293F21B9}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>CoreTests</RootNamespace>
+ <AssemblyName>CoreTests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </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>
+ </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="nunit.framework">
+ <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AbsyMetadata.cs" />
+ <Compile Include="Duplicator.cs" />
+ <Compile Include="ExprEquality.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ExprTypeChecking.cs" />
+ <Compile Include="ExprImmutability.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
+ <Project>{43dfad18-3e35-4558-9be2-caff6b5ba8a0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\TestUtil\TestUtil.csproj">
+ <Project>{59118E35-4236-495E-AF6E-0D641302ED2C}</Project>
+ <Name>TestUtil</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </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/UnitTests/CoreTests/Duplicator.cs b/Source/UnitTests/CoreTests/Duplicator.cs
index 978a041b..9e118f5d 100644
--- a/Source/UnitTests/CoreTests/Duplicator.cs
+++ b/Source/UnitTests/CoreTests/Duplicator.cs
@@ -28,7 +28,7 @@ namespace CoreTests
var A = new BvConcatExpr(Token.NoToken, bv1_8, bv2_8);
var B = d.Visit(A);
- // The duplicator should ensure we get new BVConcatExprs
+ // The duplicator should ensure we get new BVConcatExprs
Assert.AreNotSame(A, B);
}
@@ -38,7 +38,7 @@ namespace CoreTests
var A = new BvExtractExpr(Token.NoToken, bv2_8, 6,0);
var B = d.Visit(A);
- // The duplicator should ensure we get new BVExtractExprs
+ // The duplicator should ensure we get new BVExtractExprs
Assert.AreNotSame(A, B);
}
@@ -47,8 +47,8 @@ namespace CoreTests
var bv1_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 8);
var bv2_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(2), 8);
var A = NAryExpr.Eq (bv1_8, bv2_8);
- var B = d.Visit(A);
-
+ var B = d.Visit(A);
+
Assert.AreNotSame(A, B);
}
diff --git a/Source/UnitTests/CoreTests/Properties/AssemblyInfo.cs b/Source/UnitTests/CoreTests/Properties/AssemblyInfo.cs
index fb965517..ddb95704 100644
--- a/Source/UnitTests/CoreTests/Properties/AssemblyInfo.cs
+++ b/Source/UnitTests/CoreTests/Properties/AssemblyInfo.cs
@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("CoreTests")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("CoreTests")]
-[assembly: AssemblyCopyright("Copyright © 2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("5c6f8617-e212-4ab7-bce6-5b1a930fa2b8")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CoreTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CoreTests")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5c6f8617-e212-4ab7-bce6-5b1a930fa2b8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/UnitTests/CoreTests/packages.config b/Source/UnitTests/CoreTests/packages.config
index d4e241a2..ad37a528 100644
--- a/Source/UnitTests/CoreTests/packages.config
+++ b/Source/UnitTests/CoreTests/packages.config
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="NUnit" version="2.6.3" targetFramework="net45" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/Source/UnitTests/TestUtil/Properties/AssemblyInfo.cs b/Source/UnitTests/TestUtil/Properties/AssemblyInfo.cs
index 05c9fee5..dfff6200 100644
--- a/Source/UnitTests/TestUtil/Properties/AssemblyInfo.cs
+++ b/Source/UnitTests/TestUtil/Properties/AssemblyInfo.cs
@@ -1,36 +1,36 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("TestUtil")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("TestUtil")]
-[assembly: AssemblyCopyright("Copyright © 2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("5630b725-b802-4f97-9e46-6cdfd6819269")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TestUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TestUtil")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5630b725-b802-4f97-9e46-6cdfd6819269")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/UnitTests/TestUtil/TestUtil.csproj b/Source/UnitTests/TestUtil/TestUtil.csproj
index b5d620a8..463b6454 100644
--- a/Source/UnitTests/TestUtil/TestUtil.csproj
+++ b/Source/UnitTests/TestUtil/TestUtil.csproj
@@ -1,71 +1,71 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{59118E35-4236-495E-AF6E-0D641302ED2C}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>TestUtil</RootNamespace>
- <AssemblyName>TestUtil</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- </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>
- </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="nunit.framework">
- <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="AssertionTextWriterTraceListener.cs" />
- <Compile Include="BoogieTestBase.cs" />
- <Compile Include="ProgramLoader.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{b230a69c-c466-4065-b9c1-84d80e76d802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{fcd3ac7f-9dfd-46c8-ab1e-09f0b0f16dc5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- </ItemGroup>
- <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>
- -->
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{59118E35-4236-495E-AF6E-0D641302ED2C}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>TestUtil</RootNamespace>
+ <AssemblyName>TestUtil</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </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>
+ </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="nunit.framework">
+ <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AssertionTextWriterTraceListener.cs" />
+ <Compile Include="BoogieTestBase.cs" />
+ <Compile Include="ProgramLoader.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Core\Core.csproj">
+ <Project>{b230a69c-c466-4065-b9c1-84d80e76d802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
+ <Project>{fcd3ac7f-9dfd-46c8-ab1e-09f0b0f16dc5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <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/UnitTests/TestUtil/packages.config b/Source/UnitTests/TestUtil/packages.config
index d4e241a2..ad37a528 100644
--- a/Source/UnitTests/TestUtil/packages.config
+++ b/Source/UnitTests/TestUtil/packages.config
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="NUnit" version="2.6.3" targetFramework="net45" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/Source/VCExpr/BigLiteralAbstracter.cs b/Source/VCExpr/BigLiteralAbstracter.cs
index 879ab6d6..39064fb7 100644
--- a/Source/VCExpr/BigLiteralAbstracter.cs
+++ b/Source/VCExpr/BigLiteralAbstracter.cs
@@ -1,232 +1,232 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Code for replacing large integer literals in VCExpr with
-// constants. This is necessary for Simplify, which cannot deal with
-// literals larger than 32 bits
-
-namespace Microsoft.Boogie.VCExprAST {
-
- public class BigLiteralAbstracter : MutatingVCExprVisitor<bool>, ICloneable {
-
- public BigLiteralAbstracter(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
- DummyVar = gen.Variable("x", Type.Int);
- IncAxioms = new List<VCExpr>();
- Literals = new List<KeyValuePair<BigNum, VCExprVar>>();
- }
-
- private BigLiteralAbstracter(BigLiteralAbstracter abstracter)
- : base(abstracter.Gen) {
- Contract.Requires(abstracter != null);
- DummyVar = abstracter.DummyVar;
- IncAxioms = new List<VCExpr>(abstracter.IncAxioms);
- Literals = new List<KeyValuePair<BigNum, VCExprVar>>(abstracter.Literals);
- }
-
- public Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
-
- return new BigLiteralAbstracter(this);
- }
-
- private static readonly BigNum ConstantDistance = BigNum.FromLong(100000);
- private static readonly BigNum NegConstantDistance = BigNum.FromLong(-100000);
- // distance twice plus one
- private static readonly BigNum ConstantDistanceTPO = BigNum.FromLong(200001);
- private static readonly BigNum ConstantDistancePO = BigNum.FromLong(100001);
-
- public VCExpr Abstract(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Mutate(expr, true);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // list in which axioms are incrementally collected
- private readonly List<VCExpr/*!*/>/*!*/ IncAxioms;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(IncAxioms));
- }
-
- private void AddAxiom(VCExpr/*!*/ axiom) {
- Contract.Requires(axiom != null);
- IncAxioms.Add(axiom);
- }
-
- // Return all axioms that were added since the last time NewAxioms
- // was called
- public VCExpr GetNewAxioms() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
- IncAxioms.Clear();
- return res;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // All named integer literals known to the visitor, in ascending
- // order. Such literals are always positive, and the distance
- // between two literals is always more than ConstantDistance.
- private readonly List<KeyValuePair<BigNum, VCExprVar/*!*/>>/*!*/ Literals;
-
- [ContractInvariantMethod]
- void ObjectInvariat() {
- Contract.Invariant(Literals != null);
- Contract.Invariant(Contract.ForAll(Literals, i => i.Value != null));
- }
-
-
- private class EntryComparerC : IComparer<KeyValuePair<BigNum, VCExprVar/*!*/>> {
- public int Compare(KeyValuePair<BigNum, VCExprVar/*!*/> a,
- KeyValuePair<BigNum, VCExprVar/*!*/> b) {
- //Contract.Requires(a.Value!=null);
- //Contract.Requires(b.Value!=null);
- return a.Key.CompareTo(b.Key);
- }
- }
-
- private static readonly EntryComparerC EntryComparer = new EntryComparerC();
-
- // variable used when searching for entries in the literal list
- private readonly VCExprVar/*!*/ DummyVar;
- [ContractInvariantMethod]
- void ObjectInvarint() {
- Contract.Invariant(DummyVar != null);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Construct an expression to represent the given (large) integer
- // literal. Constants are defined and axiomatised if necessary
- private VCExpr Represent(BigNum lit) {
- Contract.Requires((NegConstantDistance > lit || lit > ConstantDistance));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (lit.IsNegative)
- return Gen.Function(VCExpressionGenerator.SubIOp,
- Gen.Integer(BigNum.ZERO), RepresentPos(lit.Neg));
- else
- return RepresentPos(lit);
- }
-
- private VCExpr RepresentPos(BigNum lit) {
- Contract.Requires((lit > ConstantDistance));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- int index = GetIndexFor(lit);
- if (index >= 0)
- // precise match
- return Literals[index].Value;
-
- // check whether a constant is defined that is at most
- // ConstantDistance away from lit
- index = ~index;
- VCExpr res = null;
- BigNum resDistance = ConstantDistancePO;
-
- if (index > 0) {
- BigNum dist = lit - Literals[index - 1].Key;
- if (dist < resDistance) {
- resDistance = dist;
- res = Gen.Function(VCExpressionGenerator.AddIOp,
- Literals[index - 1].Value, Gen.Integer(dist));
- }
- }
-
- if (index < Literals.Count) {
- BigNum dist = Literals[index].Key - lit;
- if (dist < resDistance) {
- resDistance = dist;
- res = Gen.Function(VCExpressionGenerator.SubIOp,
- Literals[index].Value, Gen.Integer(dist));
- }
- }
-
- if (res != null)
- return res;
-
- // otherwise, define a new constant to represent this literal
- return AddConstantFor(lit);
- }
-
- private VCExpr AddConstantFor(BigNum lit) {
- Contract.Requires((lit > ConstantDistance));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExprVar res = Gen.Variable("int#" + lit, Type.Int);
- int index = GetIndexFor(lit);
- Contract.Assert(index < 0);
- index = ~index;
-
- Literals.Insert(index, new KeyValuePair<BigNum, VCExprVar>(lit, res));
-
- // relate the new constant to the predecessor and successor
- if (index > 0)
- DefineRelationship(Literals[index - 1].Value, Literals[index - 1].Key,
- res, lit);
- else
- DefineRelationship(Gen.Integer(BigNum.ZERO), BigNum.ZERO, res, lit);
-
- if (index < Literals.Count - 1)
- DefineRelationship(res, lit,
- Literals[index + 1].Value, Literals[index + 1].Key);
-
- return res;
- }
-
- private void DefineRelationship(VCExpr/*!*/ aExpr, BigNum aValue,
- VCExpr/*!*/ bExpr, BigNum bValue) {
- Contract.Requires(aValue < bValue);
- Contract.Requires(aExpr != null);
- Contract.Requires(bExpr != null);
-
- BigNum dist = bValue - aValue;
- VCExpr distExpr = Gen.Function(VCExpressionGenerator.SubIOp, bExpr, aExpr);
- if (dist <= ConstantDistanceTPO)
- // constants that are sufficiently close to each other are put
- // into a precise relationship
- AddAxiom(Gen.Eq(distExpr, Gen.Integer(dist)));
- else
- AddAxiom(Gen.Function(VCExpressionGenerator.GtOp,
- distExpr, Gen.Integer(ConstantDistanceTPO)));
- }
-
- private int GetIndexFor(BigNum lit) {
- return Literals.BinarySearch(new KeyValuePair<BigNum, VCExprVar>
- (lit, DummyVar),
- EntryComparer);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLiteral node, bool arg) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprIntLit intLit = node as VCExprIntLit;
- if (intLit != null) {
- if (NegConstantDistance > intLit.Val || intLit.Val > ConstantDistance)
- return Represent(intLit.Val);
- }
- return node;
- }
-
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Code for replacing large integer literals in VCExpr with
+// constants. This is necessary for Simplify, which cannot deal with
+// literals larger than 32 bits
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ public class BigLiteralAbstracter : MutatingVCExprVisitor<bool>, ICloneable {
+
+ public BigLiteralAbstracter(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+ DummyVar = gen.Variable("x", Type.Int);
+ IncAxioms = new List<VCExpr>();
+ Literals = new List<KeyValuePair<BigNum, VCExprVar>>();
+ }
+
+ private BigLiteralAbstracter(BigLiteralAbstracter abstracter)
+ : base(abstracter.Gen) {
+ Contract.Requires(abstracter != null);
+ DummyVar = abstracter.DummyVar;
+ IncAxioms = new List<VCExpr>(abstracter.IncAxioms);
+ Literals = new List<KeyValuePair<BigNum, VCExprVar>>(abstracter.Literals);
+ }
+
+ public Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ return new BigLiteralAbstracter(this);
+ }
+
+ private static readonly BigNum ConstantDistance = BigNum.FromLong(100000);
+ private static readonly BigNum NegConstantDistance = BigNum.FromLong(-100000);
+ // distance twice plus one
+ private static readonly BigNum ConstantDistanceTPO = BigNum.FromLong(200001);
+ private static readonly BigNum ConstantDistancePO = BigNum.FromLong(100001);
+
+ public VCExpr Abstract(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Mutate(expr, true);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // list in which axioms are incrementally collected
+ private readonly List<VCExpr/*!*/>/*!*/ IncAxioms;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(IncAxioms));
+ }
+
+ private void AddAxiom(VCExpr/*!*/ axiom) {
+ Contract.Requires(axiom != null);
+ IncAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr GetNewAxioms() {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
+ IncAxioms.Clear();
+ return res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // All named integer literals known to the visitor, in ascending
+ // order. Such literals are always positive, and the distance
+ // between two literals is always more than ConstantDistance.
+ private readonly List<KeyValuePair<BigNum, VCExprVar/*!*/>>/*!*/ Literals;
+
+ [ContractInvariantMethod]
+ void ObjectInvariat() {
+ Contract.Invariant(Literals != null);
+ Contract.Invariant(Contract.ForAll(Literals, i => i.Value != null));
+ }
+
+
+ private class EntryComparerC : IComparer<KeyValuePair<BigNum, VCExprVar/*!*/>> {
+ public int Compare(KeyValuePair<BigNum, VCExprVar/*!*/> a,
+ KeyValuePair<BigNum, VCExprVar/*!*/> b) {
+ //Contract.Requires(a.Value!=null);
+ //Contract.Requires(b.Value!=null);
+ return a.Key.CompareTo(b.Key);
+ }
+ }
+
+ private static readonly EntryComparerC EntryComparer = new EntryComparerC();
+
+ // variable used when searching for entries in the literal list
+ private readonly VCExprVar/*!*/ DummyVar;
+ [ContractInvariantMethod]
+ void ObjectInvarint() {
+ Contract.Invariant(DummyVar != null);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Construct an expression to represent the given (large) integer
+ // literal. Constants are defined and axiomatised if necessary
+ private VCExpr Represent(BigNum lit) {
+ Contract.Requires((NegConstantDistance > lit || lit > ConstantDistance));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (lit.IsNegative)
+ return Gen.Function(VCExpressionGenerator.SubIOp,
+ Gen.Integer(BigNum.ZERO), RepresentPos(lit.Neg));
+ else
+ return RepresentPos(lit);
+ }
+
+ private VCExpr RepresentPos(BigNum lit) {
+ Contract.Requires((lit > ConstantDistance));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ int index = GetIndexFor(lit);
+ if (index >= 0)
+ // precise match
+ return Literals[index].Value;
+
+ // check whether a constant is defined that is at most
+ // ConstantDistance away from lit
+ index = ~index;
+ VCExpr res = null;
+ BigNum resDistance = ConstantDistancePO;
+
+ if (index > 0) {
+ BigNum dist = lit - Literals[index - 1].Key;
+ if (dist < resDistance) {
+ resDistance = dist;
+ res = Gen.Function(VCExpressionGenerator.AddIOp,
+ Literals[index - 1].Value, Gen.Integer(dist));
+ }
+ }
+
+ if (index < Literals.Count) {
+ BigNum dist = Literals[index].Key - lit;
+ if (dist < resDistance) {
+ resDistance = dist;
+ res = Gen.Function(VCExpressionGenerator.SubIOp,
+ Literals[index].Value, Gen.Integer(dist));
+ }
+ }
+
+ if (res != null)
+ return res;
+
+ // otherwise, define a new constant to represent this literal
+ return AddConstantFor(lit);
+ }
+
+ private VCExpr AddConstantFor(BigNum lit) {
+ Contract.Requires((lit > ConstantDistance));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExprVar res = Gen.Variable("int#" + lit, Type.Int);
+ int index = GetIndexFor(lit);
+ Contract.Assert(index < 0);
+ index = ~index;
+
+ Literals.Insert(index, new KeyValuePair<BigNum, VCExprVar>(lit, res));
+
+ // relate the new constant to the predecessor and successor
+ if (index > 0)
+ DefineRelationship(Literals[index - 1].Value, Literals[index - 1].Key,
+ res, lit);
+ else
+ DefineRelationship(Gen.Integer(BigNum.ZERO), BigNum.ZERO, res, lit);
+
+ if (index < Literals.Count - 1)
+ DefineRelationship(res, lit,
+ Literals[index + 1].Value, Literals[index + 1].Key);
+
+ return res;
+ }
+
+ private void DefineRelationship(VCExpr/*!*/ aExpr, BigNum aValue,
+ VCExpr/*!*/ bExpr, BigNum bValue) {
+ Contract.Requires(aValue < bValue);
+ Contract.Requires(aExpr != null);
+ Contract.Requires(bExpr != null);
+
+ BigNum dist = bValue - aValue;
+ VCExpr distExpr = Gen.Function(VCExpressionGenerator.SubIOp, bExpr, aExpr);
+ if (dist <= ConstantDistanceTPO)
+ // constants that are sufficiently close to each other are put
+ // into a precise relationship
+ AddAxiom(Gen.Eq(distExpr, Gen.Integer(dist)));
+ else
+ AddAxiom(Gen.Function(VCExpressionGenerator.GtOp,
+ distExpr, Gen.Integer(ConstantDistanceTPO)));
+ }
+
+ private int GetIndexFor(BigNum lit) {
+ return Literals.BinarySearch(new KeyValuePair<BigNum, VCExprVar>
+ (lit, DummyVar),
+ EntryComparer);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLiteral node, bool arg) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprIntLit intLit = node as VCExprIntLit;
+ if (intLit != null) {
+ if (NegConstantDistance > intLit.Val || intLit.Val > ConstantDistance)
+ return Represent(intLit.Val);
+ }
+ return node;
+ }
+
+ }
+
} \ No newline at end of file
diff --git a/Source/VCExpr/Boogie2VCExpr.cs b/Source/VCExpr/Boogie2VCExpr.cs
index ad319c0e..a3364ad8 100644
--- a/Source/VCExpr/Boogie2VCExpr.cs
+++ b/Source/VCExpr/Boogie2VCExpr.cs
@@ -1,1239 +1,1239 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// A translator from the Boogie AST to the VCExpr AST.
-// This was previously realised in the methods AbsyExpr.VCView
-
-namespace Microsoft.Boogie.VCExprAST {
- using Microsoft.Boogie;
-
- // TODO: in future we might use that for defining symbols for Boogie's conditional compilation
- public class VCGenerationOptions {
- private readonly List<string/*!*/>/*!*/ SupportedProverCommands;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(SupportedProverCommands));
- }
-
-
- public bool IsProverCommandSupported(string kind) {
- Contract.Requires(kind != null);
- return SupportedProverCommands.Contains(kind);
- }
-
- public bool IsAnyProverCommandSupported(string kinds) {
- Contract.Requires(kinds != null);
- if (kinds.IndexOf(',') < 0) {
- return IsProverCommandSupported(kinds);
- } else {
- return kinds.Split(',', ' ').Any(k => IsProverCommandSupported(k));
- }
- }
-
- public VCGenerationOptions(List<string/*!*/>/*!*/ supportedProverCommands) {
- Contract.Requires(cce.NonNullElements(supportedProverCommands));
- this.SupportedProverCommands = supportedProverCommands;
- }
- }
-
- public delegate VCExpr/*!*/ CodeExprConverter(CodeExpr/*!*/ codeExpr, Hashtable/*<Block, VCExprVar!>*//*!*/ blockVariables, List<VCExprLetBinding> bindings, bool isPositiveContext);
-
- public class Boogie2VCExprTranslator : ReadOnlyVisitor, ICloneable {
- // Stack on which the various Visit-methods put the result of the translation
- private readonly Stack<VCExpr/*!*/>/*!*/ SubExpressions = new Stack<VCExpr>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(SubExpressions));
- Contract.Invariant(Gen != null);
- }
-
-
- private void Push(VCExpr expr) {
- Contract.Requires(expr != null);
- SubExpressions.Push(expr);
- }
-
- private VCExpr Pop() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return SubExpressions.Pop();
- }
-
- public VCExpr Translate(Expr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- this.Visit(expr);
- return Pop();
- }
-
- public List<VCExpr/*!*/>/*!*/ Translate(IList<Expr> exprs) {
- Contract.Requires(exprs != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- foreach (Expr e in exprs)
- res.Add(Translate(cce.NonNull(e)));
- return res;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- internal readonly VCExpressionGenerator/*!*/ Gen;
-
- public Boogie2VCExprTranslator(VCExpressionGenerator gen,
- VCGenerationOptions genOptions) {
- Contract.Requires(gen != null);
- Contract.Requires(genOptions != null);
- this.Gen = gen;
- this.GenerationOptions = genOptions;
- UnboundVariables = new VariableMapping<Variable>();
- BoundVariables = new VariableMapping<BoundVariable>();
- Formals = new VariableMapping<Formal>();
- }
-
- private Boogie2VCExprTranslator(Boogie2VCExprTranslator tl) {
- Contract.Requires(tl != null);
- this.Gen = tl.Gen;
- this.GenerationOptions = tl.GenerationOptions;
- UnboundVariables =
- (VariableMapping<Variable>)tl.UnboundVariables.Clone();
- BoundVariables = new VariableMapping<BoundVariable>();
- Formals = new VariableMapping<Formal>();
- }
-
- public object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
- return new Boogie2VCExprTranslator(this);
- }
-
- private IAppliableTranslator IAppTranslatorAttr = null;
- private IAppliableTranslator IAppTranslator {
- get {
- Contract.Ensures(Contract.Result<IAppliableTranslator>() != null);
-
- if (IAppTranslatorAttr == null)
- IAppTranslatorAttr = new IAppliableTranslator(this);
- return IAppTranslatorAttr;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Class for handling occurring variables
-
- private class VariableMapping<VarKind> : ICloneable {
- private readonly List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ Mapping;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Mapping != null && Contract.ForAll(Mapping, i => cce.NonNullDictionaryAndValues(i)));
- }
-
-
- public VariableMapping() {
- List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping =
- new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>();
- mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>());
- this.Mapping = mapping;
- }
-
- private VariableMapping(VariableMapping<VarKind> vm) {
- Contract.Requires(vm != null);
- List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping =
- new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>();
- foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in vm.Mapping) {
- Contract.Assert(cce.NonNullDictionaryAndValues(d));
- mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>(d));
- }
- this.Mapping = mapping;
- }
-
- public object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
- return new VariableMapping<VarKind>(this);
- }
-
- public void PushScope() {
- Mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>());
- }
-
- public void PopScope() {
- Contract.Assume(Mapping.Count > 0);
- Mapping.RemoveAt(Mapping.Count - 1);
- }
-
- public void Bind(VarKind boogieVar, VCExprVar/*!*/ vcExprVar) {
- Contract.Requires(vcExprVar != null);
- Contract.Requires(boogieVar != null);
- Contract.Requires(!Contains(boogieVar));
- Mapping[Mapping.Count - 1].Add(boogieVar, vcExprVar);
- }
-
- public VCExprVar Lookup(VarKind boogieVar) {
- Contract.Requires(boogieVar != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res = LookupHelp(boogieVar);
- Contract.Assume(res != null);
- return res;
- }
-
- [Pure]
- public bool Contains(VarKind boogieVar) {
- Contract.Requires(boogieVar != null);
- return LookupHelp(boogieVar) != null;
- }
-
- public bool TryGetValue(VarKind boogieVar, out VCExprVar res) {
- Contract.Requires(boogieVar != null);
- res = LookupHelp(boogieVar);
- return res != null;
- }
-
- [Pure]
- private VCExprVar LookupHelp(VarKind boogieVar) {
- Contract.Requires(boogieVar != null);
- VCExprVar res;
- foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in Mapping) {
- //Contract.Assert(cce.NonNullElements(d));
- if (d.TryGetValue(boogieVar, out res)) {
- Contract.Assert(res != null);
- return res;
- }
- }
- return null;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////
-
- private readonly VariableMapping<Variable>/*!*/ UnboundVariables;
- private readonly VariableMapping<BoundVariable>/*!*/ BoundVariables;
- // used when translating the bodies of function expansions
- private readonly VariableMapping<Formal>/*!*/ Formals;
- [ContractInvariantMethod]
- void ObjectInvairant() {
- Contract.Invariant(UnboundVariables != null);
- Contract.Invariant(BoundVariables != null);
- Contract.Invariant(Formals != null);
- }
-
-
- internal void PushBoundVariableScope() {
- BoundVariables.PushScope();
- }
- internal void PopBoundVariableScope() {
- BoundVariables.PopScope();
- }
-
- internal void PushFormalsScope() {
- Formals.PushScope();
- }
- internal void PopFormalsScope() {
- Formals.PopScope();
- }
-
- public VCExprVar BindVariable(Variable boogieVar) {
- Contract.Requires(boogieVar != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- if (boogieVar is BoundVariable) {
- VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
- BoundVariables.Bind((BoundVariable)boogieVar, newVar);
- return newVar;
- } else if (boogieVar is Formal) {
- VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
- Formals.Bind((Formal)boogieVar, newVar);
- return newVar;
- } else {
- // only bound variables and formals are declared explicitly
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- public VCExprVar LookupVariable(Variable boogieVar) {
- Contract.Requires(boogieVar != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
-
- BoundVariable bv = boogieVar as BoundVariable;
- if (bv != null) {
- return BoundVariables.Lookup(bv);
- }
- VCExprVar res;
- Formal fml = boogieVar as Formal;
- if (fml != null && Formals.TryGetValue(fml, out res))
- return cce.NonNull(res);
-
- // global variables, local variables, incarnations, etc. are
- // bound the first time they occur
- if (!UnboundVariables.TryGetValue(boogieVar, out res)) {
- if (boogieVar is Constant)
- res = new VCExprConstant(boogieVar.Name, boogieVar.TypedIdent.Type);
- else
- res = new VCExprVar(boogieVar.Name, boogieVar.TypedIdent.Type);
- UnboundVariables.Bind(boogieVar, res);
- }
- return cce.NonNull(res);
- }
-
- /// <summary>
- /// Unlike LookupVariable, this method does not create a new variable mapping if none is
- /// found. Instead, this method returns null in such cases. Also, this method does not
- /// look for bound variables.
- /// </summary>
- /// <param name="boogieVar"></param>
- /// <returns></returns>
- public VCExprVar TryLookupVariable(Variable boogieVar) {
- Contract.Requires(boogieVar != null);
-
- VCExprVar res;
- Formal fml = boogieVar as Formal;
- if (fml != null && Formals.TryGetValue(fml, out res))
- return cce.NonNull(res);
-
- if (UnboundVariables.TryGetValue(boogieVar, out res)) {
- return cce.NonNull(res);
- }
-
- return null; // not present
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- internal readonly VCGenerationOptions/*!*/ GenerationOptions;
- [ContractInvariantMethod]
- void ObjectInvarian() {
- Contract.Invariant(GenerationOptions != null);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitLiteralExpr(LiteralExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateLiteralExpr(node));
- return node;
- }
- private VCExpr TranslateLiteralExpr(LiteralExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (node.Val is bool) {
- bool b = (bool)node.Val;
- if (b) {
- return VCExpressionGenerator.True;
- } else {
- return VCExpressionGenerator.False;
- }
- } else if (node.Val is BigNum) {
- return Gen.Integer(node.asBigNum);
- } else if (node.Val is BigDec) {
- return Gen.Real(node.asBigDec);
- } else if (node.Val is BigFloat) {
- return Gen.Float(node.asBigFloat);
- }
- else if (node.Val is BvConst) {
- return Gen.Bitvector((BvConst)node.Val);
- } else {
- System.Diagnostics.Debug.Assert(false, "unknown kind of literal " + node.tok.ToString());
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Contract.Assume(node.Decl != null); // the expression has to be resolved
- Push(LookupVariable(node.Decl));
- return node;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- // Because of our scheme for numbering incarnations of variables, the pre-state
- // value of a variable x is always just "x". (The first update to it in a method
- // causes it to become "x0". So we just remove old expressions with a visitor
- // before transforming it into a VCExpr.
- public override Expr VisitOldExpr(OldExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitNAryExpr(NAryExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateNAryExpr(node));
- return node;
- }
-
- public bool isPositiveContext = true;
- private VCExpr TranslateNAryExpr(NAryExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- bool flipContextForArg0 = false;
- if (node.Fun is UnaryOperator)
- {
- UnaryOperator oper = (UnaryOperator)node.Fun;
- if (oper.Op == UnaryOperator.Opcode.Not)
- flipContextForArg0 = true;
- }
- else if (node.Fun is BinaryOperator)
- {
- BinaryOperator oper = (BinaryOperator)node.Fun;
- if (oper.Op == BinaryOperator.Opcode.Imp)
- flipContextForArg0 = true;
- else if (oper.Op == BinaryOperator.Opcode.Iff) {
- Expr one = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[0], node.Args[1] });
- Expr two = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[1], node.Args[0] });
- NAryExpr cmpd = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.And), new List<Expr> { one, two });
- TypecheckingContext tc = new TypecheckingContext(null);
- cmpd.Typecheck(tc);
- return TranslateNAryExpr(cmpd);
- }
- }
-
- int n = node.Args.Count;
- List<VCExpr/*!*/>/*!*/ vcs = new List<VCExpr/*!*/>(n);
-
- for (int i = 0; i < n; i++) {
- if (i == 0 && flipContextForArg0)
- isPositiveContext = !isPositiveContext;
- vcs.Add(Translate(cce.NonNull(node.Args)[i]));
- if (i == 0 && flipContextForArg0)
- isPositiveContext = !isPositiveContext;
- }
-
- if (node.Type == null) {
- System.Console.WriteLine("*** type is null for {0}", node);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- return IAppTranslator.Translate(node.Fun, node.Type, vcs,
- ToList(cce.NonNull(node.TypeParameters)));
- }
-
-
- private static List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvirant() {
- Contract.Invariant(EMPTY_TYPE_LIST != null);
- }
-
-
- private List<Type/*!*/>/*!*/ ToList(TypeParamInstantiation insts) {
- Contract.Requires(insts != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- if (insts.FormalTypeParams.Count == 0)
- return EMPTY_TYPE_LIST;
-
- List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>();
- foreach (TypeVariable/*!*/ var in insts.FormalTypeParams) {
- Contract.Assert(var != null);
- typeArgs.Add(insts[var]);
- }
- return typeArgs;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<QuantifierExpr>() != null);
- Push(TranslateQuantifierExpr(node));
- return node;
- }
-
- public override Expr VisitExistsExpr(ExistsExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (ExistsExpr)this.VisitQuantifierExpr(node);
- return node;
- }
-
- public override Expr VisitForallExpr(ForallExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (ForallExpr)this.VisitQuantifierExpr(node);
- return node;
- }
-
- private VCExpr TranslateQuantifierExpr(QuantifierExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<TypeVariable/*!*/>/*!*/ typeParams = new List<TypeVariable/*!*/>();
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- typeParams.Add(v);
- }
-
- PushBoundVariableScope();
-
- List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>();
- foreach (Variable/*!*/ v in node.Dummies)
- boundVars.Add(BindVariable(v));
-
- try {
- List<VCTrigger/*!*/>/*!*/ triggers = TranslateTriggers(node.Triggers);
- VCExpr/*!*/ body = Translate(node.Body);
- VCQuantifierInfos/*!*/ infos = GenerateQuantifierInfos(node);
-
- Quantifier quan;
- if (node is ForallExpr)
- quan = Quantifier.ALL;
- else if (node is ExistsExpr)
- quan = Quantifier.EX;
- else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- return Gen.Quantify(quan, typeParams, boundVars, triggers, infos, body);
- } finally {
- PopBoundVariableScope();
- }
- }
-
- private List<VCTrigger/*!*/>/*!*/ TranslateTriggers(Trigger node) {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
- List<VCTrigger/*!*/>/*!*/ res = new List<VCTrigger/*!*/>();
- Trigger curTrigger = node;
- while (curTrigger != null) {
- res.Add(Gen.Trigger(curTrigger.Pos, Translate(curTrigger.Tr)));
- curTrigger = curTrigger.Next;
- }
- return res;
- }
-
- private VCQuantifierInfos GenerateQuantifierInfos(QuantifierExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCQuantifierInfos>() != null);
- string qid = getQidNameFromQKeyValue(node.Dummies, node.Attributes);
- return new VCQuantifierInfos(qid, node.SkolemId, false, node.Attributes);
- }
-
- private string getQidNameFromQKeyValue(List<Variable> vars, QKeyValue attributes) {
- Contract.Requires(vars != null);
- // Check for a 'qid, name' pair in keyvalues
- string qid = QKeyValue.FindStringAttribute(attributes, "qid");
- if (qid == null && vars.Count != 0) {
- // generate default name (line:column position in .bpl file)
- Variable v = vars[0];
- Contract.Assert(v != null); // Rustan's claim!
- // Include the first 8 characters of the filename in QID (helpful in case we use /concat)
- // We limit it to 8, so the SX file doesn't grow too big, and who on earth would need
- // more than 8 characters in a filename anyways.
- int max = 8;
- StringBuilder buf = new StringBuilder(max + 20);
- string filename = v.tok.filename;
- if (filename == null)
- filename = "unknown";
- for (int i = 0; i < filename.Length; ++i) {
- if (filename[i] == '/' || filename[i] == '\\')
- buf.Length = 0;
- if (buf.Length < max && char.IsLetterOrDigit(filename[i])) {
- if (buf.Length == 0 && char.IsDigit(filename[i])) {
- // Z3 does not like QID's to start with a digit, so we prepend another character
- buf.Append('_');
- }
- buf.Append(filename[i]);
- }
- }
- buf.Append('.').Append(v.Line).Append(':').Append(v.Col);
- qid = buf.ToString();
- }
- return qid;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitBvExtractExpr(BvExtractExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateBvExtractExpr(node));
- return node;
- }
-
- private VCExpr TranslateBvExtractExpr(BvExtractExpr node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Start <= node.End));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ bv = Translate(node.Bitvector);
- return Gen.BvExtract(bv, cce.NonNull(node.Bitvector.Type).BvBits, node.Start, node.End);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitBvConcatExpr(BvConcatExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateBvConcatExpr(node));
- return node;
- }
-
- private VCExpr TranslateBvConcatExpr(BvConcatExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ bv0 = Translate(node.E0);
- VCExpr/*!*/ bv1 = Translate(node.E1);
- return Gen.BvConcat(bv0, bv1);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
- // all the other cases should never happen
-
- public override Cmd VisitAssertCmd(AssertCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssignCmd(AssignCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssumeCmd(AssumeCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override AtomicRE VisitAtomicRE(AtomicRE node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AtomicRE>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Axiom VisitAxiom(Axiom node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Axiom>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitBasicType(BasicType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitBvType(BvType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Block VisitBlock(Block node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Block>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public CodeExprConverter codeExprConverter = null;
- public void SetCodeExprConverter(CodeExprConverter f) {
- this.codeExprConverter = f;
- }
- public override Expr/*!*/ VisitCodeExpr(CodeExpr/*!*/ codeExpr) {
- //Contract.Requires(codeExpr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Contract.Assume(codeExprConverter != null);
-
- Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
- List<VCExprLetBinding/*!*/> bindings = new List<VCExprLetBinding/*!*/>();
- VCExpr e = codeExprConverter(codeExpr, blockVariables, bindings, isPositiveContext);
- Push(e);
- return codeExpr;
- }
- public override List<Block> VisitBlockSeq(List<Block> blockSeq) {
- //Contract.Requires(blockSeq != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
- //Contract.Requires(cce.NonNullElements(blocks));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override BoundVariable VisitBoundVariable(BoundVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<BoundVariable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitCallCmd(CallCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitParCallCmd(ParCallCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
- //Contract.Requires(cmdSeq != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Choice VisitChoice(Choice node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Choice>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitCommentCmd(CommentCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Constant VisitConstant(Constant node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Constant>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override CtorType VisitCtorType(CtorType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<CtorType>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Declaration VisitDeclaration(Declaration node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Declaration>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
- //Contract.Requires(cce.NonNullElements(declarationList));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Declaration>>()));
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Requires VisitRequires(Requires @requires) {
- //Contract.Requires(@requires != null);
- Contract.Ensures(Contract.Result<Requires>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq) {
- //Contract.Requires(requiresSeq != null);
- Contract.Ensures(Contract.Result<List<Requires>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Ensures VisitEnsures(Ensures @ensures) {
- //Contract.Requires(@ensures != null);
- Contract.Ensures(Contract.Result<Ensures>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq) {
- //Contract.Requires(ensuresSeq != null);
- Contract.Ensures(Contract.Result<List<Ensures>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Formal VisitFormal(Formal node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Formal>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Function VisitFunction(Function node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override GlobalVariable VisitGlobalVariable(GlobalVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GlobalVariable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override GotoCmd VisitGotoCmd(GotoCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GotoCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitHavocCmd(HavocCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Implementation VisitImplementation(Implementation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override LocalVariable VisitLocalVariable(LocalVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<LocalVariable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override MapType VisitMapType(MapType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<MapType>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Procedure VisitProcedure(Procedure node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Procedure>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Program VisitProgram(Program node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Program>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitRE(RE node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<RE> VisitRESeq(List<RE> reSeq) {
- //Contract.Requires(reSeq != null);
- Contract.Ensures(Contract.Result<List<RE>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override ReturnCmd VisitReturnCmd(ReturnCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Sequential VisitSequential(Sequential node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Sequential>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitStateCmd(StateCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override TransferCmd VisitTransferCmd(TransferCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TransferCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Trigger VisitTrigger(Trigger node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Trigger>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitType(Type node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override TypedIdent VisitTypedIdent(TypedIdent node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TypedIdent>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitTypeVariable(TypeVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Variable VisitVariable(Variable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
- //Contract.Requires(variableSeq != null);
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- }
-
-
- /////////////////////////////////////////////////////////////////////////////////
-
- public class IAppliableTranslator : IAppliableVisitor<VCExpr/*!*/> {
-
- private readonly Boogie2VCExprTranslator/*!*/ BaseTranslator;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(BaseTranslator != null);
- }
-
-
- private VCExpressionGenerator/*!*/ Gen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
-
- return BaseTranslator.Gen;
- }
- }
- private VCGenerationOptions GenerationOptions {
- get {
- Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
-
- return BaseTranslator.GenerationOptions;
- }
- }
-
- public IAppliableTranslator(Boogie2VCExprTranslator baseTranslator) {
- Contract.Requires(baseTranslator != null);
- this.BaseTranslator = baseTranslator;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- private List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>();
- private List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarianet() {
- Contract.Invariant(args != null);
- Contract.Invariant(typeArgs != null);
- }
-
-
- public VCExpr Translate(IAppliable app, Type ty, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(ty != null);
- Contract.Requires(app != null);
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ oldArgs = this.args;
- List<Type/*!*/>/*!*/ oldTypeArgs = this.typeArgs;
- this.args = args;
- this.typeArgs = typeArgs;
- VCExpr/*!*/ result = app.Dispatch<VCExpr/*!*/>(this);
- this.args = oldArgs;
- this.typeArgs = oldTypeArgs;
- return result;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
-
-
- public VCExpr Visit(UnaryOperator unaryOperator) {
- //Contract.Requires(unaryOperator != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(unaryOperator.Op == UnaryOperator.Opcode.Neg || unaryOperator.Op == UnaryOperator.Opcode.Not);
- Contract.Assert(this.args.Count == 1);
- if (unaryOperator.Op == UnaryOperator.Opcode.Neg) {
- VCExpr e = cce.NonNull(this.args[0]);
- if (cce.NonNull(e.Type).IsInt) {
- return Gen.Function(VCExpressionGenerator.SubIOp, Gen.Integer(BigNum.ZERO), e);
- }
- else {// if (cce.NonNull(e.Type).IsReal) {
- return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), e);
- }
- //else {//is float
- //return Gen.Function(VCExpressionGenerator.SubFOp, Gen.Float(BigFloat.ZERO(8, 23)), e);
- //}
- }
- else {
- return Gen.Not(this.args);
- }
- }
-
- public VCExpr Visit(BinaryOperator binaryOperator) {
- //Contract.Requires(binaryOperator != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return TranslateBinaryOperator(binaryOperator, this.args);
- }
-
- public VCExpr Visit(FunctionCall functionCall) {
- //Contract.Requires(functionCall != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return TranslateFunctionCall(functionCall, this.args, this.typeArgs);
- }
-
- public VCExpr Visit(MapSelect mapSelect) {
- //Contract.Requires(mapSelect != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Select(this.args, this.typeArgs);
- }
-
- public VCExpr Visit(MapStore mapStore) {
- //Contract.Requires(mapStore != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Store(this.args, this.typeArgs);
- }
-
- public VCExpr Visit(TypeCoercion typeCoercion) {
- //Contract.Requires(typeCoercion != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(this.args.Count == 1);
- return this.args[0];
- }
-
- public VCExpr Visit(ArithmeticCoercion arithCoercion) {
- //Contract.Requires(arithCoercion != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(this.args.Count == 1);
- switch (arithCoercion.Coercion) {
- case ArithmeticCoercion.CoercionType.ToInt:
- return Gen.Function(VCExpressionGenerator.ToIntOp, this.args);
- case ArithmeticCoercion.CoercionType.ToReal:
- return Gen.Function(VCExpressionGenerator.ToRealOp, this.args);
- default:
- Contract.Assert(false);
- return null;
- }
- }
-
- public VCExpr Visit(IfThenElse ite) {
- //Contract.Requires(ite != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Function(VCExpressionGenerator.IfThenElseOp, this.args);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- private VCExpr TranslateBinaryOperator(BinaryOperator app, List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(app != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(args.Count == 2);
- Type t = cce.NonNull(cce.NonNull(args[0]).Type);
-
- switch (app.Op) {
- case BinaryOperator.Opcode.Add:
- if (t.IsInt) {
- return Gen.Function(VCExpressionGenerator.AddIOp, args);
- }
- else if (t.IsReal) {
- return Gen.Function(VCExpressionGenerator.AddROp, args);
- }
- else { //t is float
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "+"), args);
- }
- case BinaryOperator.Opcode.Sub:
- if (t.IsInt) {
- return Gen.Function(VCExpressionGenerator.SubIOp, args);
- }
- else if (t.IsReal) {
- return Gen.Function(VCExpressionGenerator.SubROp, args);
- }
- else { //t is float
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "-"), args);
- }
- case BinaryOperator.Opcode.Mul:
- if (t.IsInt) {
- return Gen.Function(VCExpressionGenerator.MulIOp, args);
- }
- else if (t.IsReal) {
- return Gen.Function(VCExpressionGenerator.MulROp, args);
- }
- else
- { //t is float
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "*"), args);
- }
- case BinaryOperator.Opcode.Div:
- return Gen.Function(VCExpressionGenerator.DivIOp, args);
- case BinaryOperator.Opcode.Mod:
- return Gen.Function(VCExpressionGenerator.ModOp, args);
- case BinaryOperator.Opcode.RealDiv:
- if (t.IsFloat) {
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "/"), args);
- }
- VCExpr arg0 = cce.NonNull(args[0]);
- VCExpr arg1 = cce.NonNull(args[1]);
- if (cce.NonNull(arg0.Type).IsInt) {
- arg0 = Gen.Function(VCExpressionGenerator.ToRealOp, arg0);
- }
- if (cce.NonNull(arg1.Type).IsInt) {
- arg1 = Gen.Function(VCExpressionGenerator.ToRealOp, arg1);
- }
- return Gen.Function(VCExpressionGenerator.DivROp, arg0, arg1);
- case BinaryOperator.Opcode.Pow:
- return Gen.Function(VCExpressionGenerator.PowOp, args);
- case BinaryOperator.Opcode.Eq:
- case BinaryOperator.Opcode.Iff:
- // we don't distinguish between equality and equivalence at this point
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "=="), args);
- return Gen.Function(VCExpressionGenerator.EqOp, args);
- case BinaryOperator.Opcode.Neq:
- return Gen.Function(VCExpressionGenerator.NeqOp, args);
- case BinaryOperator.Opcode.Lt:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<"), args);
- return Gen.Function(VCExpressionGenerator.LtOp, args);
- case BinaryOperator.Opcode.Le:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<="), args);
- return Gen.Function(VCExpressionGenerator.LeOp, args);
- case BinaryOperator.Opcode.Ge:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">="), args);
- return Gen.Function(VCExpressionGenerator.GeOp, args);
- case BinaryOperator.Opcode.Gt:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">"), args);
- return Gen.Function(VCExpressionGenerator.GtOp, args);
- case BinaryOperator.Opcode.Imp:
- return Gen.Function(VCExpressionGenerator.ImpliesOp, args);
- case BinaryOperator.Opcode.And:
- return Gen.Function(VCExpressionGenerator.AndOp, args);
- case BinaryOperator.Opcode.Or:
- return Gen.Function(VCExpressionGenerator.OrOp, args);
- case BinaryOperator.Opcode.Subtype:
- return Gen.Function(VCExpressionGenerator.SubtypeOp, args);
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException(); // unexpected binary operator
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- private VCExpr/*!*/ TranslateFunctionCall(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(app != null);
- Contract.Requires((app.Func != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null); // resolution must have happened
-
- VCExpr res = ApplyExpansion(app, args, typeArgs);
- if (res != null)
- return res;
-
- VCExprOp/*!*/ functionOp = Gen.BoogieFunctionOp(app.Func);
- return Gen.Function(functionOp, args, typeArgs);
- }
-
- private VCExpr ApplyExpansion(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(app != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Assert(app.Func != null); // resolution must have happened
-
- lock (app.Func)
- {
- if (app.Func.doingExpansion)
- {
- System.Console.WriteLine("*** detected expansion loop on {0}", app.Func);
- return null;
- }
-
- var exp = app.Func.Body;
- if (exp == null)
- return null;
-
- VCExpr/*!*/ translatedBody;
- VCExprSubstitution/*!*/ subst = new VCExprSubstitution();
- try
- {
- BaseTranslator.PushFormalsScope();
- BaseTranslator.PushBoundVariableScope();
- app.Func.doingExpansion = true;
-
- // first bind the formals to VCExpr variables, which are later
- // substituted with the actual parameters
- var inParams = app.Func.InParams;
- for (int i = 0; i < inParams.Count; ++i)
- subst[BaseTranslator.BindVariable(inParams[i])] = args[i];
-
- // recursively translate the body of the expansion
- translatedBody = BaseTranslator.Translate(exp);
- }
- finally
- {
- BaseTranslator.PopFormalsScope();
- BaseTranslator.PopBoundVariableScope();
- app.Func.doingExpansion = false;
- }
-
- // substitute the formals with the actual parameters in the body
- var tparms = app.Func.TypeParameters;
- Contract.Assert(typeArgs.Count == tparms.Count);
- for (int i = 0; i < typeArgs.Count; ++i)
- subst[tparms[i]] = typeArgs[i];
- SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
- return substituter.Mutate(translatedBody, subst);
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// A translator from the Boogie AST to the VCExpr AST.
+// This was previously realised in the methods AbsyExpr.VCView
+
+namespace Microsoft.Boogie.VCExprAST {
+ using Microsoft.Boogie;
+
+ // TODO: in future we might use that for defining symbols for Boogie's conditional compilation
+ public class VCGenerationOptions {
+ private readonly List<string/*!*/>/*!*/ SupportedProverCommands;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(SupportedProverCommands));
+ }
+
+
+ public bool IsProverCommandSupported(string kind) {
+ Contract.Requires(kind != null);
+ return SupportedProverCommands.Contains(kind);
+ }
+
+ public bool IsAnyProverCommandSupported(string kinds) {
+ Contract.Requires(kinds != null);
+ if (kinds.IndexOf(',') < 0) {
+ return IsProverCommandSupported(kinds);
+ } else {
+ return kinds.Split(',', ' ').Any(k => IsProverCommandSupported(k));
+ }
+ }
+
+ public VCGenerationOptions(List<string/*!*/>/*!*/ supportedProverCommands) {
+ Contract.Requires(cce.NonNullElements(supportedProverCommands));
+ this.SupportedProverCommands = supportedProverCommands;
+ }
+ }
+
+ public delegate VCExpr/*!*/ CodeExprConverter(CodeExpr/*!*/ codeExpr, Hashtable/*<Block, VCExprVar!>*//*!*/ blockVariables, List<VCExprLetBinding> bindings, bool isPositiveContext);
+
+ public class Boogie2VCExprTranslator : ReadOnlyVisitor, ICloneable {
+ // Stack on which the various Visit-methods put the result of the translation
+ private readonly Stack<VCExpr/*!*/>/*!*/ SubExpressions = new Stack<VCExpr>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(SubExpressions));
+ Contract.Invariant(Gen != null);
+ }
+
+
+ private void Push(VCExpr expr) {
+ Contract.Requires(expr != null);
+ SubExpressions.Push(expr);
+ }
+
+ private VCExpr Pop() {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return SubExpressions.Pop();
+ }
+
+ public VCExpr Translate(Expr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ this.Visit(expr);
+ return Pop();
+ }
+
+ public List<VCExpr/*!*/>/*!*/ Translate(IList<Expr> exprs) {
+ Contract.Requires(exprs != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ foreach (Expr e in exprs)
+ res.Add(Translate(cce.NonNull(e)));
+ return res;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ internal readonly VCExpressionGenerator/*!*/ Gen;
+
+ public Boogie2VCExprTranslator(VCExpressionGenerator gen,
+ VCGenerationOptions genOptions) {
+ Contract.Requires(gen != null);
+ Contract.Requires(genOptions != null);
+ this.Gen = gen;
+ this.GenerationOptions = genOptions;
+ UnboundVariables = new VariableMapping<Variable>();
+ BoundVariables = new VariableMapping<BoundVariable>();
+ Formals = new VariableMapping<Formal>();
+ }
+
+ private Boogie2VCExprTranslator(Boogie2VCExprTranslator tl) {
+ Contract.Requires(tl != null);
+ this.Gen = tl.Gen;
+ this.GenerationOptions = tl.GenerationOptions;
+ UnboundVariables =
+ (VariableMapping<Variable>)tl.UnboundVariables.Clone();
+ BoundVariables = new VariableMapping<BoundVariable>();
+ Formals = new VariableMapping<Formal>();
+ }
+
+ public object Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+ return new Boogie2VCExprTranslator(this);
+ }
+
+ private IAppliableTranslator IAppTranslatorAttr = null;
+ private IAppliableTranslator IAppTranslator {
+ get {
+ Contract.Ensures(Contract.Result<IAppliableTranslator>() != null);
+
+ if (IAppTranslatorAttr == null)
+ IAppTranslatorAttr = new IAppliableTranslator(this);
+ return IAppTranslatorAttr;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Class for handling occurring variables
+
+ private class VariableMapping<VarKind> : ICloneable {
+ private readonly List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ Mapping;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Mapping != null && Contract.ForAll(Mapping, i => cce.NonNullDictionaryAndValues(i)));
+ }
+
+
+ public VariableMapping() {
+ List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping =
+ new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>();
+ mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>());
+ this.Mapping = mapping;
+ }
+
+ private VariableMapping(VariableMapping<VarKind> vm) {
+ Contract.Requires(vm != null);
+ List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping =
+ new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>();
+ foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in vm.Mapping) {
+ Contract.Assert(cce.NonNullDictionaryAndValues(d));
+ mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>(d));
+ }
+ this.Mapping = mapping;
+ }
+
+ public object Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+ return new VariableMapping<VarKind>(this);
+ }
+
+ public void PushScope() {
+ Mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>());
+ }
+
+ public void PopScope() {
+ Contract.Assume(Mapping.Count > 0);
+ Mapping.RemoveAt(Mapping.Count - 1);
+ }
+
+ public void Bind(VarKind boogieVar, VCExprVar/*!*/ vcExprVar) {
+ Contract.Requires(vcExprVar != null);
+ Contract.Requires(boogieVar != null);
+ Contract.Requires(!Contains(boogieVar));
+ Mapping[Mapping.Count - 1].Add(boogieVar, vcExprVar);
+ }
+
+ public VCExprVar Lookup(VarKind boogieVar) {
+ Contract.Requires(boogieVar != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res = LookupHelp(boogieVar);
+ Contract.Assume(res != null);
+ return res;
+ }
+
+ [Pure]
+ public bool Contains(VarKind boogieVar) {
+ Contract.Requires(boogieVar != null);
+ return LookupHelp(boogieVar) != null;
+ }
+
+ public bool TryGetValue(VarKind boogieVar, out VCExprVar res) {
+ Contract.Requires(boogieVar != null);
+ res = LookupHelp(boogieVar);
+ return res != null;
+ }
+
+ [Pure]
+ private VCExprVar LookupHelp(VarKind boogieVar) {
+ Contract.Requires(boogieVar != null);
+ VCExprVar res;
+ foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in Mapping) {
+ //Contract.Assert(cce.NonNullElements(d));
+ if (d.TryGetValue(boogieVar, out res)) {
+ Contract.Assert(res != null);
+ return res;
+ }
+ }
+ return null;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+
+ private readonly VariableMapping<Variable>/*!*/ UnboundVariables;
+ private readonly VariableMapping<BoundVariable>/*!*/ BoundVariables;
+ // used when translating the bodies of function expansions
+ private readonly VariableMapping<Formal>/*!*/ Formals;
+ [ContractInvariantMethod]
+ void ObjectInvairant() {
+ Contract.Invariant(UnboundVariables != null);
+ Contract.Invariant(BoundVariables != null);
+ Contract.Invariant(Formals != null);
+ }
+
+
+ internal void PushBoundVariableScope() {
+ BoundVariables.PushScope();
+ }
+ internal void PopBoundVariableScope() {
+ BoundVariables.PopScope();
+ }
+
+ internal void PushFormalsScope() {
+ Formals.PushScope();
+ }
+ internal void PopFormalsScope() {
+ Formals.PopScope();
+ }
+
+ public VCExprVar BindVariable(Variable boogieVar) {
+ Contract.Requires(boogieVar != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ if (boogieVar is BoundVariable) {
+ VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
+ BoundVariables.Bind((BoundVariable)boogieVar, newVar);
+ return newVar;
+ } else if (boogieVar is Formal) {
+ VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
+ Formals.Bind((Formal)boogieVar, newVar);
+ return newVar;
+ } else {
+ // only bound variables and formals are declared explicitly
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ public VCExprVar LookupVariable(Variable boogieVar) {
+ Contract.Requires(boogieVar != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+
+ BoundVariable bv = boogieVar as BoundVariable;
+ if (bv != null) {
+ return BoundVariables.Lookup(bv);
+ }
+ VCExprVar res;
+ Formal fml = boogieVar as Formal;
+ if (fml != null && Formals.TryGetValue(fml, out res))
+ return cce.NonNull(res);
+
+ // global variables, local variables, incarnations, etc. are
+ // bound the first time they occur
+ if (!UnboundVariables.TryGetValue(boogieVar, out res)) {
+ if (boogieVar is Constant)
+ res = new VCExprConstant(boogieVar.Name, boogieVar.TypedIdent.Type);
+ else
+ res = new VCExprVar(boogieVar.Name, boogieVar.TypedIdent.Type);
+ UnboundVariables.Bind(boogieVar, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ /// <summary>
+ /// Unlike LookupVariable, this method does not create a new variable mapping if none is
+ /// found. Instead, this method returns null in such cases. Also, this method does not
+ /// look for bound variables.
+ /// </summary>
+ /// <param name="boogieVar"></param>
+ /// <returns></returns>
+ public VCExprVar TryLookupVariable(Variable boogieVar) {
+ Contract.Requires(boogieVar != null);
+
+ VCExprVar res;
+ Formal fml = boogieVar as Formal;
+ if (fml != null && Formals.TryGetValue(fml, out res))
+ return cce.NonNull(res);
+
+ if (UnboundVariables.TryGetValue(boogieVar, out res)) {
+ return cce.NonNull(res);
+ }
+
+ return null; // not present
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ internal readonly VCGenerationOptions/*!*/ GenerationOptions;
+ [ContractInvariantMethod]
+ void ObjectInvarian() {
+ Contract.Invariant(GenerationOptions != null);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr VisitLiteralExpr(LiteralExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Push(TranslateLiteralExpr(node));
+ return node;
+ }
+ private VCExpr TranslateLiteralExpr(LiteralExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (node.Val is bool) {
+ bool b = (bool)node.Val;
+ if (b) {
+ return VCExpressionGenerator.True;
+ } else {
+ return VCExpressionGenerator.False;
+ }
+ } else if (node.Val is BigNum) {
+ return Gen.Integer(node.asBigNum);
+ } else if (node.Val is BigDec) {
+ return Gen.Real(node.asBigDec);
+ } else if (node.Val is BigFloat) {
+ return Gen.Float(node.asBigFloat);
+ }
+ else if (node.Val is BvConst) {
+ return Gen.Bitvector((BvConst)node.Val);
+ } else {
+ System.Diagnostics.Debug.Assert(false, "unknown kind of literal " + node.tok.ToString());
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Contract.Assume(node.Decl != null); // the expression has to be resolved
+ Push(LookupVariable(node.Decl));
+ return node;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ // Because of our scheme for numbering incarnations of variables, the pre-state
+ // value of a variable x is always just "x". (The first update to it in a method
+ // causes it to become "x0". So we just remove old expressions with a visitor
+ // before transforming it into a VCExpr.
+ public override Expr VisitOldExpr(OldExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr VisitNAryExpr(NAryExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Push(TranslateNAryExpr(node));
+ return node;
+ }
+
+ public bool isPositiveContext = true;
+ private VCExpr TranslateNAryExpr(NAryExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ bool flipContextForArg0 = false;
+ if (node.Fun is UnaryOperator)
+ {
+ UnaryOperator oper = (UnaryOperator)node.Fun;
+ if (oper.Op == UnaryOperator.Opcode.Not)
+ flipContextForArg0 = true;
+ }
+ else if (node.Fun is BinaryOperator)
+ {
+ BinaryOperator oper = (BinaryOperator)node.Fun;
+ if (oper.Op == BinaryOperator.Opcode.Imp)
+ flipContextForArg0 = true;
+ else if (oper.Op == BinaryOperator.Opcode.Iff) {
+ Expr one = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[0], node.Args[1] });
+ Expr two = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[1], node.Args[0] });
+ NAryExpr cmpd = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.And), new List<Expr> { one, two });
+ TypecheckingContext tc = new TypecheckingContext(null);
+ cmpd.Typecheck(tc);
+ return TranslateNAryExpr(cmpd);
+ }
+ }
+
+ int n = node.Args.Count;
+ List<VCExpr/*!*/>/*!*/ vcs = new List<VCExpr/*!*/>(n);
+
+ for (int i = 0; i < n; i++) {
+ if (i == 0 && flipContextForArg0)
+ isPositiveContext = !isPositiveContext;
+ vcs.Add(Translate(cce.NonNull(node.Args)[i]));
+ if (i == 0 && flipContextForArg0)
+ isPositiveContext = !isPositiveContext;
+ }
+
+ if (node.Type == null) {
+ System.Console.WriteLine("*** type is null for {0}", node);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ return IAppTranslator.Translate(node.Fun, node.Type, vcs,
+ ToList(cce.NonNull(node.TypeParameters)));
+ }
+
+
+ private static List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvirant() {
+ Contract.Invariant(EMPTY_TYPE_LIST != null);
+ }
+
+
+ private List<Type/*!*/>/*!*/ ToList(TypeParamInstantiation insts) {
+ Contract.Requires(insts != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ if (insts.FormalTypeParams.Count == 0)
+ return EMPTY_TYPE_LIST;
+
+ List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>();
+ foreach (TypeVariable/*!*/ var in insts.FormalTypeParams) {
+ Contract.Assert(var != null);
+ typeArgs.Add(insts[var]);
+ }
+ return typeArgs;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<QuantifierExpr>() != null);
+ Push(TranslateQuantifierExpr(node));
+ return node;
+ }
+
+ public override Expr VisitExistsExpr(ExistsExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node = (ExistsExpr)this.VisitQuantifierExpr(node);
+ return node;
+ }
+
+ public override Expr VisitForallExpr(ForallExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ node = (ForallExpr)this.VisitQuantifierExpr(node);
+ return node;
+ }
+
+ private VCExpr TranslateQuantifierExpr(QuantifierExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<TypeVariable/*!*/>/*!*/ typeParams = new List<TypeVariable/*!*/>();
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ typeParams.Add(v);
+ }
+
+ PushBoundVariableScope();
+
+ List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>();
+ foreach (Variable/*!*/ v in node.Dummies)
+ boundVars.Add(BindVariable(v));
+
+ try {
+ List<VCTrigger/*!*/>/*!*/ triggers = TranslateTriggers(node.Triggers);
+ VCExpr/*!*/ body = Translate(node.Body);
+ VCQuantifierInfos/*!*/ infos = GenerateQuantifierInfos(node);
+
+ Quantifier quan;
+ if (node is ForallExpr)
+ quan = Quantifier.ALL;
+ else if (node is ExistsExpr)
+ quan = Quantifier.EX;
+ else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ return Gen.Quantify(quan, typeParams, boundVars, triggers, infos, body);
+ } finally {
+ PopBoundVariableScope();
+ }
+ }
+
+ private List<VCTrigger/*!*/>/*!*/ TranslateTriggers(Trigger node) {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
+ List<VCTrigger/*!*/>/*!*/ res = new List<VCTrigger/*!*/>();
+ Trigger curTrigger = node;
+ while (curTrigger != null) {
+ res.Add(Gen.Trigger(curTrigger.Pos, Translate(curTrigger.Tr)));
+ curTrigger = curTrigger.Next;
+ }
+ return res;
+ }
+
+ private VCQuantifierInfos GenerateQuantifierInfos(QuantifierExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCQuantifierInfos>() != null);
+ string qid = getQidNameFromQKeyValue(node.Dummies, node.Attributes);
+ return new VCQuantifierInfos(qid, node.SkolemId, false, node.Attributes);
+ }
+
+ private string getQidNameFromQKeyValue(List<Variable> vars, QKeyValue attributes) {
+ Contract.Requires(vars != null);
+ // Check for a 'qid, name' pair in keyvalues
+ string qid = QKeyValue.FindStringAttribute(attributes, "qid");
+ if (qid == null && vars.Count != 0) {
+ // generate default name (line:column position in .bpl file)
+ Variable v = vars[0];
+ Contract.Assert(v != null); // Rustan's claim!
+ // Include the first 8 characters of the filename in QID (helpful in case we use /concat)
+ // We limit it to 8, so the SX file doesn't grow too big, and who on earth would need
+ // more than 8 characters in a filename anyways.
+ int max = 8;
+ StringBuilder buf = new StringBuilder(max + 20);
+ string filename = v.tok.filename;
+ if (filename == null)
+ filename = "unknown";
+ for (int i = 0; i < filename.Length; ++i) {
+ if (filename[i] == '/' || filename[i] == '\\')
+ buf.Length = 0;
+ if (buf.Length < max && char.IsLetterOrDigit(filename[i])) {
+ if (buf.Length == 0 && char.IsDigit(filename[i])) {
+ // Z3 does not like QID's to start with a digit, so we prepend another character
+ buf.Append('_');
+ }
+ buf.Append(filename[i]);
+ }
+ }
+ buf.Append('.').Append(v.Line).Append(':').Append(v.Col);
+ qid = buf.ToString();
+ }
+ return qid;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr VisitBvExtractExpr(BvExtractExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Push(TranslateBvExtractExpr(node));
+ return node;
+ }
+
+ private VCExpr TranslateBvExtractExpr(BvExtractExpr node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Start <= node.End));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ bv = Translate(node.Bitvector);
+ return Gen.BvExtract(bv, cce.NonNull(node.Bitvector.Type).BvBits, node.Start, node.End);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public override Expr VisitBvConcatExpr(BvConcatExpr node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Push(TranslateBvConcatExpr(node));
+ return node;
+ }
+
+ private VCExpr TranslateBvConcatExpr(BvConcatExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ bv0 = Translate(node.E0);
+ VCExpr/*!*/ bv1 = Translate(node.E1);
+ return Gen.BvConcat(bv0, bv1);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ // all the other cases should never happen
+
+ public override Cmd VisitAssertCmd(AssertCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitAssignCmd(AssignCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitAssumeCmd(AssumeCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override AtomicRE VisitAtomicRE(AtomicRE node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AtomicRE>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Axiom VisitAxiom(Axiom node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Axiom>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Type VisitBasicType(BasicType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Type VisitBvType(BvType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Block VisitBlock(Block node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public CodeExprConverter codeExprConverter = null;
+ public void SetCodeExprConverter(CodeExprConverter f) {
+ this.codeExprConverter = f;
+ }
+ public override Expr/*!*/ VisitCodeExpr(CodeExpr/*!*/ codeExpr) {
+ //Contract.Requires(codeExpr != null);
+ Contract.Ensures(Contract.Result<Expr>() != null);
+ Contract.Assume(codeExprConverter != null);
+
+ Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
+ List<VCExprLetBinding/*!*/> bindings = new List<VCExprLetBinding/*!*/>();
+ VCExpr e = codeExprConverter(codeExpr, blockVariables, bindings, isPositiveContext);
+ Push(e);
+ return codeExpr;
+ }
+ public override List<Block> VisitBlockSeq(List<Block> blockSeq) {
+ //Contract.Requires(blockSeq != null);
+ Contract.Ensures(Contract.Result<List<Block>>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
+ //Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override BoundVariable VisitBoundVariable(BoundVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<BoundVariable>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitCallCmd(CallCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitParCallCmd(ParCallCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
+ //Contract.Requires(cmdSeq != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Choice VisitChoice(Choice node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Choice>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitCommentCmd(CommentCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Constant VisitConstant(Constant node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Constant>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override CtorType VisitCtorType(CtorType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Declaration VisitDeclaration(Declaration node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Declaration>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
+ //Contract.Requires(cce.NonNullElements(declarationList));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Declaration>>()));
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Requires VisitRequires(Requires @requires) {
+ //Contract.Requires(@requires != null);
+ Contract.Ensures(Contract.Result<Requires>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq) {
+ //Contract.Requires(requiresSeq != null);
+ Contract.Ensures(Contract.Result<List<Requires>>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Ensures VisitEnsures(Ensures @ensures) {
+ //Contract.Requires(@ensures != null);
+ Contract.Ensures(Contract.Result<Ensures>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq) {
+ //Contract.Requires(ensuresSeq != null);
+ Contract.Ensures(Contract.Result<List<Ensures>>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Formal VisitFormal(Formal node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Formal>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Function VisitFunction(Function node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override GlobalVariable VisitGlobalVariable(GlobalVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<GlobalVariable>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override GotoCmd VisitGotoCmd(GotoCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<GotoCmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitHavocCmd(HavocCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Implementation VisitImplementation(Implementation node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Implementation>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override LocalVariable VisitLocalVariable(LocalVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<LocalVariable>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override MapType VisitMapType(MapType node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<MapType>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Procedure VisitProcedure(Procedure node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Procedure>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Program VisitProgram(Program node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Program>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitRE(RE node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<RE> VisitRESeq(List<RE> reSeq) {
+ //Contract.Requires(reSeq != null);
+ Contract.Ensures(Contract.Result<List<RE>>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override ReturnCmd VisitReturnCmd(ReturnCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<ReturnCmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Sequential VisitSequential(Sequential node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Sequential>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<AssignLhs>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitStateCmd(StateCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override TransferCmd VisitTransferCmd(TransferCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<TransferCmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Trigger VisitTrigger(Trigger node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Trigger>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Type VisitType(Type node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override TypedIdent VisitTypedIdent(TypedIdent node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<TypedIdent>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Type VisitTypeVariable(TypeVariable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Variable VisitVariable(Variable node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Variable>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
+ //Contract.Requires(variableSeq != null);
+ Contract.Ensures(Contract.Result<List<Variable>>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Cmd>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ public class IAppliableTranslator : IAppliableVisitor<VCExpr/*!*/> {
+
+ private readonly Boogie2VCExprTranslator/*!*/ BaseTranslator;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(BaseTranslator != null);
+ }
+
+
+ private VCExpressionGenerator/*!*/ Gen {
+ get {
+ Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
+
+ return BaseTranslator.Gen;
+ }
+ }
+ private VCGenerationOptions GenerationOptions {
+ get {
+ Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
+
+ return BaseTranslator.GenerationOptions;
+ }
+ }
+
+ public IAppliableTranslator(Boogie2VCExprTranslator baseTranslator) {
+ Contract.Requires(baseTranslator != null);
+ this.BaseTranslator = baseTranslator;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ private List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>();
+ private List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarianet() {
+ Contract.Invariant(args != null);
+ Contract.Invariant(typeArgs != null);
+ }
+
+
+ public VCExpr Translate(IAppliable app, Type ty, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
+ Contract.Requires(ty != null);
+ Contract.Requires(app != null);
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ oldArgs = this.args;
+ List<Type/*!*/>/*!*/ oldTypeArgs = this.typeArgs;
+ this.args = args;
+ this.typeArgs = typeArgs;
+ VCExpr/*!*/ result = app.Dispatch<VCExpr/*!*/>(this);
+ this.args = oldArgs;
+ this.typeArgs = oldTypeArgs;
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+
+
+ public VCExpr Visit(UnaryOperator unaryOperator) {
+ //Contract.Requires(unaryOperator != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(unaryOperator.Op == UnaryOperator.Opcode.Neg || unaryOperator.Op == UnaryOperator.Opcode.Not);
+ Contract.Assert(this.args.Count == 1);
+ if (unaryOperator.Op == UnaryOperator.Opcode.Neg) {
+ VCExpr e = cce.NonNull(this.args[0]);
+ if (cce.NonNull(e.Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.SubIOp, Gen.Integer(BigNum.ZERO), e);
+ }
+ else {// if (cce.NonNull(e.Type).IsReal) {
+ return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), e);
+ }
+ //else {//is float
+ //return Gen.Function(VCExpressionGenerator.SubFOp, Gen.Float(BigFloat.ZERO(8, 23)), e);
+ //}
+ }
+ else {
+ return Gen.Not(this.args);
+ }
+ }
+
+ public VCExpr Visit(BinaryOperator binaryOperator) {
+ //Contract.Requires(binaryOperator != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return TranslateBinaryOperator(binaryOperator, this.args);
+ }
+
+ public VCExpr Visit(FunctionCall functionCall) {
+ //Contract.Requires(functionCall != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return TranslateFunctionCall(functionCall, this.args, this.typeArgs);
+ }
+
+ public VCExpr Visit(MapSelect mapSelect) {
+ //Contract.Requires(mapSelect != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Select(this.args, this.typeArgs);
+ }
+
+ public VCExpr Visit(MapStore mapStore) {
+ //Contract.Requires(mapStore != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Store(this.args, this.typeArgs);
+ }
+
+ public VCExpr Visit(TypeCoercion typeCoercion) {
+ //Contract.Requires(typeCoercion != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(this.args.Count == 1);
+ return this.args[0];
+ }
+
+ public VCExpr Visit(ArithmeticCoercion arithCoercion) {
+ //Contract.Requires(arithCoercion != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(this.args.Count == 1);
+ switch (arithCoercion.Coercion) {
+ case ArithmeticCoercion.CoercionType.ToInt:
+ return Gen.Function(VCExpressionGenerator.ToIntOp, this.args);
+ case ArithmeticCoercion.CoercionType.ToReal:
+ return Gen.Function(VCExpressionGenerator.ToRealOp, this.args);
+ default:
+ Contract.Assert(false);
+ return null;
+ }
+ }
+
+ public VCExpr Visit(IfThenElse ite) {
+ //Contract.Requires(ite != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Function(VCExpressionGenerator.IfThenElseOp, this.args);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr TranslateBinaryOperator(BinaryOperator app, List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(app != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(args.Count == 2);
+ Type t = cce.NonNull(cce.NonNull(args[0]).Type);
+
+ switch (app.Op) {
+ case BinaryOperator.Opcode.Add:
+ if (t.IsInt) {
+ return Gen.Function(VCExpressionGenerator.AddIOp, args);
+ }
+ else if (t.IsReal) {
+ return Gen.Function(VCExpressionGenerator.AddROp, args);
+ }
+ else { //t is float
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "+"), args);
+ }
+ case BinaryOperator.Opcode.Sub:
+ if (t.IsInt) {
+ return Gen.Function(VCExpressionGenerator.SubIOp, args);
+ }
+ else if (t.IsReal) {
+ return Gen.Function(VCExpressionGenerator.SubROp, args);
+ }
+ else { //t is float
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "-"), args);
+ }
+ case BinaryOperator.Opcode.Mul:
+ if (t.IsInt) {
+ return Gen.Function(VCExpressionGenerator.MulIOp, args);
+ }
+ else if (t.IsReal) {
+ return Gen.Function(VCExpressionGenerator.MulROp, args);
+ }
+ else
+ { //t is float
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "*"), args);
+ }
+ case BinaryOperator.Opcode.Div:
+ return Gen.Function(VCExpressionGenerator.DivIOp, args);
+ case BinaryOperator.Opcode.Mod:
+ return Gen.Function(VCExpressionGenerator.ModOp, args);
+ case BinaryOperator.Opcode.RealDiv:
+ if (t.IsFloat) {
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "/"), args);
+ }
+ VCExpr arg0 = cce.NonNull(args[0]);
+ VCExpr arg1 = cce.NonNull(args[1]);
+ if (cce.NonNull(arg0.Type).IsInt) {
+ arg0 = Gen.Function(VCExpressionGenerator.ToRealOp, arg0);
+ }
+ if (cce.NonNull(arg1.Type).IsInt) {
+ arg1 = Gen.Function(VCExpressionGenerator.ToRealOp, arg1);
+ }
+ return Gen.Function(VCExpressionGenerator.DivROp, arg0, arg1);
+ case BinaryOperator.Opcode.Pow:
+ return Gen.Function(VCExpressionGenerator.PowOp, args);
+ case BinaryOperator.Opcode.Eq:
+ case BinaryOperator.Opcode.Iff:
+ // we don't distinguish between equality and equivalence at this point
+ if (t.IsFloat)
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "=="), args);
+ return Gen.Function(VCExpressionGenerator.EqOp, args);
+ case BinaryOperator.Opcode.Neq:
+ return Gen.Function(VCExpressionGenerator.NeqOp, args);
+ case BinaryOperator.Opcode.Lt:
+ if (t.IsFloat)
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<"), args);
+ return Gen.Function(VCExpressionGenerator.LtOp, args);
+ case BinaryOperator.Opcode.Le:
+ if (t.IsFloat)
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<="), args);
+ return Gen.Function(VCExpressionGenerator.LeOp, args);
+ case BinaryOperator.Opcode.Ge:
+ if (t.IsFloat)
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">="), args);
+ return Gen.Function(VCExpressionGenerator.GeOp, args);
+ case BinaryOperator.Opcode.Gt:
+ if (t.IsFloat)
+ return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">"), args);
+ return Gen.Function(VCExpressionGenerator.GtOp, args);
+ case BinaryOperator.Opcode.Imp:
+ return Gen.Function(VCExpressionGenerator.ImpliesOp, args);
+ case BinaryOperator.Opcode.And:
+ return Gen.Function(VCExpressionGenerator.AndOp, args);
+ case BinaryOperator.Opcode.Or:
+ return Gen.Function(VCExpressionGenerator.OrOp, args);
+ case BinaryOperator.Opcode.Subtype:
+ return Gen.Function(VCExpressionGenerator.SubtypeOp, args);
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // unexpected binary operator
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr/*!*/ TranslateFunctionCall(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(app != null);
+ Contract.Requires((app.Func != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null); // resolution must have happened
+
+ VCExpr res = ApplyExpansion(app, args, typeArgs);
+ if (res != null)
+ return res;
+
+ VCExprOp/*!*/ functionOp = Gen.BoogieFunctionOp(app.Func);
+ return Gen.Function(functionOp, args, typeArgs);
+ }
+
+ private VCExpr ApplyExpansion(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
+ Contract.Requires(app != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Assert(app.Func != null); // resolution must have happened
+
+ lock (app.Func)
+ {
+ if (app.Func.doingExpansion)
+ {
+ System.Console.WriteLine("*** detected expansion loop on {0}", app.Func);
+ return null;
+ }
+
+ var exp = app.Func.Body;
+ if (exp == null)
+ return null;
+
+ VCExpr/*!*/ translatedBody;
+ VCExprSubstitution/*!*/ subst = new VCExprSubstitution();
+ try
+ {
+ BaseTranslator.PushFormalsScope();
+ BaseTranslator.PushBoundVariableScope();
+ app.Func.doingExpansion = true;
+
+ // first bind the formals to VCExpr variables, which are later
+ // substituted with the actual parameters
+ var inParams = app.Func.InParams;
+ for (int i = 0; i < inParams.Count; ++i)
+ subst[BaseTranslator.BindVariable(inParams[i])] = args[i];
+
+ // recursively translate the body of the expansion
+ translatedBody = BaseTranslator.Translate(exp);
+ }
+ finally
+ {
+ BaseTranslator.PopFormalsScope();
+ BaseTranslator.PopBoundVariableScope();
+ app.Func.doingExpansion = false;
+ }
+
+ // substitute the formals with the actual parameters in the body
+ var tparms = app.Func.TypeParameters;
+ Contract.Assert(typeArgs.Count == tparms.Count);
+ for (int i = 0; i < typeArgs.Count; ++i)
+ subst[tparms[i]] = typeArgs[i];
+ SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
+ return substituter.Mutate(translatedBody, subst);
+ }
+ }
+ }
+}
diff --git a/Source/VCExpr/Clustering.cs b/Source/VCExpr/Clustering.cs
index 1ab10107..a799aaae 100644
--- a/Source/VCExpr/Clustering.cs
+++ b/Source/VCExpr/Clustering.cs
@@ -1,522 +1,522 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Code for managing and clusterings sets of terms; this is used to
-// compress the input given to the theorem prover
-
-namespace Microsoft.Boogie.Clustering {
- using Microsoft.Boogie.VCExprAST;
-
-
- public class SubtermCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
-
- private readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
- Contract.Invariant(cce.NonNullDictionaryAndValues(SubtermClusters));
- }
-
-
- public SubtermCollector(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Gen = gen;
- }
-
- // variables that are global and treated like constants
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/> GlobalVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
-
- private readonly IDictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/> SubtermClusters =
- new Dictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/>();
-
- public void UnifyClusters() {
- foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
- in SubtermClusters) {
- Contract.Assert(cce.NonNullElements(pair));
- pair.Value.UnifyClusters();
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return false; // by default, do not collect terms containing node
- }
-
- public override bool Visit(VCExprLiteral node, bool arg) {
- Contract.Requires(node != null);
- return true;
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
- if (op == null) {
- base.Visit(node, arg);
- return false;
- }
-
- bool res = true;
- foreach (VCExpr subexpr in node) {
- Contract.Assert(subexpr != null);
- res &= this.Traverse(subexpr, arg);
- }
-
- if (res) {
- TermClustersSameHead clusters;
- if (!SubtermClusters.TryGetValue(op, out clusters)) {
- clusters = new TermClustersSameHead(op, GlobalVariables, Gen);
- SubtermClusters.Add(op, clusters);
- }
- cce.NonNull(clusters).AddExpr(node);
- }
-
- return res;
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node))
- GlobalVariables[node] = node;
- return true;
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- string/*!*/ res = "";
- foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
- in SubtermClusters) {
- Contract.Assert(cce.NonNullElements(pair));
- res = res + pair.Value + "\n";
- }
- return res;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // Class for managing and clustering a set of terms that all start
- // with the same function symbol
- internal class TermClustersSameHead {
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
- }
- // variables that are global and treated like constants
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
- public readonly VCExprOp/*!*/ Op;
- private readonly VCExpressionGenerator/*!*/ Gen;
-
- public TermClustersSameHead(VCExprOp op, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator/*!*/ gen) {
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- Contract.Requires(gen != null);
- Contract.Requires(op != null);
- Op = op;
- GlobalVariables = globalVars;
- Gen = gen;
- }
-
- private readonly List<Cluster>/*!*/ Clusters = new List<Cluster>();
-
- private struct Cluster {
- public readonly VCExprNAry/*!*/ Generator;
- public readonly int Size;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Generator != null);
- }
-
- public Cluster(VCExprNAry generator, int size) {
- Contract.Requires(generator != null);
- Generator = generator;
- Size = size;
- }
- }
-
- private int Distance(Cluster a, Cluster b) {
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
- visitor.AntiUnify(a.Generator, b.Generator);
-
- int reprSizeA, reprSizeB;
- visitor.RepresentationSize(GlobalVariables, out reprSizeA, out reprSizeB);
- return (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
- }
-
- private bool EqualUpToRenaming(Cluster a, Cluster b) {
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
- visitor.AntiUnify(a.Generator, b.Generator);
- return visitor.RepresentationIsRenaming(GlobalVariables);
- }
-
- private Cluster Merge(Cluster a, Cluster b) {
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
- VCExpr/*!*/ generator = visitor.AntiUnify(a.Generator, b.Generator);
- Contract.Assert(generator != null);
- VCExprNAry generatorNAry = generator as VCExprNAry;
- Contract.Assert(generatorNAry != null && Op.Equals(generatorNAry.Op));
- return new Cluster(generatorNAry, a.Size + b.Size);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void AddExpr(VCExprNAry expr) {
- Contract.Requires(expr != null);
- Contract.Requires(Op.Equals(expr.Op));
-
- Cluster c = new Cluster(expr, 1);
- for (int i = 0; i < Clusters.Count; ++i) {
- Cluster d = Clusters[i];
- if (EqualUpToRenaming(c, d)) {
- Clusters[i] = new Cluster(d.Generator, d.Size + 1);
- return;
- }
- }
-
- Clusters.Add(c);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private struct ClusteringMatrix {
-
- private readonly VCExpressionGenerator/*!*/ Gen;
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
-
- public readonly List<Cluster>/*!*/ Clusters;
- public readonly bool[]/*!*/ RemainingClusters;
-
- public readonly Distance[,]/*!*/ Distances;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
- Contract.Invariant(Clusters != null);
- Contract.Invariant(RemainingClusters != null);
- Contract.Invariant(Distances != null);
- }
-
-
- public struct Distance {
- public readonly int Dist;
- public readonly VCExprNAry/*!*/ Generator;
-
- public Distance(Cluster a, Cluster b, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(gen);
- Generator = (VCExprNAry)visitor.AntiUnify(a.Generator, b.Generator);
-
- int reprSizeA, reprSizeB;
- visitor.RepresentationSize(globalVars, out reprSizeA, out reprSizeB);
- Dist = (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
- }
- }
-
- public ClusteringMatrix(List<Cluster> clusters, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(clusters != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- List<Cluster> c = new List<Cluster>();
- c.AddRange(clusters);
- Clusters = c;
-
- GlobalVariables = globalVars;
- Gen = gen;
-
- bool[] remaining = new bool[clusters.Count];
- RemainingClusters = remaining;
- for (int i = 0; i < remaining.Length; ++i)
- remaining[i] = true;
-
- Distance[,]/*!*/ distances = new Distance[clusters.Count, clusters.Count];
- Distances = distances;
- for (int i = 1; i < clusters.Count; ++i)
- for (int j = 0; j < i; ++j)
- distances[i, j] =
- new Distance(clusters[i], clusters[j], GlobalVariables, Gen);
- }
-
- public void UnifyClusters(int maxDist) {
- while (true) {
- int i, j;
- int minDist = FindMinDistance(out i, out j);
-
- if (minDist > maxDist)
- return;
-
- MergeClusters(i, j);
- }
- }
-
- public void ResultingClusters(List<Cluster> clusters) {
- Contract.Requires(clusters != null);
- clusters.Clear();
- for (int i = 0; i < Clusters.Count; ++i)
- if (RemainingClusters[i])
- clusters.Add(Clusters[i]);
- }
-
- //////////////////////////////////////////////////////////////////////////
-
- private void Update(int i) {
- for (int j = 0; j < i; ++j) {
- if (RemainingClusters[j])
- Distances[i, j] =
- new Distance(Clusters[i], Clusters[j], GlobalVariables, Gen);
- }
- for (int j = i + 1; j < Clusters.Count; ++j) {
- if (RemainingClusters[j])
- Distances[j, i] =
- new Distance(Clusters[j], Clusters[i], GlobalVariables, Gen);
- }
- }
-
- private int FindMinDistance(out int c0, out int c1) {
- int minDist = int.MaxValue;
- c0 = -1;
- c1 = -1;
-
- for (int i = 0; i < Clusters.Count; ++i)
- if (RemainingClusters[i]) {
- for (int j = 0; j < i; ++j)
- if (RemainingClusters[j]) {
- if (Distances[i, j].Dist < minDist) {
- minDist = Distances[i, j].Dist;
- c0 = i;
- c1 = j;
- }
- }
- }
-
- Contract.Assert(c0 == -1 && c1 == -1 || c0 > c1 && c1 >= 0);
- return minDist;
- }
-
- private void MergeClusters(int i, int j) {
- Contract.Requires(j >= 0 && i > j && RemainingClusters[i] && RemainingClusters[j]);
- Clusters[i] = new Cluster(Distances[i, j].Generator,
- Clusters[i].Size + Clusters[j].Size);
- RemainingClusters[j] = false;
- Update(i);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void UnifyClusters() {
- ClusteringMatrix matrix =
- new ClusteringMatrix(Clusters, GlobalVariables, Gen);
- matrix.UnifyClusters(50);
- matrix.ResultingClusters(Clusters);
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- string/*!*/ res = "";
- foreach (Cluster c in Clusters)
- res = res + c.Generator + "\t" + c.Size + "\n";
- return res;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal class AntiUnificationVisitor : TraversingVCExprVisitor<VCExpr/*!*/, VCExpr/*!*/> {
-
- private readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(Representation));
- }
-
-
- public AntiUnificationVisitor(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Gen = gen;
- }
-
- // Sub-expressions in the first and second expression to be
- // anti-unified that are replaced with variables
- private readonly IDictionary<ExprPair, VCExprVar/*!*/>/*!*/ Representation =
- new Dictionary<ExprPair, VCExprVar/*!*/>();
-
-
-
- private struct ExprPair {
- public readonly VCExpr/*!*/ Expr0, Expr1;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Expr0 != null);
- Contract.Invariant(Expr1 != null);
- }
-
- public ExprPair(VCExpr expr0, VCExpr expr1) {
- Contract.Requires(expr1 != null);
- Contract.Requires(expr0 != null);
- Expr0 = expr0;
- Expr1 = expr1;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (that is ExprPair) {
- ExprPair thatPair = (ExprPair)that;
- return this.Expr0.Equals(thatPair.Expr0) &&
- this.Expr1.Equals(thatPair.Expr1);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Expr0.GetHashCode() + Expr1.GetHashCode() * 13;
- }
- }
-
- public void Reset() {
- Representation.Clear();
- }
-
- public bool RepresentationIsRenaming(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- if (!Representation.Any(pair => pair.Key.Expr0 is VCExprVar && pair.Key.Expr1 is VCExprVar && !globalVars.ContainsKey(cce.NonNull((VCExprVar)pair.Key.Expr0)) && !globalVars.ContainsKey(cce.NonNull((VCExprVar/*!*/)pair.Key.Expr1))))
- return false;
- // check that all substituted variables are distinct
- // TODO: optimise
- return
- Representation.All(pair1 => Representation.All(pair2 => pair1.Value.Equals(pair2.Value) || !pair1.Key.Expr0.Equals(pair2.Key.Expr0) && !pair1.Key.Expr1.Equals(pair2.Key.Expr1)));
- }
-
- public void RepresentationSize(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, out int expr0Size, out int expr1Size) {
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- ReprSizeComputingVisitor/*!*/ size0Visitor = new ReprSizeComputingVisitor();
- ReprSizeComputingVisitor/*!*/ size1Visitor = new ReprSizeComputingVisitor();
-
- foreach (KeyValuePair<ExprPair, VCExprVar/*!*/> pair in Representation) {
- Contract.Assert(pair.Value != null);
- size0Visitor.ComputeSize(pair.Key.Expr0, globalVars);
- size1Visitor.ComputeSize(pair.Key.Expr1, globalVars);
- }
-
- expr0Size = size0Visitor.Size;
- expr1Size = size1Visitor.Size;
- }
-
- public VCExpr AntiUnify(VCExpr s, VCExpr t) {
- Contract.Requires(t != null);
- Contract.Requires(s != null);
- Contract.Requires((s.Type.Equals(t.Type)));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Traverse(s, t);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private VCExprVar AbstractWithVariable(VCExpr s, VCExpr t) {
- Contract.Requires(t != null);
- Contract.Requires(s != null);
- Contract.Requires((s.Type.Equals(t.Type)));
-Contract.Ensures(Contract.Result<VCExprVar>() != null);
-
- ExprPair pair = new ExprPair(s, t);
- VCExprVar repr;
- if (!Representation.TryGetValue(pair, out repr)) {
- repr = Gen.Variable("abs" + Representation.Count, s.Type);
- Representation.Add(pair, repr);
- }
- return cce.NonNull(repr);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLiteral node, VCExpr that) {
- Contract.Requires(that != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (node.Equals(that))
- return node;
- return AbstractWithVariable(node, that);
- }
-
- public override VCExpr Visit(VCExprNAry node, VCExpr that) {
- Contract.Requires(that != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprNAry thatNAry = that as VCExprNAry;
- if (thatNAry != null && node.Op.Equals(thatNAry.Op)) {
- // type parameters should already have been eliminated at this
- // stage
- Contract.Assert(node.TypeParamArity == 0 && thatNAry.TypeParamArity == 0 && node.Arity == thatNAry.Arity);
-
- List<VCExpr/*!*/>/*!*/ unifiedArgs = new List<VCExpr/*!*/>();
- for (int i = 0; i < node.Arity; ++i)
- unifiedArgs.Add(Traverse(node[i], thatNAry[i]));
-
- return Gen.Function(node.Op, unifiedArgs);
- }
- return AbstractWithVariable(node, that);
- }
-
- public override VCExpr Visit(VCExprVar node, VCExpr that) {
- Contract.Requires(that != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (node.Equals(that))
- return node;
- return AbstractWithVariable(node, that);
- }
-
- protected override VCExpr StandardResult(VCExpr node, VCExpr that) {
- //Contract.Requires(that != null);
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException(); // not handled here
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal class ReprSizeComputingVisitor
- : TraversingVCExprVisitor<bool,
- // variables considered as global constants
- IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/> {
-
- public int Size = 0;
-
- public void ComputeSize(VCExpr expr, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
- Contract.Requires(expr != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- Traverse(expr, globalVars);
- }
-
- protected override bool StandardResult(VCExpr node, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
- //Contract.Requires(node != null);
- //Contract.Requires(cce.NonNullElements(globalVars));
- VCExprVar nodeAsVar = node as VCExprVar;
- if (nodeAsVar == null || globalVars.ContainsKey(nodeAsVar))
- Size = Size + 1;
- return true;
- }
- }
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Code for managing and clusterings sets of terms; this is used to
+// compress the input given to the theorem prover
+
+namespace Microsoft.Boogie.Clustering {
+ using Microsoft.Boogie.VCExprAST;
+
+
+ public class SubtermCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+
+ private readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(SubtermClusters));
+ }
+
+
+ public SubtermCollector(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Gen = gen;
+ }
+
+ // variables that are global and treated like constants
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/> GlobalVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
+
+ private readonly IDictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/> SubtermClusters =
+ new Dictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/>();
+
+ public void UnifyClusters() {
+ foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
+ in SubtermClusters) {
+ Contract.Assert(cce.NonNullElements(pair));
+ pair.Value.UnifyClusters();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return false; // by default, do not collect terms containing node
+ }
+
+ public override bool Visit(VCExprLiteral node, bool arg) {
+ Contract.Requires(node != null);
+ return true;
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+ VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
+ if (op == null) {
+ base.Visit(node, arg);
+ return false;
+ }
+
+ bool res = true;
+ foreach (VCExpr subexpr in node) {
+ Contract.Assert(subexpr != null);
+ res &= this.Traverse(subexpr, arg);
+ }
+
+ if (res) {
+ TermClustersSameHead clusters;
+ if (!SubtermClusters.TryGetValue(op, out clusters)) {
+ clusters = new TermClustersSameHead(op, GlobalVariables, Gen);
+ SubtermClusters.Add(op, clusters);
+ }
+ cce.NonNull(clusters).AddExpr(node);
+ }
+
+ return res;
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!BoundTermVars.Contains(node))
+ GlobalVariables[node] = node;
+ return true;
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string/*!*/ res = "";
+ foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
+ in SubtermClusters) {
+ Contract.Assert(cce.NonNullElements(pair));
+ res = res + pair.Value + "\n";
+ }
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Class for managing and clustering a set of terms that all start
+ // with the same function symbol
+ internal class TermClustersSameHead {
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
+ }
+ // variables that are global and treated like constants
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
+ public readonly VCExprOp/*!*/ Op;
+ private readonly VCExpressionGenerator/*!*/ Gen;
+
+ public TermClustersSameHead(VCExprOp op, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator/*!*/ gen) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ Contract.Requires(gen != null);
+ Contract.Requires(op != null);
+ Op = op;
+ GlobalVariables = globalVars;
+ Gen = gen;
+ }
+
+ private readonly List<Cluster>/*!*/ Clusters = new List<Cluster>();
+
+ private struct Cluster {
+ public readonly VCExprNAry/*!*/ Generator;
+ public readonly int Size;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Generator != null);
+ }
+
+ public Cluster(VCExprNAry generator, int size) {
+ Contract.Requires(generator != null);
+ Generator = generator;
+ Size = size;
+ }
+ }
+
+ private int Distance(Cluster a, Cluster b) {
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
+ visitor.AntiUnify(a.Generator, b.Generator);
+
+ int reprSizeA, reprSizeB;
+ visitor.RepresentationSize(GlobalVariables, out reprSizeA, out reprSizeB);
+ return (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
+ }
+
+ private bool EqualUpToRenaming(Cluster a, Cluster b) {
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
+ visitor.AntiUnify(a.Generator, b.Generator);
+ return visitor.RepresentationIsRenaming(GlobalVariables);
+ }
+
+ private Cluster Merge(Cluster a, Cluster b) {
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
+ VCExpr/*!*/ generator = visitor.AntiUnify(a.Generator, b.Generator);
+ Contract.Assert(generator != null);
+ VCExprNAry generatorNAry = generator as VCExprNAry;
+ Contract.Assert(generatorNAry != null && Op.Equals(generatorNAry.Op));
+ return new Cluster(generatorNAry, a.Size + b.Size);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void AddExpr(VCExprNAry expr) {
+ Contract.Requires(expr != null);
+ Contract.Requires(Op.Equals(expr.Op));
+
+ Cluster c = new Cluster(expr, 1);
+ for (int i = 0; i < Clusters.Count; ++i) {
+ Cluster d = Clusters[i];
+ if (EqualUpToRenaming(c, d)) {
+ Clusters[i] = new Cluster(d.Generator, d.Size + 1);
+ return;
+ }
+ }
+
+ Clusters.Add(c);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private struct ClusteringMatrix {
+
+ private readonly VCExpressionGenerator/*!*/ Gen;
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
+
+ public readonly List<Cluster>/*!*/ Clusters;
+ public readonly bool[]/*!*/ RemainingClusters;
+
+ public readonly Distance[,]/*!*/ Distances;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
+ Contract.Invariant(Clusters != null);
+ Contract.Invariant(RemainingClusters != null);
+ Contract.Invariant(Distances != null);
+ }
+
+
+ public struct Distance {
+ public readonly int Dist;
+ public readonly VCExprNAry/*!*/ Generator;
+
+ public Distance(Cluster a, Cluster b, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(gen);
+ Generator = (VCExprNAry)visitor.AntiUnify(a.Generator, b.Generator);
+
+ int reprSizeA, reprSizeB;
+ visitor.RepresentationSize(globalVars, out reprSizeA, out reprSizeB);
+ Dist = (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
+ }
+ }
+
+ public ClusteringMatrix(List<Cluster> clusters, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(clusters != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ List<Cluster> c = new List<Cluster>();
+ c.AddRange(clusters);
+ Clusters = c;
+
+ GlobalVariables = globalVars;
+ Gen = gen;
+
+ bool[] remaining = new bool[clusters.Count];
+ RemainingClusters = remaining;
+ for (int i = 0; i < remaining.Length; ++i)
+ remaining[i] = true;
+
+ Distance[,]/*!*/ distances = new Distance[clusters.Count, clusters.Count];
+ Distances = distances;
+ for (int i = 1; i < clusters.Count; ++i)
+ for (int j = 0; j < i; ++j)
+ distances[i, j] =
+ new Distance(clusters[i], clusters[j], GlobalVariables, Gen);
+ }
+
+ public void UnifyClusters(int maxDist) {
+ while (true) {
+ int i, j;
+ int minDist = FindMinDistance(out i, out j);
+
+ if (minDist > maxDist)
+ return;
+
+ MergeClusters(i, j);
+ }
+ }
+
+ public void ResultingClusters(List<Cluster> clusters) {
+ Contract.Requires(clusters != null);
+ clusters.Clear();
+ for (int i = 0; i < Clusters.Count; ++i)
+ if (RemainingClusters[i])
+ clusters.Add(Clusters[i]);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+
+ private void Update(int i) {
+ for (int j = 0; j < i; ++j) {
+ if (RemainingClusters[j])
+ Distances[i, j] =
+ new Distance(Clusters[i], Clusters[j], GlobalVariables, Gen);
+ }
+ for (int j = i + 1; j < Clusters.Count; ++j) {
+ if (RemainingClusters[j])
+ Distances[j, i] =
+ new Distance(Clusters[j], Clusters[i], GlobalVariables, Gen);
+ }
+ }
+
+ private int FindMinDistance(out int c0, out int c1) {
+ int minDist = int.MaxValue;
+ c0 = -1;
+ c1 = -1;
+
+ for (int i = 0; i < Clusters.Count; ++i)
+ if (RemainingClusters[i]) {
+ for (int j = 0; j < i; ++j)
+ if (RemainingClusters[j]) {
+ if (Distances[i, j].Dist < minDist) {
+ minDist = Distances[i, j].Dist;
+ c0 = i;
+ c1 = j;
+ }
+ }
+ }
+
+ Contract.Assert(c0 == -1 && c1 == -1 || c0 > c1 && c1 >= 0);
+ return minDist;
+ }
+
+ private void MergeClusters(int i, int j) {
+ Contract.Requires(j >= 0 && i > j && RemainingClusters[i] && RemainingClusters[j]);
+ Clusters[i] = new Cluster(Distances[i, j].Generator,
+ Clusters[i].Size + Clusters[j].Size);
+ RemainingClusters[j] = false;
+ Update(i);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void UnifyClusters() {
+ ClusteringMatrix matrix =
+ new ClusteringMatrix(Clusters, GlobalVariables, Gen);
+ matrix.UnifyClusters(50);
+ matrix.ResultingClusters(Clusters);
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string/*!*/ res = "";
+ foreach (Cluster c in Clusters)
+ res = res + c.Generator + "\t" + c.Size + "\n";
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class AntiUnificationVisitor : TraversingVCExprVisitor<VCExpr/*!*/, VCExpr/*!*/> {
+
+ private readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Representation));
+ }
+
+
+ public AntiUnificationVisitor(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Gen = gen;
+ }
+
+ // Sub-expressions in the first and second expression to be
+ // anti-unified that are replaced with variables
+ private readonly IDictionary<ExprPair, VCExprVar/*!*/>/*!*/ Representation =
+ new Dictionary<ExprPair, VCExprVar/*!*/>();
+
+
+
+ private struct ExprPair {
+ public readonly VCExpr/*!*/ Expr0, Expr1;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Expr0 != null);
+ Contract.Invariant(Expr1 != null);
+ }
+
+ public ExprPair(VCExpr expr0, VCExpr expr1) {
+ Contract.Requires(expr1 != null);
+ Contract.Requires(expr0 != null);
+ Expr0 = expr0;
+ Expr1 = expr1;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is ExprPair) {
+ ExprPair thatPair = (ExprPair)that;
+ return this.Expr0.Equals(thatPair.Expr0) &&
+ this.Expr1.Equals(thatPair.Expr1);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Expr0.GetHashCode() + Expr1.GetHashCode() * 13;
+ }
+ }
+
+ public void Reset() {
+ Representation.Clear();
+ }
+
+ public bool RepresentationIsRenaming(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ if (!Representation.Any(pair => pair.Key.Expr0 is VCExprVar && pair.Key.Expr1 is VCExprVar && !globalVars.ContainsKey(cce.NonNull((VCExprVar)pair.Key.Expr0)) && !globalVars.ContainsKey(cce.NonNull((VCExprVar/*!*/)pair.Key.Expr1))))
+ return false;
+ // check that all substituted variables are distinct
+ // TODO: optimise
+ return
+ Representation.All(pair1 => Representation.All(pair2 => pair1.Value.Equals(pair2.Value) || !pair1.Key.Expr0.Equals(pair2.Key.Expr0) && !pair1.Key.Expr1.Equals(pair2.Key.Expr1)));
+ }
+
+ public void RepresentationSize(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, out int expr0Size, out int expr1Size) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ ReprSizeComputingVisitor/*!*/ size0Visitor = new ReprSizeComputingVisitor();
+ ReprSizeComputingVisitor/*!*/ size1Visitor = new ReprSizeComputingVisitor();
+
+ foreach (KeyValuePair<ExprPair, VCExprVar/*!*/> pair in Representation) {
+ Contract.Assert(pair.Value != null);
+ size0Visitor.ComputeSize(pair.Key.Expr0, globalVars);
+ size1Visitor.ComputeSize(pair.Key.Expr1, globalVars);
+ }
+
+ expr0Size = size0Visitor.Size;
+ expr1Size = size1Visitor.Size;
+ }
+
+ public VCExpr AntiUnify(VCExpr s, VCExpr t) {
+ Contract.Requires(t != null);
+ Contract.Requires(s != null);
+ Contract.Requires((s.Type.Equals(t.Type)));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Traverse(s, t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private VCExprVar AbstractWithVariable(VCExpr s, VCExpr t) {
+ Contract.Requires(t != null);
+ Contract.Requires(s != null);
+ Contract.Requires((s.Type.Equals(t.Type)));
+Contract.Ensures(Contract.Result<VCExprVar>() != null);
+
+ ExprPair pair = new ExprPair(s, t);
+ VCExprVar repr;
+ if (!Representation.TryGetValue(pair, out repr)) {
+ repr = Gen.Variable("abs" + Representation.Count, s.Type);
+ Representation.Add(pair, repr);
+ }
+ return cce.NonNull(repr);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLiteral node, VCExpr that) {
+ Contract.Requires(that != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (node.Equals(that))
+ return node;
+ return AbstractWithVariable(node, that);
+ }
+
+ public override VCExpr Visit(VCExprNAry node, VCExpr that) {
+ Contract.Requires(that != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprNAry thatNAry = that as VCExprNAry;
+ if (thatNAry != null && node.Op.Equals(thatNAry.Op)) {
+ // type parameters should already have been eliminated at this
+ // stage
+ Contract.Assert(node.TypeParamArity == 0 && thatNAry.TypeParamArity == 0 && node.Arity == thatNAry.Arity);
+
+ List<VCExpr/*!*/>/*!*/ unifiedArgs = new List<VCExpr/*!*/>();
+ for (int i = 0; i < node.Arity; ++i)
+ unifiedArgs.Add(Traverse(node[i], thatNAry[i]));
+
+ return Gen.Function(node.Op, unifiedArgs);
+ }
+ return AbstractWithVariable(node, that);
+ }
+
+ public override VCExpr Visit(VCExprVar node, VCExpr that) {
+ Contract.Requires(that != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (node.Equals(that))
+ return node;
+ return AbstractWithVariable(node, that);
+ }
+
+ protected override VCExpr StandardResult(VCExpr node, VCExpr that) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // not handled here
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class ReprSizeComputingVisitor
+ : TraversingVCExprVisitor<bool,
+ // variables considered as global constants
+ IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/> {
+
+ public int Size = 0;
+
+ public void ComputeSize(VCExpr expr, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
+ Contract.Requires(expr != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ Traverse(expr, globalVars);
+ }
+
+ protected override bool StandardResult(VCExpr node, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(cce.NonNullElements(globalVars));
+ VCExprVar nodeAsVar = node as VCExprVar;
+ if (nodeAsVar == null || globalVars.ContainsKey(nodeAsVar))
+ Size = Size + 1;
+ return true;
+ }
+ }
} \ No newline at end of file
diff --git a/Source/VCExpr/LetBindingSorter.cs b/Source/VCExpr/LetBindingSorter.cs
index 474770d0..2bf28fbb 100644
--- a/Source/VCExpr/LetBindingSorter.cs
+++ b/Source/VCExpr/LetBindingSorter.cs
@@ -1,161 +1,161 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Sort the bindings in a let-expression so that terms bound earlier do
-// not contain variables bound later
-
-namespace Microsoft.Boogie.VCExprAST {
-
- // (argument is not used)
- public class LetBindingSorter : MutatingVCExprVisitor<bool> {
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FreeVarCollector != null);
- }
-
- private readonly FreeVariableCollector/*!*/ FreeVarCollector =
- new FreeVariableCollector();
-
- private List<VCExprVar/*!*/>/*!*/ FreeVarsIn(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- FreeVarCollector.Collect(expr);
- List<VCExprVar/*!*/>/*!*/ freeVars = new List<VCExprVar/*!*/>(FreeVarCollector.FreeTermVars.Keys);
- FreeVarCollector.Reset();
- return freeVars;
- }
-
- public LetBindingSorter(VCExpressionGenerator gen):base(gen) {
- Contract.Requires(gen != null);
-
- }
-
- public override VCExpr Visit(VCExprLet node, bool arg){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- IDictionary<VCExprVar/*!*/, Binding/*!*/> boundVars =
- new Dictionary<VCExprVar/*!*/, Binding/*!*/> ();
-
- // recurse and collect the free variables in bound terms and formulae
- foreach (VCExprLetBinding/*!*/ binding in node) {Contract.Assert(binding != null);
- VCExpr/*!*/ newE = Mutate(binding.E, arg);
- Binding/*!*/ b = new Binding (binding.V, newE, FreeVarsIn(newE));
- boundVars.Add(b.V, b);
- }
-
- // generate the occurrence edges
- foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars) {Contract.Assert(cce.NonNullElements(pair));
- Binding/*!*/ b = pair.Value;
- Contract.Assert(b != null);
- foreach (VCExprVar/*!*/ v in b.FreeVars) {Contract.Assert(v != null);
- Binding b2;
- if (boundVars.TryGetValue(v, out b2)) {
- cce.NonNull(b2).Occurrences.Add(b);
- b.InvOccurrencesNum = b.InvOccurrencesNum + 1;
- }
- }
- }
-
- // topological sort
- Stack<Binding/*!*/> rootBindings = new Stack<Binding/*!*/> ();
- foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars)
- {Contract.Assert(cce.NonNullElements(pair));
- if (pair.Value.InvOccurrencesNum == 0)
- rootBindings.Push(pair.Value);}
-
- List<Binding/*!*/>/*!*/ sortedBindings = new List<Binding/*!*/> ();
- while (rootBindings.Count > 0) {
- Binding/*!*/ b = rootBindings.Pop();
- Contract.Assert(b != null);
- sortedBindings.Add(b);
- foreach (Binding/*!*/ b2 in b.Occurrences) {
- Contract.Assert(b2 != null);
- b2.InvOccurrencesNum = b2.InvOccurrencesNum - 1;
- if (b2.InvOccurrencesNum == 0)
- rootBindings.Push(b2);
- }
- }
-
- if (boundVars.Any(pair=> pair.Value.InvOccurrencesNum > 0))
- System.Diagnostics.Debug.Fail("Cyclic let-bindings");
-
- Contract.Assert(node.Length == sortedBindings.Count);
-
- // check which of the bindings can be dropped
- VCExpr newBody = Mutate(node.Body, arg);
- Contract.Assert(newBody != null);
-
- IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ usedVars =
- new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/> ();
- foreach (VCExprVar/*!*/ v in FreeVarsIn(newBody)){Contract.Assert(v != null);
- if (!usedVars.ContainsKey(v))
- usedVars.Add(v, v);}
-
- for (int i = sortedBindings.Count - 1; i >= 0; --i) {
- if (usedVars.ContainsKey(sortedBindings[i].V)) {
- foreach (VCExprVar/*!*/ v in sortedBindings[i].FreeVars){
- Contract.Assert(v != null);
- if (!usedVars.ContainsKey(v))
- usedVars.Add(v, v);}
- } else {
- sortedBindings.RemoveAt(i);
- }
- }
-
- // assemble the resulting let-expression
- List<VCExprLetBinding/*!*/>/*!*/ newBindings = new List<VCExprLetBinding/*!*/>();
- foreach (Binding b in sortedBindings)
- newBindings.Add(Gen.LetBinding(b.V, b.E));
-
- return Gen.Let(newBindings, newBody);
- }
-
- private class Binding {
- public readonly VCExprVar/*!*/ V;
- public readonly VCExpr/*!*/ E;
- public readonly List<VCExprVar/*!*/>/*!*/ FreeVars;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(V != null);
- Contract.Invariant(E != null);
- Contract.Invariant(cce.NonNullElements(FreeVars));
- Contract.Invariant(Occurrences != null);
- }
-
-
- // list of all bound expression in which the variable V occurs
- // (outgoing edges)
- public readonly List<Binding>/*!*/ Occurrences;
-
- // number of variables that are bound in this let-expression
- // and that occur in FreeVars
- // (incoming edges)
- public int InvOccurrencesNum;
-
- public Binding(VCExprVar v, VCExpr e, List<VCExprVar/*!*/>/*!*/ freeVars) {
- Contract.Requires(e != null);
- Contract.Requires(v != null);
- Contract.Requires(cce.NonNullElements(freeVars));
- this.V = v;
- this.E = e;
- this.FreeVars = freeVars;
- this.Occurrences = new List<Binding>();
- this.InvOccurrencesNum = 0;
- }
- }
-
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Sort the bindings in a let-expression so that terms bound earlier do
+// not contain variables bound later
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ // (argument is not used)
+ public class LetBindingSorter : MutatingVCExprVisitor<bool> {
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FreeVarCollector != null);
+ }
+
+ private readonly FreeVariableCollector/*!*/ FreeVarCollector =
+ new FreeVariableCollector();
+
+ private List<VCExprVar/*!*/>/*!*/ FreeVarsIn(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ FreeVarCollector.Collect(expr);
+ List<VCExprVar/*!*/>/*!*/ freeVars = new List<VCExprVar/*!*/>(FreeVarCollector.FreeTermVars.Keys);
+ FreeVarCollector.Reset();
+ return freeVars;
+ }
+
+ public LetBindingSorter(VCExpressionGenerator gen):base(gen) {
+ Contract.Requires(gen != null);
+
+ }
+
+ public override VCExpr Visit(VCExprLet node, bool arg){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ IDictionary<VCExprVar/*!*/, Binding/*!*/> boundVars =
+ new Dictionary<VCExprVar/*!*/, Binding/*!*/> ();
+
+ // recurse and collect the free variables in bound terms and formulae
+ foreach (VCExprLetBinding/*!*/ binding in node) {Contract.Assert(binding != null);
+ VCExpr/*!*/ newE = Mutate(binding.E, arg);
+ Binding/*!*/ b = new Binding (binding.V, newE, FreeVarsIn(newE));
+ boundVars.Add(b.V, b);
+ }
+
+ // generate the occurrence edges
+ foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars) {Contract.Assert(cce.NonNullElements(pair));
+ Binding/*!*/ b = pair.Value;
+ Contract.Assert(b != null);
+ foreach (VCExprVar/*!*/ v in b.FreeVars) {Contract.Assert(v != null);
+ Binding b2;
+ if (boundVars.TryGetValue(v, out b2)) {
+ cce.NonNull(b2).Occurrences.Add(b);
+ b.InvOccurrencesNum = b.InvOccurrencesNum + 1;
+ }
+ }
+ }
+
+ // topological sort
+ Stack<Binding/*!*/> rootBindings = new Stack<Binding/*!*/> ();
+ foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars)
+ {Contract.Assert(cce.NonNullElements(pair));
+ if (pair.Value.InvOccurrencesNum == 0)
+ rootBindings.Push(pair.Value);}
+
+ List<Binding/*!*/>/*!*/ sortedBindings = new List<Binding/*!*/> ();
+ while (rootBindings.Count > 0) {
+ Binding/*!*/ b = rootBindings.Pop();
+ Contract.Assert(b != null);
+ sortedBindings.Add(b);
+ foreach (Binding/*!*/ b2 in b.Occurrences) {
+ Contract.Assert(b2 != null);
+ b2.InvOccurrencesNum = b2.InvOccurrencesNum - 1;
+ if (b2.InvOccurrencesNum == 0)
+ rootBindings.Push(b2);
+ }
+ }
+
+ if (boundVars.Any(pair=> pair.Value.InvOccurrencesNum > 0))
+ System.Diagnostics.Debug.Fail("Cyclic let-bindings");
+
+ Contract.Assert(node.Length == sortedBindings.Count);
+
+ // check which of the bindings can be dropped
+ VCExpr newBody = Mutate(node.Body, arg);
+ Contract.Assert(newBody != null);
+
+ IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ usedVars =
+ new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/> ();
+ foreach (VCExprVar/*!*/ v in FreeVarsIn(newBody)){Contract.Assert(v != null);
+ if (!usedVars.ContainsKey(v))
+ usedVars.Add(v, v);}
+
+ for (int i = sortedBindings.Count - 1; i >= 0; --i) {
+ if (usedVars.ContainsKey(sortedBindings[i].V)) {
+ foreach (VCExprVar/*!*/ v in sortedBindings[i].FreeVars){
+ Contract.Assert(v != null);
+ if (!usedVars.ContainsKey(v))
+ usedVars.Add(v, v);}
+ } else {
+ sortedBindings.RemoveAt(i);
+ }
+ }
+
+ // assemble the resulting let-expression
+ List<VCExprLetBinding/*!*/>/*!*/ newBindings = new List<VCExprLetBinding/*!*/>();
+ foreach (Binding b in sortedBindings)
+ newBindings.Add(Gen.LetBinding(b.V, b.E));
+
+ return Gen.Let(newBindings, newBody);
+ }
+
+ private class Binding {
+ public readonly VCExprVar/*!*/ V;
+ public readonly VCExpr/*!*/ E;
+ public readonly List<VCExprVar/*!*/>/*!*/ FreeVars;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(V != null);
+ Contract.Invariant(E != null);
+ Contract.Invariant(cce.NonNullElements(FreeVars));
+ Contract.Invariant(Occurrences != null);
+ }
+
+
+ // list of all bound expression in which the variable V occurs
+ // (outgoing edges)
+ public readonly List<Binding>/*!*/ Occurrences;
+
+ // number of variables that are bound in this let-expression
+ // and that occur in FreeVars
+ // (incoming edges)
+ public int InvOccurrencesNum;
+
+ public Binding(VCExprVar v, VCExpr e, List<VCExprVar/*!*/>/*!*/ freeVars) {
+ Contract.Requires(e != null);
+ Contract.Requires(v != null);
+ Contract.Requires(cce.NonNullElements(freeVars));
+ this.V = v;
+ this.E = e;
+ this.FreeVars = freeVars;
+ this.Occurrences = new List<Binding>();
+ this.InvOccurrencesNum = 0;
+ }
+ }
+
+ }
+
+}
diff --git a/Source/VCExpr/NameClashResolver.cs b/Source/VCExpr/NameClashResolver.cs
index a46105f8..0effb386 100644
--- a/Source/VCExpr/NameClashResolver.cs
+++ b/Source/VCExpr/NameClashResolver.cs
@@ -1,196 +1,196 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Visitor that establishes unique variable (or constant) names in a VCExpr.
-// This is done by adding a counter as suffix if name clashes occur
-
-// TODO: also handle type variables here
-
-namespace Microsoft.Boogie.VCExprAST {
- using TEHelperFuns = Microsoft.Boogie.TypeErasure.HelperFuns;
-
- public class UniqueNamer : ICloneable {
- public string Spacer = "@@";
-
- public UniqueNamer() {
- GlobalNames = new Dictionary<Object, string>();
- LocalNames = TEHelperFuns.ToList(new Dictionary<Object/*!*/, string/*!*/>()
- as IDictionary<Object/*!*/, string/*!*/>);
- UsedNames = new HashSet<string>();
- CurrentCounters = new Dictionary<string, int>();
- GlobalPlusLocalNames = new Dictionary<Object, string>();
- }
-
- private UniqueNamer(UniqueNamer namer) {
- Contract.Requires(namer != null);
-
- Spacer = namer.Spacer;
- GlobalNames = new Dictionary<Object, string>(namer.GlobalNames);
- LocalNames = new List<IDictionary<Object, string>>();
-
- foreach (IDictionary<Object/*!*/, string/*!*/>/*!*/ d in namer.LocalNames)
- LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>(d));
-
- UsedNames = new HashSet<string>(namer.UsedNames);
- CurrentCounters = new Dictionary<string, int>(namer.CurrentCounters);
- GlobalPlusLocalNames = new Dictionary<Object, string>(namer.GlobalPlusLocalNames);
- }
-
- public Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
- return new UniqueNamer(this);
- }
-
- public void Reset()
- {
- GlobalNames.Clear();
- LocalNames.Clear();
- LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
- UsedNames.Clear();
- CurrentCounters.Clear();
- GlobalPlusLocalNames.Clear();
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalNames;
- [ContractInvariantMethod]
- void GlobalNamesInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalNames));
- }
- private readonly List<IDictionary<Object/*!*/, string/*!*/>/*!*/>/*!*/ LocalNames;
- [ContractInvariantMethod]
- void LocalNamesInvariantMethod() {
- Contract.Invariant(Contract.ForAll(LocalNames, i => i != null && cce.NonNullDictionaryAndValues(i)));
- }
-
- // dictionary of all names that have already been used
- // (locally or globally)
- private readonly HashSet<string/*!*/>/*!*/ UsedNames;
- [ContractInvariantMethod]
- void UsedNamesInvariantMethod() {
- Contract.Invariant(cce.NonNull(UsedNames));
- }
- private readonly IDictionary<string/*!*/, int/*!*/>/*!*/ CurrentCounters;
- [ContractInvariantMethod]
- void CurrentCountersInvariantMethod() {
- Contract.Invariant(CurrentCounters != null);
- }
- private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalPlusLocalNames;
- [ContractInvariantMethod]
- void GlobalPlusLocalNamesInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalPlusLocalNames));
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void PushScope() {
- LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
- }
-
- public void PopScope() {
- LocalNames.RemoveAt(LocalNames.Count - 1);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private string NextFreeName(Object thingie, string baseName) {
- Contract.Requires(baseName != null);
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string/*!*/ candidate;
- int counter;
-
- if (CurrentCounters.TryGetValue(baseName, out counter)) {
- candidate = baseName + Spacer + counter;
- counter = counter + 1;
- } else {
- candidate = baseName;
- counter = 0;
- }
-
- while (UsedNames.Contains(candidate)) {
- candidate = baseName + Spacer + counter;
- counter = counter + 1;
- }
-
- UsedNames.Add(candidate);
- CurrentCounters[baseName] = counter;
- GlobalPlusLocalNames[thingie] = candidate;
- return candidate;
- }
-
- // retrieve the name of a thingie; if it does not have a name yet,
- // generate a unique name for it (as close as possible to its inherent
- // name) and register it globally
- public string GetName(Object thingie, string inherentName) {
- Contract.Requires(inherentName != null);
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string res = this[thingie];
-
- if (res != null)
- return res;
-
- // if the object is not yet registered, create a name for it
- res = NextFreeName(thingie, inherentName);
- GlobalNames.Add(thingie, res);
-
- return res;
- }
-
- [Pure]
- public string this[Object/*!*/ thingie] {
- get {
- Contract.Requires(thingie != null);
-
- string res;
- for (int i = LocalNames.Count - 1; i >= 0; --i) {
- if (LocalNames[i].TryGetValue(thingie, out res))
- return res;
- }
-
- GlobalNames.TryGetValue(thingie, out res);
- return res;
- }
- }
-
- public string GetLocalName(Object thingie, string inherentName) {
- Contract.Requires(inherentName != null);
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string res = NextFreeName(thingie, inherentName);
- LocalNames[LocalNames.Count - 1][thingie] = res;
- return res;
- }
-
- public virtual string GetQuotedName(Object thingie, string inherentName)
- {
- return GetName(thingie, inherentName);
- }
-
- public virtual string GetQuotedLocalName(Object thingie, string inherentName)
- {
- return GetLocalName(thingie, inherentName);
- }
-
- public string Lookup(Object thingie) {
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string name;
- if (GlobalPlusLocalNames.TryGetValue(thingie, out name))
- return name;
- return Spacer + "undefined" + Spacer + thingie.GetHashCode() + Spacer;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Visitor that establishes unique variable (or constant) names in a VCExpr.
+// This is done by adding a counter as suffix if name clashes occur
+
+// TODO: also handle type variables here
+
+namespace Microsoft.Boogie.VCExprAST {
+ using TEHelperFuns = Microsoft.Boogie.TypeErasure.HelperFuns;
+
+ public class UniqueNamer : ICloneable {
+ public string Spacer = "@@";
+
+ public UniqueNamer() {
+ GlobalNames = new Dictionary<Object, string>();
+ LocalNames = TEHelperFuns.ToList(new Dictionary<Object/*!*/, string/*!*/>()
+ as IDictionary<Object/*!*/, string/*!*/>);
+ UsedNames = new HashSet<string>();
+ CurrentCounters = new Dictionary<string, int>();
+ GlobalPlusLocalNames = new Dictionary<Object, string>();
+ }
+
+ private UniqueNamer(UniqueNamer namer) {
+ Contract.Requires(namer != null);
+
+ Spacer = namer.Spacer;
+ GlobalNames = new Dictionary<Object, string>(namer.GlobalNames);
+ LocalNames = new List<IDictionary<Object, string>>();
+
+ foreach (IDictionary<Object/*!*/, string/*!*/>/*!*/ d in namer.LocalNames)
+ LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>(d));
+
+ UsedNames = new HashSet<string>(namer.UsedNames);
+ CurrentCounters = new Dictionary<string, int>(namer.CurrentCounters);
+ GlobalPlusLocalNames = new Dictionary<Object, string>(namer.GlobalPlusLocalNames);
+ }
+
+ public Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ return new UniqueNamer(this);
+ }
+
+ public void Reset()
+ {
+ GlobalNames.Clear();
+ LocalNames.Clear();
+ LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
+ UsedNames.Clear();
+ CurrentCounters.Clear();
+ GlobalPlusLocalNames.Clear();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalNames;
+ [ContractInvariantMethod]
+ void GlobalNamesInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalNames));
+ }
+ private readonly List<IDictionary<Object/*!*/, string/*!*/>/*!*/>/*!*/ LocalNames;
+ [ContractInvariantMethod]
+ void LocalNamesInvariantMethod() {
+ Contract.Invariant(Contract.ForAll(LocalNames, i => i != null && cce.NonNullDictionaryAndValues(i)));
+ }
+
+ // dictionary of all names that have already been used
+ // (locally or globally)
+ private readonly HashSet<string/*!*/>/*!*/ UsedNames;
+ [ContractInvariantMethod]
+ void UsedNamesInvariantMethod() {
+ Contract.Invariant(cce.NonNull(UsedNames));
+ }
+ private readonly IDictionary<string/*!*/, int/*!*/>/*!*/ CurrentCounters;
+ [ContractInvariantMethod]
+ void CurrentCountersInvariantMethod() {
+ Contract.Invariant(CurrentCounters != null);
+ }
+ private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalPlusLocalNames;
+ [ContractInvariantMethod]
+ void GlobalPlusLocalNamesInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalPlusLocalNames));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void PushScope() {
+ LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
+ }
+
+ public void PopScope() {
+ LocalNames.RemoveAt(LocalNames.Count - 1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private string NextFreeName(Object thingie, string baseName) {
+ Contract.Requires(baseName != null);
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string/*!*/ candidate;
+ int counter;
+
+ if (CurrentCounters.TryGetValue(baseName, out counter)) {
+ candidate = baseName + Spacer + counter;
+ counter = counter + 1;
+ } else {
+ candidate = baseName;
+ counter = 0;
+ }
+
+ while (UsedNames.Contains(candidate)) {
+ candidate = baseName + Spacer + counter;
+ counter = counter + 1;
+ }
+
+ UsedNames.Add(candidate);
+ CurrentCounters[baseName] = counter;
+ GlobalPlusLocalNames[thingie] = candidate;
+ return candidate;
+ }
+
+ // retrieve the name of a thingie; if it does not have a name yet,
+ // generate a unique name for it (as close as possible to its inherent
+ // name) and register it globally
+ public string GetName(Object thingie, string inherentName) {
+ Contract.Requires(inherentName != null);
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string res = this[thingie];
+
+ if (res != null)
+ return res;
+
+ // if the object is not yet registered, create a name for it
+ res = NextFreeName(thingie, inherentName);
+ GlobalNames.Add(thingie, res);
+
+ return res;
+ }
+
+ [Pure]
+ public string this[Object/*!*/ thingie] {
+ get {
+ Contract.Requires(thingie != null);
+
+ string res;
+ for (int i = LocalNames.Count - 1; i >= 0; --i) {
+ if (LocalNames[i].TryGetValue(thingie, out res))
+ return res;
+ }
+
+ GlobalNames.TryGetValue(thingie, out res);
+ return res;
+ }
+ }
+
+ public string GetLocalName(Object thingie, string inherentName) {
+ Contract.Requires(inherentName != null);
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string res = NextFreeName(thingie, inherentName);
+ LocalNames[LocalNames.Count - 1][thingie] = res;
+ return res;
+ }
+
+ public virtual string GetQuotedName(Object thingie, string inherentName)
+ {
+ return GetName(thingie, inherentName);
+ }
+
+ public virtual string GetQuotedLocalName(Object thingie, string inherentName)
+ {
+ return GetLocalName(thingie, inherentName);
+ }
+
+ public string Lookup(Object thingie) {
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string name;
+ if (GlobalPlusLocalNames.TryGetValue(thingie, out name))
+ return name;
+ return Spacer + "undefined" + Spacer + thingie.GetHashCode() + Spacer;
+ }
+ }
+}
diff --git a/Source/VCExpr/SimplifyLikeLineariser.cs b/Source/VCExpr/SimplifyLikeLineariser.cs
index 6f74fe08..1a4374f8 100644
--- a/Source/VCExpr/SimplifyLikeLineariser.cs
+++ b/Source/VCExpr/SimplifyLikeLineariser.cs
@@ -1,1222 +1,1222 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// a naive method to turn VCExprs into strings that can be fed into Simplify
-
-namespace Microsoft.Boogie.VCExprAST {
- [ContractClassFor(typeof(LineariserOptions))]
- public abstract class LinOptContracts : LineariserOptions {
- public LinOptContracts()
- : base(true) {
- }
- public override LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- throw new NotImplementedException();
- }
-
- }
-
- // Options for the linearisation. Here one can choose, for instance,
- // whether Simplify or Z3 output is to be produced
- [ContractClass(typeof(LinOptContracts))]
- public abstract class LineariserOptions {
-
- public readonly bool AsTerm;
- public abstract LineariserOptions/*!*/ SetAsTerm(bool newVal);
-
- public abstract bool QuantifierIds {
- get;
- }
-
- public virtual bool UseWeights {
- get {
- return false;
- }
- }
-
- public virtual bool InverseImplies {
- get {
- return false;
- }
- }
-
- // whether to include type specifications in quantifiers
- public abstract bool UseTypes {
- get;
- }
-
- // variables representing formulas in let-bindings have to be
- // printed in a different way than other variables
- public virtual List<VCExprVar/*!*/>/*!*/ LetVariables {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- return EmptyList;
- }
- }
-
- public virtual LineariserOptions AddLetVariable(VCExprVar furtherVar) {
- Contract.Requires(furtherVar != null);
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- return this;
- }
-
- public virtual LineariserOptions AddLetVariables(List<VCExprVar/*!*/>/*!*/ furtherVars) {
- Contract.Requires(cce.NonNullElements(furtherVars));
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- return this;
- }
-
- private static readonly List<VCExprVar/*!*/>/*!*/ EmptyList = new List<VCExprVar/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarinat() {
- Contract.Invariant(EmptyList != null);
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- protected LineariserOptions(bool asTerm) {
- this.AsTerm = asTerm;
- }
-
- public static readonly LineariserOptions SimplifyDefault = new SimplifyOptions(false);
- internal static readonly LineariserOptions SimplifyDefaultTerm = new SimplifyOptions(true);
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- private class SimplifyOptions : LineariserOptions {
- internal SimplifyOptions(bool asTerm)
- : base(asTerm) {
-
- }
- public override bool QuantifierIds {
- get {
- return false;
- }
- }
- public override bool UseTypes {
- get {
- return false;
- }
- }
- public override LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- if (newVal)
- return SimplifyDefaultTerm;
- else
- return SimplifyDefault;
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for expressions. The result (bool) is currently not used for anything
- public class SimplifyLikeExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> {
-
- public static string ToSimplifyString(VCExpr e, UniqueNamer namer) {
- Contract.Requires(namer != null);
- Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return ToString(e, LineariserOptions.SimplifyDefault, namer);
- }
-
- public static string ToString(VCExpr/*!*/ e, LineariserOptions/*!*/ options, UniqueNamer/*!*/ namer) {
- Contract.Requires(e != null);
- Contract.Requires(options != null);
- Contract.Requires(namer != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- StringWriter sw = new StringWriter();
- SimplifyLikeExprLineariser lin = new SimplifyLikeExprLineariser(sw, namer);
- lin.Linearise(e, options);
- return sw.ToString();
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(wr != null);
- Contract.Invariant(Namer != null);
- }
-
- private readonly TextWriter/*!*/ wr;
- private SimplifyLikeOpLineariser OpLinObject = null;
- private IVCExprOpVisitor<bool, LineariserOptions/*!*/>/*!*/ OpLineariser {
- get {
- Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
- if (OpLinObject == null)
- OpLinObject = new SimplifyLikeOpLineariser(this, wr);
- return OpLinObject;
- }
- }
-
- internal readonly UniqueNamer Namer;
-
- public SimplifyLikeExprLineariser(TextWriter wr, UniqueNamer namer) {
- Contract.Requires(namer != null);
- Contract.Requires(wr != null);
- this.wr = wr;
- this.Namer = namer;
- }
-
- public void Linearise(VCExpr expr, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(expr != null);
- expr.Accept<bool, LineariserOptions>(this, options);
- }
-
- public void LineariseAsTerm(VCExpr expr, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(expr != null);
- Linearise(expr, options.SetAsTerm(true));
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public static string MakeIdPrintable(string s) {
- Contract.Requires(s != null);
- Contract.Requires(s != "");
- Contract.Ensures(Contract.Result<string>() != null);
- // make sure that no keywords are used as identifiers
- switch (s) {
- case andName:
- case orName:
- case notName:
- case impliesName:
- case iffName:
- case eqName:
- case neqName:
- case distinctName:
- case TRUEName:
- case FALSEName:
- s = "nonkeyword_" + s;
- break;
- }
-
- if (CommandLineOptions.Clo.BracketIdsInVC == 0) {
- // In this form, we go with any identifier, so we don't ever bother about brackets.
- // Except: @true and @false are always written with brackets
- return s;
- }
- bool looksLikeOperator = true;
- bool looksLikeSimpleId = true;
- bool useBrackets = false;
- foreach (char ch in s) {
- switch (ch) {
- case '=':
- case '<':
- case '>':
- case '+':
- case '-':
- case '*':
- case '/':
- case '%':
- case ':':
- // looks like operator, not simple id
- looksLikeSimpleId = false;
- break;
- default:
- if (Char.IsLetterOrDigit(ch)) {
- // looks like simple id, not operator
- looksLikeOperator = false;
- } else {
- // looks like neither operator nor simple id
- looksLikeOperator = false;
- looksLikeSimpleId = false;
- }
- break;
- }
- if (!looksLikeOperator && !looksLikeSimpleId) {
- useBrackets = true;
- break;
- }
- }
- if (useBrackets) {
- return "|" + s + "|";
- } else {
- return s;
- }
- }
-
- private static void TypeToStringHelper(Type t, StringBuilder sb) {
- Contract.Requires(t != null);
-
- TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
- if (syn != null) {
- TypeToStringHelper(syn.ExpandedType, sb);
- } else {
- if (t.IsMap) {
- MapType m = t.AsMap;
- sb.Append('[');
- for (int i = 0; i < m.MapArity; ++i) {
- if (i != 0)
- sb.Append(',');
- TypeToStringHelper(m.Arguments[i], sb);
- }
- sb.Append(']');
- TypeToStringHelper(m.Result, sb);
- } else if (t.IsBool || t.IsInt || t.IsBv) {
- sb.Append(TypeToString(t));
- } else {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
- t.Emit(stream);
- }
- sb.Append(buffer.ToString());
- }
- }
-
- }
-
-
- public static string TypeToString(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- if (t.IsBool)
- return "$bool";
- else if (t.IsInt)
- return "$int";
- else if (t.IsBv)
- return "$bv" + t.BvBits;
- else {
- StringBuilder sb = new StringBuilder();
- TypeToStringHelper(t, sb);
- return sb.ToString();
- }
- }
-
- public static string BvConcatOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Op is VCExprBvConcatOp));
- Contract.Ensures(Contract.Result<string>() != null);
- int bits1 = node[0].Type.BvBits;
- int bits2 = node[1].Type.BvBits;
- return "$bv" + (bits1 + bits2) + "_concat[" + bits1 + "." + bits2 + "]";
- }
-
- public static string BvExtractOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires(node.Op is VCExprBvExtractOp);
- Contract.Ensures(Contract.Result<string>() != null);
- VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
- return "$bv" + node.Type.BvBits + "_extract" + op.Total + "[" + op.Start + ":" + op.End + "]";
- }
-
- public static string StoreOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
- Contract.Ensures(Contract.Result<string>() != null);
- return "Store_" + TypeToString(node[0].Type);
- }
-
- public static string SelectOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
- Contract.Ensures(Contract.Result<string>() != null);
- return "Select_" + TypeToString(node[0].Type);
- }
-
- internal void WriteId(string s) {
- Contract.Requires(s != null);
- wr.Write(MakeIdPrintable(s));
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// The name for logical conjunction in Simplify
- /// </summary>
- internal const string andName = "AND"; // conjunction
- internal const string orName = "OR"; // disjunction
- internal const string notName = "NOT"; // negation
- internal const string impliesName = "IMPLIES"; // implication
- internal const string iffName = "IFF"; // logical equivalence
- internal const string eqName = "EQ"; // equality
- internal const string neqName = "NEQ"; // inequality
- internal const string lessName = "<";
- internal const string greaterName = ">";
- internal const string atmostName = "<=";
- internal const string atleastName = ">=";
- internal const string TRUEName = "TRUE"; // nullary predicate that is always true
- internal const string FALSEName = "FALSE"; // nullary predicate that is always false
- internal const string subtypeName = "<:";
- internal const string subtypeArgsName = "<::";
-
- internal const string distinctName = "DISTINCT";
- /// <summary>
- /// name of the main inclusion relation
- /// </summary>
- internal const string boolTrueName = "|@true|";
- internal const string boolFalseName = "|@false|";
- internal const string boolAndName = "boolAnd";
- internal const string boolOrName = "boolOr";
- internal const string boolNotName = "boolNot";
- internal const string termEqName = "anyEqual";
- internal const string termNeqName = "anyNeq";
- internal const string termLessName = "intLess";
- internal const string termGreaterName = "intGreater";
- internal const string termAtmostName = "intAtMost";
- internal const string termAtleastName = "intAtLeast";
- internal const string intAddName = "+";
- internal const string intAddNameReflect = "Reflect$Add";
- internal const string intSubName = "-";
- internal const string intMulName = "*";
- internal const string intDivName = "/";
- internal const string intModName = "%";
- internal const string realAddName = "realAdd";
- internal const string realSubName = "realSub";
- internal const string realMulName = "realMul";
- internal const string realDivName = "realDiv";
- internal const string floatAddName = "floatAdd";
- internal const string floatSubName = "floatSub";
- internal const string floatMulName = "floatMul";
- internal const string floatDivName = "floatDiv";
- internal const string floatRemName = "floatRem";
- internal const string floatMinName = "floatMin";
- internal const string floatMaxName = "floatMax";
- internal const string floatLeqName = "floatLeq";
- internal const string floatLtName = "floatLt";
- internal const string floatGeqName = "floatGeq";
- internal const string floatGtName = "floatGt";
- internal const string floatEqName = "floatEq";
- internal const string realPowName = "realPow";
- internal const string toIntName = "toIntCoercion";
- internal const string toRealName = "toRealCoercion";
- internal const string toFloatName = "toFloatCoercion";
-
- internal void AssertAsTerm(string x, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(x != null);
- if (!options.AsTerm)
- System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
- }
-
- internal void AssertAsFormula(string x, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(x != null);
- if (options.AsTerm)
- System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLiteral node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
-
- if (node == VCExpressionGenerator.True)
- wr.Write(options.UseTypes ? TRUEName : boolTrueName);
- else if (node == VCExpressionGenerator.False)
- wr.Write(options.UseTypes ? FALSEName : boolFalseName);
- else if (node is VCExprIntLit) {
- wr.Write(((VCExprIntLit)node).Val);
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- } else {
-
- if (node == VCExpressionGenerator.True)
- wr.Write(TRUEName);
- else if (node == VCExpressionGenerator.False)
- wr.Write(FALSEName);
- else if (node is VCExprIntLit) {
- System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- VCExprOp op = node.Op;
- Contract.Assert(op != null);
-
- if (!options.AsTerm &&
- (op.Equals(VCExpressionGenerator.AndOp) ||
- op.Equals(VCExpressionGenerator.OrOp))) {
- // handle these operators without recursion
-
- wr.Write("({0}",
- op.Equals(VCExpressionGenerator.AndOp) ? andName : orName);
- IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
- Contract.Assert(enumerator != null);
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(op)) {
- wr.Write(" ");
- Linearise(cce.NonNull((VCExpr)enumerator.Current), options);
- }
- }
-
- wr.Write(")");
-
- return true;
- }
-
- return node.Accept<bool, LineariserOptions>(OpLineariser, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprVar node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- string printedName = Namer.GetName(node, node.Name);
- Contract.Assert(printedName != null);
-
- if (options.AsTerm ||
- // variables for formulas bound in a let-binding are never
- // written as an equation
- options.LetVariables.Contains(node) ||
- // if variables are properly typed, they cannot be written as
- // equation either
- options.UseTypes) {
- WriteId(printedName);
- } else {
- wr.Write("({0} ", eqName);
- WriteId(printedName);
- wr.Write(" {0})", boolTrueName);
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprQuantifier node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- AssertAsFormula(node.Quan.ToString(), options);
- Contract.Assert(node.TypeParameters.Count == 0);
-
- Namer.PushScope();
- try {
-
- string kind = node.Quan == Quantifier.ALL ? "FORALL" : "EXISTS";
- wr.Write("({0} (", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++) {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var != null);
- string printedName = Namer.GetLocalName(var, var.Name);
- Contract.Assert(printedName != null);
- if (i != 0)
- wr.Write(" ");
- WriteId(printedName);
- if (options.UseTypes)
- wr.Write(" :TYPE {0}", TypeToString(var.Type));
- }
- wr.Write(") ");
-
- WriteTriggers(node.Triggers, options);
-
- if (options.QuantifierIds) {
- // only needed for Z3
- VCQuantifierInfos infos = node.Infos;
- Contract.Assert(infos != null);
- if (infos.qid != null) {
- wr.Write("(QID ");
- wr.Write(infos.qid);
- wr.Write(") ");
- }
- if (0 <= infos.uniqueId) {
- wr.Write("(SKOLEMID ");
- wr.Write(infos.uniqueId);
- wr.Write(") ");
- }
- }
-
- if (options.UseWeights) {
- int weight = QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
- if (weight != 1) {
- wr.Write("(WEIGHT ");
- wr.Write(weight);
- wr.Write(") ");
- }
- }
-
- Linearise(node.Body, options);
- wr.Write(")");
-
- return true;
-
- } finally {
- Namer.PopScope();
- }
- }
-
- private void WriteTriggers(List<VCTrigger/*!*/>/*!*/ triggers, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(cce.NonNullElements(triggers));
- // first, count how many neg/pos triggers there are
- int negTriggers = 0;
- int posTriggers = 0;
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- posTriggers++;
- } else {
- negTriggers++;
- }
- }
-
- if (posTriggers > 0) {
- wr.Write("(PATS");
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- if (vcTrig.Exprs.Count > 1) {
- wr.Write(" (MPAT");
- }
- foreach (VCExpr e in vcTrig.Exprs) {
- Contract.Assert(e != null);
- wr.Write(" ");
- LineariseAsTerm(e, options);
- }
- if (vcTrig.Exprs.Count > 1) {
- wr.Write(")");
- }
- }
- }
- wr.Write(") ");
- } else if (negTriggers > 0) {
- // if also positive triggers are given, the SMT solver (at least Z3)
- // will ignore the negative patterns and output a warning. Therefore
- // we never specify both negative and positive triggers
- wr.Write("(NOPATS");
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (!vcTrig.Pos) {
- wr.Write(" ");
- Contract.Assert(vcTrig.Exprs.Count == 1);
- LineariseAsTerm(vcTrig.Exprs[0], options);
- }
- }
- wr.Write(") ");
- }
-
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLet node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- Namer.PushScope();
- try {
-
- wr.Write("(LET (");
-
- LineariserOptions optionsWithVars = options.AddLetVariables(node.BoundVars);
- Contract.Assert(optionsWithVars != null);
-
- string s = "(";
- foreach (VCExprLetBinding b in node) {
- Contract.Assert(b != null);
- wr.Write(s);
- string printedName = Namer.GetLocalName(b.V, b.V.Name);
-
- bool formula = b.V.Type.IsBool;
- if (formula)
- wr.Write("FORMULA ");
- else
- wr.Write("TERM ");
- WriteId(printedName);
- wr.Write(" ");
- Linearise(b.E, optionsWithVars.SetAsTerm(!formula));
- wr.Write(")");
- s = " (";
- }
- wr.Write(") ");
- Linearise(node.Body, optionsWithVars);
- wr.Write(")");
-
- return true;
-
- } finally {
- Namer.PopScope();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for operator terms. The result (bool) is currently not used for anything
- internal class SimplifyLikeOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ExprLineariser != null);
- Contract.Invariant(wr != null);
- }
-
- private readonly SimplifyLikeExprLineariser/*!*/ ExprLineariser;
- private readonly TextWriter/*!*/ wr;
-
- public SimplifyLikeOpLineariser(SimplifyLikeExprLineariser ExprLineariser, TextWriter wr) {
- Contract.Requires(wr != null);
- Contract.Requires(ExprLineariser != null);
- this.ExprLineariser = ExprLineariser;
- this.wr = wr;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- WriteApplication(op, op, args, options, argsAsTerms);
- }
-
- private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- WriteApplication(op, op, args, options, options.AsTerm);
- }
-
- private void WriteTermApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- ExprLineariser.AssertAsTerm(op, options);
- WriteApplication(op, op, args, options, options.AsTerm);
- }
-
- private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(predOp != null);
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));
- WriteApplication(termOp, predOp, args, options, options.AsTerm);
- }
-
- private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
- Contract.Requires(options != null);
- Contract.Requires(predOp != null);
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));// change the AsTerm option for the arguments?
- wr.Write("({0}", options.AsTerm ? termOp : predOp);
-
- LineariserOptions newOptions = options.SetAsTerm(argsAsTerms);
-
- foreach (VCExpr e in args) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, newOptions);
- }
-
- wr.Write(")");
- }
-
- // write an application that can only be a term.
- // if the expression is supposed to be printed as a formula,
- // it is turned into an equation (EQ (f args) |@true|)
- private void WriteApplicationTermOnly(string termOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));
- if (!options.AsTerm)
- // Write: (EQ (f args) |@true|)
- // where "args" are written as terms
- wr.Write("({0} ", eqName);
-
- WriteApplication(termOp, args, options, true);
-
- if (!options.AsTerm)
- wr.Write(" {0})", boolTrueName);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public bool VisitNotOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(boolNotName, notName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- public bool VisitEqOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
- // use equality on terms, also if the arguments have type bool
- WriteApplication(termEqName, node, options);
- } else {
- if (node[0].Type.IsBool) {
- Contract.Assert(node[1].Type.IsBool);
- // use equivalence
- WriteApplication(iffName, node, options);
- } else {
- Contract.Assert(!node[1].Type.IsBool);
- // use equality and write the arguments as terms
- WriteApplication(eqName, node, options, true);
- }
- }
-
- return true;
- }
-
- public bool VisitNeqOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
- // use equality on terms, also if the arguments have type bool
- WriteApplication(termNeqName, node, options);
- } else {
- if (node[0].Type.IsBool) {
- Contract.Assert(node[1].Type.IsBool);
- // use equivalence and negate the whole thing
- wr.Write("({0} ", notName);
- WriteApplication(iffName, node, options);
- wr.Write(")");
- } else {
- // use equality and write the arguments as terms
- WriteApplication(neqName, node, options, true);
- }
- }
-
- return true;
- }
-
- public bool VisitAndOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- Contract.Assert(options.AsTerm);
- WriteApplication(boolAndName, andName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- public bool VisitOrOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- Contract.Assert(options.AsTerm);
- WriteApplication(boolOrName, orName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
- wr.Write("({0} ({1} ", boolOrName, boolNotName);
- ExprLineariser.Linearise(node[0], options);
- wr.Write(") ");
- ExprLineariser.Linearise(node[1], options);
- wr.Write(")");
- } else if (options.InverseImplies) {
- wr.Write("({0} ", orName);
- ExprLineariser.Linearise(node[1], options);
- wr.Write(" ({0} ", notName);
- ExprLineariser.Linearise(node[0], options);
- wr.Write("))");
- } else {
- WriteApplication(impliesName, node, options);
- }
- return true;
- }
-
- public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- ExprLineariser.AssertAsFormula(distinctName, options);
-
- if (node.Length < 2) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- wr.Write("({0}", distinctName);
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.LineariseAsTerm(e, options);
- }
- wr.Write(")");
- }
-
- return true;
- }
-
- public bool VisitLabelOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- VCExprLabelOp op = (VCExprLabelOp)node.Op;
- Contract.Assert(op != null);
- wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
- ExprLineariser.Linearise(node[0], options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitSelectOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- wr.Write("(" + SelectOpName(node));
- foreach (VCExpr/*!*/ e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitStoreOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- wr.Write("(" + StoreOpName(node));
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatAddName, node, options);
- return true;
- }
-
- public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatSubName, node, options);
- return true;
- }
-
- public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatMulName, node, options);
- return true;
- }
-
- public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatDivName, node, options);
- return true;
- }
-
- public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatRemName, node, options);
- return true;
- }
-
- public bool VisitFloatMinOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatMinName, node, options);
- return true;
- }
-
- public bool VisitFloatMaxOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatMaxName, node, options);
- return true;
- }
-
- public bool VisitFloatLeqOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatLeqName, node, options);
- return true;
- }
-
- public bool VisitFloatLtOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatLtName, node, options);
- return true;
- }
-
- public bool VisitFloatGeqOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatGeqName, node, options);
- return true;
- }
-
- public bool VisitFloatGtOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatGtName, node, options);
- return true;
- }
-
- public bool VisitFloatEqOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(floatEqName, node, options);
- return true;
- }
-
- public bool VisitBvOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication("$make_bv" + node.Type.BvBits, node, options);
- return true;
- }
-
- public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(BvExtractOpName(node), node, options);
- return true;
- }
-
- public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(BvConcatOpName(node), node, options);
- return true;
- }
-
- public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
-
- wr.Write("(ITE ");
- ExprLineariser.Linearise(node[0], options.SetAsTerm(false));
- wr.Write(" ");
- ExprLineariser.Linearise(node[1], options);
- wr.Write(" ");
- ExprLineariser.Linearise(node[2], options);
- wr.Write(")");
-
- return true;
- }
-
- public bool VisitCustomOp(VCExprNAry/*!*/ node, LineariserOptions/*!*/ options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- wr.Write("({0}", op.Name);
- foreach (VCExpr arg in node) {
- wr.Write(" ");
- ExprLineariser.Linearise(arg, options);
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitAddOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (node.Type.IsInt) {
- if (CommandLineOptions.Clo.ReflectAdd) {
- WriteTermApplication(intAddNameReflect, node, options);
- }
- else {
- WriteTermApplication(intAddName, node, options);
- }
- }
- else {
- WriteTermApplication(realAddName, node, options);
- }
- return true;
- }
-
- public bool VisitSubOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (node.Type.IsInt) {
- WriteTermApplication(intSubName, node, options);
- }
- else if (node.Type.IsReal) {
- WriteTermApplication(realSubName, node, options);
- }
- else {
- WriteTermApplication(floatSubName, node, options);
- }
- return true;
- }
-
- public bool VisitMulOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (node.Type.IsInt) {
- WriteTermApplication(intMulName, node, options);
- }
- else if (node.Type.IsReal) {
- WriteTermApplication(realMulName, node, options);
- }
- else {
- WriteTermApplication(floatMulName, node, options);
- }
- return true;
- }
-
- public bool VisitDivOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(intDivName, node, options);
- return true;
- }
-
- public bool VisitModOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(intModName, node, options);
- return true;
- }
-
- public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(realDivName, node, options);
- return true;
- }
-
- public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(realPowName, node, options);
- return true;
- }
-
- public bool VisitLtOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termLessName, lessName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitLeOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termAtmostName, atmostName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitGtOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termGreaterName, greaterName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitGeOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termAtleastName, atleastName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(subtypeName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(toIntName, node, options);
- return true;
- }
-
- public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(toRealName, node, options);
- return true;
- }
-
- public bool VisitToFloatOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(toFloatName, node, options);
- return true;
- }
-
- public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op != null);
- string funcName = op.Func.Name;
- Contract.Assert(funcName != null);
- string bvzName = op.Func.FindStringAttribute("external");
- string printedName = ExprLineariser.Namer.GetName(op.Func, funcName);
- Contract.Assert(printedName != null);
- if (bvzName != null)
- printedName = bvzName;
-
- if (options.UseTypes) {
- // we use term notation for arguments whose type is not bool, and
- // formula notation for boolean arguments
-
- wr.Write("(");
- ExprLineariser.WriteId(printedName);
-
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
-
- wr.Write(")");
- } else {
- // arguments are always terms
- WriteApplicationTermOnly(SimplifyLikeExprLineariser.MakeIdPrintable(printedName),
- node, options);
- }
- return true;
- }
-
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// a naive method to turn VCExprs into strings that can be fed into Simplify
+
+namespace Microsoft.Boogie.VCExprAST {
+ [ContractClassFor(typeof(LineariserOptions))]
+ public abstract class LinOptContracts : LineariserOptions {
+ public LinOptContracts()
+ : base(true) {
+ }
+ public override LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ throw new NotImplementedException();
+ }
+
+ }
+
+ // Options for the linearisation. Here one can choose, for instance,
+ // whether Simplify or Z3 output is to be produced
+ [ContractClass(typeof(LinOptContracts))]
+ public abstract class LineariserOptions {
+
+ public readonly bool AsTerm;
+ public abstract LineariserOptions/*!*/ SetAsTerm(bool newVal);
+
+ public abstract bool QuantifierIds {
+ get;
+ }
+
+ public virtual bool UseWeights {
+ get {
+ return false;
+ }
+ }
+
+ public virtual bool InverseImplies {
+ get {
+ return false;
+ }
+ }
+
+ // whether to include type specifications in quantifiers
+ public abstract bool UseTypes {
+ get;
+ }
+
+ // variables representing formulas in let-bindings have to be
+ // printed in a different way than other variables
+ public virtual List<VCExprVar/*!*/>/*!*/ LetVariables {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ return EmptyList;
+ }
+ }
+
+ public virtual LineariserOptions AddLetVariable(VCExprVar furtherVar) {
+ Contract.Requires(furtherVar != null);
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ return this;
+ }
+
+ public virtual LineariserOptions AddLetVariables(List<VCExprVar/*!*/>/*!*/ furtherVars) {
+ Contract.Requires(cce.NonNullElements(furtherVars));
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ return this;
+ }
+
+ private static readonly List<VCExprVar/*!*/>/*!*/ EmptyList = new List<VCExprVar/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarinat() {
+ Contract.Invariant(EmptyList != null);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ protected LineariserOptions(bool asTerm) {
+ this.AsTerm = asTerm;
+ }
+
+ public static readonly LineariserOptions SimplifyDefault = new SimplifyOptions(false);
+ internal static readonly LineariserOptions SimplifyDefaultTerm = new SimplifyOptions(true);
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private class SimplifyOptions : LineariserOptions {
+ internal SimplifyOptions(bool asTerm)
+ : base(asTerm) {
+
+ }
+ public override bool QuantifierIds {
+ get {
+ return false;
+ }
+ }
+ public override bool UseTypes {
+ get {
+ return false;
+ }
+ }
+ public override LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ if (newVal)
+ return SimplifyDefaultTerm;
+ else
+ return SimplifyDefault;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for expressions. The result (bool) is currently not used for anything
+ public class SimplifyLikeExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> {
+
+ public static string ToSimplifyString(VCExpr e, UniqueNamer namer) {
+ Contract.Requires(namer != null);
+ Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return ToString(e, LineariserOptions.SimplifyDefault, namer);
+ }
+
+ public static string ToString(VCExpr/*!*/ e, LineariserOptions/*!*/ options, UniqueNamer/*!*/ namer) {
+ Contract.Requires(e != null);
+ Contract.Requires(options != null);
+ Contract.Requires(namer != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ StringWriter sw = new StringWriter();
+ SimplifyLikeExprLineariser lin = new SimplifyLikeExprLineariser(sw, namer);
+ lin.Linearise(e, options);
+ return sw.ToString();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(wr != null);
+ Contract.Invariant(Namer != null);
+ }
+
+ private readonly TextWriter/*!*/ wr;
+ private SimplifyLikeOpLineariser OpLinObject = null;
+ private IVCExprOpVisitor<bool, LineariserOptions/*!*/>/*!*/ OpLineariser {
+ get {
+ Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
+ if (OpLinObject == null)
+ OpLinObject = new SimplifyLikeOpLineariser(this, wr);
+ return OpLinObject;
+ }
+ }
+
+ internal readonly UniqueNamer Namer;
+
+ public SimplifyLikeExprLineariser(TextWriter wr, UniqueNamer namer) {
+ Contract.Requires(namer != null);
+ Contract.Requires(wr != null);
+ this.wr = wr;
+ this.Namer = namer;
+ }
+
+ public void Linearise(VCExpr expr, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(expr != null);
+ expr.Accept<bool, LineariserOptions>(this, options);
+ }
+
+ public void LineariseAsTerm(VCExpr expr, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(expr != null);
+ Linearise(expr, options.SetAsTerm(true));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public static string MakeIdPrintable(string s) {
+ Contract.Requires(s != null);
+ Contract.Requires(s != "");
+ Contract.Ensures(Contract.Result<string>() != null);
+ // make sure that no keywords are used as identifiers
+ switch (s) {
+ case andName:
+ case orName:
+ case notName:
+ case impliesName:
+ case iffName:
+ case eqName:
+ case neqName:
+ case distinctName:
+ case TRUEName:
+ case FALSEName:
+ s = "nonkeyword_" + s;
+ break;
+ }
+
+ if (CommandLineOptions.Clo.BracketIdsInVC == 0) {
+ // In this form, we go with any identifier, so we don't ever bother about brackets.
+ // Except: @true and @false are always written with brackets
+ return s;
+ }
+ bool looksLikeOperator = true;
+ bool looksLikeSimpleId = true;
+ bool useBrackets = false;
+ foreach (char ch in s) {
+ switch (ch) {
+ case '=':
+ case '<':
+ case '>':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case ':':
+ // looks like operator, not simple id
+ looksLikeSimpleId = false;
+ break;
+ default:
+ if (Char.IsLetterOrDigit(ch)) {
+ // looks like simple id, not operator
+ looksLikeOperator = false;
+ } else {
+ // looks like neither operator nor simple id
+ looksLikeOperator = false;
+ looksLikeSimpleId = false;
+ }
+ break;
+ }
+ if (!looksLikeOperator && !looksLikeSimpleId) {
+ useBrackets = true;
+ break;
+ }
+ }
+ if (useBrackets) {
+ return "|" + s + "|";
+ } else {
+ return s;
+ }
+ }
+
+ private static void TypeToStringHelper(Type t, StringBuilder sb) {
+ Contract.Requires(t != null);
+
+ TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
+ if (syn != null) {
+ TypeToStringHelper(syn.ExpandedType, sb);
+ } else {
+ if (t.IsMap) {
+ MapType m = t.AsMap;
+ sb.Append('[');
+ for (int i = 0; i < m.MapArity; ++i) {
+ if (i != 0)
+ sb.Append(',');
+ TypeToStringHelper(m.Arguments[i], sb);
+ }
+ sb.Append(']');
+ TypeToStringHelper(m.Result, sb);
+ } else if (t.IsBool || t.IsInt || t.IsBv) {
+ sb.Append(TypeToString(t));
+ } else {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
+ t.Emit(stream);
+ }
+ sb.Append(buffer.ToString());
+ }
+ }
+
+ }
+
+
+ public static string TypeToString(Type t) {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ if (t.IsBool)
+ return "$bool";
+ else if (t.IsInt)
+ return "$int";
+ else if (t.IsBv)
+ return "$bv" + t.BvBits;
+ else {
+ StringBuilder sb = new StringBuilder();
+ TypeToStringHelper(t, sb);
+ return sb.ToString();
+ }
+ }
+
+ public static string BvConcatOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Op is VCExprBvConcatOp));
+ Contract.Ensures(Contract.Result<string>() != null);
+ int bits1 = node[0].Type.BvBits;
+ int bits2 = node[1].Type.BvBits;
+ return "$bv" + (bits1 + bits2) + "_concat[" + bits1 + "." + bits2 + "]";
+ }
+
+ public static string BvExtractOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires(node.Op is VCExprBvExtractOp);
+ Contract.Ensures(Contract.Result<string>() != null);
+ VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
+ return "$bv" + node.Type.BvBits + "_extract" + op.Total + "[" + op.Start + ":" + op.End + "]";
+ }
+
+ public static string StoreOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "Store_" + TypeToString(node[0].Type);
+ }
+
+ public static string SelectOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "Select_" + TypeToString(node[0].Type);
+ }
+
+ internal void WriteId(string s) {
+ Contract.Requires(s != null);
+ wr.Write(MakeIdPrintable(s));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// The name for logical conjunction in Simplify
+ /// </summary>
+ internal const string andName = "AND"; // conjunction
+ internal const string orName = "OR"; // disjunction
+ internal const string notName = "NOT"; // negation
+ internal const string impliesName = "IMPLIES"; // implication
+ internal const string iffName = "IFF"; // logical equivalence
+ internal const string eqName = "EQ"; // equality
+ internal const string neqName = "NEQ"; // inequality
+ internal const string lessName = "<";
+ internal const string greaterName = ">";
+ internal const string atmostName = "<=";
+ internal const string atleastName = ">=";
+ internal const string TRUEName = "TRUE"; // nullary predicate that is always true
+ internal const string FALSEName = "FALSE"; // nullary predicate that is always false
+ internal const string subtypeName = "<:";
+ internal const string subtypeArgsName = "<::";
+
+ internal const string distinctName = "DISTINCT";
+ /// <summary>
+ /// name of the main inclusion relation
+ /// </summary>
+ internal const string boolTrueName = "|@true|";
+ internal const string boolFalseName = "|@false|";
+ internal const string boolAndName = "boolAnd";
+ internal const string boolOrName = "boolOr";
+ internal const string boolNotName = "boolNot";
+ internal const string termEqName = "anyEqual";
+ internal const string termNeqName = "anyNeq";
+ internal const string termLessName = "intLess";
+ internal const string termGreaterName = "intGreater";
+ internal const string termAtmostName = "intAtMost";
+ internal const string termAtleastName = "intAtLeast";
+ internal const string intAddName = "+";
+ internal const string intAddNameReflect = "Reflect$Add";
+ internal const string intSubName = "-";
+ internal const string intMulName = "*";
+ internal const string intDivName = "/";
+ internal const string intModName = "%";
+ internal const string realAddName = "realAdd";
+ internal const string realSubName = "realSub";
+ internal const string realMulName = "realMul";
+ internal const string realDivName = "realDiv";
+ internal const string floatAddName = "floatAdd";
+ internal const string floatSubName = "floatSub";
+ internal const string floatMulName = "floatMul";
+ internal const string floatDivName = "floatDiv";
+ internal const string floatRemName = "floatRem";
+ internal const string floatMinName = "floatMin";
+ internal const string floatMaxName = "floatMax";
+ internal const string floatLeqName = "floatLeq";
+ internal const string floatLtName = "floatLt";
+ internal const string floatGeqName = "floatGeq";
+ internal const string floatGtName = "floatGt";
+ internal const string floatEqName = "floatEq";
+ internal const string realPowName = "realPow";
+ internal const string toIntName = "toIntCoercion";
+ internal const string toRealName = "toRealCoercion";
+ internal const string toFloatName = "toFloatCoercion";
+
+ internal void AssertAsTerm(string x, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(x != null);
+ if (!options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
+ }
+
+ internal void AssertAsFormula(string x, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(x != null);
+ if (options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLiteral node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write(options.UseTypes ? TRUEName : boolTrueName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write(options.UseTypes ? FALSEName : boolFalseName);
+ else if (node is VCExprIntLit) {
+ wr.Write(((VCExprIntLit)node).Val);
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ } else {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write(TRUEName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write(FALSEName);
+ else if (node is VCExprIntLit) {
+ System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ VCExprOp op = node.Op;
+ Contract.Assert(op != null);
+
+ if (!options.AsTerm &&
+ (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp))) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? andName : orName);
+ IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
+ Contract.Assert(enumerator != null);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Linearise(cce.NonNull((VCExpr)enumerator.Current), options);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, LineariserOptions>(OpLineariser, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprVar node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ string printedName = Namer.GetName(node, node.Name);
+ Contract.Assert(printedName != null);
+
+ if (options.AsTerm ||
+ // variables for formulas bound in a let-binding are never
+ // written as an equation
+ options.LetVariables.Contains(node) ||
+ // if variables are properly typed, they cannot be written as
+ // equation either
+ options.UseTypes) {
+ WriteId(printedName);
+ } else {
+ wr.Write("({0} ", eqName);
+ WriteId(printedName);
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprQuantifier node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ AssertAsFormula(node.Quan.ToString(), options);
+ Contract.Assert(node.TypeParameters.Count == 0);
+
+ Namer.PushScope();
+ try {
+
+ string kind = node.Quan == Quantifier.ALL ? "FORALL" : "EXISTS";
+ wr.Write("({0} (", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++) {
+ VCExprVar var = node.BoundVars[i];
+ Contract.Assert(var != null);
+ string printedName = Namer.GetLocalName(var, var.Name);
+ Contract.Assert(printedName != null);
+ if (i != 0)
+ wr.Write(" ");
+ WriteId(printedName);
+ if (options.UseTypes)
+ wr.Write(" :TYPE {0}", TypeToString(var.Type));
+ }
+ wr.Write(") ");
+
+ WriteTriggers(node.Triggers, options);
+
+ if (options.QuantifierIds) {
+ // only needed for Z3
+ VCQuantifierInfos infos = node.Infos;
+ Contract.Assert(infos != null);
+ if (infos.qid != null) {
+ wr.Write("(QID ");
+ wr.Write(infos.qid);
+ wr.Write(") ");
+ }
+ if (0 <= infos.uniqueId) {
+ wr.Write("(SKOLEMID ");
+ wr.Write(infos.uniqueId);
+ wr.Write(") ");
+ }
+ }
+
+ if (options.UseWeights) {
+ int weight = QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
+ if (weight != 1) {
+ wr.Write("(WEIGHT ");
+ wr.Write(weight);
+ wr.Write(") ");
+ }
+ }
+
+ Linearise(node.Body, options);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ private void WriteTriggers(List<VCTrigger/*!*/>/*!*/ triggers, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ // first, count how many neg/pos triggers there are
+ int negTriggers = 0;
+ int posTriggers = 0;
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (vcTrig.Pos) {
+ posTriggers++;
+ } else {
+ negTriggers++;
+ }
+ }
+
+ if (posTriggers > 0) {
+ wr.Write("(PATS");
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (vcTrig.Pos) {
+ if (vcTrig.Exprs.Count > 1) {
+ wr.Write(" (MPAT");
+ }
+ foreach (VCExpr e in vcTrig.Exprs) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ LineariseAsTerm(e, options);
+ }
+ if (vcTrig.Exprs.Count > 1) {
+ wr.Write(")");
+ }
+ }
+ }
+ wr.Write(") ");
+ } else if (negTriggers > 0) {
+ // if also positive triggers are given, the SMT solver (at least Z3)
+ // will ignore the negative patterns and output a warning. Therefore
+ // we never specify both negative and positive triggers
+ wr.Write("(NOPATS");
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (!vcTrig.Pos) {
+ wr.Write(" ");
+ Contract.Assert(vcTrig.Exprs.Count == 1);
+ LineariseAsTerm(vcTrig.Exprs[0], options);
+ }
+ }
+ wr.Write(") ");
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLet node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ Namer.PushScope();
+ try {
+
+ wr.Write("(LET (");
+
+ LineariserOptions optionsWithVars = options.AddLetVariables(node.BoundVars);
+ Contract.Assert(optionsWithVars != null);
+
+ string s = "(";
+ foreach (VCExprLetBinding b in node) {
+ Contract.Assert(b != null);
+ wr.Write(s);
+ string printedName = Namer.GetLocalName(b.V, b.V.Name);
+
+ bool formula = b.V.Type.IsBool;
+ if (formula)
+ wr.Write("FORMULA ");
+ else
+ wr.Write("TERM ");
+ WriteId(printedName);
+ wr.Write(" ");
+ Linearise(b.E, optionsWithVars.SetAsTerm(!formula));
+ wr.Write(")");
+ s = " (";
+ }
+ wr.Write(") ");
+ Linearise(node.Body, optionsWithVars);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for operator terms. The result (bool) is currently not used for anything
+ internal class SimplifyLikeOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExprLineariser != null);
+ Contract.Invariant(wr != null);
+ }
+
+ private readonly SimplifyLikeExprLineariser/*!*/ ExprLineariser;
+ private readonly TextWriter/*!*/ wr;
+
+ public SimplifyLikeOpLineariser(SimplifyLikeExprLineariser ExprLineariser, TextWriter wr) {
+ Contract.Requires(wr != null);
+ Contract.Requires(ExprLineariser != null);
+ this.ExprLineariser = ExprLineariser;
+ this.wr = wr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ WriteApplication(op, op, args, options, argsAsTerms);
+ }
+
+ private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteTermApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ ExprLineariser.AssertAsTerm(op, options);
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(predOp != null);
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));
+ WriteApplication(termOp, predOp, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
+ Contract.Requires(options != null);
+ Contract.Requires(predOp != null);
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));// change the AsTerm option for the arguments?
+ wr.Write("({0}", options.AsTerm ? termOp : predOp);
+
+ LineariserOptions newOptions = options.SetAsTerm(argsAsTerms);
+
+ foreach (VCExpr e in args) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, newOptions);
+ }
+
+ wr.Write(")");
+ }
+
+ // write an application that can only be a term.
+ // if the expression is supposed to be printed as a formula,
+ // it is turned into an equation (EQ (f args) |@true|)
+ private void WriteApplicationTermOnly(string termOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));
+ if (!options.AsTerm)
+ // Write: (EQ (f args) |@true|)
+ // where "args" are written as terms
+ wr.Write("({0} ", eqName);
+
+ WriteApplication(termOp, args, options, true);
+
+ if (!options.AsTerm)
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public bool VisitNotOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(boolNotName, notName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitEqOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ WriteApplication(termEqName, node, options);
+ } else {
+ if (node[0].Type.IsBool) {
+ Contract.Assert(node[1].Type.IsBool);
+ // use equivalence
+ WriteApplication(iffName, node, options);
+ } else {
+ Contract.Assert(!node[1].Type.IsBool);
+ // use equality and write the arguments as terms
+ WriteApplication(eqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitNeqOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ WriteApplication(termNeqName, node, options);
+ } else {
+ if (node[0].Type.IsBool) {
+ Contract.Assert(node[1].Type.IsBool);
+ // use equivalence and negate the whole thing
+ wr.Write("({0} ", notName);
+ WriteApplication(iffName, node, options);
+ wr.Write(")");
+ } else {
+ // use equality and write the arguments as terms
+ WriteApplication(neqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitAndOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(options.AsTerm);
+ WriteApplication(boolAndName, andName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitOrOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(options.AsTerm);
+ WriteApplication(boolOrName, orName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+ wr.Write("({0} ({1} ", boolOrName, boolNotName);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write(") ");
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(")");
+ } else if (options.InverseImplies) {
+ wr.Write("({0} ", orName);
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(" ({0} ", notName);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write("))");
+ } else {
+ WriteApplication(impliesName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ ExprLineariser.AssertAsFormula(distinctName, options);
+
+ if (node.Length < 2) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ wr.Write("({0}", distinctName);
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.LineariseAsTerm(e, options);
+ }
+ wr.Write(")");
+ }
+
+ return true;
+ }
+
+ public bool VisitLabelOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ VCExprLabelOp op = (VCExprLabelOp)node.Op;
+ Contract.Assert(op != null);
+ wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitSelectOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ wr.Write("(" + SelectOpName(node));
+ foreach (VCExpr/*!*/ e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitStoreOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ wr.Write("(" + StoreOpName(node));
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatAddName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatSubName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatMulName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatDivName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatRemName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatMinOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatMinName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatMaxOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatMaxName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatLeqOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatLeqName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatLtOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatLtName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatGeqOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatGeqName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatGtOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatGtName, node, options);
+ return true;
+ }
+
+ public bool VisitFloatEqOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(floatEqName, node, options);
+ return true;
+ }
+
+ public bool VisitBvOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication("$make_bv" + node.Type.BvBits, node, options);
+ return true;
+ }
+
+ public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(BvExtractOpName(node), node, options);
+ return true;
+ }
+
+ public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(BvConcatOpName(node), node, options);
+ return true;
+ }
+
+ public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+
+ wr.Write("(ITE ");
+ ExprLineariser.Linearise(node[0], options.SetAsTerm(false));
+ wr.Write(" ");
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(" ");
+ ExprLineariser.Linearise(node[2], options);
+ wr.Write(")");
+
+ return true;
+ }
+
+ public bool VisitCustomOp(VCExprNAry/*!*/ node, LineariserOptions/*!*/ options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ VCExprCustomOp op = (VCExprCustomOp)node.Op;
+ wr.Write("({0}", op.Name);
+ foreach (VCExpr arg in node) {
+ wr.Write(" ");
+ ExprLineariser.Linearise(arg, options);
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitAddOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (node.Type.IsInt) {
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ WriteTermApplication(intAddNameReflect, node, options);
+ }
+ else {
+ WriteTermApplication(intAddName, node, options);
+ }
+ }
+ else {
+ WriteTermApplication(realAddName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitSubOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (node.Type.IsInt) {
+ WriteTermApplication(intSubName, node, options);
+ }
+ else if (node.Type.IsReal) {
+ WriteTermApplication(realSubName, node, options);
+ }
+ else {
+ WriteTermApplication(floatSubName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitMulOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (node.Type.IsInt) {
+ WriteTermApplication(intMulName, node, options);
+ }
+ else if (node.Type.IsReal) {
+ WriteTermApplication(realMulName, node, options);
+ }
+ else {
+ WriteTermApplication(floatMulName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitDivOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(intDivName, node, options);
+ return true;
+ }
+
+ public bool VisitModOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(intModName, node, options);
+ return true;
+ }
+
+ public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(realDivName, node, options);
+ return true;
+ }
+
+ public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(realPowName, node, options);
+ return true;
+ }
+
+ public bool VisitLtOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termLessName, lessName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitLeOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termAtmostName, atmostName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGtOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termGreaterName, greaterName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGeOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termAtleastName, atleastName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(subtypeName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toIntName, node, options);
+ return true;
+ }
+
+ public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toRealName, node, options);
+ return true;
+ }
+
+ public bool VisitToFloatOp(VCExprNAry node, LineariserOptions options)
+ {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toFloatName, node, options);
+ return true;
+ }
+
+ public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
+ Contract.Assert(op != null);
+ string funcName = op.Func.Name;
+ Contract.Assert(funcName != null);
+ string bvzName = op.Func.FindStringAttribute("external");
+ string printedName = ExprLineariser.Namer.GetName(op.Func, funcName);
+ Contract.Assert(printedName != null);
+ if (bvzName != null)
+ printedName = bvzName;
+
+ if (options.UseTypes) {
+ // we use term notation for arguments whose type is not bool, and
+ // formula notation for boolean arguments
+
+ wr.Write("(");
+ ExprLineariser.WriteId(printedName);
+
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+
+ wr.Write(")");
+ } else {
+ // arguments are always terms
+ WriteApplicationTermOnly(SimplifyLikeExprLineariser.MakeIdPrintable(printedName),
+ node, options);
+ }
+ return true;
+ }
+
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TermFormulaFlattening.cs b/Source/VCExpr/TermFormulaFlattening.cs
index 7815413f..c4150024 100644
--- a/Source/VCExpr/TermFormulaFlattening.cs
+++ b/Source/VCExpr/TermFormulaFlattening.cs
@@ -1,248 +1,248 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Ensure that no formulas (expressions of type boolean that are not
-// just a variable) occur with terms (expressions of some other
-// type). This is done by introducing let-binders for boolean
-// variables.
-
-namespace Microsoft.Boogie.VCExprAST
-{
-
- public struct FlattenerState {
- public readonly int Polarity;
- public readonly bool InTerm;
-
- public static FlattenerState INITIAL = new FlattenerState(1, false);
-
- public FlattenerState(int polarity, bool inTerm) {
- Polarity = polarity;
- InTerm = inTerm;
- }
-
- public FlattenerState TogglePolarity { get {
- return new FlattenerState(-Polarity, InTerm);
- } }
-
- public FlattenerState ZeroPolarity { get {
- return new FlattenerState(0, InTerm);
- } }
-
- public FlattenerState EnterTerm { get {
- return new FlattenerState(Polarity, true);
- } }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class TermFormulaFlattener : MutatingVCExprVisitor<FlattenerState> {
-
- public TermFormulaFlattener(VCExpressionGenerator gen):base(gen){
-Contract.Requires(gen != null);
-
- }
-
- private readonly IDictionary<VCExpr/*!*/, VCExprVar/*!*/>/*!*/ Bindings =
- new Dictionary<VCExpr/*!*/, VCExprVar/*!*/> ();
-
- private int varNameCounter = 0;
-
- public VCExpr Flatten(VCExpr expr){
-Contract.Requires(expr != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ res = Mutate(expr, FlattenerState.INITIAL);
- Contract.Assert(res != null);
- while (Bindings.Count > 0) {
- List<VCExprLetBinding/*!*/>/*!*/ letBindings = new List<VCExprLetBinding/*!*/> ();
- foreach (KeyValuePair<VCExpr/*!*/, VCExprVar/*!*/> pair in Bindings){Contract.Assert(cce.NonNullElements(pair));
- letBindings.Add(Gen.LetBinding(pair.Value, pair.Key));}
- Bindings.Clear();
- res = AddBindings(letBindings, res, FlattenerState.INITIAL);
- }
- return res;
- }
-
- private VCExprVar GetVarFor(VCExpr expr){
-Contract.Requires(expr != null);
-Contract.Requires((expr.Type.IsBool));
-Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res;
- if (!Bindings.TryGetValue(expr, out res)) {
- string name = "flt" + varNameCounter;
- varNameCounter = varNameCounter + 1;
- res = Gen.Variable(name, Type.Bool);
- Bindings.Add(expr, res);
- }
- return cce.NonNull(res);
- }
-
- // Remove all let-bindings from the field bindings whose rhs
- // contains any of the specified variables
- private List<VCExprLetBinding/*!*/>/*!*/ RemoveBindingsWithVars(List<VCExprVar/*!*/>/*!*/ boundVars, List<TypeVariable/*!*/>/*!*/ boundTypeVars){
-Contract.Requires(cce.NonNullElements(boundTypeVars));
-Contract.Requires(cce.NonNullElements(boundVars));
-Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
- List<VCExprLetBinding/*!*/>/*!*/ res = new List<VCExprLetBinding/*!*/> ();
- FreeVariableCollector/*!*/ coll = new FreeVariableCollector ();
-
- foreach (KeyValuePair<VCExpr, VCExprVar> pair in Bindings) {
- Contract.Assert(cce.NonNullElements(pair));
- coll.Collect(pair.Key);
- if (boundVars.Any(var => coll.FreeTermVars.ContainsKey(var)) ||
- boundTypeVars.Any(var => coll.FreeTypeVars.Contains(var)))
- res.Add(Gen.LetBinding(pair.Value, pair.Key));
- coll.Reset();
- }
-
- foreach (VCExprLetBinding b in res){Contract.Assert(b != null);
- Bindings.Remove(b.E);}
-
- return res;
- }
-
- // Add bindings to a formula using an implication or
- // conjunction. The bindings themselves will be flattened as well,
- // which might introduce further bindings
- private VCExpr AddBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr body, FlattenerState state){
-Contract.Requires(body != null);
-Contract.Requires(cce.NonNullElements(bindings));
-Contract.Requires((body.Type.IsBool));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = FlattenBindings(bindings, state);
- Contract.Assert(mutatedBindings != null);
- VCExpr/*!*/ bindingEquations = Gen.AsEquations(mutatedBindings);
- Contract.Assert(bindingEquations != null);
- switch(state.Polarity) {
- case 1:
- return Gen.Implies(bindingEquations, body);
- case -1:
- return Gen.And(bindingEquations, body);
- case 0:
- // also add explicit quantifiers for the bound variables
- List<VCExprVar/*!*/>/*!*/ vars = new List<VCExprVar/*!*/> ();
- foreach (VCExprLetBinding/*!*/ binding in mutatedBindings){Contract.Assert(binding != null);
- vars.Add(binding.V);}
- return Gen.Forall(vars, new List<VCTrigger/*!*/>(),
- Gen.Implies(bindingEquations, body));
- }
- Contract.Assert(false); throw new cce.UnreachableException();
- }
-
- private List<VCExprLetBinding/*!*/>/*!*/ FlattenBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, FlattenerState state){
-Contract.Requires(cce.NonNullElements(bindings));
-Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
- FlattenerState stateInBindings = state.ZeroPolarity;
- List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = new List<VCExprLetBinding/*!*/> ();
- foreach (VCExprLetBinding/*!*/ b in bindings) {
- Contract.Assert(b != null);
- mutatedBindings.Add(Gen.LetBinding(b.V, Mutate(b.E, stateInBindings)));
- }
- return mutatedBindings;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override bool AvoidVisit(VCExprNAry node, FlattenerState arg)
- {
- return node.Op.Equals(VCExpressionGenerator.AndOp) ||
- node.Op.Equals(VCExpressionGenerator.OrOp);
- }
-
- public override VCExpr Visit(VCExprNAry node, FlattenerState state){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // track the polarity to know whether implications or conjunctions
- // are to be introduced
-
- if (node.Op.Equals(VCExpressionGenerator.NotOp))
- return Gen.Not(Mutate(node[0], state.TogglePolarity));
-
- if (node.Op.Equals(VCExpressionGenerator.ImpliesOp)) {
- VCExpr newArg0 = Mutate(node[0], state.TogglePolarity);
- VCExpr newArg1 = Mutate(node[1], state);
- return Gen.Implies(newArg0, newArg1);
- }
-
- if (!node.Type.IsBool)
- state = state.EnterTerm;
-
- if (!node.Op.Equals(VCExpressionGenerator.AndOp) &&
- !node.Op.Equals(VCExpressionGenerator.OrOp) &&
- !(node.Op is VCExprLabelOp))
- // standard is to set the polarity to 0 (fits most operators)
- return base.Visit(node, state.ZeroPolarity);
-
- return base.Visit(node, state);
- }
-
- public override VCExpr Visit(VCExprQuantifier node, FlattenerState state){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (state.InTerm)
- return GetVarFor(node);
-
- // we only flatten within the matrix of the quantified formula,
- // not within the triggers (since SMT-solvers do not seem to
- // appreciate triggers with let-binders)
- VCExpr newBody = Mutate(node.Body, state);
-
- // Check whether any of the extracted terms contain variables
- // bound by this quantifier. In this case, we have to add
- // let-binders and remove the extracted terms
- bool cont = true;
- while (cont) {
- List<VCExprLetBinding/*!*/>/*!*/ localBindings =
- RemoveBindingsWithVars(node.BoundVars, node.TypeParameters);
- Contract.Assert(cce.NonNullElements(localBindings));
- if (localBindings.Count > 0)
- newBody = AddBindings(localBindings, newBody, state);
- else
- cont = false;
- }
-
- return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars, node.Triggers, node.Infos, newBody);
- }
-
- public override VCExpr Visit(VCExprLet node, FlattenerState state){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (state.InTerm)
- return GetVarFor(node);
-
- VCExprLet prelimRes = (VCExprLet)cce.NonNull(base.Visit(node, state));
-
- List<VCExprLetBinding/*!*/>/*!*/ allBindings = new List<VCExprLetBinding/*!*/> ();
- allBindings.AddRange(prelimRes);
-
- // Check whether any of the extracted terms contain variables
- // bound by this binder. In this case, we have to add
- // let-binders and remove the extracted terms
- bool cont = true;
- while (cont) {
- List<VCExprLetBinding/*!*/>/*!*/ localBindings =
- RemoveBindingsWithVars(prelimRes.BoundVars, new List<TypeVariable/*!*/>());
- if (localBindings.Count > 0)
- allBindings.AddRange(FlattenBindings(localBindings, state));
- else
- cont = false;
- }
-
- return Gen.Let(allBindings, prelimRes.Body);
- }
-
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Ensure that no formulas (expressions of type boolean that are not
+// just a variable) occur with terms (expressions of some other
+// type). This is done by introducing let-binders for boolean
+// variables.
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ public struct FlattenerState {
+ public readonly int Polarity;
+ public readonly bool InTerm;
+
+ public static FlattenerState INITIAL = new FlattenerState(1, false);
+
+ public FlattenerState(int polarity, bool inTerm) {
+ Polarity = polarity;
+ InTerm = inTerm;
+ }
+
+ public FlattenerState TogglePolarity { get {
+ return new FlattenerState(-Polarity, InTerm);
+ } }
+
+ public FlattenerState ZeroPolarity { get {
+ return new FlattenerState(0, InTerm);
+ } }
+
+ public FlattenerState EnterTerm { get {
+ return new FlattenerState(Polarity, true);
+ } }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class TermFormulaFlattener : MutatingVCExprVisitor<FlattenerState> {
+
+ public TermFormulaFlattener(VCExpressionGenerator gen):base(gen){
+Contract.Requires(gen != null);
+
+ }
+
+ private readonly IDictionary<VCExpr/*!*/, VCExprVar/*!*/>/*!*/ Bindings =
+ new Dictionary<VCExpr/*!*/, VCExprVar/*!*/> ();
+
+ private int varNameCounter = 0;
+
+ public VCExpr Flatten(VCExpr expr){
+Contract.Requires(expr != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ res = Mutate(expr, FlattenerState.INITIAL);
+ Contract.Assert(res != null);
+ while (Bindings.Count > 0) {
+ List<VCExprLetBinding/*!*/>/*!*/ letBindings = new List<VCExprLetBinding/*!*/> ();
+ foreach (KeyValuePair<VCExpr/*!*/, VCExprVar/*!*/> pair in Bindings){Contract.Assert(cce.NonNullElements(pair));
+ letBindings.Add(Gen.LetBinding(pair.Value, pair.Key));}
+ Bindings.Clear();
+ res = AddBindings(letBindings, res, FlattenerState.INITIAL);
+ }
+ return res;
+ }
+
+ private VCExprVar GetVarFor(VCExpr expr){
+Contract.Requires(expr != null);
+Contract.Requires((expr.Type.IsBool));
+Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res;
+ if (!Bindings.TryGetValue(expr, out res)) {
+ string name = "flt" + varNameCounter;
+ varNameCounter = varNameCounter + 1;
+ res = Gen.Variable(name, Type.Bool);
+ Bindings.Add(expr, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ // Remove all let-bindings from the field bindings whose rhs
+ // contains any of the specified variables
+ private List<VCExprLetBinding/*!*/>/*!*/ RemoveBindingsWithVars(List<VCExprVar/*!*/>/*!*/ boundVars, List<TypeVariable/*!*/>/*!*/ boundTypeVars){
+Contract.Requires(cce.NonNullElements(boundTypeVars));
+Contract.Requires(cce.NonNullElements(boundVars));
+Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+ List<VCExprLetBinding/*!*/>/*!*/ res = new List<VCExprLetBinding/*!*/> ();
+ FreeVariableCollector/*!*/ coll = new FreeVariableCollector ();
+
+ foreach (KeyValuePair<VCExpr, VCExprVar> pair in Bindings) {
+ Contract.Assert(cce.NonNullElements(pair));
+ coll.Collect(pair.Key);
+ if (boundVars.Any(var => coll.FreeTermVars.ContainsKey(var)) ||
+ boundTypeVars.Any(var => coll.FreeTypeVars.Contains(var)))
+ res.Add(Gen.LetBinding(pair.Value, pair.Key));
+ coll.Reset();
+ }
+
+ foreach (VCExprLetBinding b in res){Contract.Assert(b != null);
+ Bindings.Remove(b.E);}
+
+ return res;
+ }
+
+ // Add bindings to a formula using an implication or
+ // conjunction. The bindings themselves will be flattened as well,
+ // which might introduce further bindings
+ private VCExpr AddBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr body, FlattenerState state){
+Contract.Requires(body != null);
+Contract.Requires(cce.NonNullElements(bindings));
+Contract.Requires((body.Type.IsBool));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = FlattenBindings(bindings, state);
+ Contract.Assert(mutatedBindings != null);
+ VCExpr/*!*/ bindingEquations = Gen.AsEquations(mutatedBindings);
+ Contract.Assert(bindingEquations != null);
+ switch(state.Polarity) {
+ case 1:
+ return Gen.Implies(bindingEquations, body);
+ case -1:
+ return Gen.And(bindingEquations, body);
+ case 0:
+ // also add explicit quantifiers for the bound variables
+ List<VCExprVar/*!*/>/*!*/ vars = new List<VCExprVar/*!*/> ();
+ foreach (VCExprLetBinding/*!*/ binding in mutatedBindings){Contract.Assert(binding != null);
+ vars.Add(binding.V);}
+ return Gen.Forall(vars, new List<VCTrigger/*!*/>(),
+ Gen.Implies(bindingEquations, body));
+ }
+ Contract.Assert(false); throw new cce.UnreachableException();
+ }
+
+ private List<VCExprLetBinding/*!*/>/*!*/ FlattenBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, FlattenerState state){
+Contract.Requires(cce.NonNullElements(bindings));
+Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+ FlattenerState stateInBindings = state.ZeroPolarity;
+ List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = new List<VCExprLetBinding/*!*/> ();
+ foreach (VCExprLetBinding/*!*/ b in bindings) {
+ Contract.Assert(b != null);
+ mutatedBindings.Add(Gen.LetBinding(b.V, Mutate(b.E, stateInBindings)));
+ }
+ return mutatedBindings;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override bool AvoidVisit(VCExprNAry node, FlattenerState arg)
+ {
+ return node.Op.Equals(VCExpressionGenerator.AndOp) ||
+ node.Op.Equals(VCExpressionGenerator.OrOp);
+ }
+
+ public override VCExpr Visit(VCExprNAry node, FlattenerState state){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // track the polarity to know whether implications or conjunctions
+ // are to be introduced
+
+ if (node.Op.Equals(VCExpressionGenerator.NotOp))
+ return Gen.Not(Mutate(node[0], state.TogglePolarity));
+
+ if (node.Op.Equals(VCExpressionGenerator.ImpliesOp)) {
+ VCExpr newArg0 = Mutate(node[0], state.TogglePolarity);
+ VCExpr newArg1 = Mutate(node[1], state);
+ return Gen.Implies(newArg0, newArg1);
+ }
+
+ if (!node.Type.IsBool)
+ state = state.EnterTerm;
+
+ if (!node.Op.Equals(VCExpressionGenerator.AndOp) &&
+ !node.Op.Equals(VCExpressionGenerator.OrOp) &&
+ !(node.Op is VCExprLabelOp))
+ // standard is to set the polarity to 0 (fits most operators)
+ return base.Visit(node, state.ZeroPolarity);
+
+ return base.Visit(node, state);
+ }
+
+ public override VCExpr Visit(VCExprQuantifier node, FlattenerState state){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (state.InTerm)
+ return GetVarFor(node);
+
+ // we only flatten within the matrix of the quantified formula,
+ // not within the triggers (since SMT-solvers do not seem to
+ // appreciate triggers with let-binders)
+ VCExpr newBody = Mutate(node.Body, state);
+
+ // Check whether any of the extracted terms contain variables
+ // bound by this quantifier. In this case, we have to add
+ // let-binders and remove the extracted terms
+ bool cont = true;
+ while (cont) {
+ List<VCExprLetBinding/*!*/>/*!*/ localBindings =
+ RemoveBindingsWithVars(node.BoundVars, node.TypeParameters);
+ Contract.Assert(cce.NonNullElements(localBindings));
+ if (localBindings.Count > 0)
+ newBody = AddBindings(localBindings, newBody, state);
+ else
+ cont = false;
+ }
+
+ return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars, node.Triggers, node.Infos, newBody);
+ }
+
+ public override VCExpr Visit(VCExprLet node, FlattenerState state){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (state.InTerm)
+ return GetVarFor(node);
+
+ VCExprLet prelimRes = (VCExprLet)cce.NonNull(base.Visit(node, state));
+
+ List<VCExprLetBinding/*!*/>/*!*/ allBindings = new List<VCExprLetBinding/*!*/> ();
+ allBindings.AddRange(prelimRes);
+
+ // Check whether any of the extracted terms contain variables
+ // bound by this binder. In this case, we have to add
+ // let-binders and remove the extracted terms
+ bool cont = true;
+ while (cont) {
+ List<VCExprLetBinding/*!*/>/*!*/ localBindings =
+ RemoveBindingsWithVars(prelimRes.BoundVars, new List<TypeVariable/*!*/>());
+ if (localBindings.Count > 0)
+ allBindings.AddRange(FlattenBindings(localBindings, state));
+ else
+ cont = false;
+ }
+
+ return Gen.Let(allBindings, prelimRes.Body);
+ }
+
+ }
+
} \ No newline at end of file
diff --git a/Source/VCExpr/TypeErasure.cs b/Source/VCExpr/TypeErasure.cs
index 6fb38c27..c2d99d77 100644
--- a/Source/VCExpr/TypeErasure.cs
+++ b/Source/VCExpr/TypeErasure.cs
@@ -1,1710 +1,1710 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// different classes for erasing complex types in VCExprs, replacing them
-// with axioms that can be handled by theorem provers and SMT solvers
-
-namespace Microsoft.Boogie.TypeErasure {
- using Microsoft.Boogie.VCExprAST;
-
- // some functionality that is needed in many places (and that should
- // really be provided by the Spec# container classes; maybe one
- // could integrate the functions in a nicer way?)
- public class HelperFuns {
-
- public static Function BoogieFunction(string name, List<TypeVariable/*!*/>/*!*/ typeParams, params Type[] types) {
- Contract.Requires(types != null);
- Contract.Requires(name != null);
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(types.Length > 0);
- Contract.Requires(Contract.ForAll(0, types.Length, i => types[i] != null));
- Contract.Ensures(Contract.Result<Function>() != null);
-
- List<Variable> args = new List<Variable>();
- for (int i = 0; i < types.Length - 1; ++i)
- args.Add(new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "arg" + i, cce.NonNull(types[i])),
- true));
- Formal result = new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "res",
- cce.NonNull(types)[types.Length - 1]),
- false);
- return new Function(Token.NoToken, name, new List<TypeVariable>(typeParams), args, result);
- }
-
- public static Function BoogieFunction(string name, params Type[] types) {
- Contract.Requires(types != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return BoogieFunction(name, new List<TypeVariable/*!*/>(), types);
- }
-
- // boogie function where all arguments and the result have the same type U
- public static Function UniformBoogieFunction(string name, int arity, Type U) {
- Contract.Requires(U != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Type[]/*!*/ types = new Type[arity + 1];
- for (int i = 0; i < arity + 1; ++i)
- types[i] = U;
- return BoogieFunction(name, types);
- }
-
- public static List<VCExprVar/*!*/>/*!*/ GenVarsForInParams(Function fun, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(fun != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar/*!*/>/*!*/ arguments = new List<VCExprVar/*!*/>(fun.InParams.Count);
- foreach (Formal/*!*/ f in fun.InParams) {
- Contract.Assert(f != null);
- VCExprVar/*!*/ var = gen.Variable(f.Name, f.TypedIdent.Type);
- arguments.Add(var);
- }
- return arguments;
- }
-
- public static List<T/*!*/>/*!*/ ToList<T>(params T[] args) where T : class{
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<T>>()));
- return new List<T>(args);
- }
-
- public static List<VCExpr/*!*/>/*!*/ ToVCExprList(List<VCExprVar/*!*/>/*!*/ list) {
- Contract.Requires(cce.NonNullElements(list));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- return new List<VCExpr>(list);
- }
-
- public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, int num, Type type, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(type != null);
- Contract.Requires(baseName != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(num);
- for (int i = 0; i < num; ++i)
- res.Add(gen.Variable(baseName + i, type));
- return res;
- }
-
- public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, List<Type/*!*/>/*!*/ types, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(baseName != null);
- Contract.Requires(cce.NonNullElements(types));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(types.Count);
- for (int i = 0; i < types.Count; ++i)
- res.Add(gen.Variable(baseName + i, types[i]));
- return res;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal struct TypeCtorRepr {
- // function that represents the application of the type constructor
- // to smaller types
- public readonly Function/*!*/ Ctor;
- // left-inverse functions that extract the subtypes of a compound type
- public readonly List<Function/*!*/>/*!*/ Dtors;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Ctor != null);
- Contract.Invariant(cce.NonNullElements(Dtors));
- }
-
-
- public TypeCtorRepr(Function ctor, List<Function/*!*/>/*!*/ dtors) {
- Contract.Requires(ctor != null);
- Contract.Requires(cce.NonNullElements(dtors));
- Contract.Requires(ctor.InParams.Count == dtors.Count);
- this.Ctor = ctor;
- this.Dtors = dtors;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // The class responsible for creating and keeping track of all
- // axioms related to the type system. This abstract class is made
- // concrete in two subclasses, one for type erasure with type
- // premisses in quantifiers (the semantic approach), and one for
- // type erasure with explicit type arguments of polymorphic
- // functions (the syntacted approach).
- [ContractClass(typeof(TypeAxiomBuilderContracts))]
- public abstract class TypeAxiomBuilder : ICloneable {
-
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(Ctor != null);
-
- }
-
-
- internal abstract MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
- get;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Type Axioms
-
- // list in which all typed axioms are collected
- private readonly List<VCExpr/*!*/>/*!*/ AllTypeAxioms;
- [ContractInvariantMethod]
- void AllTypeAxiomsInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(AllTypeAxioms));
- }
-
- // list in which type axioms are incrementally collected
- private readonly List<VCExpr/*!*/>/*!*/ IncTypeAxioms;
- [ContractInvariantMethod]
- void IncTypeAxiomsInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(IncTypeAxioms));
- }
-
- internal void AddTypeAxiom(VCExpr axiom) {
- Contract.Requires(axiom != null);
- AllTypeAxioms.Add(axiom);
- IncTypeAxioms.Add(axiom);
- }
-
- // Return all axioms that were added since the last time NewAxioms
- // was called
- public VCExpr GetNewAxioms() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ res = Gen.NAry(VCExpressionGenerator.AndOp, IncTypeAxioms);
- IncTypeAxioms.Clear();
- return res;
- }
-
- // mapping from a type to its constructor number/index
- private readonly Function/*!*/ Ctor;
- private BigNum CurrentCtorNum;
-
- private VCExpr GenCtorAssignment(VCExpr typeRepr) {
- Contract.Requires(typeRepr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None)
- return VCExpressionGenerator.True;
-
- VCExpr res = Gen.Eq(Gen.Function(Ctor, typeRepr),
- Gen.Integer(CurrentCtorNum));
- CurrentCtorNum = CurrentCtorNum + BigNum.ONE;
- return res;
- }
-
- private VCExpr GenCtorAssignment(Function typeRepr) {
- Contract.Requires(typeRepr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None)
- return VCExpressionGenerator.True;
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(typeRepr, Gen);
- VCExpr/*!*/ eq =
- GenCtorAssignment(Gen.Function(typeRepr,
- HelperFuns.ToVCExprList(quantifiedVars)));
-
- if (typeRepr.InParams.Count == 0)
- return eq;
-
- return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(),
- "ctor:" + typeRepr.Name, -1, eq);
- }
-
- // generate an axiom (forall x0, x1, ... :: invFun(fun(x0, x1, ...) == xi)
- protected VCExpr GenLeftInverseAxiom(Function fun, Function invFun, int dtorNum) {
- Contract.Requires(invFun != null);
- Contract.Requires(fun != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(fun, Gen);
- Contract.Assert(cce.NonNullElements(quantifiedVars));
-
- VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(quantifiedVars));
- VCExpr/*!*/ lhs = Gen.Function(invFun, funApp);
- VCExpr/*!*/ rhs = quantifiedVars[dtorNum];
- VCExpr/*!*/ eq = Gen.Eq(lhs, rhs);
-
- List<VCTrigger/*!*/>/*!*/ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
- Contract.Assert(cce.NonNullElements(triggers));
- return Gen.Forall(quantifiedVars, triggers, "typeInv:" + invFun.Name, -1, eq);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- // the type of everything that is not int, bool, or a type
- [ContractInvariantMethod]
- void ObjectInvariant2() {
- Contract.Invariant(UDecl != null);
- Contract.Invariant(TDecl != null);
- Contract.Invariant(U != null);
- Contract.Invariant(T != null);
- }
-
- private readonly TypeCtorDecl/*!*/ UDecl;
- public readonly Type/*!*/ U;
-
- // the type of types
- private readonly TypeCtorDecl/*!*/ TDecl;
- public readonly Type/*!*/ T;
-
- public abstract Type/*!*/ TypeAfterErasure(Type/*!*/ type);
- [Pure]
- public abstract bool UnchangedType(Type/*!*/ type);
-
- ///////////////////////////////////////////////////////////////////////////
- // Symbols for representing types
-
- private readonly IDictionary<Type/*!*/, VCExpr/*!*/>/*!*/ BasicTypeReprs;
- [ContractInvariantMethod]
- void BasicTypeReprsInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(BasicTypeReprs));
- }
-
- private VCExpr GetBasicTypeRepr(Type type) {
- Contract.Requires(type != null);
- Contract.Requires(type.IsBasic || type.IsBv);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr res;
- if (!BasicTypeReprs.TryGetValue(type, out res)) {
- res = Gen.Function(HelperFuns.BoogieFunction(type.ToString() + "Type", T));
- AddTypeAxiom(GenCtorAssignment(res));
- BasicTypeReprs.Add(type, res);
- }
- return cce.NonNull(res);
- }
-
- private readonly IDictionary<TypeCtorDecl/*!*/, TypeCtorRepr/*!*/>/*!*/ TypeCtorReprs;
- [ContractInvariantMethod]
- void TypeCtorReprsInvariantMethod() {
- Contract.Invariant(TypeCtorReprs != null);
- }
-
- internal TypeCtorRepr GetTypeCtorReprStruct(TypeCtorDecl decl) {
- Contract.Requires(decl != null);
- TypeCtorRepr reprSet;
- if (!TypeCtorReprs.TryGetValue(decl, out reprSet)) {
- Function/*!*/ ctor = HelperFuns.UniformBoogieFunction(decl.Name + "Type", decl.Arity, T);
- Contract.Assert(ctor != null);
- AddTypeAxiom(GenCtorAssignment(ctor));
-
- List<Function/*!*/>/*!*/ dtors = new List<Function/*!*/>(decl.Arity);
- for (int i = 0; i < decl.Arity; ++i) {
- Function/*!*/ dtor = HelperFuns.UniformBoogieFunction(decl.Name + "TypeInv" + i, 1, T);
- dtors.Add(dtor);
- AddTypeAxiom(GenLeftInverseAxiom(ctor, dtor, i));
- }
-
- reprSet = new TypeCtorRepr(ctor, dtors);
- TypeCtorReprs.Add(decl, reprSet);
- }
-
- return reprSet;
- }
-
- public Function GetTypeCtorRepr(TypeCtorDecl decl) {
- Contract.Requires(decl != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCtorReprStruct(decl).Ctor;
- }
-
- public Function GetTypeDtor(TypeCtorDecl decl, int num) {
- Contract.Requires(decl != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCtorReprStruct(decl).Dtors[num];
- }
-
- // mapping from free type variables to VCExpr variables
- private readonly IDictionary<TypeVariable/*!*/, VCExprVar/*!*/>/*!*/ TypeVariableMapping;
- [ContractInvariantMethod]
- void TypeVariableMappingInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableMapping));
- }
-
- public VCExprVar Typed2Untyped(TypeVariable var) {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res;
- if (!TypeVariableMapping.TryGetValue(var, out res)) {
- res = new VCExprVar(var.Name, T);
- TypeVariableMapping.Add(var, res);
- }
- return cce.NonNull(res);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Symbols for representing variables and constants
-
- // Globally defined variables
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ Typed2UntypedVariables;
- [ContractInvariantMethod]
- void Typed2UntypedVariablesInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedVariables));
- }
-
- // This method must only be used for free (unbound) variables
- public VCExprVar Typed2Untyped(VCExprVar var) {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res = TryTyped2Untyped(var);
- if (res == null) {
- res = Gen.Variable(var.Name, TypeAfterErasure(var.Type));
- Typed2UntypedVariables.Add(var, res);
- AddVarTypeAxiom(res, var.Type);
- }
- return cce.NonNull(res);
- }
-
- /// <summary>
- /// This method is like Typed2Untyped, except in the case where the given variables
- /// doesn't exist in the mapping. For that case, this method returns null whereas
- /// Typed2Untyped creates a new variable that it adds to the mapping.
- /// </summary>
- /// <param name="var"></param>
- /// <returns></returns>
- public VCExprVar TryTyped2Untyped(VCExprVar var) {
- Contract.Requires(var != null);
- VCExprVar res;
- if (Typed2UntypedVariables.TryGetValue(var, out res)) {
- return res;
- } else {
- return null;
- }
- }
-
- protected abstract void AddVarTypeAxiom(VCExprVar/*!*/ var, Type/*!*/ originalType);
-
- ///////////////////////////////////////////////////////////////////////////
- // Translation function from types to their term representation
-
- public VCExpr Type2Term(Type type, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
- Contract.Requires(type != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- //
- if (type.IsBasic || type.IsBv) {
- //
- return GetBasicTypeRepr(type);
- //
- } else if (type.IsCtor) {
- //
- CtorType ctype = type.AsCtor;
- Function/*!*/ repr = GetTypeCtorRepr(ctype.Decl);
- List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>(ctype.Arguments.Count);
- foreach (Type/*!*/ t in ctype.Arguments.ToArray()) {
- Contract.Assert(t != null);
- args.Add(Type2Term(t, varMapping));
- }
- return Gen.Function(repr, args);
- //
- } else if (type.IsVariable) {
- //
- VCExpr res;
- if (!varMapping.TryGetValue(type.AsVariable, out res))
- // then the variable is free and we bind it at this point to a term
- // variable
- res = Typed2Untyped(type.AsVariable);
- return cce.NonNull(res);
- //
- } else if (type.IsMap) {
- //
- return Type2Term(MapTypeAbstracter.AbstractMapType(type.AsMap), varMapping);
- //
- } else {
- System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + type);
- Contract.Assert(false);
- throw new cce.UnreachableException(); // please the compiler
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public TypeAxiomBuilder(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- this.Gen = gen;
- AllTypeAxioms = new List<VCExpr/*!*/>();
- IncTypeAxioms = new List<VCExpr/*!*/>();
- BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>();
- CurrentCtorNum = BigNum.ZERO;
- TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>();
- TypeVariableMapping = new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>();
- Typed2UntypedVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
-
- TypeCtorDecl/*!*/ uDecl = new TypeCtorDecl(Token.NoToken, "U", 0);
- UDecl = uDecl;
- Type/*!*/ u = new CtorType(Token.NoToken, uDecl, new List<Type>());
- U = u;
-
- TypeCtorDecl/*!*/ tDecl = new TypeCtorDecl(Token.NoToken, "T", 0);
- TDecl = tDecl;
- Type/*!*/ t = new CtorType(Token.NoToken, tDecl, new List<Type>());
- T = t;
-
- Ctor = HelperFuns.BoogieFunction("Ctor", t, Type.Int);
- }
-
- public virtual void Setup() {
- GetBasicTypeRepr(Type.Int);
- GetBasicTypeRepr(Type.Real);
- GetBasicTypeRepr(Type.Bool);
- }
-
- // constructor to allow cloning
- internal TypeAxiomBuilder(TypeAxiomBuilder builder) {
- Contract.Requires(builder != null);
- Gen = builder.Gen;
- AllTypeAxioms = new List<VCExpr/*!*/>(builder.AllTypeAxioms);
- IncTypeAxioms = new List<VCExpr/*!*/>(builder.IncTypeAxioms);
-
- UDecl = builder.UDecl;
- U = builder.U;
-
- TDecl = builder.TDecl;
- T = builder.T;
-
- Ctor = builder.Ctor;
- CurrentCtorNum = builder.CurrentCtorNum;
-
- BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>(builder.BasicTypeReprs);
- TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>(builder.TypeCtorReprs);
-
- TypeVariableMapping =
- new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>(builder.TypeVariableMapping);
- Typed2UntypedVariables =
- new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(builder.Typed2UntypedVariables);
- }
-
- public abstract Object/*!*/ Clone();
- }
-
- [ContractClassFor(typeof(TypeAxiomBuilder))]
- public abstract class TypeAxiomBuilderContracts : TypeAxiomBuilder {
- public TypeAxiomBuilderContracts()
- : base((VCExpressionGenerator)null) {
- }
- internal override MapTypeAbstractionBuilder MapTypeAbstracter {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
- throw new NotImplementedException();
- }
- }
-
- public override Type TypeAfterErasure(Type type) {
- Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
-
- public override bool UnchangedType(Type type) {
- Contract.Requires(type != null);
- throw new NotImplementedException();
- }
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- Contract.Requires(var != null);
- Contract.Requires(originalType != null);
- throw new NotImplementedException();
- }
-
- public override object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
-
- throw new NotImplementedException();
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // Subclass of the TypeAxiomBuilder that provides all functionality
- // to deal with native sorts of a theorem prover (that are the only
- // types left after erasing all other types). Currently, these are:
- //
- // U ... sort of all individuals/objects/values
- // T ... sort of all types
- // int ... integers
- // bool ... booleans
-
- [ContractClass(typeof(TypeAxiomBuilderIntBoolUContracts))]
- public abstract class TypeAxiomBuilderIntBoolU : TypeAxiomBuilder {
-
- public TypeAxiomBuilderIntBoolU(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>();
- }
-
- // constructor to allow cloning
- internal TypeAxiomBuilderIntBoolU(TypeAxiomBuilderIntBoolU builder)
- : base(builder) {
- Contract.Requires(builder != null);
-
- TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>(builder.TypeCasts);
- }
-
- public override void Setup() {
- base.Setup();
-
- GetTypeCasts(Type.Int);
- GetTypeCasts(Type.Real);
- GetTypeCasts(Type.Bool);
- }
-
- // generate inverse axioms for casts (castToU(castFromU(x)) = x, under certain premisses)
- protected abstract VCExpr/*!*/ GenReverseCastAxiom(Function/*!*/ castToU, Function/*!*/ castFromU);
-
- protected VCExpr GenReverseCastEq(Function castToU, Function castFromU, out VCExprVar var, out List<VCTrigger/*!*/>/*!*/ triggers) {
- Contract.Requires((castFromU != null));
- Contract.Requires((castToU != null));
- Contract.Ensures((cce.NonNullElements(Contract.ValueAtReturn(out triggers))));
- Contract.Ensures(Contract.ValueAtReturn(out var) != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- var = Gen.Variable("x", U);
-
- VCExpr inner = Gen.Function(castFromU, var);
- VCExpr lhs = Gen.Function(castToU, inner);
- triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(inner)));
-
- return Gen.Eq(lhs, var);
- }
-
- protected abstract VCExpr/*!*/ GenCastTypeAxioms(Function/*!*/ castToU, Function/*!*/ castFromU);
-
- ///////////////////////////////////////////////////////////////////////////
- // storage of type casts for types that are supposed to be left over in the
- // VCs (like int, bool, bitvectors)
-
- private readonly IDictionary<Type/*!*/, TypeCastSet/*!*/>/*!*/ TypeCasts;
- [ContractInvariantMethod]
- void TypeCastsInvariantMethod() {
- Contract.Invariant(TypeCasts != null);
- }
-
- private TypeCastSet GetTypeCasts(Type type) {
- Contract.Requires(type != null);
- TypeCastSet res;
- if (!TypeCasts.TryGetValue(type, out res)) {
- Function/*!*/ castToU = HelperFuns.BoogieFunction(type.ToString() + "_2_U", type, U);
- Function/*!*/ castFromU = HelperFuns.BoogieFunction("U_2_" + type.ToString(), U, type);
-
- AddTypeAxiom(GenLeftInverseAxiom(castToU, castFromU, 0));
- AddTypeAxiom(GenReverseCastAxiom(castToU, castFromU));
- AddTypeAxiom(GenCastTypeAxioms(castToU, castFromU));
-
- res = new TypeCastSet(castToU, castFromU);
- TypeCasts.Add(type, res);
- }
- return res;
- }
- [Pure]
- public Function CastTo(Type type) {
- Contract.Requires(type != null);
- Contract.Requires(UnchangedType(type));
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCasts(type).CastFromU;
- }
-
- public Function CastFrom(Type type) {
- Contract.Requires(type != null);
- Contract.Requires((UnchangedType(type)));
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCasts(type).CastToU;
- }
-
- private struct TypeCastSet {
- public readonly Function/*!*/ CastToU;
- public readonly Function/*!*/ CastFromU;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(CastToU != null);
- Contract.Invariant(CastFromU != null);
- }
-
-
- public TypeCastSet(Function castToU, Function castFromU) {
- Contract.Requires(castFromU != null);
- Contract.Requires(castToU != null);
- CastToU = castToU;
- CastFromU = castFromU;
- }
- }
-
- public bool IsCast(Function fun) {
- Contract.Requires(fun != null);
- if (fun.InParams.Count != 1)
- return false;
- Type/*!*/ inType = cce.NonNull(fun.InParams[0]).TypedIdent.Type;
- if (inType.Equals(U)) {
- Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
- if (!TypeCasts.ContainsKey(outType))
- return false;
- return fun.Equals(CastTo(outType));
- } else {
- if (!TypeCasts.ContainsKey(inType))
- return false;
- Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
- if (!outType.Equals(U))
- return false;
- return fun.Equals(CastFrom(inType));
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // the only types that we allow in "untyped" expressions are U,
- // Type.Int, Type.Real, and Type.Bool
-
- public override Type TypeAfterErasure(Type type) {
- //Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- if (UnchangedType(type))
- // these types are kept
- return type;
- else
- // all other types are replaced by U
- return U;
- }
-
- [Pure]
- public override bool UnchangedType(Type type) {
- //Contract.Requires(type != null);
- return type.IsInt || type.IsReal || type.IsBool || type.IsBv || (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays);
- }
-
- public VCExpr Cast(VCExpr expr, Type toType) {
- Contract.Requires(toType != null);
- Contract.Requires(expr != null);
- Contract.Requires((expr.Type.Equals(U) || UnchangedType(expr.Type)));
- Contract.Requires((toType.Equals(U) || UnchangedType(toType)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (expr.Type.Equals(toType))
- return expr;
-
- if (toType.Equals(U)) {
- return Gen.Function(CastFrom(expr.Type), expr);
- } else {
- Contract.Assert(expr.Type.Equals(U));
- return Gen.Function(CastTo(toType), expr);
- }
- }
-
- public List<VCExpr/*!*/>/*!*/ CastSeq(List<VCExpr/*!*/>/*!*/ exprs, Type toType) {
- Contract.Requires(toType != null);
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>(exprs.Count);
- foreach (VCExpr/*!*/ expr in exprs) {
- Contract.Assert(expr != null);
- res.Add(Cast(expr, toType));
- }
- return res;
- }
-
-
- }
-
- [ContractClassFor(typeof(TypeAxiomBuilderIntBoolU))]
- public abstract class TypeAxiomBuilderIntBoolUContracts : TypeAxiomBuilderIntBoolU {
- public TypeAxiomBuilderIntBoolUContracts()
- : base((TypeAxiomBuilderIntBoolU)null) {
- }
- protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
- Contract.Requires(castToU != null);
- Contract.Requires(castFromU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- throw new NotImplementedException();
- }
-
- protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
- Contract.Requires(castFromU != null);
- Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- throw new NotImplementedException();
- }
-
- internal override MapTypeAbstractionBuilder MapTypeAbstracter {
- get {
- throw new NotImplementedException();
- }
- }
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- throw new NotImplementedException();
- }
-
- public override object Clone() {
- throw new NotImplementedException();
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Class for computing most general abstractions of map types. An abstraction
- // of a map type t is a maptype t' in which closed proper subtypes have been replaced
- // with type variables. E.g., an abstraction of <a>[C a, int]a would be <a>[C a, b]a.
- // We subsequently consider most general abstractions as ordinary parametrised types,
- // i.e., "<a>[C a, b]a" would be considered as a type "M b" with polymorphically typed
- // access functions
- //
- // select<a,b>(M b, C a, b) returns (a)
- // store<a,b>(M b, C a, b, a) returns (M b)
- [ContractClass(typeof(MapTypeAbstractionBuilderContracts))]
- internal abstract class MapTypeAbstractionBuilder {
-
- protected readonly TypeAxiomBuilder/*!*/ AxBuilder;
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Gen != null);
- }
-
-
- internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- this.AxBuilder = axBuilder;
- this.Gen = gen;
- AbstractionVariables = new List<TypeVariable/*!*/>();
- ClassRepresentations = new Dictionary<MapType/*!*/, MapTypeClassRepresentation>();
- }
-
- // constructor for cloning
- internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilder builder) {
- Contract.Requires(builder != null);
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- this.AxBuilder = axBuilder;
- this.Gen = gen;
- AbstractionVariables =
- new List<TypeVariable/*!*/>(builder.AbstractionVariables);
- ClassRepresentations =
- new Dictionary<MapType/*!*/, MapTypeClassRepresentation>(builder.ClassRepresentations);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Type variables used in the abstractions. We use the same variables in the
- // same order in all abstractions in order to obtain comparable abstractions
- // (equals, hashcode)
-
- private readonly List<TypeVariable/*!*/>/*!*/ AbstractionVariables;
- [ContractInvariantMethod]
- void AbstractionVariablesInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(AbstractionVariables));
- }
-
- private TypeVariable AbstractionVariable(int num) {
- Contract.Requires((num >= 0));
- Contract.Ensures(Contract.Result<TypeVariable>() != null);
- while (AbstractionVariables.Count <= num)
- AbstractionVariables.Add(new TypeVariable(Token.NoToken,
- "aVar" + AbstractionVariables.Count));
- return AbstractionVariables[num];
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // The untyped representation of a class of map types, i.e., of a map type
- // <a0, a1, ...>[A0, A1, ...] R, where the argument types and the result type
- // possibly contain free type variables. For each such class, a separate type
- // constructor and separate select/store functions are introduced.
-
- protected struct MapTypeClassRepresentation {
- public readonly TypeCtorDecl/*!*/ RepresentingType;
- public readonly Function/*!*/ Select;
- public readonly Function/*!*/ Store;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(RepresentingType != null);
- Contract.Invariant(Select != null);
- Contract.Invariant(Store != null);
- }
-
-
- public MapTypeClassRepresentation(TypeCtorDecl representingType, Function select, Function store) {
- Contract.Requires(store != null);
- Contract.Requires(select != null);
- Contract.Requires(representingType != null);
- this.RepresentingType = representingType;
- this.Select = select;
- this.Store = store;
- }
- }
-
- private readonly IDictionary<MapType/*!*/, MapTypeClassRepresentation/*!*/>/*!*/ ClassRepresentations;
- [ContractInvariantMethod]
- void ClassRepresentationsInvariantMethod() {
- Contract.Invariant(ClassRepresentations != null);
- }
-
- protected MapTypeClassRepresentation GetClassRepresentation(MapType abstractedType) {
- Contract.Requires(abstractedType != null);
- MapTypeClassRepresentation res;
- if (!ClassRepresentations.TryGetValue(abstractedType, out res)) {
- int num = ClassRepresentations.Count;
- TypeCtorDecl/*!*/ synonym =
- new TypeCtorDecl(Token.NoToken, "MapType" + num, abstractedType.FreeVariables.Count);
-
- Function/*!*/ select, store;
- GenSelectStoreFunctions(abstractedType, synonym, out select, out store);
-
- res = new MapTypeClassRepresentation(synonym, select, store);
- ClassRepresentations.Add(abstractedType, res);
- }
- return res;
- }
-
- // the actual select and store functions are generated by the
- // concrete subclasses of this class
- protected abstract void GenSelectStoreFunctions(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl, out Function/*!*/ select, out Function/*!*/ store);
-
- ///////////////////////////////////////////////////////////////////////////
-
- public Function Select(MapType rawType, out List<Type> instantiations) {
- Contract.Requires((rawType != null));
- Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return AbstractAndGetRepresentation(rawType, out instantiations).Select;
- }
-
- public Function Store(MapType rawType, out List<Type> instantiations) {
- Contract.Requires((rawType != null));
- Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return AbstractAndGetRepresentation(rawType, out instantiations).Store;
- }
-
- private MapTypeClassRepresentation
- AbstractAndGetRepresentation(MapType rawType, out List<Type> instantiations) {
- Contract.Requires((rawType != null));
- Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
- instantiations = new List<Type>();
- MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
- return GetClassRepresentation(abstraction);
- }
-
- public CtorType AbstractMapType(MapType rawType) {
- Contract.Requires(rawType != null);
- Contract.Ensures(Contract.Result<CtorType>() != null);
- List<Type>/*!*/ instantiations = new List<Type>();
- MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
-
- MapTypeClassRepresentation repr = GetClassRepresentation(abstraction);
- Contract.Assume(repr.RepresentingType.Arity == instantiations.Count);
- return new CtorType(Token.NoToken, repr.RepresentingType, instantiations);
- }
-
- // TODO: cache the result of this operation
- protected MapType ThinOutMapType(MapType rawType, List<Type> instantiations) {
- Contract.Requires(instantiations != null);
- Contract.Requires(rawType != null);
- Contract.Ensures(Contract.Result<MapType>() != null);
- List<Type>/*!*/ newArguments = new List<Type>();
- foreach (Type/*!*/ subtype in rawType.Arguments.ToList()) {
- Contract.Assert(subtype != null);
- newArguments.Add(ThinOutType(subtype, rawType.TypeParameters,
- instantiations));
- }
- Type/*!*/ newResult = ThinOutType(rawType.Result, rawType.TypeParameters,
- instantiations);
- return new MapType(Token.NoToken, rawType.TypeParameters, newArguments, newResult);
- }
-
- // the instantiations of inserted type variables, the order corresponds to the order in which "AbstractionVariable(int)" delivers variables
- private Type/*!*/ ThinOutType(Type rawType, List<TypeVariable> boundTypeParams, List<Type> instantiations) {
- Contract.Requires(instantiations != null);
- Contract.Requires(boundTypeParams != null);
- Contract.Requires(rawType != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(rawType))
- return rawType;
-
- if (rawType.FreeVariables.All(var => !boundTypeParams.Contains(var))) {
- // Bingo!
- // if the type does not contain any bound variables, we can simply
- // replace it with a type variable
- TypeVariable/*!*/ abstractionVar = AbstractionVariable(instantiations.Count);
- Contract.Assume(!boundTypeParams.Contains(abstractionVar));
- instantiations.Add(rawType);
- return abstractionVar;
- }
-
- if (rawType.IsVariable) {
- //
- // then the variable has to be bound, we cannot do anything
- TypeVariable/*!*/ rawVar = rawType.AsVariable;
- Contract.Assume(boundTypeParams.Contains(rawVar));
- return rawVar;
- //
- } else if (rawType.IsMap) {
- //
- // recursively abstract this map type and continue abstracting
- CtorType/*!*/ abstraction = AbstractMapType(rawType.AsMap);
- return ThinOutType(abstraction, boundTypeParams, instantiations);
- //
- } else if (rawType.IsCtor) {
- //
- // traverse the subtypes
- CtorType/*!*/ rawCtorType = rawType.AsCtor;
- List<Type>/*!*/ newArguments = new List<Type>();
- foreach (Type/*!*/ subtype in rawCtorType.Arguments.ToList()) {
- Contract.Assert(subtype != null);
- newArguments.Add(ThinOutType(subtype, boundTypeParams,
- instantiations));
- }
- return new CtorType(Token.NoToken, rawCtorType.Decl, newArguments);
- //
- } else {
- System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + rawType);
- return rawType; // compiler appeasement policy
- }
- }
-
- }
- [ContractClassFor(typeof(MapTypeAbstractionBuilder))]
- internal abstract class MapTypeAbstractionBuilderContracts : MapTypeAbstractionBuilder {
- public MapTypeAbstractionBuilderContracts()
- : base(null, null) {
- }
- protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonymDecl, out Function select, out Function store) {
- Contract.Requires(abstractedType != null);
- Contract.Requires(synonymDecl != null);
- Contract.Ensures(Contract.ValueAtReturn(out select) != null);
- Contract.Ensures(Contract.ValueAtReturn(out store) != null);
-
- throw new NotImplementedException();
- }
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class VariableBindings {
- public readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ VCExprVarBindings;
- public readonly IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ TypeVariableBindings;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(VCExprVarBindings));
- Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableBindings));
- }
-
-
- public VariableBindings(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ vcExprVarBindings,
- IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ typeVariableBindings) {
- Contract.Requires(cce.NonNullDictionaryAndValues(vcExprVarBindings));
- Contract.Requires(cce.NonNullDictionaryAndValues(typeVariableBindings));
- this.VCExprVarBindings = vcExprVarBindings;
- this.TypeVariableBindings = typeVariableBindings;
- }
-
- public VariableBindings() :
- this(new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(),
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()) {
- }
-
- public VariableBindings Clone() {
- Contract.Ensures(Contract.Result<VariableBindings>() != null);
- IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ newVCExprVarBindings =
- new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
- foreach (KeyValuePair<VCExprVar/*!*/, VCExprVar/*!*/> pair in VCExprVarBindings) {
- Contract.Assert(cce.NonNullElements(pair));
- newVCExprVarBindings.Add(pair);
- }
- IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ newTypeVariableBindings =
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>();
- foreach (KeyValuePair<TypeVariable/*!*/, VCExpr/*!*/> pair in TypeVariableBindings) {
- Contract.Assert(cce.NonNullElements(pair));
- newTypeVariableBindings.Add(pair);
- }
- return new VariableBindings(newVCExprVarBindings, newTypeVariableBindings);
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // The central class for turning types VCExprs into untyped
- // VCExprs. This class makes use of the type axiom builder to manage
- // the available types and symbols.
- [ContractClass(typeof(TypeEraserContracts))]
- public abstract class TypeEraser : MutatingVCExprVisitor<VariableBindings/*!*/> {
-
- protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilder != null);
- }
-
-
- protected abstract OpTypeEraser/*!*/ OpEraser {
- get;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public TypeEraser(TypeAxiomBuilderIntBoolU axBuilder, VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- AxBuilder = axBuilder;
- }
-
- public VCExpr Erase(VCExpr expr, int polarity) {
- Contract.Requires(expr != null);
- Contract.Requires((polarity >= -1 && polarity <= 1));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- this.Polarity = polarity;
- return Mutate(expr, new VariableBindings());
- }
-
- internal int Polarity = 1; // 1 for positive, -1 for negative, 0 for both
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLiteral node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assume(node.Type == Type.Bool || node.Type == Type.Int || node.Type == Type.Real);
- return node;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override bool AvoidVisit(VCExprNAry node, VariableBindings arg)
- {
- return node.Op.Equals(VCExpressionGenerator.AndOp) ||
- node.Op.Equals(VCExpressionGenerator.OrOp);
- }
-
- public override VCExpr Visit(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprOp/*!*/ op = node.Op;
- if (op == VCExpressionGenerator.AndOp || op == VCExpressionGenerator.OrOp)
- // more efficient on large conjunctions/disjunctions
- return base.Visit(node, bindings);
-
- // the visitor that handles all other operators
- return node.Accept<VCExpr/*!*/, VariableBindings/*!*/>(OpEraser, bindings);
- }
-
- // this method is called by MutatingVCExprVisitor.Visit(VCExprNAry, ...)
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VariableBindings/*!*/ bindings) {
- //Contract.Requires(originalNode != null);
- //Contract.Requires(cce.NonNullElements(newSubExprs));
- //Contract.Requires(bindings != null);
- Contract.Assume(originalNode.Op == VCExpressionGenerator.AndOp ||
- originalNode.Op == VCExpressionGenerator.OrOp);
- return Gen.Function(originalNode.Op,
- AxBuilder.Cast(newSubExprs[0], Type.Bool),
- AxBuilder.Cast(newSubExprs[1], Type.Bool));
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprVar node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprVar res;
- if (!bindings.VCExprVarBindings.TryGetValue(node, out res))
- return AxBuilder.Typed2Untyped(node);
- return cce.NonNull(res);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected bool IsUniversalQuantifier(VCExprQuantifier node) {
- Contract.Requires(node != null);
- return Polarity == 1 && node.Quan == Quantifier.EX ||
- Polarity == -1 && node.Quan == Quantifier.ALL;
- }
-
- protected List<VCExprVar/*!*/>/*!*/ BoundVarsAfterErasure(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
- // the mapping between old and new variables
- // is added to this bindings-object
- VariableBindings/*!*/ bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(cce.NonNullElements(oldBoundVars));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
-
- List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
- foreach (VCExprVar/*!*/ var in oldBoundVars) {
- Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- newBoundVars.Add(newVar);
- bindings.VCExprVarBindings.Add(var, newVar);
- }
- return newBoundVars;
- }
-
- // We check whether casts Int2U or Bool2U on the bound variables
- // occur in triggers. In case a trigger like f(Int2U(x)) occurs,
- // it may be better to give variable x the type U and remove the
- // cast. The following method returns true if the quantifier
- // should be translated again with a different typing
- protected bool RedoQuantifier(VCExprQuantifier/*!*/ node,
- VCExprQuantifier/*!*/ newNode,
- // the bound vars that actually occur in the body or
- // in any of the triggers
- List<VCExprVar/*!*/>/*!*/ occurringVars,
- VariableBindings/*!*/ oldBindings,
- out VariableBindings/*!*/ newBindings,
- out List<VCExprVar/*!*/>/*!*/ newBoundVars) {
- Contract.Requires(node != null);
- Contract.Requires(newNode != null);
- Contract.Requires(cce.NonNullElements(occurringVars));
- Contract.Requires(oldBindings != null);
- Contract.Ensures(Contract.ValueAtReturn(out newBindings) != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out newBoundVars)));
- List<VCExprVar/*!*/> castVariables =
- VariableCastCollector.FindCastVariables(node, newNode, AxBuilder);
- if (castVariables.Count == 0) {
- newBindings = oldBindings; // to make the compiler happy
- newBoundVars = newNode.BoundVars; // to make the compiler happy
- return false;
- }
-
- // redo everything with a different typing ...
-
- newBindings = oldBindings.Clone();
- newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Contract.Assert(var != null);
- Type/*!*/ newType =
- castVariables.Contains(var) ? AxBuilder.U
- : AxBuilder.TypeAfterErasure(var.Type);
- Contract.Assert(newType != null);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- Contract.Assert(newVar != null);
- newBoundVars.Add(newVar);
- newBindings.VCExprVarBindings.Add(var, newVar);
- }
-
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLet node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VariableBindings/*!*/ newVarBindings = bindings.Clone();
-
- List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- newBoundVars.Add(newVar);
- newVarBindings.VCExprVarBindings.Add(var, newVar);
- }
-
- List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>(node.Length);
- for (int i = 0; i < node.Length; ++i) {
- VCExprLetBinding/*!*/ binding = node[i];
- Contract.Assert(binding != null);
- VCExprVar/*!*/ newVar = newBoundVars[i];
- Type/*!*/ newType = newVar.Type;
-
- VCExpr/*!*/ newE = AxBuilder.Cast(Mutate(binding.E, newVarBindings), newType);
- newbindings.Add(Gen.LetBinding(newVar, newE));
- }
-
- VCExpr/*!*/ newbody = Mutate(node.Body, newVarBindings);
- return Gen.Let(newbindings, newbody);
- }
- }
-
- [ContractClassFor(typeof(TypeEraser))]
- public abstract class TypeEraserContracts : TypeEraser {
- public TypeEraserContracts()
- : base(null, null) {
- }
- protected override OpTypeEraser OpEraser {
- get {
- Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
- throw new NotImplementedException();
- }
- }
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
-
- public abstract class OpTypeEraser : StandardVCExprOpVisitor<VCExpr/*!*/, VariableBindings/*!*/> {
-
- protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
-
- protected readonly TypeEraser/*!*/ Eraser;
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Eraser != null);
- Contract.Invariant(Gen != null);
- }
-
-
- public OpTypeEraser(TypeEraser/*!*/ eraser, TypeAxiomBuilderIntBoolU/*!*/ axBuilder, VCExpressionGenerator/*!*/ gen) {
- Contract.Requires(eraser != null);
- Contract.Requires(axBuilder != null);
- Contract.Requires(gen != null);
- this.AxBuilder = axBuilder;
- this.Eraser = eraser;
- this.Gen = gen;
- }
-
- protected override VCExpr StandardResult(VCExprNAry node, VariableBindings bindings) {
- //Contract.Requires(bindings != null);
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- System.Diagnostics.Debug.Fail("Don't know how to erase types in this expression: " + node);
- Contract.Assert(false);
- throw new cce.UnreachableException(); // to please the compiler
- }
-
- private List<VCExpr/*!*/>/*!*/ MutateSeq(VCExprNAry node, VariableBindings bindings, int newPolarity) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = newPolarity;
- List<VCExpr/*!*/>/*!*/ newArgs = Eraser.MutateSeq(node, bindings);
- Eraser.Polarity = oldPolarity;
- return newArgs;
- }
-
- private VCExpr CastArguments(VCExprNAry node, Type argType, VariableBindings bindings, int newPolarity) {
- Contract.Requires(bindings != null);
- Contract.Requires(argType != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Function(node.Op,
- AxBuilder.CastSeq(MutateSeq(node, bindings, newPolarity),
- argType));
- }
-
- // Cast the arguments of the node to their old type if necessary and possible; otherwise use
- // their new type (int, real, bool, or U)
- private VCExpr CastArgumentsToOldType(VCExprNAry node, VariableBindings bindings, int newPolarity) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Requires((node.Arity > 0));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, newPolarity);
- Type/*!*/ oldType = node[0].Type;
- if (AxBuilder.UnchangedType(oldType) &&
- node.Skip(1).All(e => e.Type.Equals(oldType)))
- return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, oldType));
- else
- return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, AxBuilder.U));
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- public override VCExpr VisitNotOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Bool, bindings, -Eraser.Polarity);
- }
- public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitImpliesOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(2);
- Eraser.Polarity = -Eraser.Polarity;
- newArgs.Add(Eraser.Mutate(node[0], bindings));
- Eraser.Polarity = -Eraser.Polarity;
- newArgs.Add(Eraser.Mutate(node[1], bindings));
- return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, Type.Bool));
- }
- public override VCExpr VisitDistinctOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitLabelOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // argument of the label operator should always be a formula
- // (at least for Simplify ... should this be ensured at a later point?)
- return CastArguments(node, Type.Bool, bindings, Eraser.Polarity);
- }
- public override VCExpr VisitIfThenElseOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
- newArgs[0] = AxBuilder.Cast(newArgs[0], Type.Bool);
- Type t = node.Type;
- if (!AxBuilder.UnchangedType(t)) {
- t = AxBuilder.U;
- }
- newArgs[1] = AxBuilder.Cast(newArgs[1], t);
- newArgs[2] = AxBuilder.Cast(newArgs[2], t);
- return Gen.Function(node.Op, newArgs);
- }
- public override VCExpr/*!*/ VisitCustomOp(VCExprNAry/*!*/ node, VariableBindings/*!*/ bindings) {
- Contract.Requires(node != null);
- Contract.Requires(bindings != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
- return Gen.Function(node.Op, newArgs);
- }
- public override VCExpr VisitAddOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, node.Type, bindings, 0);
- }
- public override VCExpr VisitSubOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, node.Type, bindings, 0);
- }
- public override VCExpr VisitMulOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, node.Type, bindings, 0);
- }
- public override VCExpr VisitDivOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
- }
- public override VCExpr VisitModOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
- }
- public override VCExpr VisitRealDivOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Real, bindings, 0);
- }
- /*public override VCExpr VisitFloatDivOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Float, bindings, 0);
- }*/
- public override VCExpr VisitPowOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Real, bindings, 0);
- }
- public override VCExpr VisitLtOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitLeOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitGtOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitGeOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, AxBuilder.U, bindings, 0);
- }
- public override VCExpr VisitToIntOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitToRealOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatAddOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatSubOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatMulOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatDivOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatRemOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatMinOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatMaxOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatLeqOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatLtOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatGeqOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatGtOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitFloatEqOp(VCExprNAry node, VariableBindings bindings)
- {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitBvOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitBvExtractOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitBvConcatOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
-
- // each argument is cast to its old type
- Contract.Assert(newArgs.Count == node.Arity && newArgs.Count == 2);
- VCExpr/*!*/ arg0 = AxBuilder.Cast(newArgs[0], node[0].Type);
- Contract.Assert(arg0 != null);
- VCExpr/*!*/ arg1 = AxBuilder.Cast(newArgs[1], node[1].Type);
- Contract.Assert(arg1 != null);
- return Gen.Function(node.Op, arg0, arg1);
- }
-
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// Collect all variables x occurring in expressions of the form Int2U(x) or Bool2U(x), and
- /// collect all variables x occurring outside such forms.
- /// </summary>
- internal class VariableCastCollector : TraversingVCExprVisitor<bool, bool> {
- /// <summary>
- /// Determine those bound variables in "oldNode" <em>all</em> of whose relevant uses
- /// have to be cast in potential triggers in "newNode". It is assume that
- /// the bound variables of "oldNode" correspond to the first bound
- /// variables of "newNode".
- /// </summary>
- public static List<VCExprVar/*!*/>/*!*/ FindCastVariables(VCExprQuantifier oldNode, VCExprQuantifier newNode, TypeAxiomBuilderIntBoolU axBuilder) {
- Contract.Requires((axBuilder != null));
- Contract.Requires((newNode != null));
- Contract.Requires((oldNode != null));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- VariableCastCollector/*!*/ collector = new VariableCastCollector(axBuilder);
- Contract.Assert(collector != null);
- if (newNode.Triggers.Any(trigger => trigger.Pos)) {
- // look in the given triggers
- foreach (VCTrigger/*!*/ trigger in newNode.Triggers) {
- Contract.Assert(trigger != null);
- if (trigger.Pos) {
- foreach (VCExpr/*!*/ expr in trigger.Exprs) {
- Contract.Assert(expr != null);
- collector.Traverse(expr, true);
- }
- }
- }
- } else {
- // look in the body of the quantifier
- collector.Traverse(newNode.Body, true);
- }
-
- List<VCExprVar/*!*/>/*!*/ castVariables = new List<VCExprVar/*!*/>(collector.varsInCasts.Count);
- foreach (VCExprVar/*!*/ castVar in collector.varsInCasts) {
- Contract.Assert(castVar != null);
- int i = newNode.BoundVars.IndexOf(castVar);
- if (0 <= i && i < oldNode.BoundVars.Count && !collector.varsOutsideCasts.ContainsKey(castVar))
- castVariables.Add(oldNode.BoundVars[i]);
- }
- return castVariables;
- }
-
- public VariableCastCollector(TypeAxiomBuilderIntBoolU axBuilder) {
- Contract.Requires(axBuilder != null);
- this.AxBuilder = axBuilder;
- }
-
- readonly List<VCExprVar/*!*/>/*!*/ varsInCasts = new List<VCExprVar/*!*/>();
- readonly Dictionary<VCExprVar/*!*/, object>/*!*/ varsOutsideCasts = new Dictionary<VCExprVar/*!*/, object>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(varsInCasts));
- Contract.Invariant(varsOutsideCasts != null && Contract.ForAll(varsOutsideCasts, voc => voc.Key != null));
- Contract.Invariant(AxBuilder != null);
-
- }
-
-
- readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true; // not used
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- if (node.Op is VCExprBoogieFunctionOp) {
- Function func = ((VCExprBoogieFunctionOp)node.Op).Func;
- Contract.Assert(func != null);
- if ((AxBuilder.IsCast(func)) && node[0] is VCExprVar) {
- VCExprVar castVar = (VCExprVar)node[0];
- if (!varsInCasts.Contains(castVar))
- varsInCasts.Add(castVar);
- return true;
- }
- } else if (node.Op is VCExprNAryOp) {
- VCExpressionGenerator.SingletonOp op = VCExpressionGenerator.SingletonOpDict[node.Op];
- switch (op) {
- // the following operators cannot be used in triggers, so disregard any uses of variables as direct arguments
- case VCExpressionGenerator.SingletonOp.NotOp:
- case VCExpressionGenerator.SingletonOp.EqOp:
- case VCExpressionGenerator.SingletonOp.NeqOp:
- case VCExpressionGenerator.SingletonOp.AndOp:
- case VCExpressionGenerator.SingletonOp.OrOp:
- case VCExpressionGenerator.SingletonOp.ImpliesOp:
- case VCExpressionGenerator.SingletonOp.LtOp:
- case VCExpressionGenerator.SingletonOp.LeOp:
- case VCExpressionGenerator.SingletonOp.GtOp:
- case VCExpressionGenerator.SingletonOp.GeOp:
- foreach (VCExpr n in node) {
- if (!(n is VCExprVar)) { // don't recurse on VCExprVar argument
- n.Accept<bool, bool>(this, arg);
- }
- }
- return true;
- default:
- break;
- }
- }
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!varsOutsideCasts.ContainsKey(node))
- varsOutsideCasts.Add(node, null);
- return true;
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// different classes for erasing complex types in VCExprs, replacing them
+// with axioms that can be handled by theorem provers and SMT solvers
+
+namespace Microsoft.Boogie.TypeErasure {
+ using Microsoft.Boogie.VCExprAST;
+
+ // some functionality that is needed in many places (and that should
+ // really be provided by the Spec# container classes; maybe one
+ // could integrate the functions in a nicer way?)
+ public class HelperFuns {
+
+ public static Function BoogieFunction(string name, List<TypeVariable/*!*/>/*!*/ typeParams, params Type[] types) {
+ Contract.Requires(types != null);
+ Contract.Requires(name != null);
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(types.Length > 0);
+ Contract.Requires(Contract.ForAll(0, types.Length, i => types[i] != null));
+ Contract.Ensures(Contract.Result<Function>() != null);
+
+ List<Variable> args = new List<Variable>();
+ for (int i = 0; i < types.Length - 1; ++i)
+ args.Add(new Formal(Token.NoToken,
+ new TypedIdent(Token.NoToken, "arg" + i, cce.NonNull(types[i])),
+ true));
+ Formal result = new Formal(Token.NoToken,
+ new TypedIdent(Token.NoToken, "res",
+ cce.NonNull(types)[types.Length - 1]),
+ false);
+ return new Function(Token.NoToken, name, new List<TypeVariable>(typeParams), args, result);
+ }
+
+ public static Function BoogieFunction(string name, params Type[] types) {
+ Contract.Requires(types != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return BoogieFunction(name, new List<TypeVariable/*!*/>(), types);
+ }
+
+ // boogie function where all arguments and the result have the same type U
+ public static Function UniformBoogieFunction(string name, int arity, Type U) {
+ Contract.Requires(U != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Type[]/*!*/ types = new Type[arity + 1];
+ for (int i = 0; i < arity + 1; ++i)
+ types[i] = U;
+ return BoogieFunction(name, types);
+ }
+
+ public static List<VCExprVar/*!*/>/*!*/ GenVarsForInParams(Function fun, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(fun != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar/*!*/>/*!*/ arguments = new List<VCExprVar/*!*/>(fun.InParams.Count);
+ foreach (Formal/*!*/ f in fun.InParams) {
+ Contract.Assert(f != null);
+ VCExprVar/*!*/ var = gen.Variable(f.Name, f.TypedIdent.Type);
+ arguments.Add(var);
+ }
+ return arguments;
+ }
+
+ public static List<T/*!*/>/*!*/ ToList<T>(params T[] args) where T : class{
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<T>>()));
+ return new List<T>(args);
+ }
+
+ public static List<VCExpr/*!*/>/*!*/ ToVCExprList(List<VCExprVar/*!*/>/*!*/ list) {
+ Contract.Requires(cce.NonNullElements(list));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ return new List<VCExpr>(list);
+ }
+
+ public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, int num, Type type, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(type != null);
+ Contract.Requires(baseName != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(num);
+ for (int i = 0; i < num; ++i)
+ res.Add(gen.Variable(baseName + i, type));
+ return res;
+ }
+
+ public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, List<Type/*!*/>/*!*/ types, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(baseName != null);
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(types.Count);
+ for (int i = 0; i < types.Count; ++i)
+ res.Add(gen.Variable(baseName + i, types[i]));
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal struct TypeCtorRepr {
+ // function that represents the application of the type constructor
+ // to smaller types
+ public readonly Function/*!*/ Ctor;
+ // left-inverse functions that extract the subtypes of a compound type
+ public readonly List<Function/*!*/>/*!*/ Dtors;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Ctor != null);
+ Contract.Invariant(cce.NonNullElements(Dtors));
+ }
+
+
+ public TypeCtorRepr(Function ctor, List<Function/*!*/>/*!*/ dtors) {
+ Contract.Requires(ctor != null);
+ Contract.Requires(cce.NonNullElements(dtors));
+ Contract.Requires(ctor.InParams.Count == dtors.Count);
+ this.Ctor = ctor;
+ this.Dtors = dtors;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // The class responsible for creating and keeping track of all
+ // axioms related to the type system. This abstract class is made
+ // concrete in two subclasses, one for type erasure with type
+ // premisses in quantifiers (the semantic approach), and one for
+ // type erasure with explicit type arguments of polymorphic
+ // functions (the syntacted approach).
+ [ContractClass(typeof(TypeAxiomBuilderContracts))]
+ public abstract class TypeAxiomBuilder : ICloneable {
+
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(Ctor != null);
+
+ }
+
+
+ internal abstract MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
+ get;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Type Axioms
+
+ // list in which all typed axioms are collected
+ private readonly List<VCExpr/*!*/>/*!*/ AllTypeAxioms;
+ [ContractInvariantMethod]
+ void AllTypeAxiomsInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(AllTypeAxioms));
+ }
+
+ // list in which type axioms are incrementally collected
+ private readonly List<VCExpr/*!*/>/*!*/ IncTypeAxioms;
+ [ContractInvariantMethod]
+ void IncTypeAxiomsInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(IncTypeAxioms));
+ }
+
+ internal void AddTypeAxiom(VCExpr axiom) {
+ Contract.Requires(axiom != null);
+ AllTypeAxioms.Add(axiom);
+ IncTypeAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr GetNewAxioms() {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ res = Gen.NAry(VCExpressionGenerator.AndOp, IncTypeAxioms);
+ IncTypeAxioms.Clear();
+ return res;
+ }
+
+ // mapping from a type to its constructor number/index
+ private readonly Function/*!*/ Ctor;
+ private BigNum CurrentCtorNum;
+
+ private VCExpr GenCtorAssignment(VCExpr typeRepr) {
+ Contract.Requires(typeRepr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ return VCExpressionGenerator.True;
+
+ VCExpr res = Gen.Eq(Gen.Function(Ctor, typeRepr),
+ Gen.Integer(CurrentCtorNum));
+ CurrentCtorNum = CurrentCtorNum + BigNum.ONE;
+ return res;
+ }
+
+ private VCExpr GenCtorAssignment(Function typeRepr) {
+ Contract.Requires(typeRepr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ return VCExpressionGenerator.True;
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(typeRepr, Gen);
+ VCExpr/*!*/ eq =
+ GenCtorAssignment(Gen.Function(typeRepr,
+ HelperFuns.ToVCExprList(quantifiedVars)));
+
+ if (typeRepr.InParams.Count == 0)
+ return eq;
+
+ return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(),
+ "ctor:" + typeRepr.Name, -1, eq);
+ }
+
+ // generate an axiom (forall x0, x1, ... :: invFun(fun(x0, x1, ...) == xi)
+ protected VCExpr GenLeftInverseAxiom(Function fun, Function invFun, int dtorNum) {
+ Contract.Requires(invFun != null);
+ Contract.Requires(fun != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(fun, Gen);
+ Contract.Assert(cce.NonNullElements(quantifiedVars));
+
+ VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(quantifiedVars));
+ VCExpr/*!*/ lhs = Gen.Function(invFun, funApp);
+ VCExpr/*!*/ rhs = quantifiedVars[dtorNum];
+ VCExpr/*!*/ eq = Gen.Eq(lhs, rhs);
+
+ List<VCTrigger/*!*/>/*!*/ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
+ Contract.Assert(cce.NonNullElements(triggers));
+ return Gen.Forall(quantifiedVars, triggers, "typeInv:" + invFun.Name, -1, eq);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // the type of everything that is not int, bool, or a type
+ [ContractInvariantMethod]
+ void ObjectInvariant2() {
+ Contract.Invariant(UDecl != null);
+ Contract.Invariant(TDecl != null);
+ Contract.Invariant(U != null);
+ Contract.Invariant(T != null);
+ }
+
+ private readonly TypeCtorDecl/*!*/ UDecl;
+ public readonly Type/*!*/ U;
+
+ // the type of types
+ private readonly TypeCtorDecl/*!*/ TDecl;
+ public readonly Type/*!*/ T;
+
+ public abstract Type/*!*/ TypeAfterErasure(Type/*!*/ type);
+ [Pure]
+ public abstract bool UnchangedType(Type/*!*/ type);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Symbols for representing types
+
+ private readonly IDictionary<Type/*!*/, VCExpr/*!*/>/*!*/ BasicTypeReprs;
+ [ContractInvariantMethod]
+ void BasicTypeReprsInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(BasicTypeReprs));
+ }
+
+ private VCExpr GetBasicTypeRepr(Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(type.IsBasic || type.IsBv);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr res;
+ if (!BasicTypeReprs.TryGetValue(type, out res)) {
+ res = Gen.Function(HelperFuns.BoogieFunction(type.ToString() + "Type", T));
+ AddTypeAxiom(GenCtorAssignment(res));
+ BasicTypeReprs.Add(type, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ private readonly IDictionary<TypeCtorDecl/*!*/, TypeCtorRepr/*!*/>/*!*/ TypeCtorReprs;
+ [ContractInvariantMethod]
+ void TypeCtorReprsInvariantMethod() {
+ Contract.Invariant(TypeCtorReprs != null);
+ }
+
+ internal TypeCtorRepr GetTypeCtorReprStruct(TypeCtorDecl decl) {
+ Contract.Requires(decl != null);
+ TypeCtorRepr reprSet;
+ if (!TypeCtorReprs.TryGetValue(decl, out reprSet)) {
+ Function/*!*/ ctor = HelperFuns.UniformBoogieFunction(decl.Name + "Type", decl.Arity, T);
+ Contract.Assert(ctor != null);
+ AddTypeAxiom(GenCtorAssignment(ctor));
+
+ List<Function/*!*/>/*!*/ dtors = new List<Function/*!*/>(decl.Arity);
+ for (int i = 0; i < decl.Arity; ++i) {
+ Function/*!*/ dtor = HelperFuns.UniformBoogieFunction(decl.Name + "TypeInv" + i, 1, T);
+ dtors.Add(dtor);
+ AddTypeAxiom(GenLeftInverseAxiom(ctor, dtor, i));
+ }
+
+ reprSet = new TypeCtorRepr(ctor, dtors);
+ TypeCtorReprs.Add(decl, reprSet);
+ }
+
+ return reprSet;
+ }
+
+ public Function GetTypeCtorRepr(TypeCtorDecl decl) {
+ Contract.Requires(decl != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCtorReprStruct(decl).Ctor;
+ }
+
+ public Function GetTypeDtor(TypeCtorDecl decl, int num) {
+ Contract.Requires(decl != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCtorReprStruct(decl).Dtors[num];
+ }
+
+ // mapping from free type variables to VCExpr variables
+ private readonly IDictionary<TypeVariable/*!*/, VCExprVar/*!*/>/*!*/ TypeVariableMapping;
+ [ContractInvariantMethod]
+ void TypeVariableMappingInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableMapping));
+ }
+
+ public VCExprVar Typed2Untyped(TypeVariable var) {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res;
+ if (!TypeVariableMapping.TryGetValue(var, out res)) {
+ res = new VCExprVar(var.Name, T);
+ TypeVariableMapping.Add(var, res);
+ }
+ return cce.NonNull(res);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing variables and constants
+
+ // Globally defined variables
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ Typed2UntypedVariables;
+ [ContractInvariantMethod]
+ void Typed2UntypedVariablesInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedVariables));
+ }
+
+ // This method must only be used for free (unbound) variables
+ public VCExprVar Typed2Untyped(VCExprVar var) {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res = TryTyped2Untyped(var);
+ if (res == null) {
+ res = Gen.Variable(var.Name, TypeAfterErasure(var.Type));
+ Typed2UntypedVariables.Add(var, res);
+ AddVarTypeAxiom(res, var.Type);
+ }
+ return cce.NonNull(res);
+ }
+
+ /// <summary>
+ /// This method is like Typed2Untyped, except in the case where the given variables
+ /// doesn't exist in the mapping. For that case, this method returns null whereas
+ /// Typed2Untyped creates a new variable that it adds to the mapping.
+ /// </summary>
+ /// <param name="var"></param>
+ /// <returns></returns>
+ public VCExprVar TryTyped2Untyped(VCExprVar var) {
+ Contract.Requires(var != null);
+ VCExprVar res;
+ if (Typed2UntypedVariables.TryGetValue(var, out res)) {
+ return res;
+ } else {
+ return null;
+ }
+ }
+
+ protected abstract void AddVarTypeAxiom(VCExprVar/*!*/ var, Type/*!*/ originalType);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Translation function from types to their term representation
+
+ public VCExpr Type2Term(Type type, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
+ Contract.Requires(type != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ //
+ if (type.IsBasic || type.IsBv) {
+ //
+ return GetBasicTypeRepr(type);
+ //
+ } else if (type.IsCtor) {
+ //
+ CtorType ctype = type.AsCtor;
+ Function/*!*/ repr = GetTypeCtorRepr(ctype.Decl);
+ List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>(ctype.Arguments.Count);
+ foreach (Type/*!*/ t in ctype.Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ args.Add(Type2Term(t, varMapping));
+ }
+ return Gen.Function(repr, args);
+ //
+ } else if (type.IsVariable) {
+ //
+ VCExpr res;
+ if (!varMapping.TryGetValue(type.AsVariable, out res))
+ // then the variable is free and we bind it at this point to a term
+ // variable
+ res = Typed2Untyped(type.AsVariable);
+ return cce.NonNull(res);
+ //
+ } else if (type.IsMap) {
+ //
+ return Type2Term(MapTypeAbstracter.AbstractMapType(type.AsMap), varMapping);
+ //
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + type);
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // please the compiler
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public TypeAxiomBuilder(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ this.Gen = gen;
+ AllTypeAxioms = new List<VCExpr/*!*/>();
+ IncTypeAxioms = new List<VCExpr/*!*/>();
+ BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>();
+ CurrentCtorNum = BigNum.ZERO;
+ TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>();
+ TypeVariableMapping = new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>();
+ Typed2UntypedVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
+
+ TypeCtorDecl/*!*/ uDecl = new TypeCtorDecl(Token.NoToken, "U", 0);
+ UDecl = uDecl;
+ Type/*!*/ u = new CtorType(Token.NoToken, uDecl, new List<Type>());
+ U = u;
+
+ TypeCtorDecl/*!*/ tDecl = new TypeCtorDecl(Token.NoToken, "T", 0);
+ TDecl = tDecl;
+ Type/*!*/ t = new CtorType(Token.NoToken, tDecl, new List<Type>());
+ T = t;
+
+ Ctor = HelperFuns.BoogieFunction("Ctor", t, Type.Int);
+ }
+
+ public virtual void Setup() {
+ GetBasicTypeRepr(Type.Int);
+ GetBasicTypeRepr(Type.Real);
+ GetBasicTypeRepr(Type.Bool);
+ }
+
+ // constructor to allow cloning
+ internal TypeAxiomBuilder(TypeAxiomBuilder builder) {
+ Contract.Requires(builder != null);
+ Gen = builder.Gen;
+ AllTypeAxioms = new List<VCExpr/*!*/>(builder.AllTypeAxioms);
+ IncTypeAxioms = new List<VCExpr/*!*/>(builder.IncTypeAxioms);
+
+ UDecl = builder.UDecl;
+ U = builder.U;
+
+ TDecl = builder.TDecl;
+ T = builder.T;
+
+ Ctor = builder.Ctor;
+ CurrentCtorNum = builder.CurrentCtorNum;
+
+ BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>(builder.BasicTypeReprs);
+ TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>(builder.TypeCtorReprs);
+
+ TypeVariableMapping =
+ new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>(builder.TypeVariableMapping);
+ Typed2UntypedVariables =
+ new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(builder.Typed2UntypedVariables);
+ }
+
+ public abstract Object/*!*/ Clone();
+ }
+
+ [ContractClassFor(typeof(TypeAxiomBuilder))]
+ public abstract class TypeAxiomBuilderContracts : TypeAxiomBuilder {
+ public TypeAxiomBuilderContracts()
+ : base((VCExpressionGenerator)null) {
+ }
+ internal override MapTypeAbstractionBuilder MapTypeAbstracter {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public override Type TypeAfterErasure(Type type) {
+ Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ public override bool UnchangedType(Type type) {
+ Contract.Requires(type != null);
+ throw new NotImplementedException();
+ }
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ Contract.Requires(var != null);
+ Contract.Requires(originalType != null);
+ throw new NotImplementedException();
+ }
+
+ public override object Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Subclass of the TypeAxiomBuilder that provides all functionality
+ // to deal with native sorts of a theorem prover (that are the only
+ // types left after erasing all other types). Currently, these are:
+ //
+ // U ... sort of all individuals/objects/values
+ // T ... sort of all types
+ // int ... integers
+ // bool ... booleans
+
+ [ContractClass(typeof(TypeAxiomBuilderIntBoolUContracts))]
+ public abstract class TypeAxiomBuilderIntBoolU : TypeAxiomBuilder {
+
+ public TypeAxiomBuilderIntBoolU(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>();
+ }
+
+ // constructor to allow cloning
+ internal TypeAxiomBuilderIntBoolU(TypeAxiomBuilderIntBoolU builder)
+ : base(builder) {
+ Contract.Requires(builder != null);
+
+ TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>(builder.TypeCasts);
+ }
+
+ public override void Setup() {
+ base.Setup();
+
+ GetTypeCasts(Type.Int);
+ GetTypeCasts(Type.Real);
+ GetTypeCasts(Type.Bool);
+ }
+
+ // generate inverse axioms for casts (castToU(castFromU(x)) = x, under certain premisses)
+ protected abstract VCExpr/*!*/ GenReverseCastAxiom(Function/*!*/ castToU, Function/*!*/ castFromU);
+
+ protected VCExpr GenReverseCastEq(Function castToU, Function castFromU, out VCExprVar var, out List<VCTrigger/*!*/>/*!*/ triggers) {
+ Contract.Requires((castFromU != null));
+ Contract.Requires((castToU != null));
+ Contract.Ensures((cce.NonNullElements(Contract.ValueAtReturn(out triggers))));
+ Contract.Ensures(Contract.ValueAtReturn(out var) != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ var = Gen.Variable("x", U);
+
+ VCExpr inner = Gen.Function(castFromU, var);
+ VCExpr lhs = Gen.Function(castToU, inner);
+ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(inner)));
+
+ return Gen.Eq(lhs, var);
+ }
+
+ protected abstract VCExpr/*!*/ GenCastTypeAxioms(Function/*!*/ castToU, Function/*!*/ castFromU);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // storage of type casts for types that are supposed to be left over in the
+ // VCs (like int, bool, bitvectors)
+
+ private readonly IDictionary<Type/*!*/, TypeCastSet/*!*/>/*!*/ TypeCasts;
+ [ContractInvariantMethod]
+ void TypeCastsInvariantMethod() {
+ Contract.Invariant(TypeCasts != null);
+ }
+
+ private TypeCastSet GetTypeCasts(Type type) {
+ Contract.Requires(type != null);
+ TypeCastSet res;
+ if (!TypeCasts.TryGetValue(type, out res)) {
+ Function/*!*/ castToU = HelperFuns.BoogieFunction(type.ToString() + "_2_U", type, U);
+ Function/*!*/ castFromU = HelperFuns.BoogieFunction("U_2_" + type.ToString(), U, type);
+
+ AddTypeAxiom(GenLeftInverseAxiom(castToU, castFromU, 0));
+ AddTypeAxiom(GenReverseCastAxiom(castToU, castFromU));
+ AddTypeAxiom(GenCastTypeAxioms(castToU, castFromU));
+
+ res = new TypeCastSet(castToU, castFromU);
+ TypeCasts.Add(type, res);
+ }
+ return res;
+ }
+ [Pure]
+ public Function CastTo(Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(UnchangedType(type));
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCasts(type).CastFromU;
+ }
+
+ public Function CastFrom(Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires((UnchangedType(type)));
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCasts(type).CastToU;
+ }
+
+ private struct TypeCastSet {
+ public readonly Function/*!*/ CastToU;
+ public readonly Function/*!*/ CastFromU;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(CastToU != null);
+ Contract.Invariant(CastFromU != null);
+ }
+
+
+ public TypeCastSet(Function castToU, Function castFromU) {
+ Contract.Requires(castFromU != null);
+ Contract.Requires(castToU != null);
+ CastToU = castToU;
+ CastFromU = castFromU;
+ }
+ }
+
+ public bool IsCast(Function fun) {
+ Contract.Requires(fun != null);
+ if (fun.InParams.Count != 1)
+ return false;
+ Type/*!*/ inType = cce.NonNull(fun.InParams[0]).TypedIdent.Type;
+ if (inType.Equals(U)) {
+ Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
+ if (!TypeCasts.ContainsKey(outType))
+ return false;
+ return fun.Equals(CastTo(outType));
+ } else {
+ if (!TypeCasts.ContainsKey(inType))
+ return false;
+ Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
+ if (!outType.Equals(U))
+ return false;
+ return fun.Equals(CastFrom(inType));
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // the only types that we allow in "untyped" expressions are U,
+ // Type.Int, Type.Real, and Type.Bool
+
+ public override Type TypeAfterErasure(Type type) {
+ //Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (UnchangedType(type))
+ // these types are kept
+ return type;
+ else
+ // all other types are replaced by U
+ return U;
+ }
+
+ [Pure]
+ public override bool UnchangedType(Type type) {
+ //Contract.Requires(type != null);
+ return type.IsInt || type.IsReal || type.IsBool || type.IsBv || (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays);
+ }
+
+ public VCExpr Cast(VCExpr expr, Type toType) {
+ Contract.Requires(toType != null);
+ Contract.Requires(expr != null);
+ Contract.Requires((expr.Type.Equals(U) || UnchangedType(expr.Type)));
+ Contract.Requires((toType.Equals(U) || UnchangedType(toType)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (expr.Type.Equals(toType))
+ return expr;
+
+ if (toType.Equals(U)) {
+ return Gen.Function(CastFrom(expr.Type), expr);
+ } else {
+ Contract.Assert(expr.Type.Equals(U));
+ return Gen.Function(CastTo(toType), expr);
+ }
+ }
+
+ public List<VCExpr/*!*/>/*!*/ CastSeq(List<VCExpr/*!*/>/*!*/ exprs, Type toType) {
+ Contract.Requires(toType != null);
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>(exprs.Count);
+ foreach (VCExpr/*!*/ expr in exprs) {
+ Contract.Assert(expr != null);
+ res.Add(Cast(expr, toType));
+ }
+ return res;
+ }
+
+
+ }
+
+ [ContractClassFor(typeof(TypeAxiomBuilderIntBoolU))]
+ public abstract class TypeAxiomBuilderIntBoolUContracts : TypeAxiomBuilderIntBoolU {
+ public TypeAxiomBuilderIntBoolUContracts()
+ : base((TypeAxiomBuilderIntBoolU)null) {
+ }
+ protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
+ Contract.Requires(castToU != null);
+ Contract.Requires(castFromU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
+ Contract.Requires(castFromU != null);
+ Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ internal override MapTypeAbstractionBuilder MapTypeAbstracter {
+ get {
+ throw new NotImplementedException();
+ }
+ }
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ throw new NotImplementedException();
+ }
+
+ public override object Clone() {
+ throw new NotImplementedException();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Class for computing most general abstractions of map types. An abstraction
+ // of a map type t is a maptype t' in which closed proper subtypes have been replaced
+ // with type variables. E.g., an abstraction of <a>[C a, int]a would be <a>[C a, b]a.
+ // We subsequently consider most general abstractions as ordinary parametrised types,
+ // i.e., "<a>[C a, b]a" would be considered as a type "M b" with polymorphically typed
+ // access functions
+ //
+ // select<a,b>(M b, C a, b) returns (a)
+ // store<a,b>(M b, C a, b, a) returns (M b)
+ [ContractClass(typeof(MapTypeAbstractionBuilderContracts))]
+ internal abstract class MapTypeAbstractionBuilder {
+
+ protected readonly TypeAxiomBuilder/*!*/ AxBuilder;
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilder != null);
+ Contract.Invariant(Gen != null);
+ }
+
+
+ internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ this.AxBuilder = axBuilder;
+ this.Gen = gen;
+ AbstractionVariables = new List<TypeVariable/*!*/>();
+ ClassRepresentations = new Dictionary<MapType/*!*/, MapTypeClassRepresentation>();
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilder builder) {
+ Contract.Requires(builder != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ this.AxBuilder = axBuilder;
+ this.Gen = gen;
+ AbstractionVariables =
+ new List<TypeVariable/*!*/>(builder.AbstractionVariables);
+ ClassRepresentations =
+ new Dictionary<MapType/*!*/, MapTypeClassRepresentation>(builder.ClassRepresentations);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Type variables used in the abstractions. We use the same variables in the
+ // same order in all abstractions in order to obtain comparable abstractions
+ // (equals, hashcode)
+
+ private readonly List<TypeVariable/*!*/>/*!*/ AbstractionVariables;
+ [ContractInvariantMethod]
+ void AbstractionVariablesInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(AbstractionVariables));
+ }
+
+ private TypeVariable AbstractionVariable(int num) {
+ Contract.Requires((num >= 0));
+ Contract.Ensures(Contract.Result<TypeVariable>() != null);
+ while (AbstractionVariables.Count <= num)
+ AbstractionVariables.Add(new TypeVariable(Token.NoToken,
+ "aVar" + AbstractionVariables.Count));
+ return AbstractionVariables[num];
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The untyped representation of a class of map types, i.e., of a map type
+ // <a0, a1, ...>[A0, A1, ...] R, where the argument types and the result type
+ // possibly contain free type variables. For each such class, a separate type
+ // constructor and separate select/store functions are introduced.
+
+ protected struct MapTypeClassRepresentation {
+ public readonly TypeCtorDecl/*!*/ RepresentingType;
+ public readonly Function/*!*/ Select;
+ public readonly Function/*!*/ Store;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(RepresentingType != null);
+ Contract.Invariant(Select != null);
+ Contract.Invariant(Store != null);
+ }
+
+
+ public MapTypeClassRepresentation(TypeCtorDecl representingType, Function select, Function store) {
+ Contract.Requires(store != null);
+ Contract.Requires(select != null);
+ Contract.Requires(representingType != null);
+ this.RepresentingType = representingType;
+ this.Select = select;
+ this.Store = store;
+ }
+ }
+
+ private readonly IDictionary<MapType/*!*/, MapTypeClassRepresentation/*!*/>/*!*/ ClassRepresentations;
+ [ContractInvariantMethod]
+ void ClassRepresentationsInvariantMethod() {
+ Contract.Invariant(ClassRepresentations != null);
+ }
+
+ protected MapTypeClassRepresentation GetClassRepresentation(MapType abstractedType) {
+ Contract.Requires(abstractedType != null);
+ MapTypeClassRepresentation res;
+ if (!ClassRepresentations.TryGetValue(abstractedType, out res)) {
+ int num = ClassRepresentations.Count;
+ TypeCtorDecl/*!*/ synonym =
+ new TypeCtorDecl(Token.NoToken, "MapType" + num, abstractedType.FreeVariables.Count);
+
+ Function/*!*/ select, store;
+ GenSelectStoreFunctions(abstractedType, synonym, out select, out store);
+
+ res = new MapTypeClassRepresentation(synonym, select, store);
+ ClassRepresentations.Add(abstractedType, res);
+ }
+ return res;
+ }
+
+ // the actual select and store functions are generated by the
+ // concrete subclasses of this class
+ protected abstract void GenSelectStoreFunctions(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl, out Function/*!*/ select, out Function/*!*/ store);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public Function Select(MapType rawType, out List<Type> instantiations) {
+ Contract.Requires((rawType != null));
+ Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return AbstractAndGetRepresentation(rawType, out instantiations).Select;
+ }
+
+ public Function Store(MapType rawType, out List<Type> instantiations) {
+ Contract.Requires((rawType != null));
+ Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return AbstractAndGetRepresentation(rawType, out instantiations).Store;
+ }
+
+ private MapTypeClassRepresentation
+ AbstractAndGetRepresentation(MapType rawType, out List<Type> instantiations) {
+ Contract.Requires((rawType != null));
+ Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
+ instantiations = new List<Type>();
+ MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
+ return GetClassRepresentation(abstraction);
+ }
+
+ public CtorType AbstractMapType(MapType rawType) {
+ Contract.Requires(rawType != null);
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+ List<Type>/*!*/ instantiations = new List<Type>();
+ MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
+
+ MapTypeClassRepresentation repr = GetClassRepresentation(abstraction);
+ Contract.Assume(repr.RepresentingType.Arity == instantiations.Count);
+ return new CtorType(Token.NoToken, repr.RepresentingType, instantiations);
+ }
+
+ // TODO: cache the result of this operation
+ protected MapType ThinOutMapType(MapType rawType, List<Type> instantiations) {
+ Contract.Requires(instantiations != null);
+ Contract.Requires(rawType != null);
+ Contract.Ensures(Contract.Result<MapType>() != null);
+ List<Type>/*!*/ newArguments = new List<Type>();
+ foreach (Type/*!*/ subtype in rawType.Arguments.ToList()) {
+ Contract.Assert(subtype != null);
+ newArguments.Add(ThinOutType(subtype, rawType.TypeParameters,
+ instantiations));
+ }
+ Type/*!*/ newResult = ThinOutType(rawType.Result, rawType.TypeParameters,
+ instantiations);
+ return new MapType(Token.NoToken, rawType.TypeParameters, newArguments, newResult);
+ }
+
+ // the instantiations of inserted type variables, the order corresponds to the order in which "AbstractionVariable(int)" delivers variables
+ private Type/*!*/ ThinOutType(Type rawType, List<TypeVariable> boundTypeParams, List<Type> instantiations) {
+ Contract.Requires(instantiations != null);
+ Contract.Requires(boundTypeParams != null);
+ Contract.Requires(rawType != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(rawType))
+ return rawType;
+
+ if (rawType.FreeVariables.All(var => !boundTypeParams.Contains(var))) {
+ // Bingo!
+ // if the type does not contain any bound variables, we can simply
+ // replace it with a type variable
+ TypeVariable/*!*/ abstractionVar = AbstractionVariable(instantiations.Count);
+ Contract.Assume(!boundTypeParams.Contains(abstractionVar));
+ instantiations.Add(rawType);
+ return abstractionVar;
+ }
+
+ if (rawType.IsVariable) {
+ //
+ // then the variable has to be bound, we cannot do anything
+ TypeVariable/*!*/ rawVar = rawType.AsVariable;
+ Contract.Assume(boundTypeParams.Contains(rawVar));
+ return rawVar;
+ //
+ } else if (rawType.IsMap) {
+ //
+ // recursively abstract this map type and continue abstracting
+ CtorType/*!*/ abstraction = AbstractMapType(rawType.AsMap);
+ return ThinOutType(abstraction, boundTypeParams, instantiations);
+ //
+ } else if (rawType.IsCtor) {
+ //
+ // traverse the subtypes
+ CtorType/*!*/ rawCtorType = rawType.AsCtor;
+ List<Type>/*!*/ newArguments = new List<Type>();
+ foreach (Type/*!*/ subtype in rawCtorType.Arguments.ToList()) {
+ Contract.Assert(subtype != null);
+ newArguments.Add(ThinOutType(subtype, boundTypeParams,
+ instantiations));
+ }
+ return new CtorType(Token.NoToken, rawCtorType.Decl, newArguments);
+ //
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + rawType);
+ return rawType; // compiler appeasement policy
+ }
+ }
+
+ }
+ [ContractClassFor(typeof(MapTypeAbstractionBuilder))]
+ internal abstract class MapTypeAbstractionBuilderContracts : MapTypeAbstractionBuilder {
+ public MapTypeAbstractionBuilderContracts()
+ : base(null, null) {
+ }
+ protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonymDecl, out Function select, out Function store) {
+ Contract.Requires(abstractedType != null);
+ Contract.Requires(synonymDecl != null);
+ Contract.Ensures(Contract.ValueAtReturn(out select) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out store) != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class VariableBindings {
+ public readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ VCExprVarBindings;
+ public readonly IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ TypeVariableBindings;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(VCExprVarBindings));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableBindings));
+ }
+
+
+ public VariableBindings(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ vcExprVarBindings,
+ IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ typeVariableBindings) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(vcExprVarBindings));
+ Contract.Requires(cce.NonNullDictionaryAndValues(typeVariableBindings));
+ this.VCExprVarBindings = vcExprVarBindings;
+ this.TypeVariableBindings = typeVariableBindings;
+ }
+
+ public VariableBindings() :
+ this(new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(),
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()) {
+ }
+
+ public VariableBindings Clone() {
+ Contract.Ensures(Contract.Result<VariableBindings>() != null);
+ IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ newVCExprVarBindings =
+ new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
+ foreach (KeyValuePair<VCExprVar/*!*/, VCExprVar/*!*/> pair in VCExprVarBindings) {
+ Contract.Assert(cce.NonNullElements(pair));
+ newVCExprVarBindings.Add(pair);
+ }
+ IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ newTypeVariableBindings =
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>();
+ foreach (KeyValuePair<TypeVariable/*!*/, VCExpr/*!*/> pair in TypeVariableBindings) {
+ Contract.Assert(cce.NonNullElements(pair));
+ newTypeVariableBindings.Add(pair);
+ }
+ return new VariableBindings(newVCExprVarBindings, newTypeVariableBindings);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // The central class for turning types VCExprs into untyped
+ // VCExprs. This class makes use of the type axiom builder to manage
+ // the available types and symbols.
+ [ContractClass(typeof(TypeEraserContracts))]
+ public abstract class TypeEraser : MutatingVCExprVisitor<VariableBindings/*!*/> {
+
+ protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilder != null);
+ }
+
+
+ protected abstract OpTypeEraser/*!*/ OpEraser {
+ get;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public TypeEraser(TypeAxiomBuilderIntBoolU axBuilder, VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ AxBuilder = axBuilder;
+ }
+
+ public VCExpr Erase(VCExpr expr, int polarity) {
+ Contract.Requires(expr != null);
+ Contract.Requires((polarity >= -1 && polarity <= 1));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ this.Polarity = polarity;
+ return Mutate(expr, new VariableBindings());
+ }
+
+ internal int Polarity = 1; // 1 for positive, -1 for negative, 0 for both
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLiteral node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assume(node.Type == Type.Bool || node.Type == Type.Int || node.Type == Type.Real);
+ return node;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override bool AvoidVisit(VCExprNAry node, VariableBindings arg)
+ {
+ return node.Op.Equals(VCExpressionGenerator.AndOp) ||
+ node.Op.Equals(VCExpressionGenerator.OrOp);
+ }
+
+ public override VCExpr Visit(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprOp/*!*/ op = node.Op;
+ if (op == VCExpressionGenerator.AndOp || op == VCExpressionGenerator.OrOp)
+ // more efficient on large conjunctions/disjunctions
+ return base.Visit(node, bindings);
+
+ // the visitor that handles all other operators
+ return node.Accept<VCExpr/*!*/, VariableBindings/*!*/>(OpEraser, bindings);
+ }
+
+ // this method is called by MutatingVCExprVisitor.Visit(VCExprNAry, ...)
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VariableBindings/*!*/ bindings) {
+ //Contract.Requires(originalNode != null);
+ //Contract.Requires(cce.NonNullElements(newSubExprs));
+ //Contract.Requires(bindings != null);
+ Contract.Assume(originalNode.Op == VCExpressionGenerator.AndOp ||
+ originalNode.Op == VCExpressionGenerator.OrOp);
+ return Gen.Function(originalNode.Op,
+ AxBuilder.Cast(newSubExprs[0], Type.Bool),
+ AxBuilder.Cast(newSubExprs[1], Type.Bool));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprVar node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprVar res;
+ if (!bindings.VCExprVarBindings.TryGetValue(node, out res))
+ return AxBuilder.Typed2Untyped(node);
+ return cce.NonNull(res);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected bool IsUniversalQuantifier(VCExprQuantifier node) {
+ Contract.Requires(node != null);
+ return Polarity == 1 && node.Quan == Quantifier.EX ||
+ Polarity == -1 && node.Quan == Quantifier.ALL;
+ }
+
+ protected List<VCExprVar/*!*/>/*!*/ BoundVarsAfterErasure(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
+ // the mapping between old and new variables
+ // is added to this bindings-object
+ VariableBindings/*!*/ bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(cce.NonNullElements(oldBoundVars));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+
+ List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
+ foreach (VCExprVar/*!*/ var in oldBoundVars) {
+ Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ bindings.VCExprVarBindings.Add(var, newVar);
+ }
+ return newBoundVars;
+ }
+
+ // We check whether casts Int2U or Bool2U on the bound variables
+ // occur in triggers. In case a trigger like f(Int2U(x)) occurs,
+ // it may be better to give variable x the type U and remove the
+ // cast. The following method returns true if the quantifier
+ // should be translated again with a different typing
+ protected bool RedoQuantifier(VCExprQuantifier/*!*/ node,
+ VCExprQuantifier/*!*/ newNode,
+ // the bound vars that actually occur in the body or
+ // in any of the triggers
+ List<VCExprVar/*!*/>/*!*/ occurringVars,
+ VariableBindings/*!*/ oldBindings,
+ out VariableBindings/*!*/ newBindings,
+ out List<VCExprVar/*!*/>/*!*/ newBoundVars) {
+ Contract.Requires(node != null);
+ Contract.Requires(newNode != null);
+ Contract.Requires(cce.NonNullElements(occurringVars));
+ Contract.Requires(oldBindings != null);
+ Contract.Ensures(Contract.ValueAtReturn(out newBindings) != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out newBoundVars)));
+ List<VCExprVar/*!*/> castVariables =
+ VariableCastCollector.FindCastVariables(node, newNode, AxBuilder);
+ if (castVariables.Count == 0) {
+ newBindings = oldBindings; // to make the compiler happy
+ newBoundVars = newNode.BoundVars; // to make the compiler happy
+ return false;
+ }
+
+ // redo everything with a different typing ...
+
+ newBindings = oldBindings.Clone();
+ newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Contract.Assert(var != null);
+ Type/*!*/ newType =
+ castVariables.Contains(var) ? AxBuilder.U
+ : AxBuilder.TypeAfterErasure(var.Type);
+ Contract.Assert(newType != null);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ Contract.Assert(newVar != null);
+ newBoundVars.Add(newVar);
+ newBindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLet node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VariableBindings/*!*/ newVarBindings = bindings.Clone();
+
+ List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ newVarBindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>(node.Length);
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding/*!*/ binding = node[i];
+ Contract.Assert(binding != null);
+ VCExprVar/*!*/ newVar = newBoundVars[i];
+ Type/*!*/ newType = newVar.Type;
+
+ VCExpr/*!*/ newE = AxBuilder.Cast(Mutate(binding.E, newVarBindings), newType);
+ newbindings.Add(Gen.LetBinding(newVar, newE));
+ }
+
+ VCExpr/*!*/ newbody = Mutate(node.Body, newVarBindings);
+ return Gen.Let(newbindings, newbody);
+ }
+ }
+
+ [ContractClassFor(typeof(TypeEraser))]
+ public abstract class TypeEraserContracts : TypeEraser {
+ public TypeEraserContracts()
+ : base(null, null) {
+ }
+ protected override OpTypeEraser OpEraser {
+ get {
+ Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
+ throw new NotImplementedException();
+ }
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public abstract class OpTypeEraser : StandardVCExprOpVisitor<VCExpr/*!*/, VariableBindings/*!*/> {
+
+ protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
+
+ protected readonly TypeEraser/*!*/ Eraser;
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilder != null);
+ Contract.Invariant(Eraser != null);
+ Contract.Invariant(Gen != null);
+ }
+
+
+ public OpTypeEraser(TypeEraser/*!*/ eraser, TypeAxiomBuilderIntBoolU/*!*/ axBuilder, VCExpressionGenerator/*!*/ gen) {
+ Contract.Requires(eraser != null);
+ Contract.Requires(axBuilder != null);
+ Contract.Requires(gen != null);
+ this.AxBuilder = axBuilder;
+ this.Eraser = eraser;
+ this.Gen = gen;
+ }
+
+ protected override VCExpr StandardResult(VCExprNAry node, VariableBindings bindings) {
+ //Contract.Requires(bindings != null);
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ System.Diagnostics.Debug.Fail("Don't know how to erase types in this expression: " + node);
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // to please the compiler
+ }
+
+ private List<VCExpr/*!*/>/*!*/ MutateSeq(VCExprNAry node, VariableBindings bindings, int newPolarity) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = newPolarity;
+ List<VCExpr/*!*/>/*!*/ newArgs = Eraser.MutateSeq(node, bindings);
+ Eraser.Polarity = oldPolarity;
+ return newArgs;
+ }
+
+ private VCExpr CastArguments(VCExprNAry node, Type argType, VariableBindings bindings, int newPolarity) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(argType != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Function(node.Op,
+ AxBuilder.CastSeq(MutateSeq(node, bindings, newPolarity),
+ argType));
+ }
+
+ // Cast the arguments of the node to their old type if necessary and possible; otherwise use
+ // their new type (int, real, bool, or U)
+ private VCExpr CastArgumentsToOldType(VCExprNAry node, VariableBindings bindings, int newPolarity) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Requires((node.Arity > 0));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, newPolarity);
+ Type/*!*/ oldType = node[0].Type;
+ if (AxBuilder.UnchangedType(oldType) &&
+ node.Skip(1).All(e => e.Type.Equals(oldType)))
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, oldType));
+ else
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, AxBuilder.U));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr VisitNotOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Bool, bindings, -Eraser.Polarity);
+ }
+ public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitImpliesOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(2);
+ Eraser.Polarity = -Eraser.Polarity;
+ newArgs.Add(Eraser.Mutate(node[0], bindings));
+ Eraser.Polarity = -Eraser.Polarity;
+ newArgs.Add(Eraser.Mutate(node[1], bindings));
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, Type.Bool));
+ }
+ public override VCExpr VisitDistinctOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitLabelOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // argument of the label operator should always be a formula
+ // (at least for Simplify ... should this be ensured at a later point?)
+ return CastArguments(node, Type.Bool, bindings, Eraser.Polarity);
+ }
+ public override VCExpr VisitIfThenElseOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
+ newArgs[0] = AxBuilder.Cast(newArgs[0], Type.Bool);
+ Type t = node.Type;
+ if (!AxBuilder.UnchangedType(t)) {
+ t = AxBuilder.U;
+ }
+ newArgs[1] = AxBuilder.Cast(newArgs[1], t);
+ newArgs[2] = AxBuilder.Cast(newArgs[2], t);
+ return Gen.Function(node.Op, newArgs);
+ }
+ public override VCExpr/*!*/ VisitCustomOp(VCExprNAry/*!*/ node, VariableBindings/*!*/ bindings) {
+ Contract.Requires(node != null);
+ Contract.Requires(bindings != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
+ return Gen.Function(node.Op, newArgs);
+ }
+ public override VCExpr VisitAddOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, node.Type, bindings, 0);
+ }
+ public override VCExpr VisitSubOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, node.Type, bindings, 0);
+ }
+ public override VCExpr VisitMulOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, node.Type, bindings, 0);
+ }
+ public override VCExpr VisitDivOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr VisitModOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr VisitRealDivOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Real, bindings, 0);
+ }
+ /*public override VCExpr VisitFloatDivOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Float, bindings, 0);
+ }*/
+ public override VCExpr VisitPowOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Real, bindings, 0);
+ }
+ public override VCExpr VisitLtOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitLeOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitGtOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitGeOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, AxBuilder.U, bindings, 0);
+ }
+ public override VCExpr VisitToIntOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitToRealOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatAddOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatSubOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatMulOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatDivOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatRemOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatMinOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatMaxOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatLeqOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatLtOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatGeqOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatGtOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitFloatEqOp(VCExprNAry node, VariableBindings bindings)
+ {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitBvOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitBvExtractOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitBvConcatOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
+
+ // each argument is cast to its old type
+ Contract.Assert(newArgs.Count == node.Arity && newArgs.Count == 2);
+ VCExpr/*!*/ arg0 = AxBuilder.Cast(newArgs[0], node[0].Type);
+ Contract.Assert(arg0 != null);
+ VCExpr/*!*/ arg1 = AxBuilder.Cast(newArgs[1], node[1].Type);
+ Contract.Assert(arg1 != null);
+ return Gen.Function(node.Op, arg0, arg1);
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// Collect all variables x occurring in expressions of the form Int2U(x) or Bool2U(x), and
+ /// collect all variables x occurring outside such forms.
+ /// </summary>
+ internal class VariableCastCollector : TraversingVCExprVisitor<bool, bool> {
+ /// <summary>
+ /// Determine those bound variables in "oldNode" <em>all</em> of whose relevant uses
+ /// have to be cast in potential triggers in "newNode". It is assume that
+ /// the bound variables of "oldNode" correspond to the first bound
+ /// variables of "newNode".
+ /// </summary>
+ public static List<VCExprVar/*!*/>/*!*/ FindCastVariables(VCExprQuantifier oldNode, VCExprQuantifier newNode, TypeAxiomBuilderIntBoolU axBuilder) {
+ Contract.Requires((axBuilder != null));
+ Contract.Requires((newNode != null));
+ Contract.Requires((oldNode != null));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ VariableCastCollector/*!*/ collector = new VariableCastCollector(axBuilder);
+ Contract.Assert(collector != null);
+ if (newNode.Triggers.Any(trigger => trigger.Pos)) {
+ // look in the given triggers
+ foreach (VCTrigger/*!*/ trigger in newNode.Triggers) {
+ Contract.Assert(trigger != null);
+ if (trigger.Pos) {
+ foreach (VCExpr/*!*/ expr in trigger.Exprs) {
+ Contract.Assert(expr != null);
+ collector.Traverse(expr, true);
+ }
+ }
+ }
+ } else {
+ // look in the body of the quantifier
+ collector.Traverse(newNode.Body, true);
+ }
+
+ List<VCExprVar/*!*/>/*!*/ castVariables = new List<VCExprVar/*!*/>(collector.varsInCasts.Count);
+ foreach (VCExprVar/*!*/ castVar in collector.varsInCasts) {
+ Contract.Assert(castVar != null);
+ int i = newNode.BoundVars.IndexOf(castVar);
+ if (0 <= i && i < oldNode.BoundVars.Count && !collector.varsOutsideCasts.ContainsKey(castVar))
+ castVariables.Add(oldNode.BoundVars[i]);
+ }
+ return castVariables;
+ }
+
+ public VariableCastCollector(TypeAxiomBuilderIntBoolU axBuilder) {
+ Contract.Requires(axBuilder != null);
+ this.AxBuilder = axBuilder;
+ }
+
+ readonly List<VCExprVar/*!*/>/*!*/ varsInCasts = new List<VCExprVar/*!*/>();
+ readonly Dictionary<VCExprVar/*!*/, object>/*!*/ varsOutsideCasts = new Dictionary<VCExprVar/*!*/, object>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(varsInCasts));
+ Contract.Invariant(varsOutsideCasts != null && Contract.ForAll(varsOutsideCasts, voc => voc.Key != null));
+ Contract.Invariant(AxBuilder != null);
+
+ }
+
+
+ readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return true; // not used
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+ if (node.Op is VCExprBoogieFunctionOp) {
+ Function func = ((VCExprBoogieFunctionOp)node.Op).Func;
+ Contract.Assert(func != null);
+ if ((AxBuilder.IsCast(func)) && node[0] is VCExprVar) {
+ VCExprVar castVar = (VCExprVar)node[0];
+ if (!varsInCasts.Contains(castVar))
+ varsInCasts.Add(castVar);
+ return true;
+ }
+ } else if (node.Op is VCExprNAryOp) {
+ VCExpressionGenerator.SingletonOp op = VCExpressionGenerator.SingletonOpDict[node.Op];
+ switch (op) {
+ // the following operators cannot be used in triggers, so disregard any uses of variables as direct arguments
+ case VCExpressionGenerator.SingletonOp.NotOp:
+ case VCExpressionGenerator.SingletonOp.EqOp:
+ case VCExpressionGenerator.SingletonOp.NeqOp:
+ case VCExpressionGenerator.SingletonOp.AndOp:
+ case VCExpressionGenerator.SingletonOp.OrOp:
+ case VCExpressionGenerator.SingletonOp.ImpliesOp:
+ case VCExpressionGenerator.SingletonOp.LtOp:
+ case VCExpressionGenerator.SingletonOp.LeOp:
+ case VCExpressionGenerator.SingletonOp.GtOp:
+ case VCExpressionGenerator.SingletonOp.GeOp:
+ foreach (VCExpr n in node) {
+ if (!(n is VCExprVar)) { // don't recurse on VCExprVar argument
+ n.Accept<bool, bool>(this, arg);
+ }
+ }
+ return true;
+ default:
+ break;
+ }
+ }
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!varsOutsideCasts.ContainsKey(node))
+ varsOutsideCasts.Add(node, null);
+ return true;
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TypeErasureArguments.cs b/Source/VCExpr/TypeErasureArguments.cs
index 8885cbc7..1ee79c17 100644
--- a/Source/VCExpr/TypeErasureArguments.cs
+++ b/Source/VCExpr/TypeErasureArguments.cs
@@ -1,754 +1,754 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Erasure of types using explicit type parameters for functions
-
-namespace Microsoft.Boogie.TypeErasure {
- using Microsoft.Boogie.VCExprAST;
- using HFNS = Microsoft.Boogie.VCExprAST.HelperFuns;
-
- public class TypeAxiomBuilderArguments : TypeAxiomBuilderIntBoolU {
-
- public TypeAxiomBuilderArguments(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- Typed2UntypedFunctions = new Dictionary<Function/*!*/, Function/*!*/>();
- }
-
- // constructor to allow cloning
- [NotDelayed]
- internal TypeAxiomBuilderArguments(TypeAxiomBuilderArguments builder)
- : base(builder) {
- Contract.Requires(builder != null);
- Typed2UntypedFunctions =
- new Dictionary<Function/*!*/, Function/*!*/>(builder.Typed2UntypedFunctions);
-
-
- MapTypeAbstracterAttr =
- builder.MapTypeAbstracterAttr == null ?
- null : new MapTypeAbstractionBuilderArguments(this, builder.Gen,
- builder.MapTypeAbstracterAttr);
- }
-
- public override Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
- return new TypeAxiomBuilderArguments(this);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))} Int2U(U2Int(x))==x"
- // (this makes use of the assumption that only well-typed terms are generated
- // by the SMT-solver, i.e., that U2Int is only applied to terms that actually
- // are of type int)
- protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCTrigger/*!*/>/*!*/ triggers;
- VCExprVar/*!*/ var;
- VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
- return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, eq);
- }
-
- protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // nothing
- return VCExpressionGenerator.True;
- }
-
- private MapTypeAbstractionBuilderArguments MapTypeAbstracterAttr = null;
-
- internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
-
- if (MapTypeAbstracterAttr == null)
- MapTypeAbstracterAttr = new MapTypeAbstractionBuilderArguments(this, Gen);
- return MapTypeAbstracterAttr;
- }
- }
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- //Contract.Requires(originalType != null);
- //Contract.Requires(var != null);
- // no axioms are needed for variable or function types
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Symbols for representing functions
-
- // Globally defined functions
- private readonly IDictionary<Function/*!*/, Function/*!*/>/*!*/ Typed2UntypedFunctions;
- [ContractInvariantMethod]
- void Typed2UntypedFunctionsInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedFunctions));
- }
-
- public Function Typed2Untyped(Function fun) {
- Contract.Requires(fun != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Function res;
- if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
- Contract.Assert(fun.OutParams.Count == 1);
-
- // if all of the parameters are int or bool, the function does
- // not have to be changed
- if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
- UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type)) {
- res = fun;
- } else {
- Type[]/*!*/ types = new Type[fun.TypeParameters.Count + fun.InParams.Count + 1];
-
- int i = 0;
- // the first arguments are the explicit type parameters
- for (int j = 0; j < fun.TypeParameters.Count; ++j) {
- types[i] = T;
- i = i + 1;
- }
- // followed by the actual parameters
- foreach (Variable/*!*/ x in fun.InParams) {
- Contract.Assert(x != null);
- types[i] = TypeAfterErasure(x.TypedIdent.Type);
- i = i + 1;
- }
-
- types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
-
- res = HelperFuns.BoogieFunction(fun.Name, types);
- res.Attributes = fun.Attributes;
- }
-
- Typed2UntypedFunctions.Add(fun, res);
- }
- return cce.NonNull(res);
- }
-
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal class MapTypeAbstractionBuilderArguments : MapTypeAbstractionBuilder {
-
- private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderArguments != null);
- }
-
-
- internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen)
- : base(axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderArguments = axBuilder;
- }
-
- // constructor for cloning
- internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderArguments builder)
- : base(axBuilder, gen, builder) {
- Contract.Requires(builder != null);
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- this.AxBuilderArguments = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
- //Contract.Requires(synonym != null);
-//Contract.Requires(abstractedType != null);
-Contract.Ensures(Contract.ValueAtReturn(out select) != null);
-Contract.Ensures(Contract.ValueAtReturn(out store) != null);
- Contract.Assert(synonym.Name != null);
- string/*!*/ baseName = synonym.Name;
- int typeParamNum = abstractedType.FreeVariables.Count +
- abstractedType.TypeParameters.Count;
-
- int arity = typeParamNum + abstractedType.Arguments.Count;
-
- Type/*!*/[]/*!*/ selectTypes = new Type/*!*/ [arity + 2];
- Type/*!*/[]/*!*/ storeTypes = new Type/*!*/ [arity + 3];
-
- int i = 0;
- // Fill in the free variables and type parameters
- for (; i < typeParamNum; i++) {
- selectTypes[i] = AxBuilder.T;
- storeTypes[i] = AxBuilder.T;
- }
- // Fill in the map type
- if (CommandLineOptions.Clo.MonomorphicArrays) {
- selectTypes[i] = abstractedType;
- storeTypes[i] = abstractedType;
- } else {
- selectTypes[i] = AxBuilder.U;
- storeTypes[i] = AxBuilder.U;
- }
- i++;
- // Fill in the index types
- foreach (Type/*!*/ type in abstractedType.Arguments) {
- Contract.Assert(type != null);
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type)) {
- selectTypes[i] = type;
- storeTypes[i] = type;
- } else {
- selectTypes[i] = AxBuilder.U;
- storeTypes[i] = AxBuilder.U;
- }
- i++;
- }
- // Fill in the output type for select function which also happens
- // to be the type of the last argument to the store function
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(abstractedType.Result)) {
- selectTypes[i] = abstractedType.Result;
- storeTypes[i] = abstractedType.Result;
- } else {
- selectTypes[i] = AxBuilder.U;
- storeTypes[i] = AxBuilder.U;
- }
- i++;
- // Fill in the map type which is the output of the store function
- if (CommandLineOptions.Clo.MonomorphicArrays)
- storeTypes[i] = abstractedType;
- else
- storeTypes[i] = AxBuilder.U;
- Contract.Assert(cce.NonNullElements<Type>(selectTypes));
- Contract.Assert(cce.NonNullElements<Type>(storeTypes));
-
- select = HelperFuns.BoogieFunction(baseName + "Select", selectTypes);
- store = HelperFuns.BoogieFunction(baseName + "Store", storeTypes);
-
- if (CommandLineOptions.Clo.UseArrayTheory) {
- select.AddAttribute("builtin", "select");
- store.AddAttribute("builtin", "store");
- } else {
- AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
- abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
- AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
- abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // The normal axioms of the theory of arrays (right now without extensionality)
-
- private VCExpr Select(Function select, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes) {
- Contract.Requires(map != null);
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Requires(cce.NonNullElements(types));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>();
- selectArgs.AddRange(HelperFuns.ToVCExprList(types));
- selectArgs.Add(map);
- selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- return Gen.Function(select, selectArgs);
- }
-
- private VCExpr Store(Function store, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
- Contract.Requires(val != null);
- Contract.Requires(map != null);
- Contract.Requires(store != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Requires(cce.NonNullElements(types));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>();
- storeArgs.AddRange(HelperFuns.ToVCExprList(types));
- storeArgs.Add(map);
- storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- storeArgs.Add(val);
- return Gen.Function(store, storeArgs);
- }
-
- private VCExpr/*!*/ GenMapAxiom0(Function/*!*/ select, Function/*!*/ store,
- // bound type variables in the map type
- int mapTypeParamNum,
- // free type variables in the map
- // type (abstraction)
- int mapAbstractionVarNum) {
- Contract.Requires(select != null);
- Contract.Requires(store != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
- List<VCExprVar/*!*/>/*!*/ types =
- HelperFuns.VarVector("t", mapTypeParamNum + mapAbstractionVarNum,
- AxBuilder.T, Gen);
-
- List<Type/*!*/> indexTypes = new List<Type/*!*/>();
- for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
- indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(arity == indexTypes.Count);
-
- List<VCExprVar/*!*/>/*!*/ indexes = HelperFuns.VarVector("x", indexTypes, Gen);
-
- VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
- Contract.Assert(m != null);
- VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- Contract.Assert(val != null);
-
- VCExpr/*!*/ storeExpr = Store(store, types, m, indexes, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, types, storeExpr, indexes);
- Contract.Assert(selectExpr != null);
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
- quantifiedVars.AddRange(types);
- quantifiedVars.Add(val);
- quantifiedVars.Add(m);
- quantifiedVars.AddRange(indexes);
-
- VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
- Contract.Assert(eq != null);
- return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, eq);
- }
-
- private VCExpr/*!*/ GenMapAxiom1(Function/*!*/ select, Function/*!*/ store,
- // bound type variables in the map
- // type
- int mapTypeParamNum,
- // free type variables in the map
- // type (abstraction)
- int mapAbstractionVarNum) {
- Contract.Requires(select != null);
- Contract.Requires(store != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
-
- List<VCExprVar/*!*/>/*!*/ freeTypeVars =
- HelperFuns.VarVector("u", mapAbstractionVarNum, AxBuilder.T, Gen);
- List<VCExprVar/*!*/>/*!*/ boundTypeVars0 =
- HelperFuns.VarVector("s", mapTypeParamNum, AxBuilder.T, Gen);
- List<VCExprVar/*!*/>/*!*/ boundTypeVars1 =
- HelperFuns.VarVector("t", mapTypeParamNum, AxBuilder.T, Gen);
-
- List<VCExprVar/*!*/>/*!*/ types0 = new List<VCExprVar/*!*/>(boundTypeVars0);
- types0.AddRange(freeTypeVars);
-
- List<VCExprVar/*!*/>/*!*/ types1 = new List<VCExprVar/*!*/>(boundTypeVars1);
- types1.AddRange(freeTypeVars);
-
- List<Type/*!*/> indexTypes = new List<Type/*!*/>();
- for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
- indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(arity == indexTypes.Count);
-
- List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
- List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
-
- VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
- Contract.Assert(m != null);
- VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- Contract.Assert(val != null);
-
- VCExpr/*!*/ storeExpr = Store(store, types0, m, indexes0, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectWithoutStoreExpr = Select(select, types1, m, indexes1);
- Contract.Assert(selectWithoutStoreExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, types1, storeExpr, indexes1);
- Contract.Assert(selectExpr != null);
-
- VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
- Contract.Assert(selectEq != null);
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
- quantifiedVars.AddRange(freeTypeVars);
- quantifiedVars.AddRange(boundTypeVars0);
- quantifiedVars.AddRange(boundTypeVars1);
- quantifiedVars.Add(val);
- quantifiedVars.Add(m);
- quantifiedVars.AddRange(indexes0);
- quantifiedVars.AddRange(indexes1);
-
- List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
-
- // different value arguments or different type arguments are sufficient
- // to conclude that that value of the map at some point (after an update)
- // has not changed
-
- List<VCExpr/*!*/>/*!*/ indexEqs = new List<VCExpr/*!*/>();
- for (int i = 0; i < mapTypeParamNum; ++i)
- indexEqs.Add(Gen.Eq(boundTypeVars0[i], boundTypeVars1[i]));
- for (int i = 0; i < arity; ++i)
- indexEqs.Add(Gen.Eq(indexes0[i], indexes1[i]));
-
- VCExpr/*!*/ axiom = VCExpressionGenerator.True;
- int n = 0;
- foreach (VCExpr/*!*/ indexesEq in indexEqs) {
- Contract.Assert(indexesEq != null);
- VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
- Contract.Assert(matrix != null);
- VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + n, 0, matrix);
- Contract.Assert(conjunct != null);
- axiom = Gen.AndSimp(axiom, conjunct);
- n = n + 1;
- }
-
- return axiom;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class TypeEraserArguments : TypeEraser {
-
- private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderArguments != null);
- }
-
-
- private OpTypeEraser OpEraserAttr = null;
- protected override OpTypeEraser/*!*/ OpEraser {
- get {
- Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
-
- if (OpEraserAttr == null)
- OpEraserAttr = new OpTypeEraserArguments(this, AxBuilderArguments, Gen);
- return OpEraserAttr;
- }
- }
-
- public TypeEraserArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(axBuilder, gen){
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderArguments = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
- Contract.Requires(oldBindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VariableBindings/*!*/ bindings = oldBindings.Clone();
-
- // bound term variables are replaced with bound term variables
- // typed in a simpler way
- List<VCExprVar/*!*/>/*!*/ newBoundVars =
- BoundVarsAfterErasure(node.BoundVars, bindings);
-
- // type variables are replaced with ordinary quantified variables
- GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings);
- VCExpr/*!*/ newNode = HandleQuantifier(node, newBoundVars, bindings);
- Contract.Assert(newNode != null);
-
- if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
- return newNode;
-
- VariableBindings/*!*/ bindings2;
- if (!RedoQuantifier(node, (VCExprQuantifier)newNode, node.BoundVars, oldBindings,
- out bindings2, out newBoundVars))
- return newNode;
-
- GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings2);
- return HandleQuantifier(node, newBoundVars, bindings2);
- }
-
- private void GenBoundVarsForTypeParams(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(cce.NonNullElements(newBoundVars));
- foreach (TypeVariable/*!*/ tvar in typeParams) {
- Contract.Assert(tvar != null);
- VCExprVar/*!*/ var = Gen.Variable(tvar.Name, AxBuilder.T);
- Contract.Assert(var != null);
- newBoundVars.Add(var);
- bindings.TypeVariableBindings.Add(tvar, var);
- }
- }
-
- private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings){
-Contract.Requires(bindings != null);
-Contract.Requires(node != null);
-Contract.Requires(cce.NonNullElements(newBoundVars));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
- Contract.Assert(cce.NonNullElements(newTriggers));
- VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
- Contract.Assert(newBody != null);
- newBody = AxBuilder.Cast(newBody, Type.Bool);
-
- if (newBoundVars.Count == 0) // might happen that no bound variables are left
- return newBody;
- return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
- newTriggers, node.Infos, newBody);
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class OpTypeEraserArguments : OpTypeEraser {
-
- protected readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderArguments != null);
- }
-
-
- public OpTypeEraserArguments(TypeEraserArguments eraser, TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(eraser, axBuilder, gen){
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- Contract.Requires(eraser != null);
- this.AxBuilderArguments = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private VCExpr AssembleOpExpression(OpTypesPair opTypes, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings){
-Contract.Requires(bindings != null);
-Contract.Requires(cce.NonNullElements(oldArgs));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = 0;
-
- List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/> ();
- // explicit type parameters
- foreach (Type/*!*/ t in opTypes.Types){
- Contract.Assert(newArgs != null);
- newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));}
-
- // and the actual value parameters
- Function/*!*/ newFun = ((VCExprBoogieFunctionOp)opTypes.Op).Func;
- // ^ we only allow this operator at this point
- int i = opTypes.Types.Count;
- foreach (VCExpr/*!*/ arg in oldArgs) {
- Contract.Assert(arg != null);
- newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings),
- cce.NonNull(newFun.InParams[i]).TypedIdent.Type));
- i = i + 1;
- }
-
- Eraser.Polarity = oldPolarity;
- return Gen.Function(opTypes.Op, newArgs);
- }
-
- // for the time being, we store both the types of the arguments and the explicit
- // type parameters (for most operators, this is more than actually necessary)
- private OpTypesPair OriginalOpTypes(VCExprNAry node){
-Contract.Requires(node != null);
- List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/> ();
- foreach (VCExpr/*!*/ expr in node) {
- Contract.Assert(expr != null);
- originalTypes.Add(expr.Type);
- }
- originalTypes.AddRange(node.TypeArguments);
- return new OpTypesPair (node.Op, originalTypes);
- }
-
- private VCExpr EqualTypes(Type t0, Type t1, VariableBindings bindings){
-Contract.Requires(bindings != null);
-Contract.Requires(t1 != null);
-Contract.Requires(t0 != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (t0.Equals(t1))
- return VCExpressionGenerator.True;
- VCExpr/*!*/ t0Expr = AxBuilder.Type2Term(t0, bindings.TypeVariableBindings);
- Contract.Assert(t0Expr != null);
- VCExpr/*!*/ t1Expr = AxBuilder.Type2Term(t1, bindings.TypeVariableBindings);
- Contract.Assert(t1Expr != null);
- return Gen.Eq(t0Expr, t1Expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // we also have to state that the types are equal, because the
- // translation does not contain any information about the
- // relationship between values and types
- return Gen.AndSimp(base.VisitEqOp(node, bindings),
- EqualTypes(node[0].Type, node[1].Type, bindings));
- }
-
- public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // we also have to state that the types are (un)equal, because the
- // translation does not contain any information about the
- // relationship between values and types
- return Gen.OrSimp(base.VisitNeqOp(node, bindings),
- Gen.Not(EqualTypes(node[0].Type, node[1].Type, bindings)));
- }
-
- public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = 0;
-
- VCExpr/*!*/ res =
- Gen.Function(VCExpressionGenerator.Subtype3Op,
- AxBuilder.Type2Term(node[0].Type,
- bindings.TypeVariableBindings),
- AxBuilder.Cast(Eraser.Mutate(node[0], bindings),
- AxBuilder.U),
- AxBuilder.Cast(Eraser.Mutate(node[1], bindings),
- AxBuilder.U));
-
- Eraser.Polarity = oldPolarity;
- return res;
- }
-
- public override VCExpr VisitSelectOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- OpTypesPair originalOpTypes = OriginalOpTypes(node);
- OpTypesPair newOpTypes;
-
- if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
- MapType/*!*/ rawType = node[0].Type.AsMap;
- Contract.Assert(rawType != null);
- List<Type>/*!*/ abstractionInstantiation;
- Function/*!*/ select =
- AxBuilder.MapTypeAbstracter.Select(rawType, out abstractionInstantiation);
- Contract.Assert(abstractionInstantiation != null);
- newOpTypes = TypesPairForSelectStore(node, select, abstractionInstantiation);
- NewOpCache.Add(originalOpTypes, newOpTypes);
- }
-
- return AssembleOpExpression(newOpTypes, node, bindings);
- }
-
- public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- OpTypesPair originalOpTypes = OriginalOpTypes(node);
- OpTypesPair newOpTypes;
-
- if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
- MapType/*!*/ rawType = node[0].Type.AsMap;
- List<Type>/*!*/ abstractionInstantiation;
- Function/*!*/ store =
- AxBuilder.MapTypeAbstracter.Store(rawType, out abstractionInstantiation);
-
- newOpTypes = TypesPairForSelectStore(node, store, abstractionInstantiation);
- NewOpCache.Add(originalOpTypes, newOpTypes);
- }
-
- return AssembleOpExpression(newOpTypes, node, bindings);
- }
-
- private OpTypesPair TypesPairForSelectStore(VCExprNAry/*!*/ node, Function/*!*/ untypedOp,
- // instantiation of the abstract map type parameters
- List<Type>/*!*/ abstractionInstantiation) {
- Contract.Requires(node != null);
- Contract.Requires(untypedOp != null);
- Contract.Requires(abstractionInstantiation != null);
-
- List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
- foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
-// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
- inferredTypeArgs.Add(t);}
- foreach (Type/*!*/ t in abstractionInstantiation) {
- Contract.Assert(t != null);
- inferredTypeArgs.Add(t);}
-
- Contract.Assert(untypedOp.InParams.Count == inferredTypeArgs.Count + node.Arity);
- return new OpTypesPair (Gen.BoogieFunctionOp(untypedOp), inferredTypeArgs);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- OpTypesPair originalOpTypes = OriginalOpTypes(node);
- OpTypesPair newOpTypes;
-
- if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
- Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
- Contract.Assert(oriFun != null);
- List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
- foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
-// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
- inferredTypeArgs.Add(t);}
-
- VCExprOp/*!*/ newOp = Gen.BoogieFunctionOp(AxBuilderArguments.Typed2Untyped(oriFun));
- newOpTypes = new OpTypesPair (newOp, inferredTypeArgs);
-
- NewOpCache.Add(originalOpTypes, newOpTypes);
- }
-
- return AssembleOpExpression(newOpTypes, node, bindings);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- // cache from the typed operators to the untyped operators with
- // explicit type arguments. the keys are pairs of the typed
- // operator and the actual types of the argument expressions, the
- // values are pairs of the new operators and the types that have
- // to be given as explicit type arguments
- private readonly IDictionary<OpTypesPair, OpTypesPair>/*!*/ NewOpCache =
- new Dictionary<OpTypesPair, OpTypesPair>();
-
- private struct OpTypesPair {
- public readonly VCExprOp/*!*/ Op;
- public readonly List<Type/*!*/>/*!*/ Types;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- Contract.Invariant(cce.NonNullElements(Types));
- }
-
-
- public OpTypesPair(VCExprOp op, List<Type/*!*/>/*!*/ types) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(types));
- this.Op = op;
- this.Types = types;
- this.HashCode = HFNS.PolyHash(op.GetHashCode(), 17, types);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (that is OpTypesPair) {
- OpTypesPair thatPair = (OpTypesPair)that;
- return this.Op.Equals(thatPair.Op) &&
- HFNS.SameElements(this.Types, thatPair.Types);
- }
- return false;
- }
-
- private readonly int HashCode;
-
- [Pure]
- public override int GetHashCode() {
- return HashCode;
- }
- }
- }
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Erasure of types using explicit type parameters for functions
+
+namespace Microsoft.Boogie.TypeErasure {
+ using Microsoft.Boogie.VCExprAST;
+ using HFNS = Microsoft.Boogie.VCExprAST.HelperFuns;
+
+ public class TypeAxiomBuilderArguments : TypeAxiomBuilderIntBoolU {
+
+ public TypeAxiomBuilderArguments(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ Typed2UntypedFunctions = new Dictionary<Function/*!*/, Function/*!*/>();
+ }
+
+ // constructor to allow cloning
+ [NotDelayed]
+ internal TypeAxiomBuilderArguments(TypeAxiomBuilderArguments builder)
+ : base(builder) {
+ Contract.Requires(builder != null);
+ Typed2UntypedFunctions =
+ new Dictionary<Function/*!*/, Function/*!*/>(builder.Typed2UntypedFunctions);
+
+
+ MapTypeAbstracterAttr =
+ builder.MapTypeAbstracterAttr == null ?
+ null : new MapTypeAbstractionBuilderArguments(this, builder.Gen,
+ builder.MapTypeAbstracterAttr);
+ }
+
+ public override Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ return new TypeAxiomBuilderArguments(this);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))} Int2U(U2Int(x))==x"
+ // (this makes use of the assumption that only well-typed terms are generated
+ // by the SMT-solver, i.e., that U2Int is only applied to terms that actually
+ // are of type int)
+ protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCTrigger/*!*/>/*!*/ triggers;
+ VCExprVar/*!*/ var;
+ VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
+ return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, eq);
+ }
+
+ protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // nothing
+ return VCExpressionGenerator.True;
+ }
+
+ private MapTypeAbstractionBuilderArguments MapTypeAbstracterAttr = null;
+
+ internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
+
+ if (MapTypeAbstracterAttr == null)
+ MapTypeAbstracterAttr = new MapTypeAbstractionBuilderArguments(this, Gen);
+ return MapTypeAbstracterAttr;
+ }
+ }
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ //Contract.Requires(originalType != null);
+ //Contract.Requires(var != null);
+ // no axioms are needed for variable or function types
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing functions
+
+ // Globally defined functions
+ private readonly IDictionary<Function/*!*/, Function/*!*/>/*!*/ Typed2UntypedFunctions;
+ [ContractInvariantMethod]
+ void Typed2UntypedFunctionsInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedFunctions));
+ }
+
+ public Function Typed2Untyped(Function fun) {
+ Contract.Requires(fun != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Function res;
+ if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
+ Contract.Assert(fun.OutParams.Count == 1);
+
+ // if all of the parameters are int or bool, the function does
+ // not have to be changed
+ if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
+ UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type)) {
+ res = fun;
+ } else {
+ Type[]/*!*/ types = new Type[fun.TypeParameters.Count + fun.InParams.Count + 1];
+
+ int i = 0;
+ // the first arguments are the explicit type parameters
+ for (int j = 0; j < fun.TypeParameters.Count; ++j) {
+ types[i] = T;
+ i = i + 1;
+ }
+ // followed by the actual parameters
+ foreach (Variable/*!*/ x in fun.InParams) {
+ Contract.Assert(x != null);
+ types[i] = TypeAfterErasure(x.TypedIdent.Type);
+ i = i + 1;
+ }
+
+ types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
+
+ res = HelperFuns.BoogieFunction(fun.Name, types);
+ res.Attributes = fun.Attributes;
+ }
+
+ Typed2UntypedFunctions.Add(fun, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class MapTypeAbstractionBuilderArguments : MapTypeAbstractionBuilder {
+
+ private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderArguments != null);
+ }
+
+
+ internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen)
+ : base(axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderArguments builder)
+ : base(axBuilder, gen, builder) {
+ Contract.Requires(builder != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
+ //Contract.Requires(synonym != null);
+//Contract.Requires(abstractedType != null);
+Contract.Ensures(Contract.ValueAtReturn(out select) != null);
+Contract.Ensures(Contract.ValueAtReturn(out store) != null);
+ Contract.Assert(synonym.Name != null);
+ string/*!*/ baseName = synonym.Name;
+ int typeParamNum = abstractedType.FreeVariables.Count +
+ abstractedType.TypeParameters.Count;
+
+ int arity = typeParamNum + abstractedType.Arguments.Count;
+
+ Type/*!*/[]/*!*/ selectTypes = new Type/*!*/ [arity + 2];
+ Type/*!*/[]/*!*/ storeTypes = new Type/*!*/ [arity + 3];
+
+ int i = 0;
+ // Fill in the free variables and type parameters
+ for (; i < typeParamNum; i++) {
+ selectTypes[i] = AxBuilder.T;
+ storeTypes[i] = AxBuilder.T;
+ }
+ // Fill in the map type
+ if (CommandLineOptions.Clo.MonomorphicArrays) {
+ selectTypes[i] = abstractedType;
+ storeTypes[i] = abstractedType;
+ } else {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ // Fill in the index types
+ foreach (Type/*!*/ type in abstractedType.Arguments) {
+ Contract.Assert(type != null);
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type)) {
+ selectTypes[i] = type;
+ storeTypes[i] = type;
+ } else {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ }
+ // Fill in the output type for select function which also happens
+ // to be the type of the last argument to the store function
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(abstractedType.Result)) {
+ selectTypes[i] = abstractedType.Result;
+ storeTypes[i] = abstractedType.Result;
+ } else {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ // Fill in the map type which is the output of the store function
+ if (CommandLineOptions.Clo.MonomorphicArrays)
+ storeTypes[i] = abstractedType;
+ else
+ storeTypes[i] = AxBuilder.U;
+ Contract.Assert(cce.NonNullElements<Type>(selectTypes));
+ Contract.Assert(cce.NonNullElements<Type>(storeTypes));
+
+ select = HelperFuns.BoogieFunction(baseName + "Select", selectTypes);
+ store = HelperFuns.BoogieFunction(baseName + "Store", storeTypes);
+
+ if (CommandLineOptions.Clo.UseArrayTheory) {
+ select.AddAttribute("builtin", "select");
+ store.AddAttribute("builtin", "store");
+ } else {
+ AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
+ abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
+ AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
+ abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The normal axioms of the theory of arrays (right now without extensionality)
+
+ private VCExpr Select(Function select, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes) {
+ Contract.Requires(map != null);
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>();
+ selectArgs.AddRange(HelperFuns.ToVCExprList(types));
+ selectArgs.Add(map);
+ selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ return Gen.Function(select, selectArgs);
+ }
+
+ private VCExpr Store(Function store, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
+ Contract.Requires(val != null);
+ Contract.Requires(map != null);
+ Contract.Requires(store != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>();
+ storeArgs.AddRange(HelperFuns.ToVCExprList(types));
+ storeArgs.Add(map);
+ storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ storeArgs.Add(val);
+ return Gen.Function(store, storeArgs);
+ }
+
+ private VCExpr/*!*/ GenMapAxiom0(Function/*!*/ select, Function/*!*/ store,
+ // bound type variables in the map type
+ int mapTypeParamNum,
+ // free type variables in the map
+ // type (abstraction)
+ int mapAbstractionVarNum) {
+ Contract.Requires(select != null);
+ Contract.Requires(store != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
+ List<VCExprVar/*!*/>/*!*/ types =
+ HelperFuns.VarVector("t", mapTypeParamNum + mapAbstractionVarNum,
+ AxBuilder.T, Gen);
+
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>();
+ for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
+ indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(arity == indexTypes.Count);
+
+ List<VCExprVar/*!*/>/*!*/ indexes = HelperFuns.VarVector("x", indexTypes, Gen);
+
+ VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
+ Contract.Assert(m != null);
+ VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ Contract.Assert(val != null);
+
+ VCExpr/*!*/ storeExpr = Store(store, types, m, indexes, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, types, storeExpr, indexes);
+ Contract.Assert(selectExpr != null);
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
+ quantifiedVars.AddRange(types);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes);
+
+ VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
+ Contract.Assert(eq != null);
+ return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, eq);
+ }
+
+ private VCExpr/*!*/ GenMapAxiom1(Function/*!*/ select, Function/*!*/ store,
+ // bound type variables in the map
+ // type
+ int mapTypeParamNum,
+ // free type variables in the map
+ // type (abstraction)
+ int mapAbstractionVarNum) {
+ Contract.Requires(select != null);
+ Contract.Requires(store != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
+
+ List<VCExprVar/*!*/>/*!*/ freeTypeVars =
+ HelperFuns.VarVector("u", mapAbstractionVarNum, AxBuilder.T, Gen);
+ List<VCExprVar/*!*/>/*!*/ boundTypeVars0 =
+ HelperFuns.VarVector("s", mapTypeParamNum, AxBuilder.T, Gen);
+ List<VCExprVar/*!*/>/*!*/ boundTypeVars1 =
+ HelperFuns.VarVector("t", mapTypeParamNum, AxBuilder.T, Gen);
+
+ List<VCExprVar/*!*/>/*!*/ types0 = new List<VCExprVar/*!*/>(boundTypeVars0);
+ types0.AddRange(freeTypeVars);
+
+ List<VCExprVar/*!*/>/*!*/ types1 = new List<VCExprVar/*!*/>(boundTypeVars1);
+ types1.AddRange(freeTypeVars);
+
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>();
+ for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
+ indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(arity == indexTypes.Count);
+
+ List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
+ List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
+
+ VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
+ Contract.Assert(m != null);
+ VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ Contract.Assert(val != null);
+
+ VCExpr/*!*/ storeExpr = Store(store, types0, m, indexes0, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectWithoutStoreExpr = Select(select, types1, m, indexes1);
+ Contract.Assert(selectWithoutStoreExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, types1, storeExpr, indexes1);
+ Contract.Assert(selectExpr != null);
+
+ VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
+ Contract.Assert(selectEq != null);
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
+ quantifiedVars.AddRange(freeTypeVars);
+ quantifiedVars.AddRange(boundTypeVars0);
+ quantifiedVars.AddRange(boundTypeVars1);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes0);
+ quantifiedVars.AddRange(indexes1);
+
+ List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
+
+ // different value arguments or different type arguments are sufficient
+ // to conclude that that value of the map at some point (after an update)
+ // has not changed
+
+ List<VCExpr/*!*/>/*!*/ indexEqs = new List<VCExpr/*!*/>();
+ for (int i = 0; i < mapTypeParamNum; ++i)
+ indexEqs.Add(Gen.Eq(boundTypeVars0[i], boundTypeVars1[i]));
+ for (int i = 0; i < arity; ++i)
+ indexEqs.Add(Gen.Eq(indexes0[i], indexes1[i]));
+
+ VCExpr/*!*/ axiom = VCExpressionGenerator.True;
+ int n = 0;
+ foreach (VCExpr/*!*/ indexesEq in indexEqs) {
+ Contract.Assert(indexesEq != null);
+ VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
+ Contract.Assert(matrix != null);
+ VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + n, 0, matrix);
+ Contract.Assert(conjunct != null);
+ axiom = Gen.AndSimp(axiom, conjunct);
+ n = n + 1;
+ }
+
+ return axiom;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class TypeEraserArguments : TypeEraser {
+
+ private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderArguments != null);
+ }
+
+
+ private OpTypeEraser OpEraserAttr = null;
+ protected override OpTypeEraser/*!*/ OpEraser {
+ get {
+ Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
+
+ if (OpEraserAttr == null)
+ OpEraserAttr = new OpTypeEraserArguments(this, AxBuilderArguments, Gen);
+ return OpEraserAttr;
+ }
+ }
+
+ public TypeEraserArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(axBuilder, gen){
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
+ Contract.Requires(oldBindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VariableBindings/*!*/ bindings = oldBindings.Clone();
+
+ // bound term variables are replaced with bound term variables
+ // typed in a simpler way
+ List<VCExprVar/*!*/>/*!*/ newBoundVars =
+ BoundVarsAfterErasure(node.BoundVars, bindings);
+
+ // type variables are replaced with ordinary quantified variables
+ GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings);
+ VCExpr/*!*/ newNode = HandleQuantifier(node, newBoundVars, bindings);
+ Contract.Assert(newNode != null);
+
+ if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
+ return newNode;
+
+ VariableBindings/*!*/ bindings2;
+ if (!RedoQuantifier(node, (VCExprQuantifier)newNode, node.BoundVars, oldBindings,
+ out bindings2, out newBoundVars))
+ return newNode;
+
+ GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings2);
+ return HandleQuantifier(node, newBoundVars, bindings2);
+ }
+
+ private void GenBoundVarsForTypeParams(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(cce.NonNullElements(newBoundVars));
+ foreach (TypeVariable/*!*/ tvar in typeParams) {
+ Contract.Assert(tvar != null);
+ VCExprVar/*!*/ var = Gen.Variable(tvar.Name, AxBuilder.T);
+ Contract.Assert(var != null);
+ newBoundVars.Add(var);
+ bindings.TypeVariableBindings.Add(tvar, var);
+ }
+ }
+
+ private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings){
+Contract.Requires(bindings != null);
+Contract.Requires(node != null);
+Contract.Requires(cce.NonNullElements(newBoundVars));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
+ Contract.Assert(cce.NonNullElements(newTriggers));
+ VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
+ Contract.Assert(newBody != null);
+ newBody = AxBuilder.Cast(newBody, Type.Bool);
+
+ if (newBoundVars.Count == 0) // might happen that no bound variables are left
+ return newBody;
+ return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
+ newTriggers, node.Infos, newBody);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class OpTypeEraserArguments : OpTypeEraser {
+
+ protected readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderArguments != null);
+ }
+
+
+ public OpTypeEraserArguments(TypeEraserArguments eraser, TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(eraser, axBuilder, gen){
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ Contract.Requires(eraser != null);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr AssembleOpExpression(OpTypesPair opTypes, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings){
+Contract.Requires(bindings != null);
+Contract.Requires(cce.NonNullElements(oldArgs));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/> ();
+ // explicit type parameters
+ foreach (Type/*!*/ t in opTypes.Types){
+ Contract.Assert(newArgs != null);
+ newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));}
+
+ // and the actual value parameters
+ Function/*!*/ newFun = ((VCExprBoogieFunctionOp)opTypes.Op).Func;
+ // ^ we only allow this operator at this point
+ int i = opTypes.Types.Count;
+ foreach (VCExpr/*!*/ arg in oldArgs) {
+ Contract.Assert(arg != null);
+ newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings),
+ cce.NonNull(newFun.InParams[i]).TypedIdent.Type));
+ i = i + 1;
+ }
+
+ Eraser.Polarity = oldPolarity;
+ return Gen.Function(opTypes.Op, newArgs);
+ }
+
+ // for the time being, we store both the types of the arguments and the explicit
+ // type parameters (for most operators, this is more than actually necessary)
+ private OpTypesPair OriginalOpTypes(VCExprNAry node){
+Contract.Requires(node != null);
+ List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/> ();
+ foreach (VCExpr/*!*/ expr in node) {
+ Contract.Assert(expr != null);
+ originalTypes.Add(expr.Type);
+ }
+ originalTypes.AddRange(node.TypeArguments);
+ return new OpTypesPair (node.Op, originalTypes);
+ }
+
+ private VCExpr EqualTypes(Type t0, Type t1, VariableBindings bindings){
+Contract.Requires(bindings != null);
+Contract.Requires(t1 != null);
+Contract.Requires(t0 != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (t0.Equals(t1))
+ return VCExpressionGenerator.True;
+ VCExpr/*!*/ t0Expr = AxBuilder.Type2Term(t0, bindings.TypeVariableBindings);
+ Contract.Assert(t0Expr != null);
+ VCExpr/*!*/ t1Expr = AxBuilder.Type2Term(t1, bindings.TypeVariableBindings);
+ Contract.Assert(t1Expr != null);
+ return Gen.Eq(t0Expr, t1Expr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // we also have to state that the types are equal, because the
+ // translation does not contain any information about the
+ // relationship between values and types
+ return Gen.AndSimp(base.VisitEqOp(node, bindings),
+ EqualTypes(node[0].Type, node[1].Type, bindings));
+ }
+
+ public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // we also have to state that the types are (un)equal, because the
+ // translation does not contain any information about the
+ // relationship between values and types
+ return Gen.OrSimp(base.VisitNeqOp(node, bindings),
+ Gen.Not(EqualTypes(node[0].Type, node[1].Type, bindings)));
+ }
+
+ public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ VCExpr/*!*/ res =
+ Gen.Function(VCExpressionGenerator.Subtype3Op,
+ AxBuilder.Type2Term(node[0].Type,
+ bindings.TypeVariableBindings),
+ AxBuilder.Cast(Eraser.Mutate(node[0], bindings),
+ AxBuilder.U),
+ AxBuilder.Cast(Eraser.Mutate(node[1], bindings),
+ AxBuilder.U));
+
+ Eraser.Polarity = oldPolarity;
+ return res;
+ }
+
+ public override VCExpr VisitSelectOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ MapType/*!*/ rawType = node[0].Type.AsMap;
+ Contract.Assert(rawType != null);
+ List<Type>/*!*/ abstractionInstantiation;
+ Function/*!*/ select =
+ AxBuilder.MapTypeAbstracter.Select(rawType, out abstractionInstantiation);
+ Contract.Assert(abstractionInstantiation != null);
+ newOpTypes = TypesPairForSelectStore(node, select, abstractionInstantiation);
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ MapType/*!*/ rawType = node[0].Type.AsMap;
+ List<Type>/*!*/ abstractionInstantiation;
+ Function/*!*/ store =
+ AxBuilder.MapTypeAbstracter.Store(rawType, out abstractionInstantiation);
+
+ newOpTypes = TypesPairForSelectStore(node, store, abstractionInstantiation);
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ private OpTypesPair TypesPairForSelectStore(VCExprNAry/*!*/ node, Function/*!*/ untypedOp,
+ // instantiation of the abstract map type parameters
+ List<Type>/*!*/ abstractionInstantiation) {
+ Contract.Requires(node != null);
+ Contract.Requires(untypedOp != null);
+ Contract.Requires(abstractionInstantiation != null);
+
+ List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
+ foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
+// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
+ inferredTypeArgs.Add(t);}
+ foreach (Type/*!*/ t in abstractionInstantiation) {
+ Contract.Assert(t != null);
+ inferredTypeArgs.Add(t);}
+
+ Contract.Assert(untypedOp.InParams.Count == inferredTypeArgs.Count + node.Arity);
+ return new OpTypesPair (Gen.BoogieFunctionOp(untypedOp), inferredTypeArgs);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
+ Contract.Assert(oriFun != null);
+ List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
+ foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
+// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
+ inferredTypeArgs.Add(t);}
+
+ VCExprOp/*!*/ newOp = Gen.BoogieFunctionOp(AxBuilderArguments.Typed2Untyped(oriFun));
+ newOpTypes = new OpTypesPair (newOp, inferredTypeArgs);
+
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // cache from the typed operators to the untyped operators with
+ // explicit type arguments. the keys are pairs of the typed
+ // operator and the actual types of the argument expressions, the
+ // values are pairs of the new operators and the types that have
+ // to be given as explicit type arguments
+ private readonly IDictionary<OpTypesPair, OpTypesPair>/*!*/ NewOpCache =
+ new Dictionary<OpTypesPair, OpTypesPair>();
+
+ private struct OpTypesPair {
+ public readonly VCExprOp/*!*/ Op;
+ public readonly List<Type/*!*/>/*!*/ Types;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ Contract.Invariant(cce.NonNullElements(Types));
+ }
+
+
+ public OpTypesPair(VCExprOp op, List<Type/*!*/>/*!*/ types) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(types));
+ this.Op = op;
+ this.Types = types;
+ this.HashCode = HFNS.PolyHash(op.GetHashCode(), 17, types);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is OpTypesPair) {
+ OpTypesPair thatPair = (OpTypesPair)that;
+ return this.Op.Equals(thatPair.Op) &&
+ HFNS.SameElements(this.Types, thatPair.Types);
+ }
+ return false;
+ }
+
+ private readonly int HashCode;
+
+ [Pure]
+ public override int GetHashCode() {
+ return HashCode;
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/Source/VCExpr/TypeErasurePremisses.cs b/Source/VCExpr/TypeErasurePremisses.cs
index d4b36b68..dc9ad10f 100644
--- a/Source/VCExpr/TypeErasurePremisses.cs
+++ b/Source/VCExpr/TypeErasurePremisses.cs
@@ -1,1337 +1,1337 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Erasure of types using premisses (forall x :: type(x)=T ==> p(x))
-
-namespace Microsoft.Boogie.TypeErasure
-{
- using Microsoft.Boogie.VCExprAST;
-
- // When using type premisses, we can distinguish two kinds of type
- // parameters of a function or map: parameters that occur in the
- // formal argument types of the function are "implicit" because they
- // can be inferred from the actual argument types; parameters that
- // only occur in the result type of the function are "explicit"
- // because they are not inferrable and have to be given to the
- // function as additional arguments.
- //
- // The following structure is used to store the untyped version of a
- // typed function, together with the lists of implicit and explicit
- // type parameters (in the same order as they occur in the signature
- // of the original function).
-
- internal struct UntypedFunction
- {
- public readonly Function/*!*/ Fun;
- // type parameters that can be extracted from the value parameters
- public readonly List<TypeVariable/*!*/>/*!*/ ImplicitTypeParams;
- // type parameters that have to be given explicitly
- public readonly List<TypeVariable/*!*/>/*!*/ ExplicitTypeParams;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Fun != null);
- Contract.Invariant(cce.NonNullElements(ImplicitTypeParams));
- Contract.Invariant(cce.NonNullElements(ExplicitTypeParams));
- }
-
-
- public UntypedFunction(Function/*!*/ fun,
- List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
- List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
- Contract.Requires(fun != null);
- Contract.Requires(cce.NonNullElements(implicitTypeParams));
- Contract.Requires(cce.NonNullElements(explicitTypeParams));
- Fun = fun;
- ImplicitTypeParams = implicitTypeParams;
- ExplicitTypeParams = explicitTypeParams;
- }
- }
-
- public class TypeAxiomBuilderPremisses : TypeAxiomBuilderIntBoolU
- {
-
- public TypeAxiomBuilderPremisses(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- TypeFunction = HelperFuns.BoogieFunction("dummy", Type.Int);
- Typed2UntypedFunctions = new Dictionary<Function/*!*/, UntypedFunction>();
- MapTypeAbstracterAttr = null;
- }
-
- // constructor to allow cloning
- [NotDelayed]
- internal TypeAxiomBuilderPremisses(TypeAxiomBuilderPremisses builder)
- : base(builder) {
- Contract.Requires(builder != null);
- TypeFunction = builder.TypeFunction;
- Typed2UntypedFunctions =
- new Dictionary<Function/*!*/, UntypedFunction>(builder.Typed2UntypedFunctions);
-
- MapTypeAbstracterAttr =
- builder.MapTypeAbstracterAttr == null ?
- null : new MapTypeAbstractionBuilderPremisses(this, builder.Gen,
- builder.MapTypeAbstracterAttr);
- }
-
- public override Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
- return new TypeAxiomBuilderPremisses(this);
- }
-
- public override void Setup() {
- TypeFunction = HelperFuns.BoogieFunction("type", U, T);
- base.Setup();
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))}
- // type(x)=int ==> Int2U(U2Int(x))==x"
- protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCTrigger/*!*/>/*!*/ triggers;
- VCExprVar/*!*/ var;
- VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
- Contract.Assert(cce.NonNullElements(triggers));
- Contract.Assert(var != null);
- Contract.Assert(eq != null);
- VCExpr/*!*/ premiss;
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None)
- premiss = VCExpressionGenerator.True;
- else
- premiss = GenVarTypeAxiom(var, cce.NonNull(castFromU.OutParams[0]).TypedIdent.Type,
- // we don't have any bindings available
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>());
- VCExpr/*!*/ matrix = Gen.ImpliesSimp(premiss, eq);
- Contract.Assert(matrix != null);
- return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, matrix);
- }
-
- protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Type/*!*/ fromType = cce.NonNull(castToU.InParams[0]).TypedIdent.Type;
- return GenFunctionAxiom(castToU, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>(),
- HelperFuns.ToList(fromType), fromType);
- }
-
- private MapTypeAbstractionBuilderPremisses MapTypeAbstracterAttr;
-
- internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
-
- if (MapTypeAbstracterAttr == null)
- MapTypeAbstracterAttr = new MapTypeAbstractionBuilderPremisses(this, Gen);
- return MapTypeAbstracterAttr;
- }
- }
-
- internal MapTypeAbstractionBuilderPremisses/*!*/ MapTypeAbstracterPremisses {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilderPremisses>() != null);
-
- return (MapTypeAbstractionBuilderPremisses)MapTypeAbstracter;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // function that maps individuals to their type
- // the field is overwritten with its actual value in "Setup"
- private Function/*!*/ TypeFunction;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(TypeFunction != null);
- }
-
-
- public VCExpr TypeOf(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Function(TypeFunction, expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Generate type premisses and type parameter bindings for quantifiers, functions, procedures
-
- // let-bindings to extract the instantiations of type parameters
- public List<VCExprLetBinding/*!*/>/*!*/
- GenTypeParamBindings(// the original bound variables and (implicit) type parameters
- List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ oldBoundVars,
- // VariableBindings to which the translation
- // TypeVariable -> VCExprVar is added
- VariableBindings/*!*/ bindings,
- bool addTypeVarsToBindings) {
- Contract.Requires(typeParams != null);
- Contract.Requires(cce.NonNullElements(oldBoundVars));
- Contract.Requires(bindings != null);
-
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
-
- // type variables are replaced with ordinary variables that are bound using a
- // let-expression
- if (addTypeVarsToBindings) {
- foreach (TypeVariable/*!*/ tvar in typeParams) {
- Contract.Assert(tvar != null);
- bindings.TypeVariableBindings.Add(tvar, Gen.Variable(tvar.Name, T));
- }
- }
-
- // extract the values of type variables from the term variables
- List<VCExprVar/*!*/>/*!*/ UtypedVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
- List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/>(oldBoundVars.Count);
- foreach (VCExprVar var in oldBoundVars) {
- VCExprVar/*!*/ newVar = bindings.VCExprVarBindings[var];
- if (newVar.Type.Equals(U)) {
- UtypedVars.Add(newVar);
- originalTypes.Add(var.Type);
- }
- }
-
- UtypedVars.TrimExcess();
- originalTypes.TrimExcess();
-
- return BestTypeVarExtractors(typeParams, originalTypes, UtypedVars, bindings);
- }
-
-
- public VCExpr/*!*/ AddTypePremisses(List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
- VCExpr/*!*/ typePremisses, bool universal,
- VCExpr/*!*/ body) {
- Contract.Requires(cce.NonNullElements(typeVarBindings));
- Contract.Requires(typePremisses != null);
- Contract.Requires(body != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr/*!*/ bodyWithPremisses;
- if (universal)
- bodyWithPremisses = Gen.ImpliesSimp(typePremisses, body);
- else
- bodyWithPremisses = Gen.AndSimp(typePremisses, body);
-
- return Gen.Let(typeVarBindings, bodyWithPremisses);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Extract the instantiations of type variables from the concrete types of
- // term variables. E.g., for a function f<a>(x : C a), we would extract the
- // instantiation of "a" by looking at the concrete type of "x".
-
- public List<VCExprLetBinding/*!*/>/*!*/
- BestTypeVarExtractors(List<TypeVariable/*!*/>/*!*/ vars, List<Type/*!*/>/*!*/ types,
- List<VCExprVar/*!*/>/*!*/ concreteTypeSources,
- VariableBindings/*!*/ bindings) {
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(types));
- Contract.Requires(cce.NonNullElements(concreteTypeSources));
- Contract.Requires(bindings != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
-
- List<VCExprLetBinding/*!*/>/*!*/ typeParamBindings = new List<VCExprLetBinding/*!*/>();
- foreach (TypeVariable/*!*/ var in vars) {
- Contract.Assert(var != null);
- VCExpr extractor = BestTypeVarExtractor(var, types, concreteTypeSources);
- if (extractor != null)
- typeParamBindings.Add(
- Gen.LetBinding((VCExprVar)bindings.TypeVariableBindings[var],
- extractor));
- }
- return typeParamBindings;
- }
-
- private VCExpr BestTypeVarExtractor(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
- List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
- Contract.Requires(var != null);
- Contract.Requires(cce.NonNullElements(types));
- Contract.Requires(cce.NonNullElements(concreteTypeSources));
- List<VCExpr/*!*/> allExtractors = TypeVarExtractors(var, types, concreteTypeSources);
- Contract.Assert(cce.NonNullElements(allExtractors));
- if (allExtractors.Count == 0)
- return null;
-
- VCExpr bestExtractor = allExtractors[0];
- int bestExtractorSize = SizeComputingVisitor.ComputeSize(bestExtractor);
- for (int i = 1; i < allExtractors.Count; ++i) {
- int newSize = SizeComputingVisitor.ComputeSize(allExtractors[i]);
- if (newSize < bestExtractorSize) {
- bestExtractor = allExtractors[i];
- bestExtractorSize = newSize;
- }
- }
-
- return bestExtractor;
- }
-
- private List<VCExpr/*!*/>/*!*/ TypeVarExtractors(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
- List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
- Contract.Requires(var != null);
- Contract.Requires(cce.NonNullElements(types));
- Contract.Requires(cce.NonNullElements(concreteTypeSources));
- Contract.Requires((types.Count == concreteTypeSources.Count));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- for (int i = 0; i < types.Count; ++i)
- TypeVarExtractors(var, types[i], TypeOf(concreteTypeSources[i]), res);
-
- return res;
- }
-
- private void TypeVarExtractors(TypeVariable var, Type completeType, VCExpr innerTerm, List<VCExpr/*!*/>/*!*/ extractors) {
- Contract.Requires(innerTerm != null);
- Contract.Requires(completeType != null);
- Contract.Requires(var != null);
- Contract.Requires(cce.NonNullElements(extractors));
- if (completeType.IsVariable) {
- if (var.Equals(completeType)) {
- extractors.Add(innerTerm);
- } // else nothing
- } else if (completeType.IsBasic) {
- // nothing
- } else if (completeType.IsCtor) {
- CtorType/*!*/ ctorType = completeType.AsCtor;
- if (ctorType.Arguments.Count > 0) {
- // otherwise there are no chances of extracting any
- // instantiations from this type
- TypeCtorRepr repr = GetTypeCtorReprStruct(ctorType.Decl);
- for (int i = 0; i < ctorType.Arguments.Count; ++i) {
- VCExpr/*!*/ newInnerTerm = Gen.Function(repr.Dtors[i], innerTerm);
- Contract.Assert(newInnerTerm != null);
- TypeVarExtractors(var, ctorType.Arguments[i], newInnerTerm, extractors);
- }
- }
- } else if (completeType.IsMap) {
- TypeVarExtractors(var, MapTypeAbstracter.AbstractMapType(completeType.AsMap),
- innerTerm, extractors);
- } else {
- System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + completeType);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Symbols for representing functions
-
- // Globally defined functions
- private readonly IDictionary<Function/*!*/, UntypedFunction/*!*/>/*!*/ Typed2UntypedFunctions;
- [ContractInvariantMethod]
- void Typed2UntypedFunctionsInvariantMethod() {
- Contract.Invariant(Typed2UntypedFunctions != null);
- }
-
- // distinguish between implicit and explicit type parameters
- internal static void SeparateTypeParams(List<Type/*!*/>/*!*/ valueArgumentTypes,
- List<TypeVariable>/*!*/ allTypeParams,
- out List<TypeVariable/*!*/>/*!*/ implicitParams,
- out List<TypeVariable/*!*/>/*!*/ explicitParams) {
- Contract.Requires(cce.NonNullElements(valueArgumentTypes));
- Contract.Requires(allTypeParams != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitParams)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitParams)));
- List<TypeVariable>/*!*/ varsInInParamTypes = new List<TypeVariable>();
- foreach (Type/*!*/ t in valueArgumentTypes) {
- Contract.Assert(t != null);
- varsInInParamTypes.AppendWithoutDups(t.FreeVariables);
- }
-
- implicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
- explicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
-
- foreach (TypeVariable/*!*/ var in allTypeParams) {
- Contract.Assert(var != null);
- if (varsInInParamTypes.Contains(var))
- implicitParams.Add(var);
- else
- explicitParams.Add(var);
- }
-
- implicitParams.TrimExcess();
- explicitParams.TrimExcess();
- }
-
- internal UntypedFunction Typed2Untyped(Function fun) {
- Contract.Requires(fun != null);
- UntypedFunction res;
- if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
- Contract.Assert(fun.OutParams.Count == 1);
-
- // if all of the parameters are int or bool, the function does
- // not have to be changed
- if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
- UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type) &&
- fun.TypeParameters.Count == 0) {
- res = new UntypedFunction(fun, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>());
- } else {
- List<Type/*!*/>/*!*/ argTypes = new List<Type/*!*/>();
- foreach (Variable/*!*/ v in fun.InParams) {
- Contract.Assert(v != null);
- argTypes.Add(v.TypedIdent.Type);
- }
-
- List<TypeVariable/*!*/>/*!*/ implicitParams, explicitParams;
- SeparateTypeParams(argTypes, fun.TypeParameters, out implicitParams, out explicitParams);
-
- Type[]/*!*/ types = new Type[explicitParams.Count + fun.InParams.Count + 1];
- int i = 0;
- for (int j = 0; j < explicitParams.Count; ++j) {
- types[i] = T;
- i = i + 1;
- }
- for (int j = 0; j < fun.InParams.Count; ++i, ++j)
- types[i] = TypeAfterErasure(cce.NonNull(fun.InParams[j]).TypedIdent.Type);
- types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
-
- Function/*!*/ untypedFun = HelperFuns.BoogieFunction(fun.Name, types);
- Contract.Assert(untypedFun != null);
- untypedFun.Attributes = fun.Attributes;
- res = new UntypedFunction(untypedFun, implicitParams, explicitParams);
- if (U.Equals(types[types.Length - 1]))
- AddTypeAxiom(GenFunctionAxiom(res, fun));
- }
-
- Typed2UntypedFunctions.Add(fun, res);
- }
- return res;
- }
-
- private VCExpr GenFunctionAxiom(UntypedFunction fun, Function originalFun) {
- Contract.Requires(originalFun != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<Type/*!*/>/*!*/ originalInTypes = new List<Type/*!*/>(originalFun.InParams.Count);
- foreach (Formal/*!*/ f in originalFun.InParams)
- originalInTypes.Add(f.TypedIdent.Type);
-
- return GenFunctionAxiom(fun.Fun, fun.ImplicitTypeParams, fun.ExplicitTypeParams,
- originalInTypes,
- cce.NonNull(originalFun.OutParams[0]).TypedIdent.Type);
- }
-
- internal VCExpr/*!*/ GenFunctionAxiom(Function/*!*/ fun,
- List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
- List<TypeVariable/*!*/>/*!*/ explicitTypeParams,
- List<Type/*!*/>/*!*/ originalInTypes,
- Type/*!*/ originalResultType) {
- Contract.Requires(cce.NonNullElements(implicitTypeParams));
- Contract.Requires(fun != null);
- Contract.Requires(cce.NonNullElements(explicitTypeParams));
- Contract.Requires(cce.NonNullElements(originalInTypes));
- Contract.Requires(originalResultType != null);
- Contract.Requires(originalInTypes.Count + explicitTypeParams.Count == fun.InParams.Count);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) {
- return VCExpressionGenerator.True;
- }
-
- List<VCExprVar/*!*/>/*!*/ typedInputVars = new List<VCExprVar/*!*/>(originalInTypes.Count);
- int i = 0;
- foreach (Type/*!*/ t in originalInTypes) {
- Contract.Assert(t != null);
- typedInputVars.Add(Gen.Variable("arg" + i, t));
- i = i + 1;
- }
-
- VariableBindings/*!*/ bindings = new VariableBindings();
-
- // type parameters that have to be given explicitly are replaced
- // with universally quantified type variables
- List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>(explicitTypeParams.Count + typedInputVars.Count);
- foreach (TypeVariable/*!*/ var in explicitTypeParams) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, T);
- boundVars.Add(newVar);
- bindings.TypeVariableBindings.Add(var, newVar);
- }
-
- // bound term variables are replaced with bound term variables typed in
- // a simpler way
- foreach (VCExprVar/*!*/ var in typedInputVars) {
- Contract.Assert(var != null);
- Type/*!*/ newType = TypeAfterErasure(var.Type);
- Contract.Assert(newType != null);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- Contract.Assert(newVar != null);
- boundVars.Add(newVar);
- bindings.VCExprVarBindings.Add(var, newVar);
- }
-
- List<VCExprLetBinding/*!*/> typeVarBindings =
- GenTypeParamBindings(implicitTypeParams, typedInputVars, bindings, true);
- Contract.Assert(cce.NonNullElements(typeVarBindings));
-
- VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(boundVars));
- Contract.Assert(funApp != null);
- VCExpr/*!*/ conclusion = Gen.Eq(TypeOf(funApp),
- Type2Term(originalResultType, bindings.TypeVariableBindings));
- Contract.Assert(conclusion != null);
- VCExpr conclusionWithPremisses =
- // leave out antecedents of function type axioms ... they don't appear necessary,
- // because a function can always be extended to all U-values (right?)
- // AddTypePremisses(typeVarBindings, typePremisses, true, conclusion);
- Gen.Let(typeVarBindings, conclusion);
-
- if (boundVars.Count > 0) {
- List<VCTrigger/*!*/> triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
- Contract.Assert(cce.NonNullElements(triggers));
- return Gen.Forall(boundVars, triggers, "funType:" + fun.Name, -1, conclusionWithPremisses);
- } else {
- return conclusionWithPremisses;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- //Contract.Requires(originalType != null);
- //Contract.Requires(var != null);
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) return;
- AddTypeAxiom(GenVarTypeAxiom(var, originalType,
- // we don't have any bindings available
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()));
- }
-
- public VCExpr GenVarTypeAxiom(VCExprVar var, Type originalType, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
- Contract.Requires(var != null);
- Contract.Requires(originalType != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (!var.Type.Equals(originalType)) {
- VCExpr/*!*/ typeRepr = Type2Term(originalType, varMapping);
- return Gen.Eq(TypeOf(var), typeRepr);
- }
- return VCExpressionGenerator.True;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- internal class MapTypeAbstractionBuilderPremisses : MapTypeAbstractionBuilder
- {
-
- private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderPremisses != null);
- }
-
-
- internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
- : base(axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderPremisses = axBuilder;
- }
-
- // constructor for cloning
- internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderPremisses builder)
- : base(axBuilder, gen, builder) {
- Contract.Requires(builder != null);
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderPremisses = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Determine the type parameters of a map type that have to be
- // given explicitly when applying the select function (the
- // parameters that only occur in the result type of the
- // map). These parameters are given as a list of indexes sorted in
- // ascending order; the index i refers to the i'th bound variable
- // in a type <a0, a1, ..., an>[...]...
- public List<int>/*!*/ ExplicitSelectTypeParams(MapType type) {
- Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<List<int>>() != null);
-
- List<int> res;
- if (!explicitSelectTypeParamsCache.TryGetValue(type, out res)) {
- List<TypeVariable/*!*/>/*!*/ explicitParams, implicitParams;
- TypeAxiomBuilderPremisses.SeparateTypeParams(type.Arguments.ToList(),
- type.TypeParameters,
- out implicitParams,
- out explicitParams);
- res = new List<int>(explicitParams.Count);
- foreach (TypeVariable/*!*/ var in explicitParams) {
- Contract.Assert(var != null);
- res.Add(type.TypeParameters.IndexOf(var));
- }
- explicitSelectTypeParamsCache.Add(type, res);
- }
- return cce.NonNull(res);
- }
-
- private IDictionary<MapType/*!*/, List<int>/*!*/>/*!*/ explicitSelectTypeParamsCache =
- new Dictionary<MapType/*!*/, List<int>/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(explicitSelectTypeParamsCache));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
- //Contract.Requires(synonym != null);
- //Contract.Requires(abstractedType != null);
- Contract.Ensures(Contract.ValueAtReturn(out select) != null);
- Contract.Ensures(Contract.ValueAtReturn(out store) != null);
- Type/*!*/ mapTypeSynonym;
- List<TypeVariable/*!*/>/*!*/ typeParams;
- List<Type/*!*/>/*!*/ originalInTypes;
- GenTypeAxiomParams(abstractedType, synonym, out mapTypeSynonym,
- out typeParams, out originalInTypes);
-
- // select
- List<TypeVariable/*!*/>/*!*/ explicitSelectParams, implicitSelectParams;
- select = CreateAccessFun(typeParams, originalInTypes,
- abstractedType.Result, synonym.Name + "Select",
- out implicitSelectParams, out explicitSelectParams);
-
- // store, which gets one further argument: the assigned rhs
- originalInTypes.Add(abstractedType.Result);
-
- List<TypeVariable/*!*/>/*!*/ explicitStoreParams, implicitStoreParams;
- store = CreateAccessFun(typeParams, originalInTypes,
- mapTypeSynonym, synonym.Name + "Store",
- out implicitStoreParams, out explicitStoreParams);
-
- // the store function does not have any explicit type parameters
- Contract.Assert(explicitStoreParams.Count == 0);
-
- if (CommandLineOptions.Clo.UseArrayTheory) {
- select.AddAttribute("builtin", "select");
- store.AddAttribute("builtin", "store");
- } else {
- AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
- abstractedType.Result,
- implicitSelectParams, explicitSelectParams,
- originalInTypes));
- AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
- abstractedType.Result,
- explicitSelectParams));
- }
- }
-
- protected void GenTypeAxiomParams(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl,
- out Type/*!*/ mapTypeSynonym,
- out List<TypeVariable/*!*/>/*!*/ typeParams,
- out List<Type/*!*/>/*!*/ originalIndexTypes) {
- Contract.Requires(abstractedType != null);
- Contract.Requires(synonymDecl != null);
- Contract.Ensures(Contract.ValueAtReturn(out mapTypeSynonym) != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out typeParams)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out originalIndexTypes)));
- typeParams = new List<TypeVariable/*!*/>();
- typeParams.AddRange(abstractedType.TypeParameters);
- typeParams.AddRange(abstractedType.FreeVariables);
-
- originalIndexTypes = new List<Type/*!*/>(abstractedType.Arguments.Count + 1);
- List<Type>/*!*/ mapTypeParams = new List<Type>();
- foreach (TypeVariable/*!*/ var in abstractedType.FreeVariables) {
- Contract.Assert(var != null);
- mapTypeParams.Add(var);
- }
-
- if (CommandLineOptions.Clo.MonomorphicArrays)
- mapTypeSynonym = abstractedType;
- else
- mapTypeSynonym = new CtorType(Token.NoToken, synonymDecl, mapTypeParams);
-
- originalIndexTypes.Add(mapTypeSynonym);
- originalIndexTypes.AddRange(abstractedType.Arguments.ToList());
- }
-
- // method to actually create the select or store function
- private Function/*!*/ CreateAccessFun(List<TypeVariable/*!*/>/*!*/ originalTypeParams,
- List<Type/*!*/>/*!*/ originalInTypes,
- Type/*!*/ originalResult,
- string/*!*/ name,
- out List<TypeVariable/*!*/>/*!*/ implicitTypeParams, out List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
- Contract.Requires(cce.NonNullElements(originalTypeParams));
- Contract.Requires(cce.NonNullElements(originalInTypes));
- Contract.Requires(originalResult != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitTypeParams)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitTypeParams)));
-
- // select and store are basically handled like normal functions: the type
- // parameters are split into the implicit parameters, and into the parameters
- // that have to be given explicitly
- TypeAxiomBuilderPremisses.SeparateTypeParams(originalInTypes,
- new List<TypeVariable>(originalTypeParams),
- out implicitTypeParams,
- out explicitTypeParams);
-
- Type[]/*!*/ ioTypes = new Type[explicitTypeParams.Count + originalInTypes.Count + 1];
- int i = 0;
- for (; i < explicitTypeParams.Count; ++i)
- ioTypes[i] = AxBuilder.T;
- foreach (Type/*!*/ type in originalInTypes) {
- Contract.Assert(type != null);
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type))
- ioTypes[i] = type;
- else
- ioTypes[i] = AxBuilder.U;
- i++;
- }
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(originalResult))
- ioTypes[i] = originalResult;
- else
- ioTypes[i] = AxBuilder.U;
-
- Function/*!*/ res = HelperFuns.BoogieFunction(name, ioTypes);
- Contract.Assert(res != null);
-
- if (AxBuilder.U.Equals(ioTypes[i])) {
- AxBuilder.AddTypeAxiom(
- AxBuilderPremisses.GenFunctionAxiom(res,
- implicitTypeParams, explicitTypeParams,
- originalInTypes, originalResult));
- }
- return res;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // The normal axioms of the theory of arrays (without extensionality)
-
- private VCExpr/*!*/ Select(Function/*!*/ select,
- // in general, the select function has to
- // receive explicit type parameters (which
- // are here already represented as VCExpr
- // of type T)
- List<VCExpr/*!*/>/*!*/ typeParams,
- VCExpr/*!*/ map,
- List<VCExprVar/*!*/>/*!*/ indexes) {
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(map != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>(typeParams.Count + indexes.Count + 1);
- selectArgs.AddRange(typeParams);
- selectArgs.Add(map);
- selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- return Gen.Function(select, selectArgs);
- }
-
- private VCExpr Store(Function store, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
- Contract.Requires(val != null);
- Contract.Requires(map != null);
- Contract.Requires(store != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>(indexes.Count + 2);
- storeArgs.Add(map);
- storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- storeArgs.Add(val);
- return Gen.Function(store, storeArgs);
- }
-
- /// <summary>
- /// Generate:
- /// (forall m, indexes, val ::
- /// type(val) == T ==>
- /// select(store(m, indexes, val), indexes) == val)
- /// where the quantifier body is also enclosed in a let that defines portions of T, if needed.
- /// </summary>
- private VCExpr GenMapAxiom0(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ implicitTypeParamsSelect, List<TypeVariable/*!*/>/*!*/ explicitTypeParamsSelect, List<Type/*!*/>/*!*/ originalInTypes) {
- Contract.Requires(mapResult != null);
- Contract.Requires(store != null);
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(implicitTypeParamsSelect));
- Contract.Requires(cce.NonNullElements(originalInTypes));
- Contract.Requires(cce.NonNullElements(explicitTypeParamsSelect));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- int arity = store.InParams.Count - 2;
- List<VCExprVar/*!*/> inParams = new List<VCExprVar/*!*/>();
- List<VCExprVar/*!*/> quantifiedVars = new List<VCExprVar/*!*/>(store.InParams.Count);
- VariableBindings bindings = new VariableBindings();
-
- // bound variable: m
- VCExprVar typedM = Gen.Variable("m", originalInTypes[0]);
- VCExprVar m = Gen.Variable("m", AxBuilder.U);
- inParams.Add(typedM);
- quantifiedVars.Add(m);
- bindings.VCExprVarBindings.Add(typedM, m);
-
- // bound variables: indexes
- List<Type/*!*/> origIndexTypes = new List<Type/*!*/>(arity);
- List<Type/*!*/> indexTypes = new List<Type/*!*/>(arity);
- for (int i = 1; i < store.InParams.Count - 1; i++) {
- origIndexTypes.Add(originalInTypes[i]);
- indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(arity == indexTypes.Count);
- List<VCExprVar/*!*/> typedArgs = HelperFuns.VarVector("arg", origIndexTypes, Gen);
- Contract.Assert(cce.NonNullElements(typedArgs));
- List<VCExprVar/*!*/> indexes = HelperFuns.VarVector("x", indexTypes, Gen);
- Contract.Assert(cce.NonNullElements(indexes));
- Contract.Assert(typedArgs.Count == indexes.Count);
- inParams.AddRange(typedArgs);
- quantifiedVars.AddRange(indexes);
- for (int i = 0; i < arity; i++) {
- bindings.VCExprVarBindings.Add(typedArgs[i], indexes[i]);
- }
-
- // bound variable: val
- VCExprVar typedVal = Gen.Variable("val", mapResult);
- VCExprVar val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- quantifiedVars.Add(val);
- bindings.VCExprVarBindings.Add(typedVal, val);
-
- // add all type parameters into bindings
- foreach (TypeVariable tp in implicitTypeParamsSelect) {
- VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
- bindings.TypeVariableBindings.Add(tp, tVar);
- }
- List<VCExpr/*!*/> typeParams = new List<VCExpr/*!*/>(explicitTypeParamsSelect.Count);
- foreach (TypeVariable tp in explicitTypeParamsSelect) {
- VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
- bindings.TypeVariableBindings.Add(tp, tVar);
- // ... and record these explicit type-parameter arguments in typeParams
- typeParams.Add(tVar);
- }
-
- VCExpr/*!*/ storeExpr = Store(store, m, indexes, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, typeParams, storeExpr, indexes);
- Contract.Assert(selectExpr != null);
-
- // Create let-binding definitions for all type parameters.
- // The implicit ones can be phrased in terms of the types of the ordinary in-parameters, and
- // we want to make sure that they don't get phrased in terms of the out-parameter, so we pass
- // in inParams here.
- List<VCExprLetBinding/*!*/> letBindings_Implicit =
- AxBuilderPremisses.GenTypeParamBindings(implicitTypeParamsSelect, inParams, bindings, false);
- Contract.Assert(cce.NonNullElements(letBindings_Implicit));
- // The explicit ones, by definition, can only be phrased in terms of the result, so we pass
- // in List(typedVal) here.
- List<VCExprLetBinding/*!*/> letBindings_Explicit =
- AxBuilderPremisses.GenTypeParamBindings(explicitTypeParamsSelect, HelperFuns.ToList(typedVal), bindings, false);
- Contract.Assert(cce.NonNullElements(letBindings_Explicit));
-
- // generate: select(store(m, indices, val)) == val
- VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
- Contract.Assert(eq != null);
- // generate: type(val) == T, where T is the type of val
- VCExpr/*!*/ ante = Gen.Eq(
- AxBuilderPremisses.TypeOf(val),
- AxBuilderPremisses.Type2Term(mapResult, bindings.TypeVariableBindings));
- Contract.Assert(ante != null);
- VCExpr body;
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None ||
- !AxBuilder.U.Equals(cce.NonNull(select.OutParams[0]).TypedIdent.Type)) {
- body = Gen.Let(letBindings_Explicit, eq);
- } else {
- body = Gen.Let(letBindings_Implicit, Gen.Let(letBindings_Explicit, Gen.ImpliesSimp(ante, eq)));
- }
- return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, body);
- }
-
- private VCExpr GenMapAxiom1(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ explicitSelectParams) {
- Contract.Requires(mapResult != null);
- Contract.Requires(store != null);
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(explicitSelectParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- int arity = store.InParams.Count - 2;
-
- List<Type/*!*/> indexTypes = new List<Type/*!*/>();
- for (int i = 1; i < store.InParams.Count - 1; i++) {
- indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(indexTypes.Count == arity);
-
- List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
- Contract.Assert(cce.NonNullElements(indexes0));
- List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
- Contract.Assert(cce.NonNullElements(indexes1));
- VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
- Contract.Assert(m != null);
- VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- Contract.Assert(val != null);
-
- // extract the explicit type parameters from the actual result type ...
- VCExprVar/*!*/ typedVal = Gen.Variable("val", mapResult);
- Contract.Assert(typedVal != null);
- VariableBindings/*!*/ bindings = new VariableBindings();
- bindings.VCExprVarBindings.Add(typedVal, val);
-
- List<VCExprLetBinding/*!*/>/*!*/ letBindings =
- AxBuilderPremisses.GenTypeParamBindings(explicitSelectParams,
- HelperFuns.ToList(typedVal),
- bindings, true);
- Contract.Assert(cce.NonNullElements(letBindings));
-
- // ... and quantify the introduced term variables for type
- // parameters universally
- List<VCExprVar/*!*/>/*!*/ typeParams = new List<VCExprVar/*!*/>(explicitSelectParams.Count);
- List<VCExpr/*!*/>/*!*/ typeParamsExpr = new List<VCExpr/*!*/>(explicitSelectParams.Count);
- foreach (TypeVariable/*!*/ var in explicitSelectParams) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ newVar = (VCExprVar)bindings.TypeVariableBindings[var];
- Contract.Assert(newVar != null);
- typeParams.Add(newVar);
- typeParamsExpr.Add(newVar);
- }
-
- VCExpr/*!*/ storeExpr = Store(store, m, indexes0, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectWithoutStoreExpr = Select(select, typeParamsExpr, m, indexes1);
- Contract.Assert(selectWithoutStoreExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, typeParamsExpr, storeExpr, indexes1);
- Contract.Assert(selectExpr != null);
-
- VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
- Contract.Assert(selectEq != null);
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>(indexes0.Count + indexes1.Count + 2);
- quantifiedVars.Add(val);
- quantifiedVars.Add(m);
- quantifiedVars.AddRange(indexes0);
- quantifiedVars.AddRange(indexes1);
- quantifiedVars.AddRange(typeParams);
-
- List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
- Contract.Assert(cce.NonNullElements(triggers));
-
- VCExpr/*!*/ axiom = VCExpressionGenerator.True;
- Contract.Assert(axiom != null);
-
- // first non-interference criterium: the queried location is
- // different from the assigned location
- for (int i = 0; i < arity; ++i) {
- VCExpr/*!*/ indexesEq = Gen.Eq(indexes0[i], indexes1[i]);
- VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
- VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + i, 0, matrix);
- Contract.Assert(indexesEq != null);
- Contract.Assert(matrix != null);
- Contract.Assert(conjunct != null);
- axiom = Gen.AndSimp(axiom, conjunct);
- }
-
- // second non-interference criterion: the queried type is
- // different from the assigned type
- VCExpr/*!*/ typesEq = VCExpressionGenerator.True;
- foreach (VCExprLetBinding/*!*/ b in letBindings) {
- Contract.Assert(b != null);
- typesEq = Gen.AndSimp(typesEq, Gen.Eq(b.V, b.E));
- }
- VCExpr/*!*/ matrix2 = Gen.Or(typesEq, selectEq);
- VCExpr/*!*/ conjunct2 = Gen.Forall(quantifiedVars, triggers, "mapAx2:" + select.Name, 0, matrix2);
- axiom = Gen.AndSimp(axiom, conjunct2);
-
- return axiom;
- }
-
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- public class TypeEraserPremisses : TypeEraser
- {
-
- private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderPremisses != null);
- }
-
-
- private OpTypeEraser OpEraserAttr = null;
- protected override OpTypeEraser/*!*/ OpEraser {
- get {
- Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
-
- if (OpEraserAttr == null)
- OpEraserAttr = new OpTypeEraserPremisses(this, AxBuilderPremisses, Gen);
- return OpEraserAttr;
- }
- }
-
- public TypeEraserPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
- : base(axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderPremisses = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
- Contract.Requires(oldBindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VariableBindings bindings = oldBindings.Clone();
-
- // determine the bound vars that actually occur in the body or
- // in any of the triggers (if some variables do not occur, we
- // need to take special care of type parameters that only occur
- // in the types of such variables)
- FreeVariableCollector coll = new FreeVariableCollector();
- coll.Collect(node.Body);
- foreach (VCTrigger trigger in node.Triggers) {
- if (trigger.Pos)
- foreach (VCExpr/*!*/ e in trigger.Exprs) {
- Contract.Assert(e != null);
-
- coll.Collect(e);
- }
- }
-
- List<VCExprVar/*!*/> occurringVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
- foreach (VCExprVar var in node.BoundVars)
- if (coll.FreeTermVars.ContainsKey(var))
- occurringVars.Add(var);
-
- occurringVars.TrimExcess();
-
- // bound term variables are replaced with bound term variables typed in
- // a simpler way
- List<VCExprVar/*!*/>/*!*/ newBoundVars =
- BoundVarsAfterErasure(occurringVars, bindings);
- Contract.Assert(cce.NonNullElements(newBoundVars));
- VCExpr/*!*/ newNode = HandleQuantifier(node, occurringVars,
- newBoundVars, bindings);
- Contract.Assert(newNode != null);
-
- if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
- return newNode;
-
- VariableBindings bindings2;
- if (!RedoQuantifier(node, (VCExprQuantifier)newNode, occurringVars, oldBindings,
- out bindings2, out newBoundVars))
- return newNode;
-
- return HandleQuantifier(node, occurringVars,
- newBoundVars, bindings2);
- }
-
- private VCExpr/*!*/ GenTypePremisses(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
- List<VCExprVar/*!*/>/*!*/ newBoundVars,
- IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/
- typeVarTranslation,
- List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
- out List<VCTrigger/*!*/>/*!*/ triggers) {
- Contract.Requires(cce.NonNullElements(oldBoundVars));
- Contract.Requires(cce.NonNullElements(newBoundVars));
- Contract.Requires(cce.NonNullDictionaryAndValues(typeVarTranslation));
- Contract.Requires(cce.NonNullElements(typeVarBindings));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out triggers)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- // build a substitution of the type variables that it can be checked
- // whether type premisses are trivial
- VCExprSubstitution/*!*/ typeParamSubstitution = new VCExprSubstitution();
- foreach (VCExprLetBinding/*!*/ binding in typeVarBindings) {
- Contract.Assert(binding != null);
- typeParamSubstitution[binding.V] = binding.E;
- }
- SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
- Contract.Assert(substituter != null);
-
- List<VCExpr/*!*/>/*!*/ typePremisses = new List<VCExpr/*!*/>(newBoundVars.Count);
- triggers = new List<VCTrigger/*!*/>(newBoundVars.Count);
-
- for (int i = 0; i < newBoundVars.Count; ++i) {
- VCExprVar/*!*/ oldVar = oldBoundVars[i];
- Contract.Assert(oldVar != null);
- VCExprVar/*!*/ newVar = newBoundVars[i];
- Contract.Assert(newVar != null);
-
- VCExpr/*!*/ typePremiss =
- AxBuilderPremisses.GenVarTypeAxiom(newVar, oldVar.Type,
- typeVarTranslation);
- Contract.Assert(typePremiss != null);
- if (!IsTriviallyTrue(substituter.Mutate(typePremiss,
- typeParamSubstitution))) {
- typePremisses.Add(typePremiss);
- // generate a negative trigger for the variable occurrence
- // in the type premiss
- triggers.Add(Gen.Trigger(false,
- HelperFuns.ToList(AxBuilderPremisses.TypeOf(newVar))));
- }
- }
-
- typePremisses.TrimExcess();
- triggers.TrimExcess();
-
- return Gen.NAry(VCExpressionGenerator.AndOp, typePremisses);
- }
-
- // these optimisations should maybe be moved into a separate
- // visitor (peep-hole optimisations)
- private bool IsTriviallyTrue(VCExpr expr) {
- Contract.Requires(expr != null);
- if (expr.Equals(VCExpressionGenerator.True))
- return true;
-
- if (expr is VCExprNAry) {
- VCExprNAry/*!*/ naryExpr = (VCExprNAry)expr;
- Contract.Assert(naryExpr != null);
- if (naryExpr.Op.Equals(VCExpressionGenerator.EqOp) &&
- naryExpr[0].Equals(naryExpr[1]))
- return true;
- }
-
- return false;
- }
-
- private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ occurringVars/*!*/, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Requires(cce.NonNullElements(occurringVars/*!*/));
- Contract.Requires(cce.NonNullElements(newBoundVars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings =
- AxBuilderPremisses.GenTypeParamBindings(node.TypeParameters, occurringVars, bindings, true);
- Contract.Assert(typeVarBindings != null);
- // Check whether some of the type parameters could not be
- // determined from the bound variable types. In this case, we
- // quantify explicitly over these variables
- if (typeVarBindings.Count < node.TypeParameters.Count) {
- foreach (TypeVariable/*!*/ var in node.TypeParameters) {
- Contract.Assert(var != null);
- if (typeVarBindings.All(b => !b.V.Equals(var)))
- newBoundVars.Add((VCExprVar)bindings.TypeVariableBindings[var]);
- }
- }
-
- // the lists of old and new bound variables for which type
- // antecedents are to be generated
- List<VCExprVar/*!*/>/*!*/ varsWithTypeSpecs = new List<VCExprVar/*!*/>();
- List<VCExprVar/*!*/>/*!*/ newVarsWithTypeSpecs = new List<VCExprVar/*!*/>();
- if (!IsUniversalQuantifier(node) ||
- CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.Predicates) {
- foreach (VCExprVar/*!*/ oldVar in occurringVars) {
- Contract.Assert(oldVar != null);
- varsWithTypeSpecs.Add(oldVar);
- newVarsWithTypeSpecs.Add(bindings.VCExprVarBindings[oldVar]);
- }
- } // else, no type antecedents are created for any variables
-
- List<VCTrigger/*!*/>/*!*/ furtherTriggers;
- VCExpr/*!*/ typePremisses =
- GenTypePremisses(varsWithTypeSpecs, newVarsWithTypeSpecs,
- bindings.TypeVariableBindings,
- typeVarBindings, out furtherTriggers);
-
- Contract.Assert(cce.NonNullElements(furtherTriggers));
- Contract.Assert(typePremisses != null);
- List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
- Contract.Assert(cce.NonNullElements(newTriggers));
- newTriggers.AddRange(furtherTriggers);
- newTriggers = AddLets2Triggers(newTriggers, typeVarBindings);
-
- VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
- Contract.Assert(newBody != null);
-
- // assemble the new quantified formula
-
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None) {
- typePremisses = VCExpressionGenerator.True;
- }
-
- VCExpr/*!*/ bodyWithPremisses =
- AxBuilderPremisses.AddTypePremisses(typeVarBindings, typePremisses,
- node.Quan == Quantifier.ALL,
- AxBuilder.Cast(newBody, Type.Bool));
- Contract.Assert(bodyWithPremisses != null);
- if (newBoundVars.Count == 0) // might happen that no bound variables are left
- return bodyWithPremisses;
-
- foreach (VCExprVar/*!*/ v in newBoundVars) {
- Contract.Assert(v != null);
- if (v.Type == AxBuilderPremisses.U) {
- newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Int)));
- newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Bool)));
- }
- }
-
- return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
- newTriggers, node.Infos, bodyWithPremisses);
- }
-
- // check whether we need to add let-binders for any of the type
- // parameters to the triggers (otherwise, the triggers will
- // contain unbound/dangling variables for such parameters)
- private List<VCTrigger/*!*/>/*!*/ AddLets2Triggers(List<VCTrigger/*!*/>/*!*/ triggers/*!*/, List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings) {
- Contract.Requires(cce.NonNullElements(triggers/*!*/));
- Contract.Requires(cce.NonNullElements(typeVarBindings));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
- List<VCTrigger/*!*/>/*!*/ triggersWithLets = new List<VCTrigger/*!*/>(triggers.Count);
-
- foreach (VCTrigger/*!*/ t in triggers) {
- Contract.Assert(t != null);
- List<VCExpr/*!*/>/*!*/ exprsWithLets = new List<VCExpr/*!*/>(t.Exprs.Count);
-
- bool changed = false;
- foreach (VCExpr/*!*/ e in t.Exprs) {
- Contract.Assert(e != null);
- Dictionary<VCExprVar/*!*/, object>/*!*/ freeVars =
- FreeVariableCollector.FreeTermVariables(e);
- Contract.Assert(freeVars != null && cce.NonNullElements(freeVars.Keys));
- if (typeVarBindings.Any(b => freeVars.ContainsKey(b.V))) {
- exprsWithLets.Add(Gen.Let(typeVarBindings, e));
- changed = true;
- } else {
- exprsWithLets.Add(e);
- }
- }
-
- if (changed)
- triggersWithLets.Add(Gen.Trigger(t.Pos, exprsWithLets));
- else
- triggersWithLets.Add(t);
- }
-
- return triggersWithLets;
- }
-
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class OpTypeEraserPremisses : OpTypeEraser
- {
-
- private TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderPremisses != null);
- }
-
-
- public OpTypeEraserPremisses(TypeEraserPremisses eraser, TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
- : base(eraser, axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- Contract.Requires(eraser != null);
- this.AxBuilderPremisses = axBuilder;
- }
-
- private VCExpr HandleFunctionOp(Function newFun, List<Type/*!*/>/*!*/ typeArgs/*!*/, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(newFun != null);
- Contract.Requires(cce.NonNullElements(typeArgs/*!*/));
- Contract.Requires(cce.NonNullElements(oldArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = 0;
-
- List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(typeArgs.Count);
-
- // translate the explicit type arguments
- foreach (Type/*!*/ t in typeArgs) {
- Contract.Assert(t != null);
- newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
- }
-
- // recursively translate the value arguments
- foreach (VCExpr/*!*/ arg in oldArgs) {
- Contract.Assert(arg != null);
- Type/*!*/ newType = cce.NonNull(newFun.InParams[newArgs.Count]).TypedIdent.Type;
- newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings), newType));
- }
-
- Eraser.Polarity = oldPolarity;
- return Gen.Function(newFun, newArgs);
- }
-
- public override VCExpr/*!*/ VisitSelectOp(VCExprNAry/*!*/ node,
- VariableBindings/*!*/ bindings) {
- Contract.Requires(node != null); Contract.Requires(bindings != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- MapType/*!*/ mapType = node[0].Type.AsMap;
- Contract.Assert(mapType != null);
- List<Type>/*!*/ instantiations; // not used
- Function/*!*/ select =
- AxBuilder.MapTypeAbstracter.Select(mapType, out instantiations);
- Contract.Assert(select != null);
-
- List<int>/*!*/ explicitTypeParams =
- AxBuilderPremisses.MapTypeAbstracterPremisses
- .ExplicitSelectTypeParams(mapType);
- Contract.Assert(select.InParams.Count == explicitTypeParams.Count + node.Arity);
-
- List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>(explicitTypeParams.Count);
- foreach (int i in explicitTypeParams)
- typeArgs.Add(node.TypeArguments[i]);
- return HandleFunctionOp(select, typeArgs, node, bindings);
- }
-
- public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<Type>/*!*/ instantiations; // not used
- Function/*!*/ store =
- AxBuilder.MapTypeAbstracter.Store(node[0].Type.AsMap, out instantiations);
- Contract.Assert(store != null);
- return HandleFunctionOp(store,
- // the store function never has explicit
- // type parameters
- new List<Type/*!*/>(),
- node, bindings);
- }
-
- public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
- Contract.Assert(oriFun != null);
- UntypedFunction untypedFun = AxBuilderPremisses.Typed2Untyped(oriFun);
- Contract.Assert(untypedFun.Fun.InParams.Count ==
- untypedFun.ExplicitTypeParams.Count + node.Arity);
-
- List<Type/*!*/>/*!*/ typeArgs =
- ExtractTypeArgs(node,
- oriFun.TypeParameters, untypedFun.ExplicitTypeParams);
- return HandleFunctionOp(untypedFun.Fun, typeArgs, node, bindings);
- }
-
- private List<Type/*!*/>/*!*/ ExtractTypeArgs(VCExprNAry node, List<TypeVariable> allTypeParams, List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
- Contract.Requires(allTypeParams != null);
- Contract.Requires(node != null);
- Contract.Requires(cce.NonNullElements(explicitTypeParams));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- List<Type/*!*/>/*!*/ res = new List<Type/*!*/>(explicitTypeParams.Count);
- foreach (TypeVariable/*!*/ var in explicitTypeParams) {
- Contract.Assert(var != null);
- // this lookup could be optimised
- res.Add(node.TypeArguments[allTypeParams.IndexOf(var)]);
- }
- return res;
- }
- }
-
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Erasure of types using premisses (forall x :: type(x)=T ==> p(x))
+
+namespace Microsoft.Boogie.TypeErasure
+{
+ using Microsoft.Boogie.VCExprAST;
+
+ // When using type premisses, we can distinguish two kinds of type
+ // parameters of a function or map: parameters that occur in the
+ // formal argument types of the function are "implicit" because they
+ // can be inferred from the actual argument types; parameters that
+ // only occur in the result type of the function are "explicit"
+ // because they are not inferrable and have to be given to the
+ // function as additional arguments.
+ //
+ // The following structure is used to store the untyped version of a
+ // typed function, together with the lists of implicit and explicit
+ // type parameters (in the same order as they occur in the signature
+ // of the original function).
+
+ internal struct UntypedFunction
+ {
+ public readonly Function/*!*/ Fun;
+ // type parameters that can be extracted from the value parameters
+ public readonly List<TypeVariable/*!*/>/*!*/ ImplicitTypeParams;
+ // type parameters that have to be given explicitly
+ public readonly List<TypeVariable/*!*/>/*!*/ ExplicitTypeParams;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Fun != null);
+ Contract.Invariant(cce.NonNullElements(ImplicitTypeParams));
+ Contract.Invariant(cce.NonNullElements(ExplicitTypeParams));
+ }
+
+
+ public UntypedFunction(Function/*!*/ fun,
+ List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
+ List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
+ Contract.Requires(fun != null);
+ Contract.Requires(cce.NonNullElements(implicitTypeParams));
+ Contract.Requires(cce.NonNullElements(explicitTypeParams));
+ Fun = fun;
+ ImplicitTypeParams = implicitTypeParams;
+ ExplicitTypeParams = explicitTypeParams;
+ }
+ }
+
+ public class TypeAxiomBuilderPremisses : TypeAxiomBuilderIntBoolU
+ {
+
+ public TypeAxiomBuilderPremisses(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ TypeFunction = HelperFuns.BoogieFunction("dummy", Type.Int);
+ Typed2UntypedFunctions = new Dictionary<Function/*!*/, UntypedFunction>();
+ MapTypeAbstracterAttr = null;
+ }
+
+ // constructor to allow cloning
+ [NotDelayed]
+ internal TypeAxiomBuilderPremisses(TypeAxiomBuilderPremisses builder)
+ : base(builder) {
+ Contract.Requires(builder != null);
+ TypeFunction = builder.TypeFunction;
+ Typed2UntypedFunctions =
+ new Dictionary<Function/*!*/, UntypedFunction>(builder.Typed2UntypedFunctions);
+
+ MapTypeAbstracterAttr =
+ builder.MapTypeAbstracterAttr == null ?
+ null : new MapTypeAbstractionBuilderPremisses(this, builder.Gen,
+ builder.MapTypeAbstracterAttr);
+ }
+
+ public override Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ return new TypeAxiomBuilderPremisses(this);
+ }
+
+ public override void Setup() {
+ TypeFunction = HelperFuns.BoogieFunction("type", U, T);
+ base.Setup();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))}
+ // type(x)=int ==> Int2U(U2Int(x))==x"
+ protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCTrigger/*!*/>/*!*/ triggers;
+ VCExprVar/*!*/ var;
+ VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
+ Contract.Assert(cce.NonNullElements(triggers));
+ Contract.Assert(var != null);
+ Contract.Assert(eq != null);
+ VCExpr/*!*/ premiss;
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ premiss = VCExpressionGenerator.True;
+ else
+ premiss = GenVarTypeAxiom(var, cce.NonNull(castFromU.OutParams[0]).TypedIdent.Type,
+ // we don't have any bindings available
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>());
+ VCExpr/*!*/ matrix = Gen.ImpliesSimp(premiss, eq);
+ Contract.Assert(matrix != null);
+ return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, matrix);
+ }
+
+ protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Type/*!*/ fromType = cce.NonNull(castToU.InParams[0]).TypedIdent.Type;
+ return GenFunctionAxiom(castToU, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>(),
+ HelperFuns.ToList(fromType), fromType);
+ }
+
+ private MapTypeAbstractionBuilderPremisses MapTypeAbstracterAttr;
+
+ internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
+
+ if (MapTypeAbstracterAttr == null)
+ MapTypeAbstracterAttr = new MapTypeAbstractionBuilderPremisses(this, Gen);
+ return MapTypeAbstracterAttr;
+ }
+ }
+
+ internal MapTypeAbstractionBuilderPremisses/*!*/ MapTypeAbstracterPremisses {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilderPremisses>() != null);
+
+ return (MapTypeAbstractionBuilderPremisses)MapTypeAbstracter;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // function that maps individuals to their type
+ // the field is overwritten with its actual value in "Setup"
+ private Function/*!*/ TypeFunction;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(TypeFunction != null);
+ }
+
+
+ public VCExpr TypeOf(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Function(TypeFunction, expr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Generate type premisses and type parameter bindings for quantifiers, functions, procedures
+
+ // let-bindings to extract the instantiations of type parameters
+ public List<VCExprLetBinding/*!*/>/*!*/
+ GenTypeParamBindings(// the original bound variables and (implicit) type parameters
+ List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ oldBoundVars,
+ // VariableBindings to which the translation
+ // TypeVariable -> VCExprVar is added
+ VariableBindings/*!*/ bindings,
+ bool addTypeVarsToBindings) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(cce.NonNullElements(oldBoundVars));
+ Contract.Requires(bindings != null);
+
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+
+ // type variables are replaced with ordinary variables that are bound using a
+ // let-expression
+ if (addTypeVarsToBindings) {
+ foreach (TypeVariable/*!*/ tvar in typeParams) {
+ Contract.Assert(tvar != null);
+ bindings.TypeVariableBindings.Add(tvar, Gen.Variable(tvar.Name, T));
+ }
+ }
+
+ // extract the values of type variables from the term variables
+ List<VCExprVar/*!*/>/*!*/ UtypedVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
+ List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/>(oldBoundVars.Count);
+ foreach (VCExprVar var in oldBoundVars) {
+ VCExprVar/*!*/ newVar = bindings.VCExprVarBindings[var];
+ if (newVar.Type.Equals(U)) {
+ UtypedVars.Add(newVar);
+ originalTypes.Add(var.Type);
+ }
+ }
+
+ UtypedVars.TrimExcess();
+ originalTypes.TrimExcess();
+
+ return BestTypeVarExtractors(typeParams, originalTypes, UtypedVars, bindings);
+ }
+
+
+ public VCExpr/*!*/ AddTypePremisses(List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
+ VCExpr/*!*/ typePremisses, bool universal,
+ VCExpr/*!*/ body) {
+ Contract.Requires(cce.NonNullElements(typeVarBindings));
+ Contract.Requires(typePremisses != null);
+ Contract.Requires(body != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr/*!*/ bodyWithPremisses;
+ if (universal)
+ bodyWithPremisses = Gen.ImpliesSimp(typePremisses, body);
+ else
+ bodyWithPremisses = Gen.AndSimp(typePremisses, body);
+
+ return Gen.Let(typeVarBindings, bodyWithPremisses);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Extract the instantiations of type variables from the concrete types of
+ // term variables. E.g., for a function f<a>(x : C a), we would extract the
+ // instantiation of "a" by looking at the concrete type of "x".
+
+ public List<VCExprLetBinding/*!*/>/*!*/
+ BestTypeVarExtractors(List<TypeVariable/*!*/>/*!*/ vars, List<Type/*!*/>/*!*/ types,
+ List<VCExprVar/*!*/>/*!*/ concreteTypeSources,
+ VariableBindings/*!*/ bindings) {
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Requires(cce.NonNullElements(concreteTypeSources));
+ Contract.Requires(bindings != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+
+ List<VCExprLetBinding/*!*/>/*!*/ typeParamBindings = new List<VCExprLetBinding/*!*/>();
+ foreach (TypeVariable/*!*/ var in vars) {
+ Contract.Assert(var != null);
+ VCExpr extractor = BestTypeVarExtractor(var, types, concreteTypeSources);
+ if (extractor != null)
+ typeParamBindings.Add(
+ Gen.LetBinding((VCExprVar)bindings.TypeVariableBindings[var],
+ extractor));
+ }
+ return typeParamBindings;
+ }
+
+ private VCExpr BestTypeVarExtractor(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
+ List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
+ Contract.Requires(var != null);
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Requires(cce.NonNullElements(concreteTypeSources));
+ List<VCExpr/*!*/> allExtractors = TypeVarExtractors(var, types, concreteTypeSources);
+ Contract.Assert(cce.NonNullElements(allExtractors));
+ if (allExtractors.Count == 0)
+ return null;
+
+ VCExpr bestExtractor = allExtractors[0];
+ int bestExtractorSize = SizeComputingVisitor.ComputeSize(bestExtractor);
+ for (int i = 1; i < allExtractors.Count; ++i) {
+ int newSize = SizeComputingVisitor.ComputeSize(allExtractors[i]);
+ if (newSize < bestExtractorSize) {
+ bestExtractor = allExtractors[i];
+ bestExtractorSize = newSize;
+ }
+ }
+
+ return bestExtractor;
+ }
+
+ private List<VCExpr/*!*/>/*!*/ TypeVarExtractors(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
+ List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
+ Contract.Requires(var != null);
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Requires(cce.NonNullElements(concreteTypeSources));
+ Contract.Requires((types.Count == concreteTypeSources.Count));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ for (int i = 0; i < types.Count; ++i)
+ TypeVarExtractors(var, types[i], TypeOf(concreteTypeSources[i]), res);
+
+ return res;
+ }
+
+ private void TypeVarExtractors(TypeVariable var, Type completeType, VCExpr innerTerm, List<VCExpr/*!*/>/*!*/ extractors) {
+ Contract.Requires(innerTerm != null);
+ Contract.Requires(completeType != null);
+ Contract.Requires(var != null);
+ Contract.Requires(cce.NonNullElements(extractors));
+ if (completeType.IsVariable) {
+ if (var.Equals(completeType)) {
+ extractors.Add(innerTerm);
+ } // else nothing
+ } else if (completeType.IsBasic) {
+ // nothing
+ } else if (completeType.IsCtor) {
+ CtorType/*!*/ ctorType = completeType.AsCtor;
+ if (ctorType.Arguments.Count > 0) {
+ // otherwise there are no chances of extracting any
+ // instantiations from this type
+ TypeCtorRepr repr = GetTypeCtorReprStruct(ctorType.Decl);
+ for (int i = 0; i < ctorType.Arguments.Count; ++i) {
+ VCExpr/*!*/ newInnerTerm = Gen.Function(repr.Dtors[i], innerTerm);
+ Contract.Assert(newInnerTerm != null);
+ TypeVarExtractors(var, ctorType.Arguments[i], newInnerTerm, extractors);
+ }
+ }
+ } else if (completeType.IsMap) {
+ TypeVarExtractors(var, MapTypeAbstracter.AbstractMapType(completeType.AsMap),
+ innerTerm, extractors);
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + completeType);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing functions
+
+ // Globally defined functions
+ private readonly IDictionary<Function/*!*/, UntypedFunction/*!*/>/*!*/ Typed2UntypedFunctions;
+ [ContractInvariantMethod]
+ void Typed2UntypedFunctionsInvariantMethod() {
+ Contract.Invariant(Typed2UntypedFunctions != null);
+ }
+
+ // distinguish between implicit and explicit type parameters
+ internal static void SeparateTypeParams(List<Type/*!*/>/*!*/ valueArgumentTypes,
+ List<TypeVariable>/*!*/ allTypeParams,
+ out List<TypeVariable/*!*/>/*!*/ implicitParams,
+ out List<TypeVariable/*!*/>/*!*/ explicitParams) {
+ Contract.Requires(cce.NonNullElements(valueArgumentTypes));
+ Contract.Requires(allTypeParams != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitParams)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitParams)));
+ List<TypeVariable>/*!*/ varsInInParamTypes = new List<TypeVariable>();
+ foreach (Type/*!*/ t in valueArgumentTypes) {
+ Contract.Assert(t != null);
+ varsInInParamTypes.AppendWithoutDups(t.FreeVariables);
+ }
+
+ implicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
+ explicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
+
+ foreach (TypeVariable/*!*/ var in allTypeParams) {
+ Contract.Assert(var != null);
+ if (varsInInParamTypes.Contains(var))
+ implicitParams.Add(var);
+ else
+ explicitParams.Add(var);
+ }
+
+ implicitParams.TrimExcess();
+ explicitParams.TrimExcess();
+ }
+
+ internal UntypedFunction Typed2Untyped(Function fun) {
+ Contract.Requires(fun != null);
+ UntypedFunction res;
+ if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
+ Contract.Assert(fun.OutParams.Count == 1);
+
+ // if all of the parameters are int or bool, the function does
+ // not have to be changed
+ if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
+ UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type) &&
+ fun.TypeParameters.Count == 0) {
+ res = new UntypedFunction(fun, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>());
+ } else {
+ List<Type/*!*/>/*!*/ argTypes = new List<Type/*!*/>();
+ foreach (Variable/*!*/ v in fun.InParams) {
+ Contract.Assert(v != null);
+ argTypes.Add(v.TypedIdent.Type);
+ }
+
+ List<TypeVariable/*!*/>/*!*/ implicitParams, explicitParams;
+ SeparateTypeParams(argTypes, fun.TypeParameters, out implicitParams, out explicitParams);
+
+ Type[]/*!*/ types = new Type[explicitParams.Count + fun.InParams.Count + 1];
+ int i = 0;
+ for (int j = 0; j < explicitParams.Count; ++j) {
+ types[i] = T;
+ i = i + 1;
+ }
+ for (int j = 0; j < fun.InParams.Count; ++i, ++j)
+ types[i] = TypeAfterErasure(cce.NonNull(fun.InParams[j]).TypedIdent.Type);
+ types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
+
+ Function/*!*/ untypedFun = HelperFuns.BoogieFunction(fun.Name, types);
+ Contract.Assert(untypedFun != null);
+ untypedFun.Attributes = fun.Attributes;
+ res = new UntypedFunction(untypedFun, implicitParams, explicitParams);
+ if (U.Equals(types[types.Length - 1]))
+ AddTypeAxiom(GenFunctionAxiom(res, fun));
+ }
+
+ Typed2UntypedFunctions.Add(fun, res);
+ }
+ return res;
+ }
+
+ private VCExpr GenFunctionAxiom(UntypedFunction fun, Function originalFun) {
+ Contract.Requires(originalFun != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<Type/*!*/>/*!*/ originalInTypes = new List<Type/*!*/>(originalFun.InParams.Count);
+ foreach (Formal/*!*/ f in originalFun.InParams)
+ originalInTypes.Add(f.TypedIdent.Type);
+
+ return GenFunctionAxiom(fun.Fun, fun.ImplicitTypeParams, fun.ExplicitTypeParams,
+ originalInTypes,
+ cce.NonNull(originalFun.OutParams[0]).TypedIdent.Type);
+ }
+
+ internal VCExpr/*!*/ GenFunctionAxiom(Function/*!*/ fun,
+ List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
+ List<TypeVariable/*!*/>/*!*/ explicitTypeParams,
+ List<Type/*!*/>/*!*/ originalInTypes,
+ Type/*!*/ originalResultType) {
+ Contract.Requires(cce.NonNullElements(implicitTypeParams));
+ Contract.Requires(fun != null);
+ Contract.Requires(cce.NonNullElements(explicitTypeParams));
+ Contract.Requires(cce.NonNullElements(originalInTypes));
+ Contract.Requires(originalResultType != null);
+ Contract.Requires(originalInTypes.Count + explicitTypeParams.Count == fun.InParams.Count);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) {
+ return VCExpressionGenerator.True;
+ }
+
+ List<VCExprVar/*!*/>/*!*/ typedInputVars = new List<VCExprVar/*!*/>(originalInTypes.Count);
+ int i = 0;
+ foreach (Type/*!*/ t in originalInTypes) {
+ Contract.Assert(t != null);
+ typedInputVars.Add(Gen.Variable("arg" + i, t));
+ i = i + 1;
+ }
+
+ VariableBindings/*!*/ bindings = new VariableBindings();
+
+ // type parameters that have to be given explicitly are replaced
+ // with universally quantified type variables
+ List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>(explicitTypeParams.Count + typedInputVars.Count);
+ foreach (TypeVariable/*!*/ var in explicitTypeParams) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, T);
+ boundVars.Add(newVar);
+ bindings.TypeVariableBindings.Add(var, newVar);
+ }
+
+ // bound term variables are replaced with bound term variables typed in
+ // a simpler way
+ foreach (VCExprVar/*!*/ var in typedInputVars) {
+ Contract.Assert(var != null);
+ Type/*!*/ newType = TypeAfterErasure(var.Type);
+ Contract.Assert(newType != null);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ Contract.Assert(newVar != null);
+ boundVars.Add(newVar);
+ bindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ List<VCExprLetBinding/*!*/> typeVarBindings =
+ GenTypeParamBindings(implicitTypeParams, typedInputVars, bindings, true);
+ Contract.Assert(cce.NonNullElements(typeVarBindings));
+
+ VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(boundVars));
+ Contract.Assert(funApp != null);
+ VCExpr/*!*/ conclusion = Gen.Eq(TypeOf(funApp),
+ Type2Term(originalResultType, bindings.TypeVariableBindings));
+ Contract.Assert(conclusion != null);
+ VCExpr conclusionWithPremisses =
+ // leave out antecedents of function type axioms ... they don't appear necessary,
+ // because a function can always be extended to all U-values (right?)
+ // AddTypePremisses(typeVarBindings, typePremisses, true, conclusion);
+ Gen.Let(typeVarBindings, conclusion);
+
+ if (boundVars.Count > 0) {
+ List<VCTrigger/*!*/> triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
+ Contract.Assert(cce.NonNullElements(triggers));
+ return Gen.Forall(boundVars, triggers, "funType:" + fun.Name, -1, conclusionWithPremisses);
+ } else {
+ return conclusionWithPremisses;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ //Contract.Requires(originalType != null);
+ //Contract.Requires(var != null);
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) return;
+ AddTypeAxiom(GenVarTypeAxiom(var, originalType,
+ // we don't have any bindings available
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()));
+ }
+
+ public VCExpr GenVarTypeAxiom(VCExprVar var, Type originalType, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
+ Contract.Requires(var != null);
+ Contract.Requires(originalType != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (!var.Type.Equals(originalType)) {
+ VCExpr/*!*/ typeRepr = Type2Term(originalType, varMapping);
+ return Gen.Eq(TypeOf(var), typeRepr);
+ }
+ return VCExpressionGenerator.True;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ internal class MapTypeAbstractionBuilderPremisses : MapTypeAbstractionBuilder
+ {
+
+ private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderPremisses != null);
+ }
+
+
+ internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
+ : base(axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderPremisses builder)
+ : base(axBuilder, gen, builder) {
+ Contract.Requires(builder != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Determine the type parameters of a map type that have to be
+ // given explicitly when applying the select function (the
+ // parameters that only occur in the result type of the
+ // map). These parameters are given as a list of indexes sorted in
+ // ascending order; the index i refers to the i'th bound variable
+ // in a type <a0, a1, ..., an>[...]...
+ public List<int>/*!*/ ExplicitSelectTypeParams(MapType type) {
+ Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<List<int>>() != null);
+
+ List<int> res;
+ if (!explicitSelectTypeParamsCache.TryGetValue(type, out res)) {
+ List<TypeVariable/*!*/>/*!*/ explicitParams, implicitParams;
+ TypeAxiomBuilderPremisses.SeparateTypeParams(type.Arguments.ToList(),
+ type.TypeParameters,
+ out implicitParams,
+ out explicitParams);
+ res = new List<int>(explicitParams.Count);
+ foreach (TypeVariable/*!*/ var in explicitParams) {
+ Contract.Assert(var != null);
+ res.Add(type.TypeParameters.IndexOf(var));
+ }
+ explicitSelectTypeParamsCache.Add(type, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ private IDictionary<MapType/*!*/, List<int>/*!*/>/*!*/ explicitSelectTypeParamsCache =
+ new Dictionary<MapType/*!*/, List<int>/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(explicitSelectTypeParamsCache));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
+ //Contract.Requires(synonym != null);
+ //Contract.Requires(abstractedType != null);
+ Contract.Ensures(Contract.ValueAtReturn(out select) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out store) != null);
+ Type/*!*/ mapTypeSynonym;
+ List<TypeVariable/*!*/>/*!*/ typeParams;
+ List<Type/*!*/>/*!*/ originalInTypes;
+ GenTypeAxiomParams(abstractedType, synonym, out mapTypeSynonym,
+ out typeParams, out originalInTypes);
+
+ // select
+ List<TypeVariable/*!*/>/*!*/ explicitSelectParams, implicitSelectParams;
+ select = CreateAccessFun(typeParams, originalInTypes,
+ abstractedType.Result, synonym.Name + "Select",
+ out implicitSelectParams, out explicitSelectParams);
+
+ // store, which gets one further argument: the assigned rhs
+ originalInTypes.Add(abstractedType.Result);
+
+ List<TypeVariable/*!*/>/*!*/ explicitStoreParams, implicitStoreParams;
+ store = CreateAccessFun(typeParams, originalInTypes,
+ mapTypeSynonym, synonym.Name + "Store",
+ out implicitStoreParams, out explicitStoreParams);
+
+ // the store function does not have any explicit type parameters
+ Contract.Assert(explicitStoreParams.Count == 0);
+
+ if (CommandLineOptions.Clo.UseArrayTheory) {
+ select.AddAttribute("builtin", "select");
+ store.AddAttribute("builtin", "store");
+ } else {
+ AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
+ abstractedType.Result,
+ implicitSelectParams, explicitSelectParams,
+ originalInTypes));
+ AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
+ abstractedType.Result,
+ explicitSelectParams));
+ }
+ }
+
+ protected void GenTypeAxiomParams(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl,
+ out Type/*!*/ mapTypeSynonym,
+ out List<TypeVariable/*!*/>/*!*/ typeParams,
+ out List<Type/*!*/>/*!*/ originalIndexTypes) {
+ Contract.Requires(abstractedType != null);
+ Contract.Requires(synonymDecl != null);
+ Contract.Ensures(Contract.ValueAtReturn(out mapTypeSynonym) != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out typeParams)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out originalIndexTypes)));
+ typeParams = new List<TypeVariable/*!*/>();
+ typeParams.AddRange(abstractedType.TypeParameters);
+ typeParams.AddRange(abstractedType.FreeVariables);
+
+ originalIndexTypes = new List<Type/*!*/>(abstractedType.Arguments.Count + 1);
+ List<Type>/*!*/ mapTypeParams = new List<Type>();
+ foreach (TypeVariable/*!*/ var in abstractedType.FreeVariables) {
+ Contract.Assert(var != null);
+ mapTypeParams.Add(var);
+ }
+
+ if (CommandLineOptions.Clo.MonomorphicArrays)
+ mapTypeSynonym = abstractedType;
+ else
+ mapTypeSynonym = new CtorType(Token.NoToken, synonymDecl, mapTypeParams);
+
+ originalIndexTypes.Add(mapTypeSynonym);
+ originalIndexTypes.AddRange(abstractedType.Arguments.ToList());
+ }
+
+ // method to actually create the select or store function
+ private Function/*!*/ CreateAccessFun(List<TypeVariable/*!*/>/*!*/ originalTypeParams,
+ List<Type/*!*/>/*!*/ originalInTypes,
+ Type/*!*/ originalResult,
+ string/*!*/ name,
+ out List<TypeVariable/*!*/>/*!*/ implicitTypeParams, out List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
+ Contract.Requires(cce.NonNullElements(originalTypeParams));
+ Contract.Requires(cce.NonNullElements(originalInTypes));
+ Contract.Requires(originalResult != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitTypeParams)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitTypeParams)));
+
+ // select and store are basically handled like normal functions: the type
+ // parameters are split into the implicit parameters, and into the parameters
+ // that have to be given explicitly
+ TypeAxiomBuilderPremisses.SeparateTypeParams(originalInTypes,
+ new List<TypeVariable>(originalTypeParams),
+ out implicitTypeParams,
+ out explicitTypeParams);
+
+ Type[]/*!*/ ioTypes = new Type[explicitTypeParams.Count + originalInTypes.Count + 1];
+ int i = 0;
+ for (; i < explicitTypeParams.Count; ++i)
+ ioTypes[i] = AxBuilder.T;
+ foreach (Type/*!*/ type in originalInTypes) {
+ Contract.Assert(type != null);
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type))
+ ioTypes[i] = type;
+ else
+ ioTypes[i] = AxBuilder.U;
+ i++;
+ }
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(originalResult))
+ ioTypes[i] = originalResult;
+ else
+ ioTypes[i] = AxBuilder.U;
+
+ Function/*!*/ res = HelperFuns.BoogieFunction(name, ioTypes);
+ Contract.Assert(res != null);
+
+ if (AxBuilder.U.Equals(ioTypes[i])) {
+ AxBuilder.AddTypeAxiom(
+ AxBuilderPremisses.GenFunctionAxiom(res,
+ implicitTypeParams, explicitTypeParams,
+ originalInTypes, originalResult));
+ }
+ return res;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The normal axioms of the theory of arrays (without extensionality)
+
+ private VCExpr/*!*/ Select(Function/*!*/ select,
+ // in general, the select function has to
+ // receive explicit type parameters (which
+ // are here already represented as VCExpr
+ // of type T)
+ List<VCExpr/*!*/>/*!*/ typeParams,
+ VCExpr/*!*/ map,
+ List<VCExprVar/*!*/>/*!*/ indexes) {
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(map != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>(typeParams.Count + indexes.Count + 1);
+ selectArgs.AddRange(typeParams);
+ selectArgs.Add(map);
+ selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ return Gen.Function(select, selectArgs);
+ }
+
+ private VCExpr Store(Function store, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
+ Contract.Requires(val != null);
+ Contract.Requires(map != null);
+ Contract.Requires(store != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>(indexes.Count + 2);
+ storeArgs.Add(map);
+ storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ storeArgs.Add(val);
+ return Gen.Function(store, storeArgs);
+ }
+
+ /// <summary>
+ /// Generate:
+ /// (forall m, indexes, val ::
+ /// type(val) == T ==>
+ /// select(store(m, indexes, val), indexes) == val)
+ /// where the quantifier body is also enclosed in a let that defines portions of T, if needed.
+ /// </summary>
+ private VCExpr GenMapAxiom0(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ implicitTypeParamsSelect, List<TypeVariable/*!*/>/*!*/ explicitTypeParamsSelect, List<Type/*!*/>/*!*/ originalInTypes) {
+ Contract.Requires(mapResult != null);
+ Contract.Requires(store != null);
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(implicitTypeParamsSelect));
+ Contract.Requires(cce.NonNullElements(originalInTypes));
+ Contract.Requires(cce.NonNullElements(explicitTypeParamsSelect));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ int arity = store.InParams.Count - 2;
+ List<VCExprVar/*!*/> inParams = new List<VCExprVar/*!*/>();
+ List<VCExprVar/*!*/> quantifiedVars = new List<VCExprVar/*!*/>(store.InParams.Count);
+ VariableBindings bindings = new VariableBindings();
+
+ // bound variable: m
+ VCExprVar typedM = Gen.Variable("m", originalInTypes[0]);
+ VCExprVar m = Gen.Variable("m", AxBuilder.U);
+ inParams.Add(typedM);
+ quantifiedVars.Add(m);
+ bindings.VCExprVarBindings.Add(typedM, m);
+
+ // bound variables: indexes
+ List<Type/*!*/> origIndexTypes = new List<Type/*!*/>(arity);
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>(arity);
+ for (int i = 1; i < store.InParams.Count - 1; i++) {
+ origIndexTypes.Add(originalInTypes[i]);
+ indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(arity == indexTypes.Count);
+ List<VCExprVar/*!*/> typedArgs = HelperFuns.VarVector("arg", origIndexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(typedArgs));
+ List<VCExprVar/*!*/> indexes = HelperFuns.VarVector("x", indexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(indexes));
+ Contract.Assert(typedArgs.Count == indexes.Count);
+ inParams.AddRange(typedArgs);
+ quantifiedVars.AddRange(indexes);
+ for (int i = 0; i < arity; i++) {
+ bindings.VCExprVarBindings.Add(typedArgs[i], indexes[i]);
+ }
+
+ // bound variable: val
+ VCExprVar typedVal = Gen.Variable("val", mapResult);
+ VCExprVar val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ quantifiedVars.Add(val);
+ bindings.VCExprVarBindings.Add(typedVal, val);
+
+ // add all type parameters into bindings
+ foreach (TypeVariable tp in implicitTypeParamsSelect) {
+ VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
+ bindings.TypeVariableBindings.Add(tp, tVar);
+ }
+ List<VCExpr/*!*/> typeParams = new List<VCExpr/*!*/>(explicitTypeParamsSelect.Count);
+ foreach (TypeVariable tp in explicitTypeParamsSelect) {
+ VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
+ bindings.TypeVariableBindings.Add(tp, tVar);
+ // ... and record these explicit type-parameter arguments in typeParams
+ typeParams.Add(tVar);
+ }
+
+ VCExpr/*!*/ storeExpr = Store(store, m, indexes, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, typeParams, storeExpr, indexes);
+ Contract.Assert(selectExpr != null);
+
+ // Create let-binding definitions for all type parameters.
+ // The implicit ones can be phrased in terms of the types of the ordinary in-parameters, and
+ // we want to make sure that they don't get phrased in terms of the out-parameter, so we pass
+ // in inParams here.
+ List<VCExprLetBinding/*!*/> letBindings_Implicit =
+ AxBuilderPremisses.GenTypeParamBindings(implicitTypeParamsSelect, inParams, bindings, false);
+ Contract.Assert(cce.NonNullElements(letBindings_Implicit));
+ // The explicit ones, by definition, can only be phrased in terms of the result, so we pass
+ // in List(typedVal) here.
+ List<VCExprLetBinding/*!*/> letBindings_Explicit =
+ AxBuilderPremisses.GenTypeParamBindings(explicitTypeParamsSelect, HelperFuns.ToList(typedVal), bindings, false);
+ Contract.Assert(cce.NonNullElements(letBindings_Explicit));
+
+ // generate: select(store(m, indices, val)) == val
+ VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
+ Contract.Assert(eq != null);
+ // generate: type(val) == T, where T is the type of val
+ VCExpr/*!*/ ante = Gen.Eq(
+ AxBuilderPremisses.TypeOf(val),
+ AxBuilderPremisses.Type2Term(mapResult, bindings.TypeVariableBindings));
+ Contract.Assert(ante != null);
+ VCExpr body;
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None ||
+ !AxBuilder.U.Equals(cce.NonNull(select.OutParams[0]).TypedIdent.Type)) {
+ body = Gen.Let(letBindings_Explicit, eq);
+ } else {
+ body = Gen.Let(letBindings_Implicit, Gen.Let(letBindings_Explicit, Gen.ImpliesSimp(ante, eq)));
+ }
+ return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, body);
+ }
+
+ private VCExpr GenMapAxiom1(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ explicitSelectParams) {
+ Contract.Requires(mapResult != null);
+ Contract.Requires(store != null);
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(explicitSelectParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ int arity = store.InParams.Count - 2;
+
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>();
+ for (int i = 1; i < store.InParams.Count - 1; i++) {
+ indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(indexTypes.Count == arity);
+
+ List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(indexes0));
+ List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(indexes1));
+ VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
+ Contract.Assert(m != null);
+ VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ Contract.Assert(val != null);
+
+ // extract the explicit type parameters from the actual result type ...
+ VCExprVar/*!*/ typedVal = Gen.Variable("val", mapResult);
+ Contract.Assert(typedVal != null);
+ VariableBindings/*!*/ bindings = new VariableBindings();
+ bindings.VCExprVarBindings.Add(typedVal, val);
+
+ List<VCExprLetBinding/*!*/>/*!*/ letBindings =
+ AxBuilderPremisses.GenTypeParamBindings(explicitSelectParams,
+ HelperFuns.ToList(typedVal),
+ bindings, true);
+ Contract.Assert(cce.NonNullElements(letBindings));
+
+ // ... and quantify the introduced term variables for type
+ // parameters universally
+ List<VCExprVar/*!*/>/*!*/ typeParams = new List<VCExprVar/*!*/>(explicitSelectParams.Count);
+ List<VCExpr/*!*/>/*!*/ typeParamsExpr = new List<VCExpr/*!*/>(explicitSelectParams.Count);
+ foreach (TypeVariable/*!*/ var in explicitSelectParams) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ newVar = (VCExprVar)bindings.TypeVariableBindings[var];
+ Contract.Assert(newVar != null);
+ typeParams.Add(newVar);
+ typeParamsExpr.Add(newVar);
+ }
+
+ VCExpr/*!*/ storeExpr = Store(store, m, indexes0, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectWithoutStoreExpr = Select(select, typeParamsExpr, m, indexes1);
+ Contract.Assert(selectWithoutStoreExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, typeParamsExpr, storeExpr, indexes1);
+ Contract.Assert(selectExpr != null);
+
+ VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
+ Contract.Assert(selectEq != null);
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>(indexes0.Count + indexes1.Count + 2);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes0);
+ quantifiedVars.AddRange(indexes1);
+ quantifiedVars.AddRange(typeParams);
+
+ List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
+ Contract.Assert(cce.NonNullElements(triggers));
+
+ VCExpr/*!*/ axiom = VCExpressionGenerator.True;
+ Contract.Assert(axiom != null);
+
+ // first non-interference criterium: the queried location is
+ // different from the assigned location
+ for (int i = 0; i < arity; ++i) {
+ VCExpr/*!*/ indexesEq = Gen.Eq(indexes0[i], indexes1[i]);
+ VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
+ VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + i, 0, matrix);
+ Contract.Assert(indexesEq != null);
+ Contract.Assert(matrix != null);
+ Contract.Assert(conjunct != null);
+ axiom = Gen.AndSimp(axiom, conjunct);
+ }
+
+ // second non-interference criterion: the queried type is
+ // different from the assigned type
+ VCExpr/*!*/ typesEq = VCExpressionGenerator.True;
+ foreach (VCExprLetBinding/*!*/ b in letBindings) {
+ Contract.Assert(b != null);
+ typesEq = Gen.AndSimp(typesEq, Gen.Eq(b.V, b.E));
+ }
+ VCExpr/*!*/ matrix2 = Gen.Or(typesEq, selectEq);
+ VCExpr/*!*/ conjunct2 = Gen.Forall(quantifiedVars, triggers, "mapAx2:" + select.Name, 0, matrix2);
+ axiom = Gen.AndSimp(axiom, conjunct2);
+
+ return axiom;
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ public class TypeEraserPremisses : TypeEraser
+ {
+
+ private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderPremisses != null);
+ }
+
+
+ private OpTypeEraser OpEraserAttr = null;
+ protected override OpTypeEraser/*!*/ OpEraser {
+ get {
+ Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
+
+ if (OpEraserAttr == null)
+ OpEraserAttr = new OpTypeEraserPremisses(this, AxBuilderPremisses, Gen);
+ return OpEraserAttr;
+ }
+ }
+
+ public TypeEraserPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
+ : base(axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
+ Contract.Requires(oldBindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VariableBindings bindings = oldBindings.Clone();
+
+ // determine the bound vars that actually occur in the body or
+ // in any of the triggers (if some variables do not occur, we
+ // need to take special care of type parameters that only occur
+ // in the types of such variables)
+ FreeVariableCollector coll = new FreeVariableCollector();
+ coll.Collect(node.Body);
+ foreach (VCTrigger trigger in node.Triggers) {
+ if (trigger.Pos)
+ foreach (VCExpr/*!*/ e in trigger.Exprs) {
+ Contract.Assert(e != null);
+
+ coll.Collect(e);
+ }
+ }
+
+ List<VCExprVar/*!*/> occurringVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
+ foreach (VCExprVar var in node.BoundVars)
+ if (coll.FreeTermVars.ContainsKey(var))
+ occurringVars.Add(var);
+
+ occurringVars.TrimExcess();
+
+ // bound term variables are replaced with bound term variables typed in
+ // a simpler way
+ List<VCExprVar/*!*/>/*!*/ newBoundVars =
+ BoundVarsAfterErasure(occurringVars, bindings);
+ Contract.Assert(cce.NonNullElements(newBoundVars));
+ VCExpr/*!*/ newNode = HandleQuantifier(node, occurringVars,
+ newBoundVars, bindings);
+ Contract.Assert(newNode != null);
+
+ if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
+ return newNode;
+
+ VariableBindings bindings2;
+ if (!RedoQuantifier(node, (VCExprQuantifier)newNode, occurringVars, oldBindings,
+ out bindings2, out newBoundVars))
+ return newNode;
+
+ return HandleQuantifier(node, occurringVars,
+ newBoundVars, bindings2);
+ }
+
+ private VCExpr/*!*/ GenTypePremisses(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
+ List<VCExprVar/*!*/>/*!*/ newBoundVars,
+ IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/
+ typeVarTranslation,
+ List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
+ out List<VCTrigger/*!*/>/*!*/ triggers) {
+ Contract.Requires(cce.NonNullElements(oldBoundVars));
+ Contract.Requires(cce.NonNullElements(newBoundVars));
+ Contract.Requires(cce.NonNullDictionaryAndValues(typeVarTranslation));
+ Contract.Requires(cce.NonNullElements(typeVarBindings));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out triggers)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ // build a substitution of the type variables that it can be checked
+ // whether type premisses are trivial
+ VCExprSubstitution/*!*/ typeParamSubstitution = new VCExprSubstitution();
+ foreach (VCExprLetBinding/*!*/ binding in typeVarBindings) {
+ Contract.Assert(binding != null);
+ typeParamSubstitution[binding.V] = binding.E;
+ }
+ SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
+ Contract.Assert(substituter != null);
+
+ List<VCExpr/*!*/>/*!*/ typePremisses = new List<VCExpr/*!*/>(newBoundVars.Count);
+ triggers = new List<VCTrigger/*!*/>(newBoundVars.Count);
+
+ for (int i = 0; i < newBoundVars.Count; ++i) {
+ VCExprVar/*!*/ oldVar = oldBoundVars[i];
+ Contract.Assert(oldVar != null);
+ VCExprVar/*!*/ newVar = newBoundVars[i];
+ Contract.Assert(newVar != null);
+
+ VCExpr/*!*/ typePremiss =
+ AxBuilderPremisses.GenVarTypeAxiom(newVar, oldVar.Type,
+ typeVarTranslation);
+ Contract.Assert(typePremiss != null);
+ if (!IsTriviallyTrue(substituter.Mutate(typePremiss,
+ typeParamSubstitution))) {
+ typePremisses.Add(typePremiss);
+ // generate a negative trigger for the variable occurrence
+ // in the type premiss
+ triggers.Add(Gen.Trigger(false,
+ HelperFuns.ToList(AxBuilderPremisses.TypeOf(newVar))));
+ }
+ }
+
+ typePremisses.TrimExcess();
+ triggers.TrimExcess();
+
+ return Gen.NAry(VCExpressionGenerator.AndOp, typePremisses);
+ }
+
+ // these optimisations should maybe be moved into a separate
+ // visitor (peep-hole optimisations)
+ private bool IsTriviallyTrue(VCExpr expr) {
+ Contract.Requires(expr != null);
+ if (expr.Equals(VCExpressionGenerator.True))
+ return true;
+
+ if (expr is VCExprNAry) {
+ VCExprNAry/*!*/ naryExpr = (VCExprNAry)expr;
+ Contract.Assert(naryExpr != null);
+ if (naryExpr.Op.Equals(VCExpressionGenerator.EqOp) &&
+ naryExpr[0].Equals(naryExpr[1]))
+ return true;
+ }
+
+ return false;
+ }
+
+ private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ occurringVars/*!*/, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Requires(cce.NonNullElements(occurringVars/*!*/));
+ Contract.Requires(cce.NonNullElements(newBoundVars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings =
+ AxBuilderPremisses.GenTypeParamBindings(node.TypeParameters, occurringVars, bindings, true);
+ Contract.Assert(typeVarBindings != null);
+ // Check whether some of the type parameters could not be
+ // determined from the bound variable types. In this case, we
+ // quantify explicitly over these variables
+ if (typeVarBindings.Count < node.TypeParameters.Count) {
+ foreach (TypeVariable/*!*/ var in node.TypeParameters) {
+ Contract.Assert(var != null);
+ if (typeVarBindings.All(b => !b.V.Equals(bindings.TypeVariableBindings[var])))
+ newBoundVars.Add((VCExprVar)bindings.TypeVariableBindings[var]);
+ }
+ }
+
+ // the lists of old and new bound variables for which type
+ // antecedents are to be generated
+ List<VCExprVar/*!*/>/*!*/ varsWithTypeSpecs = new List<VCExprVar/*!*/>();
+ List<VCExprVar/*!*/>/*!*/ newVarsWithTypeSpecs = new List<VCExprVar/*!*/>();
+ if (!IsUniversalQuantifier(node) ||
+ CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.Predicates) {
+ foreach (VCExprVar/*!*/ oldVar in occurringVars) {
+ Contract.Assert(oldVar != null);
+ varsWithTypeSpecs.Add(oldVar);
+ newVarsWithTypeSpecs.Add(bindings.VCExprVarBindings[oldVar]);
+ }
+ } // else, no type antecedents are created for any variables
+
+ List<VCTrigger/*!*/>/*!*/ furtherTriggers;
+ VCExpr/*!*/ typePremisses =
+ GenTypePremisses(varsWithTypeSpecs, newVarsWithTypeSpecs,
+ bindings.TypeVariableBindings,
+ typeVarBindings, out furtherTriggers);
+
+ Contract.Assert(cce.NonNullElements(furtherTriggers));
+ Contract.Assert(typePremisses != null);
+ List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
+ Contract.Assert(cce.NonNullElements(newTriggers));
+ newTriggers.AddRange(furtherTriggers);
+ newTriggers = AddLets2Triggers(newTriggers, typeVarBindings);
+
+ VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
+ Contract.Assert(newBody != null);
+
+ // assemble the new quantified formula
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None) {
+ typePremisses = VCExpressionGenerator.True;
+ }
+
+ VCExpr/*!*/ bodyWithPremisses =
+ AxBuilderPremisses.AddTypePremisses(typeVarBindings, typePremisses,
+ node.Quan == Quantifier.ALL,
+ AxBuilder.Cast(newBody, Type.Bool));
+ Contract.Assert(bodyWithPremisses != null);
+ if (newBoundVars.Count == 0) // might happen that no bound variables are left
+ return bodyWithPremisses;
+
+ foreach (VCExprVar/*!*/ v in newBoundVars) {
+ Contract.Assert(v != null);
+ if (v.Type == AxBuilderPremisses.U) {
+ newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Int)));
+ newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Bool)));
+ }
+ }
+
+ return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
+ newTriggers, node.Infos, bodyWithPremisses);
+ }
+
+ // check whether we need to add let-binders for any of the type
+ // parameters to the triggers (otherwise, the triggers will
+ // contain unbound/dangling variables for such parameters)
+ private List<VCTrigger/*!*/>/*!*/ AddLets2Triggers(List<VCTrigger/*!*/>/*!*/ triggers/*!*/, List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings) {
+ Contract.Requires(cce.NonNullElements(triggers/*!*/));
+ Contract.Requires(cce.NonNullElements(typeVarBindings));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
+ List<VCTrigger/*!*/>/*!*/ triggersWithLets = new List<VCTrigger/*!*/>(triggers.Count);
+
+ foreach (VCTrigger/*!*/ t in triggers) {
+ Contract.Assert(t != null);
+ List<VCExpr/*!*/>/*!*/ exprsWithLets = new List<VCExpr/*!*/>(t.Exprs.Count);
+
+ bool changed = false;
+ foreach (VCExpr/*!*/ e in t.Exprs) {
+ Contract.Assert(e != null);
+ Dictionary<VCExprVar/*!*/, object>/*!*/ freeVars =
+ FreeVariableCollector.FreeTermVariables(e);
+ Contract.Assert(freeVars != null && cce.NonNullElements(freeVars.Keys));
+ if (typeVarBindings.Any(b => freeVars.ContainsKey(b.V))) {
+ exprsWithLets.Add(Gen.Let(typeVarBindings, e));
+ changed = true;
+ } else {
+ exprsWithLets.Add(e);
+ }
+ }
+
+ if (changed)
+ triggersWithLets.Add(Gen.Trigger(t.Pos, exprsWithLets));
+ else
+ triggersWithLets.Add(t);
+ }
+
+ return triggersWithLets;
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class OpTypeEraserPremisses : OpTypeEraser
+ {
+
+ private TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderPremisses != null);
+ }
+
+
+ public OpTypeEraserPremisses(TypeEraserPremisses eraser, TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
+ : base(eraser, axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ Contract.Requires(eraser != null);
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ private VCExpr HandleFunctionOp(Function newFun, List<Type/*!*/>/*!*/ typeArgs/*!*/, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(newFun != null);
+ Contract.Requires(cce.NonNullElements(typeArgs/*!*/));
+ Contract.Requires(cce.NonNullElements(oldArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(typeArgs.Count);
+
+ // translate the explicit type arguments
+ foreach (Type/*!*/ t in typeArgs) {
+ Contract.Assert(t != null);
+ newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
+ }
+
+ // recursively translate the value arguments
+ foreach (VCExpr/*!*/ arg in oldArgs) {
+ Contract.Assert(arg != null);
+ Type/*!*/ newType = cce.NonNull(newFun.InParams[newArgs.Count]).TypedIdent.Type;
+ newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings), newType));
+ }
+
+ Eraser.Polarity = oldPolarity;
+ return Gen.Function(newFun, newArgs);
+ }
+
+ public override VCExpr/*!*/ VisitSelectOp(VCExprNAry/*!*/ node,
+ VariableBindings/*!*/ bindings) {
+ Contract.Requires(node != null); Contract.Requires(bindings != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ MapType/*!*/ mapType = node[0].Type.AsMap;
+ Contract.Assert(mapType != null);
+ List<Type>/*!*/ instantiations; // not used
+ Function/*!*/ select =
+ AxBuilder.MapTypeAbstracter.Select(mapType, out instantiations);
+ Contract.Assert(select != null);
+
+ List<int>/*!*/ explicitTypeParams =
+ AxBuilderPremisses.MapTypeAbstracterPremisses
+ .ExplicitSelectTypeParams(mapType);
+ Contract.Assert(select.InParams.Count == explicitTypeParams.Count + node.Arity);
+
+ List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>(explicitTypeParams.Count);
+ foreach (int i in explicitTypeParams)
+ typeArgs.Add(node.TypeArguments[i]);
+ return HandleFunctionOp(select, typeArgs, node, bindings);
+ }
+
+ public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<Type>/*!*/ instantiations; // not used
+ Function/*!*/ store =
+ AxBuilder.MapTypeAbstracter.Store(node[0].Type.AsMap, out instantiations);
+ Contract.Assert(store != null);
+ return HandleFunctionOp(store,
+ // the store function never has explicit
+ // type parameters
+ new List<Type/*!*/>(),
+ node, bindings);
+ }
+
+ public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
+ Contract.Assert(oriFun != null);
+ UntypedFunction untypedFun = AxBuilderPremisses.Typed2Untyped(oriFun);
+ Contract.Assert(untypedFun.Fun.InParams.Count ==
+ untypedFun.ExplicitTypeParams.Count + node.Arity);
+
+ List<Type/*!*/>/*!*/ typeArgs =
+ ExtractTypeArgs(node,
+ oriFun.TypeParameters, untypedFun.ExplicitTypeParams);
+ return HandleFunctionOp(untypedFun.Fun, typeArgs, node, bindings);
+ }
+
+ private List<Type/*!*/>/*!*/ ExtractTypeArgs(VCExprNAry node, List<TypeVariable> allTypeParams, List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
+ Contract.Requires(allTypeParams != null);
+ Contract.Requires(node != null);
+ Contract.Requires(cce.NonNullElements(explicitTypeParams));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ List<Type/*!*/>/*!*/ res = new List<Type/*!*/>(explicitTypeParams.Count);
+ foreach (TypeVariable/*!*/ var in explicitTypeParams) {
+ Contract.Assert(var != null);
+ // this lookup could be optimised
+ res.Add(node.TypeArguments[allTypeParams.IndexOf(var)]);
+ }
+ return res;
+ }
+ }
+
+
+}
diff --git a/Source/VCExpr/VCExpr.csproj b/Source/VCExpr/VCExpr.csproj
index acacb4d1..efac274e 100644
--- a/Source/VCExpr/VCExpr.csproj
+++ b/Source/VCExpr/VCExpr.csproj
@@ -1,223 +1,223 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>VCExpr</RootNamespace>
- <AssemblyName>VCExpr</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for VCExpr.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\VCExpr.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="BigLiteralAbstracter.cs" />
- <Compile Include="Boogie2VCExpr.cs" />
- <Compile Include="Clustering.cs" />
- <Compile Include="LetBindingSorter.cs" />
- <Compile Include="NameClashResolver.cs" />
- <Compile Include="SimplifyLikeLineariser.cs" />
- <Compile Include="TermFormulaFlattening.cs" />
- <Compile Include="TypeErasure.cs" />
- <Compile Include="TypeErasureArguments.cs" />
- <Compile Include="TypeErasurePremisses.cs" />
- <Compile Include="VCExprAST.cs" />
- <Compile Include="VCExprASTPrinter.cs" />
- <Compile Include="VCExprASTVisitors.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>VCExpr</RootNamespace>
+ <AssemblyName>BoogieVCExpr</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for VCExpr.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\VCExpr.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="BigLiteralAbstracter.cs" />
+ <Compile Include="Boogie2VCExpr.cs" />
+ <Compile Include="Clustering.cs" />
+ <Compile Include="LetBindingSorter.cs" />
+ <Compile Include="NameClashResolver.cs" />
+ <Compile Include="SimplifyLikeLineariser.cs" />
+ <Compile Include="TermFormulaFlattening.cs" />
+ <Compile Include="TypeErasure.cs" />
+ <Compile Include="TypeErasureArguments.cs" />
+ <Compile Include="TypeErasurePremisses.cs" />
+ <Compile Include="VCExprAST.cs" />
+ <Compile Include="VCExprASTPrinter.cs" />
+ <Compile Include="VCExprASTVisitors.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Source/VCExpr/VCExprAST.cs b/Source/VCExpr/VCExprAST.cs
index b22853ce..b5d4dfb5 100644
--- a/Source/VCExpr/VCExprAST.cs
+++ b/Source/VCExpr/VCExprAST.cs
@@ -1,2260 +1,2276 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Prover-independent syntax trees for representing verification conditions
-// The language can be seen as a simple polymorphically typed first-order logic,
-// very similar to the expression language of Boogie
-
-namespace Microsoft.Boogie {
- using Microsoft.Boogie.VCExprAST;
-
- public class VCExpressionGenerator {
- public static readonly VCExpr False = new VCExprLiteral(Type.Bool);
- public static readonly VCExpr True = new VCExprLiteral(Type.Bool);
-
- private Function ControlFlowFunction = null;
- public VCExpr ControlFlowFunctionApplication(VCExpr e1, VCExpr e2) {
- Contract.Requires(e1 != null);
- Contract.Requires(e2 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (ControlFlowFunction == null) {
- Formal/*!*/ first = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
- Formal/*!*/ second = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
- List<Variable> inputs = new List<Variable>();
- inputs.Add(first);
- inputs.Add(second);
- Formal/*!*/ returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), false);
- ControlFlowFunction = new Function(Token.NoToken, "ControlFlow", inputs, returnVar);
- }
- List<VCExpr/*!*/> args = new List<VCExpr/*!*/>();
- args.Add(e1);
- args.Add(e2);
- return Function(BoogieFunctionOp(ControlFlowFunction), args);
- }
-
- public VCExpr/*!*/ Integer(BigNum x) {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return new VCExprIntLit(x);
- }
-
- public VCExpr/*!*/ Real(BigDec x) {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return new VCExprRealLit(x);
- }
-
- public VCExpr/*!*/ Float(BigFloat x)
- {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return new VCExprFloatLit(x);
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op,
- List<VCExpr/*!*/>/*!*/ arguments,
- List<Type/*!*/>/*!*/ typeArguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(cce.NonNullElements(typeArguments));
- if (typeArguments.Count > 0)
- return new VCExprMultiAry(op, arguments, typeArguments);
-
- switch (arguments.Count) {
- case 0:
- return new VCExprNullary(op);
- case 1:
- return new VCExprUnary(op, arguments);
- case 2:
- return new VCExprBinary(op, arguments);
- default:
- return new VCExprMultiAry(op, arguments);
- }
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(op, arguments, VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op, params VCExpr[]/*!*/ arguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
-
- return Function(op,
- HelperFuns.ToNonNullList(arguments),
- VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op, VCExpr[]/*!*/ arguments, Type[]/*!*/ typeArguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(cce.NonNullElements(typeArguments));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
-
- return Function(op,
- HelperFuns.ToNonNullList(arguments),
- HelperFuns.ToNonNullList(typeArguments));
- }
-
- public VCExpr/*!*/ Function(Function/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(BoogieFunctionOp(op), arguments, VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr/*!*/ Function(Function/*!*/ op, params VCExpr[]/*!*/ arguments) {
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(op != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(BoogieFunctionOp(op), arguments);
- }
-
-
- // The following method should really be called "ReduceLeft". It must
- // only be used for the binary operators "and" and "or"
- public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return NAry(op, args.ToArray());
- }
-
- public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, params VCExpr[]/*!*/ args) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(op == AndOp || op == OrOp);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- bool and = (op == AndOp);
-
- VCExpr/*!*/ e = and ? True : False;
- foreach (VCExpr a in args) {
- e = and ? AndSimp(e, cce.NonNull(a)) : OrSimp(e, cce.NonNull(a));
- }
- return e;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- public static readonly VCExprOp NotOp = new VCExprNAryOp(1, Type.Bool);
- public static readonly VCExprOp EqOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp NeqOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp AndOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp OrOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp ImpliesOp = new VCExprNAryOp(2, Type.Bool);
-
- public VCExprDistinctOp DistinctOp(int arity) {
- Contract.Ensures(Contract.Result<VCExprDistinctOp>() != null);
-
- return new VCExprDistinctOp(arity);
- }
-
- public VCExpr/*!*/ Not(List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(args != null);
- Contract.Requires(args.Count == 1);
- Contract.Requires(args[0] != null);
- return Function(NotOp, args);
- }
-
- public VCExpr/*!*/ Not(VCExpr/*!*/ e0) {
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(NotOp, e0);
- }
- public VCExpr/*!*/ Eq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- return Function(EqOp, e0, e1);
- }
- public VCExpr/*!*/ Neq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(NeqOp, e0, e1);
- }
- public VCExpr/*!*/ And(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(AndOp, e0, e1);
- }
- public VCExpr/*!*/ Gt(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
- {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(GtOp, e0, e1);
- }
- public VCExpr/*!*/ Add(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
- {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExprOp op = cce.NonNull(cce.NonNull(e0).Type).IsInt ? AddIOp : AddROp;
- return Function(op, e0, e1);
- }
- public VCExpr/*!*/ Or(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(OrOp, e0, e1);
- }
- public VCExpr/*!*/ Implies(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(ImpliesOp, e0, e1);
- }
- public VCExpr/*!*/ Distinct(List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (args.Count <= 1)
- // trivial case
- return True;
- return Function(DistinctOp(args.Count), args);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Versions of the propositional operators that automatically simplify in
- // certain cases (for example, if one of the operators is True or False)
-
- public VCExpr NotSimp(VCExpr e0) {
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(True))
- return False;
- if (e0.Equals(False))
- return True;
- return Not(e0);
- }
- public VCExpr AndSimp(VCExpr e0, VCExpr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(True))
- return e1;
- if (e1.Equals(True))
- return e0;
- if (e0.Equals(False) || e1.Equals(False))
- return False;
- return And(e0, e1);
- }
- public VCExpr OrSimp(VCExpr e0, VCExpr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(False))
- return e1;
- if (e1.Equals(False))
- return e0;
- if (e0.Equals(True) || e1.Equals(True))
- return True;
- return Or(e0, e1);
- }
- public VCExpr ImpliesSimp(VCExpr e0, VCExpr e1, bool aggressive = true) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(True))
- return e1;
- if (e1.Equals(False))
- return NotSimp(e0);
- if (e0.Equals(False) || e1.Equals(True))
- return True;
- // attempt to save on the depth of expressions (to reduce chances of stack overflows)
- while (aggressive && e1 is VCExprBinary) {
- VCExprBinary n = (VCExprBinary)e1;
- if (n.Op == ImpliesOp) {
- if (AndSize(n[0]) <= AndSize(e0)) {
- // combine the antecedents
- e0 = And(e0, n[0]);
- e1 = n[1];
- continue;
- }
- }
- break;
- }
- return Implies(e0, e1);
- }
-
- ///<summary>
- /// Returns some measure of the number of conjuncts in e. This could be the total number of conjuncts in all
- /// top-most layers of the expression, or it can simply be the length of the left-prong of this and-tree. The
- /// important thing is that: AndSize(e0) >= AndSize(31) ==> AndSize(And(e0,e1)) > AndSize(e0).
- ///</summary>
- int AndSize(VCExpr e) {
- Contract.Requires(e != null);
- int n = 1;
- while (true) {
- VCExprNAry nary = e as VCExprNAry;
- if (nary != null && nary.Op == AndOp && 2 <= nary.Arity) {
- e = nary[0];
- n++;
- } else {
- return n;
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Further operators
-
- public static readonly VCExprOp AddIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp AddROp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp SubIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp SubROp = new VCExprNAryOp(2, Type.Real);
- // public static readonly VCExprOp SubFOp = new VCExprNAryOp(2, Type.Float);
- public static readonly VCExprOp MulIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp MulROp = new VCExprNAryOp(2, Type.Real);
- //public static readonly VCExprOp MulFOp = new VCExprNAryOp(2, Type.Float);
- public static readonly VCExprOp DivIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp DivROp = new VCExprNAryOp(2, Type.Real);
- //public static readonly VCExprOp DivFOp = new VCExprNAryOp(2, Type.Float);
- public static readonly VCExprOp ModOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp PowOp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp LtOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp LeOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp GtOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp GeOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp SubtypeOp = new VCExprNAryOp(2, Type.Bool);
- // ternary version of the subtype operator, the first argument of which gives
- // the type of the compared terms
- public static readonly VCExprOp Subtype3Op = new VCExprNAryOp(3, Type.Bool);
- public static readonly VCExprOp IfThenElseOp = new VCExprIfThenElseOp();
- public static readonly VCExprOp ToIntOp = new VCExprNAryOp(1, Type.Int);
- public static readonly VCExprOp ToRealOp = new VCExprNAryOp(1, Type.Real);
- //public static readonly VCExprOp ToFloatOp = new VCExprNAryOp(1, Type.Float);
-
- public static readonly VCExprOp TickleBoolOp = new VCExprCustomOp("tickleBool", 1, Type.Bool);
-
- public VCExprOp BoogieFunctionOp(Function func) {
- Contract.Requires(func != null);
- Contract.Ensures(Contract.Result<VCExprOp>() != null);
- return new VCExprBoogieFunctionOp(func);
- }
-
- // Float nodes
-
- public VCExprOp BinaryFloatOp(int exp, int man, string op)
- {
- Contract.Requires(exp > 0);
- Contract.Requires(man > 0);
- Contract.Requires(op != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return new VCExprBinaryFloatOp(exp, man, op);
- }
-
- // Bitvector nodes
-
- public VCExpr Bitvector(BvConst bv) {
- Contract.Requires(bv != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprBvOp(bv.Bits), Integer(bv.Value));
- }
-
- public VCExpr BvExtract(VCExpr bv, int bits, int start, int end) {
- Contract.Requires(bv != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprBvExtractOp(start, end, bits), bv);
- }
-
- public VCExpr BvConcat(VCExpr bv1, VCExpr bv2) {
- Contract.Requires(bv2 != null);
- Contract.Requires(bv1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprBvConcatOp(bv1.Type.BvBits, bv2.Type.BvBits), bv1, bv2);
- }
-
- public VCExpr AtMost(VCExpr smaller, VCExpr greater) {
- Contract.Requires(greater != null);
- Contract.Requires(smaller != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(SubtypeOp, smaller, greater);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- // Dispatcher for the visitor
-
- // the declared singleton operators
- internal enum SingletonOp {
- NotOp,
- EqOp,
- NeqOp,
- AndOp,
- OrOp,
- ImpliesOp,
- AddOp,
- SubOp,
- MulOp,
- DivOp,
- ModOp,
- RealDivOp,
- PowOp,
- LtOp,
- LeOp,
- GtOp,
- GeOp,
- SubtypeOp,
- Subtype3Op,
- BvConcatOp,
- ToIntOp,
- ToRealOp,
- ToFloatOp
- };
- internal static Dictionary<VCExprOp/*!*/, SingletonOp>/*!*/ SingletonOpDict;
- [ContractInvariantMethod]
- void MiscInvariant() {
- Contract.Invariant(SingletonOpDict != null);
- }
-
-
- static VCExpressionGenerator() {
- SingletonOpDict = new Dictionary<VCExprOp/*!*/, SingletonOp>();
- SingletonOpDict.Add(NotOp, SingletonOp.NotOp);
- SingletonOpDict.Add(EqOp, SingletonOp.EqOp);
- SingletonOpDict.Add(NeqOp, SingletonOp.NeqOp);
- SingletonOpDict.Add(AndOp, SingletonOp.AndOp);
- SingletonOpDict.Add(OrOp, SingletonOp.OrOp);
- SingletonOpDict.Add(ImpliesOp, SingletonOp.ImpliesOp);
- SingletonOpDict.Add(AddIOp, SingletonOp.AddOp);
- SingletonOpDict.Add(AddROp, SingletonOp.AddOp);
- SingletonOpDict.Add(SubIOp, SingletonOp.SubOp);
- SingletonOpDict.Add(SubROp, SingletonOp.SubOp);
- //SingletonOpDict.Add(SubFOp, SingletonOp.SubOp);
- SingletonOpDict.Add(MulIOp, SingletonOp.MulOp);
- SingletonOpDict.Add(MulROp, SingletonOp.MulOp);
- //SingletonOpDict.Add(MulFOp, SingletonOp.MulOp);
- SingletonOpDict.Add(DivIOp, SingletonOp.DivOp);
- SingletonOpDict.Add(DivROp, SingletonOp.RealDivOp);
- //SingletonOpDict.Add(DivFOp, SingletonOp.FloatDivOp);
- SingletonOpDict.Add(ModOp, SingletonOp.ModOp);
- SingletonOpDict.Add(PowOp, SingletonOp.PowOp);
- SingletonOpDict.Add(LtOp, SingletonOp.LtOp);
- SingletonOpDict.Add(LeOp, SingletonOp.LeOp);
- SingletonOpDict.Add(GtOp, SingletonOp.GtOp);
- SingletonOpDict.Add(GeOp, SingletonOp.GeOp);
- SingletonOpDict.Add(SubtypeOp, SingletonOp.SubtypeOp);
- SingletonOpDict.Add(Subtype3Op, SingletonOp.Subtype3Op);
- SingletonOpDict.Add(ToIntOp, SingletonOp.ToIntOp);
- SingletonOpDict.Add(ToRealOp, SingletonOp.ToRealOp);
- //SingletonOpDict.Add(ToFloatOp, SingletonOp.ToFloatOp);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
-
- // Let-bindings
-
- public VCExprLetBinding LetBinding(VCExprVar v, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(v != null);
- Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
- return new VCExprLetBinding(v, e);
- }
-
- // A "real" let expression. All let-bindings happen simultaneously, i.e.,
- // at this level the order of the bindings does not matter. It is possible to
- // create expressions like "let x = y, y = 5 in ...". All bound variables are
- // bound in all bound terms/formulas and can occur there, but the dependencies
- // have to be acyclic
- public VCExpr Let(List<VCExprLetBinding> bindings, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (bindings.Count == 0)
- // no empty let-bindings
- return body;
- return new VCExprLet(bindings, body);
- }
-
- public VCExpr Let(VCExpr body, params VCExprLetBinding[] bindings) {
- Contract.Requires(body != null);
- Contract.Requires((cce.NonNullElements(bindings)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Let(HelperFuns.ToNonNullList(bindings), body);
- }
-
-
- /// <summary>
- /// In contrast to the previous method, the following methods are not a general LET.
- /// Instead, it
- /// is a boolean "LET b = P in Q", where P and Q are predicates, that is allowed to be
- /// encoded as "(b == P) ==> Q" or even as "(P ==> b) ==> Q"
- /// (or "(P ==> b) and Q" in negative positions).
- /// The method assumes that the variables in the bindings are unique in the entire formula
- /// to be produced, which allows the implementation to ignore scope issues in the event that
- /// it needs to generate an alternate expression for LET.
- /// </summary>
-
-
- // Turn let-bindings let v = E in ... into implications E ==> v
- public VCExpr AsImplications(List<VCExprLetBinding> bindings) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ antecedents = True;
- foreach (VCExprLetBinding b in bindings)
- // turn "LET_binding v = E" into "v <== E"
- antecedents = AndSimp(antecedents, Implies(b.E, b.V));
- return antecedents;
- }
-
- // Turn let-bindings let v = E in ... into equations v == E
- public VCExpr AsEquations(List<VCExprLetBinding> bindings) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ antecedents = True;
- foreach (VCExprLetBinding b in bindings)
- // turn "LET_binding v = E" into "v <== E"
- antecedents = AndSimp(antecedents, Eq(b.E, b.V));
- return antecedents;
- }
-
-
-
- // Maps
-
- public VCExpr Select(params VCExpr[] allArgs) {
- Contract.Requires(allArgs != null);
- Contract.Requires((cce.NonNullElements(allArgs)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprSelectOp(allArgs.Length - 1, 0),
- HelperFuns.ToNonNullList(allArgs),
- VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr Select(VCExpr[] allArgs, Type[] typeArgs) {
- Contract.Requires(1 <= allArgs.Length);
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprSelectOp(allArgs.Length - 1, typeArgs.Length),
- allArgs, typeArgs);
- }
-
- public VCExpr Select(List<VCExpr> allArgs, List<Type> typeArgs) {
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires((1 <= allArgs.Count));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprSelectOp(allArgs.Count - 1, typeArgs.Count),
- allArgs, typeArgs);
- }
-
- public VCExpr Store(params VCExpr[] allArgs) {
- Contract.Requires(allArgs != null);
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprStoreOp(allArgs.Length - 2, 0),
- HelperFuns.ToNonNullList(allArgs),
- VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr Store(VCExpr[] allArgs, Type[] typeArgs) {
- Contract.Requires(typeArgs != null);
- Contract.Requires(allArgs != null);
- Contract.Requires((2 <= allArgs.Length));
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprStoreOp(allArgs.Length - 2, typeArgs.Length),
- allArgs, typeArgs);
- }
-
- public VCExpr Store(List<VCExpr> allArgs, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires((2 <= allArgs.Count));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprStoreOp(allArgs.Count - 2, typeArgs.Count),
- allArgs, typeArgs);
- }
-
-
- // Labels
-
- public VCExprLabelOp LabelOp(bool pos, string l) {
- Contract.Requires(l != null);
- Contract.Ensures(Contract.Result<VCExprLabelOp>() != null);
- return new VCExprLabelOp(pos, l);
- }
-
- public VCExpr LabelNeg(string label, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e.Equals(True)) {
- return e; // don't bother putting negative labels around True (which will expose the True to further peephole optimizations)
- }
- return Function(LabelOp(false, label), e);
- }
- public VCExpr LabelPos(string label, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(LabelOp(true, label), e);
- }
-
- // Quantifiers
-
- public VCExpr Quantify(Quantifier quan, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return new VCExprQuantifier(quan, typeParams, vars, triggers, infos, body);
- }
-
- public VCExpr Forall(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.ALL, typeParams, vars, triggers, infos, body);
- }
- public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, string qid, int weight, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(qid != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- QKeyValue kv = null;
- if (0 <= weight) {
- kv = new QKeyValue(Token.NoToken, "weight", new List<object>() { new LiteralExpr(Token.NoToken, BigNum.FromInt(0)) }, null);
- }
- return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
- triggers, new VCQuantifierInfos(qid, -1, false, kv), body);
- }
- public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
- triggers, new VCQuantifierInfos(null, -1, false, null), body);
- }
- public VCExpr Forall(VCExprVar var, VCTrigger trigger, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(trigger != null);
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Forall(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
- }
- public VCExpr Exists(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.EX, typeParams, vars, triggers, infos, body);
- }
- public VCExpr Exists(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.EX, new List<TypeVariable/*!*/>(), vars,
- triggers, new VCQuantifierInfos(null, -1, false, null), body);
- }
- public VCExpr Exists(VCExprVar var, VCTrigger trigger, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(trigger != null);
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Exists(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
- }
-
- public VCTrigger Trigger(bool pos, List<VCExpr> exprs) {
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(Contract.Result<VCTrigger>() != null);
- return new VCTrigger(pos, exprs);
- }
-
- public VCTrigger Trigger(bool pos, params VCExpr[] exprs) {
- Contract.Requires(exprs != null);
- Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
- Contract.Ensures(Contract.Result<VCTrigger>() != null);
- return Trigger(pos, HelperFuns.ToNonNullList(exprs));
- }
-
- // Reference to a bound or free variable
-
- public VCExprVar Variable(string name, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- return new VCExprVar(name, type);
- }
- }
-}
-
-namespace Microsoft.Boogie.VCExprAST {
-
- public class HelperFuns {
- public static bool SameElements(IEnumerable a, IEnumerable b) {
- Contract.Requires(b != null);
- Contract.Requires(a != null);
- IEnumerator ia = a.GetEnumerator();
- IEnumerator ib = b.GetEnumerator();
- while (true) {
- if (ia.MoveNext()) {
- if (ib.MoveNext()) {
- if (!cce.NonNull(ia.Current).Equals(ib.Current))
- return false;
- } else {
- return false;
- }
- } else {
- return !ib.MoveNext();
- }
- }
- }
-
- public static int PolyHash(int init, int factor, IEnumerable a) {
- Contract.Requires(a != null);
- int res = init;
- foreach (object x in a)
- res = res * factor + (cce.NonNull(x)).GetHashCode();
- return res;
- }
-
- public static List<T> ToList<T>(IEnumerable<T> l) {
- Contract.Requires(l != null);
- Contract.Ensures(Contract.Result<List<T>>() != null);
- List<T>/*!*/ res = new List<T>();
- foreach (T x in l)
- res.Add(x);
- return res;
- }
-
- public static List<Type> ToTypeSeq(VCExpr[] exprs, int startIndex) {
- Contract.Requires(exprs != null);
- Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
- Contract.Ensures(Contract.Result<List<Type>>() != null);
- List<Type>/*!*/ res = new List<Type>();
- for (int i = startIndex; i < exprs.Length; ++i)
- res.Add(cce.NonNull(exprs[i]).Type);
- return res;
- }
-
- public static List<T/*!*/>/*!*/ ToNonNullList<T>(params T[] args) where T : class {
- Contract.Requires(args != null);
- List<T/*!*/>/*!*/ res = new List<T>(args.Length);
- foreach (T t in args)
- res.Add(cce.NonNull(t));
- return res;
- }
-
- public static IDictionary<A, B> Clone<A, B>(IDictionary<A, B> dict) {
- Contract.Requires(dict != null);
- Contract.Ensures(Contract.Result<IDictionary<A, B>>() != null);
- IDictionary<A, B> res = new Dictionary<A, B>(dict.Count);
- foreach (KeyValuePair<A, B> pair in dict)
- res.Add(pair);
- return res;
- }
- }
-
- [ContractClassFor(typeof(VCExpr))]
- public abstract class VCExprContracts : VCExpr {
- public override Type Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- throw new NotImplementedException();
- }
-
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- Contract.Requires(visitor != null);
- throw new NotImplementedException();
- }
- }
-
- [ContractClass(typeof(VCExprContracts))]
- public abstract class VCExpr {
- public abstract Type Type {
- get;
- }
-
- public abstract Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg);
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- StringWriter sw = new StringWriter();
- VCExprPrinter printer = new VCExprPrinter();
- printer.Print(this, sw);
- return cce.NonNull(sw.ToString());
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Literal expressions
-
- public class VCExprLiteral : VCExpr {
- private readonly Type LitType;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(LitType != null);
- }
-
- public override Type Type {
- get {
- return LitType;
- }
- }
- internal VCExprLiteral(Type type) {
- Contract.Requires(type != null);
- this.LitType = type;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-
- public class VCExprIntLit : VCExprLiteral {
- public readonly BigNum Val;
- internal VCExprIntLit(BigNum val)
- : base(Type.Int) {
- this.Val = val;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprIntLit)
- return Val == ((VCExprIntLit)that).Val;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Val.GetHashCode() * 72321;
- }
- }
-
- public class VCExprRealLit : VCExprLiteral {
- public readonly BigDec Val;
- internal VCExprRealLit(BigDec val)
- : base(Type.Real) {
- this.Val = val;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprRealLit)
- return Val == ((VCExprRealLit)that).Val;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Val.GetHashCode() * 72321;
- }
- }
-
- public class VCExprFloatLit : VCExprLiteral
- {
- public readonly BigFloat Val;
- internal VCExprFloatLit(BigFloat val)
- : base(Type.GetFloatType(val.ExponentSize, val.SignificandSize))
- {
- this.Val = val;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that)
- {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprFloatLit)
- return Val == ((VCExprFloatLit)that).Val;
- return false;
- }
- [Pure]
- public override int GetHashCode()
- {
- return Val.GetHashCode() * 72321;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Operator expressions with fixed arity
- [ContractClassFor(typeof(VCExprNAry))]
- public abstract class VCExprNAryContracts : VCExprNAry {
- public VCExprNAryContracts()
- : base(null) {
- }
- public override VCExpr this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- throw new NotImplementedException();
- }
- }
- }
-
- [ContractClass(typeof(VCExprNAryContracts))]
- public abstract class VCExprNAry : VCExpr, IEnumerable<VCExpr/*!*/> {
- public readonly VCExprOp Op;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- Contract.Invariant(cce.NonNullElements(EMPTY_TYPE_LIST));
- Contract.Invariant(cce.NonNullElements(EMPTY_VCEXPR_LIST));
- }
-
- public int Arity {
- get {
- return Op.Arity;
- }
- }
- public int TypeParamArity {
- get {
- return Op.TypeParamArity;
- }
- }
- public int Length {
- get {
- return Arity;
- }
- }
- // the sub-expressions of the expression
- public abstract VCExpr/*!*/ this[int index] {
- get;
- }
-
- // the type arguments
- public abstract List<Type/*!*/>/*!*/ TypeArguments {
- get;
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- public IEnumerator<VCExpr/*!*/>/*!*/ GetEnumerator() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExpr>>()));
- for (int i = 0; i < Arity; ++i)
- yield return this[i];
- }
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator>() != null);
- for (int i = 0; i < Arity; ++i)
- yield return this[i];
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprNAry) {
- // we compare the subterms iteratively (not recursively)
- // to avoid stack overflows
-
- VCExprNAryEnumerator enum0 = new VCExprNAryEnumerator(this);
- VCExprNAryEnumerator enum1 = new VCExprNAryEnumerator((VCExprNAry)that);
-
- while (true) {
- bool next0 = enum0.MoveNext();
- bool next1 = enum1.MoveNext();
- if (next0 != next1)
- return false;
- if (!next0)
- return true;
-
- VCExprNAry nextExprNAry0 = enum0.Current as VCExprNAry;
- VCExprNAry nextExprNAry1 = enum1.Current as VCExprNAry;
-
- if ((nextExprNAry0 == null) != (nextExprNAry1 == null))
- return false;
- if (nextExprNAry0 != null && nextExprNAry1 != null) {
- if (!nextExprNAry0.Op.Equals(nextExprNAry1.Op))
- return false;
- } else {
- if (!cce.NonNull(enum0.Current).Equals(enum1.Current))
- return false;
- }
- }
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return HelperFuns.PolyHash(Op.GetHashCode() * 123 + Arity * 61521,
- 3, this);
- }
-
- internal VCExprNAry(VCExprOp op) {
- Contract.Requires(op != null);
- this.Op = op;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- public Result Accept<Result, Arg>(IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- Contract.Requires(visitor != null);
- return Op.Accept(this, visitor, arg);
- }
-
- internal static readonly List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
- internal static readonly List<VCExpr/*!*/>/*!*/ EMPTY_VCEXPR_LIST = new List<VCExpr/*!*/>();
-
- public IEnumerable<VCExpr> UniformArguments
- {
- get
- {
- var enumerator = new VCExprNAryUniformOpEnumerator(this);
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(this.Op)) {
- yield return (VCExpr)enumerator.Current;
- }
- }
- }
- }
- }
-
- // We give specialised implementations for nullary, unary and binary expressions
-
- internal class VCExprNullary : VCExprNAry {
- private readonly Type ExprType;
- [ContractInvariantMethod]
- void loneinvariant() {
- Contract.Invariant(ExprType != null);
- }
-
- public override Type Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Contract.Assert(false);
- throw new cce.UnreachableException(); // no arguments
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return EMPTY_TYPE_LIST;
- }
- }
-
- internal VCExprNullary(VCExprOp op)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(op.Arity == 0 && op.TypeParamArity == 0);
- this.ExprType = op.InferType(EMPTY_VCEXPR_LIST, EMPTY_TYPE_LIST);
- }
- }
-
- internal class VCExprUnary : VCExprNAry {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Argument != null);
- Contract.Invariant(ExprType != null);
-
- }
-
- private readonly VCExpr/*!*/ Argument;
- private readonly Type/*!*/ ExprType;
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr/*!*/ this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Contract.Assume(index == 0);
- return Argument;
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return EMPTY_TYPE_LIST;
- }
- }
-
- internal VCExprUnary(VCExprOp op, List<VCExpr> arguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0 && arguments.Count == 1);
-
- this.Argument = arguments[0];
- this.ExprType =
- op.InferType(arguments, EMPTY_TYPE_LIST);
- }
-
- internal VCExprUnary(VCExprOp op, VCExpr argument)
- : base(op) {
- Contract.Requires(argument != null);
- Contract.Requires(op != null);
- Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0);
-
- this.Argument = argument;
- // PR: could be optimised so that the argument does
- // not have to be boxed in an array each time
- this.ExprType =
- op.InferType(HelperFuns.ToNonNullList(argument), EMPTY_TYPE_LIST);
- }
- }
-
- internal class VCExprBinary : VCExprNAry {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Argument0 != null);
- Contract.Invariant(Argument1 != null);
- Contract.Invariant(ExprType != null);
- }
-
- private readonly VCExpr Argument0;
- private readonly VCExpr Argument1;
- private readonly Type ExprType;
- public override Type Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- switch (index) {
- case 0:
- return Argument0;
- case 1:
- return Argument1;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return EMPTY_TYPE_LIST;
- }
- }
-
- internal VCExprBinary(VCExprOp op, List<VCExpr> arguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0 && arguments.Count == 2);
-
- this.Argument0 = arguments[0];
- this.Argument1 = arguments[1];
- this.ExprType = op.InferType(arguments, EMPTY_TYPE_LIST);
- }
-
- internal VCExprBinary(VCExprOp op, VCExpr argument0, VCExpr argument1)
- : base(op) {
- Contract.Requires(argument1 != null);
- Contract.Requires(argument0 != null);
- Contract.Requires(op != null);
- Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0);
- this.Argument0 = argument0;
- this.Argument1 = argument1;
- // PR: could be optimised so that the arguments do
- // not have to be boxed in an array each time
- this.ExprType =
- op.InferType(HelperFuns.ToNonNullList(argument0, argument1),
- EMPTY_TYPE_LIST);
- }
- }
-
- internal class VCExprMultiAry : VCExprNAry {
- private readonly List<VCExpr/*!*/>/*!*/ Arguments;
- private readonly List<Type/*!*/>/*!*/ TypeArgumentsAttr;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(Arguments));
- Contract.Invariant(cce.NonNullElements(TypeArgumentsAttr));
- Contract.Invariant(ExprType != null);
- }
-
-
- private readonly Type/*!*/ ExprType;
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr/*!*/ this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Contract.Assume(index >= 0 && index < Arity);
- return cce.NonNull(Arguments)[index];
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return TypeArgumentsAttr;
- }
- }
-
- internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- this.Arguments = arguments;
- this.TypeArgumentsAttr = EMPTY_TYPE_LIST;
- this.ExprType = op.InferType(arguments, TypeArgumentsAttr);
- }
- internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments, List<Type/*!*/>/*!*/ typeArguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(typeArguments));
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(arguments.Count > 2 || typeArguments.Count > 0);
- Contract.Requires(op.Arity == arguments.Count);
- Contract.Requires(op.TypeParamArity == typeArguments.Count);
- this.Arguments = arguments;
- this.TypeArgumentsAttr = typeArguments;
- this.ExprType = op.InferType(arguments, typeArguments);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // The various operators available
- [ContractClass(typeof(VCExprOpContracts))]
- public abstract class VCExprOp {
- // the number of value parameters
- public abstract int Arity {
- get;
- }
- // the number of type parameters
- public abstract int TypeParamArity {
- get;
- }
-
- public abstract Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs);
-
- public virtual Result Accept<Result, Arg>(VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- Contract.Requires(visitor != null);
- Contract.Requires(expr != null);
- VCExpressionGenerator.SingletonOp op;
- if (VCExpressionGenerator.SingletonOpDict.TryGetValue(this, out op)) {
- switch (op) {
- case VCExpressionGenerator.SingletonOp.NotOp:
- return visitor.VisitNotOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.EqOp:
- return visitor.VisitEqOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.NeqOp:
- return visitor.VisitNeqOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.AndOp:
- return visitor.VisitAndOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.OrOp:
- return visitor.VisitOrOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ImpliesOp:
- return visitor.VisitImpliesOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.AddOp:
- return visitor.VisitAddOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.SubOp:
- return visitor.VisitSubOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.MulOp:
- return visitor.VisitMulOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.DivOp:
- return visitor.VisitDivOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ModOp:
- return visitor.VisitModOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.RealDivOp:
- return visitor.VisitRealDivOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.PowOp:
- return visitor.VisitPowOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.LtOp:
- return visitor.VisitLtOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.LeOp:
- return visitor.VisitLeOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.GtOp:
- return visitor.VisitGtOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.GeOp:
- return visitor.VisitGeOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.SubtypeOp:
- return visitor.VisitSubtypeOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.Subtype3Op:
- return visitor.VisitSubtype3Op(expr, arg);
- case VCExpressionGenerator.SingletonOp.BvConcatOp:
- return visitor.VisitBvConcatOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ToIntOp:
- return visitor.VisitToIntOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ToRealOp:
- return visitor.VisitToRealOp(expr, arg);
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- }
- [ContractClassFor(typeof(VCExprOp))]
- abstract class VCExprOpContracts : VCExprOp {
- public override Type InferType(List<VCExpr> args, List<Type> typeArgs) {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- }
-
- public class VCExprNAryOp : VCExprOp {
- private readonly Type OpType;
- private readonly int OpArity;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(OpType != null);
- }
-
- public override int Arity {
- get {
- return OpArity;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return OpType;
- }
-
- internal VCExprNAryOp(int arity, Type type) {
- Contract.Requires(type != null);
- this.OpArity = arity;
- this.OpType = type;
- }
- }
-
- public class VCExprDistinctOp : VCExprNAryOp {
- internal VCExprDistinctOp(int arity)
- : base(arity, Type.Bool) {
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprDistinctOp)
- return Arity == ((VCExprDistinctOp)that).Arity;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Arity * 917632481;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitDistinctOp(expr, arg);
- }
- }
-
- public class VCExprLabelOp : VCExprOp {
- public override int Arity {
- get {
- return 1;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return args[0].Type;
- }
-
- public readonly bool pos;
- public readonly string label;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(label != null);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprLabelOp) {
- VCExprLabelOp/*!*/ thatOp = (VCExprLabelOp)that;
- return this.pos == thatOp.pos && this.label.Equals(thatOp.label);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return (pos ? 9817231 : 7198639) + label.GetHashCode();
- }
-
- internal VCExprLabelOp(bool pos, string l) {
- Contract.Requires(l != null);
- this.pos = pos;
- this.label = pos ? "+" + l : "@" + l;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitLabelOp(expr, arg);
- }
- }
-
- public class VCExprSelectOp : VCExprOp {
- private readonly int MapArity;
- private readonly int MapTypeParamArity;
- public override int Arity {
- get {
- return MapArity + 1;
- }
- }
- public override int TypeParamArity {
- get {
- return MapTypeParamArity;
- }
- }
-
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- MapType/*!*/ mapType = args[0].Type.AsMap;
- Contract.Assert(TypeParamArity == mapType.TypeParameters.Count);
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- for (int i = 0; i < TypeParamArity; ++i)
- subst.Add(mapType.TypeParameters[i], typeArgs[i]);
- return mapType.Result.Substitute(subst);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprSelectOp)
- return Arity == ((VCExprSelectOp)that).Arity &&
- TypeParamArity == ((VCExprSelectOp)that).TypeParamArity;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Arity * 1212481 + TypeParamArity * 298741;
- }
-
- internal VCExprSelectOp(int arity, int typeParamArity) {
- Contract.Requires(0 <= arity && 0 <= typeParamArity);
- this.MapArity = arity;
- this.MapTypeParamArity = typeParamArity;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitSelectOp(expr, arg);
- }
- }
-
- public class VCExprStoreOp : VCExprOp {
- private readonly int MapArity;
- private readonly int MapTypeParamArity;
- public override int Arity {
- get {
- return MapArity + 2;
- }
- }
- // stores never need explicit type parameters, because also the
- // rhs is a value argument
- public override int TypeParamArity {
- get {
- return MapTypeParamArity;
- }
- }
-
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return args[0].Type;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprStoreOp)
- return Arity == ((VCExprStoreOp)that).Arity;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Arity * 91361821;
- }
-
- internal VCExprStoreOp(int arity, int typeParamArity) {
- Contract.Requires(0 <= arity && 0 <= typeParamArity);
- this.MapArity = arity;
- this.MapTypeParamArity = typeParamArity;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitStoreOp(expr, arg);
- }
- }
-
- public class VCExprIfThenElseOp : VCExprOp {
- public override int Arity {
- get {
- return 3;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return args[1].Type;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprIfThenElseOp)
- return true;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return 1;
- }
-
- internal VCExprIfThenElseOp() {
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitIfThenElseOp(expr, arg);
- }
- }
-
- public class VCExprCustomOp : VCExprOp {
- public readonly string/*!*/ Name;
- int arity;
- public readonly Type/*!*/ Type;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- Contract.Invariant(Type != null);
- }
-
- public VCExprCustomOp(string/*!*/ name, int arity, Type/*!*/ type) {
- Contract.Requires(name != null);
- Contract.Requires(type != null);
- this.Name = name;
- this.arity = arity;
- this.Type = type;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- VCExprCustomOp t = that as VCExprCustomOp;
- if (t == null)
- return false;
- return this.Name == t.Name && this.arity == t.arity && this.Type == t.Type;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override int GetHashCode() {
- int h = Name.GetHashCode();
- h = 7823 * h + arity;
- h = 7823 * h + Type.GetHashCode();
- return h;
- }
- public override int Arity {
- get {
- return arity;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires((cce.NonNullElements(args)));
- //Contract.Requires((cce.NonNullElements(typeArgs)));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry/*!*/ expr, IVCExprOpVisitor<Result, Arg>/*!*/ visitor, Arg arg) {
- //Contract.Requires(expr != null);
- //Contract.Requires(visitor != null);
- return visitor.VisitCustomOp(expr, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Float operators
-
- public class VCExprBinaryFloatOp : VCExprOp {
- public readonly int Mantissa;
- public readonly int Exponent;
- private string op;
-
- public override int Arity {
- get {
- return 2;
- }
- }
- public override int TypeParamArity {
- get {
- return 2;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetFloatType(Exponent, Mantissa);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBinaryFloatOp)
- return this.Exponent == ((VCExprBinaryFloatOp)that).Exponent && this.Mantissa == ((VCExprBinaryFloatOp)that).Mantissa;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Exponent * 81748912 + Mantissa * 67867979;
- }
-
- internal VCExprBinaryFloatOp(int exp, int man, string op) {
- this.Exponent = exp;
- this.Mantissa = man;
- this.op = op;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- switch (op) {
- case ("+"):
- return visitor.VisitFloatAddOp(expr, arg);
- case ("-"):
- return visitor.VisitFloatSubOp(expr, arg);
- case ("*"):
- return visitor.VisitFloatMulOp(expr, arg);
- case ("/"):
- return visitor.VisitFloatDivOp(expr, arg);
- case ("rem"):
- return visitor.VisitFloatRemOp(expr, arg);
- case ("min"):
- return visitor.VisitFloatMinOp(expr, arg);
- case ("max"):
- return visitor.VisitFloatMaxOp(expr, arg);
- case ("<="):
- return visitor.VisitFloatLeqOp(expr, arg);
- case ("<"):
- return visitor.VisitFloatLtOp(expr, arg);
- case (">="):
- return visitor.VisitFloatGeqOp(expr, arg);
- case (">"):
- return visitor.VisitFloatGtOp(expr, arg);
- case ("=="):
- return visitor.VisitFloatEqOp(expr, arg);
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Bitvector operators
-
- public class VCExprBvOp : VCExprOp {
- public readonly int Bits;
-
- public override int Arity {
- get {
- return 1;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetBvType(Bits);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBvOp)
- return this.Bits == ((VCExprBvOp)that).Bits;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Bits * 81748912;
- }
-
- internal VCExprBvOp(int bits) {
- this.Bits = bits;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBvOp(expr, arg);
- }
- }
-
- public class VCExprBvExtractOp : VCExprOp {
- public readonly int Start;
- public readonly int End;
- public readonly int Total; // the number of bits from which the End-Start bits are extracted
-
- public override int Arity {
- get {
- return 1;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetBvType(End - Start);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBvExtractOp) {
- VCExprBvExtractOp/*!*/ thatExtract = (VCExprBvExtractOp)that;
- return this.Start == thatExtract.Start && this.End == thatExtract.End && this.Total == thatExtract.Total;
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Start * 81912 + End * 978132 + Total * 571289;
- }
-
- internal VCExprBvExtractOp(int start, int end, int total) {
- Contract.Requires(0 <= start && start <= end && end <= total);
- this.Start = start;
- this.End = end;
- this.Total = total;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBvExtractOp(expr, arg);
- }
- }
-
- public class VCExprBvConcatOp : VCExprOp {
- public readonly int LeftSize;
- public readonly int RightSize;
-
- public override int Arity {
- get {
- return 2;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetBvType(args[0].Type.BvBits + args[1].Type.BvBits);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBvConcatOp) {
- VCExprBvConcatOp thatConcat = (VCExprBvConcatOp)that;
- return this.LeftSize == thatConcat.LeftSize && this.RightSize == thatConcat.RightSize;
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return LeftSize * 81912 + RightSize * 978132;
- }
-
- internal VCExprBvConcatOp(int leftSize, int rightSize) {
- Contract.Requires(0 <= leftSize && 0 <= rightSize);
- this.LeftSize = leftSize;
- this.RightSize = rightSize;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBvConcatOp(expr, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // References to user-defined Boogie functions
-
- public class VCExprBoogieFunctionOp : VCExprOp {
- public readonly Function Func;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Func != null);
- }
-
-
- public override int Arity {
- get {
- return Func.InParams.Count;
- }
- }
- public override int TypeParamArity {
- get {
- return Func.TypeParameters.Count;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(TypeParamArity == Func.TypeParameters.Count);
- if (TypeParamArity == 0)
- return cce.NonNull(Func.OutParams[0]).TypedIdent.Type;
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>(TypeParamArity);
- for (int i = 0; i < TypeParamArity; ++i)
- subst.Add(Func.TypeParameters[i], typeArgs[i]);
- return cce.NonNull(Func.OutParams[0]).TypedIdent.Type.Substitute(subst);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBoogieFunctionOp)
- return this.Func.Equals(((VCExprBoogieFunctionOp)that).Func);
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Func.GetHashCode() + 18731;
- }
-
- // we require that the result type of the expression is specified, because we
- // do not want to perform full type inference at this point
- internal VCExprBoogieFunctionOp(Function func) {
- Contract.Requires(func != null);
- this.Func = func;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBoogieFunctionOp(expr, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Binders (quantifiers and let-expressions). We introduce our own class for
- // term variables, but use the Boogie-AST class for type variables
-
- public class VCExprVar : VCExpr {
- // the name of the variable. Note that the name is not used for comparison,
- // i.e., there can be two distinct variables with the same name
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- Contract.Invariant(VarType != null);
- }
-
- public readonly string/*!*/ Name;
- private readonly Type/*!*/ VarType;
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return VarType;
- }
- }
-
- internal VCExprVar(string name, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- this.Name = name;
- this.VarType = type;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-
- public class VCExprConstant : VCExprVar
- {
- internal VCExprConstant(string name, Type type) : base(name,type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- }
- }
-
- public abstract class VCExprBinder : VCExpr {
- public readonly VCExpr/*!*/ Body;
- public readonly List<TypeVariable/*!*/>/*!*/ TypeParameters;
- public readonly List<VCExprVar/*!*/>/*!*/ BoundVars;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Body != null);
- Contract.Invariant(cce.NonNullElements(TypeParameters));
- Contract.Invariant(cce.NonNullElements(BoundVars));
- }
-
-
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Body.Type;
- }
- }
-
- internal VCExprBinder(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(boundVars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(boundVars.Count + typeParams.Count > 0); // only nontrivial binders ...
- this.TypeParameters = typeParams;
- this.BoundVars = boundVars;
- this.Body = body;
- }
- }
-
- public class VCTrigger {
- public readonly bool Pos;
- public readonly List<VCExpr/*!*/>/*!*/ Exprs;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Exprs != null);
- }
-
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCTrigger) {
- VCTrigger/*!*/ thatTrigger = (VCTrigger)that;
- return this.Pos == thatTrigger.Pos &&
- HelperFuns.SameElements(this.Exprs, thatTrigger.Exprs);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return (Pos ? 913821 : 871334) +
- HelperFuns.PolyHash(123, 7, this.Exprs);
- }
-
- public VCTrigger(bool pos, List<VCExpr> exprs) {
- Contract.Requires(cce.NonNullElements(exprs));
- this.Pos = pos;
- this.Exprs = exprs;
- }
- }
-
- public class VCQuantifierInfos {
- public readonly string qid;
- public readonly int uniqueId;
- public readonly bool bvZ3Native;
- public QKeyValue attributes;
-
- public VCQuantifierInfos(string qid, int uniqueId, bool bvZ3Native, QKeyValue attributes) {
- this.qid = qid;
- this.uniqueId = uniqueId;
- this.bvZ3Native = bvZ3Native;
- this.attributes = attributes;
- }
- }
-
- public enum Quantifier {
- ALL,
- EX
- };
-
- public class VCExprQuantifier : VCExprBinder {
- public readonly Quantifier Quan;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Infos != null);
- Contract.Invariant(cce.NonNullElements(Triggers));
- }
-
-
- public readonly List<VCTrigger/*!*/>/*!*/ Triggers;
- public readonly VCQuantifierInfos Infos;
-
- // Equality is /not/ modulo bound renaming at this point
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprQuantifier) {
- VCExprQuantifier/*!*/ thatQuan = (VCExprQuantifier)that;
- return this.Quan == thatQuan.Quan &&
- HelperFuns.SameElements(this.Triggers, thatQuan.Triggers) &&
- HelperFuns.SameElements(this.TypeParameters, thatQuan.TypeParameters) &&
- HelperFuns.SameElements(this.BoundVars, thatQuan.BoundVars) &&
- this.Body.Equals(thatQuan.Body);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Quan.GetHashCode() +
- HelperFuns.PolyHash(973219, 7, TypeParameters) +
- HelperFuns.PolyHash(998431, 9, BoundVars) +
- HelperFuns.PolyHash(123, 11, Triggers);
- }
-
- internal VCExprQuantifier(Quantifier kind, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body)
- : base(typeParams, boundVars, body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(boundVars));
- Contract.Requires(cce.NonNullElements(typeParams));
-
- this.Quan = kind;
- this.Triggers = triggers;
- this.Infos = infos;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Let-Bindings
-
- public class VCExprLetBinding {
- public readonly VCExprVar V;
- public readonly VCExpr E;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(V != null);
- Contract.Invariant(E != null);
- }
-
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprLetBinding) {
- VCExprLetBinding/*!*/ thatB = (VCExprLetBinding)that;
- return this.V.Equals(thatB.V) && this.E.Equals(thatB.E);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return V.GetHashCode() * 71261 + E.GetHashCode();
- }
-
- internal VCExprLetBinding(VCExprVar v, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(v != null);
- this.V = v;
- this.E = e;
- Contract.Assert(v.Type.Equals(e.Type));
- }
- }
-
- public class VCExprLet : VCExprBinder, IEnumerable<VCExprLetBinding/*!*/> {
- private readonly List<VCExprLetBinding/*!*/>/*!*/ Bindings;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(Bindings));
-
- }
-
-
- public int Length {
- get {
- return Bindings.Count;
- }
- }
- public VCExprLetBinding this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
- return Bindings[index];
- }
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprLet) {
- VCExprLet/*!*/ thatLet = (VCExprLet)that;
- return this.Body.Equals(thatLet.Body) &&
- HelperFuns.SameElements(this, (VCExprLet)that);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return HelperFuns.PolyHash(Body.GetHashCode(), 9, Bindings);
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- public IEnumerator<VCExprLetBinding/*!*/>/*!*/ GetEnumerator() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExprLetBinding>>()));
- return Bindings.GetEnumerator();
- }
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator>() != null);
- return Bindings.GetEnumerator();
- }
-
- private static List<VCExprVar/*!*/>/*!*/ toSeq(List<VCExprLetBinding/*!*/>/*!*/ bindings) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar> res = new List<VCExprVar>();
- foreach (VCExprLetBinding/*!*/ b in bindings)
- res.Add(b.V);
- return res;
- }
-
- internal VCExprLet(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr/*!*/ body)
- : base(new List<TypeVariable/*!*/>(), toSeq(bindings), body) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Requires(body != null);
- this.Bindings = bindings;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Prover-independent syntax trees for representing verification conditions
+// The language can be seen as a simple polymorphically typed first-order logic,
+// very similar to the expression language of Boogie
+
+namespace Microsoft.Boogie {
+ using Microsoft.Boogie.VCExprAST;
+
+ public class VCExpressionGenerator {
+ public static readonly VCExpr False = new VCExprLiteral(Type.Bool);
+ public static readonly VCExpr True = new VCExprLiteral(Type.Bool);
+
+ private Function ControlFlowFunction = null;
+ public VCExpr ControlFlowFunctionApplication(VCExpr e1, VCExpr e2) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e2 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (ControlFlowFunction == null) {
+ Formal/*!*/ first = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
+ Formal/*!*/ second = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
+ List<Variable> inputs = new List<Variable>();
+ inputs.Add(first);
+ inputs.Add(second);
+ Formal/*!*/ returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), false);
+ ControlFlowFunction = new Function(Token.NoToken, "ControlFlow", inputs, returnVar);
+ }
+ List<VCExpr/*!*/> args = new List<VCExpr/*!*/>();
+ args.Add(e1);
+ args.Add(e2);
+ return Function(BoogieFunctionOp(ControlFlowFunction), args);
+ }
+
+ public VCExpr/*!*/ Integer(BigNum x) {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return new VCExprIntLit(x);
+ }
+
+ public VCExpr/*!*/ Real(BigDec x) {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return new VCExprRealLit(x);
+ }
+
+ public VCExpr/*!*/ Float(BigFloat x)
+ {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return new VCExprFloatLit(x);
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op,
+ List<VCExpr/*!*/>/*!*/ arguments,
+ List<Type/*!*/>/*!*/ typeArguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(cce.NonNullElements(typeArguments));
+ if (typeArguments.Count > 0)
+ return new VCExprMultiAry(op, arguments, typeArguments);
+
+ switch (arguments.Count) {
+ case 0:
+ return new VCExprNullary(op);
+ case 1:
+ return new VCExprUnary(op, arguments);
+ case 2:
+ return new VCExprBinary(op, arguments);
+ default:
+ return new VCExprMultiAry(op, arguments);
+ }
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(op, arguments, VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op, params VCExpr[]/*!*/ arguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+
+ return Function(op,
+ HelperFuns.ToNonNullList(arguments),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op, VCExpr[]/*!*/ arguments, Type[]/*!*/ typeArguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(cce.NonNullElements(typeArguments));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+
+ return Function(op,
+ HelperFuns.ToNonNullList(arguments),
+ HelperFuns.ToNonNullList(typeArguments));
+ }
+
+ public VCExpr/*!*/ Function(Function/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(BoogieFunctionOp(op), arguments, VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr/*!*/ Function(Function/*!*/ op, params VCExpr[]/*!*/ arguments) {
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(op != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(BoogieFunctionOp(op), arguments);
+ }
+
+
+ // The following method should really be called "ReduceLeft". It must
+ // only be used for the binary operators "and" and "or"
+ public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return NAry(op, args.ToArray());
+ }
+
+ public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, params VCExpr[]/*!*/ args) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(op == AndOp || op == OrOp);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ bool and = (op == AndOp);
+
+ VCExpr/*!*/ e = and ? True : False;
+ foreach (VCExpr a in args) {
+ e = and ? AndSimp(e, cce.NonNull(a)) : OrSimp(e, cce.NonNull(a));
+ }
+ return e;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ public static readonly VCExprOp NotOp = new VCExprNAryOp(1, Type.Bool);
+ public static readonly VCExprOp EqOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp NeqOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp AndOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp OrOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp ImpliesOp = new VCExprNAryOp(2, Type.Bool);
+
+ public VCExprDistinctOp DistinctOp(int arity) {
+ Contract.Ensures(Contract.Result<VCExprDistinctOp>() != null);
+
+ return new VCExprDistinctOp(arity);
+ }
+
+ public VCExpr/*!*/ Not(List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(args != null);
+ Contract.Requires(args.Count == 1);
+ Contract.Requires(args[0] != null);
+ return Function(NotOp, args);
+ }
+
+ public VCExpr/*!*/ Not(VCExpr/*!*/ e0) {
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(NotOp, e0);
+ }
+ public VCExpr/*!*/ Eq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ return Function(EqOp, e0, e1);
+ }
+ public VCExpr/*!*/ Neq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(NeqOp, e0, e1);
+ }
+ public VCExpr/*!*/ And(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(AndOp, e0, e1);
+ }
+ public VCExpr/*!*/ Gt(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
+ {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(GtOp, e0, e1);
+ }
+ public VCExpr/*!*/ Add(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
+ {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExprOp op = cce.NonNull(cce.NonNull(e0).Type).IsInt ? AddIOp : AddROp;
+ return Function(op, e0, e1);
+ }
+ public VCExpr/*!*/ Or(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(OrOp, e0, e1);
+ }
+ public VCExpr/*!*/ Implies(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(ImpliesOp, e0, e1);
+ }
+ public VCExpr/*!*/ Distinct(List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (args.Count <= 1)
+ // trivial case
+ return True;
+ return Function(DistinctOp(args.Count), args);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Versions of the propositional operators that automatically simplify in
+ // certain cases (for example, if one of the operators is True or False)
+
+ public VCExpr NotSimp(VCExpr e0) {
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(True))
+ return False;
+ if (e0.Equals(False))
+ return True;
+ return Not(e0);
+ }
+ public VCExpr AndSimp(VCExpr e0, VCExpr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(True))
+ return e1;
+ if (e1.Equals(True))
+ return e0;
+ if (e0.Equals(False) || e1.Equals(False))
+ return False;
+ return And(e0, e1);
+ }
+ public VCExpr OrSimp(VCExpr e0, VCExpr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(False))
+ return e1;
+ if (e1.Equals(False))
+ return e0;
+ if (e0.Equals(True) || e1.Equals(True))
+ return True;
+ return Or(e0, e1);
+ }
+ public VCExpr ImpliesSimp(VCExpr e0, VCExpr e1, bool aggressive = true) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(True))
+ return e1;
+ if (e1.Equals(False))
+ return NotSimp(e0);
+ if (e0.Equals(False) || e1.Equals(True))
+ return True;
+ // attempt to save on the depth of expressions (to reduce chances of stack overflows)
+ while (aggressive && e1 is VCExprBinary) {
+ VCExprBinary n = (VCExprBinary)e1;
+ if (n.Op == ImpliesOp) {
+ if (AndSize(n[0]) <= AndSize(e0)) {
+ // combine the antecedents
+ e0 = And(e0, n[0]);
+ e1 = n[1];
+ continue;
+ }
+ }
+ break;
+ }
+ return Implies(e0, e1);
+ }
+
+ ///<summary>
+ /// Returns some measure of the number of conjuncts in e. This could be the total number of conjuncts in all
+ /// top-most layers of the expression, or it can simply be the length of the left-prong of this and-tree. The
+ /// important thing is that: AndSize(e0) >= AndSize(31) ==> AndSize(And(e0,e1)) > AndSize(e0).
+ ///</summary>
+ int AndSize(VCExpr e) {
+ Contract.Requires(e != null);
+ int n = 1;
+ while (true) {
+ VCExprNAry nary = e as VCExprNAry;
+ if (nary != null && nary.Op == AndOp && 2 <= nary.Arity) {
+ e = nary[0];
+ n++;
+ } else {
+ return n;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Further operators
+
+ public static readonly VCExprOp AddIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp AddROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp SubIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp SubROp = new VCExprNAryOp(2, Type.Real);
+ // public static readonly VCExprOp SubFOp = new VCExprNAryOp(2, Type.Float);
+ public static readonly VCExprOp MulIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp MulROp = new VCExprNAryOp(2, Type.Real);
+ //public static readonly VCExprOp MulFOp = new VCExprNAryOp(2, Type.Float);
+ public static readonly VCExprOp DivIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp DivROp = new VCExprNAryOp(2, Type.Real);
+ //public static readonly VCExprOp DivFOp = new VCExprNAryOp(2, Type.Float);
+ public static readonly VCExprOp ModOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp PowOp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp LtOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp LeOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp GtOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp GeOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp SubtypeOp = new VCExprNAryOp(2, Type.Bool);
+ // ternary version of the subtype operator, the first argument of which gives
+ // the type of the compared terms
+ public static readonly VCExprOp Subtype3Op = new VCExprNAryOp(3, Type.Bool);
+ public static readonly VCExprOp IfThenElseOp = new VCExprIfThenElseOp();
+ public static readonly VCExprOp ToIntOp = new VCExprNAryOp(1, Type.Int);
+ public static readonly VCExprOp ToRealOp = new VCExprNAryOp(1, Type.Real);
+ //public static readonly VCExprOp ToFloatOp = new VCExprNAryOp(1, Type.Float);
+
+ public static readonly VCExprOp TickleBoolOp = new VCExprCustomOp("tickleBool", 1, Type.Bool);
+
+ public static readonly VCExprOp TimeoutDiagnosticsOp = new VCExprCustomOp("timeoutDiagnostics", 1, Type.Bool);
+
+ public static readonly VCExprOp MinimizeOp = new VCExprCustomOp("minimize##dummy", 2, Type.Bool);
+ public static readonly VCExprOp MaximizeOp = new VCExprCustomOp("maximize##dummy", 2, Type.Bool);
+ public static readonly VCExprOp NamedAssumeOp = new VCExprCustomOp("named_assume##dummy", 2, Type.Bool);
+
+ public VCExprOp BoogieFunctionOp(Function func) {
+ Contract.Requires(func != null);
+ Contract.Ensures(Contract.Result<VCExprOp>() != null);
+ return new VCExprBoogieFunctionOp(func);
+ }
+
+ // Float nodes
+
+ public VCExprOp BinaryFloatOp(int exp, int man, string op)
+ {
+ Contract.Requires(exp > 0);
+ Contract.Requires(man > 0);
+ Contract.Requires(op != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return new VCExprBinaryFloatOp(exp, man, op);
+ }
+
+ // Bitvector nodes
+
+ public VCExpr Bitvector(BvConst bv) {
+ Contract.Requires(bv != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprBvOp(bv.Bits), Integer(bv.Value));
+ }
+
+ public VCExpr BvExtract(VCExpr bv, int bits, int start, int end) {
+ Contract.Requires(bv != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprBvExtractOp(start, end, bits), bv);
+ }
+
+ public VCExpr BvConcat(VCExpr bv1, VCExpr bv2) {
+ Contract.Requires(bv2 != null);
+ Contract.Requires(bv1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprBvConcatOp(bv1.Type.BvBits, bv2.Type.BvBits), bv1, bv2);
+ }
+
+ public VCExpr AtMost(VCExpr smaller, VCExpr greater) {
+ Contract.Requires(greater != null);
+ Contract.Requires(smaller != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(SubtypeOp, smaller, greater);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Dispatcher for the visitor
+
+ // the declared singleton operators
+ internal enum SingletonOp {
+ NotOp,
+ EqOp,
+ NeqOp,
+ AndOp,
+ OrOp,
+ ImpliesOp,
+ AddOp,
+ SubOp,
+ MulOp,
+ DivOp,
+ ModOp,
+ RealDivOp,
+ PowOp,
+ LtOp,
+ LeOp,
+ GtOp,
+ GeOp,
+ SubtypeOp,
+ Subtype3Op,
+ BvConcatOp,
+ ToIntOp,
+ ToRealOp,
+ ToFloatOp
+ };
+ internal static Dictionary<VCExprOp/*!*/, SingletonOp>/*!*/ SingletonOpDict;
+ [ContractInvariantMethod]
+ void MiscInvariant() {
+ Contract.Invariant(SingletonOpDict != null);
+ }
+
+
+ static VCExpressionGenerator() {
+ SingletonOpDict = new Dictionary<VCExprOp/*!*/, SingletonOp>();
+ SingletonOpDict.Add(NotOp, SingletonOp.NotOp);
+ SingletonOpDict.Add(EqOp, SingletonOp.EqOp);
+ SingletonOpDict.Add(NeqOp, SingletonOp.NeqOp);
+ SingletonOpDict.Add(AndOp, SingletonOp.AndOp);
+ SingletonOpDict.Add(OrOp, SingletonOp.OrOp);
+ SingletonOpDict.Add(ImpliesOp, SingletonOp.ImpliesOp);
+ SingletonOpDict.Add(AddIOp, SingletonOp.AddOp);
+ SingletonOpDict.Add(AddROp, SingletonOp.AddOp);
+ SingletonOpDict.Add(SubIOp, SingletonOp.SubOp);
+ SingletonOpDict.Add(SubROp, SingletonOp.SubOp);
+ //SingletonOpDict.Add(SubFOp, SingletonOp.SubOp);
+ SingletonOpDict.Add(MulIOp, SingletonOp.MulOp);
+ SingletonOpDict.Add(MulROp, SingletonOp.MulOp);
+ //SingletonOpDict.Add(MulFOp, SingletonOp.MulOp);
+ SingletonOpDict.Add(DivIOp, SingletonOp.DivOp);
+ SingletonOpDict.Add(DivROp, SingletonOp.RealDivOp);
+ //SingletonOpDict.Add(DivFOp, SingletonOp.FloatDivOp);
+ SingletonOpDict.Add(ModOp, SingletonOp.ModOp);
+ SingletonOpDict.Add(PowOp, SingletonOp.PowOp);
+ SingletonOpDict.Add(LtOp, SingletonOp.LtOp);
+ SingletonOpDict.Add(LeOp, SingletonOp.LeOp);
+ SingletonOpDict.Add(GtOp, SingletonOp.GtOp);
+ SingletonOpDict.Add(GeOp, SingletonOp.GeOp);
+ SingletonOpDict.Add(SubtypeOp, SingletonOp.SubtypeOp);
+ SingletonOpDict.Add(Subtype3Op, SingletonOp.Subtype3Op);
+ SingletonOpDict.Add(ToIntOp, SingletonOp.ToIntOp);
+ SingletonOpDict.Add(ToRealOp, SingletonOp.ToRealOp);
+ //SingletonOpDict.Add(ToFloatOp, SingletonOp.ToFloatOp);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ // Let-bindings
+
+ public VCExprLetBinding LetBinding(VCExprVar v, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(v != null);
+ Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
+ return new VCExprLetBinding(v, e);
+ }
+
+ // A "real" let expression. All let-bindings happen simultaneously, i.e.,
+ // at this level the order of the bindings does not matter. It is possible to
+ // create expressions like "let x = y, y = 5 in ...". All bound variables are
+ // bound in all bound terms/formulas and can occur there, but the dependencies
+ // have to be acyclic
+ public VCExpr Let(List<VCExprLetBinding> bindings, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (bindings.Count == 0)
+ // no empty let-bindings
+ return body;
+ return new VCExprLet(bindings, body);
+ }
+
+ public VCExpr Let(VCExpr body, params VCExprLetBinding[] bindings) {
+ Contract.Requires(body != null);
+ Contract.Requires((cce.NonNullElements(bindings)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Let(HelperFuns.ToNonNullList(bindings), body);
+ }
+
+
+ /// <summary>
+ /// In contrast to the previous method, the following methods are not a general LET.
+ /// Instead, it
+ /// is a boolean "LET b = P in Q", where P and Q are predicates, that is allowed to be
+ /// encoded as "(b == P) ==> Q" or even as "(P ==> b) ==> Q"
+ /// (or "(P ==> b) and Q" in negative positions).
+ /// The method assumes that the variables in the bindings are unique in the entire formula
+ /// to be produced, which allows the implementation to ignore scope issues in the event that
+ /// it needs to generate an alternate expression for LET.
+ /// </summary>
+
+
+ // Turn let-bindings let v = E in ... into implications E ==> v
+ public VCExpr AsImplications(List<VCExprLetBinding> bindings) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ antecedents = True;
+ foreach (VCExprLetBinding b in bindings)
+ // turn "LET_binding v = E" into "v <== E"
+ antecedents = AndSimp(antecedents, Implies(b.E, b.V));
+ return antecedents;
+ }
+
+ // Turn let-bindings let v = E in ... into equations v == E
+ public VCExpr AsEquations(List<VCExprLetBinding> bindings) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ antecedents = True;
+ foreach (VCExprLetBinding b in bindings)
+ // turn "LET_binding v = E" into "v <== E"
+ antecedents = AndSimp(antecedents, Eq(b.E, b.V));
+ return antecedents;
+ }
+
+
+
+ // Maps
+
+ public VCExpr Select(params VCExpr[] allArgs) {
+ Contract.Requires(allArgs != null);
+ Contract.Requires((cce.NonNullElements(allArgs)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprSelectOp(allArgs.Length - 1, 0),
+ HelperFuns.ToNonNullList(allArgs),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr Select(VCExpr[] allArgs, Type[] typeArgs) {
+ Contract.Requires(1 <= allArgs.Length);
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprSelectOp(allArgs.Length - 1, typeArgs.Length),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr Select(List<VCExpr> allArgs, List<Type> typeArgs) {
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires((1 <= allArgs.Count));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprSelectOp(allArgs.Count - 1, typeArgs.Count),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr Store(params VCExpr[] allArgs) {
+ Contract.Requires(allArgs != null);
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprStoreOp(allArgs.Length - 2, 0),
+ HelperFuns.ToNonNullList(allArgs),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr Store(VCExpr[] allArgs, Type[] typeArgs) {
+ Contract.Requires(typeArgs != null);
+ Contract.Requires(allArgs != null);
+ Contract.Requires((2 <= allArgs.Length));
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprStoreOp(allArgs.Length - 2, typeArgs.Length),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr Store(List<VCExpr> allArgs, List<Type/*!*/>/*!*/ typeArgs) {
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires((2 <= allArgs.Count));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprStoreOp(allArgs.Count - 2, typeArgs.Count),
+ allArgs, typeArgs);
+ }
+
+
+ // Labels
+
+ public VCExprLabelOp LabelOp(bool pos, string l) {
+ Contract.Requires(l != null);
+ Contract.Ensures(Contract.Result<VCExprLabelOp>() != null);
+ return new VCExprLabelOp(pos, l);
+ }
+
+ public VCExpr LabelNeg(string label, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e.Equals(True)) {
+ return e; // don't bother putting negative labels around True (which will expose the True to further peephole optimizations)
+ }
+ return Function(LabelOp(false, label), e);
+ }
+ public VCExpr LabelPos(string label, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(LabelOp(true, label), e);
+ }
+
+ // Quantifiers
+
+ public VCExpr Quantify(Quantifier quan, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return new VCExprQuantifier(quan, typeParams, vars, triggers, infos, body);
+ }
+
+ public VCExpr Forall(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.ALL, typeParams, vars, triggers, infos, body);
+ }
+ public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, string qid, int weight, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(qid != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ QKeyValue kv = null;
+ if (0 <= weight) {
+ kv = new QKeyValue(Token.NoToken, "weight", new List<object>() { new LiteralExpr(Token.NoToken, BigNum.FromInt(0)) }, null);
+ }
+ return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
+ triggers, new VCQuantifierInfos(qid, -1, false, kv), body);
+ }
+ public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
+ triggers, new VCQuantifierInfos(null, -1, false, null), body);
+ }
+ public VCExpr Forall(VCExprVar var, VCTrigger trigger, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(trigger != null);
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Forall(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
+ }
+ public VCExpr Exists(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.EX, typeParams, vars, triggers, infos, body);
+ }
+ public VCExpr Exists(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.EX, new List<TypeVariable/*!*/>(), vars,
+ triggers, new VCQuantifierInfos(null, -1, false, null), body);
+ }
+ public VCExpr Exists(VCExprVar var, VCTrigger trigger, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(trigger != null);
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Exists(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
+ }
+
+ public VCTrigger Trigger(bool pos, List<VCExpr> exprs) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(Contract.Result<VCTrigger>() != null);
+ return new VCTrigger(pos, exprs);
+ }
+
+ public VCTrigger Trigger(bool pos, params VCExpr[] exprs) {
+ Contract.Requires(exprs != null);
+ Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
+ Contract.Ensures(Contract.Result<VCTrigger>() != null);
+ return Trigger(pos, HelperFuns.ToNonNullList(exprs));
+ }
+
+ // Reference to a bound or free variable
+
+ public VCExprVar Variable(string name, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ return new VCExprVar(name, type);
+ }
+ }
+}
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ public class HelperFuns {
+ public static bool SameElements(IEnumerable a, IEnumerable b) {
+ Contract.Requires(b != null);
+ Contract.Requires(a != null);
+ IEnumerator ia = a.GetEnumerator();
+ IEnumerator ib = b.GetEnumerator();
+ while (true) {
+ if (ia.MoveNext()) {
+ if (ib.MoveNext()) {
+ if (!cce.NonNull(ia.Current).Equals(ib.Current))
+ return false;
+ } else {
+ return false;
+ }
+ } else {
+ return !ib.MoveNext();
+ }
+ }
+ }
+
+ public static int PolyHash(int init, int factor, IEnumerable a) {
+ Contract.Requires(a != null);
+ int res = init;
+ foreach (object x in a)
+ res = res * factor + (cce.NonNull(x)).GetHashCode();
+ return res;
+ }
+
+ public static List<T> ToList<T>(IEnumerable<T> l) {
+ Contract.Requires(l != null);
+ Contract.Ensures(Contract.Result<List<T>>() != null);
+ List<T>/*!*/ res = new List<T>();
+ foreach (T x in l)
+ res.Add(x);
+ return res;
+ }
+
+ public static List<Type> ToTypeSeq(VCExpr[] exprs, int startIndex) {
+ Contract.Requires(exprs != null);
+ Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
+ Contract.Ensures(Contract.Result<List<Type>>() != null);
+ List<Type>/*!*/ res = new List<Type>();
+ for (int i = startIndex; i < exprs.Length; ++i)
+ res.Add(cce.NonNull(exprs[i]).Type);
+ return res;
+ }
+
+ public static List<T/*!*/>/*!*/ ToNonNullList<T>(params T[] args) where T : class {
+ Contract.Requires(args != null);
+ List<T/*!*/>/*!*/ res = new List<T>(args.Length);
+ foreach (T t in args)
+ res.Add(cce.NonNull(t));
+ return res;
+ }
+
+ public static IDictionary<A, B> Clone<A, B>(IDictionary<A, B> dict) {
+ Contract.Requires(dict != null);
+ Contract.Ensures(Contract.Result<IDictionary<A, B>>() != null);
+ IDictionary<A, B> res = new Dictionary<A, B>(dict.Count);
+ foreach (KeyValuePair<A, B> pair in dict)
+ res.Add(pair);
+ return res;
+ }
+ }
+
+ [ContractClassFor(typeof(VCExpr))]
+ public abstract class VCExprContracts : VCExpr {
+ public override Type Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ throw new NotImplementedException();
+ }
+
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ Contract.Requires(visitor != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ [ContractClass(typeof(VCExprContracts))]
+ public abstract class VCExpr {
+ public abstract Type Type {
+ get;
+ }
+
+ public abstract Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg);
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringWriter sw = new StringWriter();
+ VCExprPrinter printer = new VCExprPrinter();
+ printer.Print(this, sw);
+ return cce.NonNull(sw.ToString());
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Literal expressions
+
+ public class VCExprLiteral : VCExpr {
+ private readonly Type LitType;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(LitType != null);
+ }
+
+ public override Type Type {
+ get {
+ return LitType;
+ }
+ }
+ internal VCExprLiteral(Type type) {
+ Contract.Requires(type != null);
+ this.LitType = type;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ public class VCExprIntLit : VCExprLiteral {
+ public readonly BigNum Val;
+ internal VCExprIntLit(BigNum val)
+ : base(Type.Int) {
+ this.Val = val;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprIntLit)
+ return Val == ((VCExprIntLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
+ public class VCExprRealLit : VCExprLiteral {
+ public readonly BigDec Val;
+ internal VCExprRealLit(BigDec val)
+ : base(Type.Real) {
+ this.Val = val;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprRealLit)
+ return Val == ((VCExprRealLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
+ public class VCExprFloatLit : VCExprLiteral
+ {
+ public readonly BigFloat Val;
+ internal VCExprFloatLit(BigFloat val)
+ : base(Type.GetFloatType(val.ExponentSize, val.SignificandSize))
+ {
+ this.Val = val;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that)
+ {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprFloatLit)
+ return Val == ((VCExprFloatLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode()
+ {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Operator expressions with fixed arity
+ [ContractClassFor(typeof(VCExprNAry))]
+ public abstract class VCExprNAryContracts : VCExprNAry {
+ public VCExprNAryContracts()
+ : base(null) {
+ }
+ public override VCExpr this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ throw new NotImplementedException();
+ }
+ }
+ }
+
+ [ContractClass(typeof(VCExprNAryContracts))]
+ public abstract class VCExprNAry : VCExpr, IEnumerable<VCExpr/*!*/> {
+ public readonly VCExprOp Op;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ Contract.Invariant(cce.NonNullElements(EMPTY_TYPE_LIST));
+ Contract.Invariant(cce.NonNullElements(EMPTY_VCEXPR_LIST));
+ }
+
+ public int Arity {
+ get {
+ return Op.Arity;
+ }
+ }
+ public int TypeParamArity {
+ get {
+ return Op.TypeParamArity;
+ }
+ }
+ public int Length {
+ get {
+ return Arity;
+ }
+ }
+ // the sub-expressions of the expression
+ public abstract VCExpr/*!*/ this[int index] {
+ get;
+ }
+
+ // the type arguments
+ public abstract List<Type/*!*/>/*!*/ TypeArguments {
+ get;
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ public IEnumerator<VCExpr/*!*/>/*!*/ GetEnumerator() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExpr>>()));
+ for (int i = 0; i < Arity; ++i)
+ yield return this[i];
+ }
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ for (int i = 0; i < Arity; ++i)
+ yield return this[i];
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprNAry) {
+ // we compare the subterms iteratively (not recursively)
+ // to avoid stack overflows
+
+ VCExprNAryEnumerator enum0 = new VCExprNAryEnumerator(this);
+ VCExprNAryEnumerator enum1 = new VCExprNAryEnumerator((VCExprNAry)that);
+
+ while (true) {
+ bool next0 = enum0.MoveNext();
+ bool next1 = enum1.MoveNext();
+ if (next0 != next1)
+ return false;
+ if (!next0)
+ return true;
+
+ VCExprNAry nextExprNAry0 = enum0.Current as VCExprNAry;
+ VCExprNAry nextExprNAry1 = enum1.Current as VCExprNAry;
+
+ if ((nextExprNAry0 == null) != (nextExprNAry1 == null))
+ return false;
+ if (nextExprNAry0 != null && nextExprNAry1 != null) {
+ if (!nextExprNAry0.Op.Equals(nextExprNAry1.Op))
+ return false;
+ } else {
+ if (!cce.NonNull(enum0.Current).Equals(enum1.Current))
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return HelperFuns.PolyHash(Op.GetHashCode() * 123 + Arity * 61521,
+ 3, this);
+ }
+
+ internal VCExprNAry(VCExprOp op) {
+ Contract.Requires(op != null);
+ this.Op = op;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ public Result Accept<Result, Arg>(IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ Contract.Requires(visitor != null);
+ return Op.Accept(this, visitor, arg);
+ }
+
+ internal static readonly List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
+ internal static readonly List<VCExpr/*!*/>/*!*/ EMPTY_VCEXPR_LIST = new List<VCExpr/*!*/>();
+
+ public IEnumerable<VCExpr> UniformArguments
+ {
+ get
+ {
+ var enumerator = new VCExprNAryUniformOpEnumerator(this);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(this.Op)) {
+ yield return (VCExpr)enumerator.Current;
+ }
+ }
+ }
+ }
+ }
+
+ // We give specialised implementations for nullary, unary and binary expressions
+
+ internal class VCExprNullary : VCExprNAry {
+ private readonly Type ExprType;
+ [ContractInvariantMethod]
+ void loneinvariant() {
+ Contract.Invariant(ExprType != null);
+ }
+
+ public override Type Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // no arguments
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return EMPTY_TYPE_LIST;
+ }
+ }
+
+ internal VCExprNullary(VCExprOp op)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(op.Arity == 0 && op.TypeParamArity == 0);
+ this.ExprType = op.InferType(EMPTY_VCEXPR_LIST, EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprUnary : VCExprNAry {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Argument != null);
+ Contract.Invariant(ExprType != null);
+
+ }
+
+ private readonly VCExpr/*!*/ Argument;
+ private readonly Type/*!*/ ExprType;
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr/*!*/ this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Contract.Assume(index == 0);
+ return Argument;
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return EMPTY_TYPE_LIST;
+ }
+ }
+
+ internal VCExprUnary(VCExprOp op, List<VCExpr> arguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0 && arguments.Count == 1);
+
+ this.Argument = arguments[0];
+ this.ExprType =
+ op.InferType(arguments, EMPTY_TYPE_LIST);
+ }
+
+ internal VCExprUnary(VCExprOp op, VCExpr argument)
+ : base(op) {
+ Contract.Requires(argument != null);
+ Contract.Requires(op != null);
+ Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0);
+
+ this.Argument = argument;
+ // PR: could be optimised so that the argument does
+ // not have to be boxed in an array each time
+ this.ExprType =
+ op.InferType(HelperFuns.ToNonNullList(argument), EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprBinary : VCExprNAry {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Argument0 != null);
+ Contract.Invariant(Argument1 != null);
+ Contract.Invariant(ExprType != null);
+ }
+
+ private readonly VCExpr Argument0;
+ private readonly VCExpr Argument1;
+ private readonly Type ExprType;
+ public override Type Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ switch (index) {
+ case 0:
+ return Argument0;
+ case 1:
+ return Argument1;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return EMPTY_TYPE_LIST;
+ }
+ }
+
+ internal VCExprBinary(VCExprOp op, List<VCExpr> arguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0 && arguments.Count == 2);
+
+ this.Argument0 = arguments[0];
+ this.Argument1 = arguments[1];
+ this.ExprType = op.InferType(arguments, EMPTY_TYPE_LIST);
+ }
+
+ internal VCExprBinary(VCExprOp op, VCExpr argument0, VCExpr argument1)
+ : base(op) {
+ Contract.Requires(argument1 != null);
+ Contract.Requires(argument0 != null);
+ Contract.Requires(op != null);
+ Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0);
+ this.Argument0 = argument0;
+ this.Argument1 = argument1;
+ // PR: could be optimised so that the arguments do
+ // not have to be boxed in an array each time
+ this.ExprType =
+ op.InferType(HelperFuns.ToNonNullList(argument0, argument1),
+ EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprMultiAry : VCExprNAry {
+ private readonly List<VCExpr/*!*/>/*!*/ Arguments;
+ private readonly List<Type/*!*/>/*!*/ TypeArgumentsAttr;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(Arguments));
+ Contract.Invariant(cce.NonNullElements(TypeArgumentsAttr));
+ Contract.Invariant(ExprType != null);
+ }
+
+
+ private readonly Type/*!*/ ExprType;
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr/*!*/ this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Contract.Assume(index >= 0 && index < Arity);
+ return cce.NonNull(Arguments)[index];
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return TypeArgumentsAttr;
+ }
+ }
+
+ internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ this.Arguments = arguments;
+ this.TypeArgumentsAttr = EMPTY_TYPE_LIST;
+ this.ExprType = op.InferType(arguments, TypeArgumentsAttr);
+ }
+ internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments, List<Type/*!*/>/*!*/ typeArguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(typeArguments));
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(arguments.Count > 2 || typeArguments.Count > 0);
+ Contract.Requires(op.Arity == arguments.Count);
+ Contract.Requires(op.TypeParamArity == typeArguments.Count);
+ this.Arguments = arguments;
+ this.TypeArgumentsAttr = typeArguments;
+ this.ExprType = op.InferType(arguments, typeArguments);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // The various operators available
+ [ContractClass(typeof(VCExprOpContracts))]
+ public abstract class VCExprOp {
+ // the number of value parameters
+ public abstract int Arity {
+ get;
+ }
+ // the number of type parameters
+ public abstract int TypeParamArity {
+ get;
+ }
+
+ public abstract Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs);
+
+ public virtual Result Accept<Result, Arg>(VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ Contract.Requires(visitor != null);
+ Contract.Requires(expr != null);
+ VCExpressionGenerator.SingletonOp op;
+ if (VCExpressionGenerator.SingletonOpDict.TryGetValue(this, out op)) {
+ switch (op) {
+ case VCExpressionGenerator.SingletonOp.NotOp:
+ return visitor.VisitNotOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.EqOp:
+ return visitor.VisitEqOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.NeqOp:
+ return visitor.VisitNeqOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.AndOp:
+ return visitor.VisitAndOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.OrOp:
+ return visitor.VisitOrOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ImpliesOp:
+ return visitor.VisitImpliesOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.AddOp:
+ return visitor.VisitAddOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.SubOp:
+ return visitor.VisitSubOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.MulOp:
+ return visitor.VisitMulOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.DivOp:
+ return visitor.VisitDivOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ModOp:
+ return visitor.VisitModOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.RealDivOp:
+ return visitor.VisitRealDivOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.PowOp:
+ return visitor.VisitPowOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.LtOp:
+ return visitor.VisitLtOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.LeOp:
+ return visitor.VisitLeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.GtOp:
+ return visitor.VisitGtOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.GeOp:
+ return visitor.VisitGeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.SubtypeOp:
+ return visitor.VisitSubtypeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.Subtype3Op:
+ return visitor.VisitSubtype3Op(expr, arg);
+ case VCExpressionGenerator.SingletonOp.BvConcatOp:
+ return visitor.VisitBvConcatOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ToIntOp:
+ return visitor.VisitToIntOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ToRealOp:
+ return visitor.VisitToRealOp(expr, arg);
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+ [ContractClassFor(typeof(VCExprOp))]
+ abstract class VCExprOpContracts : VCExprOp {
+ public override Type InferType(List<VCExpr> args, List<Type> typeArgs) {
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public class VCExprNAryOp : VCExprOp {
+ private readonly Type OpType;
+ private readonly int OpArity;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(OpType != null);
+ }
+
+ public override int Arity {
+ get {
+ return OpArity;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return OpType;
+ }
+
+ internal VCExprNAryOp(int arity, Type type) {
+ Contract.Requires(type != null);
+ this.OpArity = arity;
+ this.OpType = type;
+ }
+ }
+
+ public class VCExprDistinctOp : VCExprNAryOp {
+ internal VCExprDistinctOp(int arity)
+ : base(arity, Type.Bool) {
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprDistinctOp)
+ return Arity == ((VCExprDistinctOp)that).Arity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 917632481;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitDistinctOp(expr, arg);
+ }
+ }
+
+ public class VCExprLabelOp : VCExprOp {
+ public override int Arity {
+ get {
+ return 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return args[0].Type;
+ }
+
+ public readonly bool pos;
+ public readonly string label;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(label != null);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLabelOp) {
+ VCExprLabelOp/*!*/ thatOp = (VCExprLabelOp)that;
+ return this.pos == thatOp.pos && this.label.Equals(thatOp.label);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (pos ? 9817231 : 7198639) + label.GetHashCode();
+ }
+
+ internal VCExprLabelOp(bool pos, string l) {
+ Contract.Requires(l != null);
+ this.pos = pos;
+ this.label = pos ? "+" + l : "@" + l;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitLabelOp(expr, arg);
+ }
+ }
+
+ public class VCExprSelectOp : VCExprOp {
+ private readonly int MapArity;
+ private readonly int MapTypeParamArity;
+ public override int Arity {
+ get {
+ return MapArity + 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return MapTypeParamArity;
+ }
+ }
+
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ MapType/*!*/ mapType = args[0].Type.AsMap;
+ Contract.Assert(TypeParamArity == mapType.TypeParameters.Count);
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ for (int i = 0; i < TypeParamArity; ++i)
+ subst.Add(mapType.TypeParameters[i], typeArgs[i]);
+ return mapType.Result.Substitute(subst);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprSelectOp)
+ return Arity == ((VCExprSelectOp)that).Arity &&
+ TypeParamArity == ((VCExprSelectOp)that).TypeParamArity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 1212481 + TypeParamArity * 298741;
+ }
+
+ internal VCExprSelectOp(int arity, int typeParamArity) {
+ Contract.Requires(0 <= arity && 0 <= typeParamArity);
+ this.MapArity = arity;
+ this.MapTypeParamArity = typeParamArity;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitSelectOp(expr, arg);
+ }
+ }
+
+ public class VCExprStoreOp : VCExprOp {
+ private readonly int MapArity;
+ private readonly int MapTypeParamArity;
+ public override int Arity {
+ get {
+ return MapArity + 2;
+ }
+ }
+ // stores never need explicit type parameters, because also the
+ // rhs is a value argument
+ public override int TypeParamArity {
+ get {
+ return MapTypeParamArity;
+ }
+ }
+
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return args[0].Type;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprStoreOp)
+ return Arity == ((VCExprStoreOp)that).Arity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 91361821;
+ }
+
+ internal VCExprStoreOp(int arity, int typeParamArity) {
+ Contract.Requires(0 <= arity && 0 <= typeParamArity);
+ this.MapArity = arity;
+ this.MapTypeParamArity = typeParamArity;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitStoreOp(expr, arg);
+ }
+ }
+
+ public class VCExprIfThenElseOp : VCExprOp {
+ public override int Arity {
+ get {
+ return 3;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return args[1].Type;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprIfThenElseOp)
+ return true;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return 1;
+ }
+
+ internal VCExprIfThenElseOp() {
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitIfThenElseOp(expr, arg);
+ }
+ }
+
+ public class VCExprSoftOp : VCExprCustomOp
+ {
+ public readonly int Weight;
+
+ public VCExprSoftOp(int weight) : base("soft##dummy", 2, Microsoft.Boogie.Type.Bool)
+ {
+ Weight = weight;
+ }
+ }
+
+ public class VCExprCustomOp : VCExprOp {
+ public readonly string/*!*/ Name;
+ int arity;
+ public readonly Type/*!*/ Type;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ Contract.Invariant(Type != null);
+ }
+
+ public VCExprCustomOp(string/*!*/ name, int arity, Type/*!*/ type) {
+ Contract.Requires(name != null);
+ Contract.Requires(type != null);
+ this.Name = name;
+ this.arity = arity;
+ this.Type = type;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ VCExprCustomOp t = that as VCExprCustomOp;
+ if (t == null)
+ return false;
+ return this.Name == t.Name && this.arity == t.arity && this.Type == t.Type;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override int GetHashCode() {
+ int h = Name.GetHashCode();
+ h = 7823 * h + arity;
+ h = 7823 * h + Type.GetHashCode();
+ return h;
+ }
+ public override int Arity {
+ get {
+ return arity;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires((cce.NonNullElements(args)));
+ //Contract.Requires((cce.NonNullElements(typeArgs)));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry/*!*/ expr, IVCExprOpVisitor<Result, Arg>/*!*/ visitor, Arg arg) {
+ //Contract.Requires(expr != null);
+ //Contract.Requires(visitor != null);
+ return visitor.VisitCustomOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Float operators
+
+ public class VCExprBinaryFloatOp : VCExprOp {
+ public readonly int Mantissa;
+ public readonly int Exponent;
+ private string op;
+
+ public override int Arity {
+ get {
+ return 2;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 2;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetFloatType(Exponent, Mantissa);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBinaryFloatOp)
+ return this.Exponent == ((VCExprBinaryFloatOp)that).Exponent && this.Mantissa == ((VCExprBinaryFloatOp)that).Mantissa;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Exponent * 81748912 + Mantissa * 67867979;
+ }
+
+ internal VCExprBinaryFloatOp(int exp, int man, string op) {
+ this.Exponent = exp;
+ this.Mantissa = man;
+ this.op = op;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ switch (op) {
+ case ("+"):
+ return visitor.VisitFloatAddOp(expr, arg);
+ case ("-"):
+ return visitor.VisitFloatSubOp(expr, arg);
+ case ("*"):
+ return visitor.VisitFloatMulOp(expr, arg);
+ case ("/"):
+ return visitor.VisitFloatDivOp(expr, arg);
+ case ("rem"):
+ return visitor.VisitFloatRemOp(expr, arg);
+ case ("min"):
+ return visitor.VisitFloatMinOp(expr, arg);
+ case ("max"):
+ return visitor.VisitFloatMaxOp(expr, arg);
+ case ("<="):
+ return visitor.VisitFloatLeqOp(expr, arg);
+ case ("<"):
+ return visitor.VisitFloatLtOp(expr, arg);
+ case (">="):
+ return visitor.VisitFloatGeqOp(expr, arg);
+ case (">"):
+ return visitor.VisitFloatGtOp(expr, arg);
+ case ("=="):
+ return visitor.VisitFloatEqOp(expr, arg);
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Bitvector operators
+
+ public class VCExprBvOp : VCExprOp {
+ public readonly int Bits;
+
+ public override int Arity {
+ get {
+ return 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetBvType(Bits);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvOp)
+ return this.Bits == ((VCExprBvOp)that).Bits;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Bits * 81748912;
+ }
+
+ internal VCExprBvOp(int bits) {
+ this.Bits = bits;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBvOp(expr, arg);
+ }
+ }
+
+ public class VCExprBvExtractOp : VCExprOp {
+ public readonly int Start;
+ public readonly int End;
+ public readonly int Total; // the number of bits from which the End-Start bits are extracted
+
+ public override int Arity {
+ get {
+ return 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetBvType(End - Start);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvExtractOp) {
+ VCExprBvExtractOp/*!*/ thatExtract = (VCExprBvExtractOp)that;
+ return this.Start == thatExtract.Start && this.End == thatExtract.End && this.Total == thatExtract.Total;
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Start * 81912 + End * 978132 + Total * 571289;
+ }
+
+ internal VCExprBvExtractOp(int start, int end, int total) {
+ Contract.Requires(0 <= start && start <= end && end <= total);
+ this.Start = start;
+ this.End = end;
+ this.Total = total;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBvExtractOp(expr, arg);
+ }
+ }
+
+ public class VCExprBvConcatOp : VCExprOp {
+ public readonly int LeftSize;
+ public readonly int RightSize;
+
+ public override int Arity {
+ get {
+ return 2;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetBvType(args[0].Type.BvBits + args[1].Type.BvBits);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvConcatOp) {
+ VCExprBvConcatOp thatConcat = (VCExprBvConcatOp)that;
+ return this.LeftSize == thatConcat.LeftSize && this.RightSize == thatConcat.RightSize;
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return LeftSize * 81912 + RightSize * 978132;
+ }
+
+ internal VCExprBvConcatOp(int leftSize, int rightSize) {
+ Contract.Requires(0 <= leftSize && 0 <= rightSize);
+ this.LeftSize = leftSize;
+ this.RightSize = rightSize;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBvConcatOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // References to user-defined Boogie functions
+
+ public class VCExprBoogieFunctionOp : VCExprOp {
+ public readonly Function Func;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Func != null);
+ }
+
+
+ public override int Arity {
+ get {
+ return Func.InParams.Count;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return Func.TypeParameters.Count;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(TypeParamArity == Func.TypeParameters.Count);
+ if (TypeParamArity == 0)
+ return cce.NonNull(Func.OutParams[0]).TypedIdent.Type;
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>(TypeParamArity);
+ for (int i = 0; i < TypeParamArity; ++i)
+ subst.Add(Func.TypeParameters[i], typeArgs[i]);
+ return cce.NonNull(Func.OutParams[0]).TypedIdent.Type.Substitute(subst);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBoogieFunctionOp)
+ return this.Func.Equals(((VCExprBoogieFunctionOp)that).Func);
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Func.GetHashCode() + 18731;
+ }
+
+ // we require that the result type of the expression is specified, because we
+ // do not want to perform full type inference at this point
+ internal VCExprBoogieFunctionOp(Function func) {
+ Contract.Requires(func != null);
+ this.Func = func;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBoogieFunctionOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Binders (quantifiers and let-expressions). We introduce our own class for
+ // term variables, but use the Boogie-AST class for type variables
+
+ public class VCExprVar : VCExpr {
+ // the name of the variable. Note that the name is not used for comparison,
+ // i.e., there can be two distinct variables with the same name
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ Contract.Invariant(VarType != null);
+ }
+
+ public readonly string/*!*/ Name;
+ private readonly Type/*!*/ VarType;
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return VarType;
+ }
+ }
+
+ internal VCExprVar(string name, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ this.Name = name;
+ this.VarType = type;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ public class VCExprConstant : VCExprVar
+ {
+ internal VCExprConstant(string name, Type type) : base(name,type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ }
+ }
+
+ public abstract class VCExprBinder : VCExpr {
+ public readonly VCExpr/*!*/ Body;
+ public readonly List<TypeVariable/*!*/>/*!*/ TypeParameters;
+ public readonly List<VCExprVar/*!*/>/*!*/ BoundVars;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Body != null);
+ Contract.Invariant(cce.NonNullElements(TypeParameters));
+ Contract.Invariant(cce.NonNullElements(BoundVars));
+ }
+
+
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Body.Type;
+ }
+ }
+
+ internal VCExprBinder(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(boundVars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(boundVars.Count + typeParams.Count > 0); // only nontrivial binders ...
+ this.TypeParameters = typeParams;
+ this.BoundVars = boundVars;
+ this.Body = body;
+ }
+ }
+
+ public class VCTrigger {
+ public readonly bool Pos;
+ public readonly List<VCExpr/*!*/>/*!*/ Exprs;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Exprs != null);
+ }
+
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCTrigger) {
+ VCTrigger/*!*/ thatTrigger = (VCTrigger)that;
+ return this.Pos == thatTrigger.Pos &&
+ HelperFuns.SameElements(this.Exprs, thatTrigger.Exprs);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (Pos ? 913821 : 871334) +
+ HelperFuns.PolyHash(123, 7, this.Exprs);
+ }
+
+ public VCTrigger(bool pos, List<VCExpr> exprs) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ this.Pos = pos;
+ this.Exprs = exprs;
+ }
+ }
+
+ public class VCQuantifierInfos {
+ public readonly string qid;
+ public readonly int uniqueId;
+ public readonly bool bvZ3Native;
+ public QKeyValue attributes;
+
+ public VCQuantifierInfos(string qid, int uniqueId, bool bvZ3Native, QKeyValue attributes) {
+ this.qid = qid;
+ this.uniqueId = uniqueId;
+ this.bvZ3Native = bvZ3Native;
+ this.attributes = attributes;
+ }
+ }
+
+ public enum Quantifier {
+ ALL,
+ EX
+ };
+
+ public class VCExprQuantifier : VCExprBinder {
+ public readonly Quantifier Quan;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Infos != null);
+ Contract.Invariant(cce.NonNullElements(Triggers));
+ }
+
+
+ public readonly List<VCTrigger/*!*/>/*!*/ Triggers;
+ public readonly VCQuantifierInfos Infos;
+
+ // Equality is /not/ modulo bound renaming at this point
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprQuantifier) {
+ VCExprQuantifier/*!*/ thatQuan = (VCExprQuantifier)that;
+ return this.Quan == thatQuan.Quan &&
+ HelperFuns.SameElements(this.Triggers, thatQuan.Triggers) &&
+ HelperFuns.SameElements(this.TypeParameters, thatQuan.TypeParameters) &&
+ HelperFuns.SameElements(this.BoundVars, thatQuan.BoundVars) &&
+ this.Body.Equals(thatQuan.Body);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Quan.GetHashCode() +
+ HelperFuns.PolyHash(973219, 7, TypeParameters) +
+ HelperFuns.PolyHash(998431, 9, BoundVars) +
+ HelperFuns.PolyHash(123, 11, Triggers);
+ }
+
+ internal VCExprQuantifier(Quantifier kind, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body)
+ : base(typeParams, boundVars, body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(boundVars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+
+ this.Quan = kind;
+ this.Triggers = triggers;
+ this.Infos = infos;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Let-Bindings
+
+ public class VCExprLetBinding {
+ public readonly VCExprVar V;
+ public readonly VCExpr E;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(V != null);
+ Contract.Invariant(E != null);
+ }
+
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLetBinding) {
+ VCExprLetBinding/*!*/ thatB = (VCExprLetBinding)that;
+ return this.V.Equals(thatB.V) && this.E.Equals(thatB.E);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return V.GetHashCode() * 71261 + E.GetHashCode();
+ }
+
+ internal VCExprLetBinding(VCExprVar v, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(v != null);
+ this.V = v;
+ this.E = e;
+ Contract.Assert(v.Type.Equals(e.Type));
+ }
+ }
+
+ public class VCExprLet : VCExprBinder, IEnumerable<VCExprLetBinding/*!*/> {
+ private readonly List<VCExprLetBinding/*!*/>/*!*/ Bindings;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(Bindings));
+
+ }
+
+
+ public int Length {
+ get {
+ return Bindings.Count;
+ }
+ }
+ public VCExprLetBinding this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
+ return Bindings[index];
+ }
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLet) {
+ VCExprLet/*!*/ thatLet = (VCExprLet)that;
+ return this.Body.Equals(thatLet.Body) &&
+ HelperFuns.SameElements(this, (VCExprLet)that);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return HelperFuns.PolyHash(Body.GetHashCode(), 9, Bindings);
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ public IEnumerator<VCExprLetBinding/*!*/>/*!*/ GetEnumerator() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExprLetBinding>>()));
+ return Bindings.GetEnumerator();
+ }
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ return Bindings.GetEnumerator();
+ }
+
+ private static List<VCExprVar/*!*/>/*!*/ toSeq(List<VCExprLetBinding/*!*/>/*!*/ bindings) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar> res = new List<VCExprVar>();
+ foreach (VCExprLetBinding/*!*/ b in bindings)
+ res.Add(b.V);
+ return res;
+ }
+
+ internal VCExprLet(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr/*!*/ body)
+ : base(new List<TypeVariable/*!*/>(), toSeq(bindings), body) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Requires(body != null);
+ this.Bindings = bindings;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+}
diff --git a/Source/VCExpr/VCExprASTPrinter.cs b/Source/VCExpr/VCExprASTPrinter.cs
index 8e2f5d12..dac9604c 100644
--- a/Source/VCExpr/VCExprASTPrinter.cs
+++ b/Source/VCExpr/VCExprASTPrinter.cs
@@ -1,432 +1,432 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// A simple visitor for turning a VCExpr into a human-readable string
-// (S-expr syntax)
-
-namespace Microsoft.Boogie.VCExprAST {
-
- public class VCExprPrinter : IVCExprVisitor<bool, TextWriter/*!*/> {
- private VCExprOpPrinter OpPrinterVar = null;
- private VCExprOpPrinter/*!*/ OpPrinter {
- get {
- Contract.Ensures(Contract.Result<VCExprOpPrinter>() != null);
-
- if (OpPrinterVar == null)
- OpPrinterVar = new VCExprOpPrinter(this);
- return OpPrinterVar;
- }
- }
-
- public void Print(VCExpr expr, TextWriter wr) {
- Contract.Requires(wr != null);
- Contract.Requires(expr != null);
- expr.Accept<bool, TextWriter/*!*/>(this, wr);
- }
-
- public bool Visit(VCExprLiteral node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- if (node == VCExpressionGenerator.True) {
- wr.Write("true");
- } else if (node == VCExpressionGenerator.False) {
- wr.Write("false");
- } else if (node is VCExprIntLit) {
- wr.Write(((VCExprIntLit)node).Val);
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- return true;
- }
- public bool Visit(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- VCExprOp/*!*/ op = node.Op;
- Contract.Assert(op != null);
-
- if (op.Equals(VCExpressionGenerator.AndOp) ||
- op.Equals(VCExpressionGenerator.OrOp)) {
- // handle these operators without recursion
-
- wr.Write("({0}",
- op.Equals(VCExpressionGenerator.AndOp) ? "And" : "Or");
- IEnumerator/*!*/ enumerator = new VCExprNAryUniformOpEnumerator(node);
- Contract.Assert(enumerator != null);
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(op)) {
- wr.Write(" ");
- Print(cce.NonNull((VCExpr/*!*/)enumerator.Current), wr);
- }
- }
-
- wr.Write(")");
-
- return true;
- }
-
- return node.Accept<bool, TextWriter/*!*/>(OpPrinter, wr);
- }
- public bool Visit(VCExprVar node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- wr.Write(node.Name);
- return true;
- }
- public bool Visit(VCExprQuantifier node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- string/*!*/ quan = node.Quan == Quantifier.ALL ? "Forall" : "Exists";
- Contract.Assert(quan != null);
-
- wr.Write("({0} ", quan);
-
- if (node.TypeParameters.Count > 0) {
- wr.Write("<");
- string/*!*/ sep = "";
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- wr.Write(sep);
- sep = ", ";
- wr.Write("{0}", v.Name);
- }
- wr.Write("> ");
- }
-
- if (node.BoundVars.Count > 0) {
- string/*!*/ sep = "";
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- wr.Write(sep);
- sep = ", ";
- Print(v, wr);
- }
- wr.Write(" ");
- }
-
- wr.Write(":: ");
-
- if (node.Triggers.Count > 0) {
- wr.Write("{0} ", "{");
- string/*!*/ sep = "";
- foreach (VCTrigger/*!*/ t in node.Triggers) {
- Contract.Assert(t != null);
- wr.Write(sep);
- sep = ", ";
- string/*!*/ sep2 = "";
- foreach (VCExpr/*!*/ e in t.Exprs) {
- Contract.Assert(e != null);
- wr.Write(sep2);
- sep2 = "+";
- Print(e, wr);
- }
- }
- wr.Write(" {0} ", "}");
- }
-
- Print(node.Body, wr);
- wr.Write(")");
- return true;
- }
- public bool Visit(VCExprLet node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- wr.Write("(Let ");
-
- string/*!*/ sep = "";
- foreach (VCExprLetBinding/*!*/ b in node) {
- Contract.Assert(b != null);
- wr.Write(sep);
- sep = ", ";
- Print(b.V, wr);
- wr.Write(" = ");
- Print(b.E, wr);
- }
- wr.Write(" ");
-
- Print(node.Body, wr);
- wr.Write(")");
- return true;
- }
- }
-
- public class VCExprOpPrinter : IVCExprOpVisitor<bool, TextWriter/*!*/> {
- private VCExprPrinter/*!*/ ExprPrinter;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ExprPrinter != null);
- }
-
-
- public VCExprOpPrinter(VCExprPrinter exprPrinter) {
- Contract.Requires(exprPrinter != null);
- this.ExprPrinter = exprPrinter;
- }
-
- private bool PrintNAry(string op, VCExprNAry node, TextWriter wr) {
- Contract.Requires(wr != null);
- Contract.Requires(node != null);
- Contract.Requires(op != null);
- wr.Write("({0}", op);
- foreach (VCExpr/*!*/ arg in node) {
- Contract.Assert(arg != null);
- wr.Write(" ");
- ExprPrinter.Print(arg, wr);
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitNotOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("!", node, wr);
- }
- public bool VisitEqOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("==", node, wr);
- }
- public bool VisitNeqOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("!=", node, wr);
- }
- public bool VisitAndOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public bool VisitOrOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public bool VisitImpliesOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Implies", node, wr);
- }
- public bool VisitDistinctOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Distinct", node, wr);
- }
- public bool VisitLabelOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- VCExprLabelOp/*!*/ op = (VCExprLabelOp)node.Op;
- Contract.Assert(op != null);
- return PrintNAry("Label " + op.label, node, wr);
- }
- public bool VisitSelectOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Select", node, wr);
- }
- public bool VisitStoreOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Store", node, wr);
- }
- public bool VisitFloatAddOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.add", node, wr);
- }
- public bool VisitFloatSubOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.sub", node, wr);
- }
- public bool VisitFloatMulOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.mul", node, wr);
- }
- public bool VisitFloatDivOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.div", node, wr);
- }
- public bool VisitFloatRemOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.rem", node, wr);
- }
- public bool VisitFloatMinOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.min", node, wr);
- }
- public bool VisitFloatMaxOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.max", node, wr);
- }
- public bool VisitFloatLeqOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.leq", node, wr);
- }
- public bool VisitFloatLtOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.lt", node, wr);
- }
- public bool VisitFloatGeqOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.geq", node, wr);
- }
- public bool VisitFloatGtOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.gt", node, wr);
- }
- public bool VisitFloatEqOp(VCExprNAry node, TextWriter wr)
- {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("fp.eq", node, wr);
- }
- public bool VisitBvOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Bv", node, wr);
- }
- public bool VisitBvExtractOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("BvExtract", node, wr);
- }
- public bool VisitBvConcatOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("BvConcat", node, wr);
- }
- public bool VisitIfThenElseOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("if-then-else", node, wr);
- }
- public bool VisitCustomOp(VCExprNAry/*!*/ node, TextWriter/*!*/ wr) {
- //Contract.Requires(node!=null);
- //Contract.Requires(wr != null);
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- return PrintNAry(op.Name, node, wr);
- }
- public bool VisitAddOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- if (CommandLineOptions.Clo.ReflectAdd) {
- return PrintNAry("Reflect$Add", node, wr);
- } else {
- return PrintNAry("+", node, wr);
- }
- }
- public bool VisitSubOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("-", node, wr);
- }
- public bool VisitMulOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("*", node, wr);
- }
- public bool VisitDivOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("div", node, wr);
- }
- public bool VisitModOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("mod", node, wr);
- }
- public bool VisitRealDivOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("/", node, wr);
- }
- public bool VisitPowOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("**", node, wr);
- }
- public bool VisitLtOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<", node, wr);
- }
- public bool VisitLeOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<=", node, wr);
- }
- public bool VisitGtOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry(">", node, wr);
- }
- public bool VisitGeOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry(">=", node, wr);
- }
- public bool VisitSubtypeOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<:", node, wr);
- }
- public bool VisitSubtype3Op(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<::", node, wr);
- }
- public bool VisitToIntOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("int", node, wr);
- }
- public bool VisitToRealOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("real", node, wr);
- }
- public bool VisitBoogieFunctionOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- VCExprBoogieFunctionOp/*!*/ op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op != null);
- return PrintNAry(op.Func.Name, node, wr);
- }
- }
-
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// A simple visitor for turning a VCExpr into a human-readable string
+// (S-expr syntax)
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ public class VCExprPrinter : IVCExprVisitor<bool, TextWriter/*!*/> {
+ private VCExprOpPrinter OpPrinterVar = null;
+ private VCExprOpPrinter/*!*/ OpPrinter {
+ get {
+ Contract.Ensures(Contract.Result<VCExprOpPrinter>() != null);
+
+ if (OpPrinterVar == null)
+ OpPrinterVar = new VCExprOpPrinter(this);
+ return OpPrinterVar;
+ }
+ }
+
+ public void Print(VCExpr expr, TextWriter wr) {
+ Contract.Requires(wr != null);
+ Contract.Requires(expr != null);
+ expr.Accept<bool, TextWriter/*!*/>(this, wr);
+ }
+
+ public bool Visit(VCExprLiteral node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ if (node == VCExpressionGenerator.True) {
+ wr.Write("true");
+ } else if (node == VCExpressionGenerator.False) {
+ wr.Write("false");
+ } else if (node is VCExprIntLit) {
+ wr.Write(((VCExprIntLit)node).Val);
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ return true;
+ }
+ public bool Visit(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ VCExprOp/*!*/ op = node.Op;
+ Contract.Assert(op != null);
+
+ if (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp)) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? "And" : "Or");
+ IEnumerator/*!*/ enumerator = new VCExprNAryUniformOpEnumerator(node);
+ Contract.Assert(enumerator != null);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Print(cce.NonNull((VCExpr/*!*/)enumerator.Current), wr);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, TextWriter/*!*/>(OpPrinter, wr);
+ }
+ public bool Visit(VCExprVar node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ wr.Write(node.Name);
+ return true;
+ }
+ public bool Visit(VCExprQuantifier node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ string/*!*/ quan = node.Quan == Quantifier.ALL ? "Forall" : "Exists";
+ Contract.Assert(quan != null);
+
+ wr.Write("({0} ", quan);
+
+ if (node.TypeParameters.Count > 0) {
+ wr.Write("<");
+ string/*!*/ sep = "";
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ wr.Write(sep);
+ sep = ", ";
+ wr.Write("{0}", v.Name);
+ }
+ wr.Write("> ");
+ }
+
+ if (node.BoundVars.Count > 0) {
+ string/*!*/ sep = "";
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ wr.Write(sep);
+ sep = ", ";
+ Print(v, wr);
+ }
+ wr.Write(" ");
+ }
+
+ wr.Write(":: ");
+
+ if (node.Triggers.Count > 0) {
+ wr.Write("{0} ", "{");
+ string/*!*/ sep = "";
+ foreach (VCTrigger/*!*/ t in node.Triggers) {
+ Contract.Assert(t != null);
+ wr.Write(sep);
+ sep = ", ";
+ string/*!*/ sep2 = "";
+ foreach (VCExpr/*!*/ e in t.Exprs) {
+ Contract.Assert(e != null);
+ wr.Write(sep2);
+ sep2 = "+";
+ Print(e, wr);
+ }
+ }
+ wr.Write(" {0} ", "}");
+ }
+
+ Print(node.Body, wr);
+ wr.Write(")");
+ return true;
+ }
+ public bool Visit(VCExprLet node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ wr.Write("(Let ");
+
+ string/*!*/ sep = "";
+ foreach (VCExprLetBinding/*!*/ b in node) {
+ Contract.Assert(b != null);
+ wr.Write(sep);
+ sep = ", ";
+ Print(b.V, wr);
+ wr.Write(" = ");
+ Print(b.E, wr);
+ }
+ wr.Write(" ");
+
+ Print(node.Body, wr);
+ wr.Write(")");
+ return true;
+ }
+ }
+
+ public class VCExprOpPrinter : IVCExprOpVisitor<bool, TextWriter/*!*/> {
+ private VCExprPrinter/*!*/ ExprPrinter;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExprPrinter != null);
+ }
+
+
+ public VCExprOpPrinter(VCExprPrinter exprPrinter) {
+ Contract.Requires(exprPrinter != null);
+ this.ExprPrinter = exprPrinter;
+ }
+
+ private bool PrintNAry(string op, VCExprNAry node, TextWriter wr) {
+ Contract.Requires(wr != null);
+ Contract.Requires(node != null);
+ Contract.Requires(op != null);
+ wr.Write("({0}", op);
+ foreach (VCExpr/*!*/ arg in node) {
+ Contract.Assert(arg != null);
+ wr.Write(" ");
+ ExprPrinter.Print(arg, wr);
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitNotOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("!", node, wr);
+ }
+ public bool VisitEqOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("==", node, wr);
+ }
+ public bool VisitNeqOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("!=", node, wr);
+ }
+ public bool VisitAndOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public bool VisitOrOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public bool VisitImpliesOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Implies", node, wr);
+ }
+ public bool VisitDistinctOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Distinct", node, wr);
+ }
+ public bool VisitLabelOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ VCExprLabelOp/*!*/ op = (VCExprLabelOp)node.Op;
+ Contract.Assert(op != null);
+ return PrintNAry("Label " + op.label, node, wr);
+ }
+ public bool VisitSelectOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Select", node, wr);
+ }
+ public bool VisitStoreOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Store", node, wr);
+ }
+ public bool VisitFloatAddOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.add", node, wr);
+ }
+ public bool VisitFloatSubOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.sub", node, wr);
+ }
+ public bool VisitFloatMulOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.mul", node, wr);
+ }
+ public bool VisitFloatDivOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.div", node, wr);
+ }
+ public bool VisitFloatRemOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.rem", node, wr);
+ }
+ public bool VisitFloatMinOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.min", node, wr);
+ }
+ public bool VisitFloatMaxOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.max", node, wr);
+ }
+ public bool VisitFloatLeqOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.leq", node, wr);
+ }
+ public bool VisitFloatLtOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.lt", node, wr);
+ }
+ public bool VisitFloatGeqOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.geq", node, wr);
+ }
+ public bool VisitFloatGtOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.gt", node, wr);
+ }
+ public bool VisitFloatEqOp(VCExprNAry node, TextWriter wr)
+ {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("fp.eq", node, wr);
+ }
+ public bool VisitBvOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Bv", node, wr);
+ }
+ public bool VisitBvExtractOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("BvExtract", node, wr);
+ }
+ public bool VisitBvConcatOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("BvConcat", node, wr);
+ }
+ public bool VisitIfThenElseOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("if-then-else", node, wr);
+ }
+ public bool VisitCustomOp(VCExprNAry/*!*/ node, TextWriter/*!*/ wr) {
+ //Contract.Requires(node!=null);
+ //Contract.Requires(wr != null);
+ VCExprCustomOp op = (VCExprCustomOp)node.Op;
+ return PrintNAry(op.Name, node, wr);
+ }
+ public bool VisitAddOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ return PrintNAry("Reflect$Add", node, wr);
+ } else {
+ return PrintNAry("+", node, wr);
+ }
+ }
+ public bool VisitSubOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("-", node, wr);
+ }
+ public bool VisitMulOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("*", node, wr);
+ }
+ public bool VisitDivOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("div", node, wr);
+ }
+ public bool VisitModOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("mod", node, wr);
+ }
+ public bool VisitRealDivOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("/", node, wr);
+ }
+ public bool VisitPowOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("**", node, wr);
+ }
+ public bool VisitLtOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<", node, wr);
+ }
+ public bool VisitLeOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<=", node, wr);
+ }
+ public bool VisitGtOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry(">", node, wr);
+ }
+ public bool VisitGeOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry(">=", node, wr);
+ }
+ public bool VisitSubtypeOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<:", node, wr);
+ }
+ public bool VisitSubtype3Op(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<::", node, wr);
+ }
+ public bool VisitToIntOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("int", node, wr);
+ }
+ public bool VisitToRealOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("real", node, wr);
+ }
+ public bool VisitBoogieFunctionOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ VCExprBoogieFunctionOp/*!*/ op = (VCExprBoogieFunctionOp)node.Op;
+ Contract.Assert(op != null);
+ return PrintNAry(op.Func.Name, node, wr);
+ }
+ }
+
+
+}
diff --git a/Source/VCExpr/VCExprASTVisitors.cs b/Source/VCExpr/VCExprASTVisitors.cs
index c81f69e5..a23aaf8a 100644
--- a/Source/VCExpr/VCExprASTVisitors.cs
+++ b/Source/VCExpr/VCExprASTVisitors.cs
@@ -1,1681 +1,1681 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-using Microsoft.Basetypes;
-
-// Some visitor skeletons for the VCExpression AST
-
-namespace Microsoft.Boogie.VCExprAST {
- using Microsoft.Boogie;
-
- [ContractClass(typeof(IVCExprVisitorContracts<,>))]
- public interface IVCExprVisitor<Result, Arg> {
- Result Visit(VCExprLiteral/*!*/ node, Arg arg);
- Result Visit(VCExprNAry/*!*/ node, Arg arg);
- Result Visit(VCExprVar/*!*/ node, Arg arg);
- Result Visit(VCExprQuantifier/*!*/ node, Arg arg);
- Result Visit(VCExprLet/*!*/ node, Arg arg);
- }
- [ContractClassFor(typeof(IVCExprVisitor<,>))]
- public abstract class IVCExprVisitorContracts<Result, Arg> : IVCExprVisitor<Result, Arg> {
- #region IVCExprVisitor Members
-
- public Result Visit(VCExprLiteral node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprVar node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprQuantifier node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprLet node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- #endregion
- }
- [ContractClass(typeof(IVCExprOpVisitorContracts<,>))]
- public interface IVCExprOpVisitor<Result, Arg> {
- Result VisitNotOp(VCExprNAry node, Arg arg);
- Result VisitEqOp(VCExprNAry node, Arg arg);
- Result VisitNeqOp(VCExprNAry node, Arg arg);
- Result VisitAndOp(VCExprNAry node, Arg arg);
- Result VisitOrOp(VCExprNAry node, Arg arg);
- Result VisitImpliesOp(VCExprNAry node, Arg arg);
- Result VisitDistinctOp(VCExprNAry node, Arg arg);
- Result VisitLabelOp(VCExprNAry node, Arg arg);
- Result VisitSelectOp(VCExprNAry node, Arg arg);
- Result VisitStoreOp(VCExprNAry node, Arg arg);
- Result VisitFloatAddOp(VCExprNAry node, Arg arg);
- Result VisitFloatSubOp(VCExprNAry node, Arg arg);
- Result VisitFloatMulOp(VCExprNAry node, Arg arg);
- Result VisitFloatDivOp(VCExprNAry node, Arg arg);
- Result VisitFloatRemOp(VCExprNAry node, Arg arg);
- Result VisitFloatMinOp(VCExprNAry node, Arg arg);
- Result VisitFloatMaxOp(VCExprNAry node, Arg arg);
- Result VisitFloatLeqOp(VCExprNAry node, Arg arg);
- Result VisitFloatLtOp(VCExprNAry node, Arg arg);
- Result VisitFloatGeqOp(VCExprNAry node, Arg arg);
- Result VisitFloatGtOp(VCExprNAry node, Arg arg);
- Result VisitFloatEqOp(VCExprNAry node, Arg arg);
- Result VisitBvOp(VCExprNAry node, Arg arg);
- Result VisitBvExtractOp(VCExprNAry node, Arg arg);
- Result VisitBvConcatOp(VCExprNAry node, Arg arg);
- Result VisitAddOp(VCExprNAry node, Arg arg);
- Result VisitSubOp(VCExprNAry node, Arg arg);
- Result VisitMulOp(VCExprNAry node, Arg arg);
- Result VisitDivOp(VCExprNAry node, Arg arg);
- Result VisitModOp(VCExprNAry node, Arg arg);
- Result VisitRealDivOp(VCExprNAry node, Arg arg);
- Result VisitPowOp(VCExprNAry node, Arg arg);
- Result VisitLtOp(VCExprNAry node, Arg arg);
- Result VisitLeOp(VCExprNAry node, Arg arg);
- Result VisitGtOp(VCExprNAry node, Arg arg);
- Result VisitGeOp(VCExprNAry node, Arg arg);
- Result VisitSubtypeOp(VCExprNAry node, Arg arg);
- Result VisitSubtype3Op(VCExprNAry node, Arg arg);
- Result VisitToIntOp(VCExprNAry node, Arg arg);
- Result VisitToRealOp(VCExprNAry node, Arg arg);
- Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg);
- Result VisitIfThenElseOp(VCExprNAry node, Arg arg);
- Result VisitCustomOp(VCExprNAry node, Arg arg);
- }
- [ContractClassFor(typeof(IVCExprOpVisitor<,>))]
- public abstract class IVCExprOpVisitorContracts<Result, Arg> : IVCExprOpVisitor<Result, Arg> {
- #region IVCExprOpVisitor<Result,Arg> Members
-
- public Result VisitNotOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitEqOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitNeqOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitAndOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitOrOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitImpliesOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitDistinctOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitLabelOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSelectOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitStoreOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatAddOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatSubOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatMulOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatDivOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatRemOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatMinOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatMaxOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatLeqOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatLtOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatGeqOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatGtOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitFloatEqOp(VCExprNAry node, Arg arg)
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBvOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitAddOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSubOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitMulOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitDivOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitModOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitRealDivOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitPowOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitLtOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitLeOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitGtOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitGeOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitToIntOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitToRealOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitToFloat(VCExprNAry node, Arg arg) //TODO: modify later
- {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitCustomOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- #endregion
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Standard implementations that make it easier to create own visitors
-
- // Simple traversal of VCExprs. The Visit implementations work
- // recursively, apart from the implementation for VCExprNAry that
- // uses a stack when applied to nested nodes with the same
- // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
- // to avoid stack overflows
-
-
- [ContractClass(typeof(TraversingVCExprVisitorContracts<,>))]
- public abstract class TraversingVCExprVisitor<Result, Arg>
- : IVCExprVisitor<Result, Arg> {
- protected abstract Result StandardResult(VCExpr/*!*/ node, Arg arg);
-
- public Result Traverse(VCExpr node, Arg arg) {
- Contract.Requires(node != null);
- return node.Accept(this, arg);
- }
-
- public virtual Result Visit(VCExprLiteral node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
-
- public virtual Result Visit(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- Result res = StandardResult(node, arg);
-
-
- if (node.TypeParamArity == 0 &&
- (node.Op == VCExpressionGenerator.AndOp ||
- node.Op == VCExpressionGenerator.OrOp ||
- node.Op == VCExpressionGenerator.ImpliesOp)) {
- Contract.Assert(node.Op != null);
- VCExprOp op = node.Op;
- HashSet<VCExprOp> ops = new HashSet<VCExprOp>();
- ops.Add(VCExpressionGenerator.AndOp);
- ops.Add(VCExpressionGenerator.OrOp);
- ops.Add(VCExpressionGenerator.ImpliesOp);
- IEnumerator enumerator = new VCExprNAryMultiUniformOpEnumerator(node, ops);
- while (enumerator.MoveNext()) {
- VCExpr expr = cce.NonNull((VCExpr)enumerator.Current);
- VCExprNAry naryExpr = expr as VCExprNAry;
- if (naryExpr == null || !ops.Contains(naryExpr.Op)) {
- expr.Accept(this, arg);
- } else {
- StandardResult(expr, arg);
- }
- }
- } else {
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- e.Accept(this, arg);
- }
- }
-
- return res;
- }
-
- public virtual Result Visit(VCExprVar node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result Visit(VCExprQuantifier node, Arg arg) {
- //Contract.Requires(node != null);
- Result res = StandardResult(node, arg);
- foreach (VCTrigger/*!*/ trigger in node.Triggers) {
- Contract.Assert(trigger != null);
- foreach (VCExpr/*!*/ expr in trigger.Exprs) {
- Contract.Assert(expr != null);
- expr.Accept(this, arg);
- }
- }
- node.Body.Accept(this, arg);
- return res;
- }
- public virtual Result Visit(VCExprLet node, Arg arg) {
- //Contract.Requires(node != null);
- Result res = StandardResult(node, arg);
- // visit the bound expressions first
- foreach (VCExprLetBinding/*!*/ binding in node) {
- Contract.Assert(binding != null);
- binding.E.Accept(this, arg);
- }
- node.Body.Accept(this, arg);
- return res;
- }
- }
- [ContractClassFor(typeof(TraversingVCExprVisitor<,>))]
- public abstract class TraversingVCExprVisitorContracts<Result, Arg> : TraversingVCExprVisitor<Result, Arg> {
- protected override Result StandardResult(VCExpr node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- // Class to iterate over the nodes of a tree of VCExprNAry. This is
- // used to avoid handling such VCExpr recursively, which can easily
- // lead to stack overflows
-
- public class VCExprNAryEnumerator : IEnumerator {
-
- private readonly VCExprNAry/*!*/ CompleteExpr;
- private VCExpr CurrentExpr = null;
- private readonly Stack<VCExpr/*!*/>/*!*/ ExprTodo = new Stack<VCExpr/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(CompleteExpr != null);
- Contract.Invariant(cce.NonNullElements(ExprTodo));
- }
-
- public VCExprNAryEnumerator(VCExprNAry completeExpr) {
- Contract.Requires(completeExpr != null);
- this.CompleteExpr = completeExpr;
- Stack<VCExpr/*!*/>/*!*/ exprTodo = new Stack<VCExpr/*!*/>();
- exprTodo.Push(completeExpr);
- ExprTodo = exprTodo;
- }
-
- // Method using which a subclass can decide whether the
- // subexpressions of an expression should be enumerated as well
- // The default is to enumerate all nodes
- protected virtual bool Descend(VCExprNAry expr) {
- Contract.Requires(expr != null);
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public bool MoveNext() {
- if (ExprTodo.Count == 0)
- return false;
-
- CurrentExpr = ExprTodo.Pop();
- VCExprNAry currentNAry = CurrentExpr as VCExprNAry;
- if (currentNAry != null && Descend(currentNAry)) {
- for (int i = currentNAry.Arity - 1; i >= 0; --i)
- ExprTodo.Push(currentNAry[i]);
- }
-
- return true;
- }
-
- public object Current {
- get {
- return cce.NonNull(CurrentExpr);
- }
- }
-
- public void Reset() {
- ExprTodo.Clear();
- CurrentExpr = null;
- ExprTodo.Push(CompleteExpr);
- }
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class VCExprNAryUniformOpEnumerator : VCExprNAryEnumerator {
- private readonly VCExprOp/*!*/ Op;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- }
-
- public VCExprNAryUniformOpEnumerator(VCExprNAry completeExpr)
- : base(completeExpr) {
- Contract.Requires(completeExpr != null);
-
- this.Op = completeExpr.Op;
- }
- protected override bool Descend(VCExprNAry expr) {
- //Contract.Requires(expr != null);
- return expr.Op.Equals(Op) &&
- // we never skip nodes with type parameters
- // (those are too interesting ...)
- expr.TypeParamArity == 0;
- }
- }
-
- public class VCExprNAryMultiUniformOpEnumerator : VCExprNAryEnumerator
- {
- private readonly HashSet<VCExprOp> Ops;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Ops != null);
- }
-
- public VCExprNAryMultiUniformOpEnumerator(VCExprNAry completeExpr, HashSet<VCExprOp> ops)
- : base(completeExpr)
- {
- Contract.Requires(completeExpr != null);
-
- this.Ops = ops;
- }
- protected override bool Descend(VCExprNAry expr)
- {
- return Ops.Contains(expr.Op) && expr.TypeParamArity == 0;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Visitor that knows about the variables bound at each location in a VCExpr
-
- public abstract class BoundVarTraversingVCExprVisitor<Result, Arg>
- : TraversingVCExprVisitor<Result, Arg> {
- // Maps with all variables bound above a certain location in the VCExpression.
- // The value of the map tells how often a particular symbol was bound
- private readonly IDictionary<VCExprVar/*!*/, int>/*!*/ BoundTermVarsDict =
- new Dictionary<VCExprVar/*!*/, int>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(BoundTermVarsDict != null);
- Contract.Invariant(BoundTypeVarsDict != null);
- }
-
- private readonly IDictionary<TypeVariable/*!*/, int>/*!*/ BoundTypeVarsDict =
- new Dictionary<TypeVariable/*!*/, int>();
-
- protected ICollection<VCExprVar/*!*/>/*!*/ BoundTermVars {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<VCExprVar>>()));
- return BoundTermVarsDict.Keys;
- }
- }
- protected ICollection<TypeVariable/*!*/>/*!*/ BoundTypeVars {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<TypeVariable>>()));
- return BoundTypeVarsDict.Keys;
- }
- }
-
- private void AddBoundVar<T>(IDictionary<T, int> dict, T sym) {
- Contract.Requires(sym != null);
- Contract.Requires(dict != null);
- int n;
- if (dict.TryGetValue(sym, out n))
- dict[sym] = n + 1;
- else
- dict[sym] = 1;
- }
-
- private void RemoveBoundVar<T>(IDictionary<T/*!*/, int/*!*/>/*!*/ dict, T sym) {
- Contract.Requires(sym != null);
- Contract.Requires(dict != null);
- int n;
- bool b = dict.TryGetValue(sym, out n);
- Contract.Assert(b && n > 0);
- if (n == 1)
- dict.Remove(sym);
- else
- dict[sym] = n - 1;
- }
-
- public override Result Visit(VCExprQuantifier node, Arg arg) {
- Contract.Requires(node != null);
- // we temporarily add bound (term and type) variables to the
- // corresponding lists
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- AddBoundVar<TypeVariable>(BoundTypeVarsDict, v);
- }
-
- Result res;
- try {
- res = VisitAfterBinding(node, arg);
- } finally {
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- RemoveBoundVar<TypeVariable>(BoundTypeVarsDict, v);
- }
- }
- return res;
- }
- public override Result Visit(VCExprLet node, Arg arg) {
- Contract.Requires(node != null);
- // we temporarily add bound term variables to the
- // corresponding lists
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
-
- Result res;
- try {
- res = VisitAfterBinding(node, arg);
- } finally {
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
- }
- return res;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // The possibility is provided to look at a (quantifier or let) node
- // after its bound variables have been registered
- // (when overriding the normal visit-methods, the node will be visited
- // before the binding happens)
-
- protected virtual Result VisitAfterBinding(VCExprQuantifier node, Arg arg) {
- Contract.Requires(node != null);
- return base.Visit(node, arg);
- }
-
- protected virtual Result VisitAfterBinding(VCExprLet node, Arg arg) {
- Contract.Requires(node != null);
- return base.Visit(node, arg);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // General visitor for recursively collecting information in a VCExpr.
- // As the visitor is not used anywhere for the time being, it maybe should
- // be removed
-
- [ContractClass(typeof(CollectingVCExprVisitorContracts<,>))]
- public abstract class CollectingVCExprVisitor<Result, Arg>
- : IVCExprVisitor<Result, Arg> {
- protected abstract Result CombineResults(List<Result>/*!*/ results, Arg arg);
-
- public Result Collect(VCExpr node, Arg arg) {
- Contract.Requires(node != null);
- return node.Accept(this, arg);
- }
-
- public virtual Result Visit(VCExprLiteral node, Arg arg) {
- //Contract.Requires(node != null);
- return CombineResults(new List<Result>(), arg);
- }
- public virtual Result Visit(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- List<Result>/*!*/ results = new List<Result>();
- foreach (VCExpr/*!*/ subnode in node) {
- Contract.Assert(subnode != null);
- results.Add(subnode.Accept(this, arg));
- }
- return CombineResults(results, arg);
- }
- public virtual Result Visit(VCExprVar node, Arg arg) {
- //Contract.Requires(node != null);
- return CombineResults(new List<Result>(), arg);
- }
- public virtual Result Visit(VCExprQuantifier node, Arg arg) {
- //Contract.Requires(node != null);
- List<Result>/*!*/ result = new List<Result>();
- result.Add(node.Body.Accept(this, arg));
- foreach (VCTrigger/*!*/ trigger in node.Triggers) {
- Contract.Assert(trigger != null);
- foreach (VCExpr/*!*/ expr in trigger.Exprs) {
- Contract.Assert(expr != null);
- result.Add(expr.Accept(this, arg));
- }
- }
- return CombineResults(result, arg);
- }
- public virtual Result Visit(VCExprLet node, Arg arg) {
- //Contract.Requires(node != null);
- List<Result>/*!*/ results = new List<Result>();
- // visit the bound expressions first
- foreach (VCExprLetBinding/*!*/ binding in node) {
- Contract.Assert(binding != null);
- results.Add(binding.E.Accept(this, arg));
- }
- results.Add(node.Body.Accept(this, arg));
- return CombineResults(results, arg);
- }
- }
- [ContractClassFor(typeof(CollectingVCExprVisitor<,>))]
- public abstract class CollectingVCExprVisitorContracts<Result, Arg> : CollectingVCExprVisitor<Result, Arg> {
- protected override Result CombineResults(List<Result> results, Arg arg) {
- Contract.Requires(results != null);
- throw new NotImplementedException();
- }
- }
- ////////////////////////////////////////////////////////////////////////////
-
- public class SizeComputingVisitor : TraversingVCExprVisitor<bool, bool> {
-
- private int Size = 0;
-
- public static int ComputeSize(VCExpr expr) {
- Contract.Requires(expr != null);
- SizeComputingVisitor/*!*/ visitor = new SizeComputingVisitor();
- visitor.Traverse(expr, true);
- return visitor.Size;
- }
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- Size = Size + 1;
- return true;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Collect all free term and type variables in a VCExpr. Type variables
- // can occur free either in the types of bound variables, or in the type
- // parameters of VCExprNAry.
-
- // the result and argument (of type bool) are not used currently
- public class FreeVariableCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
- public readonly Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVars = new Dictionary<VCExprVar/*!*/, object>();
- public readonly List<TypeVariable/*!*/>/*!*/ FreeTypeVars = new List<TypeVariable/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FreeTermVars != null && Contract.ForAll(FreeTermVars, entry => entry.Key != null));
- Contract.Invariant(cce.NonNullElements(FreeTypeVars));
- }
-
-
- // not used
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true;
- }
-
- public static Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVariables(VCExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Dictionary<VCExprVar, object>>() != null);
- Contract.Ensures(Contract.ForAll(Contract.Result<Dictionary<VCExprVar, object>>(), ftv => ftv.Key != null));
- FreeVariableCollector collector = new FreeVariableCollector();
- collector.Traverse(node, true);
- return collector.FreeTermVars;
- }
-
- public static List<TypeVariable/*!*/>/*!*/ FreeTypeVariables(VCExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
- FreeVariableCollector collector = new FreeVariableCollector();
- collector.Traverse(node, true);
- return collector.FreeTypeVars;
- }
-
- public void Reset() {
- FreeTermVars.Clear();
- FreeTypeVars.Clear();
- }
-
- public void Collect(VCExpr node) {
- Contract.Requires(node != null);
- Traverse(node, true);
- }
-
- public void Collect(Type type) {
- Contract.Requires(type != null);
- AddTypeVariables(type.FreeVariables.ToList());
- }
-
- /////////////////////////////////////////////////////////////////////////
-
- private void CollectTypeVariables(IEnumerable<VCExprVar/*!*/>/*!*/ boundVars) {
- Contract.Requires(cce.NonNullElements(boundVars));
- foreach (VCExprVar/*!*/ var in boundVars) {
- Contract.Assert(var != null);
- Collect(var.Type);
- }
- }
-
- private void AddTypeVariables(IEnumerable<TypeVariable/*!*/>/*!*/ typeVars) {
- Contract.Requires(cce.NonNullElements(typeVars));
- foreach (TypeVariable/*!*/ tvar in typeVars) {
- Contract.Assert(tvar != null);
- if (!BoundTypeVars.Contains(tvar) && !FreeTypeVars.Contains(tvar))
- FreeTypeVars.Add(tvar);
- }
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node) && !FreeTermVars.ContainsKey(node)) {
- FreeTermVars.Add(node, null);
- Collect(node.Type);
- }
- return true;
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- foreach (Type/*!*/ t in node.TypeArguments) {
- Contract.Assert(t != null);
- Collect(t);
- }
- return base.Visit(node, arg);
- }
-
- protected override bool VisitAfterBinding(VCExprQuantifier node, bool arg) {
- //Contract.Requires(node != null);
- CollectTypeVariables(node.BoundVars);
- return base.VisitAfterBinding(node, arg);
- }
-
- protected override bool VisitAfterBinding(VCExprLet node, bool arg) {
- //Contract.Requires(node != null);
- CollectTypeVariables(node.BoundVars);
- return base.VisitAfterBinding(node, arg);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Framework for mutating VCExprs
-
- // The Visit implementations in the following visitor work
- // recursively, apart from the implementation for VCExprNAry that
- // uses its own stack when applied to nested nodes with the same
- // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
- // to avoid stack overflows (like in TraversingVCExprVisitor)
-
- public abstract class MutatingVCExprVisitor<Arg>
- : IVCExprVisitor<VCExpr/*!*/, Arg> {
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- }
-
-
- public MutatingVCExprVisitor(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- this.Gen = gen;
- }
-
- public VCExpr Mutate(VCExpr expr, Arg arg) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return expr.Accept(this, arg);
- }
-
- public List<VCExpr/*!*/>/*!*/ MutateSeq(IEnumerable<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- foreach (VCExpr/*!*/ expr in exprs) {
- Contract.Assert(expr != null);
- res.Add(expr.Accept(this, arg));
- }
- return res;
- }
-
- private List<VCExpr/*!*/>/*!*/ MutateList(List<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- bool changed = false;
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- foreach (VCExpr/*!*/ expr in exprs) {
- Contract.Assert(expr != null);
- VCExpr/*!*/ newExpr = expr.Accept(this, arg);
- if (!Object.ReferenceEquals(expr, newExpr))
- changed = true;
- res.Add(newExpr);
- }
- if (!changed)
- return exprs;
- return res;
- }
-
- public virtual VCExpr Visit(VCExprLiteral node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return node;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Special element used to mark the positions in the todo-stack where
- // results have to be popped from the result-stack.
- private static readonly VCExpr/*!*/ CombineResultsMarker = new VCExprLiteral(Type.Bool);
-
- // The todo-stack contains records of the shape
- //
- // arg0
- // arg1
- // arg2
- // ...
- // CombineResultsMarker
- // f(arg0, arg1, arg2, ...) (the original expression)
-
- private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprTodoStack = new Stack<VCExpr/*!*/>();
- private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprResultStack = new Stack<VCExpr/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarianta() {
- Contract.Invariant(cce.NonNullElements(NAryExprResultStack));
- Contract.Invariant(cce.NonNullElements(NAryExprTodoStack));
- }
-
-
- private void PushTodo(VCExprNAry exprTodo) {
- Contract.Requires(exprTodo != null);
- NAryExprTodoStack.Push(exprTodo);
- NAryExprTodoStack.Push(CombineResultsMarker);
- for (int i = exprTodo.Arity - 1; i >= 0; --i)
- NAryExprTodoStack.Push(exprTodo[i]);
- }
-
- public virtual bool AvoidVisit(VCExprNAry node, Arg arg)
- {
- return true;
- }
-
- public virtual VCExpr Visit(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- int initialStackSize = NAryExprTodoStack.Count;
- int initialResultStackSize = NAryExprResultStack.Count;
-
- PushTodo(node);
-
- while (NAryExprTodoStack.Count > initialStackSize) {
- VCExpr/*!*/ subExpr = NAryExprTodoStack.Pop();
- Contract.Assert(subExpr != null);
-
- if (Object.ReferenceEquals(subExpr, CombineResultsMarker)) {
- // assemble a result
- VCExprNAry/*!*/ originalExpr = (VCExprNAry)NAryExprTodoStack.Pop();
- Contract.Assert(originalExpr != null);
- VCExprOp/*!*/ op = originalExpr.Op;
- bool changed = false;
- List<VCExpr/*!*/>/*!*/ newSubExprs = new List<VCExpr/*!*/>();
-
- for (int i = op.Arity - 1; i >= 0; --i) {
- VCExpr/*!*/ nextSubExpr = NAryExprResultStack.Pop();
- Contract.Assert(nextSubExpr != null);
- if (!Object.ReferenceEquals(nextSubExpr, originalExpr[i]))
- changed = true;
- newSubExprs.Insert(0, nextSubExpr);
- }
-
- NAryExprResultStack.Push(UpdateModifiedNode(originalExpr, newSubExprs, changed, arg));
- //
- } else {
- //
- VCExprNAry narySubExpr = subExpr as VCExprNAry;
- if (narySubExpr != null && this.AvoidVisit(narySubExpr, arg) &&
- // as in VCExprNAryUniformOpEnumerator, all expressions with
- // type parameters are allowed to be inspected more closely
- narySubExpr.TypeParamArity == 0) {
- PushTodo(narySubExpr);
- } else {
- NAryExprResultStack.Push(subExpr.Accept(this, arg));
- }
- //
- }
- }
-
- Contract.Assert(NAryExprTodoStack.Count == initialStackSize && NAryExprResultStack.Count == initialResultStackSize + 1);
- return NAryExprResultStack.Pop();
- }
-
- protected virtual VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, // has any of the subexpressions changed?
- bool changed,
- Arg arg) {
- Contract.Requires(cce.NonNullElements(newSubExprs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (changed)
- return Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- return originalNode;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public virtual VCExpr Visit(VCExprVar node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return node;
- }
-
- protected List<VCTrigger/*!*/>/*!*/ MutateTriggers(List<VCTrigger/*!*/>/*!*/ triggers, Arg arg) {
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
- List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
- bool changed = false;
- foreach (VCTrigger/*!*/ trigger in triggers) {
- Contract.Assert(trigger != null);
- List<VCExpr/*!*/>/*!*/ exprs = trigger.Exprs;
- List<VCExpr/*!*/>/*!*/ newExprs = MutateList(exprs, arg);
-
- if (Object.ReferenceEquals(exprs, newExprs)) {
- newTriggers.Add(trigger);
- } else {
- newTriggers.Add(Gen.Trigger(trigger.Pos, newExprs));
- changed = true;
- }
- }
- if (!changed)
- return triggers;
- return newTriggers;
- }
-
- public virtual VCExpr Visit(VCExprQuantifier node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- bool changed = false;
-
- VCExpr/*!*/ body = node.Body;
- Contract.Assert(body != null);
- VCExpr/*!*/ newbody = body.Accept(this, arg);
- Contract.Assert(newbody != null);
- if (!Object.ReferenceEquals(body, newbody))
- changed = true;
-
- // visit the trigger expressions as well
- List<VCTrigger/*!*/>/*!*/ triggers = node.Triggers;
- Contract.Assert(cce.NonNullElements(triggers));
- List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(triggers, arg);
- Contract.Assert(cce.NonNullElements(newTriggers));
- if (!Object.ReferenceEquals(triggers, newTriggers))
- changed = true;
-
- if (!changed)
- return node;
- return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars,
- newTriggers, node.Infos, newbody);
- }
-
- public virtual VCExpr Visit(VCExprLet node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- bool changed = false;
-
- VCExpr/*!*/ body = node.Body;
- VCExpr/*!*/ newbody = body.Accept(this, arg);
- if (!Object.ReferenceEquals(body, newbody))
- changed = true;
-
- List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
- for (int i = 0; i < node.Length; ++i) {
- VCExprLetBinding/*!*/ binding = node[i];
- Contract.Assert(binding != null);
- VCExpr/*!*/ e = binding.E;
- VCExpr/*!*/ newE = e.Accept(this, arg);
- if (Object.ReferenceEquals(e, newE)) {
- newbindings.Add(binding);
- } else {
- changed = true;
- newbindings.Add(Gen.LetBinding(binding.V, newE));
- }
- }
-
- if (!changed)
- return node;
- return Gen.Let(newbindings, newbody);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Substitutions and a visitor for applying substitutions. A substitution can
- // substitute both type variables and term variables
-
- public class VCExprSubstitution {
- private readonly List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ TermSubsts;
- [ContractInvariantMethod]
- void TermSubstsInvariantMethod() {
- Contract.Invariant(TermSubsts != null && Contract.ForAll(TermSubsts, i => cce.NonNullDictionaryAndValues(i)));
- }
- private readonly List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ TypeSubsts;
- [ContractInvariantMethod]
- void TypeSubstsInvariantMethod() {
- Contract.Invariant(TermSubsts != null && Contract.ForAll(TypeSubsts, i => cce.NonNullDictionaryAndValues(i)));
- }
-
- public VCExprSubstitution(IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ termSubst, IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst) {
- Contract.Requires(cce.NonNullDictionaryAndValues(termSubst));
- Contract.Requires(cce.NonNullDictionaryAndValues(typeSubst));
- List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ termSubsts =
- new List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>();
- termSubsts.Add(termSubst);
- List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ typeSubsts =
- new List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>();
- typeSubsts.Add(typeSubst);
- this.TermSubsts = termSubsts;
- this.TypeSubsts = typeSubsts;
- }
-
- public VCExprSubstitution()
- : this(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>()) {
-
- }
-
- public void PushScope() {
- TermSubsts.Add(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>());
- TypeSubsts.Add(new Dictionary<TypeVariable/*!*/, Type/*!*/>());
- }
-
- public void PopScope() {
- TermSubsts.RemoveAt(TermSubsts.Count - 1);
- TypeSubsts.RemoveAt(TypeSubsts.Count - 1);
- }
-
- public VCExpr this[VCExprVar/*!*/ var] {
- get {
- Contract.Requires(var != null);
- VCExpr res;
- for (int i = TermSubsts.Count - 1; i >= 0; --i) {
- if (TermSubsts[i].TryGetValue(var, out res))
- return res;
- }
- return null;
- }
- set {
- TermSubsts[TermSubsts.Count - 1][var] = cce.NonNull(value);
- }
- }
-
- public Type this[TypeVariable/*!*/ var] {
- get {
- Contract.Requires(var != null);
- Type res;
- for (int i = TypeSubsts.Count - 1; i >= 0; --i) {
- if (TypeSubsts[i].TryGetValue(var, out res))
- return res;
- }
- return null;
- }
- set {
- TypeSubsts[TypeSubsts.Count - 1][var] = cce.NonNull(value);
- }
- }
-
- public bool ContainsKey(VCExprVar var) {
- Contract.Requires(var != null);
- return this[var] != null;
- }
-
- public bool ContainsKey(TypeVariable var) {
- Contract.Requires(var != null);
- return this[var] != null;
- }
-
- public bool TermSubstIsEmpty {
- get {
- return TermSubsts.All(dict => !dict.Any());
- }
- }
-
- public bool TypeSubstIsEmpty {
- get {
- return TypeSubsts.All(dict => !dict.Any());
- }
- }
-
- public IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ ToTypeSubst {
- get {
- Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ res = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
- foreach (KeyValuePair<TypeVariable/*!*/, Type/*!*/> pair in dict) {
- Contract.Assert(cce.NonNullElements(pair));
- // later ones overwrite earlier ones
- res[pair.Key] = pair.Value;
- }
- }
- return res;
- }
- }
-
- // the variables that are not mapped to themselves
- public IEnumerable<VCExprVar/*!*/>/*!*/ TermDomain {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<VCExprVar>>()));
- HashSet<VCExprVar/*!*/>/*!*/ domain = new HashSet<VCExprVar/*!*/>();
- foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts) {
- Contract.Assert(dict != null);
- foreach (VCExprVar/*!*/ var in dict.Keys) {
- Contract.Assert(var != null);
- if (!var.Equals(this[var]))
- domain.Add(var);
- }
- }
- return domain;
- }
- }
-
- // the variables that are not mapped to themselves
- public IEnumerable<TypeVariable/*!*/>/*!*/ TypeDomain {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<TypeVariable>>()));
- HashSet<TypeVariable/*!*/>/*!*/ domain = new HashSet<TypeVariable/*!*/>();
- foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
- Contract.Assert(dict != null);
- foreach (TypeVariable/*!*/ var in dict.Keys) {
- Contract.Assert(var != null);
- if (!var.Equals(this[var]))
- domain.Add(var);
- }
- }
- return domain;
- }
- }
-
- public FreeVariableCollector/*!*/ Codomains {
- get {
- Contract.Ensures(Contract.Result<FreeVariableCollector>() != null);
-
- FreeVariableCollector/*!*/ coll = new FreeVariableCollector();
- foreach (VCExprVar/*!*/ var in TermDomain)
- coll.Collect(cce.NonNull(this)[var]);
- foreach (TypeVariable/*!*/ var in TypeDomain)
- coll.Collect(cce.NonNull(this)[var]);
- return coll;
- }
- }
-
- public VCExprSubstitution Clone() {
- Contract.Ensures(Contract.Result<VCExprSubstitution>() != null);
- VCExprSubstitution/*!*/ res = new VCExprSubstitution();
- foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts)
- res.TermSubsts.Add(HelperFuns.Clone(dict));
- foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts)
- res.TypeSubsts.Add(HelperFuns.Clone(dict));
- return res;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
-
- public class SubstitutingVCExprVisitor
- : MutatingVCExprVisitor<VCExprSubstitution/*!*/> {
- public SubstitutingVCExprVisitor(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- }
-
- // when descending across a binder, we have to check that no collisions
- // or variable capture can occur. if this might happen, we replace the
- // term and type variables bound by the binder with fresh variables
- private bool CollisionPossible(IEnumerable<TypeVariable/*!*/>/*!*/ typeParams, IEnumerable<VCExprVar/*!*/>/*!*/ boundVars, VCExprSubstitution/*!*/ substitution) {
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(cce.NonNullElements(boundVars));
- Contract.Requires(substitution != null);
- // variables can be shadowed by a binder
- if (typeParams.Any(var => substitution.ContainsKey(var)) ||
- boundVars.Any(var => substitution.ContainsKey(var)))
- return true;
- // compute the codomain of the substitution
- FreeVariableCollector coll = substitution.Codomains;
- Contract.Assert(coll != null);
- // variables could be captured when applying the substitution
- return typeParams.Any(var => coll.FreeTypeVars.Contains(var)) ||
- boundVars.Any(var => coll.FreeTermVars.ContainsKey(var));
- }
-
- // can be overwritten if names of bound variables are to be changed
- protected virtual string ChooseNewVariableName(string oldName) {
- Contract.Requires(oldName != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return oldName;
- }
-
- // handle type parameters in VCExprNAry
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VCExprSubstitution/*!*/ substitution) {
- //Contract.Requires(originalNode != null);
- //Contract.Requires(cce.NonNullElements(newSubExprs));
- //Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<Type/*!*/>/*!*/ typeParams = new List<Type/*!*/>();
- foreach (Type/*!*/ t in originalNode.TypeArguments) {
- Contract.Assert(t != null);
- Type/*!*/ newType = t.Substitute(substitution.ToTypeSubst);
- Contract.Assert(newType != null);
- if (!ReferenceEquals(t, newType))
- changed = true;
- typeParams.Add(newType);
- }
- if (changed)
- return Gen.Function(originalNode.Op, newSubExprs, typeParams);
- else
- return originalNode;
- }
-
- public override VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution) {
- Contract.Requires(node != null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- // the default is to refresh bound variables only if necessary
- // because of collisions
- return Visit(node, substitution, false);
- }
-
- public VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution, bool refreshBoundVariables) {
- Contract.Requires(node != null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- substitution.PushScope();
- try {
-
- List<TypeVariable/*!*/>/*!*/ typeParams = node.TypeParameters;
- Contract.Assert(cce.NonNullElements(typeParams));
- bool refreshAllVariables = refreshBoundVariables ||
- CollisionPossible(node.TypeParameters, node.BoundVars, substitution);
- if (refreshAllVariables) {
- // we introduce fresh type variables to ensure that none gets captured
- typeParams = new List<TypeVariable/*!*/>();
- foreach (TypeVariable/*!*/ var in node.TypeParameters) {
- Contract.Assert(var != null);
- TypeVariable/*!*/ freshVar =
- new TypeVariable(Token.NoToken, ChooseNewVariableName(var.Name));
- Contract.Assert(freshVar != null);
- typeParams.Add(freshVar);
- substitution[var] = freshVar;
- // this might overwrite other elements of the substitution, deliberately
- }
- }
-
- List<VCExprVar/*!*/>/*!*/ boundVars = node.BoundVars;
- Contract.Assert(cce.NonNullElements(boundVars));
- if (refreshAllVariables || !substitution.TypeSubstIsEmpty) {
- // collisions are possible, or we also substitute type variables. in this case
- // the bound term variables have to be replaced with fresh variables with the
- // right types
- boundVars = new List<VCExprVar/*!*/>();
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
- Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ freshVar =
- Gen.Variable(ChooseNewVariableName(var.Name),
- var.Type.Substitute(typeSubst));
- Contract.Assert(freshVar != null);
- boundVars.Add(freshVar);
- substitution[var] = freshVar;
- // this might overwrite other elements of the substitution, deliberately
- }
- }
-
- List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
- foreach (VCTrigger/*!*/ trigger in node.Triggers) {
- Contract.Assert(trigger != null);
- newTriggers.Add(Gen.Trigger(trigger.Pos, MutateSeq(trigger.Exprs, substitution)));
- }
-
- VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
- Contract.Assert(newBody != null);
-
- return Gen.Quantify(node.Quan, typeParams, boundVars,
- newTriggers, node.Infos, newBody);
-
- } finally {
- substitution.PopScope();
- }
- }
-
- public override VCExpr Visit(VCExprVar node, VCExprSubstitution substitution) {
- Contract.Requires(substitution != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr res = substitution[node];
- if (res != null)
- return res;
- return node;
- }
-
- public override VCExpr Visit(VCExprLet node, VCExprSubstitution substitution) {
- Contract.Requires(substitution != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // the default is to refresh bound variables only if necessary
- // because of collisions
- return Visit(node, substitution, false);
- }
-
- public VCExpr Visit(VCExprLet node, VCExprSubstitution substitution, bool refreshBoundVariables) {
- Contract.Requires(substitution != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // let-expressions do not have type parameters (fortunately ...)
- substitution.PushScope();
- try {
-
- bool refreshAllVariables =
- refreshBoundVariables ||
- !substitution.TypeSubstIsEmpty ||
- CollisionPossible(new List<TypeVariable/*!*/>(), node.BoundVars, substitution);
-
- List<VCExprVar/*!*/>/*!*/ newBoundVars = node.BoundVars;
- Contract.Assert(cce.NonNullElements(newBoundVars));
- if (refreshAllVariables) {
- // collisions are possible, or we also substitute type variables. in this case
- // the bound term variables have to be replaced with fresh variables with the
- // right types
- newBoundVars = new List<VCExprVar/*!*/>();
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
- Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ freshVar =
- Gen.Variable(ChooseNewVariableName(var.Name),
- var.Type.Substitute(typeSubst));
- Contract.Assert(freshVar != null);
- newBoundVars.Add(freshVar);
- substitution[var] = freshVar;
- // this might overwrite other elements of the substitution, deliberately
- }
- }
-
- List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
- for (int i = 0; i < node.Length; ++i) {
- VCExprLetBinding/*!*/ binding = node[i];
- Contract.Assert(binding != null);
- newbindings.Add(Gen.LetBinding(newBoundVars[i], Mutate(binding.E, substitution)));
- }
-
- VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
- Contract.Assert(newBody != null);
- return Gen.Let(newbindings, newBody);
-
- } finally {
- substitution.PopScope();
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- [ContractClassFor(typeof(StandardVCExprOpVisitor<,>))]
- public abstract class StandardVCExprOpVisitorContracts<Result, Arg> : StandardVCExprOpVisitor<Result, Arg> {
- protected override Result StandardResult(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
- }
-
-
- [ContractClass(typeof(StandardVCExprOpVisitorContracts<,>))]
- public abstract class StandardVCExprOpVisitor<Result, Arg>
- : IVCExprOpVisitor<Result, Arg> {
- protected abstract Result StandardResult(VCExprNAry/*!*/ node, Arg arg);
-
- public virtual Result VisitNotOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitEqOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitNeqOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitAndOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitOrOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitImpliesOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitDistinctOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitLabelOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSelectOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitStoreOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatAddOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatSubOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatMulOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatDivOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatRemOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatMinOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatMaxOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatLeqOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatLtOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatGeqOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatGtOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitFloatEqOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBvOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitCustomOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitAddOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSubOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitMulOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitDivOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitModOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitRealDivOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitPowOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitLtOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitLeOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitGtOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitGeOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitToIntOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitToRealOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitToFloatOp(VCExprNAry node, Arg arg)
- {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using Microsoft.Basetypes;
+
+// Some visitor skeletons for the VCExpression AST
+
+namespace Microsoft.Boogie.VCExprAST {
+ using Microsoft.Boogie;
+
+ [ContractClass(typeof(IVCExprVisitorContracts<,>))]
+ public interface IVCExprVisitor<Result, Arg> {
+ Result Visit(VCExprLiteral/*!*/ node, Arg arg);
+ Result Visit(VCExprNAry/*!*/ node, Arg arg);
+ Result Visit(VCExprVar/*!*/ node, Arg arg);
+ Result Visit(VCExprQuantifier/*!*/ node, Arg arg);
+ Result Visit(VCExprLet/*!*/ node, Arg arg);
+ }
+ [ContractClassFor(typeof(IVCExprVisitor<,>))]
+ public abstract class IVCExprVisitorContracts<Result, Arg> : IVCExprVisitor<Result, Arg> {
+ #region IVCExprVisitor Members
+
+ public Result Visit(VCExprLiteral node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprVar node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprQuantifier node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprLet node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+ [ContractClass(typeof(IVCExprOpVisitorContracts<,>))]
+ public interface IVCExprOpVisitor<Result, Arg> {
+ Result VisitNotOp(VCExprNAry node, Arg arg);
+ Result VisitEqOp(VCExprNAry node, Arg arg);
+ Result VisitNeqOp(VCExprNAry node, Arg arg);
+ Result VisitAndOp(VCExprNAry node, Arg arg);
+ Result VisitOrOp(VCExprNAry node, Arg arg);
+ Result VisitImpliesOp(VCExprNAry node, Arg arg);
+ Result VisitDistinctOp(VCExprNAry node, Arg arg);
+ Result VisitLabelOp(VCExprNAry node, Arg arg);
+ Result VisitSelectOp(VCExprNAry node, Arg arg);
+ Result VisitStoreOp(VCExprNAry node, Arg arg);
+ Result VisitFloatAddOp(VCExprNAry node, Arg arg);
+ Result VisitFloatSubOp(VCExprNAry node, Arg arg);
+ Result VisitFloatMulOp(VCExprNAry node, Arg arg);
+ Result VisitFloatDivOp(VCExprNAry node, Arg arg);
+ Result VisitFloatRemOp(VCExprNAry node, Arg arg);
+ Result VisitFloatMinOp(VCExprNAry node, Arg arg);
+ Result VisitFloatMaxOp(VCExprNAry node, Arg arg);
+ Result VisitFloatLeqOp(VCExprNAry node, Arg arg);
+ Result VisitFloatLtOp(VCExprNAry node, Arg arg);
+ Result VisitFloatGeqOp(VCExprNAry node, Arg arg);
+ Result VisitFloatGtOp(VCExprNAry node, Arg arg);
+ Result VisitFloatEqOp(VCExprNAry node, Arg arg);
+ Result VisitBvOp(VCExprNAry node, Arg arg);
+ Result VisitBvExtractOp(VCExprNAry node, Arg arg);
+ Result VisitBvConcatOp(VCExprNAry node, Arg arg);
+ Result VisitAddOp(VCExprNAry node, Arg arg);
+ Result VisitSubOp(VCExprNAry node, Arg arg);
+ Result VisitMulOp(VCExprNAry node, Arg arg);
+ Result VisitDivOp(VCExprNAry node, Arg arg);
+ Result VisitModOp(VCExprNAry node, Arg arg);
+ Result VisitRealDivOp(VCExprNAry node, Arg arg);
+ Result VisitPowOp(VCExprNAry node, Arg arg);
+ Result VisitLtOp(VCExprNAry node, Arg arg);
+ Result VisitLeOp(VCExprNAry node, Arg arg);
+ Result VisitGtOp(VCExprNAry node, Arg arg);
+ Result VisitGeOp(VCExprNAry node, Arg arg);
+ Result VisitSubtypeOp(VCExprNAry node, Arg arg);
+ Result VisitSubtype3Op(VCExprNAry node, Arg arg);
+ Result VisitToIntOp(VCExprNAry node, Arg arg);
+ Result VisitToRealOp(VCExprNAry node, Arg arg);
+ Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg);
+ Result VisitIfThenElseOp(VCExprNAry node, Arg arg);
+ Result VisitCustomOp(VCExprNAry node, Arg arg);
+ }
+ [ContractClassFor(typeof(IVCExprOpVisitor<,>))]
+ public abstract class IVCExprOpVisitorContracts<Result, Arg> : IVCExprOpVisitor<Result, Arg> {
+ #region IVCExprOpVisitor<Result,Arg> Members
+
+ public Result VisitNotOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitEqOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitNeqOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitAndOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitOrOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitImpliesOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitDistinctOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitLabelOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSelectOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitStoreOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatAddOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatSubOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatMulOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatDivOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatRemOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatMinOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatMaxOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatLeqOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatLtOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatGeqOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatGtOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitFloatEqOp(VCExprNAry node, Arg arg)
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBvOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitAddOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSubOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitMulOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitDivOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitModOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitRealDivOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitPowOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitLtOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitLeOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitGtOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitGeOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitToIntOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitToRealOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitToFloat(VCExprNAry node, Arg arg) //TODO: modify later
+ {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitCustomOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Standard implementations that make it easier to create own visitors
+
+ // Simple traversal of VCExprs. The Visit implementations work
+ // recursively, apart from the implementation for VCExprNAry that
+ // uses a stack when applied to nested nodes with the same
+ // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
+ // to avoid stack overflows
+
+
+ [ContractClass(typeof(TraversingVCExprVisitorContracts<,>))]
+ public abstract class TraversingVCExprVisitor<Result, Arg>
+ : IVCExprVisitor<Result, Arg> {
+ protected abstract Result StandardResult(VCExpr/*!*/ node, Arg arg);
+
+ public Result Traverse(VCExpr node, Arg arg) {
+ Contract.Requires(node != null);
+ return node.Accept(this, arg);
+ }
+
+ public virtual Result Visit(VCExprLiteral node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+
+ public virtual Result Visit(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ Result res = StandardResult(node, arg);
+
+
+ if (node.TypeParamArity == 0 &&
+ (node.Op == VCExpressionGenerator.AndOp ||
+ node.Op == VCExpressionGenerator.OrOp ||
+ node.Op == VCExpressionGenerator.ImpliesOp)) {
+ Contract.Assert(node.Op != null);
+ VCExprOp op = node.Op;
+ HashSet<VCExprOp> ops = new HashSet<VCExprOp>();
+ ops.Add(VCExpressionGenerator.AndOp);
+ ops.Add(VCExpressionGenerator.OrOp);
+ ops.Add(VCExpressionGenerator.ImpliesOp);
+ IEnumerator enumerator = new VCExprNAryMultiUniformOpEnumerator(node, ops);
+ while (enumerator.MoveNext()) {
+ VCExpr expr = cce.NonNull((VCExpr)enumerator.Current);
+ VCExprNAry naryExpr = expr as VCExprNAry;
+ if (naryExpr == null || !ops.Contains(naryExpr.Op)) {
+ expr.Accept(this, arg);
+ } else {
+ StandardResult(expr, arg);
+ }
+ }
+ } else {
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ e.Accept(this, arg);
+ }
+ }
+
+ return res;
+ }
+
+ public virtual Result Visit(VCExprVar node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result Visit(VCExprQuantifier node, Arg arg) {
+ //Contract.Requires(node != null);
+ Result res = StandardResult(node, arg);
+ foreach (VCTrigger/*!*/ trigger in node.Triggers) {
+ Contract.Assert(trigger != null);
+ foreach (VCExpr/*!*/ expr in trigger.Exprs) {
+ Contract.Assert(expr != null);
+ expr.Accept(this, arg);
+ }
+ }
+ node.Body.Accept(this, arg);
+ return res;
+ }
+ public virtual Result Visit(VCExprLet node, Arg arg) {
+ //Contract.Requires(node != null);
+ Result res = StandardResult(node, arg);
+ // visit the bound expressions first
+ foreach (VCExprLetBinding/*!*/ binding in node) {
+ Contract.Assert(binding != null);
+ binding.E.Accept(this, arg);
+ }
+ node.Body.Accept(this, arg);
+ return res;
+ }
+ }
+ [ContractClassFor(typeof(TraversingVCExprVisitor<,>))]
+ public abstract class TraversingVCExprVisitorContracts<Result, Arg> : TraversingVCExprVisitor<Result, Arg> {
+ protected override Result StandardResult(VCExpr node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+ }
+ //////////////////////////////////////////////////////////////////////////////
+ // Class to iterate over the nodes of a tree of VCExprNAry. This is
+ // used to avoid handling such VCExpr recursively, which can easily
+ // lead to stack overflows
+
+ public class VCExprNAryEnumerator : IEnumerator {
+
+ private readonly VCExprNAry/*!*/ CompleteExpr;
+ private VCExpr CurrentExpr = null;
+ private readonly Stack<VCExpr/*!*/>/*!*/ ExprTodo = new Stack<VCExpr/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(CompleteExpr != null);
+ Contract.Invariant(cce.NonNullElements(ExprTodo));
+ }
+
+ public VCExprNAryEnumerator(VCExprNAry completeExpr) {
+ Contract.Requires(completeExpr != null);
+ this.CompleteExpr = completeExpr;
+ Stack<VCExpr/*!*/>/*!*/ exprTodo = new Stack<VCExpr/*!*/>();
+ exprTodo.Push(completeExpr);
+ ExprTodo = exprTodo;
+ }
+
+ // Method using which a subclass can decide whether the
+ // subexpressions of an expression should be enumerated as well
+ // The default is to enumerate all nodes
+ protected virtual bool Descend(VCExprNAry expr) {
+ Contract.Requires(expr != null);
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public bool MoveNext() {
+ if (ExprTodo.Count == 0)
+ return false;
+
+ CurrentExpr = ExprTodo.Pop();
+ VCExprNAry currentNAry = CurrentExpr as VCExprNAry;
+ if (currentNAry != null && Descend(currentNAry)) {
+ for (int i = currentNAry.Arity - 1; i >= 0; --i)
+ ExprTodo.Push(currentNAry[i]);
+ }
+
+ return true;
+ }
+
+ public object Current {
+ get {
+ return cce.NonNull(CurrentExpr);
+ }
+ }
+
+ public void Reset() {
+ ExprTodo.Clear();
+ CurrentExpr = null;
+ ExprTodo.Push(CompleteExpr);
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class VCExprNAryUniformOpEnumerator : VCExprNAryEnumerator {
+ private readonly VCExprOp/*!*/ Op;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ }
+
+ public VCExprNAryUniformOpEnumerator(VCExprNAry completeExpr)
+ : base(completeExpr) {
+ Contract.Requires(completeExpr != null);
+
+ this.Op = completeExpr.Op;
+ }
+ protected override bool Descend(VCExprNAry expr) {
+ //Contract.Requires(expr != null);
+ return expr.Op.Equals(Op) &&
+ // we never skip nodes with type parameters
+ // (those are too interesting ...)
+ expr.TypeParamArity == 0;
+ }
+ }
+
+ public class VCExprNAryMultiUniformOpEnumerator : VCExprNAryEnumerator
+ {
+ private readonly HashSet<VCExprOp> Ops;
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(Ops != null);
+ }
+
+ public VCExprNAryMultiUniformOpEnumerator(VCExprNAry completeExpr, HashSet<VCExprOp> ops)
+ : base(completeExpr)
+ {
+ Contract.Requires(completeExpr != null);
+
+ this.Ops = ops;
+ }
+ protected override bool Descend(VCExprNAry expr)
+ {
+ return Ops.Contains(expr.Op) && expr.TypeParamArity == 0;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Visitor that knows about the variables bound at each location in a VCExpr
+
+ public abstract class BoundVarTraversingVCExprVisitor<Result, Arg>
+ : TraversingVCExprVisitor<Result, Arg> {
+ // Maps with all variables bound above a certain location in the VCExpression.
+ // The value of the map tells how often a particular symbol was bound
+ private readonly IDictionary<VCExprVar/*!*/, int>/*!*/ BoundTermVarsDict =
+ new Dictionary<VCExprVar/*!*/, int>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(BoundTermVarsDict != null);
+ Contract.Invariant(BoundTypeVarsDict != null);
+ }
+
+ private readonly IDictionary<TypeVariable/*!*/, int>/*!*/ BoundTypeVarsDict =
+ new Dictionary<TypeVariable/*!*/, int>();
+
+ protected ICollection<VCExprVar/*!*/>/*!*/ BoundTermVars {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<VCExprVar>>()));
+ return BoundTermVarsDict.Keys;
+ }
+ }
+ protected ICollection<TypeVariable/*!*/>/*!*/ BoundTypeVars {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<TypeVariable>>()));
+ return BoundTypeVarsDict.Keys;
+ }
+ }
+
+ private void AddBoundVar<T>(IDictionary<T, int> dict, T sym) {
+ Contract.Requires(sym != null);
+ Contract.Requires(dict != null);
+ int n;
+ if (dict.TryGetValue(sym, out n))
+ dict[sym] = n + 1;
+ else
+ dict[sym] = 1;
+ }
+
+ private void RemoveBoundVar<T>(IDictionary<T/*!*/, int/*!*/>/*!*/ dict, T sym) {
+ Contract.Requires(sym != null);
+ Contract.Requires(dict != null);
+ int n;
+ bool b = dict.TryGetValue(sym, out n);
+ Contract.Assert(b && n > 0);
+ if (n == 1)
+ dict.Remove(sym);
+ else
+ dict[sym] = n - 1;
+ }
+
+ public override Result Visit(VCExprQuantifier node, Arg arg) {
+ Contract.Requires(node != null);
+ // we temporarily add bound (term and type) variables to the
+ // corresponding lists
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ AddBoundVar<TypeVariable>(BoundTypeVarsDict, v);
+ }
+
+ Result res;
+ try {
+ res = VisitAfterBinding(node, arg);
+ } finally {
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ RemoveBoundVar<TypeVariable>(BoundTypeVarsDict, v);
+ }
+ }
+ return res;
+ }
+ public override Result Visit(VCExprLet node, Arg arg) {
+ Contract.Requires(node != null);
+ // we temporarily add bound term variables to the
+ // corresponding lists
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+
+ Result res;
+ try {
+ res = VisitAfterBinding(node, arg);
+ } finally {
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ }
+ return res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // The possibility is provided to look at a (quantifier or let) node
+ // after its bound variables have been registered
+ // (when overriding the normal visit-methods, the node will be visited
+ // before the binding happens)
+
+ protected virtual Result VisitAfterBinding(VCExprQuantifier node, Arg arg) {
+ Contract.Requires(node != null);
+ return base.Visit(node, arg);
+ }
+
+ protected virtual Result VisitAfterBinding(VCExprLet node, Arg arg) {
+ Contract.Requires(node != null);
+ return base.Visit(node, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // General visitor for recursively collecting information in a VCExpr.
+ // As the visitor is not used anywhere for the time being, it maybe should
+ // be removed
+
+ [ContractClass(typeof(CollectingVCExprVisitorContracts<,>))]
+ public abstract class CollectingVCExprVisitor<Result, Arg>
+ : IVCExprVisitor<Result, Arg> {
+ protected abstract Result CombineResults(List<Result>/*!*/ results, Arg arg);
+
+ public Result Collect(VCExpr node, Arg arg) {
+ Contract.Requires(node != null);
+ return node.Accept(this, arg);
+ }
+
+ public virtual Result Visit(VCExprLiteral node, Arg arg) {
+ //Contract.Requires(node != null);
+ return CombineResults(new List<Result>(), arg);
+ }
+ public virtual Result Visit(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ List<Result>/*!*/ results = new List<Result>();
+ foreach (VCExpr/*!*/ subnode in node) {
+ Contract.Assert(subnode != null);
+ results.Add(subnode.Accept(this, arg));
+ }
+ return CombineResults(results, arg);
+ }
+ public virtual Result Visit(VCExprVar node, Arg arg) {
+ //Contract.Requires(node != null);
+ return CombineResults(new List<Result>(), arg);
+ }
+ public virtual Result Visit(VCExprQuantifier node, Arg arg) {
+ //Contract.Requires(node != null);
+ List<Result>/*!*/ result = new List<Result>();
+ result.Add(node.Body.Accept(this, arg));
+ foreach (VCTrigger/*!*/ trigger in node.Triggers) {
+ Contract.Assert(trigger != null);
+ foreach (VCExpr/*!*/ expr in trigger.Exprs) {
+ Contract.Assert(expr != null);
+ result.Add(expr.Accept(this, arg));
+ }
+ }
+ return CombineResults(result, arg);
+ }
+ public virtual Result Visit(VCExprLet node, Arg arg) {
+ //Contract.Requires(node != null);
+ List<Result>/*!*/ results = new List<Result>();
+ // visit the bound expressions first
+ foreach (VCExprLetBinding/*!*/ binding in node) {
+ Contract.Assert(binding != null);
+ results.Add(binding.E.Accept(this, arg));
+ }
+ results.Add(node.Body.Accept(this, arg));
+ return CombineResults(results, arg);
+ }
+ }
+ [ContractClassFor(typeof(CollectingVCExprVisitor<,>))]
+ public abstract class CollectingVCExprVisitorContracts<Result, Arg> : CollectingVCExprVisitor<Result, Arg> {
+ protected override Result CombineResults(List<Result> results, Arg arg) {
+ Contract.Requires(results != null);
+ throw new NotImplementedException();
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+
+ public class SizeComputingVisitor : TraversingVCExprVisitor<bool, bool> {
+
+ private int Size = 0;
+
+ public static int ComputeSize(VCExpr expr) {
+ Contract.Requires(expr != null);
+ SizeComputingVisitor/*!*/ visitor = new SizeComputingVisitor();
+ visitor.Traverse(expr, true);
+ return visitor.Size;
+ }
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ Size = Size + 1;
+ return true;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Collect all free term and type variables in a VCExpr. Type variables
+ // can occur free either in the types of bound variables, or in the type
+ // parameters of VCExprNAry.
+
+ // the result and argument (of type bool) are not used currently
+ public class FreeVariableCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+ public readonly Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVars = new Dictionary<VCExprVar/*!*/, object>();
+ public readonly List<TypeVariable/*!*/>/*!*/ FreeTypeVars = new List<TypeVariable/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FreeTermVars != null && Contract.ForAll(FreeTermVars, entry => entry.Key != null));
+ Contract.Invariant(cce.NonNullElements(FreeTypeVars));
+ }
+
+
+ // not used
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return true;
+ }
+
+ public static Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVariables(VCExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Dictionary<VCExprVar, object>>() != null);
+ Contract.Ensures(Contract.ForAll(Contract.Result<Dictionary<VCExprVar, object>>(), ftv => ftv.Key != null));
+ FreeVariableCollector collector = new FreeVariableCollector();
+ collector.Traverse(node, true);
+ return collector.FreeTermVars;
+ }
+
+ public static List<TypeVariable/*!*/>/*!*/ FreeTypeVariables(VCExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
+ FreeVariableCollector collector = new FreeVariableCollector();
+ collector.Traverse(node, true);
+ return collector.FreeTypeVars;
+ }
+
+ public void Reset() {
+ FreeTermVars.Clear();
+ FreeTypeVars.Clear();
+ }
+
+ public void Collect(VCExpr node) {
+ Contract.Requires(node != null);
+ Traverse(node, true);
+ }
+
+ public void Collect(Type type) {
+ Contract.Requires(type != null);
+ AddTypeVariables(type.FreeVariables.ToList());
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ private void CollectTypeVariables(IEnumerable<VCExprVar/*!*/>/*!*/ boundVars) {
+ Contract.Requires(cce.NonNullElements(boundVars));
+ foreach (VCExprVar/*!*/ var in boundVars) {
+ Contract.Assert(var != null);
+ Collect(var.Type);
+ }
+ }
+
+ private void AddTypeVariables(IEnumerable<TypeVariable/*!*/>/*!*/ typeVars) {
+ Contract.Requires(cce.NonNullElements(typeVars));
+ foreach (TypeVariable/*!*/ tvar in typeVars) {
+ Contract.Assert(tvar != null);
+ if (!BoundTypeVars.Contains(tvar) && !FreeTypeVars.Contains(tvar))
+ FreeTypeVars.Add(tvar);
+ }
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!BoundTermVars.Contains(node) && !FreeTermVars.ContainsKey(node)) {
+ FreeTermVars.Add(node, null);
+ Collect(node.Type);
+ }
+ return true;
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+ foreach (Type/*!*/ t in node.TypeArguments) {
+ Contract.Assert(t != null);
+ Collect(t);
+ }
+ return base.Visit(node, arg);
+ }
+
+ protected override bool VisitAfterBinding(VCExprQuantifier node, bool arg) {
+ //Contract.Requires(node != null);
+ CollectTypeVariables(node.BoundVars);
+ return base.VisitAfterBinding(node, arg);
+ }
+
+ protected override bool VisitAfterBinding(VCExprLet node, bool arg) {
+ //Contract.Requires(node != null);
+ CollectTypeVariables(node.BoundVars);
+ return base.VisitAfterBinding(node, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Framework for mutating VCExprs
+
+ // The Visit implementations in the following visitor work
+ // recursively, apart from the implementation for VCExprNAry that
+ // uses its own stack when applied to nested nodes with the same
+ // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
+ // to avoid stack overflows (like in TraversingVCExprVisitor)
+
+ public abstract class MutatingVCExprVisitor<Arg>
+ : IVCExprVisitor<VCExpr/*!*/, Arg> {
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ }
+
+
+ public MutatingVCExprVisitor(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ this.Gen = gen;
+ }
+
+ public VCExpr Mutate(VCExpr expr, Arg arg) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return expr.Accept(this, arg);
+ }
+
+ public List<VCExpr/*!*/>/*!*/ MutateSeq(IEnumerable<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ foreach (VCExpr/*!*/ expr in exprs) {
+ Contract.Assert(expr != null);
+ res.Add(expr.Accept(this, arg));
+ }
+ return res;
+ }
+
+ private List<VCExpr/*!*/>/*!*/ MutateList(List<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ bool changed = false;
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ foreach (VCExpr/*!*/ expr in exprs) {
+ Contract.Assert(expr != null);
+ VCExpr/*!*/ newExpr = expr.Accept(this, arg);
+ if (!Object.ReferenceEquals(expr, newExpr))
+ changed = true;
+ res.Add(newExpr);
+ }
+ if (!changed)
+ return exprs;
+ return res;
+ }
+
+ public virtual VCExpr Visit(VCExprLiteral node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return node;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Special element used to mark the positions in the todo-stack where
+ // results have to be popped from the result-stack.
+ private static readonly VCExpr/*!*/ CombineResultsMarker = new VCExprLiteral(Type.Bool);
+
+ // The todo-stack contains records of the shape
+ //
+ // arg0
+ // arg1
+ // arg2
+ // ...
+ // CombineResultsMarker
+ // f(arg0, arg1, arg2, ...) (the original expression)
+
+ private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprTodoStack = new Stack<VCExpr/*!*/>();
+ private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprResultStack = new Stack<VCExpr/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarianta() {
+ Contract.Invariant(cce.NonNullElements(NAryExprResultStack));
+ Contract.Invariant(cce.NonNullElements(NAryExprTodoStack));
+ }
+
+
+ private void PushTodo(VCExprNAry exprTodo) {
+ Contract.Requires(exprTodo != null);
+ NAryExprTodoStack.Push(exprTodo);
+ NAryExprTodoStack.Push(CombineResultsMarker);
+ for (int i = exprTodo.Arity - 1; i >= 0; --i)
+ NAryExprTodoStack.Push(exprTodo[i]);
+ }
+
+ public virtual bool AvoidVisit(VCExprNAry node, Arg arg)
+ {
+ return true;
+ }
+
+ public virtual VCExpr Visit(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ int initialStackSize = NAryExprTodoStack.Count;
+ int initialResultStackSize = NAryExprResultStack.Count;
+
+ PushTodo(node);
+
+ while (NAryExprTodoStack.Count > initialStackSize) {
+ VCExpr/*!*/ subExpr = NAryExprTodoStack.Pop();
+ Contract.Assert(subExpr != null);
+
+ if (Object.ReferenceEquals(subExpr, CombineResultsMarker)) {
+ // assemble a result
+ VCExprNAry/*!*/ originalExpr = (VCExprNAry)NAryExprTodoStack.Pop();
+ Contract.Assert(originalExpr != null);
+ VCExprOp/*!*/ op = originalExpr.Op;
+ bool changed = false;
+ List<VCExpr/*!*/>/*!*/ newSubExprs = new List<VCExpr/*!*/>();
+
+ for (int i = op.Arity - 1; i >= 0; --i) {
+ VCExpr/*!*/ nextSubExpr = NAryExprResultStack.Pop();
+ Contract.Assert(nextSubExpr != null);
+ if (!Object.ReferenceEquals(nextSubExpr, originalExpr[i]))
+ changed = true;
+ newSubExprs.Insert(0, nextSubExpr);
+ }
+
+ NAryExprResultStack.Push(UpdateModifiedNode(originalExpr, newSubExprs, changed, arg));
+ //
+ } else {
+ //
+ VCExprNAry narySubExpr = subExpr as VCExprNAry;
+ if (narySubExpr != null && this.AvoidVisit(narySubExpr, arg) &&
+ // as in VCExprNAryUniformOpEnumerator, all expressions with
+ // type parameters are allowed to be inspected more closely
+ narySubExpr.TypeParamArity == 0) {
+ PushTodo(narySubExpr);
+ } else {
+ NAryExprResultStack.Push(subExpr.Accept(this, arg));
+ }
+ //
+ }
+ }
+
+ Contract.Assert(NAryExprTodoStack.Count == initialStackSize && NAryExprResultStack.Count == initialResultStackSize + 1);
+ return NAryExprResultStack.Pop();
+ }
+
+ protected virtual VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, // has any of the subexpressions changed?
+ bool changed,
+ Arg arg) {
+ Contract.Requires(cce.NonNullElements(newSubExprs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (changed)
+ return Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ return originalNode;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public virtual VCExpr Visit(VCExprVar node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return node;
+ }
+
+ protected List<VCTrigger/*!*/>/*!*/ MutateTriggers(List<VCTrigger/*!*/>/*!*/ triggers, Arg arg) {
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
+ List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
+ bool changed = false;
+ foreach (VCTrigger/*!*/ trigger in triggers) {
+ Contract.Assert(trigger != null);
+ List<VCExpr/*!*/>/*!*/ exprs = trigger.Exprs;
+ List<VCExpr/*!*/>/*!*/ newExprs = MutateList(exprs, arg);
+
+ if (Object.ReferenceEquals(exprs, newExprs)) {
+ newTriggers.Add(trigger);
+ } else {
+ newTriggers.Add(Gen.Trigger(trigger.Pos, newExprs));
+ changed = true;
+ }
+ }
+ if (!changed)
+ return triggers;
+ return newTriggers;
+ }
+
+ public virtual VCExpr Visit(VCExprQuantifier node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ bool changed = false;
+
+ VCExpr/*!*/ body = node.Body;
+ Contract.Assert(body != null);
+ VCExpr/*!*/ newbody = body.Accept(this, arg);
+ Contract.Assert(newbody != null);
+ if (!Object.ReferenceEquals(body, newbody))
+ changed = true;
+
+ // visit the trigger expressions as well
+ List<VCTrigger/*!*/>/*!*/ triggers = node.Triggers;
+ Contract.Assert(cce.NonNullElements(triggers));
+ List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(triggers, arg);
+ Contract.Assert(cce.NonNullElements(newTriggers));
+ if (!Object.ReferenceEquals(triggers, newTriggers))
+ changed = true;
+
+ if (!changed)
+ return node;
+ return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars,
+ newTriggers, node.Infos, newbody);
+ }
+
+ public virtual VCExpr Visit(VCExprLet node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ bool changed = false;
+
+ VCExpr/*!*/ body = node.Body;
+ VCExpr/*!*/ newbody = body.Accept(this, arg);
+ if (!Object.ReferenceEquals(body, newbody))
+ changed = true;
+
+ List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding/*!*/ binding = node[i];
+ Contract.Assert(binding != null);
+ VCExpr/*!*/ e = binding.E;
+ VCExpr/*!*/ newE = e.Accept(this, arg);
+ if (Object.ReferenceEquals(e, newE)) {
+ newbindings.Add(binding);
+ } else {
+ changed = true;
+ newbindings.Add(Gen.LetBinding(binding.V, newE));
+ }
+ }
+
+ if (!changed)
+ return node;
+ return Gen.Let(newbindings, newbody);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Substitutions and a visitor for applying substitutions. A substitution can
+ // substitute both type variables and term variables
+
+ public class VCExprSubstitution {
+ private readonly List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ TermSubsts;
+ [ContractInvariantMethod]
+ void TermSubstsInvariantMethod() {
+ Contract.Invariant(TermSubsts != null && Contract.ForAll(TermSubsts, i => cce.NonNullDictionaryAndValues(i)));
+ }
+ private readonly List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ TypeSubsts;
+ [ContractInvariantMethod]
+ void TypeSubstsInvariantMethod() {
+ Contract.Invariant(TermSubsts != null && Contract.ForAll(TypeSubsts, i => cce.NonNullDictionaryAndValues(i)));
+ }
+
+ public VCExprSubstitution(IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ termSubst, IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(termSubst));
+ Contract.Requires(cce.NonNullDictionaryAndValues(typeSubst));
+ List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ termSubsts =
+ new List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>();
+ termSubsts.Add(termSubst);
+ List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ typeSubsts =
+ new List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>();
+ typeSubsts.Add(typeSubst);
+ this.TermSubsts = termSubsts;
+ this.TypeSubsts = typeSubsts;
+ }
+
+ public VCExprSubstitution()
+ : this(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>()) {
+
+ }
+
+ public void PushScope() {
+ TermSubsts.Add(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>());
+ TypeSubsts.Add(new Dictionary<TypeVariable/*!*/, Type/*!*/>());
+ }
+
+ public void PopScope() {
+ TermSubsts.RemoveAt(TermSubsts.Count - 1);
+ TypeSubsts.RemoveAt(TypeSubsts.Count - 1);
+ }
+
+ public VCExpr this[VCExprVar/*!*/ var] {
+ get {
+ Contract.Requires(var != null);
+ VCExpr res;
+ for (int i = TermSubsts.Count - 1; i >= 0; --i) {
+ if (TermSubsts[i].TryGetValue(var, out res))
+ return res;
+ }
+ return null;
+ }
+ set {
+ TermSubsts[TermSubsts.Count - 1][var] = cce.NonNull(value);
+ }
+ }
+
+ public Type this[TypeVariable/*!*/ var] {
+ get {
+ Contract.Requires(var != null);
+ Type res;
+ for (int i = TypeSubsts.Count - 1; i >= 0; --i) {
+ if (TypeSubsts[i].TryGetValue(var, out res))
+ return res;
+ }
+ return null;
+ }
+ set {
+ TypeSubsts[TypeSubsts.Count - 1][var] = cce.NonNull(value);
+ }
+ }
+
+ public bool ContainsKey(VCExprVar var) {
+ Contract.Requires(var != null);
+ return this[var] != null;
+ }
+
+ public bool ContainsKey(TypeVariable var) {
+ Contract.Requires(var != null);
+ return this[var] != null;
+ }
+
+ public bool TermSubstIsEmpty {
+ get {
+ return TermSubsts.All(dict => !dict.Any());
+ }
+ }
+
+ public bool TypeSubstIsEmpty {
+ get {
+ return TypeSubsts.All(dict => !dict.Any());
+ }
+ }
+
+ public IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ ToTypeSubst {
+ get {
+ Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ res = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
+ foreach (KeyValuePair<TypeVariable/*!*/, Type/*!*/> pair in dict) {
+ Contract.Assert(cce.NonNullElements(pair));
+ // later ones overwrite earlier ones
+ res[pair.Key] = pair.Value;
+ }
+ }
+ return res;
+ }
+ }
+
+ // the variables that are not mapped to themselves
+ public IEnumerable<VCExprVar/*!*/>/*!*/ TermDomain {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<VCExprVar>>()));
+ HashSet<VCExprVar/*!*/>/*!*/ domain = new HashSet<VCExprVar/*!*/>();
+ foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts) {
+ Contract.Assert(dict != null);
+ foreach (VCExprVar/*!*/ var in dict.Keys) {
+ Contract.Assert(var != null);
+ if (!var.Equals(this[var]))
+ domain.Add(var);
+ }
+ }
+ return domain;
+ }
+ }
+
+ // the variables that are not mapped to themselves
+ public IEnumerable<TypeVariable/*!*/>/*!*/ TypeDomain {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<TypeVariable>>()));
+ HashSet<TypeVariable/*!*/>/*!*/ domain = new HashSet<TypeVariable/*!*/>();
+ foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
+ Contract.Assert(dict != null);
+ foreach (TypeVariable/*!*/ var in dict.Keys) {
+ Contract.Assert(var != null);
+ if (!var.Equals(this[var]))
+ domain.Add(var);
+ }
+ }
+ return domain;
+ }
+ }
+
+ public FreeVariableCollector/*!*/ Codomains {
+ get {
+ Contract.Ensures(Contract.Result<FreeVariableCollector>() != null);
+
+ FreeVariableCollector/*!*/ coll = new FreeVariableCollector();
+ foreach (VCExprVar/*!*/ var in TermDomain)
+ coll.Collect(cce.NonNull(this)[var]);
+ foreach (TypeVariable/*!*/ var in TypeDomain)
+ coll.Collect(cce.NonNull(this)[var]);
+ return coll;
+ }
+ }
+
+ public VCExprSubstitution Clone() {
+ Contract.Ensures(Contract.Result<VCExprSubstitution>() != null);
+ VCExprSubstitution/*!*/ res = new VCExprSubstitution();
+ foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts)
+ res.TermSubsts.Add(HelperFuns.Clone(dict));
+ foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts)
+ res.TypeSubsts.Add(HelperFuns.Clone(dict));
+ return res;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ public class SubstitutingVCExprVisitor
+ : MutatingVCExprVisitor<VCExprSubstitution/*!*/> {
+ public SubstitutingVCExprVisitor(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ }
+
+ // when descending across a binder, we have to check that no collisions
+ // or variable capture can occur. if this might happen, we replace the
+ // term and type variables bound by the binder with fresh variables
+ private bool CollisionPossible(IEnumerable<TypeVariable/*!*/>/*!*/ typeParams, IEnumerable<VCExprVar/*!*/>/*!*/ boundVars, VCExprSubstitution/*!*/ substitution) {
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(cce.NonNullElements(boundVars));
+ Contract.Requires(substitution != null);
+ // variables can be shadowed by a binder
+ if (typeParams.Any(var => substitution.ContainsKey(var)) ||
+ boundVars.Any(var => substitution.ContainsKey(var)))
+ return true;
+ // compute the codomain of the substitution
+ FreeVariableCollector coll = substitution.Codomains;
+ Contract.Assert(coll != null);
+ // variables could be captured when applying the substitution
+ return typeParams.Any(var => coll.FreeTypeVars.Contains(var)) ||
+ boundVars.Any(var => coll.FreeTermVars.ContainsKey(var));
+ }
+
+ // can be overwritten if names of bound variables are to be changed
+ protected virtual string ChooseNewVariableName(string oldName) {
+ Contract.Requires(oldName != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return oldName;
+ }
+
+ // handle type parameters in VCExprNAry
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VCExprSubstitution/*!*/ substitution) {
+ //Contract.Requires(originalNode != null);
+ //Contract.Requires(cce.NonNullElements(newSubExprs));
+ //Contract.Requires(substitution != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<Type/*!*/>/*!*/ typeParams = new List<Type/*!*/>();
+ foreach (Type/*!*/ t in originalNode.TypeArguments) {
+ Contract.Assert(t != null);
+ Type/*!*/ newType = t.Substitute(substitution.ToTypeSubst);
+ Contract.Assert(newType != null);
+ if (!ReferenceEquals(t, newType))
+ changed = true;
+ typeParams.Add(newType);
+ }
+ if (changed)
+ return Gen.Function(originalNode.Op, newSubExprs, typeParams);
+ else
+ return originalNode;
+ }
+
+ public override VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution) {
+ Contract.Requires(node != null);
+ Contract.Requires(substitution != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ // the default is to refresh bound variables only if necessary
+ // because of collisions
+ return Visit(node, substitution, false);
+ }
+
+ public VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution, bool refreshBoundVariables) {
+ Contract.Requires(node != null);
+ Contract.Requires(substitution != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ substitution.PushScope();
+ try {
+
+ List<TypeVariable/*!*/>/*!*/ typeParams = node.TypeParameters;
+ Contract.Assert(cce.NonNullElements(typeParams));
+ bool refreshAllVariables = refreshBoundVariables ||
+ CollisionPossible(node.TypeParameters, node.BoundVars, substitution);
+ if (refreshAllVariables) {
+ // we introduce fresh type variables to ensure that none gets captured
+ typeParams = new List<TypeVariable/*!*/>();
+ foreach (TypeVariable/*!*/ var in node.TypeParameters) {
+ Contract.Assert(var != null);
+ TypeVariable/*!*/ freshVar =
+ new TypeVariable(Token.NoToken, ChooseNewVariableName(var.Name));
+ Contract.Assert(freshVar != null);
+ typeParams.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCExprVar/*!*/>/*!*/ boundVars = node.BoundVars;
+ Contract.Assert(cce.NonNullElements(boundVars));
+ if (refreshAllVariables || !substitution.TypeSubstIsEmpty) {
+ // collisions are possible, or we also substitute type variables. in this case
+ // the bound term variables have to be replaced with fresh variables with the
+ // right types
+ boundVars = new List<VCExprVar/*!*/>();
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
+ Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ freshVar =
+ Gen.Variable(ChooseNewVariableName(var.Name),
+ var.Type.Substitute(typeSubst));
+ Contract.Assert(freshVar != null);
+ boundVars.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
+ foreach (VCTrigger/*!*/ trigger in node.Triggers) {
+ Contract.Assert(trigger != null);
+ newTriggers.Add(Gen.Trigger(trigger.Pos, MutateSeq(trigger.Exprs, substitution)));
+ }
+
+ VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
+ Contract.Assert(newBody != null);
+
+ return Gen.Quantify(node.Quan, typeParams, boundVars,
+ newTriggers, node.Infos, newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+
+ public override VCExpr Visit(VCExprVar node, VCExprSubstitution substitution) {
+ Contract.Requires(substitution != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr res = substitution[node];
+ if (res != null)
+ return res;
+ return node;
+ }
+
+ public override VCExpr Visit(VCExprLet node, VCExprSubstitution substitution) {
+ Contract.Requires(substitution != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // the default is to refresh bound variables only if necessary
+ // because of collisions
+ return Visit(node, substitution, false);
+ }
+
+ public VCExpr Visit(VCExprLet node, VCExprSubstitution substitution, bool refreshBoundVariables) {
+ Contract.Requires(substitution != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // let-expressions do not have type parameters (fortunately ...)
+ substitution.PushScope();
+ try {
+
+ bool refreshAllVariables =
+ refreshBoundVariables ||
+ !substitution.TypeSubstIsEmpty ||
+ CollisionPossible(new List<TypeVariable/*!*/>(), node.BoundVars, substitution);
+
+ List<VCExprVar/*!*/>/*!*/ newBoundVars = node.BoundVars;
+ Contract.Assert(cce.NonNullElements(newBoundVars));
+ if (refreshAllVariables) {
+ // collisions are possible, or we also substitute type variables. in this case
+ // the bound term variables have to be replaced with fresh variables with the
+ // right types
+ newBoundVars = new List<VCExprVar/*!*/>();
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
+ Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ freshVar =
+ Gen.Variable(ChooseNewVariableName(var.Name),
+ var.Type.Substitute(typeSubst));
+ Contract.Assert(freshVar != null);
+ newBoundVars.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding/*!*/ binding = node[i];
+ Contract.Assert(binding != null);
+ newbindings.Add(Gen.LetBinding(newBoundVars[i], Mutate(binding.E, substitution)));
+ }
+
+ VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
+ Contract.Assert(newBody != null);
+ return Gen.Let(newbindings, newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ [ContractClassFor(typeof(StandardVCExprOpVisitor<,>))]
+ public abstract class StandardVCExprOpVisitorContracts<Result, Arg> : StandardVCExprOpVisitor<Result, Arg> {
+ protected override Result StandardResult(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+ }
+
+
+ [ContractClass(typeof(StandardVCExprOpVisitorContracts<,>))]
+ public abstract class StandardVCExprOpVisitor<Result, Arg>
+ : IVCExprOpVisitor<Result, Arg> {
+ protected abstract Result StandardResult(VCExprNAry/*!*/ node, Arg arg);
+
+ public virtual Result VisitNotOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitEqOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitNeqOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitAndOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitOrOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitImpliesOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitDistinctOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLabelOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSelectOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitStoreOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatAddOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatSubOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatMulOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatDivOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatRemOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatMinOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatMaxOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatLeqOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatLtOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatGeqOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatGtOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitFloatEqOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitCustomOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitAddOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitMulOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitDivOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitModOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitRealDivOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitPowOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLtOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLeOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitGtOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitGeOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitToIntOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitToRealOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitToFloatOp(VCExprNAry node, Arg arg)
+ {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ }
+
} \ No newline at end of file
diff --git a/Source/VCExpr/cce.cs b/Source/VCExpr/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/VCExpr/cce.cs
+++ b/Source/VCExpr/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file
diff --git a/Source/VCGeneration/Check.cs b/Source/VCGeneration/Check.cs
index da8624e9..7bda0022 100644
--- a/Source/VCGeneration/Check.cs
+++ b/Source/VCGeneration/Check.cs
@@ -1,687 +1,694 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Basetypes;
-using System.Threading.Tasks;
-
-namespace Microsoft.Boogie {
-
- enum CheckerStatus
- {
- Idle,
- Ready,
- Busy,
- Closed
- }
-
- /// <summary>
- /// Interface to the theorem prover specialized to Boogie.
- ///
- /// This class creates the appropriate background axioms. There
- /// should be one instance per BoogiePL program.
- /// </summary>
- public sealed class Checker {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(gen != null);
- Contract.Invariant(thmProver != null);
- }
-
- private readonly VCExpressionGenerator gen;
-
- private ProverInterface thmProver;
- private int timeout;
-
- // state for the async interface
- private volatile ProverInterface.Outcome outcome;
- private volatile bool hasOutput;
- private volatile UnexpectedProverOutputException outputExn;
- private DateTime proverStart;
- private TimeSpan proverRunTime;
- private volatile ProverInterface.ErrorHandler handler;
- private volatile CheckerStatus status;
- public volatile Program Program;
-
- public void GetReady()
- {
- Contract.Requires(IsIdle);
-
- status = CheckerStatus.Ready;
- }
-
- public void GoBackToIdle()
- {
- Contract.Requires(IsBusy);
-
- status = CheckerStatus.Idle;
- }
-
- public Task ProverTask { get; set; }
-
- public bool WillingToHandle(int timeout, Program prog) {
- return status == CheckerStatus.Idle && timeout == this.timeout && (prog == null || Program == prog);
- }
-
- public VCExpressionGenerator VCExprGen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
- return this.gen;
- }
- }
- public ProverInterface TheoremProver {
- get {
- Contract.Ensures(Contract.Result<ProverInterface>() != null);
- return this.thmProver;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // We share context information for the same program between different Checkers
-
- private struct ContextCacheKey {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(program != null);
- }
-
- public readonly Program program;
-
- public ContextCacheKey(Program prog) {
- Contract.Requires(prog != null);
- this.program = prog;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (that is ContextCacheKey) {
- ContextCacheKey thatKey = (ContextCacheKey)that;
- return this.program.Equals(thatKey.program);
- }
- return false;
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.program.GetHashCode();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// Constructor. Initialize a checker with the program and log file.
- /// Optionally, use prover context provided by parameter "ctx".
- /// </summary>
- public Checker(VC.ConditionGeneration vcgen, Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, ProverContext ctx = null) {
- Contract.Requires(vcgen != null);
- Contract.Requires(prog != null);
- this.timeout = timeout;
- this.Program = prog;
-
- ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
-
- if (logFilePath != null) {
- options.LogFilename = logFilePath;
- if (appendLogFile)
- options.AppendLogFile = appendLogFile;
- }
-
- if (timeout > 0) {
- options.TimeLimit = timeout * 1000;
- }
-
- options.Parse(CommandLineOptions.Clo.ProverOptions);
-
- ContextCacheKey key = new ContextCacheKey(prog);
- ProverInterface prover;
-
- if (vcgen.CheckerCommonState == null) {
- vcgen.CheckerCommonState = new Dictionary<ContextCacheKey, ProverContext>();
- }
- IDictionary<ContextCacheKey, ProverContext>/*!>!*/ cachedContexts = (IDictionary<ContextCacheKey, ProverContext/*!*/>)vcgen.CheckerCommonState;
-
- if (ctx == null && cachedContexts.TryGetValue(key, out ctx))
- {
- ctx = (ProverContext)cce.NonNull(ctx).Clone();
- prover = (ProverInterface)
- CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
- } else {
- if (ctx == null) ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
-
- Setup(prog, ctx);
-
- // we first generate the prover and then store a clone of the
- // context in the cache, so that the prover can setup stuff in
- // the context to be cached
- prover = (ProverInterface)
- CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
- cachedContexts.Add(key, cce.NonNull((ProverContext)ctx.Clone()));
- }
-
- this.thmProver = prover;
- this.gen = prover.VCExprGen;
- }
-
- public void Retarget(Program prog, ProverContext ctx, int timeout = 0)
- {
- lock (this)
- {
- hasOutput = default(bool);
- outcome = default(ProverInterface.Outcome);
- outputExn = default(UnexpectedProverOutputException);
- handler = default(ProverInterface.ErrorHandler);
- TheoremProver.FullReset(gen);
- ctx.Reset();
- Setup(prog, ctx);
- this.timeout = timeout;
- SetTimeout();
- }
- }
-
- public void RetargetWithoutReset(Program prog, ProverContext ctx)
- {
- ctx.Clear();
- Setup(prog, ctx);
- }
-
-
- public void SetTimeout()
- {
- if (0 < timeout)
- {
- TheoremProver.SetTimeOut(timeout * 1000);
- }
- else
- {
- TheoremProver.SetTimeOut(0);
- }
- }
-
- /// <summary>
- /// Set up the context.
- /// </summary>
- private void Setup(Program prog, ProverContext ctx)
- {
- Program = prog;
- lock (Program.TopLevelDeclarations)
- {
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- Contract.Assert(decl != null);
- var typeDecl = decl as TypeCtorDecl;
- var constDecl = decl as Constant;
- var funDecl = decl as Function;
- var axiomDecl = decl as Axiom;
- var glVarDecl = decl as GlobalVariable;
- if (typeDecl != null)
- {
- ctx.DeclareType(typeDecl, null);
- }
- else if (constDecl != null)
- {
- ctx.DeclareConstant(constDecl, constDecl.Unique, null);
- }
- else if (funDecl != null)
- {
- ctx.DeclareFunction(funDecl, null);
- }
- else if (axiomDecl != null)
- {
- ctx.AddAxiom(axiomDecl, null);
- }
- else if (glVarDecl != null)
- {
- ctx.DeclareGlobalVariable(glVarDecl, null);
- }
- }
- }
- }
-
- /// <summary>
- /// Clean-up.
- /// </summary>
- public void Close() {
- thmProver.Close();
- status = CheckerStatus.Closed;
- }
-
- /// <summary>
- /// Push a Verification Condition as an Axiom
- /// (Required for Doomed Program Point detection)
- /// </summary>
- public void PushVCExpr(VCExpr vc) {
- Contract.Requires(vc != null);
- //thmProver.Context.AddAxiom(vc);
- thmProver.PushVCExpression(vc);
- }
-
- public bool IsBusy {
- get {
- return status == CheckerStatus.Busy;
- }
- }
-
- public bool IsReady
- {
- get
- {
- return status == CheckerStatus.Ready;
- }
- }
-
- public bool IsClosed {
- get {
- return status == CheckerStatus.Closed;
- }
- }
-
- public bool IsIdle
- {
- get
- {
- return status == CheckerStatus.Idle;
- }
- }
-
- public bool HasOutput {
- get {
- return hasOutput;
- }
- }
-
- public TimeSpan ProverRunTime {
- get {
- return proverRunTime;
- }
- }
-
- private void WaitForOutput(object dummy) {
- lock (this)
- {
- try
- {
- outcome = thmProver.CheckOutcome(cce.NonNull(handler));
- }
- catch (UnexpectedProverOutputException e)
- {
- outputExn = e;
- }
-
- switch (outcome)
- {
- case ProverInterface.Outcome.Valid:
- thmProver.LogComment("Valid");
- break;
- case ProverInterface.Outcome.Invalid:
- thmProver.LogComment("Invalid");
- break;
- case ProverInterface.Outcome.TimeOut:
- thmProver.LogComment("Timed out");
- break;
- case ProverInterface.Outcome.OutOfMemory:
- thmProver.LogComment("Out of memory");
- break;
- case ProverInterface.Outcome.Undetermined:
- thmProver.LogComment("Undetermined");
- break;
- }
-
- hasOutput = true;
- proverRunTime = DateTime.UtcNow - proverStart;
- }
- }
-
- public void BeginCheck(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler) {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(vc != null);
- Contract.Requires(handler != null);
- Contract.Requires(IsReady);
-
- status = CheckerStatus.Busy;
- hasOutput = false;
- outputExn = null;
- this.handler = handler;
-
- thmProver.Reset(gen);
- SetTimeout();
- proverStart = DateTime.UtcNow;
- thmProver.BeginCheck(descriptiveName, vc, handler);
- // gen.ClearSharedFormulas(); PR: don't know yet what to do with this guy
-
- ProverTask = Task.Factory.StartNew(() => { WaitForOutput(null); } , TaskCreationOptions.LongRunning);
- }
-
- public ProverInterface.Outcome ReadOutcome() {
- Contract.Requires(IsBusy);
- Contract.Requires(HasOutput);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- hasOutput = false;
-
- if (outputExn != null) {
- throw outputExn;
- }
-
- return outcome;
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public abstract class ProverInterface {
- public static ProverInterface CreateProver(Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, int taskID = -1) {
- Contract.Requires(prog != null);
-
- ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
-
- if (logFilePath != null) {
- options.LogFilename = logFilePath;
- if (appendLogFile)
- options.AppendLogFile = appendLogFile;
- }
-
- if (timeout > 0) {
- options.TimeLimit = timeout * 1000;
- }
-
- if (taskID >= 0) {
- options.Parse(CommandLineOptions.Clo.Cho[taskID].ProverOptions);
- } else {
- options.Parse(CommandLineOptions.Clo.ProverOptions);
- }
-
- ProverContext ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
-
- // set up the context
- foreach (Declaration decl in prog.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- TypeCtorDecl t = decl as TypeCtorDecl;
- if (t != null) {
- ctx.DeclareType(t, null);
- }
- }
- foreach (Declaration decl in prog.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- Constant c = decl as Constant;
- if (c != null) {
- ctx.DeclareConstant(c, c.Unique, null);
- }
- else {
- Function f = decl as Function;
- if (f != null) {
- ctx.DeclareFunction(f, null);
- }
- }
- }
- foreach (var ax in prog.Axioms) {
- ctx.AddAxiom(ax, null);
- }
- foreach (Declaration decl in prog.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- GlobalVariable v = decl as GlobalVariable;
- if (v != null) {
- ctx.DeclareGlobalVariable(v, null);
- }
- }
-
- return (ProverInterface)CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
- }
-
- public enum Outcome {
- Valid,
- Invalid,
- TimeOut,
- OutOfMemory,
- Undetermined
- }
- public class ErrorHandler {
- // Used in CheckOutcomeCore
- public virtual int StartingProcId()
- {
- return 0;
- }
-
- public virtual void OnModel(IList<string> labels, Model model, Outcome proverOutcome) {
- Contract.Requires(cce.NonNullElements(labels));
- }
-
- public virtual void OnResourceExceeded(string message) {
- Contract.Requires(message != null);
- }
-
- public virtual void OnProverWarning(string message)
- {
- Contract.Requires(message != null);
- switch (CommandLineOptions.Clo.PrintProverWarnings) {
- case CommandLineOptions.ProverWarnings.None:
- break;
- case CommandLineOptions.ProverWarnings.Stdout:
- Console.WriteLine("Prover warning: " + message);
- break;
- case CommandLineOptions.ProverWarnings.Stderr:
- Console.Error.WriteLine("Prover warning: " + message);
- break;
- default:
- Contract.Assume(false);
- throw new cce.UnreachableException(); // unexpected case
- }
- }
-
- public virtual Absy Label2Absy(string label) {
- Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- throw new System.NotImplementedException();
- }
- }
- public abstract void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler);
-
- public virtual Outcome CheckRPFP(string descriptiveName, RPFP vc, ErrorHandler handler,
- out RPFP.Node cex,
- Dictionary<int, Dictionary<string, string>> varSubst, Dictionary<string,int> extra_bound = null)
- {
- throw new System.NotImplementedException();
- }
- [NoDefaultContract]
- public abstract Outcome CheckOutcome(ErrorHandler handler, int taskID = -1);
- public virtual string[] CalculatePath(int controlFlowConstant) {
- throw new System.NotImplementedException();
- }
- public virtual void LogComment(string comment) {
- Contract.Requires(comment != null);
- }
- public virtual void Close() {
- }
-
- public abstract void Reset(VCExpressionGenerator gen);
-
- public abstract void FullReset(VCExpressionGenerator gen);
-
- /// <summary>
- /// MSchaef: Allows to Push a VCExpression as Axiom on the prover stack (beta)
- /// for now it is only implemented by ProcessTheoremProver and still requires some
- /// testing
- /// </summary>
- public virtual void PushVCExpression(VCExpr vc) {
- Contract.Requires(vc != null);
- throw new NotImplementedException();
- }
- public virtual string VCExpressionToString(VCExpr vc) {
- Contract.Requires(vc != null);
- Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
- }
- public virtual void Pop() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
- public virtual int NumAxiomsPushed() {
- throw new NotImplementedException();
- }
- public virtual int FlushAxiomsToTheoremProver() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
-
- // (assert vc)
- public virtual void Assert(VCExpr vc, bool polarity)
- {
- throw new NotImplementedException();
- }
-
- // (assert implicit-axioms)
- public virtual void AssertAxioms()
- {
- throw new NotImplementedException();
- }
-
- // (check-sat)
- public virtual void Check()
- {
- throw new NotImplementedException();
- }
-
- // (check-sat + get-unsat-core + checkOutcome)
- public virtual Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
- {
- throw new NotImplementedException();
- }
-
- public virtual Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) {
- throw new NotImplementedException();
- }
-
- public virtual Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1)
- {
- throw new NotImplementedException();
- }
-
- // (push 1)
- public virtual void Push()
- {
- throw new NotImplementedException();
- }
-
- // Set theorem prover timeout for the next "check-sat"
- public virtual void SetTimeOut(int ms)
- { }
-
- public abstract ProverContext Context {
- get;
- }
-
- public abstract VCExpressionGenerator VCExprGen {
- get;
- }
-
- public virtual void DefineMacro(Macro fun, VCExpr vc) {
- throw new NotImplementedException();
- }
-
- public class VCExprEvaluationException : Exception
- {
-
- }
-
- public virtual object Evaluate(VCExpr expr)
- {
- throw new NotImplementedException();
- }
-
- //////////////////////
- // For interpolation queries
- //////////////////////
-
- // Assert vc tagged with a name
- public virtual void AssertNamed(VCExpr vc, bool polarity, string name)
- {
- throw new NotImplementedException();
- }
-
- // Returns Interpolant(A,B)
- public virtual VCExpr ComputeInterpolant(VCExpr A, VCExpr B)
- {
- throw new NotImplementedException();
- }
-
- // Returns for each l, Interpolant(root + (leaves - l), l)
- // Preconditions:
- // leaves cannot have subformulas with same variable names
- // Both root and leaves should have been previously named via AssertNamed
- public virtual List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves)
- {
- throw new NotImplementedException();
- }
-
- }
-
- public class ProverInterfaceContracts : ProverInterface {
- public override ProverContext Context {
- get {
- Contract.Ensures(Contract.Result<ProverContext>() != null);
-
- throw new NotImplementedException();
- }
- }
- public override VCExpressionGenerator VCExprGen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
-
- throw new NotImplementedException();
- }
- }
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) {/*Contract.Requires(descriptiveName != null);*/
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- throw new NotImplementedException();
- }
- [NoDefaultContract]
- public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1) {
- //Contract.Requires(handler != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
-
- public override void Reset(VCExpressionGenerator gen)
- {
- throw new NotImplementedException();
- }
-
- public override void FullReset(VCExpressionGenerator gen)
- {
- throw new NotImplementedException();
- }
- }
-
- public class ProverException : Exception {
- public ProverException(string s)
- : base(s) {
- }
- }
- public class UnexpectedProverOutputException : ProverException {
- public UnexpectedProverOutputException(string s)
- : base(s) {
- }
- }
- public class ProverDiedException : UnexpectedProverOutputException {
- public ProverDiedException()
- : base("Prover died with no further output, perhaps it ran out of memory or was killed.") {
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.AbstractInterpretation;
+using Microsoft.Boogie.VCExprAST;
+using Microsoft.Basetypes;
+using System.Threading.Tasks;
+
+namespace Microsoft.Boogie {
+
+ enum CheckerStatus
+ {
+ Idle,
+ Ready,
+ Busy,
+ Closed
+ }
+
+ /// <summary>
+ /// Interface to the theorem prover specialized to Boogie.
+ ///
+ /// This class creates the appropriate background axioms. There
+ /// should be one instance per BoogiePL program.
+ /// </summary>
+ public sealed class Checker {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(gen != null);
+ Contract.Invariant(thmProver != null);
+ }
+
+ private readonly VCExpressionGenerator gen;
+
+ private ProverInterface thmProver;
+ private int timeout;
+
+ // state for the async interface
+ private volatile ProverInterface.Outcome outcome;
+ private volatile bool hasOutput;
+ private volatile UnexpectedProverOutputException outputExn;
+ private DateTime proverStart;
+ private TimeSpan proverRunTime;
+ private volatile ProverInterface.ErrorHandler handler;
+ private volatile CheckerStatus status;
+ public volatile Program Program;
+
+ public void GetReady()
+ {
+ Contract.Requires(IsIdle);
+
+ status = CheckerStatus.Ready;
+ }
+
+ public void GoBackToIdle()
+ {
+ Contract.Requires(IsBusy);
+
+ status = CheckerStatus.Idle;
+ }
+
+ public Task ProverTask { get; set; }
+
+ public bool WillingToHandle(int timeout, Program prog) {
+ return status == CheckerStatus.Idle && timeout == this.timeout && (prog == null || Program == prog);
+ }
+
+ public VCExpressionGenerator VCExprGen {
+ get {
+ Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
+ return this.gen;
+ }
+ }
+ public ProverInterface TheoremProver {
+ get {
+ Contract.Ensures(Contract.Result<ProverInterface>() != null);
+ return this.thmProver;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // We share context information for the same program between different Checkers
+
+ private struct ContextCacheKey {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(program != null);
+ }
+
+ public readonly Program program;
+
+ public ContextCacheKey(Program prog) {
+ Contract.Requires(prog != null);
+ this.program = prog;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is ContextCacheKey) {
+ ContextCacheKey thatKey = (ContextCacheKey)that;
+ return this.program.Equals(thatKey.program);
+ }
+ return false;
+ }
+
+ [Pure]
+ public override int GetHashCode() {
+ return this.program.GetHashCode();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// Constructor. Initialize a checker with the program and log file.
+ /// Optionally, use prover context provided by parameter "ctx".
+ /// </summary>
+ public Checker(VC.ConditionGeneration vcgen, Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, ProverContext ctx = null) {
+ Contract.Requires(vcgen != null);
+ Contract.Requires(prog != null);
+ this.timeout = timeout;
+ this.Program = prog;
+
+ ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
+
+ if (logFilePath != null) {
+ options.LogFilename = logFilePath;
+ if (appendLogFile)
+ options.AppendLogFile = appendLogFile;
+ }
+
+ if (timeout > 0) {
+ options.TimeLimit = timeout * 1000;
+ }
+
+ options.Parse(CommandLineOptions.Clo.ProverOptions);
+
+ ContextCacheKey key = new ContextCacheKey(prog);
+ ProverInterface prover;
+
+ if (vcgen.CheckerCommonState == null) {
+ vcgen.CheckerCommonState = new Dictionary<ContextCacheKey, ProverContext>();
+ }
+ IDictionary<ContextCacheKey, ProverContext>/*!>!*/ cachedContexts = (IDictionary<ContextCacheKey, ProverContext/*!*/>)vcgen.CheckerCommonState;
+
+ if (ctx == null && cachedContexts.TryGetValue(key, out ctx))
+ {
+ ctx = (ProverContext)cce.NonNull(ctx).Clone();
+ prover = (ProverInterface)
+ CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
+ } else {
+ if (ctx == null) ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
+
+ Setup(prog, ctx);
+
+ // we first generate the prover and then store a clone of the
+ // context in the cache, so that the prover can setup stuff in
+ // the context to be cached
+ prover = (ProverInterface)
+ CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
+ cachedContexts.Add(key, cce.NonNull((ProverContext)ctx.Clone()));
+ }
+
+ this.thmProver = prover;
+ this.gen = prover.VCExprGen;
+ }
+
+ public void Retarget(Program prog, ProverContext ctx, int timeout = 0)
+ {
+ lock (this)
+ {
+ hasOutput = default(bool);
+ outcome = default(ProverInterface.Outcome);
+ outputExn = default(UnexpectedProverOutputException);
+ handler = default(ProverInterface.ErrorHandler);
+ TheoremProver.FullReset(gen);
+ ctx.Reset();
+ Setup(prog, ctx);
+ this.timeout = timeout;
+ SetTimeout();
+ }
+ }
+
+ public void RetargetWithoutReset(Program prog, ProverContext ctx)
+ {
+ ctx.Clear();
+ Setup(prog, ctx);
+ }
+
+
+ public void SetTimeout()
+ {
+ if (0 < timeout)
+ {
+ TheoremProver.SetTimeOut(timeout * 1000);
+ }
+ else
+ {
+ TheoremProver.SetTimeOut(0);
+ }
+ }
+
+ /// <summary>
+ /// Set up the context.
+ /// </summary>
+ private void Setup(Program prog, ProverContext ctx)
+ {
+ Program = prog;
+ // TODO(wuestholz): Is this lock necessary?
+ lock (Program.TopLevelDeclarations)
+ {
+ foreach (Declaration decl in Program.TopLevelDeclarations)
+ {
+ Contract.Assert(decl != null);
+ var typeDecl = decl as TypeCtorDecl;
+ var constDecl = decl as Constant;
+ var funDecl = decl as Function;
+ var axiomDecl = decl as Axiom;
+ var glVarDecl = decl as GlobalVariable;
+ if (typeDecl != null)
+ {
+ ctx.DeclareType(typeDecl, null);
+ }
+ else if (constDecl != null)
+ {
+ ctx.DeclareConstant(constDecl, constDecl.Unique, null);
+ }
+ else if (funDecl != null)
+ {
+ ctx.DeclareFunction(funDecl, null);
+ }
+ else if (axiomDecl != null)
+ {
+ ctx.AddAxiom(axiomDecl, null);
+ }
+ else if (glVarDecl != null)
+ {
+ ctx.DeclareGlobalVariable(glVarDecl, null);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Clean-up.
+ /// </summary>
+ public void Close() {
+ thmProver.Close();
+ status = CheckerStatus.Closed;
+ }
+
+ /// <summary>
+ /// Push a Verification Condition as an Axiom
+ /// (Required for Doomed Program Point detection)
+ /// </summary>
+ public void PushVCExpr(VCExpr vc) {
+ Contract.Requires(vc != null);
+ //thmProver.Context.AddAxiom(vc);
+ thmProver.PushVCExpression(vc);
+ }
+
+ public bool IsBusy {
+ get {
+ return status == CheckerStatus.Busy;
+ }
+ }
+
+ public bool IsReady
+ {
+ get
+ {
+ return status == CheckerStatus.Ready;
+ }
+ }
+
+ public bool IsClosed {
+ get {
+ return status == CheckerStatus.Closed;
+ }
+ }
+
+ public bool IsIdle
+ {
+ get
+ {
+ return status == CheckerStatus.Idle;
+ }
+ }
+
+ public bool HasOutput {
+ get {
+ return hasOutput;
+ }
+ }
+
+ public TimeSpan ProverRunTime {
+ get {
+ return proverRunTime;
+ }
+ }
+
+ private void WaitForOutput(object dummy) {
+ lock (this)
+ {
+ try
+ {
+ outcome = thmProver.CheckOutcome(cce.NonNull(handler));
+ }
+ catch (UnexpectedProverOutputException e)
+ {
+ outputExn = e;
+ }
+
+ switch (outcome)
+ {
+ case ProverInterface.Outcome.Valid:
+ thmProver.LogComment("Valid");
+ break;
+ case ProverInterface.Outcome.Invalid:
+ thmProver.LogComment("Invalid");
+ break;
+ case ProverInterface.Outcome.TimeOut:
+ thmProver.LogComment("Timed out");
+ break;
+ case ProverInterface.Outcome.OutOfMemory:
+ thmProver.LogComment("Out of memory");
+ break;
+ case ProverInterface.Outcome.Undetermined:
+ thmProver.LogComment("Undetermined");
+ break;
+ }
+
+ hasOutput = true;
+ proverRunTime = DateTime.UtcNow - proverStart;
+ }
+ }
+
+ public void BeginCheck(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler) {
+ Contract.Requires(descriptiveName != null);
+ Contract.Requires(vc != null);
+ Contract.Requires(handler != null);
+ Contract.Requires(IsReady);
+
+ status = CheckerStatus.Busy;
+ hasOutput = false;
+ outputExn = null;
+ this.handler = handler;
+
+ thmProver.Reset(gen);
+ SetTimeout();
+ proverStart = DateTime.UtcNow;
+ thmProver.BeginCheck(descriptiveName, vc, handler);
+ // gen.ClearSharedFormulas(); PR: don't know yet what to do with this guy
+
+ ProverTask = Task.Factory.StartNew(() => { WaitForOutput(null); }, TaskCreationOptions.LongRunning);
+ }
+
+ public ProverInterface.Outcome ReadOutcome() {
+ Contract.Requires(IsBusy);
+ Contract.Requires(HasOutput);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ hasOutput = false;
+
+ if (outputExn != null) {
+ throw outputExn;
+ }
+
+ return outcome;
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ public abstract class ProverInterface {
+
+ public static ProverInterface CreateProver(Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, int taskID = -1) {
+ Contract.Requires(prog != null);
+
+ ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
+
+ if (logFilePath != null) {
+ options.LogFilename = logFilePath;
+ if (appendLogFile)
+ options.AppendLogFile = appendLogFile;
+ }
+
+ if (timeout > 0) {
+ options.TimeLimit = timeout * 1000;
+ }
+
+ if (taskID >= 0) {
+ options.Parse(CommandLineOptions.Clo.Cho[taskID].ProverOptions);
+ } else {
+ options.Parse(CommandLineOptions.Clo.ProverOptions);
+ }
+
+ ProverContext ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
+
+ // set up the context
+ foreach (Declaration decl in prog.TopLevelDeclarations) {
+ Contract.Assert(decl != null);
+ TypeCtorDecl t = decl as TypeCtorDecl;
+ if (t != null) {
+ ctx.DeclareType(t, null);
+ }
+ }
+ foreach (Declaration decl in prog.TopLevelDeclarations) {
+ Contract.Assert(decl != null);
+ Constant c = decl as Constant;
+ if (c != null) {
+ ctx.DeclareConstant(c, c.Unique, null);
+ }
+ else {
+ Function f = decl as Function;
+ if (f != null) {
+ ctx.DeclareFunction(f, null);
+ }
+ }
+ }
+ foreach (var ax in prog.Axioms) {
+ ctx.AddAxiom(ax, null);
+ }
+ foreach (Declaration decl in prog.TopLevelDeclarations) {
+ Contract.Assert(decl != null);
+ GlobalVariable v = decl as GlobalVariable;
+ if (v != null) {
+ ctx.DeclareGlobalVariable(v, null);
+ }
+ }
+
+ return (ProverInterface)CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
+ }
+
+ public enum Outcome {
+ Valid,
+ Invalid,
+ TimeOut,
+ OutOfMemory,
+ Undetermined,
+ Bounded
+ }
+
+ public readonly ISet<VCExprVar> NamedAssumes = new HashSet<VCExprVar>();
+ public ISet<string> UsedNamedAssumes { get; protected set; }
+
+ public class ErrorHandler {
+ // Used in CheckOutcomeCore
+ public virtual int StartingProcId()
+ {
+ return 0;
+ }
+
+ public virtual void OnModel(IList<string> labels, Model model, Outcome proverOutcome) {
+ Contract.Requires(cce.NonNullElements(labels));
+ }
+
+ public virtual void OnResourceExceeded(string message, IEnumerable<Tuple<AssertCmd, TransferCmd>> assertCmds = null) {
+ Contract.Requires(message != null);
+ }
+
+ public virtual void OnProverWarning(string message)
+ {
+ Contract.Requires(message != null);
+ switch (CommandLineOptions.Clo.PrintProverWarnings) {
+ case CommandLineOptions.ProverWarnings.None:
+ break;
+ case CommandLineOptions.ProverWarnings.Stdout:
+ Console.WriteLine("Prover warning: " + message);
+ break;
+ case CommandLineOptions.ProverWarnings.Stderr:
+ Console.Error.WriteLine("Prover warning: " + message);
+ break;
+ default:
+ Contract.Assume(false);
+ throw new cce.UnreachableException(); // unexpected case
+ }
+ }
+
+ public virtual Absy Label2Absy(string label) {
+ Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ throw new System.NotImplementedException();
+ }
+ }
+ public abstract void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler);
+
+ public virtual Outcome CheckRPFP(string descriptiveName, RPFP vc, ErrorHandler handler,
+ out RPFP.Node cex,
+ Dictionary<int, Dictionary<string, string>> varSubst, Dictionary<string,int> extra_bound = null)
+ {
+ throw new System.NotImplementedException();
+ }
+ [NoDefaultContract]
+ public abstract Outcome CheckOutcome(ErrorHandler handler, int taskID = -1);
+ public virtual string[] CalculatePath(int controlFlowConstant) {
+ throw new System.NotImplementedException();
+ }
+ public virtual void LogComment(string comment) {
+ Contract.Requires(comment != null);
+ }
+ public virtual void Close() {
+ }
+
+ public abstract void Reset(VCExpressionGenerator gen);
+
+ public abstract void FullReset(VCExpressionGenerator gen);
+
+ /// <summary>
+ /// MSchaef: Allows to Push a VCExpression as Axiom on the prover stack (beta)
+ /// for now it is only implemented by ProcessTheoremProver and still requires some
+ /// testing
+ /// </summary>
+ public virtual void PushVCExpression(VCExpr vc) {
+ Contract.Requires(vc != null);
+ throw new NotImplementedException();
+ }
+ public virtual string VCExpressionToString(VCExpr vc) {
+ Contract.Requires(vc != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ throw new NotImplementedException();
+ }
+ public virtual void Pop() {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ throw new NotImplementedException();
+ }
+ public virtual int NumAxiomsPushed() {
+ throw new NotImplementedException();
+ }
+ public virtual int FlushAxiomsToTheoremProver() {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ throw new NotImplementedException();
+ }
+
+ // (assert vc)
+ public virtual void Assert(VCExpr vc, bool polarity, bool isSoft = false, int weight = 1)
+ {
+ throw new NotImplementedException();
+ }
+
+ // (assert implicit-axioms)
+ public virtual void AssertAxioms()
+ {
+ throw new NotImplementedException();
+ }
+
+ // (check-sat)
+ public virtual void Check()
+ {
+ throw new NotImplementedException();
+ }
+
+ // (check-sat + get-unsat-core + checkOutcome)
+ public virtual Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) {
+ throw new NotImplementedException();
+ }
+
+ public virtual Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1)
+ {
+ throw new NotImplementedException();
+ }
+
+ // (push 1)
+ public virtual void Push()
+ {
+ throw new NotImplementedException();
+ }
+
+ // Set theorem prover timeout for the next "check-sat"
+ public virtual void SetTimeOut(int ms)
+ { }
+
+ public abstract ProverContext Context {
+ get;
+ }
+
+ public abstract VCExpressionGenerator VCExprGen {
+ get;
+ }
+
+ public virtual void DefineMacro(Macro fun, VCExpr vc) {
+ throw new NotImplementedException();
+ }
+
+ public class VCExprEvaluationException : Exception
+ {
+
+ }
+
+ public virtual object Evaluate(VCExpr expr)
+ {
+ throw new NotImplementedException();
+ }
+
+ //////////////////////
+ // For interpolation queries
+ //////////////////////
+
+ // Assert vc tagged with a name
+ public virtual void AssertNamed(VCExpr vc, bool polarity, string name)
+ {
+ throw new NotImplementedException();
+ }
+
+ // Returns Interpolant(A,B)
+ public virtual VCExpr ComputeInterpolant(VCExpr A, VCExpr B)
+ {
+ throw new NotImplementedException();
+ }
+
+ // Returns for each l, Interpolant(root + (leaves - l), l)
+ // Preconditions:
+ // leaves cannot have subformulas with same variable names
+ // Both root and leaves should have been previously named via AssertNamed
+ public virtual List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves)
+ {
+ throw new NotImplementedException();
+ }
+
+ }
+
+ public class ProverInterfaceContracts : ProverInterface {
+ public override ProverContext Context {
+ get {
+ Contract.Ensures(Contract.Result<ProverContext>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+ public override VCExpressionGenerator VCExprGen {
+ get {
+ Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+ public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) {/*Contract.Requires(descriptiveName != null);*/
+ //Contract.Requires(vc != null);
+ //Contract.Requires(handler != null);
+ throw new NotImplementedException();
+ }
+ [NoDefaultContract]
+ public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1) {
+ //Contract.Requires(handler != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ throw new NotImplementedException();
+ }
+
+ public override void Reset(VCExpressionGenerator gen)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void FullReset(VCExpressionGenerator gen)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class ProverException : Exception {
+ public ProverException(string s)
+ : base(s) {
+ }
+ }
+ public class UnexpectedProverOutputException : ProverException {
+ public UnexpectedProverOutputException(string s)
+ : base(s) {
+ }
+ }
+ public class ProverDiedException : UnexpectedProverOutputException {
+ public ProverDiedException()
+ : base("Prover died with no further output, perhaps it ran out of memory or was killed.") {
+ }
+ }
+}
diff --git a/Source/VCGeneration/ConditionGeneration.cs b/Source/VCGeneration/ConditionGeneration.cs
index 515ec16d..19438924 100644
--- a/Source/VCGeneration/ConditionGeneration.cs
+++ b/Source/VCGeneration/ConditionGeneration.cs
@@ -1,1985 +1,2041 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-using Set = Microsoft.Boogie.GSet<object>;
-
-namespace Microsoft.Boogie {
-
- public class CalleeCounterexampleInfo {
- public Counterexample counterexample;
- public List<object>/*!>!*/ args;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(args));
- }
-
- public CalleeCounterexampleInfo(Counterexample cex, List<object/*!>!*/> x)
- {
- Contract.Requires(cce.NonNullElements(x));
- counterexample = cex;
- args = x;
- }
- }
-
- public class TraceLocation : IEquatable<TraceLocation>
- {
- public int numBlock;
- public int numInstr;
-
- public TraceLocation(int numBlock, int numInstr)
- {
- this.numBlock = numBlock;
- this.numInstr = numInstr;
- }
-
- public override bool Equals(object obj)
- {
- TraceLocation that = obj as TraceLocation;
- if (that == null) return false;
- return (numBlock == that.numBlock && numInstr == that.numInstr);
- }
-
- public bool Equals(TraceLocation that)
- {
- return (numBlock == that.numBlock && numInstr == that.numInstr);
- }
-
- public override int GetHashCode()
- {
- return numBlock.GetHashCode() ^ 131 * numInstr.GetHashCode();
- }
- }
-
- public abstract class Counterexample {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Trace != null);
- Contract.Invariant(Context != null);
- Contract.Invariant(cce.NonNullElements(relatedInformation));
- Contract.Invariant(cce.NonNullDictionaryAndValues(calleeCounterexamples));
- }
-
- [Peer]
- public List<Block> Trace;
- public Model Model;
- public VC.ModelViewInfo MvInfo;
- public ProverContext Context;
- [Peer]
- public List<string>/*!>!*/ relatedInformation;
- public string OriginalRequestId;
- public string RequestId;
- public abstract byte[] Checksum { get; }
- public byte[] SugaredCmdChecksum;
-
- public Dictionary<TraceLocation, CalleeCounterexampleInfo> calleeCounterexamples;
-
- internal Counterexample(List<Block> trace, Model model, VC.ModelViewInfo mvInfo, ProverContext context) {
- Contract.Requires(trace != null);
- Contract.Requires(context != null);
- this.Trace = trace;
- this.Model = model;
- this.MvInfo = mvInfo;
- this.Context = context;
- this.relatedInformation = new List<string>();
- this.calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
- }
-
- // Create a shallow copy of the counterexample
- public abstract Counterexample Clone();
-
- public void AddCalleeCounterexample(TraceLocation loc, CalleeCounterexampleInfo cex)
- {
- Contract.Requires(cex != null);
- calleeCounterexamples[loc] = cex;
- }
-
- public void AddCalleeCounterexample(int numBlock, int numInstr, CalleeCounterexampleInfo cex)
- {
- Contract.Requires(cex != null);
- calleeCounterexamples[new TraceLocation(numBlock, numInstr)] = cex;
- }
-
- public void AddCalleeCounterexample(Dictionary<TraceLocation, CalleeCounterexampleInfo> cs)
- {
- Contract.Requires(cce.NonNullDictionaryAndValues(cs));
- foreach (TraceLocation loc in cs.Keys)
- {
- AddCalleeCounterexample(loc, cs[loc]);
- }
- }
-
- // Looks up the Cmd at a given index into the trace
- public Cmd getTraceCmd(TraceLocation loc)
- {
- Debug.Assert(loc.numBlock < Trace.Count);
- Block b = Trace[loc.numBlock];
- Debug.Assert(loc.numInstr < b.Cmds.Count);
- return b.Cmds[loc.numInstr];
- }
-
- // Looks up the name of the called procedure.
- // Asserts that the name exists
- public string getCalledProcName(Cmd cmd)
- {
- // There are two options:
- // 1. cmd is a CallCmd
- // 2. cmd is an AssumeCmd (passified version of a CallCmd)
- if(cmd is CallCmd) {
- return (cmd as CallCmd).Proc.Name;
- }
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- Debug.Assert(assumeCmd != null);
-
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- Debug.Assert(naryExpr != null);
-
- return naryExpr.Fun.FunctionName;
- }
-
- public void Print(int indent, TextWriter tw, Action<Block> blockAction = null) {
- int numBlock = -1;
- string ind = new string(' ', indent);
- foreach (Block b in Trace) {
- Contract.Assert(b != null);
- numBlock++;
- if (b.tok == null) {
- tw.WriteLine("{0}<intermediate block>", ind);
- } else {
- // for ErrorTrace == 1 restrict the output;
- // do not print tokens with -17:-4 as their location because they have been
- // introduced in the translation and do not give any useful feedback to the user
- if (!(CommandLineOptions.Clo.ErrorTrace == 1 && b.tok.line == -17 && b.tok.col == -4)) {
- if (blockAction != null)
- {
- blockAction(b);
- }
-
- tw.WriteLine("{4}{0}({1},{2}): {3}", b.tok.filename, b.tok.line, b.tok.col, b.Label, ind);
-
- for (int numInstr = 0; numInstr < b.Cmds.Count; numInstr++)
- {
- var loc = new TraceLocation(numBlock, numInstr);
- if (calleeCounterexamples.ContainsKey(loc))
- {
- var cmd = getTraceCmd(loc);
- var calleeName = getCalledProcName(cmd);
- if (calleeName.StartsWith(VC.StratifiedVCGen.recordProcName) && CommandLineOptions.Clo.StratifiedInlining > 0)
- {
- Contract.Assert(calleeCounterexamples[loc].args.Count == 1);
- var arg = calleeCounterexamples[loc].args[0];
- tw.WriteLine("{0}value = {1}", ind, arg.ToString());
- }
- else
- {
- tw.WriteLine("{1}Inlined call to procedure {0} begins", calleeName, ind);
- calleeCounterexamples[loc].counterexample.Print(indent + 4, tw);
- tw.WriteLine("{1}Inlined call to procedure {0} ends", calleeName, ind);
- }
- }
- }
- }
- }
- }
- }
-
- public static bool firstModelFile = true;
-
- public bool ModelHasStatesAlready = false;
-
- public void PrintModel(TextWriter tw)
- {
- var filename = CommandLineOptions.Clo.ModelViewFile;
- if (Model == null || filename == null || CommandLineOptions.Clo.StratifiedInlining > 0) return;
-
- if (!ModelHasStatesAlready) {
- PopulateModelWithStates();
- ModelHasStatesAlready = true;
- }
-
- if (filename == "-") {
- Model.Write(tw);
- tw.Flush();
- } else {
- using (var wr = new StreamWriter(filename, !firstModelFile)) {
- firstModelFile = false;
- Model.Write(wr);
- }
- }
- }
-
- void ApplyRedirections(Model m) {
- var mapping = new Dictionary<Model.Element, Model.Element>();
- foreach (var name in new string[] { "U_2_bool", "U_2_int" }) {
- Model.Func f = m.TryGetFunc(name);
- if (f != null && f.Arity == 1) {
- foreach (var ft in f.Apps) mapping[ft.Args[0]] = ft.Result;
- }
- }
- m.Substitute(mapping);
- }
-
- public void PopulateModelWithStates()
- {
- Contract.Requires(Model != null);
-
- Model m = Model;
- ApplyRedirections(m);
-
- var mvstates = m.TryGetFunc("$mv_state");
- if (MvInfo == null || mvstates == null || (mvstates.Arity == 1 && mvstates.Apps.Count() == 0))
- return;
-
- Contract.Assert(mvstates.Arity == 2);
-
- foreach (Variable v in MvInfo.AllVariables) {
- m.InitialState.AddBinding(v.Name, GetModelValue(m, v));
- }
-
- var states = new List<int>();
- foreach (var t in mvstates.Apps)
- states.Add(t.Args[1].AsInt());
-
- states.Sort();
-
- for (int i = 0; i < states.Count; ++i) {
- var s = states[i];
- if (0 <= s && s < MvInfo.CapturePoints.Count) {
- VC.ModelViewInfo.Mapping map = MvInfo.CapturePoints[s];
- var prevInc = i > 0 ? MvInfo.CapturePoints[states[i - 1]].IncarnationMap : new Dictionary<Variable, Expr>();
- var cs = m.MkState(map.Description);
-
- foreach (Variable v in MvInfo.AllVariables) {
- Expr e = map.IncarnationMap.ContainsKey(v) ? map.IncarnationMap[v] : null;
- if (e == null) continue;
-
- Expr prevIncV = prevInc.ContainsKey(v) ? prevInc[v] : null;
- if (prevIncV == e) continue; // skip unchanged variables
-
- Model.Element elt;
-
- if (e is IdentifierExpr) {
- IdentifierExpr ide = (IdentifierExpr)e;
- elt = GetModelValue(m, ide.Decl);
- } else if (e is LiteralExpr) {
- LiteralExpr lit = (LiteralExpr)e;
- elt = m.MkElement(lit.Val.ToString());
- } else {
- elt = m.MkFunc(e.ToString(), 0).GetConstant();
- }
-
- cs.AddBinding(v.Name, elt);
- }
-
- } else {
- Contract.Assume(false);
- }
- }
- }
-
- private Model.Element GetModelValue(Model m, Variable v) {
- Model.Element elt;
- // first, get the unique name
- string uniqueName;
- VCExprVar vvar = Context.BoogieExprTranslator.TryLookupVariable(v);
- if (vvar == null) {
- uniqueName = v.Name;
- } else {
- uniqueName = Context.Lookup(vvar);
- }
-
- var f = m.TryGetFunc(uniqueName);
- if (f == null) {
- f = m.MkFunc(uniqueName, 0);
- }
- elt = f.GetConstant();
- return elt;
- }
-
- public abstract int GetLocation();
- }
-
- public class CounterexampleComparer : IComparer<Counterexample> {
-
- private int Compare(List<Block> bs1, List<Block> bs2)
- {
- if (bs1.Count < bs2.Count)
- {
- return -1;
- }
- else if (bs2.Count < bs1.Count)
- {
- return 1;
- }
-
- for (int i = 0; i < bs1.Count; i++)
- {
- var b1 = bs1[i];
- var b2 = bs2[i];
- if (b1.tok.pos < b2.tok.pos)
- {
- return -1;
- }
- else if (b2.tok.pos < b1.tok.pos)
- {
- return 1;
- }
- }
-
- return 0;
- }
-
- public int Compare(Counterexample c1, Counterexample c2)
- {
- //Contract.Requires(c1 != null);
- //Contract.Requires(c2 != null);
- if (c1.GetLocation() == c2.GetLocation())
- {
- var c = Compare(c1.Trace, c2.Trace);
- if (c != 0)
- {
- return c;
- }
- // TODO(wuestholz): Generalize this to compare all IPotentialErrorNodes of the counterexample.
- var a1 = c1 as AssertCounterexample;
- var a2 = c2 as AssertCounterexample;
- if (a1 != null && a2 != null)
- {
- var s1 = a1.FailingAssert.ErrorData as string;
- var s2 = a2.FailingAssert.ErrorData as string;
- if (s1 != null && s2 != null)
- {
- return s1.CompareTo(s2);
- }
- }
-
- return 0;
- }
- if (c1.GetLocation() > c2.GetLocation())
- {
- return 1;
- }
- return -1;
- }
- }
-
- public class AssertCounterexample : Counterexample {
- [Peer]
- public AssertCmd FailingAssert;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FailingAssert != null);
- }
-
-
- public AssertCounterexample(List<Block> trace, AssertCmd failingAssert, Model model, VC.ModelViewInfo mvInfo, ProverContext context)
- : base(trace, model, mvInfo, context) {
- Contract.Requires(trace != null);
- Contract.Requires(failingAssert != null);
- Contract.Requires(context != null);
- this.FailingAssert = failingAssert;
- }
-
- public override int GetLocation() {
- return FailingAssert.tok.line * 1000 + FailingAssert.tok.col;
- }
-
- public override byte[] Checksum
- {
- get { return FailingAssert.Checksum; }
- }
-
- public override Counterexample Clone()
- {
- var ret = new AssertCounterexample(Trace, FailingAssert, Model, MvInfo, Context);
- ret.calleeCounterexamples = calleeCounterexamples;
- return ret;
- }
- }
-
- public class CallCounterexample : Counterexample {
- public CallCmd FailingCall;
- public Requires FailingRequires;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FailingCall != null);
- Contract.Invariant(FailingRequires != null);
- }
-
-
- public CallCounterexample(List<Block> trace, CallCmd failingCall, Requires failingRequires, Model model, VC.ModelViewInfo mvInfo, ProverContext context, byte[] checksum = null)
- : base(trace, model, mvInfo, context) {
- Contract.Requires(!failingRequires.Free);
- Contract.Requires(trace != null);
- Contract.Requires(context != null);
- Contract.Requires(failingCall != null);
- Contract.Requires(failingRequires != null);
- this.FailingCall = failingCall;
- this.FailingRequires = failingRequires;
- this.checksum = checksum;
- this.SugaredCmdChecksum = failingCall.Checksum;
- }
-
- public override int GetLocation() {
- return FailingCall.tok.line * 1000 + FailingCall.tok.col;
- }
-
- byte[] checksum;
- public override byte[] Checksum
- {
- get { return checksum; }
- }
-
- public override Counterexample Clone()
- {
- var ret = new CallCounterexample(Trace, FailingCall, FailingRequires, Model, MvInfo, Context, Checksum);
- ret.calleeCounterexamples = calleeCounterexamples;
- return ret;
- }
- }
-
- public class ReturnCounterexample : Counterexample {
- public TransferCmd FailingReturn;
- public Ensures FailingEnsures;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FailingEnsures != null);
- Contract.Invariant(FailingReturn != null);
- }
-
-
- public ReturnCounterexample(List<Block> trace, TransferCmd failingReturn, Ensures failingEnsures, Model model, VC.ModelViewInfo mvInfo, ProverContext context, byte[] checksum)
- : base(trace, model, mvInfo, context) {
- Contract.Requires(trace != null);
- Contract.Requires(context != null);
- Contract.Requires(failingReturn != null);
- Contract.Requires(failingEnsures != null);
- Contract.Requires(!failingEnsures.Free);
- this.FailingReturn = failingReturn;
- this.FailingEnsures = failingEnsures;
- this.checksum = checksum;
- }
-
- public override int GetLocation() {
- return FailingReturn.tok.line * 1000 + FailingReturn.tok.col;
- }
-
- byte[] checksum;
-
- /// <summary>
- /// Returns the checksum of the corresponding assertion.
- /// </summary>
- public override byte[] Checksum
- {
- get
- {
- return checksum;
- }
- }
-
- public override Counterexample Clone()
- {
- var ret = new ReturnCounterexample(Trace, FailingReturn, FailingEnsures, Model, MvInfo, Context, checksum);
- ret.calleeCounterexamples = calleeCounterexamples;
- return ret;
- }
- }
-
- public class VerifierCallback {
- // reason == null means this is genuine counterexample returned by the prover
- // other reason means it's time out/memory out/crash
- public virtual void OnCounterexample(Counterexample ce, string/*?*/ reason) {
- Contract.Requires(ce != null);
- }
-
- // called in case resource is exceeded and we don't have counterexample
- public virtual void OnTimeout(string reason) {
- Contract.Requires(reason != null);
- }
-
- public virtual void OnOutOfMemory(string reason) {
- Contract.Requires(reason != null);
- }
-
- public virtual void OnProgress(string phase, int step, int totalSteps, double progressEstimate) {
- }
-
- public virtual void OnUnreachableCode(Implementation impl) {
- Contract.Requires(impl != null);
- }
-
- public virtual void OnWarning(string msg) {
- Contract.Requires(msg != null);
- switch (CommandLineOptions.Clo.PrintProverWarnings) {
- case CommandLineOptions.ProverWarnings.None:
- break;
- case CommandLineOptions.ProverWarnings.Stdout:
- Console.WriteLine("Prover warning: " + msg);
- break;
- case CommandLineOptions.ProverWarnings.Stderr:
- Console.Error.WriteLine("Prover warning: " + msg);
- break;
- default:
- Contract.Assume(false);
- throw new cce.UnreachableException(); // unexpected case
- }
- }
- }
-}
-
-////////////////////////////////////////////
-
-namespace VC {
- using Bpl = Microsoft.Boogie;
-
- public class VCGenException : Exception {
- public VCGenException(string s)
- : base(s) {
- }
- }
- [ContractClassFor(typeof(ConditionGeneration))]
- public abstract class ConditionGenerationContracts : ConditionGeneration {
- public override Outcome VerifyImplementation(Implementation impl, VerifierCallback callback) {
- Contract.Requires(impl != null);
- Contract.Requires(callback != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
- public ConditionGenerationContracts(Program p, List<Checker> checkers)
- : base(p, checkers) {
- }
- }
-
- [ContractClass(typeof(ConditionGenerationContracts))]
- public abstract class ConditionGeneration : IDisposable {
- protected internal object CheckerCommonState;
-
- public enum Outcome {
- Correct,
- Errors,
- TimedOut,
- OutOfMemory,
- Inconclusive,
- ReachedBound
- }
-
- public static Outcome ProverInterfaceOutcomeToConditionGenerationOutcome(ProverInterface.Outcome outcome) {
- switch (outcome) {
- case ProverInterface.Outcome.Invalid:
- return Outcome.Errors;
- case ProverInterface.Outcome.OutOfMemory:
- return Outcome.OutOfMemory;
- case ProverInterface.Outcome.TimeOut:
- return Outcome.TimedOut;
- case ProverInterface.Outcome.Undetermined:
- return Outcome.Inconclusive;
- case ProverInterface.Outcome.Valid:
- return Outcome.Correct;
- }
- return Outcome.Inconclusive; // unreachable but the stupid compiler does not understand
- }
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(checkers));
- Contract.Invariant(cce.NonNullDictionaryAndValues(incarnationOriginMap));
- Contract.Invariant(program != null);
- }
-
- public int CumulativeAssertionCount; // for statistics
-
- protected readonly List<Checker>/*!>!*/ checkers;
-
- private bool _disposed;
-
- protected Implementation currentImplementation;
-
- protected List<Variable> CurrentLocalVariables = null;
-
- // shared across each implementation; created anew for each implementation
- protected Dictionary<Variable, int> variable2SequenceNumber;
- public Dictionary<Incarnation, Absy>/*!>!*/ incarnationOriginMap = new Dictionary<Incarnation, Absy>();
-
- public Program program;
- protected string/*?*/ logFilePath;
- protected bool appendLogFile;
-
- public static List<Model> errorModelList;
-
- public ConditionGeneration(Program p, List<Checker> checkers) {
- Contract.Requires(p != null && checkers != null && cce.NonNullElements(checkers));
- program = p;
- this.checkers = checkers;
- Cores = 1;
- }
-
- /// <summary>
- /// Takes an implementation and constructs a verification condition and sends
- /// it to the theorem prover.
- /// Returns null if "impl" is correct. Otherwise, returns a list of counterexamples,
- /// each counterexample consisting of an array of labels.
- /// </summary>
- /// <param name="impl"></param>
- public Outcome VerifyImplementation(Implementation impl, out List<Counterexample>/*?*/ errors, string requestId = null) {
- Contract.Requires(impl != null);
-
- Contract.Ensures(Contract.ValueAtReturn(out errors) == null || Contract.ForAll(Contract.ValueAtReturn(out errors), i => i != null));
- Contract.Ensures(Contract.Result<Outcome>() != Outcome.Errors || errors != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- Helpers.ExtraTraceInformation("Starting implementation verification");
-
- CounterexampleCollector collector = new CounterexampleCollector();
- collector.RequestId = requestId;
- Outcome outcome = VerifyImplementation(impl, collector);
- if (outcome == Outcome.Errors || outcome == Outcome.TimedOut || outcome == Outcome.OutOfMemory) {
- errors = collector.examples;
- } else {
- errors = null;
- }
-
- Helpers.ExtraTraceInformation("Finished implementation verification");
- return outcome;
- }
-
- /// <summary>
- /// Takes an implementation and constructs a verification condition and sends
- /// it to the theorem prover.
- /// Returns null if "impl" is correct. Otherwise, returns a list of counterexamples,
- /// each counterexample consisting of an array of labels.
- /// </summary>
- /// <param name="impl"></param>
- public Outcome VerifyImplementation(Implementation impl, out List<Counterexample> errors, out List<Model> errorsModel)
- {
- Contract.Ensures(Contract.Result<Outcome>() != Outcome.Errors || Contract.ValueAtReturn(out errors) != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- List<Counterexample> errorsOut;
-
- Outcome outcome;
- errorModelList = new List<Model>();
- outcome = VerifyImplementation(impl, out errorsOut);
- errors = errorsOut;
- errorsModel = errorModelList;
-
- return outcome;
- }
-
- public abstract Outcome VerifyImplementation(Implementation impl, VerifierCallback callback);
-
- /////////////////////////////////// Common Methods and Classes //////////////////////////////////////////
-
- #region Methods for injecting pre- and postconditions
- private static void
- ThreadInCodeExpr(Implementation impl,
- Block targetBlock,
- CodeExpr codeExpr,
- bool replaceWithAssert,
- TokenTextWriter debugWriter) {
- Contract.Requires(impl != null);
- Contract.Requires(codeExpr != null);
- Contract.Requires(targetBlock != null);
- // Go through codeExpr and for all blocks that have a "return e"
- // as their transfer command:
- // Replace all "return e" with "assert/assume e"
- // Change the transfer command to "goto targetBlock"
- // Then add all of the blocks in codeExpr to the implementation (at the end)
- foreach (Block b in codeExpr.Blocks) {
- Contract.Assert(b != null);
- ReturnExprCmd rec = b.TransferCmd as ReturnExprCmd;
- if (rec != null) { // otherwise it is a goto command
- if (replaceWithAssert) {
- Ensures ens = new Ensures(rec.tok, false, rec.Expr, null);
- Contract.Assert(ens != null);
- Cmd c = new AssertEnsuresCmd(ens);
- Contract.Assert(c != null);
- b.Cmds.Add(c);
- } else {
- b.Cmds.Add(new AssumeCmd(rec.tok, rec.Expr));
- }
- b.TransferCmd = new GotoCmd(Token.NoToken,
- new List<String> { targetBlock.Label },
- new List<Block> { targetBlock });
- targetBlock.Predecessors.Add(b);
- }
- impl.Blocks.Add(b);
- }
- if (debugWriter != null) {
- codeExpr.Emit(debugWriter, 1, false);
- }
- return;
- }
-
- private static void AddAsPrefix(Block b, List<Cmd> cs) {
- Contract.Requires(b != null);
- Contract.Requires(cs != null);
- List<Cmd> newCommands = new List<Cmd>();
- newCommands.AddRange(cs);
- newCommands.AddRange(b.Cmds);
- b.Cmds = newCommands;
- }
-
-
- /// <summary>
- /// Modifies an implementation by prepending it with startCmds and then, as assume
- /// statements, all preconditions. Insert new blocks as needed, and adjust impl.Blocks[0]
- /// accordingly to make it the new implementation entry block.
- /// </summary>
- /// <param name="impl"></param>
- /// <param name="startCmds"></param>
- protected static void InjectPreconditions(Implementation impl, [Captured] List<Cmd> startCmds) {
- Contract.Requires(impl != null);
- Contract.Requires(startCmds != null);
- Contract.Requires(impl.Proc != null);
-
- TokenTextWriter debugWriter = null;
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
- debugWriter.WriteLine("Effective precondition:");
- }
-
- Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
- string blockLabel = "PreconditionGeneratedEntry";
-
- Block origStartBlock = impl.Blocks[0];
- Block insertionPoint = new Block(
- new Token(-17, -4), blockLabel, startCmds,
- new GotoCmd(Token.NoToken, new List<String> { origStartBlock.Label }, new List<Block> { origStartBlock }));
-
- impl.Blocks[0] = insertionPoint; // make insertionPoint the start block
- impl.Blocks.Add(origStartBlock); // and put the previous start block at the end of the list
-
- // (free and checked) requires clauses
- foreach (Requires req in impl.Proc.Requires)
- // invariant: insertionPoint.TransferCmd is "goto origStartBlock;", but origStartBlock.Predecessors has not yet been updated
- {
- Contract.Assert(req != null);
- Expr e = Substituter.Apply(formalProcImplSubst, req.Condition);
- Cmd c = new AssumeCmd(req.tok, e);
- insertionPoint.Cmds.Add(c);
- if (debugWriter != null) {
- c.Emit(debugWriter, 1);
- }
- }
- origStartBlock.Predecessors.Add(insertionPoint);
-
- if (debugWriter != null) {
- debugWriter.WriteLine();
- }
- }
- /// <summary>
- /// Modifies an implementation by inserting all postconditions
- /// as assert statements at the end of the implementation
- /// Returns the possibly-new unified exit block of the implementation
- /// </summary>
- /// <param name="impl"></param>
- /// <param name="unifiedExitblock">The unified exit block that has
- /// already been constructed for the implementation (and so
- /// is already an element of impl.Blocks)
- /// </param>
- protected static void InjectPostConditions(Implementation impl, Block unifiedExitBlock, Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins) {
- Contract.Requires(impl != null);
- Contract.Requires(unifiedExitBlock != null);
- Contract.Requires(gotoCmdOrigins != null);
- Contract.Requires(impl.Proc != null);
- Contract.Requires(unifiedExitBlock.TransferCmd is ReturnCmd);
-
- TokenTextWriter debugWriter = null;
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
- debugWriter.WriteLine("Effective postcondition:");
- }
-
- Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
-
- // (free and checked) ensures clauses
- foreach (Ensures ens in impl.Proc.Ensures) {
- Contract.Assert(ens != null);
- if (!ens.Free) { // skip free ensures clauses
- Expr e = Substituter.Apply(formalProcImplSubst, ens.Condition);
- Ensures ensCopy = (Ensures)cce.NonNull(ens.Clone());
- ensCopy.Condition = e;
- AssertEnsuresCmd c = new AssertEnsuresCmd(ensCopy);
- c.ErrorDataEnhanced = ensCopy.ErrorDataEnhanced;
- unifiedExitBlock.Cmds.Add(c);
- if (debugWriter != null) {
- c.Emit(debugWriter, 1);
- }
- }
- }
-
- if (debugWriter != null) {
- debugWriter.WriteLine();
- }
- }
-
-
- /// <summary>
- /// Get the pre-condition of an implementation, including the where clauses from the in-parameters.
- /// </summary>
- /// <param name="impl"></param>
- protected static List<Cmd> GetPre(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
-
-
- TokenTextWriter debugWriter = null;
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
- debugWriter.WriteLine("Effective precondition:");
- }
-
- Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
- List<Cmd> pre = new List<Cmd>();
-
- // (free and checked) requires clauses
- foreach (Requires req in impl.Proc.Requires) {
- Contract.Assert(req != null);
- Expr e = Substituter.Apply(formalProcImplSubst, req.Condition);
- Contract.Assert(e != null);
- Cmd c = new AssumeCmd(req.tok, e);
- Contract.Assert(c != null);
- pre.Add(c);
-
- if (debugWriter != null) {
- c.Emit(debugWriter, 1);
- }
- }
-
- if (debugWriter != null) {
- debugWriter.WriteLine();
- }
-
- return pre;
- }
-
- /// <summary>
- /// Get the post-condition of an implementation.
- /// </summary>
- /// <param name="impl"></param>
- protected static List<Cmd> GetPost(Implementation impl) {
-
-
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- Console.WriteLine("Effective postcondition:");
- }
-
- // Construct an Expr for the post-condition
- Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
- List<Cmd> post = new List<Cmd>();
- foreach (Ensures ens in impl.Proc.Ensures) {
- Contract.Assert(ens != null);
- if (!ens.Free) {
- Expr e = Substituter.Apply(formalProcImplSubst, ens.Condition);
- Contract.Assert(e != null);
- Ensures ensCopy = cce.NonNull((Ensures)ens.Clone());
- ensCopy.Condition = e;
- Cmd c = new AssertEnsuresCmd(ensCopy);
- ((AssertEnsuresCmd)c).ErrorDataEnhanced = ensCopy.ErrorDataEnhanced;
- post.Add(c);
-
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- c.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false), 1);
- }
- }
- }
-
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- Console.WriteLine();
- }
-
- return post;
- }
-
- /// <summary>
- /// Get the where clauses from the in- and out-parameters as
- /// a sequence of assume commands.
- /// As a side effect, this method adds these where clauses to the out parameters.
- /// </summary>
- /// <param name="impl"></param>
- protected static List<Cmd> GetParamWhereClauses(Implementation impl) {
- Contract.Requires(impl != null);
- Contract.Requires(impl.Proc != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- TokenTextWriter debugWriter = null;
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
- debugWriter.WriteLine("Effective precondition from where-clauses:");
- }
-
- Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
- List<Cmd> whereClauses = new List<Cmd>();
-
- // where clauses of in-parameters
- foreach (Formal f in impl.Proc.InParams) {
- Contract.Assert(f != null);
- if (f.TypedIdent.WhereExpr != null) {
- Expr e = Substituter.Apply(formalProcImplSubst, f.TypedIdent.WhereExpr);
- Cmd c = new AssumeCmd(f.tok, e);
- whereClauses.Add(c);
-
- if (debugWriter != null) {
- c.Emit(debugWriter, 1);
- }
- }
- }
-
- // where clauses of out-parameters
- Contract.Assert(impl.OutParams.Count == impl.Proc.OutParams.Count);
- for (int i = 0; i < impl.OutParams.Count; i++) {
- Variable f = cce.NonNull(impl.Proc.OutParams[i]);
- if (f.TypedIdent.WhereExpr != null) {
- Expr e = Substituter.Apply(formalProcImplSubst, f.TypedIdent.WhereExpr);
- Cmd c = new AssumeCmd(f.tok, e);
- whereClauses.Add(c);
-
- Variable fi = cce.NonNull(impl.OutParams[i]);
- Contract.Assume(fi.TypedIdent.WhereExpr == null);
- fi.TypedIdent.WhereExpr = e;
-
- if (debugWriter != null) {
- c.Emit(debugWriter, 1);
- }
- }
- }
-
- if (debugWriter != null) {
- debugWriter.WriteLine();
- }
-
- return whereClauses;
- }
-
- protected static void RestoreParamWhereClauses(Implementation impl) {
- Contract.Requires(impl != null);
- // We no longer need the where clauses on the out parameters, so we remove them to restore the situation from before VC generation
- foreach (Formal f in impl.OutParams) {
- Contract.Assert(f != null);
- f.TypedIdent.WhereExpr = null;
- }
- }
- #endregion
-
-
- protected Checker FindCheckerFor(int timeout, bool isBlocking = true)
- {
- Contract.Ensures(!isBlocking || Contract.Result<Checker>() != null);
-
- var maxRetries = 3;
- lock (checkers)
- {
- retry:
- // Look for existing checker.
- for (int i = 0; i < checkers.Count; i++)
- {
- var c = checkers[i];
- if (Monitor.TryEnter(c))
- {
- try
- {
- if (c.WillingToHandle(timeout, program))
- {
- c.GetReady();
- return c;
- }
- else if (c.IsIdle || c.IsClosed)
- {
- if (c.IsIdle)
- {
- c.Retarget(program, c.TheoremProver.Context, timeout);
- c.GetReady();
- return c;
- }
- else
- {
- checkers.RemoveAt(i);
- }
- }
- }
- finally
- {
- Monitor.Exit(c);
- }
- }
- }
-
- if (Cores <= checkers.Count)
- {
- if (isBlocking || 0 < maxRetries)
- {
- Monitor.Wait(checkers, 50);
- maxRetries--;
- goto retry;
- }
- else
- {
- return null;
- }
- }
-
- // Create a new checker.
- string log = logFilePath;
- if (log != null && !log.Contains("@PROC@") && checkers.Count > 0)
- {
- log = log + "." + checkers.Count;
- }
- Checker ch = new Checker(this, program, log, appendLogFile, timeout);
- ch.GetReady();
- checkers.Add(ch);
- return ch;
- }
- }
-
-
- virtual public void Close() {
- }
-
-
- public class CounterexampleCollector : VerifierCallback {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(examples));
- }
-
- public string RequestId;
-
- public readonly List<Counterexample>/*!>!*/ examples = new List<Counterexample>();
- public override void OnCounterexample(Counterexample ce, string/*?*/ reason) {
- //Contract.Requires(ce != null);
- if (RequestId != null)
- {
- ce.RequestId = RequestId;
- }
- if (ce.OriginalRequestId == null && 1 < CommandLineOptions.Clo.VerifySnapshots)
- {
- ce.OriginalRequestId = RequestId;
- }
- examples.Add(ce);
- }
-
- public override void OnUnreachableCode(Implementation impl) {
- //Contract.Requires(impl != null);
- System.Console.WriteLine("found unreachable code:");
- EmitImpl(impl, false);
- // TODO report error about next to last in seq
- }
- }
-
- protected static void EmitImpl(Implementation impl, bool printDesugarings) {
- Contract.Requires(impl != null);
- int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
- CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
- bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
- CommandLineOptions.Clo.PrintDesugarings = printDesugarings;
- impl.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false), 0);
- CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
- CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
- }
-
-
- protected Block GenerateUnifiedExit(Implementation impl, Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins) {
- Contract.Requires(impl != null);
- Contract.Requires(gotoCmdOrigins != null);
- Contract.Ensures(Contract.Result<Block>() != null);
-
- Contract.Ensures(Contract.Result<Block>().TransferCmd is ReturnCmd);
- Block/*?*/ exitBlock = null;
- #region Create a unified exit block, if there's more than one
- {
- int returnBlocks = 0;
- foreach (Block b in impl.Blocks) {
- if (b.TransferCmd is ReturnCmd) {
- exitBlock = b;
- returnBlocks++;
- }
- }
- if (returnBlocks > 1) {
- string unifiedExitLabel = "GeneratedUnifiedExit";
- Block unifiedExit = new Block(new Token(-17, -4), unifiedExitLabel, new List<Cmd>(), new ReturnCmd(Token.NoToken));
- Contract.Assert(unifiedExit != null);
- foreach (Block b in impl.Blocks) {
- if (b.TransferCmd is ReturnCmd) {
- List<String> labels = new List<String>();
- labels.Add(unifiedExitLabel);
- List<Block> bs = new List<Block>();
- bs.Add(unifiedExit);
- GotoCmd go = new GotoCmd(Token.NoToken, labels, bs);
- gotoCmdOrigins[go] = (ReturnCmd)b.TransferCmd;
- b.TransferCmd = go;
- unifiedExit.Predecessors.Add(b);
- }
- }
-
- exitBlock = unifiedExit;
- impl.Blocks.Add(unifiedExit);
- }
- Contract.Assert(exitBlock != null);
- }
- return exitBlock;
- #endregion
- }
-
- protected static void ResetPredecessors(List<Block> blocks) {
- Contract.Requires(blocks != null);
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- b.Predecessors = new List<Block>();
- }
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- foreach (Block ch in Exits(b)) {
- Contract.Assert(ch != null);
- ch.Predecessors.Add(b);
- }
- }
- }
-
- protected static IEnumerable Exits(Block b) {
- Contract.Requires(b != null);
- GotoCmd g = b.TransferCmd as GotoCmd;
- if (g != null) {
- return cce.NonNull(g.labelTargets);
- }
- return new List<Block>();
- }
-
- protected Variable CreateIncarnation(Variable x, Absy a) {
- Contract.Requires(this.variable2SequenceNumber != null);
- Contract.Requires(this.CurrentLocalVariables != null);
- Contract.Requires(a is Block || a is AssignCmd || a is HavocCmd);
-
- Contract.Requires(x != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
-
- int currentIncarnationNumber =
- variable2SequenceNumber.ContainsKey(x)
- ?
- variable2SequenceNumber[x]
- :
- -1;
- Variable v = new Incarnation(x, currentIncarnationNumber + 1);
- variable2SequenceNumber[x] = currentIncarnationNumber + 1;
- CurrentLocalVariables.Add(v);
- incarnationOriginMap.Add((Incarnation)v, a);
- return v;
- }
-
- /// <summary>
- /// Compute the incarnation map at the beginning of block "b" from the incarnation blocks of the
- /// predecessors of "b".
- ///
- /// The predecessor map b.map for block "b" is defined as follows:
- /// b.map.Domain == Union{Block p in b.predecessors; p.map.Domain}
- /// Forall{Variable v in b.map.Domain;
- /// b.map[v] == (v in Intersection{Block p in b.predecessors; p.map}.Domain
- /// ? b.predecessors[0].map[v]
- /// : new Variable())}
- /// Every variable that b.map maps to a fresh variable requires a fixup in all predecessor blocks.
- /// </summary>
- /// <param name="b"></param>
- /// <param name="block2Incarnation">Gives incarnation maps for b's predecessors.</param>
- /// <returns></returns>
- protected Dictionary<Variable, Expr> ComputeIncarnationMap(Block b, Dictionary<Block, Dictionary<Variable, Expr>> block2Incarnation) {
- Contract.Requires(b != null);
- Contract.Requires(block2Incarnation != null);
- Contract.Ensures(Contract.Result<Dictionary<Variable, Expr>>() != null);
-
- if (b.Predecessors.Count == 0) {
- return new Dictionary<Variable, Expr>();
- }
-
- Dictionary<Variable, Expr> incarnationMap = null;
- Set /*Variable*/ fixUps = new Set /*Variable*/ ();
- foreach (Block pred in b.Predecessors) {
- Contract.Assert(pred != null);
- Contract.Assert(block2Incarnation.ContainsKey(pred)); // otherwise, Passive Transformation found a block whose predecessors have not been processed yet
- Dictionary<Variable, Expr> predMap = (Dictionary<Variable, Expr>)block2Incarnation[pred];
- Contract.Assert(predMap != null);
- if (incarnationMap == null) {
- incarnationMap = new Dictionary<Variable, Expr>(predMap);
- continue;
- }
-
- ArrayList /*Variable*/ conflicts = new ArrayList /*Variable*/ ();
- foreach (Variable v in incarnationMap.Keys) {
- Contract.Assert(v != null);
- if (!predMap.ContainsKey(v)) {
- // conflict!!
- conflicts.Add(v);
- fixUps.Add(v);
- }
- }
- // Now that we're done with enumeration, we'll do all the removes
- foreach (Variable v in conflicts) {
- Contract.Assert(v != null);
- incarnationMap.Remove(v);
- }
- foreach (Variable v in predMap.Keys) {
- Contract.Assert(v != null);
- if (!incarnationMap.ContainsKey(v)) {
- // v was not in the domain of the predecessors seen so far, so it needs to be fixed up
- fixUps.Add(v);
- } else {
- // v in incarnationMap ==> all pred blocks (up to now) all agree on its incarnation
- if (predMap[v] != incarnationMap[v]) {
- // conflict!!
- incarnationMap.Remove(v);
- fixUps.Add(v);
- }
- }
- }
- }
-
- #region Second, for all variables in the fixups list, introduce a new incarnation and push it back into the preds.
- foreach (Variable v in fixUps) {
- Contract.Assert(v != null);
- if (!b.IsLive(v))
- continue;
- Variable v_prime = CreateIncarnation(v, b);
- IdentifierExpr ie = new IdentifierExpr(v_prime.tok, v_prime);
- Contract.Assert(incarnationMap != null);
- incarnationMap[v] = ie;
- foreach (Block pred in b.Predecessors) {
- Contract.Assert(pred != null);
- #region Create an assume command equating v_prime with its last incarnation in pred
- #region Create an identifier expression for the last incarnation in pred
- Dictionary<Variable, Expr> predMap = (Dictionary<Variable, Expr>)cce.NonNull(block2Incarnation[pred]);
-
- Expr pred_incarnation_exp;
- Expr o = predMap.ContainsKey(v) ? predMap[v] : null;
- if (o == null) {
- Variable predIncarnation = v;
- IdentifierExpr ie2 = new IdentifierExpr(predIncarnation.tok, predIncarnation);
- pred_incarnation_exp = ie2;
- } else {
- pred_incarnation_exp = o;
- }
- #endregion
- #region Create an identifier expression for the new incarnation
- IdentifierExpr v_prime_exp = new IdentifierExpr(v_prime.tok, v_prime);
- #endregion
- #region Create the assume command itself
- AssumeCmd ac = new AssumeCmd(v.tok, TypedExprEq(v_prime_exp, pred_incarnation_exp, v_prime.Name.Contains("a##post##")));
- pred.Cmds.Add(ac);
- #endregion
- #endregion
- }
- }
- #endregion
-
- Contract.Assert(incarnationMap != null);
- return incarnationMap;
- }
-
- Dictionary<Variable, Expr> preHavocIncarnationMap = null; // null = the previous command was not an HashCmd. Otherwise, a *copy* of the map before the havoc statement
-
- protected void TurnIntoPassiveBlock(Block b, Dictionary<Variable, Expr> incarnationMap, ModelViewInfo mvInfo, Substitution oldFrameSubst, MutableVariableCollector variableCollector, byte[] currentChecksum = null) {
- Contract.Requires(b != null);
- Contract.Requires(incarnationMap != null);
- Contract.Requires(mvInfo != null);
- Contract.Requires(oldFrameSubst != null);
- #region Walk forward over the commands in this block and convert them to passive commands
-
- List<Cmd> passiveCmds = new List<Cmd>();
- foreach (Cmd c in b.Cmds) {
- Contract.Assert(c != null); // walk forward over the commands because the map gets modified in a forward direction
- ChecksumHelper.ComputeChecksums(c, currentImplementation, variableCollector.UsedVariables, currentChecksum);
- variableCollector.Visit(c);
- currentChecksum = c.Checksum;
- TurnIntoPassiveCmd(c, incarnationMap, oldFrameSubst, passiveCmds, mvInfo, b);
- }
- b.Checksum = currentChecksum;
- b.Cmds = passiveCmds;
-
- if (b.TransferCmd is ReturnExprCmd) {
- ReturnExprCmd rec = (ReturnExprCmd)b.TransferCmd.Clone();
- Substitution incarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
- rec.Expr = Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, rec.Expr);
- b.TransferCmd = rec;
- }
- #endregion
- }
-
- protected Dictionary<Variable, Expr> Convert2PassiveCmd(Implementation impl, ModelViewInfo mvInfo) {
- Contract.Requires(impl != null);
- Contract.Requires(mvInfo != null);
-
- currentImplementation = impl;
-
- var start = DateTime.UtcNow;
-
- Dictionary<Variable, Expr> r = ConvertBlocks2PassiveCmd(impl.Blocks, impl.Proc.Modifies, mvInfo);
-
- var end = DateTime.UtcNow;
-
- if (CommandLineOptions.Clo.TraceCachingForDebugging)
- {
- Console.Out.WriteLine("Turned implementation into passive commands within {0:F0} ms.\n", end.Subtract(start).TotalMilliseconds);
- }
-
- if (CommandLineOptions.Clo.TraceCachingForDebugging)
- {
- using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
- {
- var pd = CommandLineOptions.Clo.PrintDesugarings;
- var pu = CommandLineOptions.Clo.PrintUnstructured;
- CommandLineOptions.Clo.PrintDesugarings = true;
- CommandLineOptions.Clo.PrintUnstructured = 1;
- impl.Emit(tokTxtWr, 0);
- CommandLineOptions.Clo.PrintDesugarings = pd;
- CommandLineOptions.Clo.PrintUnstructured = pu;
- }
- }
-
- currentImplementation = null;
-
- RestoreParamWhereClauses(impl);
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify) {
- Console.WriteLine("after conversion to passive commands");
- EmitImpl(impl, true);
- }
- #endregion
-
- return r;
- }
-
- protected Dictionary<Variable, Expr> ConvertBlocks2PassiveCmd(List<Block> blocks, List<IdentifierExpr> modifies, ModelViewInfo mvInfo) {
- Contract.Requires(blocks != null);
- Contract.Requires(modifies != null);
- Contract.Requires(mvInfo != null);
- #region Convert to Passive Commands
-
- #region Topological sort -- need to process in a linearization of the partial order
- Graph<Block> dag = new Graph<Block>();
- dag.AddSource(cce.NonNull(blocks[0])); // there is always at least one node in the graph
- foreach (Block b in blocks) {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- Contract.Assume(gtc.labelTargets != null);
- foreach (Block dest in gtc.labelTargets) {
- Contract.Assert(dest != null);
- dag.AddEdge(b, dest);
- }
- }
- }
-
- IEnumerable sortedNodes;
- if (CommandLineOptions.Clo.ModifyTopologicalSorting) {
- sortedNodes = dag.TopologicalSort(true);
- } else {
- sortedNodes = dag.TopologicalSort();
- }
-
- Contract.Assert(sortedNodes != null);
- #endregion
-
- Substitution oldFrameSubst = ComputeOldExpressionSubstitution(modifies);
-
- // Now we can process the nodes in an order so that we're guaranteed to have
- // processed all of a node's predecessors before we process the node.
- Dictionary<Block, Dictionary<Variable, Expr>> block2Incarnation = new Dictionary<Block, Dictionary<Variable, Expr>>();
- Block exitBlock = null;
- Dictionary<Variable, Expr> exitIncarnationMap = null;
- var variableCollectors = new Dictionary<Block, MutableVariableCollector>();
- foreach (Block b in sortedNodes) {
- Contract.Assert(b != null);
- Contract.Assert(!block2Incarnation.ContainsKey(b));
- Dictionary<Variable, Expr> incarnationMap = ComputeIncarnationMap(b, block2Incarnation);
-
- // b.liveVarsBefore has served its purpose in the just-finished call to ComputeIncarnationMap; null it out.
- b.liveVarsBefore = null;
-
- // Decrement the succCount field in each predecessor. Once the field reaches zero in any block,
- // all its successors have been passified. Consequently, its entry in block2Incarnation can be removed.
- byte[] currentChecksum = null;
- var mvc = new MutableVariableCollector();
- variableCollectors[b] = mvc;
- foreach (Block p in b.Predecessors) {
- p.succCount--;
- if (p.Checksum != null)
- {
- // Compute the checksum based on the checksums of the predecessor. The order should not matter.
- currentChecksum = ChecksumHelper.CombineChecksums(p.Checksum, currentChecksum, true);
- }
- mvc.AddUsedVariables(variableCollectors[p].UsedVariables);
- if (p.succCount == 0)
- block2Incarnation.Remove(p);
- }
-
- #region Each block's map needs to be available to successor blocks
- GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
- if (gotoCmd == null) {
- b.succCount = 0;
- }
- else {
- // incarnationMap needs to be added only if there is some successor of b
- b.succCount = gotoCmd.labelNames.Count;
- block2Incarnation.Add(b, incarnationMap);
- }
- #endregion Each block's map needs to be available to successor blocks
-
- TurnIntoPassiveBlock(b, incarnationMap, mvInfo, oldFrameSubst, mvc, currentChecksum);
- exitBlock = b;
- exitIncarnationMap = incarnationMap;
- }
-
- variableCollectors.Clear();
-
- // Verify that exitBlock is indeed the unique exit block
- Contract.Assert(exitBlock != null);
- Contract.Assert(exitBlock.TransferCmd is ReturnCmd);
- #endregion Convert to Passive Commands
-
- return exitIncarnationMap;
- }
-
- /// <summary>
- /// Compute the substitution for old expressions.
- /// </summary>
- protected static Substitution ComputeOldExpressionSubstitution(List<IdentifierExpr> modifies)
- {
- Dictionary<Variable, Expr> oldFrameMap = new Dictionary<Variable, Expr>();
- foreach (IdentifierExpr ie in modifies)
- {
- Contract.Assert(ie != null);
- if (!oldFrameMap.ContainsKey(cce.NonNull(ie.Decl)))
- oldFrameMap.Add(ie.Decl, ie);
- }
- return Substituter.SubstitutionFromHashtable(oldFrameMap);
- }
-
- public enum CachingAction : byte
- {
- DoNothingToAssert,
- MarkAsPartiallyVerified,
- MarkAsFullyVerified,
- RecycleError,
- AssumeNegationOfAssumptionVariable,
- DropAssume
- }
-
- public long[] CachingActionCounts;
-
- void TraceCachingAction(Cmd cmd, CachingAction action)
- {
- if (CommandLineOptions.Clo.TraceCachingForTesting)
- {
- using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
- {
- var loc = cmd.tok != null && cmd.tok != Token.NoToken ? string.Format("{0}({1},{2})", cmd.tok.filename, cmd.tok.line, cmd.tok.col) : "<unknown location>";
- Console.Write("Processing command (at {0}) ", loc);
- cmd.Emit(tokTxtWr, 0);
- Console.Out.WriteLine(" >>> {0}", action);
- }
- }
-
- if (CommandLineOptions.Clo.TraceCachingForBenchmarking && CachingActionCounts != null)
- {
- Interlocked.Increment(ref CachingActionCounts[(int)action]);
- }
- }
-
- /// <summary>
- /// Turn a command into a passive command, and it remembers the previous step, to see if it is a havoc or not. In the case, it remembers the incarnation map BEFORE the havoc
- /// Meanwhile, record any information needed to later reconstruct a model view.
- /// </summary>
- protected void TurnIntoPassiveCmd(Cmd c, Dictionary<Variable, Expr> incarnationMap, Substitution oldFrameSubst, List<Cmd> passiveCmds, ModelViewInfo mvInfo, Block containingBlock) {
- Contract.Requires(c != null);
- Contract.Requires(incarnationMap != null);
- Contract.Requires(oldFrameSubst != null);
- Contract.Requires(passiveCmds != null);
- Contract.Requires(mvInfo != null);
- Contract.Requires(containingBlock != null);
-
- Substitution incarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
- #region assert/assume P |--> assert/assume P[x := in(x)], out := in
- if (c is PredicateCmd) {
- Contract.Assert(c is AssertCmd || c is AssumeCmd); // otherwise, unexpected PredicateCmd type
-
- PredicateCmd pc = (PredicateCmd)c.Clone();
- Contract.Assert(pc != null);
-
- Expr copy = Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, pc.Expr);
- if (CommandLineOptions.Clo.ModelViewFile != null && pc is AssumeCmd) {
- string description = QKeyValue.FindStringAttribute(pc.Attributes, "captureState");
- if (description != null) {
- Expr mv = new NAryExpr(pc.tok, new FunctionCall(ModelViewInfo.MVState_FunctionDef), new List<Expr> { Bpl.Expr.Ident(ModelViewInfo.MVState_ConstantDef), Bpl.Expr.Literal(mvInfo.CapturePoints.Count) });
- copy = Bpl.Expr.And(mv, copy);
- mvInfo.CapturePoints.Add(new ModelViewInfo.Mapping(description, new Dictionary<Variable, Expr>(incarnationMap)));
- }
- }
- Contract.Assert(copy != null);
- var dropCmd = false;
- var relevantAssumpVars = currentImplementation != null ? currentImplementation.RelevantInjectedAssumptionVariables(incarnationMap) : new List<LocalVariable>();
- var relevantDoomedAssumpVars = currentImplementation != null ? currentImplementation.RelevantDoomedInjectedAssumptionVariables(incarnationMap) : new List<LocalVariable>();
- var checksum = pc.Checksum;
- if (pc is AssertCmd) {
- var ac = (AssertCmd)pc;
- ac.OrigExpr = ac.Expr;
- Contract.Assert(ac.IncarnationMap == null);
- ac.IncarnationMap = (Dictionary<Variable, Expr>)cce.NonNull(new Dictionary<Variable, Expr>(incarnationMap));
-
- var subsumption = Wlp.Subsumption(ac);
- if (relevantDoomedAssumpVars.Any())
- {
- TraceCachingAction(pc, CachingAction.DoNothingToAssert);
- }
- else if (currentImplementation != null
- && currentImplementation.HasCachedSnapshot
- && checksum != null
- && currentImplementation.IsAssertionChecksumInCachedSnapshot(checksum)
- && !currentImplementation.IsErrorChecksumInCachedSnapshot(checksum))
- {
- if (!currentImplementation.AnyErrorsInCachedSnapshot
- && currentImplementation.InjectedAssumptionVariables.Count == 1
- && relevantAssumpVars.Count == 1)
- {
- TraceCachingAction(pc, CachingAction.MarkAsPartiallyVerified);
- }
- else
- {
- bool isTrue;
- var assmVars = currentImplementation.ConjunctionOfInjectedAssumptionVariables(incarnationMap, out isTrue);
- TraceCachingAction(pc, !isTrue ? CachingAction.MarkAsPartiallyVerified : CachingAction.MarkAsFullyVerified);
- var litExpr = ac.Expr as LiteralExpr;
- if (litExpr == null || !litExpr.IsTrue)
- {
- ac.MarkAsVerifiedUnder(assmVars);
- }
- else
- {
- dropCmd = true;
- }
- }
- }
- else if (currentImplementation != null
- && currentImplementation.HasCachedSnapshot
- && relevantAssumpVars.Count == 0
- && checksum != null
- && currentImplementation.IsAssertionChecksumInCachedSnapshot(checksum)
- && currentImplementation.IsErrorChecksumInCachedSnapshot(checksum))
- {
- TraceCachingAction(pc, CachingAction.RecycleError);
- ac.MarkAsVerifiedUnder(Expr.True);
- currentImplementation.AddRecycledFailingAssertion(ac);
- pc.Attributes = new QKeyValue(Token.NoToken, "recycled_failing_assertion", new List<object>(), pc.Attributes);
- }
- else
- {
- TraceCachingAction(pc, CachingAction.DoNothingToAssert);
- }
- }
- else if (pc is AssumeCmd
- && QKeyValue.FindBoolAttribute(pc.Attributes, "precondition_previous_snapshot")
- && pc.SugaredCmdChecksum != null)
- {
- if (!relevantDoomedAssumpVars.Any()
- && currentImplementation.HasCachedSnapshot
- && currentImplementation.IsAssertionChecksumInCachedSnapshot(pc.SugaredCmdChecksum)
- && !currentImplementation.IsErrorChecksumInCachedSnapshot(pc.SugaredCmdChecksum))
- {
- bool isTrue;
- var assmVars = currentImplementation.ConjunctionOfInjectedAssumptionVariables(incarnationMap, out isTrue);
- if (!isTrue)
- {
- copy = LiteralExpr.Imp(assmVars, copy);
- TraceCachingAction(pc, CachingAction.MarkAsPartiallyVerified);
- }
- else
- {
- TraceCachingAction(pc, CachingAction.MarkAsFullyVerified);
- }
- }
- else
- {
- TraceCachingAction(pc, CachingAction.DropAssume);
- dropCmd = true;
- }
- }
- else if (pc is AssumeCmd && QKeyValue.FindBoolAttribute(pc.Attributes, "assumption_variable_initialization"))
- {
- var identExpr = pc.Expr as IdentifierExpr;
- if (identExpr != null && identExpr.Decl != null && !incarnationMap.ContainsKey(identExpr.Decl))
- {
- incarnationMap[identExpr.Decl] = LiteralExpr.True;
- dropCmd = true;
- }
- }
- pc.Expr = copy;
- if (!dropCmd)
- {
- passiveCmds.Add(pc);
- }
- }
- #endregion
- #region x1 := E1, x2 := E2, ... |--> assume x1' = E1[in] & x2' = E2[in], out := in( x |-> x' ) [except as noted below]
- else if (c is AssignCmd) {
- AssignCmd assign = ((AssignCmd)c).AsSimpleAssignCmd; // first remove map assignments
- Contract.Assert(assign != null);
- #region Substitute all variables in E with the current map
- List<Expr> copies = new List<Expr>();
- foreach (Expr e in assign.Rhss) {
- Contract.Assert(e != null);
- copies.Add(Substituter.ApplyReplacingOldExprs(incarnationSubst,
- oldFrameSubst,
- e));
- }
- #endregion
-
- List<Expr/*!>!*/> assumptions = new List<Expr>();
- // it might be too slow to create a new dictionary each time ...
- IDictionary<Variable, Expr> newIncarnationMappings =
- new Dictionary<Variable, Expr>();
-
- for (int i = 0; i < assign.Lhss.Count; ++i) {
- IdentifierExpr lhsIdExpr =
- cce.NonNull((SimpleAssignLhs)assign.Lhss[i]).AssignedVariable;
- Variable lhs = cce.NonNull(lhsIdExpr.Decl);
- Contract.Assert(lhs != null);
- Expr rhs = assign.Rhss[i];
- Contract.Assert(rhs != null);
-
- // don't create incarnations for assignments of literals or single variables.
- if (rhs is LiteralExpr) {
- incarnationMap[lhs] = rhs;
- } else if (rhs is IdentifierExpr) {
- IdentifierExpr ie = (IdentifierExpr)rhs;
- if (incarnationMap.ContainsKey(cce.NonNull(ie.Decl)))
- newIncarnationMappings[lhs] = cce.NonNull((Expr)incarnationMap[ie.Decl]);
- else
- newIncarnationMappings[lhs] = ie;
- } else {
- IdentifierExpr x_prime_exp = null;
- #region Make a new incarnation, x', for variable x, but only if x is *not* already an incarnation
- if (lhs is Incarnation) {
- // incarnations are already written only once, no need to make an incarnation of an incarnation
- x_prime_exp = lhsIdExpr;
- } else {
- Variable v = CreateIncarnation(lhs, c);
- x_prime_exp = new IdentifierExpr(lhsIdExpr.tok, v);
- newIncarnationMappings[lhs] = x_prime_exp;
- }
- #endregion
-
- var nAryExpr = copies[i] as NAryExpr;
- if (nAryExpr != null)
- {
- var binOp = nAryExpr.Fun as BinaryOperator;
- if (binOp != null
- && binOp.Op == BinaryOperator.Opcode.And)
- {
- var arg0 = nAryExpr.Args[0] as LiteralExpr;
- var arg1 = nAryExpr.Args[1] as LiteralExpr;
- if ((arg0 != null && arg0.IsTrue) || (arg1 != null && arg1.IsFalse))
- {
- // Replace the expressions "true && arg1" or "arg0 && false" by "arg1".
- copies[i] = nAryExpr.Args[1];
- }
- }
- }
-
- #region Create an assume command with the new variable
- assumptions.Add(TypedExprEq(x_prime_exp, copies[i], x_prime_exp.Decl != null && x_prime_exp.Decl.Name.Contains("a##post##")));
- #endregion
- }
- }
-
- foreach (KeyValuePair<Variable, Expr> pair in newIncarnationMappings) {
- Contract.Assert(pair.Key != null && pair.Value != null);
- incarnationMap[pair.Key] = pair.Value;
- }
-
- if (assumptions.Count > 0) {
- Expr assumption = assumptions[0];
-
- for (int i = 1; i < assumptions.Count; ++i) {
- Contract.Assert(assumption != null);
- assumption = Expr.And(assumption, assumptions[i]);
- }
- passiveCmds.Add(new AssumeCmd(c.tok, assumption));
- }
-
- if (currentImplementation != null
- && currentImplementation.HasCachedSnapshot
- && !currentImplementation.AnyErrorsInCachedSnapshot
- && currentImplementation.InjectedAssumptionVariables.Count == 1
- && assign.Lhss.Count == 1)
- {
- var identExpr = assign.Lhss[0].AsExpr as IdentifierExpr;
- Expr incarnation;
- if (identExpr != null && identExpr.Decl != null && QKeyValue.FindBoolAttribute(identExpr.Decl.Attributes, "assumption") && incarnationMap.TryGetValue(identExpr.Decl, out incarnation))
- {
- TraceCachingAction(assign, CachingAction.AssumeNegationOfAssumptionVariable);
- passiveCmds.Add(new AssumeCmd(c.tok, Expr.Not(incarnation)));
- }
- }
- }
- #endregion
- #region havoc w |--> assume whereClauses, out := in( w |-> w' )
- else if (c is HavocCmd) {
- if (this.preHavocIncarnationMap == null) // Save a copy of the incarnation map (at the top of a sequence of havoc statements)
- this.preHavocIncarnationMap = new Dictionary<Variable, Expr>(incarnationMap);
-
- HavocCmd hc = (HavocCmd)c;
- Contract.Assert(c != null);
- // If an assumption variable for postconditions is included here, it must have been assigned within a loop.
- // We do not need to havoc it if we have performed a modular proof of the loop (i.e., using only the loop
- // invariant) in the previous snapshot and are therefore not going refer to the assumption variable after
- // the loop. We can achieve this by simply not updating/adding it in the incarnation map.
- List<IdentifierExpr> havocVars = hc.Vars.Where(v => !(QKeyValue.FindBoolAttribute(v.Decl.Attributes, "assumption") && v.Decl.Name.StartsWith("a##post##"))).ToList();
- // First, compute the new incarnations
- foreach (IdentifierExpr ie in havocVars) {
- Contract.Assert(ie != null);
- if (!(ie.Decl is Incarnation)) {
- Variable x = cce.NonNull(ie.Decl);
- Variable x_prime = CreateIncarnation(x, c);
- incarnationMap[x] = new IdentifierExpr(x_prime.tok, x_prime);
- }
- }
- // Then, perform the assume of the where clauses, using the updated incarnations
- Substitution updatedIncarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
- foreach (IdentifierExpr ie in havocVars) {
- Contract.Assert(ie != null);
- if (!(ie.Decl is Incarnation)) {
- Variable x = cce.NonNull(ie.Decl);
- Bpl.Expr w = x.TypedIdent.WhereExpr;
- if (w != null) {
- Expr copy = Substituter.ApplyReplacingOldExprs(updatedIncarnationSubst, oldFrameSubst, w);
- passiveCmds.Add(new AssumeCmd(c.tok, copy));
- }
- }
- }
- }
- #endregion
- else if (c is CommentCmd) {
- // comments are just for debugging and don't affect verification
- } else if (c is SugaredCmd) {
- SugaredCmd sug = (SugaredCmd)c;
- Contract.Assert(sug != null);
- Cmd cmd = sug.Desugaring;
- Contract.Assert(cmd != null);
- TurnIntoPassiveCmd(cmd, incarnationMap, oldFrameSubst, passiveCmds, mvInfo, containingBlock);
- } else if (c is StateCmd) {
- this.preHavocIncarnationMap = null; // we do not need to remeber the previous incarnations
- StateCmd st = (StateCmd)c;
- Contract.Assert(st != null);
- // account for any where clauses among the local variables
- foreach (Variable v in st.Locals) {
- Contract.Assert(v != null);
- Expr w = v.TypedIdent.WhereExpr;
- if (w != null) {
- passiveCmds.Add(new AssumeCmd(v.tok, w));
- }
- }
- // do the sub-commands
- foreach (Cmd s in st.Cmds) {
- Contract.Assert(s != null);
- TurnIntoPassiveCmd(s, incarnationMap, oldFrameSubst, passiveCmds, mvInfo, containingBlock);
- }
- // remove the local variables from the incarnation map
- foreach (Variable v in st.Locals) {
- Contract.Assert(v != null);
- incarnationMap.Remove(v);
- }
- }
- #region There shouldn't be any other types of commands at this point
- else {
- Debug.Fail("Internal Error: Passive transformation handed a command that is not one of assert,assume,havoc,assign.");
- }
- #endregion
-
-
- #region We remember if we have put an havoc statement into a passive form
-
- if (!(c is HavocCmd))
- this.preHavocIncarnationMap = null;
- // else: it has already been set by the case for the HavocCmd
- #endregion
- }
-
- NAryExpr TypedExprEq(Expr e0, Expr e1, bool doNotResolveOverloading = false) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- NAryExpr e = Expr.Eq(e0, e1);
- var fun = e.Fun as IOverloadedAppliable;
- if (fun != null)
- {
- fun.DoNotResolveOverloading = doNotResolveOverloading;
- }
- e.Type = Bpl.Type.Bool;
- e.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- return e;
- }
-
- /// <summary>
- /// Creates a new block to add to impl.Blocks, where impl is the implementation that contains
- /// succ. Caller must do the add to impl.Blocks.
- /// </summary>
- protected Block CreateBlockBetween(int predIndex, Block succ) {
- Contract.Requires(0 <= predIndex && predIndex < succ.Predecessors.Count);
-
-
- Contract.Requires(succ != null);
- Contract.Ensures(Contract.Result<Block>() != null);
-
- Block pred = cce.NonNull(succ.Predecessors[predIndex]);
-
- string newBlockLabel = pred.Label + "_@2_" + succ.Label;
-
- // successor of newBlock list
- List<String> ls = new List<String>();
- ls.Add(succ.Label);
- List<Block> bs = new List<Block>();
- bs.Add(succ);
-
- Block newBlock = new Block(
- new Token(-17, -4),
- newBlockLabel,
- new List<Cmd>(),
- new GotoCmd(Token.NoToken, ls, bs)
- );
-
- // predecessors of newBlock
- List<Block> ps = new List<Block>();
- ps.Add(pred);
- newBlock.Predecessors = ps;
-
- // fix successors of pred
- #region Change the edge "pred->succ" to "pred->newBlock"
- GotoCmd gtc = (GotoCmd)cce.NonNull(pred.TransferCmd);
- Contract.Assume(gtc.labelTargets != null);
- Contract.Assume(gtc.labelNames != null);
- for (int i = 0, n = gtc.labelTargets.Count; i < n; i++) {
- if (gtc.labelTargets[i] == succ) {
- gtc.labelTargets[i] = newBlock;
- gtc.labelNames[i] = newBlockLabel;
- break;
- }
- }
- #endregion Change the edge "pred->succ" to "pred->newBlock"
-
- // fix predecessors of succ
- succ.Predecessors[predIndex] = newBlock;
-
- return newBlock;
- }
-
- protected void AddBlocksBetween(List<Block> blocks) {
- Contract.Requires(blocks != null);
- #region Introduce empty blocks between join points and their multi-successor predecessors
- List<Block> tweens = new List<Block>();
- foreach (Block b in blocks) {
- int nPreds = b.Predecessors.Count;
- if (nPreds > 1) {
- // b is a join point (i.e., it has more than one predecessor)
- for (int i = 0; i < nPreds; i++) {
- GotoCmd gotocmd = (GotoCmd)(cce.NonNull(b.Predecessors[i]).TransferCmd);
- if (gotocmd.labelNames != null && gotocmd.labelNames.Count > 1) {
- tweens.Add(CreateBlockBetween(i, b));
- }
- }
- }
- }
- blocks.AddRange(tweens); // must wait until iteration is done before changing the list
- #endregion
- }
-
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposed)
- {
- if (disposing)
- {
- Close();
- }
- _disposed = true;
- }
- }
-
- public int Cores { get; set; }
- }
-
- public class ModelViewInfo
- {
- public readonly List<Variable> AllVariables = new List<Variable>();
- public readonly List<Mapping> CapturePoints = new List<Mapping>();
- public static readonly Function MVState_FunctionDef = new Function(Token.NoToken, "$mv_state",
- new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, TypedIdent.NoName, Bpl.Type.Int), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, TypedIdent.NoName, Bpl.Type.Int), true) },
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, TypedIdent.NoName, Bpl.Type.Bool), false));
- public static readonly Constant MVState_ConstantDef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "$mv_state_const", Bpl.Type.Int));
-
- public ModelViewInfo(Program program, Implementation impl) {
- Contract.Requires(program != null);
- Contract.Requires(impl != null);
-
- // global variables
- lock (program.TopLevelDeclarations)
- {
- foreach (var v in program.Variables)
- {
- if (!(v is Constant))
- {
- AllVariables.Add(v);
- }
- }
- }
- // implementation parameters
- foreach (Variable p in impl.InParams) {
- AllVariables.Add(p);
- }
- foreach (Variable p in impl.OutParams) {
- AllVariables.Add(p);
- }
- // implementation locals
- foreach (Variable v in impl.LocVars) {
- AllVariables.Add(v);
- }
- }
-
- public ModelViewInfo(CodeExpr codeExpr) {
- Contract.Requires(codeExpr != null);
- // TODO: also need all variables of enclosing scopes (the global variables of the program, the parameters
- // and perhaps locals of the implementation (if any), any enclosing code expressions).
-
- foreach (Variable v in codeExpr.LocVars) {
- AllVariables.Add(v);
- }
- }
-
- public class Mapping
- {
- public readonly string Description;
- public readonly Dictionary<Variable, Expr> IncarnationMap;
- public Mapping(string description, Dictionary<Variable, Expr> incarnationMap) {
- Description = description;
- IncarnationMap = incarnationMap;
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+using Set = Microsoft.Boogie.GSet<object>;
+
+namespace Microsoft.Boogie {
+
+ public class CalleeCounterexampleInfo {
+ public Counterexample counterexample;
+ public List<object>/*!>!*/ args;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(args));
+ }
+
+ public CalleeCounterexampleInfo(Counterexample cex, List<object/*!>!*/> x)
+ {
+ Contract.Requires(cce.NonNullElements(x));
+ counterexample = cex;
+ args = x;
+ }
+ }
+
+ public class TraceLocation : IEquatable<TraceLocation>
+ {
+ public int numBlock;
+ public int numInstr;
+
+ public TraceLocation(int numBlock, int numInstr)
+ {
+ this.numBlock = numBlock;
+ this.numInstr = numInstr;
+ }
+
+ public override bool Equals(object obj)
+ {
+ TraceLocation that = obj as TraceLocation;
+ if (that == null) return false;
+ return (numBlock == that.numBlock && numInstr == that.numInstr);
+ }
+
+ public bool Equals(TraceLocation that)
+ {
+ return (numBlock == that.numBlock && numInstr == that.numInstr);
+ }
+
+ public override int GetHashCode()
+ {
+ return numBlock.GetHashCode() ^ 131 * numInstr.GetHashCode();
+ }
+ }
+
+ public abstract class Counterexample {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Trace != null);
+ Contract.Invariant(Context != null);
+ Contract.Invariant(cce.NonNullElements(relatedInformation));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(calleeCounterexamples));
+ }
+
+ [Peer]
+ public List<Block> Trace;
+ public Model Model;
+ public VC.ModelViewInfo MvInfo;
+ public ProverContext Context;
+ [Peer]
+ public List<string>/*!>!*/ relatedInformation;
+ public string OriginalRequestId;
+ public string RequestId;
+ public abstract byte[] Checksum { get; }
+ public byte[] SugaredCmdChecksum;
+ public bool IsAuxiliaryCexForDiagnosingTimeouts;
+
+ public Dictionary<TraceLocation, CalleeCounterexampleInfo> calleeCounterexamples;
+
+ internal Counterexample(List<Block> trace, Model model, VC.ModelViewInfo mvInfo, ProverContext context) {
+ Contract.Requires(trace != null);
+ Contract.Requires(context != null);
+ this.Trace = trace;
+ this.Model = model;
+ this.MvInfo = mvInfo;
+ this.Context = context;
+ this.relatedInformation = new List<string>();
+ this.calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
+ }
+
+ // Create a shallow copy of the counterexample
+ public abstract Counterexample Clone();
+
+ public void AddCalleeCounterexample(TraceLocation loc, CalleeCounterexampleInfo cex)
+ {
+ Contract.Requires(cex != null);
+ calleeCounterexamples[loc] = cex;
+ }
+
+ public void AddCalleeCounterexample(int numBlock, int numInstr, CalleeCounterexampleInfo cex)
+ {
+ Contract.Requires(cex != null);
+ calleeCounterexamples[new TraceLocation(numBlock, numInstr)] = cex;
+ }
+
+ public void AddCalleeCounterexample(Dictionary<TraceLocation, CalleeCounterexampleInfo> cs)
+ {
+ Contract.Requires(cce.NonNullDictionaryAndValues(cs));
+ foreach (TraceLocation loc in cs.Keys)
+ {
+ AddCalleeCounterexample(loc, cs[loc]);
+ }
+ }
+
+ // Looks up the Cmd at a given index into the trace
+ public Cmd getTraceCmd(TraceLocation loc)
+ {
+ Debug.Assert(loc.numBlock < Trace.Count);
+ Block b = Trace[loc.numBlock];
+ Debug.Assert(loc.numInstr < b.Cmds.Count);
+ return b.Cmds[loc.numInstr];
+ }
+
+ // Looks up the name of the called procedure.
+ // Asserts that the name exists
+ public string getCalledProcName(Cmd cmd)
+ {
+ // There are two options:
+ // 1. cmd is a CallCmd
+ // 2. cmd is an AssumeCmd (passified version of a CallCmd)
+ if(cmd is CallCmd) {
+ return (cmd as CallCmd).Proc.Name;
+ }
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ Debug.Assert(assumeCmd != null);
+
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ Debug.Assert(naryExpr != null);
+
+ return naryExpr.Fun.FunctionName;
+ }
+
+ public void Print(int indent, TextWriter tw, Action<Block> blockAction = null) {
+ int numBlock = -1;
+ string ind = new string(' ', indent);
+ foreach (Block b in Trace) {
+ Contract.Assert(b != null);
+ numBlock++;
+ if (b.tok == null) {
+ tw.WriteLine("{0}<intermediate block>", ind);
+ } else {
+ // for ErrorTrace == 1 restrict the output;
+ // do not print tokens with -17:-4 as their location because they have been
+ // introduced in the translation and do not give any useful feedback to the user
+ if (!(CommandLineOptions.Clo.ErrorTrace == 1 && b.tok.line == -17 && b.tok.col == -4)) {
+ if (blockAction != null)
+ {
+ blockAction(b);
+ }
+
+ tw.WriteLine("{4}{0}({1},{2}): {3}", b.tok.filename, b.tok.line, b.tok.col, b.Label, ind);
+
+ for (int numInstr = 0; numInstr < b.Cmds.Count; numInstr++)
+ {
+ var loc = new TraceLocation(numBlock, numInstr);
+ if (calleeCounterexamples.ContainsKey(loc))
+ {
+ var cmd = getTraceCmd(loc);
+ var calleeName = getCalledProcName(cmd);
+ if (calleeName.StartsWith(VC.StratifiedVCGen.recordProcName) && CommandLineOptions.Clo.StratifiedInlining > 0)
+ {
+ Contract.Assert(calleeCounterexamples[loc].args.Count == 1);
+ var arg = calleeCounterexamples[loc].args[0];
+ tw.WriteLine("{0}value = {1}", ind, arg.ToString());
+ }
+ else
+ {
+ tw.WriteLine("{1}Inlined call to procedure {0} begins", calleeName, ind);
+ calleeCounterexamples[loc].counterexample.Print(indent + 4, tw);
+ tw.WriteLine("{1}Inlined call to procedure {0} ends", calleeName, ind);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static bool firstModelFile = true;
+
+ public bool ModelHasStatesAlready = false;
+
+ public void PrintModel(TextWriter tw)
+ {
+ var filename = CommandLineOptions.Clo.ModelViewFile;
+ if (Model == null || filename == null || CommandLineOptions.Clo.StratifiedInlining > 0) return;
+
+ if (!ModelHasStatesAlready) {
+ PopulateModelWithStates();
+ ModelHasStatesAlready = true;
+ }
+
+ if (filename == "-") {
+ Model.Write(tw);
+ tw.Flush();
+ } else {
+ using (var wr = new StreamWriter(filename, !firstModelFile)) {
+ firstModelFile = false;
+ Model.Write(wr);
+ }
+ }
+ }
+
+ void ApplyRedirections(Model m) {
+ var mapping = new Dictionary<Model.Element, Model.Element>();
+ foreach (var name in new string[] { "U_2_bool", "U_2_int" }) {
+ Model.Func f = m.TryGetFunc(name);
+ if (f != null && f.Arity == 1) {
+ foreach (var ft in f.Apps) mapping[ft.Args[0]] = ft.Result;
+ }
+ }
+ m.Substitute(mapping);
+ }
+
+ public void PopulateModelWithStates()
+ {
+ Contract.Requires(Model != null);
+
+ Model m = Model;
+ ApplyRedirections(m);
+
+ var mvstates = m.TryGetFunc("$mv_state");
+ if (MvInfo == null || mvstates == null || (mvstates.Arity == 1 && mvstates.Apps.Count() == 0))
+ return;
+
+ Contract.Assert(mvstates.Arity == 2);
+
+ foreach (Variable v in MvInfo.AllVariables) {
+ m.InitialState.AddBinding(v.Name, GetModelValue(m, v));
+ }
+
+ var states = new List<int>();
+ foreach (var t in mvstates.Apps)
+ states.Add(t.Args[1].AsInt());
+
+ states.Sort();
+
+ for (int i = 0; i < states.Count; ++i) {
+ var s = states[i];
+ if (0 <= s && s < MvInfo.CapturePoints.Count) {
+ VC.ModelViewInfo.Mapping map = MvInfo.CapturePoints[s];
+ var prevInc = i > 0 ? MvInfo.CapturePoints[states[i - 1]].IncarnationMap : new Dictionary<Variable, Expr>();
+ var cs = m.MkState(map.Description);
+
+ foreach (Variable v in MvInfo.AllVariables) {
+ Expr e = map.IncarnationMap.ContainsKey(v) ? map.IncarnationMap[v] : null;
+ if (e == null) continue;
+
+ Expr prevIncV = prevInc.ContainsKey(v) ? prevInc[v] : null;
+ if (prevIncV == e) continue; // skip unchanged variables
+
+ Model.Element elt;
+
+ if (e is IdentifierExpr) {
+ IdentifierExpr ide = (IdentifierExpr)e;
+ elt = GetModelValue(m, ide.Decl);
+ } else if (e is LiteralExpr) {
+ LiteralExpr lit = (LiteralExpr)e;
+ elt = m.MkElement(lit.Val.ToString());
+ } else {
+ elt = m.MkFunc(e.ToString(), 0).GetConstant();
+ }
+
+ cs.AddBinding(v.Name, elt);
+ }
+
+ } else {
+ Contract.Assume(false);
+ }
+ }
+ }
+
+ private Model.Element GetModelValue(Model m, Variable v) {
+ Model.Element elt;
+ // first, get the unique name
+ string uniqueName;
+ VCExprVar vvar = Context.BoogieExprTranslator.TryLookupVariable(v);
+ if (vvar == null) {
+ uniqueName = v.Name;
+ } else {
+ uniqueName = Context.Lookup(vvar);
+ }
+
+ var f = m.TryGetFunc(uniqueName);
+ if (f == null) {
+ f = m.MkFunc(uniqueName, 0);
+ }
+ elt = f.GetConstant();
+ return elt;
+ }
+
+ public abstract int GetLocation();
+ }
+
+ public class CounterexampleComparer : IComparer<Counterexample>, IEqualityComparer<Counterexample> {
+
+ private int Compare(List<Block> bs1, List<Block> bs2)
+ {
+ if (bs1.Count < bs2.Count)
+ {
+ return -1;
+ }
+ else if (bs2.Count < bs1.Count)
+ {
+ return 1;
+ }
+
+ for (int i = 0; i < bs1.Count; i++)
+ {
+ var b1 = bs1[i];
+ var b2 = bs2[i];
+ if (b1.tok.pos < b2.tok.pos)
+ {
+ return -1;
+ }
+ else if (b2.tok.pos < b1.tok.pos)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ public int Compare(Counterexample c1, Counterexample c2)
+ {
+ //Contract.Requires(c1 != null);
+ //Contract.Requires(c2 != null);
+ if (c1.GetLocation() == c2.GetLocation())
+ {
+ var c = Compare(c1.Trace, c2.Trace);
+ if (c != 0)
+ {
+ return c;
+ }
+ // TODO(wuestholz): Generalize this to compare all IPotentialErrorNodes of the counterexample.
+ var a1 = c1 as AssertCounterexample;
+ var a2 = c2 as AssertCounterexample;
+ if (a1 != null && a2 != null)
+ {
+ var s1 = a1.FailingAssert.ErrorData as string;
+ var s2 = a2.FailingAssert.ErrorData as string;
+ if (s1 != null && s2 != null)
+ {
+ return s1.CompareTo(s2);
+ }
+ }
+
+ return 0;
+ }
+ if (c1.GetLocation() > c2.GetLocation())
+ {
+ return 1;
+ }
+ return -1;
+ }
+
+ public bool Equals(Counterexample x, Counterexample y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(Counterexample obj)
+ {
+ return 0;
+ }
+ }
+
+ public class AssertCounterexample : Counterexample {
+ [Peer]
+ public AssertCmd FailingAssert;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FailingAssert != null);
+ }
+
+
+ public AssertCounterexample(List<Block> trace, AssertCmd failingAssert, Model model, VC.ModelViewInfo mvInfo, ProverContext context)
+ : base(trace, model, mvInfo, context) {
+ Contract.Requires(trace != null);
+ Contract.Requires(failingAssert != null);
+ Contract.Requires(context != null);
+ this.FailingAssert = failingAssert;
+ }
+
+ public override int GetLocation() {
+ return FailingAssert.tok.line * 1000 + FailingAssert.tok.col;
+ }
+
+ public override byte[] Checksum
+ {
+ get { return FailingAssert.Checksum; }
+ }
+
+ public override Counterexample Clone()
+ {
+ var ret = new AssertCounterexample(Trace, FailingAssert, Model, MvInfo, Context);
+ ret.calleeCounterexamples = calleeCounterexamples;
+ return ret;
+ }
+ }
+
+ public class CallCounterexample : Counterexample {
+ public CallCmd FailingCall;
+ public Requires FailingRequires;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FailingCall != null);
+ Contract.Invariant(FailingRequires != null);
+ }
+
+
+ public CallCounterexample(List<Block> trace, CallCmd failingCall, Requires failingRequires, Model model, VC.ModelViewInfo mvInfo, ProverContext context, byte[] checksum = null)
+ : base(trace, model, mvInfo, context) {
+ Contract.Requires(!failingRequires.Free);
+ Contract.Requires(trace != null);
+ Contract.Requires(context != null);
+ Contract.Requires(failingCall != null);
+ Contract.Requires(failingRequires != null);
+ this.FailingCall = failingCall;
+ this.FailingRequires = failingRequires;
+ this.checksum = checksum;
+ this.SugaredCmdChecksum = failingCall.Checksum;
+ }
+
+ public override int GetLocation() {
+ return FailingCall.tok.line * 1000 + FailingCall.tok.col;
+ }
+
+ byte[] checksum;
+ public override byte[] Checksum
+ {
+ get { return checksum; }
+ }
+
+ public override Counterexample Clone()
+ {
+ var ret = new CallCounterexample(Trace, FailingCall, FailingRequires, Model, MvInfo, Context, Checksum);
+ ret.calleeCounterexamples = calleeCounterexamples;
+ return ret;
+ }
+ }
+
+ public class ReturnCounterexample : Counterexample {
+ public TransferCmd FailingReturn;
+ public Ensures FailingEnsures;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FailingEnsures != null);
+ Contract.Invariant(FailingReturn != null);
+ }
+
+
+ public ReturnCounterexample(List<Block> trace, TransferCmd failingReturn, Ensures failingEnsures, Model model, VC.ModelViewInfo mvInfo, ProverContext context, byte[] checksum)
+ : base(trace, model, mvInfo, context) {
+ Contract.Requires(trace != null);
+ Contract.Requires(context != null);
+ Contract.Requires(failingReturn != null);
+ Contract.Requires(failingEnsures != null);
+ Contract.Requires(!failingEnsures.Free);
+ this.FailingReturn = failingReturn;
+ this.FailingEnsures = failingEnsures;
+ this.checksum = checksum;
+ }
+
+ public override int GetLocation() {
+ return FailingReturn.tok.line * 1000 + FailingReturn.tok.col;
+ }
+
+ byte[] checksum;
+
+ /// <summary>
+ /// Returns the checksum of the corresponding assertion.
+ /// </summary>
+ public override byte[] Checksum
+ {
+ get
+ {
+ return checksum;
+ }
+ }
+
+ public override Counterexample Clone()
+ {
+ var ret = new ReturnCounterexample(Trace, FailingReturn, FailingEnsures, Model, MvInfo, Context, checksum);
+ ret.calleeCounterexamples = calleeCounterexamples;
+ return ret;
+ }
+ }
+
+ public class VerifierCallback {
+ // reason == null means this is genuine counterexample returned by the prover
+ // other reason means it's time out/memory out/crash
+ public virtual void OnCounterexample(Counterexample ce, string/*?*/ reason) {
+ Contract.Requires(ce != null);
+ }
+
+ // called in case resource is exceeded and we don't have counterexample
+ public virtual void OnTimeout(string reason) {
+ Contract.Requires(reason != null);
+ }
+
+ public virtual void OnOutOfMemory(string reason) {
+ Contract.Requires(reason != null);
+ }
+
+ public virtual void OnProgress(string phase, int step, int totalSteps, double progressEstimate) {
+ }
+
+ public virtual void OnUnreachableCode(Implementation impl) {
+ Contract.Requires(impl != null);
+ }
+
+ public virtual void OnWarning(string msg) {
+ Contract.Requires(msg != null);
+ switch (CommandLineOptions.Clo.PrintProverWarnings) {
+ case CommandLineOptions.ProverWarnings.None:
+ break;
+ case CommandLineOptions.ProverWarnings.Stdout:
+ Console.WriteLine("Prover warning: " + msg);
+ break;
+ case CommandLineOptions.ProverWarnings.Stderr:
+ Console.Error.WriteLine("Prover warning: " + msg);
+ break;
+ default:
+ Contract.Assume(false);
+ throw new cce.UnreachableException(); // unexpected case
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////
+
+namespace VC {
+ using Bpl = Microsoft.Boogie;
+
+ public class VCGenException : Exception {
+ public VCGenException(string s)
+ : base(s) {
+ }
+ }
+ [ContractClassFor(typeof(ConditionGeneration))]
+ public abstract class ConditionGenerationContracts : ConditionGeneration {
+ public override Outcome VerifyImplementation(Implementation impl, VerifierCallback callback) {
+ Contract.Requires(impl != null);
+ Contract.Requires(callback != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ throw new NotImplementedException();
+ }
+ public ConditionGenerationContracts(Program p, List<Checker> checkers)
+ : base(p, checkers) {
+ }
+ }
+
+ [ContractClass(typeof(ConditionGenerationContracts))]
+ public abstract class ConditionGeneration : IDisposable {
+ protected internal object CheckerCommonState;
+
+ public enum Outcome {
+ Correct,
+ Errors,
+ TimedOut,
+ OutOfMemory,
+ Inconclusive,
+ ReachedBound
+ }
+
+ public static Outcome ProverInterfaceOutcomeToConditionGenerationOutcome(ProverInterface.Outcome outcome) {
+ switch (outcome) {
+ case ProverInterface.Outcome.Invalid:
+ return Outcome.Errors;
+ case ProverInterface.Outcome.OutOfMemory:
+ return Outcome.OutOfMemory;
+ case ProverInterface.Outcome.TimeOut:
+ return Outcome.TimedOut;
+ case ProverInterface.Outcome.Undetermined:
+ return Outcome.Inconclusive;
+ case ProverInterface.Outcome.Valid:
+ return Outcome.Correct;
+ }
+ return Outcome.Inconclusive; // unreachable but the stupid compiler does not understand
+ }
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(checkers));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(incarnationOriginMap));
+ Contract.Invariant(program != null);
+ }
+
+ public int CumulativeAssertionCount; // for statistics
+
+ protected readonly List<Checker>/*!>!*/ checkers;
+
+ private bool _disposed;
+
+ protected Implementation currentImplementation;
+
+ protected List<Variable> CurrentLocalVariables = null;
+
+ // shared across each implementation; created anew for each implementation
+ protected Dictionary<Variable, int> variable2SequenceNumber;
+ public Dictionary<Incarnation, Absy>/*!>!*/ incarnationOriginMap = new Dictionary<Incarnation, Absy>();
+
+ public Program program;
+ protected string/*?*/ logFilePath;
+ protected bool appendLogFile;
+
+ public static List<Model> errorModelList;
+
+ public ConditionGeneration(Program p, List<Checker> checkers) {
+ Contract.Requires(p != null && checkers != null && cce.NonNullElements(checkers));
+ program = p;
+ this.checkers = checkers;
+ Cores = 1;
+ }
+
+ /// <summary>
+ /// Takes an implementation and constructs a verification condition and sends
+ /// it to the theorem prover.
+ /// Returns null if "impl" is correct. Otherwise, returns a list of counterexamples,
+ /// each counterexample consisting of an array of labels.
+ /// </summary>
+ /// <param name="impl"></param>
+ public Outcome VerifyImplementation(Implementation impl, out List<Counterexample>/*?*/ errors, string requestId = null) {
+ Contract.Requires(impl != null);
+
+ Contract.Ensures(Contract.ValueAtReturn(out errors) == null || Contract.ForAll(Contract.ValueAtReturn(out errors), i => i != null));
+ Contract.Ensures(Contract.Result<Outcome>() != Outcome.Errors || errors != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ Helpers.ExtraTraceInformation("Starting implementation verification");
+
+ CounterexampleCollector collector = new CounterexampleCollector();
+ collector.RequestId = requestId;
+ Outcome outcome = VerifyImplementation(impl, collector);
+ if (outcome == Outcome.Errors || outcome == Outcome.TimedOut || outcome == Outcome.OutOfMemory) {
+ errors = collector.examples;
+ } else {
+ errors = null;
+ }
+
+ Helpers.ExtraTraceInformation("Finished implementation verification");
+ return outcome;
+ }
+
+ /// <summary>
+ /// Takes an implementation and constructs a verification condition and sends
+ /// it to the theorem prover.
+ /// Returns null if "impl" is correct. Otherwise, returns a list of counterexamples,
+ /// each counterexample consisting of an array of labels.
+ /// </summary>
+ /// <param name="impl"></param>
+ public Outcome VerifyImplementation(Implementation impl, out List<Counterexample> errors, out List<Model> errorsModel)
+ {
+ Contract.Ensures(Contract.Result<Outcome>() != Outcome.Errors || Contract.ValueAtReturn(out errors) != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ List<Counterexample> errorsOut;
+
+ Outcome outcome;
+ errorModelList = new List<Model>();
+ outcome = VerifyImplementation(impl, out errorsOut);
+ errors = errorsOut;
+ errorsModel = errorModelList;
+
+ return outcome;
+ }
+
+ public abstract Outcome VerifyImplementation(Implementation impl, VerifierCallback callback);
+
+ /////////////////////////////////// Common Methods and Classes //////////////////////////////////////////
+
+ #region Methods for injecting pre- and postconditions
+ private static void
+ ThreadInCodeExpr(Implementation impl,
+ Block targetBlock,
+ CodeExpr codeExpr,
+ bool replaceWithAssert,
+ TokenTextWriter debugWriter) {
+ Contract.Requires(impl != null);
+ Contract.Requires(codeExpr != null);
+ Contract.Requires(targetBlock != null);
+ // Go through codeExpr and for all blocks that have a "return e"
+ // as their transfer command:
+ // Replace all "return e" with "assert/assume e"
+ // Change the transfer command to "goto targetBlock"
+ // Then add all of the blocks in codeExpr to the implementation (at the end)
+ foreach (Block b in codeExpr.Blocks) {
+ Contract.Assert(b != null);
+ ReturnExprCmd rec = b.TransferCmd as ReturnExprCmd;
+ if (rec != null) { // otherwise it is a goto command
+ if (replaceWithAssert) {
+ Ensures ens = new Ensures(rec.tok, false, rec.Expr, null);
+ Contract.Assert(ens != null);
+ Cmd c = new AssertEnsuresCmd(ens);
+ Contract.Assert(c != null);
+ b.Cmds.Add(c);
+ } else {
+ b.Cmds.Add(new AssumeCmd(rec.tok, rec.Expr));
+ }
+ b.TransferCmd = new GotoCmd(Token.NoToken,
+ new List<String> { targetBlock.Label },
+ new List<Block> { targetBlock });
+ targetBlock.Predecessors.Add(b);
+ }
+ impl.Blocks.Add(b);
+ }
+ if (debugWriter != null) {
+ codeExpr.Emit(debugWriter, 1, false);
+ }
+ return;
+ }
+
+ private static void AddAsPrefix(Block b, List<Cmd> cs) {
+ Contract.Requires(b != null);
+ Contract.Requires(cs != null);
+ List<Cmd> newCommands = new List<Cmd>();
+ newCommands.AddRange(cs);
+ newCommands.AddRange(b.Cmds);
+ b.Cmds = newCommands;
+ }
+
+
+ /// <summary>
+ /// Modifies an implementation by prepending it with startCmds and then, as assume
+ /// statements, all preconditions. Insert new blocks as needed, and adjust impl.Blocks[0]
+ /// accordingly to make it the new implementation entry block.
+ /// </summary>
+ /// <param name="impl"></param>
+ /// <param name="startCmds"></param>
+ protected static void InjectPreconditions(Implementation impl, [Captured] List<Cmd> startCmds) {
+ Contract.Requires(impl != null);
+ Contract.Requires(startCmds != null);
+ Contract.Requires(impl.Proc != null);
+
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
+ debugWriter.WriteLine("Effective precondition:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ string blockLabel = "PreconditionGeneratedEntry";
+
+ Block origStartBlock = impl.Blocks[0];
+ Block insertionPoint = new Block(
+ new Token(-17, -4), blockLabel, startCmds,
+ new GotoCmd(Token.NoToken, new List<String> { origStartBlock.Label }, new List<Block> { origStartBlock }));
+
+ impl.Blocks[0] = insertionPoint; // make insertionPoint the start block
+ impl.Blocks.Add(origStartBlock); // and put the previous start block at the end of the list
+
+ // (free and checked) requires clauses
+ foreach (Requires req in impl.Proc.Requires)
+ // invariant: insertionPoint.TransferCmd is "goto origStartBlock;", but origStartBlock.Predecessors has not yet been updated
+ {
+ Contract.Assert(req != null);
+ Expr e = Substituter.Apply(formalProcImplSubst, req.Condition);
+ Cmd c = new AssumeCmd(req.tok, e);
+ c.IrrelevantForChecksumComputation = true;
+ insertionPoint.Cmds.Add(c);
+ if (debugWriter != null) {
+ c.Emit(debugWriter, 1);
+ }
+ }
+ origStartBlock.Predecessors.Add(insertionPoint);
+
+ if (impl.ExplicitAssumptionAboutCachedPrecondition != null)
+ {
+ insertionPoint.Cmds.Add(impl.ExplicitAssumptionAboutCachedPrecondition);
+ }
+
+ if (debugWriter != null) {
+ debugWriter.WriteLine();
+ }
+ }
+ /// <summary>
+ /// Modifies an implementation by inserting all postconditions
+ /// as assert statements at the end of the implementation
+ /// Returns the possibly-new unified exit block of the implementation
+ /// </summary>
+ /// <param name="impl"></param>
+ /// <param name="unifiedExitblock">The unified exit block that has
+ /// already been constructed for the implementation (and so
+ /// is already an element of impl.Blocks)
+ /// </param>
+ protected static void InjectPostConditions(Implementation impl, Block unifiedExitBlock, Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins) {
+ Contract.Requires(impl != null);
+ Contract.Requires(unifiedExitBlock != null);
+ Contract.Requires(gotoCmdOrigins != null);
+ Contract.Requires(impl.Proc != null);
+ Contract.Requires(unifiedExitBlock.TransferCmd is ReturnCmd);
+
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
+ debugWriter.WriteLine("Effective postcondition:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+
+ // (free and checked) ensures clauses
+ foreach (Ensures ens in impl.Proc.Ensures) {
+ Contract.Assert(ens != null);
+ if (!ens.Free) { // skip free ensures clauses
+ Expr e = Substituter.Apply(formalProcImplSubst, ens.Condition);
+ Ensures ensCopy = (Ensures)cce.NonNull(ens.Clone());
+ ensCopy.Condition = e;
+ AssertEnsuresCmd c = new AssertEnsuresCmd(ensCopy);
+ c.ErrorDataEnhanced = ensCopy.ErrorDataEnhanced;
+ unifiedExitBlock.Cmds.Add(c);
+ if (debugWriter != null) {
+ c.Emit(debugWriter, 1);
+ }
+ }
+ }
+
+ if (debugWriter != null) {
+ debugWriter.WriteLine();
+ }
+ }
+
+
+ /// <summary>
+ /// Get the pre-condition of an implementation, including the where clauses from the in-parameters.
+ /// </summary>
+ /// <param name="impl"></param>
+ protected static List<Cmd> GetPre(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+
+
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
+ debugWriter.WriteLine("Effective precondition:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ List<Cmd> pre = new List<Cmd>();
+
+ // (free and checked) requires clauses
+ foreach (Requires req in impl.Proc.Requires) {
+ Contract.Assert(req != null);
+ Expr e = Substituter.Apply(formalProcImplSubst, req.Condition);
+ Contract.Assert(e != null);
+ Cmd c = new AssumeCmd(req.tok, e);
+ Contract.Assert(c != null);
+ pre.Add(c);
+
+ if (debugWriter != null) {
+ c.Emit(debugWriter, 1);
+ }
+ }
+
+ if (debugWriter != null) {
+ debugWriter.WriteLine();
+ }
+
+ return pre;
+ }
+
+ /// <summary>
+ /// Get the post-condition of an implementation.
+ /// </summary>
+ /// <param name="impl"></param>
+ protected static List<Cmd> GetPost(Implementation impl) {
+
+
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ Console.WriteLine("Effective postcondition:");
+ }
+
+ // Construct an Expr for the post-condition
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ List<Cmd> post = new List<Cmd>();
+ foreach (Ensures ens in impl.Proc.Ensures) {
+ Contract.Assert(ens != null);
+ if (!ens.Free) {
+ Expr e = Substituter.Apply(formalProcImplSubst, ens.Condition);
+ Contract.Assert(e != null);
+ Ensures ensCopy = cce.NonNull((Ensures)ens.Clone());
+ ensCopy.Condition = e;
+ Cmd c = new AssertEnsuresCmd(ensCopy);
+ ((AssertEnsuresCmd)c).ErrorDataEnhanced = ensCopy.ErrorDataEnhanced;
+ post.Add(c);
+
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ c.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false), 1);
+ }
+ }
+ }
+
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ Console.WriteLine();
+ }
+
+ return post;
+ }
+
+ /// <summary>
+ /// Get the where clauses from the in- and out-parameters as
+ /// a sequence of assume commands.
+ /// As a side effect, this method adds these where clauses to the out parameters.
+ /// </summary>
+ /// <param name="impl"></param>
+ protected static List<Cmd> GetParamWhereClauses(Implementation impl) {
+ Contract.Requires(impl != null);
+ Contract.Requires(impl.Proc != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+ TokenTextWriter debugWriter = null;
+ if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
+ debugWriter = new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false);
+ debugWriter.WriteLine("Effective precondition from where-clauses:");
+ }
+
+ Substitution formalProcImplSubst = Substituter.SubstitutionFromHashtable(impl.GetImplFormalMap());
+ List<Cmd> whereClauses = new List<Cmd>();
+
+ // where clauses of in-parameters
+ foreach (Formal f in impl.Proc.InParams) {
+ Contract.Assert(f != null);
+ if (f.TypedIdent.WhereExpr != null) {
+ Expr e = Substituter.Apply(formalProcImplSubst, f.TypedIdent.WhereExpr);
+ Cmd c = new AssumeCmd(f.tok, e);
+ whereClauses.Add(c);
+
+ if (debugWriter != null) {
+ c.Emit(debugWriter, 1);
+ }
+ }
+ }
+
+ // where clauses of out-parameters
+ Contract.Assert(impl.OutParams.Count == impl.Proc.OutParams.Count);
+ for (int i = 0; i < impl.OutParams.Count; i++) {
+ Variable f = cce.NonNull(impl.Proc.OutParams[i]);
+ if (f.TypedIdent.WhereExpr != null) {
+ Expr e = Substituter.Apply(formalProcImplSubst, f.TypedIdent.WhereExpr);
+ Cmd c = new AssumeCmd(f.tok, e);
+ whereClauses.Add(c);
+
+ Variable fi = cce.NonNull(impl.OutParams[i]);
+ Contract.Assume(fi.TypedIdent.WhereExpr == null);
+ fi.TypedIdent.WhereExpr = e;
+
+ if (debugWriter != null) {
+ c.Emit(debugWriter, 1);
+ }
+ }
+ }
+
+ if (debugWriter != null) {
+ debugWriter.WriteLine();
+ }
+
+ return whereClauses;
+ }
+
+ protected static void RestoreParamWhereClauses(Implementation impl) {
+ Contract.Requires(impl != null);
+ // We no longer need the where clauses on the out parameters, so we remove them to restore the situation from before VC generation
+ foreach (Formal f in impl.OutParams) {
+ Contract.Assert(f != null);
+ f.TypedIdent.WhereExpr = null;
+ }
+ }
+ #endregion
+
+
+ protected Checker FindCheckerFor(int timeout, bool isBlocking = true, int waitTimeinMs = 50, int maxRetries = 3)
+ {
+ Contract.Requires(0 <= waitTimeinMs && 0 <= maxRetries);
+ Contract.Ensures(!isBlocking || Contract.Result<Checker>() != null);
+
+ lock (checkers)
+ {
+ retry:
+ // Look for existing checker.
+ for (int i = 0; i < checkers.Count; i++)
+ {
+ var c = checkers[i];
+ if (Monitor.TryEnter(c))
+ {
+ try
+ {
+ if (c.WillingToHandle(timeout, program))
+ {
+ c.GetReady();
+ return c;
+ }
+ else if (c.IsIdle || c.IsClosed)
+ {
+ if (c.IsIdle)
+ {
+ c.Retarget(program, c.TheoremProver.Context, timeout);
+ c.GetReady();
+ return c;
+ }
+ else
+ {
+ checkers.RemoveAt(i);
+ i--;
+ continue;
+ }
+ }
+ }
+ finally
+ {
+ Monitor.Exit(c);
+ }
+ }
+ }
+
+ if (Cores <= checkers.Count)
+ {
+ if (isBlocking || 0 < maxRetries)
+ {
+ if (0 < waitTimeinMs)
+ {
+ Monitor.Wait(checkers, waitTimeinMs);
+ }
+ maxRetries--;
+ goto retry;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ // Create a new checker.
+ string log = logFilePath;
+ if (log != null && !log.Contains("@PROC@") && checkers.Count > 0)
+ {
+ log = log + "." + checkers.Count;
+ }
+ Checker ch = new Checker(this, program, log, appendLogFile, timeout);
+ ch.GetReady();
+ checkers.Add(ch);
+ return ch;
+ }
+ }
+
+
+ virtual public void Close() {
+ }
+
+
+ public class CounterexampleCollector : VerifierCallback {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(examples));
+ }
+
+ public string RequestId;
+
+ public readonly List<Counterexample>/*!>!*/ examples = new List<Counterexample>();
+ public override void OnCounterexample(Counterexample ce, string/*?*/ reason) {
+ //Contract.Requires(ce != null);
+ if (RequestId != null)
+ {
+ ce.RequestId = RequestId;
+ }
+ if (ce.OriginalRequestId == null && 1 < CommandLineOptions.Clo.VerifySnapshots)
+ {
+ ce.OriginalRequestId = RequestId;
+ }
+ examples.Add(ce);
+ }
+
+ public override void OnUnreachableCode(Implementation impl) {
+ //Contract.Requires(impl != null);
+ System.Console.WriteLine("found unreachable code:");
+ EmitImpl(impl, false);
+ // TODO report error about next to last in seq
+ }
+ }
+
+ protected static void EmitImpl(Implementation impl, bool printDesugarings) {
+ Contract.Requires(impl != null);
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
+ bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
+ CommandLineOptions.Clo.PrintDesugarings = printDesugarings;
+ impl.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false), 0);
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+
+
+ protected Block GenerateUnifiedExit(Implementation impl, Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins) {
+ Contract.Requires(impl != null);
+ Contract.Requires(gotoCmdOrigins != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+
+ Contract.Ensures(Contract.Result<Block>().TransferCmd is ReturnCmd);
+ Block/*?*/ exitBlock = null;
+ #region Create a unified exit block, if there's more than one
+ {
+ int returnBlocks = 0;
+ foreach (Block b in impl.Blocks) {
+ if (b.TransferCmd is ReturnCmd) {
+ exitBlock = b;
+ returnBlocks++;
+ }
+ }
+ if (returnBlocks > 1) {
+ string unifiedExitLabel = "GeneratedUnifiedExit";
+ Block unifiedExit;
+ unifiedExit = new Block(new Token(-17, -4), unifiedExitLabel, new List<Cmd>(), new ReturnCmd(impl.StructuredStmts != null ? impl.StructuredStmts.EndCurly : Token.NoToken));
+ Contract.Assert(unifiedExit != null);
+ foreach (Block b in impl.Blocks) {
+ if (b.TransferCmd is ReturnCmd) {
+ List<String> labels = new List<String>();
+ labels.Add(unifiedExitLabel);
+ List<Block> bs = new List<Block>();
+ bs.Add(unifiedExit);
+ GotoCmd go = new GotoCmd(Token.NoToken, labels, bs);
+ gotoCmdOrigins[go] = (ReturnCmd)b.TransferCmd;
+ b.TransferCmd = go;
+ unifiedExit.Predecessors.Add(b);
+ }
+ }
+
+ exitBlock = unifiedExit;
+ impl.Blocks.Add(unifiedExit);
+ }
+ Contract.Assert(exitBlock != null);
+ }
+ return exitBlock;
+ #endregion
+ }
+
+ protected static void ResetPredecessors(List<Block> blocks) {
+ Contract.Requires(blocks != null);
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ b.Predecessors = new List<Block>();
+ }
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ foreach (Block ch in Exits(b)) {
+ Contract.Assert(ch != null);
+ ch.Predecessors.Add(b);
+ }
+ }
+ }
+
+ protected static IEnumerable Exits(Block b) {
+ Contract.Requires(b != null);
+ GotoCmd g = b.TransferCmd as GotoCmd;
+ if (g != null) {
+ return cce.NonNull(g.labelTargets);
+ }
+ return new List<Block>();
+ }
+
+ protected Variable CreateIncarnation(Variable x, Absy a) {
+ Contract.Requires(this.variable2SequenceNumber != null);
+ Contract.Requires(this.CurrentLocalVariables != null);
+ Contract.Requires(a is Block || a is AssignCmd || a is HavocCmd);
+
+ Contract.Requires(x != null);
+ Contract.Ensures(Contract.Result<Variable>() != null);
+
+ int currentIncarnationNumber =
+ variable2SequenceNumber.ContainsKey(x)
+ ?
+ variable2SequenceNumber[x]
+ :
+ -1;
+ Variable v = new Incarnation(x, currentIncarnationNumber + 1);
+ variable2SequenceNumber[x] = currentIncarnationNumber + 1;
+ CurrentLocalVariables.Add(v);
+ incarnationOriginMap.Add((Incarnation)v, a);
+ return v;
+ }
+
+ /// <summary>
+ /// Compute the incarnation map at the beginning of block "b" from the incarnation blocks of the
+ /// predecessors of "b".
+ ///
+ /// The predecessor map b.map for block "b" is defined as follows:
+ /// b.map.Domain == Union{Block p in b.predecessors; p.map.Domain}
+ /// Forall{Variable v in b.map.Domain;
+ /// b.map[v] == (v in Intersection{Block p in b.predecessors; p.map}.Domain
+ /// ? b.predecessors[0].map[v]
+ /// : new Variable())}
+ /// Every variable that b.map maps to a fresh variable requires a fixup in all predecessor blocks.
+ /// </summary>
+ /// <param name="b"></param>
+ /// <param name="block2Incarnation">Gives incarnation maps for b's predecessors.</param>
+ /// <returns></returns>
+ protected Dictionary<Variable, Expr> ComputeIncarnationMap(Block b, Dictionary<Block, Dictionary<Variable, Expr>> block2Incarnation) {
+ Contract.Requires(b != null);
+ Contract.Requires(block2Incarnation != null);
+ Contract.Ensures(Contract.Result<Dictionary<Variable, Expr>>() != null);
+
+ if (b.Predecessors.Count == 0) {
+ return new Dictionary<Variable, Expr>();
+ }
+
+ Dictionary<Variable, Expr> incarnationMap = null;
+ Set /*Variable*/ fixUps = new Set /*Variable*/ ();
+ foreach (Block pred in b.Predecessors) {
+ Contract.Assert(pred != null);
+ Contract.Assert(block2Incarnation.ContainsKey(pred)); // otherwise, Passive Transformation found a block whose predecessors have not been processed yet
+ Dictionary<Variable, Expr> predMap = (Dictionary<Variable, Expr>)block2Incarnation[pred];
+ Contract.Assert(predMap != null);
+ if (incarnationMap == null) {
+ incarnationMap = new Dictionary<Variable, Expr>(predMap);
+ continue;
+ }
+
+ ArrayList /*Variable*/ conflicts = new ArrayList /*Variable*/ ();
+ foreach (Variable v in incarnationMap.Keys) {
+ Contract.Assert(v != null);
+ if (!predMap.ContainsKey(v)) {
+ // conflict!!
+ conflicts.Add(v);
+ fixUps.Add(v);
+ }
+ }
+ // Now that we're done with enumeration, we'll do all the removes
+ foreach (Variable v in conflicts) {
+ Contract.Assert(v != null);
+ incarnationMap.Remove(v);
+ }
+ foreach (Variable v in predMap.Keys) {
+ Contract.Assert(v != null);
+ if (!incarnationMap.ContainsKey(v)) {
+ // v was not in the domain of the predecessors seen so far, so it needs to be fixed up
+ fixUps.Add(v);
+ } else {
+ // v in incarnationMap ==> all pred blocks (up to now) all agree on its incarnation
+ if (predMap[v] != incarnationMap[v]) {
+ // conflict!!
+ incarnationMap.Remove(v);
+ fixUps.Add(v);
+ }
+ }
+ }
+ }
+
+ #region Second, for all variables in the fixups list, introduce a new incarnation and push it back into the preds.
+ foreach (Variable v in fixUps) {
+ Contract.Assert(v != null);
+ if (!b.IsLive(v))
+ continue;
+ Variable v_prime = CreateIncarnation(v, b);
+ IdentifierExpr ie = new IdentifierExpr(v_prime.tok, v_prime);
+ Contract.Assert(incarnationMap != null);
+ incarnationMap[v] = ie;
+ foreach (Block pred in b.Predecessors) {
+ Contract.Assert(pred != null);
+ #region Create an assume command equating v_prime with its last incarnation in pred
+ #region Create an identifier expression for the last incarnation in pred
+ Dictionary<Variable, Expr> predMap = (Dictionary<Variable, Expr>)cce.NonNull(block2Incarnation[pred]);
+
+ Expr pred_incarnation_exp;
+ Expr o = predMap.ContainsKey(v) ? predMap[v] : null;
+ if (o == null) {
+ Variable predIncarnation = v;
+ IdentifierExpr ie2 = new IdentifierExpr(predIncarnation.tok, predIncarnation);
+ pred_incarnation_exp = ie2;
+ } else {
+ pred_incarnation_exp = o;
+ }
+ #endregion
+ #region Create an identifier expression for the new incarnation
+ IdentifierExpr v_prime_exp = new IdentifierExpr(v_prime.tok, v_prime);
+ #endregion
+ #region Create the assume command itself
+ AssumeCmd ac = new AssumeCmd(v.tok, TypedExprEq(v_prime_exp, pred_incarnation_exp, v_prime.Name.Contains("a##cached##")));
+ pred.Cmds.Add(ac);
+ #endregion
+ #endregion
+ }
+ }
+ #endregion
+
+ Contract.Assert(incarnationMap != null);
+ return incarnationMap;
+ }
+
+ Dictionary<Variable, Expr> preHavocIncarnationMap = null; // null = the previous command was not an HashCmd. Otherwise, a *copy* of the map before the havoc statement
+
+ protected void TurnIntoPassiveBlock(Block b, Dictionary<Variable, Expr> incarnationMap, ModelViewInfo mvInfo, Substitution oldFrameSubst, MutableVariableCollector variableCollector, byte[] currentChecksum = null) {
+ Contract.Requires(b != null);
+ Contract.Requires(incarnationMap != null);
+ Contract.Requires(mvInfo != null);
+ Contract.Requires(oldFrameSubst != null);
+ #region Walk forward over the commands in this block and convert them to passive commands
+
+ List<Cmd> passiveCmds = new List<Cmd>();
+ foreach (Cmd c in b.Cmds) {
+ Contract.Assert(c != null); // walk forward over the commands because the map gets modified in a forward direction
+ ChecksumHelper.ComputeChecksums(c, currentImplementation, variableCollector.UsedVariables, currentChecksum);
+ variableCollector.Visit(c);
+ currentChecksum = c.Checksum;
+ TurnIntoPassiveCmd(c, incarnationMap, oldFrameSubst, passiveCmds, mvInfo, b);
+ }
+ b.Checksum = currentChecksum;
+ b.Cmds = passiveCmds;
+
+ if (b.TransferCmd is ReturnExprCmd) {
+ ReturnExprCmd rec = (ReturnExprCmd)b.TransferCmd.Clone();
+ Substitution incarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
+ rec.Expr = Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, rec.Expr);
+ b.TransferCmd = rec;
+ }
+ #endregion
+ }
+
+ protected Dictionary<Variable, Expr> Convert2PassiveCmd(Implementation impl, ModelViewInfo mvInfo) {
+ Contract.Requires(impl != null);
+ Contract.Requires(mvInfo != null);
+
+ currentImplementation = impl;
+
+ var start = DateTime.UtcNow;
+
+ Dictionary<Variable, Expr> r = ConvertBlocks2PassiveCmd(impl.Blocks, impl.Proc.Modifies, mvInfo);
+
+ var end = DateTime.UtcNow;
+
+ if (CommandLineOptions.Clo.TraceCachingForDebugging)
+ {
+ Console.Out.WriteLine("Turned implementation into passive commands within {0:F0} ms.\n", end.Subtract(start).TotalMilliseconds);
+ }
+
+ if (CommandLineOptions.Clo.TraceCachingForDebugging)
+ {
+ using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
+ {
+ var pd = CommandLineOptions.Clo.PrintDesugarings;
+ var pu = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintDesugarings = true;
+ CommandLineOptions.Clo.PrintUnstructured = 1;
+ impl.Emit(tokTxtWr, 0);
+ CommandLineOptions.Clo.PrintDesugarings = pd;
+ CommandLineOptions.Clo.PrintUnstructured = pu;
+ }
+ }
+
+ currentImplementation = null;
+
+ RestoreParamWhereClauses(impl);
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify) {
+ Console.WriteLine("after conversion to passive commands");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ return r;
+ }
+
+ protected Dictionary<Variable, Expr> ConvertBlocks2PassiveCmd(List<Block> blocks, List<IdentifierExpr> modifies, ModelViewInfo mvInfo) {
+ Contract.Requires(blocks != null);
+ Contract.Requires(modifies != null);
+ Contract.Requires(mvInfo != null);
+ #region Convert to Passive Commands
+
+ #region Topological sort -- need to process in a linearization of the partial order
+ Graph<Block> dag = new Graph<Block>();
+ dag.AddSource(cce.NonNull(blocks[0])); // there is always at least one node in the graph
+ foreach (Block b in blocks) {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null) {
+ Contract.Assume(gtc.labelTargets != null);
+ foreach (Block dest in gtc.labelTargets) {
+ Contract.Assert(dest != null);
+ dag.AddEdge(b, dest);
+ }
+ }
+ }
+
+ IEnumerable sortedNodes;
+ if (CommandLineOptions.Clo.ModifyTopologicalSorting) {
+ sortedNodes = dag.TopologicalSort(true);
+ } else {
+ sortedNodes = dag.TopologicalSort();
+ }
+
+ Contract.Assert(sortedNodes != null);
+ #endregion
+
+ Substitution oldFrameSubst = ComputeOldExpressionSubstitution(modifies);
+
+ // Now we can process the nodes in an order so that we're guaranteed to have
+ // processed all of a node's predecessors before we process the node.
+ Dictionary<Block, Dictionary<Variable, Expr>> block2Incarnation = new Dictionary<Block, Dictionary<Variable, Expr>>();
+ Block exitBlock = null;
+ Dictionary<Variable, Expr> exitIncarnationMap = null;
+ var variableCollectors = new Dictionary<Block, MutableVariableCollector>();
+ foreach (Block b in sortedNodes) {
+ Contract.Assert(b != null);
+ Contract.Assert(!block2Incarnation.ContainsKey(b));
+ Dictionary<Variable, Expr> incarnationMap = ComputeIncarnationMap(b, block2Incarnation);
+
+ // b.liveVarsBefore has served its purpose in the just-finished call to ComputeIncarnationMap; null it out.
+ b.liveVarsBefore = null;
+
+ // Decrement the succCount field in each predecessor. Once the field reaches zero in any block,
+ // all its successors have been passified. Consequently, its entry in block2Incarnation can be removed.
+ byte[] currentChecksum = null;
+ var mvc = new MutableVariableCollector();
+ variableCollectors[b] = mvc;
+ foreach (Block p in b.Predecessors) {
+ p.succCount--;
+ if (p.Checksum != null)
+ {
+ // Compute the checksum based on the checksums of the predecessor. The order should not matter.
+ currentChecksum = ChecksumHelper.CombineChecksums(p.Checksum, currentChecksum, true);
+ }
+ mvc.AddUsedVariables(variableCollectors[p].UsedVariables);
+ if (p.succCount == 0)
+ block2Incarnation.Remove(p);
+ }
+
+ #region Each block's map needs to be available to successor blocks
+ GotoCmd gotoCmd = b.TransferCmd as GotoCmd;
+ if (gotoCmd == null) {
+ b.succCount = 0;
+ }
+ else {
+ // incarnationMap needs to be added only if there is some successor of b
+ b.succCount = gotoCmd.labelNames.Count;
+ block2Incarnation.Add(b, incarnationMap);
+ }
+ #endregion Each block's map needs to be available to successor blocks
+
+ TurnIntoPassiveBlock(b, incarnationMap, mvInfo, oldFrameSubst, mvc, currentChecksum);
+ exitBlock = b;
+ exitIncarnationMap = incarnationMap;
+ }
+
+ variableCollectors.Clear();
+
+ // Verify that exitBlock is indeed the unique exit block
+ Contract.Assert(exitBlock != null);
+ Contract.Assert(exitBlock.TransferCmd is ReturnCmd);
+ #endregion Convert to Passive Commands
+
+ return exitIncarnationMap;
+ }
+
+ /// <summary>
+ /// Compute the substitution for old expressions.
+ /// </summary>
+ protected static Substitution ComputeOldExpressionSubstitution(List<IdentifierExpr> modifies)
+ {
+ Dictionary<Variable, Expr> oldFrameMap = new Dictionary<Variable, Expr>();
+ foreach (IdentifierExpr ie in modifies)
+ {
+ Contract.Assert(ie != null);
+ if (!oldFrameMap.ContainsKey(cce.NonNull(ie.Decl)))
+ oldFrameMap.Add(ie.Decl, ie);
+ }
+ return Substituter.SubstitutionFromHashtable(oldFrameMap);
+ }
+
+ public enum CachingAction : byte
+ {
+ DoNothingToAssert,
+ MarkAsPartiallyVerified,
+ MarkAsFullyVerified,
+ RecycleError,
+ AssumeNegationOfAssumptionVariable,
+ DropAssume
+ }
+
+ public long[] CachingActionCounts;
+
+ void TraceCachingAction(Cmd cmd, CachingAction action)
+ {
+ if (CommandLineOptions.Clo.TraceCachingForTesting)
+ {
+ using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
+ {
+ var loc = cmd.tok != null && cmd.tok != Token.NoToken ? string.Format("{0}({1},{2})", cmd.tok.filename, cmd.tok.line, cmd.tok.col) : "<unknown location>";
+ Console.Write("Processing command (at {0}) ", loc);
+ cmd.Emit(tokTxtWr, 0);
+ Console.Out.WriteLine(" >>> {0}", action);
+ }
+ }
+
+ if (CommandLineOptions.Clo.TraceCachingForBenchmarking && CachingActionCounts != null)
+ {
+ Interlocked.Increment(ref CachingActionCounts[(int)action]);
+ }
+ }
+
+ /// <summary>
+ /// Turn a command into a passive command, and it remembers the previous step, to see if it is a havoc or not. In the case, it remembers the incarnation map BEFORE the havoc
+ /// Meanwhile, record any information needed to later reconstruct a model view.
+ /// </summary>
+ protected void TurnIntoPassiveCmd(Cmd c, Dictionary<Variable, Expr> incarnationMap, Substitution oldFrameSubst, List<Cmd> passiveCmds, ModelViewInfo mvInfo, Block containingBlock) {
+ Contract.Requires(c != null);
+ Contract.Requires(incarnationMap != null);
+ Contract.Requires(oldFrameSubst != null);
+ Contract.Requires(passiveCmds != null);
+ Contract.Requires(mvInfo != null);
+ Contract.Requires(containingBlock != null);
+
+ Substitution incarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
+ #region assert/assume P |--> assert/assume P[x := in(x)], out := in
+ if (c is PredicateCmd) {
+ Contract.Assert(c is AssertCmd || c is AssumeCmd); // otherwise, unexpected PredicateCmd type
+
+ PredicateCmd pc = (PredicateCmd)c.Clone();
+ Contract.Assert(pc != null);
+
+ QKeyValue current = pc.Attributes;
+ while (current != null)
+ {
+ if (current.Key == "minimize" || current.Key == "maximize") {
+ Contract.Assume(current.Params.Count == 1);
+ var param = current.Params[0] as Expr;
+ Contract.Assume(param != null && (param.Type.IsInt || param.Type.IsReal || param.Type.IsBv));
+ current.ClearParams();
+ current.AddParam(Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, param));
+ }
+ if (current.Key == "verified_under") {
+ Contract.Assume(current.Params.Count == 1);
+ var param = current.Params[0] as Expr;
+ Contract.Assume(param != null && param.Type.IsBool);
+ current.ClearParams();
+ current.AddParam(Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, param));
+ }
+ current = current.Next;
+ }
+
+ Expr copy = Substituter.ApplyReplacingOldExprs(incarnationSubst, oldFrameSubst, pc.Expr);
+ if (CommandLineOptions.Clo.ModelViewFile != null && pc is AssumeCmd) {
+ string description = QKeyValue.FindStringAttribute(pc.Attributes, "captureState");
+ if (description != null) {
+ Expr mv = new NAryExpr(pc.tok, new FunctionCall(ModelViewInfo.MVState_FunctionDef), new List<Expr> { Bpl.Expr.Ident(ModelViewInfo.MVState_ConstantDef), Bpl.Expr.Literal(mvInfo.CapturePoints.Count) });
+ copy = Bpl.Expr.And(mv, copy);
+ mvInfo.CapturePoints.Add(new ModelViewInfo.Mapping(description, new Dictionary<Variable, Expr>(incarnationMap)));
+ }
+ }
+ Contract.Assert(copy != null);
+ var dropCmd = false;
+ var relevantAssumpVars = currentImplementation != null ? currentImplementation.RelevantInjectedAssumptionVariables(incarnationMap) : new List<LocalVariable>();
+ var relevantDoomedAssumpVars = currentImplementation != null ? currentImplementation.RelevantDoomedInjectedAssumptionVariables(incarnationMap) : new List<LocalVariable>();
+ var checksum = pc.Checksum;
+ if (pc is AssertCmd) {
+ var ac = (AssertCmd)pc;
+ ac.OrigExpr = ac.Expr;
+ Contract.Assert(ac.IncarnationMap == null);
+ ac.IncarnationMap = (Dictionary<Variable, Expr>)cce.NonNull(new Dictionary<Variable, Expr>(incarnationMap));
+
+ var subsumption = Wlp.Subsumption(ac);
+ if (relevantDoomedAssumpVars.Any())
+ {
+ TraceCachingAction(pc, CachingAction.DoNothingToAssert);
+ }
+ else if (currentImplementation != null
+ && currentImplementation.HasCachedSnapshot
+ && checksum != null
+ && currentImplementation.IsAssertionChecksumInCachedSnapshot(checksum)
+ && !currentImplementation.IsErrorChecksumInCachedSnapshot(checksum))
+ {
+ if (!currentImplementation.AnyErrorsInCachedSnapshot
+ && currentImplementation.InjectedAssumptionVariables.Count == 1
+ && relevantAssumpVars.Count == 1)
+ {
+ TraceCachingAction(pc, CachingAction.MarkAsPartiallyVerified);
+ }
+ else
+ {
+ bool isTrue;
+ var assmVars = currentImplementation.ConjunctionOfInjectedAssumptionVariables(incarnationMap, out isTrue);
+ TraceCachingAction(pc, !isTrue ? CachingAction.MarkAsPartiallyVerified : CachingAction.MarkAsFullyVerified);
+ var litExpr = ac.Expr as LiteralExpr;
+ if (litExpr == null || !litExpr.IsTrue)
+ {
+ ac.MarkAsVerifiedUnder(assmVars);
+ }
+ else
+ {
+ dropCmd = true;
+ }
+ }
+ }
+ else if (currentImplementation != null
+ && currentImplementation.HasCachedSnapshot
+ && relevantAssumpVars.Count == 0
+ && checksum != null
+ && currentImplementation.IsAssertionChecksumInCachedSnapshot(checksum)
+ && currentImplementation.IsErrorChecksumInCachedSnapshot(checksum))
+ {
+ TraceCachingAction(pc, CachingAction.RecycleError);
+ ac.MarkAsVerifiedUnder(Expr.True);
+ currentImplementation.AddRecycledFailingAssertion(ac);
+ pc.Attributes = new QKeyValue(Token.NoToken, "recycled_failing_assertion", new List<object>(), pc.Attributes);
+ }
+ else
+ {
+ TraceCachingAction(pc, CachingAction.DoNothingToAssert);
+ }
+ }
+ else if (pc is AssumeCmd
+ && QKeyValue.FindBoolAttribute(pc.Attributes, "precondition_previous_snapshot")
+ && pc.SugaredCmdChecksum != null)
+ {
+ if (!relevantDoomedAssumpVars.Any()
+ && currentImplementation.HasCachedSnapshot
+ && currentImplementation.IsAssertionChecksumInCachedSnapshot(pc.SugaredCmdChecksum)
+ && !currentImplementation.IsErrorChecksumInCachedSnapshot(pc.SugaredCmdChecksum))
+ {
+ bool isTrue;
+ var assmVars = currentImplementation.ConjunctionOfInjectedAssumptionVariables(incarnationMap, out isTrue);
+ if (!isTrue)
+ {
+ copy = LiteralExpr.Imp(assmVars, copy);
+ TraceCachingAction(pc, CachingAction.MarkAsPartiallyVerified);
+ }
+ else
+ {
+ TraceCachingAction(pc, CachingAction.MarkAsFullyVerified);
+ }
+ }
+ else
+ {
+ TraceCachingAction(pc, CachingAction.DropAssume);
+ dropCmd = true;
+ }
+ }
+ else if (pc is AssumeCmd && QKeyValue.FindBoolAttribute(pc.Attributes, "assumption_variable_initialization"))
+ {
+ var identExpr = pc.Expr as IdentifierExpr;
+ if (identExpr != null && identExpr.Decl != null && !incarnationMap.ContainsKey(identExpr.Decl))
+ {
+ incarnationMap[identExpr.Decl] = LiteralExpr.True;
+ dropCmd = true;
+ }
+ }
+ pc.Expr = copy;
+ if (!dropCmd)
+ {
+ passiveCmds.Add(pc);
+ }
+ }
+ #endregion
+ #region x1 := E1, x2 := E2, ... |--> assume x1' = E1[in] & x2' = E2[in], out := in( x |-> x' ) [except as noted below]
+ else if (c is AssignCmd) {
+ AssignCmd assign = ((AssignCmd)c).AsSimpleAssignCmd; // first remove map assignments
+ Contract.Assert(assign != null);
+ #region Substitute all variables in E with the current map
+ List<Expr> copies = new List<Expr>();
+ foreach (Expr e in assign.Rhss) {
+ Contract.Assert(e != null);
+ copies.Add(Substituter.ApplyReplacingOldExprs(incarnationSubst,
+ oldFrameSubst,
+ e));
+ }
+ #endregion
+
+ List<Expr/*!>!*/> assumptions = new List<Expr>();
+ // it might be too slow to create a new dictionary each time ...
+ IDictionary<Variable, Expr> newIncarnationMappings =
+ new Dictionary<Variable, Expr>();
+
+ for (int i = 0; i < assign.Lhss.Count; ++i) {
+ IdentifierExpr lhsIdExpr =
+ cce.NonNull((SimpleAssignLhs)assign.Lhss[i]).AssignedVariable;
+ Variable lhs = cce.NonNull(lhsIdExpr.Decl);
+ Contract.Assert(lhs != null);
+ Expr rhs = assign.Rhss[i];
+ Contract.Assert(rhs != null);
+
+ // don't create incarnations for assignments of literals or single variables.
+ if (rhs is LiteralExpr) {
+ incarnationMap[lhs] = rhs;
+ } else if (rhs is IdentifierExpr) {
+ IdentifierExpr ie = (IdentifierExpr)rhs;
+ if (incarnationMap.ContainsKey(cce.NonNull(ie.Decl)))
+ newIncarnationMappings[lhs] = cce.NonNull((Expr)incarnationMap[ie.Decl]);
+ else
+ newIncarnationMappings[lhs] = ie;
+ } else {
+ IdentifierExpr x_prime_exp = null;
+ #region Make a new incarnation, x', for variable x, but only if x is *not* already an incarnation
+ if (lhs is Incarnation) {
+ // incarnations are already written only once, no need to make an incarnation of an incarnation
+ x_prime_exp = lhsIdExpr;
+ } else {
+ Variable v = CreateIncarnation(lhs, c);
+ x_prime_exp = new IdentifierExpr(lhsIdExpr.tok, v);
+ newIncarnationMappings[lhs] = x_prime_exp;
+ }
+ #endregion
+
+ var nAryExpr = copies[i] as NAryExpr;
+ if (nAryExpr != null)
+ {
+ var binOp = nAryExpr.Fun as BinaryOperator;
+ if (binOp != null
+ && binOp.Op == BinaryOperator.Opcode.And)
+ {
+ var arg0 = nAryExpr.Args[0] as LiteralExpr;
+ var arg1 = nAryExpr.Args[1] as LiteralExpr;
+ if ((arg0 != null && arg0.IsTrue) || (arg1 != null && arg1.IsFalse))
+ {
+ // Replace the expressions "true && arg1" or "arg0 && false" by "arg1".
+ copies[i] = nAryExpr.Args[1];
+ }
+ }
+ }
+
+ #region Create an assume command with the new variable
+ assumptions.Add(TypedExprEq(x_prime_exp, copies[i], x_prime_exp.Decl != null && x_prime_exp.Decl.Name.Contains("a##cached##")));
+ #endregion
+ }
+ }
+
+ foreach (KeyValuePair<Variable, Expr> pair in newIncarnationMappings) {
+ Contract.Assert(pair.Key != null && pair.Value != null);
+ incarnationMap[pair.Key] = pair.Value;
+ }
+
+ if (assumptions.Count > 0) {
+ Expr assumption = assumptions[0];
+
+ for (int i = 1; i < assumptions.Count; ++i) {
+ Contract.Assert(assumption != null);
+ assumption = Expr.And(assumption, assumptions[i]);
+ }
+ passiveCmds.Add(new AssumeCmd(c.tok, assumption));
+ }
+
+ if (currentImplementation != null
+ && currentImplementation.HasCachedSnapshot
+ && !currentImplementation.AnyErrorsInCachedSnapshot
+ && currentImplementation.DoomedInjectedAssumptionVariables.Count == 0
+ && currentImplementation.InjectedAssumptionVariables.Count == 1
+ && assign.Lhss.Count == 1)
+ {
+ var identExpr = assign.Lhss[0].AsExpr as IdentifierExpr;
+ Expr incarnation;
+ if (identExpr != null && identExpr.Decl != null && QKeyValue.FindBoolAttribute(identExpr.Decl.Attributes, "assumption") && incarnationMap.TryGetValue(identExpr.Decl, out incarnation))
+ {
+ TraceCachingAction(assign, CachingAction.AssumeNegationOfAssumptionVariable);
+ passiveCmds.Add(new AssumeCmd(c.tok, Expr.Not(incarnation)));
+ }
+ }
+ }
+ #endregion
+ #region havoc w |--> assume whereClauses, out := in( w |-> w' )
+ else if (c is HavocCmd) {
+ if (this.preHavocIncarnationMap == null) // Save a copy of the incarnation map (at the top of a sequence of havoc statements)
+ this.preHavocIncarnationMap = new Dictionary<Variable, Expr>(incarnationMap);
+
+ HavocCmd hc = (HavocCmd)c;
+ Contract.Assert(c != null);
+ // If an assumption variable for postconditions is included here, it must have been assigned within a loop.
+ // We do not need to havoc it if we have performed a modular proof of the loop (i.e., using only the loop
+ // invariant) in the previous snapshot and, consequently, the corresponding assumption did not affect the
+ // anything after the loop. We can achieve this by simply not updating/adding it in the incarnation map.
+ List<IdentifierExpr> havocVars = hc.Vars.Where(v => !(QKeyValue.FindBoolAttribute(v.Decl.Attributes, "assumption") && v.Decl.Name.StartsWith("a##cached##"))).ToList();
+ // First, compute the new incarnations
+ foreach (IdentifierExpr ie in havocVars) {
+ Contract.Assert(ie != null);
+ if (!(ie.Decl is Incarnation)) {
+ Variable x = cce.NonNull(ie.Decl);
+ Variable x_prime = CreateIncarnation(x, c);
+ incarnationMap[x] = new IdentifierExpr(x_prime.tok, x_prime);
+ }
+ }
+ // Then, perform the assume of the where clauses, using the updated incarnations
+ Substitution updatedIncarnationSubst = Substituter.SubstitutionFromHashtable(incarnationMap);
+ foreach (IdentifierExpr ie in havocVars) {
+ Contract.Assert(ie != null);
+ if (!(ie.Decl is Incarnation)) {
+ Variable x = cce.NonNull(ie.Decl);
+ Bpl.Expr w = x.TypedIdent.WhereExpr;
+ if (w != null) {
+ Expr copy = Substituter.ApplyReplacingOldExprs(updatedIncarnationSubst, oldFrameSubst, w);
+ passiveCmds.Add(new AssumeCmd(c.tok, copy));
+ }
+ }
+ }
+
+ // Add the following assume-statement for each assumption variable 'v', where 'v_post' is the new incarnation and 'v_pre' is the old one:
+ // assume v_post ==> v_pre;
+ foreach (IdentifierExpr ie in havocVars)
+ {
+ if (QKeyValue.FindBoolAttribute(ie.Decl.Attributes, "assumption"))
+ {
+ var preInc = (Expr)(preHavocIncarnationMap[ie.Decl].Clone());
+ var postInc = (Expr)(incarnationMap[ie.Decl].Clone());
+ passiveCmds.Add(new AssumeCmd(c.tok, Expr.Imp(postInc, preInc)));
+ }
+ }
+ }
+ #endregion
+ else if (c is CommentCmd) {
+ // comments are just for debugging and don't affect verification
+ } else if (c is SugaredCmd) {
+ SugaredCmd sug = (SugaredCmd)c;
+ Contract.Assert(sug != null);
+ Cmd cmd = sug.Desugaring;
+ Contract.Assert(cmd != null);
+ TurnIntoPassiveCmd(cmd, incarnationMap, oldFrameSubst, passiveCmds, mvInfo, containingBlock);
+ } else if (c is StateCmd) {
+ this.preHavocIncarnationMap = null; // we do not need to remeber the previous incarnations
+ StateCmd st = (StateCmd)c;
+ Contract.Assert(st != null);
+ // account for any where clauses among the local variables
+ foreach (Variable v in st.Locals) {
+ Contract.Assert(v != null);
+ Expr w = v.TypedIdent.WhereExpr;
+ if (w != null) {
+ passiveCmds.Add(new AssumeCmd(v.tok, w));
+ }
+ }
+ // do the sub-commands
+ foreach (Cmd s in st.Cmds) {
+ Contract.Assert(s != null);
+ TurnIntoPassiveCmd(s, incarnationMap, oldFrameSubst, passiveCmds, mvInfo, containingBlock);
+ }
+ // remove the local variables from the incarnation map
+ foreach (Variable v in st.Locals) {
+ Contract.Assert(v != null);
+ incarnationMap.Remove(v);
+ }
+ }
+ #region There shouldn't be any other types of commands at this point
+ else {
+ Debug.Fail("Internal Error: Passive transformation handed a command that is not one of assert,assume,havoc,assign.");
+ }
+ #endregion
+
+
+ #region We remember if we have put an havoc statement into a passive form
+
+ if (!(c is HavocCmd))
+ this.preHavocIncarnationMap = null;
+ // else: it has already been set by the case for the HavocCmd
+ #endregion
+ }
+
+ NAryExpr TypedExprEq(Expr e0, Expr e1, bool doNotResolveOverloading = false) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ NAryExpr e = Expr.Eq(e0, e1);
+ var fun = e.Fun as IOverloadedAppliable;
+ if (fun != null)
+ {
+ fun.DoNotResolveOverloading = doNotResolveOverloading;
+ }
+ e.Type = Bpl.Type.Bool;
+ e.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
+ return e;
+ }
+
+ /// <summary>
+ /// Creates a new block to add to impl.Blocks, where impl is the implementation that contains
+ /// succ. Caller must do the add to impl.Blocks.
+ /// </summary>
+ protected Block CreateBlockBetween(int predIndex, Block succ) {
+ Contract.Requires(0 <= predIndex && predIndex < succ.Predecessors.Count);
+
+
+ Contract.Requires(succ != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+
+ Block pred = cce.NonNull(succ.Predecessors[predIndex]);
+
+ string newBlockLabel = pred.Label + "_@2_" + succ.Label;
+
+ // successor of newBlock list
+ List<String> ls = new List<String>();
+ ls.Add(succ.Label);
+ List<Block> bs = new List<Block>();
+ bs.Add(succ);
+
+ Block newBlock = new Block(
+ new Token(-17, -4),
+ newBlockLabel,
+ new List<Cmd>(),
+ new GotoCmd(Token.NoToken, ls, bs)
+ );
+
+ // predecessors of newBlock
+ List<Block> ps = new List<Block>();
+ ps.Add(pred);
+ newBlock.Predecessors = ps;
+
+ // fix successors of pred
+ #region Change the edge "pred->succ" to "pred->newBlock"
+ GotoCmd gtc = (GotoCmd)cce.NonNull(pred.TransferCmd);
+ Contract.Assume(gtc.labelTargets != null);
+ Contract.Assume(gtc.labelNames != null);
+ for (int i = 0, n = gtc.labelTargets.Count; i < n; i++) {
+ if (gtc.labelTargets[i] == succ) {
+ gtc.labelTargets[i] = newBlock;
+ gtc.labelNames[i] = newBlockLabel;
+ break;
+ }
+ }
+ #endregion Change the edge "pred->succ" to "pred->newBlock"
+
+ // fix predecessors of succ
+ succ.Predecessors[predIndex] = newBlock;
+
+ return newBlock;
+ }
+
+ protected void AddBlocksBetween(List<Block> blocks) {
+ Contract.Requires(blocks != null);
+ #region Introduce empty blocks between join points and their multi-successor predecessors
+ List<Block> tweens = new List<Block>();
+ foreach (Block b in blocks) {
+ int nPreds = b.Predecessors.Count;
+ if (nPreds > 1) {
+ // b is a join point (i.e., it has more than one predecessor)
+ for (int i = 0; i < nPreds; i++) {
+ GotoCmd gotocmd = (GotoCmd)(cce.NonNull(b.Predecessors[i]).TransferCmd);
+ if (gotocmd.labelNames != null && gotocmd.labelNames.Count > 1) {
+ tweens.Add(CreateBlockBetween(i, b));
+ }
+ }
+ }
+ }
+ blocks.AddRange(tweens); // must wait until iteration is done before changing the list
+ #endregion
+ }
+
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (disposing)
+ {
+ Close();
+ }
+ _disposed = true;
+ }
+ }
+
+ public int Cores { get; set; }
+ }
+
+ public class ModelViewInfo
+ {
+ public readonly List<Variable> AllVariables = new List<Variable>();
+ public readonly List<Mapping> CapturePoints = new List<Mapping>();
+ public static readonly Function MVState_FunctionDef = new Function(Token.NoToken, "$mv_state",
+ new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, TypedIdent.NoName, Bpl.Type.Int), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, TypedIdent.NoName, Bpl.Type.Int), true) },
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, TypedIdent.NoName, Bpl.Type.Bool), false));
+ public static readonly Constant MVState_ConstantDef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "$mv_state_const", Bpl.Type.Int));
+
+ public ModelViewInfo(Program program, Implementation impl) {
+ Contract.Requires(program != null);
+ Contract.Requires(impl != null);
+
+ // global variables
+ lock (program.TopLevelDeclarations)
+ {
+ foreach (var v in program.Variables)
+ {
+ if (!(v is Constant))
+ {
+ AllVariables.Add(v);
+ }
+ }
+ }
+ // implementation parameters
+ foreach (Variable p in impl.InParams) {
+ AllVariables.Add(p);
+ }
+ foreach (Variable p in impl.OutParams) {
+ AllVariables.Add(p);
+ }
+ // implementation locals
+ foreach (Variable v in impl.LocVars) {
+ AllVariables.Add(v);
+ }
+ }
+
+ public ModelViewInfo(CodeExpr codeExpr) {
+ Contract.Requires(codeExpr != null);
+ // TODO: also need all variables of enclosing scopes (the global variables of the program, the parameters
+ // and perhaps locals of the implementation (if any), any enclosing code expressions).
+
+ foreach (Variable v in codeExpr.LocVars) {
+ AllVariables.Add(v);
+ }
+ }
+
+ public class Mapping
+ {
+ public readonly string Description;
+ public readonly Dictionary<Variable, Expr> IncarnationMap;
+ public Mapping(string description, Dictionary<Variable, Expr> incarnationMap) {
+ Description = description;
+ IncarnationMap = incarnationMap;
+ }
+ }
+ }
+}
diff --git a/Source/VCGeneration/Context.cs b/Source/VCGeneration/Context.cs
index 83787dc5..3bd14e6b 100644
--- a/Source/VCGeneration/Context.cs
+++ b/Source/VCGeneration/Context.cs
@@ -1,254 +1,256 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie
-{
- /// <summary>
- /// The methods of this class are called in the following order:
- /// DeclareType*
- /// (DeclareConstant DeclareFunction)*
- /// AddAxiom*
- /// DeclareGlobalVariable*
- /// At this time, all "attributes" are passed in as null.
- /// </summary>
- [ContractClass(typeof(ProverContextContracts))]
- public abstract class ProverContext : ICloneable {
- protected virtual void ProcessDeclaration(Declaration decl) {Contract.Requires(decl != null);}
- public virtual void DeclareType(TypeCtorDecl t, string attributes) {Contract.Requires(t != null); ProcessDeclaration(t); }
- public virtual void DeclareConstant(Constant c, bool uniq, string attributes) {Contract.Requires(c != null); ProcessDeclaration(c); }
- public virtual void DeclareFunction(Function f, string attributes) {Contract.Requires(f != null); ProcessDeclaration(f); }
- public virtual void AddAxiom(Axiom a, string attributes) {Contract.Requires(a != null); ProcessDeclaration(a); }
- public virtual void DeclareGlobalVariable(GlobalVariable v, string attributes) {Contract.Requires(v != null); ProcessDeclaration(v); }
- public abstract void AddAxiom(VCExpr vc);
- public abstract string Lookup(VCExprVar var);
- public abstract VCExpressionGenerator ExprGen { get; }
- public abstract Boogie2VCExprTranslator BoogieExprTranslator { get; }
- public abstract VCGenerationOptions VCGenOptions { get; }
- public abstract object Clone();
- public abstract void Reset();
- public abstract void Clear();
- }
-
-[ContractClassFor(typeof(ProverContext))]
-public abstract class ProverContextContracts:ProverContext{
- public override void AddAxiom(VCExpr vc) {
- }
- public override void AddAxiom(Axiom a, string attributes)
-{
-}
- public override VCExpressionGenerator ExprGen
-{
- get { Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
- throw new NotImplementedException(); }
-}
- public override Boogie2VCExprTranslator BoogieExprTranslator
-{
- get { Contract.Ensures(Contract.Result<Boogie2VCExprTranslator>() != null);
- throw new NotImplementedException(); }
-}
- public override VCGenerationOptions VCGenOptions
-{
- get {Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
- throw new NotImplementedException(); }
-}
- public override object Clone()
-{
- Contract.Ensures(Contract.Result<object>() != null);
- throw new NotImplementedException();
-}
-}
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- /// <summary>
- /// This ProverContext subclass is intended for use with untyped provers that do not require names
- /// to be declared before use. It constructs its context from unique constants and given axioms.
- /// </summary>
- public class DeclFreeProverContext : ProverContext {
- protected VCExpressionGenerator gen;
- protected VCGenerationOptions genOptions;
- protected Boogie2VCExprTranslator translator;
-
- protected OrderingAxiomBuilder orderingAxiomBuilder;
-
- protected List<Variable> distincts;
- protected List<VCExpr> axiomConjuncts;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(gen != null);
- Contract.Invariant(genOptions != null);
- Contract.Invariant(translator != null);
- Contract.Invariant(orderingAxiomBuilder != null);
- Contract.Invariant(cce.NonNullElements(distincts));
- Contract.Invariant(cce.NonNullElements(axiomConjuncts));
- }
-
- public VCExprTranslator/*?*/ exprTranslator;
-
- public DeclFreeProverContext(VCExpressionGenerator gen,
- VCGenerationOptions genOptions) {
- Contract.Requires(gen != null);
- Contract.Requires(genOptions != null);
- this.gen = gen;
- this.genOptions = genOptions;
- Boogie2VCExprTranslator t = new Boogie2VCExprTranslator (gen, genOptions);
- this.translator = t;
-
- SetupOrderingAxiomBuilder(gen, t);
-
- distincts = new List<Variable>();
- axiomConjuncts = new List<VCExpr>();
-
- exprTranslator = null;
- }
-
- private void SetupOrderingAxiomBuilder(VCExpressionGenerator gen, Boogie2VCExprTranslator t)
- {
- OrderingAxiomBuilder oab = new OrderingAxiomBuilder(gen, t);
- Contract.Assert(oab != null);
- oab.Setup();
- this.orderingAxiomBuilder = oab;
- }
-
- public override void Reset()
- {
- SetupOrderingAxiomBuilder(gen, translator);
- distincts = new List<Variable>();
- axiomConjuncts = new List<VCExpr>();
- }
-
- public override void Clear()
- {
- distincts = new List<Variable>();
- axiomConjuncts = new List<VCExpr>();
- }
-
- protected DeclFreeProverContext(DeclFreeProverContext ctxt) {
- Contract.Requires(ctxt != null);
- this.gen = ctxt.gen;
- this.genOptions = ctxt.genOptions;
- Boogie2VCExprTranslator t = (Boogie2VCExprTranslator)ctxt.translator.Clone();
- Contract.Assert(t != null);
- this.translator = t;
- this.orderingAxiomBuilder = new OrderingAxiomBuilder(ctxt.gen, t, ctxt.orderingAxiomBuilder);
-
- StringBuilder cmds = new StringBuilder ();
-
- distincts = new List<Variable>(ctxt.distincts);
- axiomConjuncts = new List<VCExpr>(ctxt.axiomConjuncts);
-
- if (ctxt.exprTranslator == null)
- exprTranslator = null;
- else
- exprTranslator = (VCExprTranslator)cce.NonNull(ctxt.exprTranslator.Clone());
- }
-
- public override object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
-
- return new DeclFreeProverContext(this);
- }
-
- public override void DeclareFunction(Function f, string attributes) {//Contract.Requires(f != null);
- base.ProcessDeclaration(f);
- }
-
- public override void DeclareConstant(Constant c, bool uniq, string attributes) {//Contract.Requires(c != null);
- base.DeclareConstant(c, uniq, attributes);
- orderingAxiomBuilder.AddConstant(c);
-
- // TODO: make separate distinct lists for names coming from different types
- // e.g., one for strings, one for ints, one for program types.
- if (uniq){
- distincts.Add(c);
- }
- }
-
- public override void AddAxiom(Axiom ax, string attributes) {//Contract.Requires(ax != null);
- base.AddAxiom(ax, attributes);
-
- axiomConjuncts.Add(translator.Translate(ax.Expr));
- }
-
- public override void AddAxiom(VCExpr vc)
- {//Contract.Requires(vc != null);
- axiomConjuncts.Add(vc);
- }
-
- public VCExpr Axioms {
- get {Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr axioms = gen.NAry(VCExpressionGenerator.AndOp, axiomConjuncts);
- List<VCExpr>/*!>!*/ distinctVars = new List<VCExpr> ();
- foreach (Variable v in distincts){
- Contract.Assert(v != null);
- distinctVars.Add(translator.LookupVariable(v));}
- axioms = gen.AndSimp(gen.Distinct(distinctVars), axioms);
- if (CommandLineOptions.Clo.TypeEncodingMethod != CommandLineOptions.TypeEncoding.Monomorphic)
- axioms = gen.AndSimp(orderingAxiomBuilder.Axioms, axioms);
- return axioms;
- }
- }
-
- public override string Lookup(VCExprVar var)
- {
- return exprTranslator.Lookup(var);
- }
-
- public override VCExpressionGenerator ExprGen { get {Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
-
- return gen;
- } }
- public override Boogie2VCExprTranslator BoogieExprTranslator { get {Contract.Ensures(Contract.Result<Boogie2VCExprTranslator>() != null);
-
- return translator;
- } }
- public override VCGenerationOptions VCGenOptions { get {Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
-
- return genOptions;
- } }
- }
-
- // Translator from VCExpressions to strings, which are implemented
- // by the various provers
- [ContractClass(typeof(VCExprTranslatorContracts))]
- public abstract class VCExprTranslator : ICloneable {
- public abstract string translate(VCExpr expr, int polarity);
- public abstract string Lookup(VCExprVar var);
- public abstract Object Clone();
- }
-
- [ContractClassFor(typeof(VCExprTranslator))]
-
- public abstract class VCExprTranslatorContracts : VCExprTranslator {
- public override object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
- throw new NotImplementedException();
- }
- public override string Lookup(VCExprVar var) {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- throw new NotImplementedException();
- }
- public override string translate(VCExpr expr, int polarity) {
-
- Contract.Requires(expr != null);
-
- Contract.Ensures(Contract.Result<string>() != null);
-
- throw new NotImplementedException();
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+namespace Microsoft.Boogie
+{
+ /// <summary>
+ /// The methods of this class are called in the following order:
+ /// DeclareType*
+ /// (DeclareConstant DeclareFunction)*
+ /// AddAxiom*
+ /// DeclareGlobalVariable*
+ /// At this time, all "attributes" are passed in as null.
+ /// </summary>
+ [ContractClass(typeof(ProverContextContracts))]
+ public abstract class ProverContext : ICloneable {
+ public int TimoutDiagnosticsCount { get; set; }
+ public readonly Dictionary<int, Tuple<AssertCmd, TransferCmd>> TimeoutDiagnosticIDToAssertion = new Dictionary<int, Tuple<AssertCmd, TransferCmd>>();
+ protected virtual void ProcessDeclaration(Declaration decl) {Contract.Requires(decl != null);}
+ public virtual void DeclareType(TypeCtorDecl t, string attributes) {Contract.Requires(t != null); ProcessDeclaration(t); }
+ public virtual void DeclareConstant(Constant c, bool uniq, string attributes) {Contract.Requires(c != null); ProcessDeclaration(c); }
+ public virtual void DeclareFunction(Function f, string attributes) {Contract.Requires(f != null); ProcessDeclaration(f); }
+ public virtual void AddAxiom(Axiom a, string attributes) {Contract.Requires(a != null); ProcessDeclaration(a); }
+ public virtual void DeclareGlobalVariable(GlobalVariable v, string attributes) {Contract.Requires(v != null); ProcessDeclaration(v); }
+ public abstract void AddAxiom(VCExpr vc);
+ public abstract string Lookup(VCExprVar var);
+ public abstract VCExpressionGenerator ExprGen { get; }
+ public abstract Boogie2VCExprTranslator BoogieExprTranslator { get; }
+ public abstract VCGenerationOptions VCGenOptions { get; }
+ public abstract object Clone();
+ public abstract void Reset();
+ public abstract void Clear();
+ }
+
+[ContractClassFor(typeof(ProverContext))]
+public abstract class ProverContextContracts:ProverContext{
+ public override void AddAxiom(VCExpr vc) {
+ }
+ public override void AddAxiom(Axiom a, string attributes)
+{
+}
+ public override VCExpressionGenerator ExprGen
+{
+ get { Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
+ throw new NotImplementedException(); }
+}
+ public override Boogie2VCExprTranslator BoogieExprTranslator
+{
+ get { Contract.Ensures(Contract.Result<Boogie2VCExprTranslator>() != null);
+ throw new NotImplementedException(); }
+}
+ public override VCGenerationOptions VCGenOptions
+{
+ get {Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
+ throw new NotImplementedException(); }
+}
+ public override object Clone()
+{
+ Contract.Ensures(Contract.Result<object>() != null);
+ throw new NotImplementedException();
+}
+}
+
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------
+
+ /// <summary>
+ /// This ProverContext subclass is intended for use with untyped provers that do not require names
+ /// to be declared before use. It constructs its context from unique constants and given axioms.
+ /// </summary>
+ public class DeclFreeProverContext : ProverContext {
+ protected VCExpressionGenerator gen;
+ protected VCGenerationOptions genOptions;
+ protected Boogie2VCExprTranslator translator;
+
+ protected OrderingAxiomBuilder orderingAxiomBuilder;
+
+ protected List<Variable> distincts;
+ protected List<VCExpr> axiomConjuncts;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(gen != null);
+ Contract.Invariant(genOptions != null);
+ Contract.Invariant(translator != null);
+ Contract.Invariant(orderingAxiomBuilder != null);
+ Contract.Invariant(cce.NonNullElements(distincts));
+ Contract.Invariant(cce.NonNullElements(axiomConjuncts));
+ }
+
+ public VCExprTranslator/*?*/ exprTranslator;
+
+ public DeclFreeProverContext(VCExpressionGenerator gen,
+ VCGenerationOptions genOptions) {
+ Contract.Requires(gen != null);
+ Contract.Requires(genOptions != null);
+ this.gen = gen;
+ this.genOptions = genOptions;
+ Boogie2VCExprTranslator t = new Boogie2VCExprTranslator (gen, genOptions);
+ this.translator = t;
+
+ SetupOrderingAxiomBuilder(gen, t);
+
+ distincts = new List<Variable>();
+ axiomConjuncts = new List<VCExpr>();
+
+ exprTranslator = null;
+ }
+
+ private void SetupOrderingAxiomBuilder(VCExpressionGenerator gen, Boogie2VCExprTranslator t)
+ {
+ OrderingAxiomBuilder oab = new OrderingAxiomBuilder(gen, t);
+ Contract.Assert(oab != null);
+ oab.Setup();
+ this.orderingAxiomBuilder = oab;
+ }
+
+ public override void Reset()
+ {
+ SetupOrderingAxiomBuilder(gen, translator);
+ distincts = new List<Variable>();
+ axiomConjuncts = new List<VCExpr>();
+ }
+
+ public override void Clear()
+ {
+ distincts = new List<Variable>();
+ axiomConjuncts = new List<VCExpr>();
+ }
+
+ protected DeclFreeProverContext(DeclFreeProverContext ctxt) {
+ Contract.Requires(ctxt != null);
+ this.gen = ctxt.gen;
+ this.genOptions = ctxt.genOptions;
+ Boogie2VCExprTranslator t = (Boogie2VCExprTranslator)ctxt.translator.Clone();
+ Contract.Assert(t != null);
+ this.translator = t;
+ this.orderingAxiomBuilder = new OrderingAxiomBuilder(ctxt.gen, t, ctxt.orderingAxiomBuilder);
+
+ StringBuilder cmds = new StringBuilder ();
+
+ distincts = new List<Variable>(ctxt.distincts);
+ axiomConjuncts = new List<VCExpr>(ctxt.axiomConjuncts);
+
+ if (ctxt.exprTranslator == null)
+ exprTranslator = null;
+ else
+ exprTranslator = (VCExprTranslator)cce.NonNull(ctxt.exprTranslator.Clone());
+ }
+
+ public override object Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ return new DeclFreeProverContext(this);
+ }
+
+ public override void DeclareFunction(Function f, string attributes) {//Contract.Requires(f != null);
+ base.ProcessDeclaration(f);
+ }
+
+ public override void DeclareConstant(Constant c, bool uniq, string attributes) {//Contract.Requires(c != null);
+ base.DeclareConstant(c, uniq, attributes);
+ orderingAxiomBuilder.AddConstant(c);
+
+ // TODO: make separate distinct lists for names coming from different types
+ // e.g., one for strings, one for ints, one for program types.
+ if (uniq){
+ distincts.Add(c);
+ }
+ }
+
+ public override void AddAxiom(Axiom ax, string attributes) {//Contract.Requires(ax != null);
+ base.AddAxiom(ax, attributes);
+
+ axiomConjuncts.Add(translator.Translate(ax.Expr));
+ }
+
+ public override void AddAxiom(VCExpr vc)
+ {//Contract.Requires(vc != null);
+ axiomConjuncts.Add(vc);
+ }
+
+ public VCExpr Axioms {
+ get {Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr axioms = gen.NAry(VCExpressionGenerator.AndOp, axiomConjuncts);
+ List<VCExpr>/*!>!*/ distinctVars = new List<VCExpr> ();
+ foreach (Variable v in distincts){
+ Contract.Assert(v != null);
+ distinctVars.Add(translator.LookupVariable(v));}
+ axioms = gen.AndSimp(gen.Distinct(distinctVars), axioms);
+ if (CommandLineOptions.Clo.TypeEncodingMethod != CommandLineOptions.TypeEncoding.Monomorphic)
+ axioms = gen.AndSimp(orderingAxiomBuilder.Axioms, axioms);
+ return axioms;
+ }
+ }
+
+ public override string Lookup(VCExprVar var)
+ {
+ return exprTranslator.Lookup(var);
+ }
+
+ public override VCExpressionGenerator ExprGen { get {Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
+
+ return gen;
+ } }
+ public override Boogie2VCExprTranslator BoogieExprTranslator { get {Contract.Ensures(Contract.Result<Boogie2VCExprTranslator>() != null);
+
+ return translator;
+ } }
+ public override VCGenerationOptions VCGenOptions { get {Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
+
+ return genOptions;
+ } }
+ }
+
+ // Translator from VCExpressions to strings, which are implemented
+ // by the various provers
+ [ContractClass(typeof(VCExprTranslatorContracts))]
+ public abstract class VCExprTranslator : ICloneable {
+ public abstract string translate(VCExpr expr, int polarity);
+ public abstract string Lookup(VCExprVar var);
+ public abstract Object Clone();
+ }
+
+ [ContractClassFor(typeof(VCExprTranslator))]
+
+ public abstract class VCExprTranslatorContracts : VCExprTranslator {
+ public override object Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+ throw new NotImplementedException();
+ }
+ public override string Lookup(VCExprVar var) {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ throw new NotImplementedException();
+ }
+ public override string translate(VCExpr expr, int polarity) {
+
+ Contract.Requires(expr != null);
+
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Source/VCGeneration/ExprExtensions.cs b/Source/VCGeneration/ExprExtensions.cs
index 2bdb4af7..5e0dcf8e 100644
--- a/Source/VCGeneration/ExprExtensions.cs
+++ b/Source/VCGeneration/ExprExtensions.cs
@@ -1,353 +1,353 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 2012 Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Term = Microsoft.Boogie.VCExprAST.VCExpr;
-using FuncDecl = Microsoft.Boogie.VCExprAST.VCExprOp;
-using Sort = Microsoft.Boogie.Type;
-using Microsoft.Boogie.VCExprAST;
-
-
-/** This namespace contains some extensions to allow VCExpr to provide the
- * interface needed by RPFP and FixedpointVC. */
-
-namespace Microsoft.Boogie.ExprExtensions
-{
- class ReferenceComparer<T> : IEqualityComparer<T> where T : class
- {
- private static ReferenceComparer<T> m_instance;
-
- public static ReferenceComparer<T> Instance
- {
- get
- {
- return m_instance ?? (m_instance = new ReferenceComparer<T>());
- }
- }
-
- public bool Equals(T x, T y)
- {
- return ReferenceEquals(x, y);
- }
-
- public int GetHashCode(T obj)
- {
- return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
- }
- }
-
- public class TermDict<T> : Dictionary<Term, T>
- {
- public TermDict() : base(ReferenceComparer<Term>.Instance) { }
- }
-
-
-
- public enum TermKind { App, Other };
-
- public enum DeclKind { Uninterpreted, And, Implies, Label, Other };
-
- public static class MyExtensions
- {
- public static Term[] GetAppArgs(this Term t)
- {
- Microsoft.Boogie.VCExprAST.VCExprNAry tn = t as Microsoft.Boogie.VCExprAST.VCExprNAry;
- return tn.ToArray();
- }
-
- public static FuncDecl GetAppDecl(this Term t)
- {
- Microsoft.Boogie.VCExprAST.VCExprNAry tn = t as Microsoft.Boogie.VCExprAST.VCExprNAry;
- return tn.Op;
- }
-
- public static string GetDeclName(this FuncDecl f)
- {
- return (f as VCExprBoogieFunctionOp).Func.Name; //TODO
- }
-
- public static DeclKind GetKind(this FuncDecl f)
- {
- if (f is VCExprBoogieFunctionOp)
- return DeclKind.Uninterpreted;
- if (f == VCExpressionGenerator.AndOp)
- return DeclKind.And;
- if (f == VCExpressionGenerator.ImpliesOp)
- return DeclKind.Implies;
- if (f is VCExprLabelOp)
- return DeclKind.Label;
- return DeclKind.Other;
- }
-
- public static bool IsLabel(this Term t)
- {
- return (t is VCExprNAry) && (GetAppDecl(t) is VCExprLabelOp);
- }
-
- public static string LabelName(this Term t)
- {
- return (GetAppDecl(t) as VCExprLabelOp).label;
- }
-
- public static Sort GetSort(this Term t)
- {
- return t.Type;
- }
-
- public static TermKind GetKind(this Term t)
- {
- if (t is Microsoft.Boogie.VCExprAST.VCExprNAry)
- return TermKind.App;
- return TermKind.Other;
- }
-
- public static bool IsFunctionApp(this Term t)
- {
- return t.GetKind() == TermKind.App && t.GetAppDecl().GetKind() == DeclKind.Uninterpreted;
- }
-
- public static bool IsFalse(this Term t)
- {
- return t == VCExpressionGenerator.False;
- }
-
- public static Term VCExprToTerm(this Microsoft.Boogie.ProverContext ctx, VCExpr e, LineariserOptions lin){
- return e;
- }
-
- }
-
- public class Context : Microsoft.Boogie.VCExpressionGenerator
- {
- public Term MkTrue()
- {
- return VCExpressionGenerator.True;
- }
-
- public Term MkFalse()
- {
- return VCExpressionGenerator.False;
- }
-
-
- public List<Term> axioms = new List<Term>();
-
- public void AddAxiom(Term ax)
- {
- axioms.Add(ax);
- }
-
- public void RemoveAxiom(Term ax)
- {
- axioms.Remove(ax);
- }
-
- public FuncDecl MkFuncDecl(string name, FuncDecl f)
- {
- Function h = (f as VCExprBoogieFunctionOp).Func;
- Function g = new Function(Token.NoToken, name, h.InParams, h.OutParams[0]);
- return BoogieFunctionOp(g);
- }
-
- public FuncDecl MkFuncDecl(string name, Sort rng)
- {
- Function g = new Function(Token.NoToken, name, new List<Variable>(), new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "dummy",rng)));
- return BoogieFunctionOp(g);
- }
-
- public Term MkApp(FuncDecl f, Term[] args)
- {
- return Function(f, args);
- }
-
- public Term MkApp(FuncDecl f, Term[] args, Type[]/*!*/ typeArguments)
- {
- return Function(f, args, typeArguments);
- }
-
- public Term MkApp(FuncDecl f, Term arg)
- {
- return Function(f, arg);
- }
-
- public Term CloneApp(Term t, Term[] args)
- {
- var f = t.GetAppDecl();
- var typeArgs = (t as VCExprNAry).TypeArguments;
- if (typeArgs != null && typeArgs.Count > 0)
- {
- return MkApp(f, args, typeArgs.ToArray());
- }
- else
- {
- return MkApp(f, args);
- }
- }
-
- public Term MkAnd(Term[] args)
- {
- if (args.Length == 0) return True;
- Term res = args[0];
- for (int i = 1; i < args.Length; i++)
- res = And(res, args[i]);
- return res;
- }
-
- public Term MkAnd(Term arg1, Term arg2)
- {
- return And(arg1, arg2);
- }
-
-
- public Term MkNot(Term arg1)
- {
- return Not(arg1);
- }
-
- public Term MkImplies(Term arg1, Term arg2)
- {
- return Implies(arg1, arg2);
- }
-
- public Term MkEq(Term arg1, Term arg2)
- {
- return Eq(arg1, arg2);
- }
-
- public Sort MkBoolSort()
- {
- return Type.Bool;
- }
-
- public Term MkConst(string name, Sort sort)
- {
- return Variable(name, sort);
- }
-
- public Term MkForall(Term[] bounds, Term body)
- {
- if (bounds.Length == 0)
- return body;
- List<VCExprVar> vbs = new List<VCExprVar>();
- foreach(var v in bounds)
- vbs.Add(v as VCExprVar);
- return Forall(vbs,new List<VCTrigger>(), body);
- }
-
- public Term MkExists(Term[] bounds, Term body)
- {
- if (bounds.Length == 0)
- return body;
- List<VCExprVar> vbs = new List<VCExprVar>();
- foreach (var v in bounds)
- vbs.Add(v as VCExprVar);
- return Exists(vbs, new List<VCTrigger>(), body);
- }
-
- private class Letifier
- {
- private class counter
- {
- public int cnt = 0;
- }
- TermDict<counter> refcnt = new TermDict<counter>();
- List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
- TermDict< VCExprVar> bindingMap = new TermDict< VCExprVar>();
- int letcnt = 0;
- Context ctx;
-
- public Letifier(Context _ctx) { ctx = _ctx; }
-
- private void RefCnt(Term t)
- {
- counter cnt;
- if (!refcnt.TryGetValue(t, out cnt))
- {
- cnt = new counter();
- refcnt.Add(t, cnt);
- }
- cnt.cnt++;
- if (cnt.cnt == 1)
- {
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- var args = t.GetAppArgs();
- foreach (var arg in args)
- RefCnt(arg);
- }
- else if (t is VCExprQuantifier)
- {
- RefCnt((t as VCExprQuantifier).Body);
- }
- }
- }
-
- private Term Doit(Term t)
- {
- VCExprVar v;
- if (bindingMap.TryGetValue(t, out v))
- {
- return v;
- }
- Term res = null;
- var kind = t.GetKind();
- bool letok = false;
- if (kind == TermKind.App)
- {
- var f = t.GetAppDecl();
- var args = t.GetAppArgs();
- args = args.Select(x => Doit(x)).ToArray();
- res = ctx.MkApp(f, args);
- letok = true;
- }
- else if (t is VCExprQuantifier)
- {
- var q = t as VCExprQuantifier;
- var newbody = ctx.Letify(q.Body);
- if (q.Quan == Quantifier.ALL)
- res = ctx.Forall(q.BoundVars, q.Triggers, newbody);
- else
- res = ctx.Exists(q.BoundVars, q.Triggers, newbody);
- letok = true;
- }
- else res = t;
- if (letok && refcnt[t].cnt > 1)
- {
- VCExprVar lv = ctx.MkConst("fpvc$" + Convert.ToString(letcnt), t.GetSort()) as VCExprVar;
- VCExprLetBinding b = ctx.LetBinding(lv, res);
- bindings.Add(b);
- bindingMap.Add(t, lv);
- res = lv;
- letcnt++;
- }
- return res;
- }
-
- public Term Letify(Term t)
- {
- RefCnt(t);
- Term res = Doit(t);
- if (bindings.Count > 0)
- res = ctx.Let(bindings, res);
- return res;
- }
-
- }
-
- public Term Letify(Term t)
- {
- var thing = new Letifier(this);
- return thing.Letify(t);
- }
-
- };
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 2012 Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Term = Microsoft.Boogie.VCExprAST.VCExpr;
+using FuncDecl = Microsoft.Boogie.VCExprAST.VCExprOp;
+using Sort = Microsoft.Boogie.Type;
+using Microsoft.Boogie.VCExprAST;
+
+
+/** This namespace contains some extensions to allow VCExpr to provide the
+ * interface needed by RPFP and FixedpointVC. */
+
+namespace Microsoft.Boogie.ExprExtensions
+{
+ class ReferenceComparer<T> : IEqualityComparer<T> where T : class
+ {
+ private static ReferenceComparer<T> m_instance;
+
+ public static ReferenceComparer<T> Instance
+ {
+ get
+ {
+ return m_instance ?? (m_instance = new ReferenceComparer<T>());
+ }
+ }
+
+ public bool Equals(T x, T y)
+ {
+ return ReferenceEquals(x, y);
+ }
+
+ public int GetHashCode(T obj)
+ {
+ return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
+ }
+ }
+
+ public class TermDict<T> : Dictionary<Term, T>
+ {
+ public TermDict() : base(ReferenceComparer<Term>.Instance) { }
+ }
+
+
+
+ public enum TermKind { App, Other };
+
+ public enum DeclKind { Uninterpreted, And, Implies, Label, Other };
+
+ public static class MyExtensions
+ {
+ public static Term[] GetAppArgs(this Term t)
+ {
+ Microsoft.Boogie.VCExprAST.VCExprNAry tn = t as Microsoft.Boogie.VCExprAST.VCExprNAry;
+ return tn.ToArray();
+ }
+
+ public static FuncDecl GetAppDecl(this Term t)
+ {
+ Microsoft.Boogie.VCExprAST.VCExprNAry tn = t as Microsoft.Boogie.VCExprAST.VCExprNAry;
+ return tn.Op;
+ }
+
+ public static string GetDeclName(this FuncDecl f)
+ {
+ return (f as VCExprBoogieFunctionOp).Func.Name; //TODO
+ }
+
+ public static DeclKind GetKind(this FuncDecl f)
+ {
+ if (f is VCExprBoogieFunctionOp)
+ return DeclKind.Uninterpreted;
+ if (f == VCExpressionGenerator.AndOp)
+ return DeclKind.And;
+ if (f == VCExpressionGenerator.ImpliesOp)
+ return DeclKind.Implies;
+ if (f is VCExprLabelOp)
+ return DeclKind.Label;
+ return DeclKind.Other;
+ }
+
+ public static bool IsLabel(this Term t)
+ {
+ return (t is VCExprNAry) && (GetAppDecl(t) is VCExprLabelOp);
+ }
+
+ public static string LabelName(this Term t)
+ {
+ return (GetAppDecl(t) as VCExprLabelOp).label;
+ }
+
+ public static Sort GetSort(this Term t)
+ {
+ return t.Type;
+ }
+
+ public static TermKind GetKind(this Term t)
+ {
+ if (t is Microsoft.Boogie.VCExprAST.VCExprNAry)
+ return TermKind.App;
+ return TermKind.Other;
+ }
+
+ public static bool IsFunctionApp(this Term t)
+ {
+ return t.GetKind() == TermKind.App && t.GetAppDecl().GetKind() == DeclKind.Uninterpreted;
+ }
+
+ public static bool IsFalse(this Term t)
+ {
+ return t == VCExpressionGenerator.False;
+ }
+
+ public static Term VCExprToTerm(this Microsoft.Boogie.ProverContext ctx, VCExpr e, LineariserOptions lin){
+ return e;
+ }
+
+ }
+
+ public class Context : Microsoft.Boogie.VCExpressionGenerator
+ {
+ public Term MkTrue()
+ {
+ return VCExpressionGenerator.True;
+ }
+
+ public Term MkFalse()
+ {
+ return VCExpressionGenerator.False;
+ }
+
+
+ public List<Term> axioms = new List<Term>();
+
+ public void AddAxiom(Term ax)
+ {
+ axioms.Add(ax);
+ }
+
+ public void RemoveAxiom(Term ax)
+ {
+ axioms.Remove(ax);
+ }
+
+ public FuncDecl MkFuncDecl(string name, FuncDecl f)
+ {
+ Function h = (f as VCExprBoogieFunctionOp).Func;
+ Function g = new Function(Token.NoToken, name, h.InParams, h.OutParams[0]);
+ return BoogieFunctionOp(g);
+ }
+
+ public FuncDecl MkFuncDecl(string name, Sort rng)
+ {
+ Function g = new Function(Token.NoToken, name, new List<Variable>(), new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "dummy",rng)));
+ return BoogieFunctionOp(g);
+ }
+
+ public Term MkApp(FuncDecl f, Term[] args)
+ {
+ return Function(f, args);
+ }
+
+ public Term MkApp(FuncDecl f, Term[] args, Type[]/*!*/ typeArguments)
+ {
+ return Function(f, args, typeArguments);
+ }
+
+ public Term MkApp(FuncDecl f, Term arg)
+ {
+ return Function(f, arg);
+ }
+
+ public Term CloneApp(Term t, Term[] args)
+ {
+ var f = t.GetAppDecl();
+ var typeArgs = (t as VCExprNAry).TypeArguments;
+ if (typeArgs != null && typeArgs.Count > 0)
+ {
+ return MkApp(f, args, typeArgs.ToArray());
+ }
+ else
+ {
+ return MkApp(f, args);
+ }
+ }
+
+ public Term MkAnd(Term[] args)
+ {
+ if (args.Length == 0) return True;
+ Term res = args[0];
+ for (int i = 1; i < args.Length; i++)
+ res = And(res, args[i]);
+ return res;
+ }
+
+ public Term MkAnd(Term arg1, Term arg2)
+ {
+ return And(arg1, arg2);
+ }
+
+
+ public Term MkNot(Term arg1)
+ {
+ return Not(arg1);
+ }
+
+ public Term MkImplies(Term arg1, Term arg2)
+ {
+ return Implies(arg1, arg2);
+ }
+
+ public Term MkEq(Term arg1, Term arg2)
+ {
+ return Eq(arg1, arg2);
+ }
+
+ public Sort MkBoolSort()
+ {
+ return Type.Bool;
+ }
+
+ public Term MkConst(string name, Sort sort)
+ {
+ return Variable(name, sort);
+ }
+
+ public Term MkForall(Term[] bounds, Term body)
+ {
+ if (bounds.Length == 0)
+ return body;
+ List<VCExprVar> vbs = new List<VCExprVar>();
+ foreach(var v in bounds)
+ vbs.Add(v as VCExprVar);
+ return Forall(vbs,new List<VCTrigger>(), body);
+ }
+
+ public Term MkExists(Term[] bounds, Term body)
+ {
+ if (bounds.Length == 0)
+ return body;
+ List<VCExprVar> vbs = new List<VCExprVar>();
+ foreach (var v in bounds)
+ vbs.Add(v as VCExprVar);
+ return Exists(vbs, new List<VCTrigger>(), body);
+ }
+
+ private class Letifier
+ {
+ private class counter
+ {
+ public int cnt = 0;
+ }
+ TermDict<counter> refcnt = new TermDict<counter>();
+ List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
+ TermDict< VCExprVar> bindingMap = new TermDict< VCExprVar>();
+ int letcnt = 0;
+ Context ctx;
+
+ public Letifier(Context _ctx) { ctx = _ctx; }
+
+ private void RefCnt(Term t)
+ {
+ counter cnt;
+ if (!refcnt.TryGetValue(t, out cnt))
+ {
+ cnt = new counter();
+ refcnt.Add(t, cnt);
+ }
+ cnt.cnt++;
+ if (cnt.cnt == 1)
+ {
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ var args = t.GetAppArgs();
+ foreach (var arg in args)
+ RefCnt(arg);
+ }
+ else if (t is VCExprQuantifier)
+ {
+ RefCnt((t as VCExprQuantifier).Body);
+ }
+ }
+ }
+
+ private Term Doit(Term t)
+ {
+ VCExprVar v;
+ if (bindingMap.TryGetValue(t, out v))
+ {
+ return v;
+ }
+ Term res = null;
+ var kind = t.GetKind();
+ bool letok = false;
+ if (kind == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ var args = t.GetAppArgs();
+ args = args.Select(x => Doit(x)).ToArray();
+ res = ctx.MkApp(f, args);
+ letok = true;
+ }
+ else if (t is VCExprQuantifier)
+ {
+ var q = t as VCExprQuantifier;
+ var newbody = ctx.Letify(q.Body);
+ if (q.Quan == Quantifier.ALL)
+ res = ctx.Forall(q.BoundVars, q.Triggers, newbody);
+ else
+ res = ctx.Exists(q.BoundVars, q.Triggers, newbody);
+ letok = true;
+ }
+ else res = t;
+ if (letok && refcnt[t].cnt > 1)
+ {
+ VCExprVar lv = ctx.MkConst("fpvc$" + Convert.ToString(letcnt), t.GetSort()) as VCExprVar;
+ VCExprLetBinding b = ctx.LetBinding(lv, res);
+ bindings.Add(b);
+ bindingMap.Add(t, lv);
+ res = lv;
+ letcnt++;
+ }
+ return res;
+ }
+
+ public Term Letify(Term t)
+ {
+ RefCnt(t);
+ Term res = Doit(t);
+ if (bindings.Count > 0)
+ res = ctx.Let(bindings, res);
+ return res;
+ }
+
+ }
+
+ public Term Letify(Term t)
+ {
+ var thing = new Letifier(this);
+ return thing.Letify(t);
+ }
+
+ };
+}
diff --git a/Source/VCGeneration/FixedpointVC.cs b/Source/VCGeneration/FixedpointVC.cs
index 7dbf6b05..c636ea2b 100644
--- a/Source/VCGeneration/FixedpointVC.cs
+++ b/Source/VCGeneration/FixedpointVC.cs
@@ -1,2229 +1,2245 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 2012 Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-
-
-using Term = Microsoft.Boogie.VCExprAST.VCExpr;
-using FuncDecl = Microsoft.Boogie.VCExprAST.VCExprOp;
-using Sort = Microsoft.Boogie.Type;
-using Microsoft.Boogie.ExprExtensions;
-
-
-namespace Microsoft.Boogie
-{
- public class FixedpointVC : VC.VCGen
- {
-
- public class AnnotationInfo
- {
- public enum AnnotationType { LoopInvariant, ProcedureSummary };
- public string filename;
- public int lineno;
- public string[] argnames;
- public AnnotationType type;
- };
-
- static bool NoLabels = false;
-
- // options
- bool largeblock = false;
-
- public bool SetOption(string option, string value)
- {
- if (option == "LargeBlock")
- {
- largeblock = true;
- return true;
- }
- return false;
- }
-
- Context ctx;
- RPFP rpfp;
- // Program program;
- Microsoft.Boogie.ProverContext boogieContext;
- Microsoft.Boogie.VCExpressionGenerator gen;
- public readonly static string recordProcName = "boogie_si_record"; // TODO: this really needed?
- private Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo
- = new Dictionary<string, StratifiedInliningInfo>();
- Checker checker;
- // Microsoft.Boogie.Z3.Z3InstanceOptions options = new Microsoft.Boogie.Z3.Z3InstanceOptions(); // TODO: what?
- LineariserOptions linOptions;
- Dictionary<FuncDecl, StratifiedInliningInfo> relationToProc = new Dictionary<FuncDecl, StratifiedInliningInfo>();
- Dictionary<string, Term> labels = new Dictionary<string, Term> ();
- List<Term> DualityVCs = new List<Term>();
- Dictionary<string, bool> summaries = new Dictionary<string, bool>();
- Dictionary<Block, List<Block>> edgesCut = new Dictionary<Block, List<Block>>();
- string main_proc_name = "main";
- Dictionary<string, int> extraRecBound = null;
-
-
- public enum Mode { Corral, OldCorral, Boogie};
- public enum AnnotationStyle { Flat, Procedure, Call };
-
- Mode mode;
- AnnotationStyle style;
-
- private static Checker old_checker = null;
-
- public static void CleanUp()
- {
- if (old_checker != null)
- {
- old_checker.Close();
- old_checker = null;
- }
- }
-
- public FixedpointVC( Program _program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers, Dictionary<string,int> _extraRecBound = null)
- : base(_program, logFilePath, appendLogFile, checkers)
- {
- switch (CommandLineOptions.Clo.FixedPointMode)
- {
- case CommandLineOptions.FixedPointInferenceMode.Corral:
- mode = Mode.Corral;
- style = AnnotationStyle.Procedure;
- break;
- case CommandLineOptions.FixedPointInferenceMode.OldCorral:
- mode = Mode.OldCorral;
- style = AnnotationStyle.Procedure;
- break;
- case CommandLineOptions.FixedPointInferenceMode.Flat:
- mode = Mode.Boogie;
- style = AnnotationStyle.Flat;
- break;
- case CommandLineOptions.FixedPointInferenceMode.Procedure:
- mode = Mode.Boogie;
- style = AnnotationStyle.Procedure;
- break;
- case CommandLineOptions.FixedPointInferenceMode.Call:
- mode = Mode.Boogie;
- style = AnnotationStyle.Call;
- break;
- }
- ctx = new Context(); // TODO is this right?
- rpfp = new RPFP(RPFP.CreateLogicSolver(ctx));
- program = _program;
- gen = ctx;
- if(old_checker == null)
- checker = new Checker(this, program, logFilePath, appendLogFile, CommandLineOptions.Clo.ProverKillTime, null);
- else {
- checker = old_checker;
- checker.RetargetWithoutReset(program,checker.TheoremProver.Context);
- }
- old_checker = checker;
- boogieContext = checker.TheoremProver.Context;
- linOptions = null; // new Microsoft.Boogie.Z3.Z3LineariserOptions(false, options, new List<VCExprVar>());
- extraRecBound = _extraRecBound;
- }
-
- Dictionary<string, AnnotationInfo> annotationInfo = new Dictionary<string, AnnotationInfo>();
-
- public void AnnotateLoops(Implementation impl, ProverContext ctxt)
- {
- Contract.Requires(impl != null);
-
- CurrentLocalVariables = impl.LocVars;
- variable2SequenceNumber = new Dictionary<Variable, int>();
- incarnationOriginMap = new Dictionary<Incarnation, Absy>();
-
- ResetPredecessors(impl.Blocks);
-
- #region Create the graph by adding the source node and each edge
- GraphUtil.Graph<Block> g = Program.GraphFromImpl(impl);
- #endregion
-
- //Graph<Block> g = program.ProcessLoops(impl);
-
- g.ComputeLoops(); // this is the call that does all of the processing
- if (!g.Reducible)
- {
- throw new System.Exception("Irreducible flow graphs are unsupported.");
- }
-
- #region add a symbolic annoation to every loop head
- foreach (Block header in cce.NonNull(g.Headers))
- AnnotateBlock(impl, ctxt, header);
- #endregion
- }
-
- private void AnnotateCallSites(Implementation impl, ProverContext ctxt, Dictionary<string, bool> impls){
- foreach (var b in impl.Blocks)
- {
- foreach (var cmd in b.Cmds)
- {
- if (cmd is CallCmd)
- {
- string name = (cmd as CallCmd).callee;
- if(impls.ContainsKey(name))
- goto annotate;
- }
- }
- continue;
- annotate:
- AnnotateBlock(impl, ctxt, b);
- }
- }
-
-
- private void AnnotateBlock(Implementation impl, ProverContext ctxt, Block header)
- {
- Contract.Assert(header != null);
-
- string name = impl.Name + "_" + header.Label + "_invar";
- if (annotationInfo.ContainsKey(name))
- return;
-
- // collect the variables needed in the invariant
- List<Expr> exprs = new List<Expr>();
- List<Variable> vars = new List<Variable>();
- List<string> names = new List<string>();
-
- if (style == AnnotationStyle.Flat)
- {
- // in flat mode, all live globals should be in live set
-#if false
- foreach (Variable v in program.GlobalVariables)
- {
- vars.Add(v);
- names.Add(v.ToString());
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
-#endif
- foreach (Variable v in /* impl.LocVars */ header.liveVarsBefore)
- {
- if (!(v is BoundVariable))
- {
- vars.Add(v);
- names.Add(v.ToString());
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- }
- }
- else
- {
- foreach (Variable v in program.GlobalVariables)
- {
- vars.Add(v);
- names.Add("@old_" + v.ToString());
- exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
- }
- foreach (IdentifierExpr ie in impl.Proc.Modifies)
- {
- if (ie.Decl == null)
- continue;
- vars.Add(ie.Decl);
- names.Add(ie.Decl.ToString());
- exprs.Add(ie);
- }
- foreach (Variable v in impl.Proc.InParams)
- {
- Contract.Assert(v != null);
- vars.Add(v);
- names.Add("@old_" + v.ToString());
- exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
- }
- foreach (Variable v in impl.LocVars)
- {
- vars.Add(v);
- names.Add(v.ToString());
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- }
-
- TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
- Contract.Assert(ti != null);
- Formal returnVar = new Formal(Token.NoToken, ti, false);
- Contract.Assert(returnVar != null);
- var function = new Function(Token.NoToken, name, vars, returnVar);
- ctxt.DeclareFunction(function, "");
-
- Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
- var invarAssertion = new AssertCmd(Token.NoToken, invarExpr);
- List<Cmd> newCmds = new List<Cmd>();
- newCmds.Add(invarAssertion);
-
- // make a record in annotationInfo;
- var info = new AnnotationInfo();
- info.filename = header.tok.filename;
- info.lineno = header.Line;
- info.argnames = names.ToArray();
- info.type = AnnotationInfo.AnnotationType.LoopInvariant;
- annotationInfo.Add(name, info);
- // get file and line info from havoc, if there is...
- if (header.Cmds.Count > 0)
- {
- PredicateCmd bif = header.Cmds[0] as PredicateCmd;
- if (bif != null)
- {
- string foo = QKeyValue.FindStringAttribute(bif.Attributes, "sourcefile");
- if (foo != null)
- info.filename = foo;
- int bar = QKeyValue.FindIntAttribute(bif.Attributes, "sourceline", -1);
- if (bar != -1)
- info.lineno = bar;
- }
- }
- var thing = header;
- foreach (Cmd c in header.Cmds)
- {
- newCmds.Add(c);
- }
- header.Cmds = newCmds;
- }
-
-#if true
- public void AnnotateProcRequires(Procedure proc, Implementation impl, ProverContext ctxt)
- {
- Contract.Requires(impl != null);
-
- CurrentLocalVariables = impl.LocVars;
-
- // collect the variables needed in the invariant
- List<Expr> exprs = new List<Expr>();
- List<Variable> vars = new List<Variable>();
- List<string> names = new List<string>();
-
- foreach (Variable v in program.GlobalVariables)
- {
- vars.Add(v);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- names.Add(v.Name);
- }
- foreach (Variable v in proc.InParams)
- {
- Contract.Assert(v != null);
- vars.Add(v);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- names.Add(v.Name);
- }
- string name = impl.Name + "_precond";
- TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
- Contract.Assert(ti != null);
- Formal returnVar = new Formal(Token.NoToken, ti, false);
- Contract.Assert(returnVar != null);
- var function = new Function(Token.NoToken, name, vars, returnVar);
- ctxt.DeclareFunction(function, "");
-
- Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
-
- proc.Requires.Add(new Requires(Token.NoToken, false, invarExpr, "", null));
-
- var info = new AnnotationInfo();
- info.filename = proc.tok.filename;
- info.lineno = proc.Line;
- info.argnames = names.ToArray();
- info.type = AnnotationInfo.AnnotationType.LoopInvariant;
- annotationInfo.Add(name, info);
- }
-
- public void AnnotateProcEnsures(Procedure proc, Implementation impl, ProverContext ctxt)
- {
- Contract.Requires(impl != null);
-
- CurrentLocalVariables = impl.LocVars;
-
- // collect the variables needed in the invariant
- List<Expr> exprs = new List<Expr>();
- List<Variable> vars = new List<Variable>();
- List<string> names = new List<string>();
-
- foreach (Variable v in program.GlobalVariables)
- {
- vars.Add(v);
- exprs.Add(new OldExpr(Token.NoToken,new IdentifierExpr(Token.NoToken, v)));
- names.Add(v.Name);
- }
- foreach (Variable v in proc.InParams)
- {
- Contract.Assert(v != null);
- vars.Add(v);
- exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
- names.Add(v.Name);
- }
- foreach (IdentifierExpr ie in proc.Modifies)
- {
- if (ie.Decl == null)
- continue;
- vars.Add(ie.Decl);
- exprs.Add(ie);
- names.Add(ie.Decl.Name + "_out");
- }
- foreach (Variable v in proc.OutParams)
- {
- Contract.Assert(v != null);
- vars.Add(v);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- names.Add(v.Name);
- }
- string name = impl.Name + "_summary";
- summaries.Add(name, true);
- TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
- Contract.Assert(ti != null);
- Formal returnVar = new Formal(Token.NoToken, ti, false);
- Contract.Assert(returnVar != null);
- var function = new Function(Token.NoToken, name, vars, returnVar);
- ctxt.DeclareFunction(function, "");
-
- Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
-
- proc.Ensures.Add(new Ensures(Token.NoToken, false, invarExpr, "", null));
-
- var info = new AnnotationInfo();
- info.filename = proc.tok.filename;
- info.lineno = proc.Line;
- info.argnames = names.ToArray();
- info.type = AnnotationInfo.AnnotationType.ProcedureSummary;
- annotationInfo.Add(name, info);
- }
-#endif
-
- void MarkAllFunctionImplementationsInline()
- {
- foreach (var func in program.Functions)
- {
- if (func.Body == null && func.DefinitionAxiom != null)
- {
- var def = func.DefinitionAxiom.Expr as QuantifierExpr;
- var bod = def.Body as NAryExpr;
- func.Body = bod.Args[1];
- func.DefinitionAxiom = null;
- }
- if (func.Body != null)
- if (func.FindExprAttribute("inline") == null)
- func.AddAttribute("inline", Expr.Literal(100));
- }
- }
-
- void InlineAll()
- {
- foreach (var impl in program.Implementations)
- {
- impl.OriginalBlocks = impl.Blocks;
- impl.OriginalLocVars = impl.LocVars;
- if(impl.Name != main_proc_name)
- if(impl.FindExprAttribute("inline") == null)
- impl.AddAttribute("inline", Expr.Literal(100));
- }
- foreach (var impl in program.Implementations)
- {
- if (!impl.SkipVerification)
- {
- Inliner.ProcessImplementation(program, impl);
- }
- }
- foreach (var impl in program.Implementations)
- {
- impl.OriginalBlocks = null;
- impl.OriginalLocVars = null;
- }
- }
-
- public class LazyInliningInfo
- {
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(impl != null);
- Contract.Invariant(function != null);
- Contract.Invariant(controlFlowVariable != null);
- Contract.Invariant(assertExpr != null);
- Contract.Invariant(cce.NonNullElements(interfaceVars));
- Contract.Invariant(incarnationOriginMap == null || cce.NonNullDictionaryAndValues(incarnationOriginMap));
- }
-
- public Implementation impl;
- public int uniqueId;
- public Function function;
- public Variable controlFlowVariable;
- public List<Variable> interfaceVars;
- public List<List<Variable>> interfaceVarCopies;
- public Expr assertExpr;
- public VCExpr vcexpr;
- public List<VCExprVar> privateVars;
- public Dictionary<Incarnation, Absy> incarnationOriginMap;
- public Hashtable /*Variable->Expr*/ exitIncarnationMap;
- public Hashtable /*GotoCmd->returnCmd*/ gotoCmdOrigins;
- public Dictionary<int, Absy> label2absy;
- public VC.ModelViewInfo mvInfo;
-
- public Dictionary<Block, VCExprVar> reachVars;
- public List<VCExprLetBinding> reachVarBindings;
- public Variable inputErrorVariable;
- public Variable outputErrorVariable;
-
-
-
- public LazyInliningInfo(Implementation impl, Program program, ProverContext ctxt, int uniqueId, GlobalVariable errorVariable)
- {
- Contract.Requires(impl != null);
- Contract.Requires(program != null);
- Procedure proc = cce.NonNull(impl.Proc);
-
- this.impl = impl;
- this.uniqueId = uniqueId;
- this.controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "cfc", Microsoft.Boogie.Type.Int));
- impl.LocVars.Add(controlFlowVariable);
-
- List<Variable> interfaceVars = new List<Variable>();
- Expr assertExpr = new LiteralExpr(Token.NoToken, true);
- Contract.Assert(assertExpr != null);
- foreach (Variable v in program.GlobalVariables)
- {
- Contract.Assert(v != null);
- interfaceVars.Add(v);
- if (v.Name == "error")
- inputErrorVariable = v;
- }
- // InParams must be obtained from impl and not proc
- foreach (Variable v in impl.InParams)
- {
- Contract.Assert(v != null);
- interfaceVars.Add(v);
- }
- // OutParams must be obtained from impl and not proc
- foreach (Variable v in impl.OutParams)
- {
- Contract.Assert(v != null);
- Constant c = new Constant(Token.NoToken,
- new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
- interfaceVars.Add(c);
- Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
- assertExpr = Expr.And(assertExpr, eqExpr);
- }
- if (errorVariable != null)
- {
- proc.Modifies.Add(new IdentifierExpr(Token.NoToken, errorVariable));
- }
- foreach (IdentifierExpr e in proc.Modifies)
- {
- Contract.Assert(e != null);
- if (e.Decl == null)
- continue;
- Variable v = e.Decl;
- Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
- interfaceVars.Add(c);
- if (v.Name == "error")
- {
- outputErrorVariable = c;
- continue;
- }
- Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
- assertExpr = Expr.And(assertExpr, eqExpr);
- }
-
- this.interfaceVars = interfaceVars;
- this.assertExpr = Expr.Not(assertExpr);
- List<Variable> functionInterfaceVars = new List<Variable>();
- foreach (Variable v in interfaceVars)
- {
- Contract.Assert(v != null);
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, v.Name, v.TypedIdent.Type), true));
- }
- TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
- Contract.Assert(ti != null);
- Formal returnVar = new Formal(Token.NoToken, ti, false);
- Contract.Assert(returnVar != null);
- this.function = new Function(Token.NoToken, proc.Name, functionInterfaceVars, returnVar);
- ctxt.DeclareFunction(this.function, "");
-
- interfaceVarCopies = new List<List<Variable>>();
- int temp = 0;
- for (int i = 0; i < /* CommandLineOptions.Clo.ProcedureCopyBound */ 0; i++)
- {
- interfaceVarCopies.Add(new List<Variable>());
- foreach (Variable v in interfaceVars)
- {
- Constant constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, v.Name + temp++, v.TypedIdent.Type));
- interfaceVarCopies[i].Add(constant);
- //program.AddTopLevelDeclaration(constant);
- }
- }
- }
- }
-
- public class StratifiedInliningInfo : LazyInliningInfo
- {
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(cce.NonNullElements(privateVars));
- Contract.Invariant(cce.NonNullElements(interfaceExprVars));
- Contract.Invariant(cce.NonNullElements(interfaceExprVars));
- }
-
- // public StratifiedVCGenBase vcgen;
- //public Implementation impl;
- //public Program program;
- //public ProverContext ctxt;
- //public int uniqueid;
- //public Function function;
- //public Variable controlFlowVariable;
- //public Expr assertExpr;
- //public VCExpr vcexpr;
- //public List<VCExprVar> interfaceExprVars;
- //public List<VCExprVar> privateExprVars;
- //public Dictionary<int, Absy> label2absy;
- //public VC.ModelViewInfo mvInfo;
- //public Dictionary<Block, List<CallSite>> callSites;
- //public Dictionary<Block, List<CallSite>> recordProcCallSites;
- //public IEnumerable<Block> sortedBlocks;
- //public bool initialized { get; private set; }
-
-
- public List<VCExprVar> interfaceExprVars;
- // public List<VCExprVar> privateVars;
- public VCExpr funcExpr;
- public VCExpr falseExpr;
- public RPFP.Transformer F;
- public RPFP.Node node;
- public RPFP.Edge edge;
- public bool isMain = false;
- public Dictionary<Absy, string> label2absyInv;
- public ProverContext ctxt;
- public Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
- public List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
-
- public StratifiedInliningInfo(Implementation _impl, Program _program, ProverContext _ctxt, int _uniqueid)
- : base(_impl,_program,_ctxt,_uniqueid,null){
- Contract.Requires(_impl != null);
- Contract.Requires(_program != null);
- privateVars = new List<VCExprVar>();
- interfaceExprVars = new List<VCExprVar>();
- ctxt = _ctxt;
- }
-
- }
-
- protected override void addExitAssert(string implName, Block exitBlock)
- {
- if (implName2StratifiedInliningInfo != null
- && implName2StratifiedInliningInfo.ContainsKey(implName)
- && !implName2StratifiedInliningInfo[implName].isMain)
- {
- if (mode == Mode.Boogie) return;
- Expr assertExpr = implName2StratifiedInliningInfo[implName].assertExpr;
- Contract.Assert(assertExpr != null);
- exitBlock.Cmds.Add(new AssertCmd(Token.NoToken, assertExpr));
- }
- }
-
-#if false
- protected override void storeIncarnationMaps(string implName, Hashtable exitIncarnationMap)
- {
- if (implName2StratifiedInliningInfo != null && implName2StratifiedInliningInfo.ContainsKey(implName))
- {
- StratifiedInliningInfo info = implName2StratifiedInliningInfo[implName];
- Contract.Assert(info != null);
- info.exitIncarnationMap = exitIncarnationMap;
- info.incarnationOriginMap = this.incarnationOriginMap;
- }
- }
-#endif
-
- public void GenerateVCsForStratifiedInlining()
- {
- Contract.Requires(program != null);
- foreach (var impl in program.Implementations)
- {
- Contract.Assert(!impl.Name.StartsWith(recordProcName), "Not allowed to have an implementation for this guy");
-
- Procedure proc = cce.NonNull(impl.Proc);
-
- {
- StratifiedInliningInfo info = new StratifiedInliningInfo(impl, program, boogieContext, QuantifierExpr.GetNextSkolemId());
- implName2StratifiedInliningInfo[impl.Name] = info;
- // We don't need controlFlowVariable for stratified Inlining
- //impl.LocVars.Add(info.controlFlowVariable);
- List<Expr> exprs = new List<Expr>();
-
- if (mode != Mode.Boogie && QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
- {
- proc.Ensures.Add(new Ensures(Token.NoToken, true, Microsoft.Boogie.Expr.False, "", null));
- info.assertExpr = Microsoft.Boogie.Expr.False;
- // info.isMain = true;
- }
- else if (mode == Mode.Corral || proc.FindExprAttribute("inline") != null || proc is LoopProcedure)
- {
- foreach (Variable v in program.GlobalVariables)
- {
- Contract.Assert(v != null);
- exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
- }
- foreach (Variable v in proc.InParams)
- {
- Contract.Assert(v != null);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- foreach (Variable v in proc.OutParams)
- {
- Contract.Assert(v != null);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- foreach (IdentifierExpr ie in proc.Modifies)
- {
- Contract.Assert(ie != null);
- if (ie.Decl == null)
- continue;
- exprs.Add(ie);
- }
- Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(info.function), exprs);
-#if true
- if(mode == Mode.Corral || mode == Mode.OldCorral)
- proc.Ensures.Add(new Ensures(Token.NoToken, true, freePostExpr, "", new QKeyValue(Token.NoToken, "si_fcall", new List<object>(), null)));
-#endif
- }
- else // not marked "inline" must be main
- {
- Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(info.function), exprs);
- info.isMain = true;
- }
- }
- }
-
- if (mode == Mode.Boogie) return;
-
- foreach (var proc in program.Procedures)
- {
- if (!proc.Name.StartsWith(recordProcName)) continue;
- Contract.Assert(proc.InParams.Count == 1);
-
- // Make a new function
- TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
- Contract.Assert(ti != null);
- Formal returnVar = new Formal(Token.NoToken, ti, false);
- Contract.Assert(returnVar != null);
-
- // Get record type
- var argtype = proc.InParams[0].TypedIdent.Type;
-
- var ins = new List<Variable>();
- ins.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", argtype), true));
-
- var recordFunc = new Function(Token.NoToken, proc.Name, ins, returnVar);
- boogieContext.DeclareFunction(recordFunc, "");
-
- var exprs = new List<Expr>();
- exprs.Add(new IdentifierExpr(Token.NoToken, proc.InParams[0]));
-
- Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(recordFunc), exprs);
- proc.Ensures.Add(new Ensures(true, freePostExpr));
- }
- }
-
- private void FixedPointToSpecs(){
-
- if(mode != Mode.Corral || CommandLineOptions.Clo.PrintFixedPoint == null)
- return; // not implemented for other annotation modes yet
-
- var twr = new TokenTextWriter(CommandLineOptions.Clo.PrintFixedPoint, /*pretty=*/ false);
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node> ();
-
- foreach (var node in rpfp.nodes)
- pmap.Add ((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
-
- foreach (var impl in program.Implementations)
- {
- Contract.Assert(!impl.Name.StartsWith(recordProcName), "Not allowed to have an implementation for this guy");
-
- Procedure proc = cce.NonNull(impl.Proc);
-
- {
- StratifiedInliningInfo info = new StratifiedInliningInfo(impl, program, boogieContext, QuantifierExpr.GetNextSkolemId());
- implName2StratifiedInliningInfo[impl.Name] = info;
- // We don't need controlFlowVariable for stratified Inlining
- //impl.LocVars.Add(info.controlFlowVariable);
- List<Expr> exprs = new List<Expr>();
-
- {
- if (pmap.ContainsKey(impl.Name))
- {
- RPFP.Node node = pmap[impl.Name];
- var annot = node.Annotation;
- EmitProcSpec(twr, proc, info, annot);
- }
- }
- }
- }
- twr.Close ();
- }
-
- private void EmitProcSpec(TokenTextWriter twr, Procedure proc, StratifiedInliningInfo info, RPFP.Transformer annot)
- {
- // last ensures clause will be the symbolic one
- if (!info.isMain)
- {
- var ens = proc.Ensures[proc.Ensures.Count - 1];
- if (ens.Condition != Expr.False) // this is main
- {
- var postExpr = ens.Condition as NAryExpr;
- var args = postExpr.Args;
-
- var ind = annot.IndParams;
- var bound = new Dictionary<VCExpr, Expr>();
- for (int i = 0; i < args.Count; i++)
- {
- bound[ind[i]] = args[i];
- }
- var new_ens_cond = VCExprToExpr(annot.Formula, bound);
- if (new_ens_cond != Expr.True)
- {
- var new_ens = new Ensures(false, new_ens_cond);
- var enslist = new List<Ensures>();
- enslist.Add(new_ens);
- var new_proc = new Procedure(proc.tok, proc.Name, proc.TypeParameters, proc.InParams,
- proc.OutParams, new List<Requires>(), new List<IdentifierExpr>(), enslist);
- new_proc.Emit(twr, 0);
- }
- }
- }
- }
-
- static int ConjectureFileCounter = 0;
-
- private void ConjecturesToSpecs()
- {
-
- if (mode != Mode.Corral || CommandLineOptions.Clo.PrintConjectures == null)
- return; // not implemented for other annotation modes yet
-
- var twr = new TokenTextWriter(CommandLineOptions.Clo.PrintConjectures + "." + ConjectureFileCounter.ToString(), /*pretty=*/ false);
- ConjectureFileCounter++;
-
- foreach (var c in rpfp.conjectures)
- {
- var name = c.node.Name.GetDeclName();
- if (implName2StratifiedInliningInfo.ContainsKey(name))
- {
- StratifiedInliningInfo info = implName2StratifiedInliningInfo[c.node.Name.GetDeclName()];
- Implementation impl = info.impl;
- Procedure proc = impl.Proc;
- EmitProcSpec(twr, proc, info, c.bound);
- }
- }
-
- twr.Close ();
- }
-
- private Term ExtractSmallerVCsRec(TermDict< Term> memo, Term t, List<Term> small, Term lbl = null)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- var f = t.GetAppDecl();
- if (f.GetKind() == DeclKind.Implies){
- var lhs = t.GetAppArgs()[0];
- if(lhs.GetKind() == TermKind.App){
- var r = lhs.GetAppDecl();
- if (r.GetKind() == DeclKind.And)
- {
- Term q = t.GetAppArgs()[1];
- var lhsargs = lhs.GetAppArgs();
- for (int i = lhsargs.Length-1; i >= 0; --i)
- {
- q = ctx.MkImplies(lhsargs[i], q);
- }
- res = ExtractSmallerVCsRec(memo, q, small,lbl);
- goto done;
- }
- if (r.GetKind() == DeclKind.Label)
- {
- var arg = lhs;
- arg = lhs.GetAppArgs()[0];
- if (!(arg.GetKind() == TermKind.App && arg.GetAppDecl().GetKind() == DeclKind.Uninterpreted))
- goto normal;
- if (!(annotationInfo.ContainsKey(arg.GetAppDecl().GetDeclName()) && annotationInfo[arg.GetAppDecl().GetDeclName()].type == AnnotationInfo.AnnotationType.LoopInvariant))
- goto normal;
- var sm = ctx.MkImplies(lhs, ExtractSmallerVCsRec(memo, t.GetAppArgs()[1], small));
- if (lbl != null)
- sm = ctx.MkImplies(lbl, sm);
- small.Add(sm);
- res = ctx.MkTrue();
- goto done;
- }
- if (r.GetKind() == DeclKind.Uninterpreted)
- {
- var arg = lhs;
- if (!(annotationInfo.ContainsKey(arg.GetAppDecl().GetDeclName()) && annotationInfo[arg.GetAppDecl().GetDeclName()].type == AnnotationInfo.AnnotationType.LoopInvariant))
- goto normal;
- var sm = ctx.MkImplies(lhs,ExtractSmallerVCsRec(memo,t.GetAppArgs()[1],small));
- if (lbl != null)
- sm = ctx.MkImplies(lbl, sm);
- small.Add(sm);
- res = ctx.MkTrue();
- goto done;
- }
- }
- normal:
- Term newlbl = null;
- if (lhs.IsLabel() && lhs.GetAppArgs()[0] == ctx.MkTrue())
- newlbl = lhs;
- res = ctx.MkImplies(lhs,ExtractSmallerVCsRec(memo,t.GetAppArgs()[1],small,newlbl));
- }
- else if (f.GetKind() == DeclKind.And)
- {
- res = ctx.MkApp(f,t.GetAppArgs().Select(x => ExtractSmallerVCsRec(memo, x, small)).ToArray());
- }
- else
- res = t;
- }
- else
- res = t;
- done:
- memo.Add(t, res);
- return res;
- }
-
- private void ExtractSmallerVCs(Term t, List<Term> small){
- TermDict< Term> memo = new TermDict< Term>();
- Term top = ExtractSmallerVCsRec(memo, t, small);
- small.Add(top);
- }
-
- private Dictionary<FuncDecl, int> goalNumbering = new Dictionary<FuncDecl, int>();
-
- private Term NormalizeGoal(Term goal, FuncDecl label)
- {
- var f = goal.GetAppDecl();
- var args = goal.GetAppArgs();
- int number;
- if (!goalNumbering.TryGetValue(f, out number))
- {
- number = goalNumbering.Count;
- goalNumbering.Add(f, number);
- }
- Term[] tvars = new Term[args.Length];
- Term[] eqns = new Term[args.Length];
- AnnotationInfo info = null;
- annotationInfo.TryGetValue(f.GetDeclName(), out info);
- for (int i = 0; i < args.Length; i++)
- {
- string pname = (info == null) ? i.ToString() : info.argnames[i];
- tvars[i] = ctx.MkConst("@a" + number.ToString() + "_" + pname, args[i].GetSort());
- eqns[i] = ctx.MkEq(tvars[i], args[i]);
- }
- return ctx.MkImplies(ctx.MkAnd(eqns), ctx.MkApp(label, ctx.MkApp(f, tvars)));
- }
-
- private Term MergeGoalsRec(TermDict< Term> memo, Term t)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- var f = t.GetAppDecl();
- var args = t.GetAppArgs();
- if (f.GetKind() == DeclKind.Implies)
- {
- res = ctx.MkImplies(args[0], MergeGoalsRec(memo, args[1]));
- goto done;
- }
- else if (f.GetKind() == DeclKind.And)
- {
- args = args.Select(x => MergeGoalsRec(memo, x)).ToArray();
- res = ctx.MkApp(f, args);
- goto done;
- }
- else if (f.GetKind() == DeclKind.Label)
- {
- var arg = t.GetAppArgs()[0];
- var r = arg.GetAppDecl();
- if (r.GetKind() == DeclKind.Uninterpreted)
- {
- res = NormalizeGoal(arg, f);
- goto done;
- }
- }
- }
- res = t;
- done:
- memo.Add(t, res);
- return res;
- }
-
- private Term MergeGoals(Term t)
- {
- TermDict< Term> memo = new TermDict< Term>();
- return MergeGoalsRec(memo, t);
- }
-
- private Term CollectGoalsRec(TermDict< Term> memo, Term t, List<Term> goals, List<Term> cruft)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- var f = t.GetAppDecl();
- if (f.GetKind() == DeclKind.Implies)
- {
- CollectGoalsRec(memo, t.GetAppArgs()[1], goals, cruft);
- goto done;
- }
- else if (f.GetKind() == DeclKind.And)
- {
- foreach (var arg in t.GetAppArgs())
- {
- CollectGoalsRec(memo, arg, goals, cruft);
- }
- goto done;
- }
- else if (f.GetKind() == DeclKind.Label)
- {
- var arg = t.GetAppArgs()[0];
- if (arg.GetKind() == TermKind.App && arg.GetAppDecl().GetKind() == DeclKind.Uninterpreted)
- {
- var r = arg.GetAppDecl();
- if (memo.TryGetValue(arg, out res))
- goto done;
- if (!annotationInfo.ContainsKey(r.GetDeclName()) && !arg.GetAppDecl().GetDeclName().StartsWith("_solve_"))
- goto done;
- goals.Add(arg);
- memo.Add(arg, arg);
- goto done;
- }
- else
- return CollectGoalsRec(memo, arg, goals, cruft);
- }
- else if (f.GetKind() == DeclKind.Uninterpreted)
- {
- string name = f.GetDeclName();
- if (name.StartsWith("_solve_"))
- {
- if (memo.TryGetValue(t, out res))
- goto done;
- goals.Add(t);
- memo.Add(t, t);
- return t;
- }
- }
- }
- // else the goal must be cruft
- cruft.Add(t);
- done:
- res = t; // just to return something
- memo.Add(t, res);
- return res;
- }
-
- private void CollectGoals(Term t, List<Term> goals, List<Term> cruft)
- {
- TermDict< Term> memo = new TermDict< Term>();
- CollectGoalsRec(memo, t.GetAppArgs()[1], goals, cruft);
- }
-
- private Term SubstRec(TermDict< Term> memo, Term t)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- // var f = t.GetAppDecl();
- var args = t.GetAppArgs().Select(x => SubstRec(memo, x)).ToArray();
- res = ctx.CloneApp(t, args);
- }
- else res = t;
- memo.Add(t, res);
- return res;
- }
-
- private Term SubstRecGoals(TermDict< Term> memo, Term t)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- var f = t.GetAppDecl();
- var args = t.GetAppArgs();
- if (f.GetKind() == DeclKind.Implies){
- res = SubstRecGoals(memo, args[1]);
- if (res != ctx.MkTrue())
- res = ctx.MkImplies(args[0],res);
- goto done;
- }
- else if (f.GetKind() == DeclKind.And)
- {
- args = args.Select(x => SubstRecGoals(memo, x)).ToArray();
- args = args.Where(x => x != ctx.MkTrue()).ToArray();
- res = ctx.MkAnd(args);
- goto done;
- }
- else if (f.GetKind() == DeclKind.Label)
- {
- var arg = t.GetAppArgs()[0];
- if (arg.GetKind() == TermKind.App && arg.GetAppDecl().GetKind() == DeclKind.Uninterpreted)
- {
- var r = arg.GetAppDecl();
- if (memo.TryGetValue(arg, out res))
- {
- if(res != ctx.MkTrue())
- res = ctx.MkApp(f, res);
- goto done;
- }
- }
- else
- {
- res = ctx.MkApp(f, SubstRecGoals(memo, arg));
- goto done;
- }
-
- }
- // what's left could be cruft!
- if (memo.TryGetValue(t, out res))
- {
- goto done;
- }
- }
- res = t;
- done:
- memo.Add(t, res);
- return res;
- }
-
- private void FactorVCs(Term t, List<Term> vcs)
- {
- List<Term> small = new List<Term>();
- ExtractSmallerVCs(t, small);
- foreach (var smm in small)
- {
- List<Term> goals = new List<Term>();
- List<Term> cruft = new List<Term>();
- var sm = largeblock ? MergeGoals(smm) : smm;
- CollectGoals(sm, goals,cruft);
- foreach (var goal in goals)
- {
- TermDict< Term> memo = new TermDict< Term>();
- foreach (var othergoal in goals)
- memo.Add(othergoal, othergoal.Equals(goal) ? ctx.MkFalse() : ctx.MkTrue());
- foreach (var thing in cruft)
- memo.Add(thing, ctx.MkTrue());
- var vc = SubstRecGoals(memo, sm);
- vc = ctx.MkImplies(ctx.MkNot(vc), goal);
- vcs.Add(vc);
- }
- {
- TermDict< Term> memo = new TermDict< Term>();
- foreach (var othergoal in goals)
- memo.Add(othergoal, ctx.MkTrue());
- var vc = SubstRecGoals(memo, sm);
- if (vc != ctx.MkTrue())
- {
- vc = ctx.MkImplies(ctx.MkNot(vc), ctx.MkFalse());
- vcs.Add(vc);
- }
- }
- }
- }
-
-
-
- private void GenerateVCForStratifiedInlining(Program program, StratifiedInliningInfo info, Checker checker)
- {
- Contract.Requires(program != null);
- Contract.Requires(info != null);
- Contract.Requires(checker != null);
- Contract.Requires(info.impl != null);
- Contract.Requires(info.impl.Proc != null);
-
-
-
- Implementation impl = info.impl;
- if (mode == Mode.Boogie && style == AnnotationStyle.Flat && impl.Name != main_proc_name)
- return;
- Contract.Assert(impl != null);
- ConvertCFG2DAG(impl,edgesCut);
- VC.ModelViewInfo mvInfo;
- PassifyImpl(impl, out mvInfo);
- Dictionary<int, Absy> label2absy = null;
- VCExpressionGenerator gen = checker.VCExprGen;
- Contract.Assert(gen != null);
- VCExpr vcexpr;
- if(NoLabels){
- // int assertionCount = 0;
- VCExpr startCorrect = null; /* VC.VCGen.LetVC(cce.NonNull(impl.Blocks[0]), null, null, info.blockVariables, info.bindings,
- info.ctxt, out assertionCount); */
- vcexpr = gen.Let(info.bindings, startCorrect);
- }
- else vcexpr = GenerateVC(impl, null /* info.controlFlowVariable */, out label2absy, info.ctxt);
- if(mode != Mode.Boogie)
- vcexpr = gen.Not(vcexpr);
- Contract.Assert(vcexpr != null);
- info.label2absy = label2absy;
- info.mvInfo = mvInfo;
- List<VCExpr> interfaceExprs = new List<VCExpr>();
-
- if (true /* was: !info.isMain */)
- {
- Boogie2VCExprTranslator translator = checker.TheoremProver.Context.BoogieExprTranslator;
- Contract.Assert(translator != null);
- info.privateVars = new List<VCExprVar>();
- foreach (Variable v in impl.LocVars)
- {
- Contract.Assert(v != null);
- info.privateVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in impl.OutParams)
- {
- Contract.Assert(v != null);
- info.privateVars.Add(translator.LookupVariable(v));
- }
-
- info.interfaceExprVars = new List<VCExprVar>();
-
- foreach (Variable v in info.interfaceVars)
- {
- Contract.Assert(v != null);
- VCExprVar ev = translator.LookupVariable(v);
- Contract.Assert(ev != null);
- info.interfaceExprVars.Add(ev);
- interfaceExprs.Add(ev);
- }
- }
-
- Function function = cce.NonNull(info.function);
- Contract.Assert(function != null);
- info.funcExpr = gen.Function(function, interfaceExprs);
- info.vcexpr = vcexpr;
-
- if (mode == Mode.Boogie)
- {
- Term z3vc = boogieContext.VCExprToTerm(vcexpr, linOptions);
- FactorVCs(z3vc, DualityVCs);
- }
- else
- {
- // Index the procedures by relational variable
- FuncDecl R = boogieContext.VCExprToTerm(info.funcExpr, linOptions).GetAppDecl();
- relationToProc.Add(R, info);
- info.node = rpfp.CreateNode(boogieContext.VCExprToTerm(info.funcExpr, linOptions));
- rpfp.nodes.Add(info.node);
- if (info.isMain || QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
- info.node.Bound.Formula = ctx.MkFalse();
- }
- }
-
- // This returns a new FuncDel with same sort as top-level function
- // of term t, but with numeric suffix appended to name.
-
- private FuncDecl SuffixFuncDecl(Term t, int n)
- {
- var name = t.GetAppDecl().GetDeclName() + "_" + n.ToString();
- return ctx.MkFuncDecl(name, t.GetAppDecl());
- }
-
- // Collect the relational paremeters
-
- private Term CollectParamsRec(TermDict<Term> memo, Term t, List<FuncDecl> parms, List<RPFP.Node> nodes, Dictionary<Term,Term> done)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- var kind = t.GetKind();
- if (kind == TermKind.App)
- {
- var f = t.GetAppDecl();
- var args = t.GetAppArgs();
- args = args.Select(x => CollectParamsRec(memo, x, parms, nodes, done)).ToArray();
- StratifiedInliningInfo info;
- if (relationToProc.TryGetValue(f, out info))
- {
- if (done.ContainsKey(t))
- res = done[t];
- else
- {
- f = SuffixFuncDecl(t, parms.Count);
- parms.Add(f);
- nodes.Add(info.node);
- res = ctx.MkApp(f, args);
- done.Add(t,res); // don't count same expression twice!
- }
- }
- else
- res = ctx.CloneApp(t, args);
- } // TODO: handle quantifiers
- else res = t;
- memo.Add(t, res);
- return res;
- }
-
- public void GetTransformer(StratifiedInliningInfo info)
- {
- Term vcTerm = boogieContext.VCExprToTerm(info.vcexpr, linOptions);
- Term[] paramTerms = info.interfaceExprVars.Select(x => boogieContext.VCExprToTerm(x, linOptions)).ToArray();
- var relParams = new List<FuncDecl>();
- var nodeParams = new List<RPFP.Node>();
- var memo = new TermDict< Term>();
- var done = new Dictionary<Term,Term>(); // note this hashes on equality, not reference!
- vcTerm = CollectParamsRec(memo, vcTerm, relParams, nodeParams,done);
- // var ops = new Util.ContextOps(ctx);
- // var foo = ops.simplify_lhs(vcTerm);
- // vcTerm = foo.Item1;
- info.F = rpfp.CreateTransformer(relParams.ToArray(), paramTerms, vcTerm);
- info.edge = rpfp.CreateEdge(info.node, info.F, nodeParams.ToArray());
- rpfp.edges.Add(info.edge);
- // TODO labels[info.edge.number] = foo.Item2;
- }
-
- public RPFP.Node GetNodeOfImpl(Implementation/*!*/ impl)
- {
- return implName2StratifiedInliningInfo[impl.Name].node;
- }
-
- public class CyclicLiveVariableAnalysis : Microsoft.Boogie.LiveVariableAnalysis
- {
- public new static void ComputeLiveVariables(Implementation impl)
- {
-
- bool some_change = true;
- List<Block> sortedNodes = new List<Block>();
- foreach (var block in impl.Blocks)
- {
- sortedNodes.Add(block);
- }
- sortedNodes.Reverse();
-
- while (some_change)
- {
- some_change = false;
- foreach (Block/*!*/ block in sortedNodes)
- {
- Contract.Assert(block != null);
- HashSet<Variable/*!*/>/*!*/ liveVarsAfter = new HashSet<Variable/*!*/>();
- if (block.TransferCmd is GotoCmd)
- {
- GotoCmd gotoCmd = (GotoCmd)block.TransferCmd;
- if (gotoCmd.labelTargets != null)
- {
- foreach (Block/*!*/ succ in gotoCmd.labelTargets)
- {
- Contract.Assert(succ != null);
- if (succ.liveVarsBefore != null)
- liveVarsAfter.UnionWith(succ.liveVarsBefore);
- }
- }
- }
-
- List<Cmd> cmds = block.Cmds;
- int len = cmds.Count;
- for (int i = len - 1; i >= 0; i--)
- {
- if (cmds[i] is CallCmd)
- {
- Procedure/*!*/ proc = cce.NonNull(cce.NonNull((CallCmd/*!*/)cmds[i]).Proc);
- if (InterProcGenKill.HasSummary(proc.Name))
- {
- liveVarsAfter =
- InterProcGenKill.PropagateLiveVarsAcrossCall(cce.NonNull((CallCmd/*!*/)cmds[i]), liveVarsAfter);
- continue;
- }
- }
- Propagate(cmds[i], liveVarsAfter);
- }
-
- if (block.liveVarsBefore == null)
- block.liveVarsBefore = new HashSet<Variable>();
- if (!liveVarsAfter.IsSubsetOf(block.liveVarsBefore))
- {
- block.liveVarsBefore = liveVarsAfter;
- some_change = true;
- }
- }
- }
- }
- }
-
- public void Generate()
- {
-
- var oldDagOption = CommandLineOptions.Clo.vcVariety;
- CommandLineOptions.Clo.vcVariety = CommandLineOptions.VCVariety.Dag;
-
- // MarkAllFunctionImplementationsInline(); // This is for SMACK, which goes crazy with functions
-
- // Run live variable analysis (TODO: should this be here?)
-#if false
- if (CommandLineOptions.Clo.LiveVariableAnalysis == 2)
- {
- Microsoft.Boogie.InterProcGenKill.ComputeLiveVars(impl, program);
- }
-#endif
-
- #region In Boogie mode, annotate the program
- if (mode == Mode.Boogie)
- {
-
- // find the name of the main procedure
- main_proc_name = null; // default in case no entry point defined
- foreach (var impl in program.Implementations)
- {
- if (QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
- main_proc_name = impl.Proc.Name;
- }
- if (main_proc_name == null)
- {
- foreach (var impl in program.Implementations)
- {
- if (impl.Proc.Name == "main" || impl.Proc.Name.EndsWith(".main"))
- main_proc_name = impl.Proc.Name;
- }
- }
- if (main_proc_name == null)
- main_proc_name = "main";
-
- if (style == AnnotationStyle.Flat)
- {
- InlineAll();
- Microsoft.Boogie.BlockCoalescer.CoalesceBlocks(program);
- foreach (var impl in program.Implementations)
- {
- if (main_proc_name == impl.Proc.Name)
- {
- Microsoft.Boogie.LiveVariableAnalysis.ClearLiveVariables(impl);
- CyclicLiveVariableAnalysis.ComputeLiveVariables(impl);
- AnnotateLoops(impl, boogieContext);
- }
- }
- }
- else
- {
-
- if (style == AnnotationStyle.Procedure || style == AnnotationStyle.Call)
- {
- foreach (var impl in program.Implementations)
- {
- if (!QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
- AnnotateProcRequires(impl.Proc, impl, boogieContext);
- AnnotateProcEnsures(impl.Proc, impl, boogieContext);
- }
- if (style == AnnotationStyle.Call)
- {
-
- }
- }
-
- // must do this after annotating procedures, else calls
- // will be prematurely desugared
-
- foreach (var impl in program.Implementations)
- {
- Microsoft.Boogie.LiveVariableAnalysis.ClearLiveVariables(impl);
- CyclicLiveVariableAnalysis.ComputeLiveVariables(impl);
- }
-
-
- if (style == AnnotationStyle.Flat || style == AnnotationStyle.Call)
- {
- foreach (var impl in program.Implementations)
- {
- AnnotateLoops(impl, boogieContext);
- }
- }
- if (style == AnnotationStyle.Call)
- {
- Dictionary<string, bool> impls = new Dictionary<string, bool>();
- foreach (var impl in program.Implementations)
- {
- impls.Add(impl.Proc.Name, true);
- }
- foreach (var impl in program.Implementations)
- {
- AnnotateCallSites(impl, boogieContext, impls);
- }
- }
- if (style == AnnotationStyle.Flat)
- InlineAll();
- }
- }
- #endregion
-
- /* Generate the VC's */
- GenerateVCsForStratifiedInlining();
-
- /* Generate the background axioms */
- Term background = ctx.MkTrue(); // TODO boogieContext.VCExprToTerm(boogieContext.Axioms, linOptions);
- rpfp.AssertAxiom(background);
-
- int save_option = CommandLineOptions.Clo.StratifiedInlining; // need this to get funcall labels
- CommandLineOptions.Clo.StratifiedInlining = 1;
-
- /* Create the nodes, indexing procedures by their relational symbols. */
- foreach (StratifiedInliningInfo info in implName2StratifiedInliningInfo.Values)
- GenerateVCForStratifiedInlining(program, info, checker);
-
- CommandLineOptions.Clo.StratifiedInlining = save_option;
-
- if (mode == Mode.Boogie)
- {
- // var ops = new Util.ContextOps(ctx);
- var vcs = DualityVCs;
- DualityVCs = new List<Term>();
- foreach (var vc in vcs)
- {
- // var foo = ops.simplify_lhs(vc.GetAppArgs()[0]);
- var foo = vc.GetAppArgs()[0];
- if (!foo.IsFalse())
- DualityVCs.Add(ctx.MkImplies(foo, vc.GetAppArgs()[1]));
- }
-
- rpfp.FromClauses(DualityVCs.ToArray());
- // TODO rpfp.HornClauses = style == AnnotationStyle.Flat;
- }
- else
- {
- /* Generate the edges. */
- foreach (StratifiedInliningInfo info in implName2StratifiedInliningInfo.Values)
- GetTransformer(info);
- }
-
- // save some information for debugging purposes
- // TODO rpfp.ls.SetAnnotationInfo(annotationInfo);
-
- CommandLineOptions.Clo.vcVariety = oldDagOption;
- }
-
-
- private class ErrorHandler : ProverInterface.ErrorHandler
- {
- //TODO: anything we need to handle?
- }
-
- Dictionary<int, Dictionary<string, string>> varSubst = null;
-
- /** Check the RPFP, and return a counterexample if there is one. */
-
- public RPFP.LBool Check(ref RPFP.Node cexroot)
- {
- var start = DateTime.Now;
-
- ErrorHandler handler = new ErrorHandler();
- RPFP.Node cex;
- varSubst = new Dictionary<int,Dictionary<string,string>>();
-
-#if false
- int origRecursionBound = CommandLineOptions.Clo.RecursionBound;
- if (CommandLineOptions.Clo.RecursionBound > 0 && extraRecBound != null)
- {
- int maxExtra = 0;
- foreach (string s in extraRecBound.Keys)
- {
- int extra = extraRecBound[s];
- if (extra > maxExtra) maxExtra = extra;
- }
- CommandLineOptions.Clo.RecursionBound += maxExtra;
- }
-#endif
-
- ProverInterface.Outcome outcome =
- checker.TheoremProver.CheckRPFP("name", rpfp, handler, out cex, varSubst, extraRecBound);
- cexroot = cex;
-
-#if false
- CommandLineOptions.Clo.RecursionBound = origRecursionBound;
-#endif
-
- Console.WriteLine("solve: {0}s", (DateTime.Now - start).TotalSeconds);
-
- switch(outcome)
- {
- case ProverInterface.Outcome.Valid:
- return RPFP.LBool.False;
- case ProverInterface.Outcome.Invalid:
- return RPFP.LBool.True;
- default:
- return RPFP.LBool.Undef;
- }
- }
-
- private bool generated = false;
-
- static private Object thisLock = new Object();
-
- public override VC.VCGen.Outcome VerifyImplementation(Implementation impl, VerifierCallback collector)
- {
-
- lock (thisLock)
- {
- Procedure proc = impl.Proc;
-
- // we verify all the impls at once, so we need to execute only once
- // TODO: make sure needToCheck is true only once
- bool needToCheck = false;
- if (mode == Mode.OldCorral)
- needToCheck = proc.FindExprAttribute("inline") == null && !(proc is LoopProcedure);
- else if (mode == Mode.Corral || mode == Mode.Boogie)
- needToCheck = QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint") && !(proc is LoopProcedure);
- else
- needToCheck = impl.Name == main_proc_name;
-
- if (needToCheck)
- {
-
- var start = DateTime.Now;
-
- if (!generated)
- {
- Generate();
- Console.WriteLine("generate: {0}s", (DateTime.Now - start).TotalSeconds);
- generated = true;
- }
-
-
- Console.WriteLine("Verifying {0}...", impl.Name);
-
- RPFP.Node cexroot = null;
- // start = DateTime.Now;
- var checkres = Check(ref cexroot);
- Console.WriteLine("check: {0}s", (DateTime.Now - start).TotalSeconds);
- switch (checkres)
- {
- case RPFP.LBool.True:
- Console.WriteLine("Counterexample found.\n");
- // start = DateTime.Now;
- Counterexample cex = CreateBoogieCounterExample(cexroot.owner, cexroot, impl);
- // cexroot.owner.DisposeDualModel();
- // cex.Print(0); // just for testing
- collector.OnCounterexample(cex, "assertion failure");
- Console.WriteLine("cex: {0}s", (DateTime.Now - start).TotalSeconds);
- ConjecturesToSpecs();
- return VC.ConditionGeneration.Outcome.Errors;
- case RPFP.LBool.False:
- Console.WriteLine("Procedure is correct.");
- FixedPointToSpecs();
- ConjecturesToSpecs();
- return Outcome.Correct;
- case RPFP.LBool.Undef:
- Console.WriteLine("Inconclusive result.");
- ConjecturesToSpecs();
- return Outcome.ReachedBound;
- }
-
- }
-
- return Outcome.Inconclusive;
- }
- }
-
- public void FindLabelsRec(HashSet<Term> memo, Term t, Dictionary<string, Term> res)
- {
- if (memo.Contains(t))
- return;
- if (t.IsLabel())
- {
- string l = t.LabelName();
- if (!res.ContainsKey(l))
- res.Add(l, t.GetAppArgs()[0]);
- }
- if (t.GetKind() == TermKind.App)
- {
- var args = t.GetAppArgs();
- foreach (var a in args)
- FindLabelsRec(memo, a, res);
- } // TODO: handle quantifiers
-
- memo.Add(t);
- }
-
- public void FindLabels()
- {
- labels = new Dictionary<string, Term>();
- foreach(var e in rpfp.edges){
- int id = e.number;
- HashSet<Term> memo = new HashSet<Term>(ReferenceComparer<Term>.Instance);
- FindLabelsRec(memo, e.F.Formula, labels);
- }
- }
-
- public string CodeLabel(Absy code, StratifiedInliningInfo info, string prefix)
- {
- if (info.label2absyInv == null)
- {
- info.label2absyInv = new Dictionary<Absy, string>();
- foreach (int foo in info.label2absy.Keys)
- {
- Absy bar = info.label2absy[foo] as Absy;
- string lbl = foo.ToString();
- info.label2absyInv.Add(bar, lbl);
- }
- }
- if (info.label2absyInv.ContainsKey(code))
- {
- string label = info.label2absyInv[code];
- return prefix+label;
- }
- return null;
- }
-
- public Term CodeLabeledExpr(RPFP rpfp, RPFP.Node root, Absy code, StratifiedInliningInfo info, string prefix)
- {
- string label = CodeLabel(code, info, prefix);
-
- if (label != null)
- {
- var res = labels[label];
- return res;
- }
- else return null;
- }
-
- public class LabelNotFound : Exception { };
-
- public bool CodeLabelTrue(RPFP rpfp, RPFP.Node root, Absy code, StratifiedInliningInfo info, string prefix)
- {
- string label = CodeLabel(code, info, prefix);
-
- if (label == null)
- throw new LabelNotFound();
- return root.Outgoing.labels.Contains(label);
- }
-
- public bool CodeLabelFalse(RPFP rpfp, RPFP.Node root, Absy code, StratifiedInliningInfo info, string prefix)
- {
- return CodeLabelTrue(rpfp, root, code, info, prefix);
- }
-
-
- private class StateId
- {
- public RPFP.Edge edge;
- public int capturePoint;
- public StratifiedInliningInfo info;
- public StateId(RPFP.Edge e, int c, StratifiedInliningInfo i)
- {
- edge = e;
- capturePoint = c;
- info = i;
- }
- }
-
-
- public Counterexample CreateBoogieCounterExample(RPFP rpfp, RPFP.Node root, Implementation mainImpl)
- {
- FindLabels();
- var orderedStateIds = new List<StateId>();
- Counterexample newCounterexample =
- GenerateTrace(rpfp, root, orderedStateIds, mainImpl,true);
- if (CommandLineOptions.Clo.ModelViewFile != null)
- {
- Model m = root.owner.GetBackgroundModel();
- GetModelWithStates(m, root, implName2StratifiedInliningInfo[mainImpl.Name],
- orderedStateIds, varSubst);
- newCounterexample.Model = m;
- newCounterexample.ModelHasStatesAlready = true;
- }
- return newCounterexample;
- }
-
-
-
- private Counterexample GenerateTrace(RPFP rpfp, RPFP.Node root,
- List<StateId> orderedStateIds, Implementation procImpl, bool toplevel)
- {
- Contract.Requires(procImpl != null);
-
- Contract.Assert(!rpfp.Empty(root));
-
-
- var info = implName2StratifiedInliningInfo[procImpl.Name];
- Block entryBlock = cce.NonNull(procImpl.Blocks[0]);
- Contract.Assert(entryBlock != null);
-
- List<Block> trace = new List<Block>();
- trace.Add(entryBlock);
-
- var calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
-
- Counterexample newCounterexample =
- GenerateTraceRec(rpfp, root, orderedStateIds, entryBlock, trace, calleeCounterexamples, info, toplevel);
-
- return newCounterexample;
- }
-
- // TODO: this is a bit cheesy. Rather than finding the argument position
- // of a relational term in a transformer by linear search, better to index this
- // somewhere, but where?
- private int TransformerArgPosition(RPFP rpfp, RPFP.Node root, Term expr)
- {
- FuncDecl rel = expr.GetAppDecl();
- string relname = rel.GetDeclName();
- var rps = root.Outgoing.F.RelParams;
- for (int i = 0; i < rps.Length; i++)
- {
- string thisname = rps[i].GetDeclName();
- if (thisname == relname)
- return i;
- }
- return -1;
- }
-
- private bool EvalToFalse(RPFP rpfp, RPFP.Node root, Term expr,StratifiedInliningInfo info){
- Term res = rpfp.Eval(root.Outgoing,expr);
- return res.Equals(ctx.MkTrue());
- }
-
- private Counterexample GenerateTraceRec(
- RPFP rpfp, RPFP.Node root,
- List<StateId> orderedStateIds,
- Block/*!*/ b, List<Block>/*!*/ trace,
- Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples,
- StratifiedInliningInfo info,
- bool toplevel)
- {
- Contract.Requires(b != null);
- Contract.Requires(trace != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(calleeCounterexamples));
-
- Stack<RPFP.Node> continuation_stack = new Stack<RPFP.Node>();
-
- // If our block is not present, try diving into precondition
- // and push a continuation.
- // TODO: is the precondition always the first child?
- while (!CodeLabelFalse(rpfp, root, b, info, "+"))
- {
- if (root.Outgoing != null && root.Outgoing.Children.Length > 0)
- {
- continuation_stack.Push(root);
- root = root.Outgoing.Children[0];
- }
- else
- {
- // can't find our block
- Contract.Assert(false);
- return null;
- }
- }
-
- // After translation, all potential errors come from asserts.
- while (true)
- {
-
-
- List<Cmd> cmds = b.Cmds;
- TransferCmd transferCmd = cce.NonNull(b.TransferCmd);
- for (int i = 0; i < cmds.Count; i++)
- {
- Cmd cmd = cce.NonNull(cmds[i]);
-
- // Skip if 'cmd' not contained in the trace or not an assert
- if (cmd is AssertCmd)
- {
- bool is_failed_assertion = false;
- if (NoLabels)
- is_failed_assertion = true; // we assume only assertions on
- else
- is_failed_assertion = CodeLabelTrue(rpfp, root, cmd, info, "@");
-
- if (is_failed_assertion)
- {
- if (continuation_stack.Count == 0)
- {
- Counterexample newCounterexample =
- AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, new Microsoft.Boogie.Model(), info.mvInfo,
- boogieContext);
- newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
- return newCounterexample;
- }
- root = continuation_stack.Pop();
- }
- continue;
- }
-
- // Counterexample generation for inlined procedures
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- if (assumeCmd == null)
- continue;
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- if (naryExpr == null)
- continue;
- string calleeName = naryExpr.Fun.FunctionName;
- Contract.Assert(calleeName != null);
-
- // what is this crap???
- BinaryOperator binOp = naryExpr.Fun as BinaryOperator;
- if (binOp != null && binOp.Op == BinaryOperator.Opcode.And)
- {
- Expr expr = naryExpr.Args[0];
- NAryExpr mvStateExpr = expr as NAryExpr;
- if (mvStateExpr != null && mvStateExpr.Fun.FunctionName == VC.ModelViewInfo.MVState_FunctionDef.Name)
- {
- LiteralExpr x = mvStateExpr.Args[1] as LiteralExpr;
- // Debug.Assert(x != null);
- int foo = x.asBigNum.ToInt;
- orderedStateIds.Add(new StateId(root.Outgoing,foo,info));
- }
- }
-
- if (calleeName.EndsWith("_summary"))
- calleeName = calleeName.Substring(0, calleeName.Length - 8);
-
- if (!implName2StratifiedInliningInfo.ContainsKey(calleeName) && !calleeName.EndsWith("_summary"))
- continue;
-
- {
- Term code = CodeLabeledExpr(rpfp, root, cmd, info, "+si_fcall_");
- int pos = TransformerArgPosition(rpfp, root, code);
- if (pos >= 0)
- {
- RPFP.Node callee = root.Outgoing.Children[pos];
- orderedStateIds.Add(new StateId(callee.Outgoing, CALL,info));
- calleeCounterexamples[new TraceLocation(trace.Count - 1, i)] =
- new CalleeCounterexampleInfo(
- cce.NonNull(GenerateTrace(rpfp, callee, orderedStateIds,
- implName2StratifiedInliningInfo[calleeName].impl, false)),
- new List<object>());
- orderedStateIds.Add(new StateId(root.Outgoing, RETURN,info));
- }
- }
- }
-
- GotoCmd gotoCmd = transferCmd as GotoCmd;
- List<Block> cuts = null;
- if (edgesCut.ContainsKey(b))
- cuts = edgesCut[b];
- b = null;
-
- if (gotoCmd != null)
- {
-
- foreach (Block bb in cce.NonNull(gotoCmd.labelTargets))
- {
- Contract.Assert(bb != null);
- if (CodeLabelFalse(rpfp, root, bb, info, "+"))
- {
- trace.Add(bb);
- b = bb;
- break;
- }
- }
- if (b != null) continue;
- }
- // HACK: we have to try edges that were cut in generating the VC
-
- if (cuts != null)
- foreach (var bb in cuts)
- {
- if (CodeLabelFalse(rpfp, root, bb, info, "+"))
- {
- trace.Add(bb);
- b = bb;
- break;
- }
- }
- if (b != null) continue;
-
- return null;
- }
-
-
- }
-
- public override Counterexample extractLoopTrace(Counterexample cex, string mainProcName, Program program, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
- {
- // Construct the set of inlined procs in the original program
- var inlinedProcs = new HashSet<string>();
- foreach (var decl in program.TopLevelDeclarations)
- {
- // Implementations
- if (decl is Implementation)
- {
- var impl = decl as Implementation;
- if (!(impl.Proc is LoopProcedure))
- {
- inlinedProcs.Add(impl.Name);
- }
- }
-
- // And recording procedures
- if (decl is Procedure)
- {
- var proc = decl as Procedure;
- if (proc.Name.StartsWith(recordProcName))
- {
- // Debug.Assert(!(decl is LoopProcedure));
- inlinedProcs.Add(proc.Name);
- }
- }
- }
- return extractLoopTraceRec(
- new CalleeCounterexampleInfo(cex, new List<object>()),
- mainProcName, inlinedProcs, extractLoopMappingInfo).counterexample;
- }
-
- protected override bool elIsLoop(string procname)
- {
- StratifiedInliningInfo info = null;
- if (implName2StratifiedInliningInfo.ContainsKey(procname))
- {
- info = implName2StratifiedInliningInfo[procname];
- }
-
- if (info == null) return false;
-
- var lp = info.impl.Proc as LoopProcedure;
-
- if (lp == null) return false;
- return true;
- }
-
- private void NumberCexEdges(RPFP.Node node, Dictionary<int,RPFP.Edge> map)
- {
- if (node.Outgoing == null)
- return; // shouldn't happen
- RPFP.Edge edge = node.Outgoing;
- map[edge.number] = edge;
- foreach (var c in edge.Children)
- NumberCexEdges(c, map);
- }
-
- private void GetModelWithStates(Model m, RPFP.Node cex, StratifiedInliningInfo mainInfo,
- List<StateId> orderedStateIds,
- Dictionary<int,Dictionary<string,string>> varSubst)
- {
- if (m == null) return;
- var mvInfo = mainInfo.mvInfo;
-
-
- foreach (Variable v in mvInfo.AllVariables)
- {
- m.InitialState.AddBinding(v.Name, GetModelValue(m, v, varSubst[cex.Outgoing.number]));
- }
-
- Dictionary<int, RPFP.Edge> edgeNumbering = new Dictionary<int,RPFP.Edge>();
- NumberCexEdges(cex, edgeNumbering);
-
- int lastCandidate = 0;
- int lastCapturePoint = CALL;
- for (int i = 0; i < orderedStateIds.Count; ++i)
- {
- var s = orderedStateIds[i];
- RPFP.Edge edge = s.edge;
- int candidate = edge.number;
- int capturePoint = s.capturePoint;
- Dictionary<string, string> subst = varSubst[candidate];
-
- string implName = edge.Parent.Name.GetDeclName();
- var info = s.info.mvInfo;
-
- if (capturePoint == CALL || capturePoint == RETURN)
- {
- lastCandidate = candidate;
- lastCapturePoint = capturePoint;
- continue;
- }
-
- Contract.Assume(0 <= capturePoint && capturePoint < info.CapturePoints.Count);
- VC.ModelViewInfo.Mapping map = info.CapturePoints[capturePoint];
- var prevInc = (lastCapturePoint != CALL && lastCapturePoint != RETURN && candidate == lastCandidate)
- ? info.CapturePoints[lastCapturePoint].IncarnationMap : new Dictionary<Variable, Expr>();
- var cs = m.MkState(map.Description);
-
- foreach (Variable v in info.AllVariables)
- {
- var e = (Expr)map.IncarnationMap[v];
-
- if (e == null)
- {
- if (lastCapturePoint == CALL || lastCapturePoint == RETURN)
- {
- cs.AddBinding(v.Name, GetModelValue(m, v, subst));
- }
- continue;
- }
-
- if (lastCapturePoint != CALL && lastCapturePoint != RETURN && prevInc[v] == e) continue; // skip unchanged variables
-
- Model.Element elt;
- if (e is IdentifierExpr)
- {
- IdentifierExpr ide = (IdentifierExpr)e;
- elt = GetModelValue(m, ide.Decl, subst);
- }
- else if (e is LiteralExpr)
- {
- LiteralExpr lit = (LiteralExpr)e;
- elt = m.MkElement(lit.Val.ToString());
- }
- else
- {
- Contract.Assume(false);
- elt = m.MkFunc(e.ToString(), 0).GetConstant();
- }
- cs.AddBinding(v.Name, elt);
- }
-
- lastCandidate = candidate;
- lastCapturePoint = capturePoint;
- }
-
- return;
- }
-
-
- public readonly static int CALL = -1;
- public readonly static int RETURN = -2;
-
- private Model.Element GetModelValue(Model m, Variable v, Dictionary<string,string> subst)
- {
- // first, get the unique name
- string uniqueName;
-
- VCExprVar vvar = boogieContext.BoogieExprTranslator.TryLookupVariable(v);
-
- uniqueName = v.Name;
-
- if(subst.ContainsKey(uniqueName))
- return m.MkElement(subst[uniqueName]);
- return m.MkFunc("@undefined", 0).GetConstant();
- }
-
- class InternalError : Exception {
- }
-
-
- private BinaryOperator.Opcode VCOpToOp (VCExprOp op)
- {
- if (op == VCExpressionGenerator.AddIOp)
- return BinaryOperator.Opcode.Add;
- if (op == VCExpressionGenerator.SubIOp)
- return BinaryOperator.Opcode.Sub;
- if (op == VCExpressionGenerator.MulIOp)
- return BinaryOperator.Opcode.Mul;
- if (op == VCExpressionGenerator.DivIOp)
- return BinaryOperator.Opcode.Div;
- if (op == VCExpressionGenerator.EqOp)
- return BinaryOperator.Opcode.Eq;
- if (op == VCExpressionGenerator.LeOp)
- return BinaryOperator.Opcode.Le;
- if (op == VCExpressionGenerator.LtOp)
- return BinaryOperator.Opcode.Lt;
- if (op == VCExpressionGenerator.GeOp)
- return BinaryOperator.Opcode.Ge;
- if (op == VCExpressionGenerator.GtOp)
- return BinaryOperator.Opcode.Gt;
- if (op == VCExpressionGenerator.AndOp)
- return BinaryOperator.Opcode.And;
- if (op == VCExpressionGenerator.OrOp)
- return BinaryOperator.Opcode.Or;
- throw new InternalError();
- }
-
- private Expr MakeBinary (BinaryOperator.Opcode op, List<Expr> args)
- {
- if(args.Count == 0){
- // with zero args we need the identity of the op
- switch(op){
- case BinaryOperator.Opcode.And:
- return Expr.True;
- case BinaryOperator.Opcode.Or:
- return Expr.False;
- case BinaryOperator.Opcode.Add:
- return new LiteralExpr(Token.NoToken,Microsoft.Basetypes.BigNum.ZERO);
- default:
- throw new InternalError();
- }
- }
- var temp = args[0];
- for(int i = 1; i < args.Count; i++)
- temp = Expr.Binary(Token.NoToken,op,temp,args[i]);
- return temp;
- }
-
- private Variable MakeVar(VCExprVar v){
- var foo = new TypedIdent(Token.NoToken,v.Name.ToString(),v.Type);
- return new BoundVariable(Token.NoToken,foo);
- }
-
- private Expr VCExprToExpr (VCExpr e, Dictionary<VCExpr,Expr> bound)
- {
- if (e is VCExprVar) {
- if(bound.ContainsKey(e))
- return bound[e];
- return Expr.Ident(MakeVar(e as VCExprVar)); // TODO: this isn't right
- }
- if (e is VCExprIntLit) {
- var n = e as VCExprIntLit;
- return new LiteralExpr(Token.NoToken,n.Val);
- }
- if (e is VCExprNAry) {
- var f = e as VCExprNAry;
- var args = new List<Expr>();
- for(int i = 0; i < f.Arity; i++){
- args.Add (VCExprToExpr (f[i],bound));
- }
-
- if(f.Op == VCExpressionGenerator.NotOp)
- return Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, args[0]);
-
- if(f.Op == VCExpressionGenerator.IfThenElseOp)
- return new NAryExpr(Token.NoToken,new IfThenElse(Token.NoToken),args);
-
- if(f.Op is VCExprSelectOp){
- var idx = new List<Expr>();
- idx.Add(args[1]);
- return Expr.Select(args[0],idx);
- }
-
- if(f.Op is VCExprStoreOp){
- var idx = new List<Expr>();
- idx.Add(args[1]);
- return Expr.Store(args[0],idx,args[2]);
- }
-
- var op = VCOpToOp (f.Op);
- return MakeBinary(op,args);
- }
-
- if(e is VCExprQuantifier) {
- var f = e as VCExprQuantifier;
- var vs = new List<Variable>();
- var new_bound = new Dictionary<VCExpr,Expr>(bound);
- foreach(var v in f.BoundVars){
- var ve = MakeVar(v);
- vs.Add(ve);
- new_bound.Add (v,Expr.Ident (ve));
- }
- var bd = VCExprToExpr(f.Body,new_bound);
- if(f.Quan == Quantifier.EX)
- return new ExistsExpr(Token.NoToken,vs,bd);
- else
- return new ForallExpr(Token.NoToken,vs,bd);
- }
- if (e == VCExpressionGenerator.True) {
- return Expr.True;
- }
- if (e == VCExpressionGenerator.False) {
- return Expr.False;
- }
- if (e is VCExprLet) {
-
- }
-
- throw new InternalError();
- }
-
-
- }
-
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 2012 Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+
+
+using Term = Microsoft.Boogie.VCExprAST.VCExpr;
+using FuncDecl = Microsoft.Boogie.VCExprAST.VCExprOp;
+using Sort = Microsoft.Boogie.Type;
+using Microsoft.Boogie.ExprExtensions;
+
+
+namespace Microsoft.Boogie
+{
+ public class FixedpointVC : VC.VCGen
+ {
+
+ public class AnnotationInfo
+ {
+ public enum AnnotationType { LoopInvariant, ProcedureSummary };
+ public string filename;
+ public int lineno;
+ public string[] argnames;
+ public AnnotationType type;
+ };
+
+ static bool NoLabels = false;
+
+ // options
+ bool largeblock = false;
+
+ public bool SetOption(string option, string value)
+ {
+ if (option == "LargeBlock")
+ {
+ largeblock = true;
+ return true;
+ }
+ return false;
+ }
+
+ Context ctx;
+ RPFP rpfp;
+ // Program program;
+ Microsoft.Boogie.ProverContext boogieContext;
+ Microsoft.Boogie.VCExpressionGenerator gen;
+ public readonly static string recordProcName = "boogie_si_record"; // TODO: this really needed?
+ private Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo
+ = new Dictionary<string, StratifiedInliningInfo>();
+ Checker checker;
+ // Microsoft.Boogie.Z3.Z3InstanceOptions options = new Microsoft.Boogie.Z3.Z3InstanceOptions(); // TODO: what?
+ LineariserOptions linOptions;
+ Dictionary<FuncDecl, StratifiedInliningInfo> relationToProc = new Dictionary<FuncDecl, StratifiedInliningInfo>();
+ Dictionary<string, Term> labels = new Dictionary<string, Term> ();
+ List<Term> DualityVCs = new List<Term>();
+ Dictionary<string, bool> summaries = new Dictionary<string, bool>();
+ Dictionary<Block, List<Block>> edgesCut = new Dictionary<Block, List<Block>>();
+ string main_proc_name = "main";
+ Dictionary<string, int> extraRecBound = null;
+
+
+ public enum Mode { Corral, OldCorral, Boogie};
+ public enum AnnotationStyle { Flat, Procedure, Call };
+
+ Mode mode;
+ AnnotationStyle style;
+
+ private static Checker old_checker = null;
+
+ public static void CleanUp()
+ {
+ if (old_checker != null)
+ {
+ old_checker.Close();
+ old_checker = null;
+ }
+ }
+
+ public FixedpointVC( Program _program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers, Dictionary<string,int> _extraRecBound = null)
+ : base(_program, logFilePath, appendLogFile, checkers)
+ {
+ switch (CommandLineOptions.Clo.FixedPointMode)
+ {
+ case CommandLineOptions.FixedPointInferenceMode.Corral:
+ mode = Mode.Corral;
+ style = AnnotationStyle.Procedure;
+ break;
+ case CommandLineOptions.FixedPointInferenceMode.OldCorral:
+ mode = Mode.OldCorral;
+ style = AnnotationStyle.Procedure;
+ break;
+ case CommandLineOptions.FixedPointInferenceMode.Flat:
+ mode = Mode.Boogie;
+ style = AnnotationStyle.Flat;
+ break;
+ case CommandLineOptions.FixedPointInferenceMode.Procedure:
+ mode = Mode.Boogie;
+ style = AnnotationStyle.Procedure;
+ break;
+ case CommandLineOptions.FixedPointInferenceMode.Call:
+ mode = Mode.Boogie;
+ style = AnnotationStyle.Call;
+ break;
+ }
+ ctx = new Context(); // TODO is this right?
+ rpfp = new RPFP(RPFP.CreateLogicSolver(ctx));
+ program = _program;
+ gen = ctx;
+ if(old_checker == null)
+ checker = new Checker(this, program, logFilePath, appendLogFile, CommandLineOptions.Clo.ProverKillTime, null);
+ else {
+ checker = old_checker;
+ checker.RetargetWithoutReset(program,checker.TheoremProver.Context);
+ }
+ old_checker = checker;
+ boogieContext = checker.TheoremProver.Context;
+ linOptions = null; // new Microsoft.Boogie.Z3.Z3LineariserOptions(false, options, new List<VCExprVar>());
+ extraRecBound = _extraRecBound;
+ }
+
+ Dictionary<string, AnnotationInfo> annotationInfo = new Dictionary<string, AnnotationInfo>();
+
+ public void AnnotateLoops(Implementation impl, ProverContext ctxt)
+ {
+ Contract.Requires(impl != null);
+
+ CurrentLocalVariables = impl.LocVars;
+ variable2SequenceNumber = new Dictionary<Variable, int>();
+ incarnationOriginMap = new Dictionary<Incarnation, Absy>();
+
+ ResetPredecessors(impl.Blocks);
+
+ #region Create the graph by adding the source node and each edge
+ GraphUtil.Graph<Block> g = Program.GraphFromImpl(impl);
+ #endregion
+
+ //Graph<Block> g = program.ProcessLoops(impl);
+
+ g.ComputeLoops(); // this is the call that does all of the processing
+ if (!g.Reducible)
+ {
+ throw new System.Exception("Irreducible flow graphs are unsupported.");
+ }
+
+ #region add a symbolic annoation to every loop head
+ foreach (Block header in cce.NonNull(g.Headers))
+ AnnotateBlock(impl, ctxt, header);
+ #endregion
+ }
+
+ private void AnnotateCallSites(Implementation impl, ProverContext ctxt, Dictionary<string, bool> impls){
+ foreach (var b in impl.Blocks)
+ {
+ foreach (var cmd in b.Cmds)
+ {
+ if (cmd is CallCmd)
+ {
+ string name = (cmd as CallCmd).callee;
+ if(impls.ContainsKey(name))
+ goto annotate;
+ }
+ }
+ continue;
+ annotate:
+ AnnotateBlock(impl, ctxt, b);
+ }
+ }
+
+
+ private void AnnotateBlock(Implementation impl, ProverContext ctxt, Block header)
+ {
+ Contract.Assert(header != null);
+
+ string name = impl.Name + "_" + header.Label + "_invar";
+ if (annotationInfo.ContainsKey(name))
+ return;
+
+ // collect the variables needed in the invariant
+ List<Expr> exprs = new List<Expr>();
+ List<Variable> vars = new List<Variable>();
+ List<string> names = new List<string>();
+
+ if (style == AnnotationStyle.Flat)
+ {
+ // in flat mode, all live globals should be in live set
+#if false
+ foreach (Variable v in program.GlobalVariables)
+ {
+ vars.Add(v);
+ names.Add(v.ToString());
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+#endif
+ foreach (Variable v in /* impl.LocVars */ header.liveVarsBefore)
+ {
+ if (!(v is BoundVariable))
+ {
+ vars.Add(v);
+ names.Add(v.ToString());
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ }
+ }
+ else
+ {
+ foreach (Variable v in program.GlobalVariables)
+ {
+ vars.Add(v);
+ names.Add("@old_" + v.ToString());
+ exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
+ }
+ foreach (IdentifierExpr ie in impl.Proc.Modifies)
+ {
+ if (ie.Decl == null)
+ continue;
+ vars.Add(ie.Decl);
+ names.Add(ie.Decl.ToString());
+ exprs.Add(ie);
+ }
+ foreach (Variable v in impl.Proc.InParams)
+ {
+ Contract.Assert(v != null);
+ vars.Add(v);
+ names.Add("@old_" + v.ToString());
+ exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
+ }
+ foreach (Variable v in impl.LocVars)
+ {
+ vars.Add(v);
+ names.Add(v.ToString());
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ }
+
+ TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
+ Contract.Assert(ti != null);
+ Formal returnVar = new Formal(Token.NoToken, ti, false);
+ Contract.Assert(returnVar != null);
+ var function = new Function(Token.NoToken, name, vars, returnVar);
+ ctxt.DeclareFunction(function, "");
+
+ Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
+ var invarAssertion = new AssertCmd(Token.NoToken, invarExpr);
+ List<Cmd> newCmds = new List<Cmd>();
+ newCmds.Add(invarAssertion);
+
+ // make a record in annotationInfo;
+ var info = new AnnotationInfo();
+ info.filename = header.tok.filename;
+ info.lineno = header.Line;
+ info.argnames = names.ToArray();
+ info.type = AnnotationInfo.AnnotationType.LoopInvariant;
+ annotationInfo.Add(name, info);
+ // get file and line info from havoc, if there is...
+ if (header.Cmds.Count > 0)
+ {
+ PredicateCmd bif = header.Cmds[0] as PredicateCmd;
+ if (bif != null)
+ {
+ string foo = QKeyValue.FindStringAttribute(bif.Attributes, "sourcefile");
+ if (foo != null)
+ info.filename = foo;
+ int bar = QKeyValue.FindIntAttribute(bif.Attributes, "sourceline", -1);
+ if (bar != -1)
+ info.lineno = bar;
+ }
+ }
+ var thing = header;
+ foreach (Cmd c in header.Cmds)
+ {
+ newCmds.Add(c);
+ }
+ header.Cmds = newCmds;
+ }
+
+#if true
+ public void AnnotateProcRequires(Procedure proc, Implementation impl, ProverContext ctxt)
+ {
+ Contract.Requires(impl != null);
+
+ CurrentLocalVariables = impl.LocVars;
+
+ // collect the variables needed in the invariant
+ List<Expr> exprs = new List<Expr>();
+ List<Variable> vars = new List<Variable>();
+ List<string> names = new List<string>();
+
+ foreach (Variable v in program.GlobalVariables)
+ {
+ vars.Add(v);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ names.Add(v.Name);
+ }
+ foreach (Variable v in proc.InParams)
+ {
+ Contract.Assert(v != null);
+ vars.Add(v);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ names.Add(v.Name);
+ }
+ string name = impl.Name + "_precond";
+ TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
+ Contract.Assert(ti != null);
+ Formal returnVar = new Formal(Token.NoToken, ti, false);
+ Contract.Assert(returnVar != null);
+ var function = new Function(Token.NoToken, name, vars, returnVar);
+ ctxt.DeclareFunction(function, "");
+
+ Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
+
+ proc.Requires.Add(new Requires(Token.NoToken, false, invarExpr, "", null));
+
+ var info = new AnnotationInfo();
+ info.filename = proc.tok.filename;
+ info.lineno = proc.Line;
+ info.argnames = names.ToArray();
+ info.type = AnnotationInfo.AnnotationType.LoopInvariant;
+ annotationInfo.Add(name, info);
+ }
+
+ public void AnnotateProcEnsures(Procedure proc, Implementation impl, ProverContext ctxt)
+ {
+ Contract.Requires(impl != null);
+
+ CurrentLocalVariables = impl.LocVars;
+
+ // collect the variables needed in the invariant
+ List<Expr> exprs = new List<Expr>();
+ List<Variable> vars = new List<Variable>();
+ List<string> names = new List<string>();
+
+ foreach (Variable v in program.GlobalVariables)
+ {
+ vars.Add(v);
+ exprs.Add(new OldExpr(Token.NoToken,new IdentifierExpr(Token.NoToken, v)));
+ names.Add(v.Name);
+ }
+ foreach (Variable v in proc.InParams)
+ {
+ Contract.Assert(v != null);
+ vars.Add(v);
+ exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
+ names.Add(v.Name);
+ }
+ foreach (IdentifierExpr ie in proc.Modifies)
+ {
+ if (ie.Decl == null)
+ continue;
+ vars.Add(ie.Decl);
+ exprs.Add(ie);
+ names.Add(ie.Decl.Name + "_out");
+ }
+ foreach (Variable v in proc.OutParams)
+ {
+ Contract.Assert(v != null);
+ vars.Add(v);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ names.Add(v.Name);
+ }
+ string name = impl.Name + "_summary";
+ summaries.Add(name, true);
+ TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
+ Contract.Assert(ti != null);
+ Formal returnVar = new Formal(Token.NoToken, ti, false);
+ Contract.Assert(returnVar != null);
+ var function = new Function(Token.NoToken, name, vars, returnVar);
+ ctxt.DeclareFunction(function, "");
+
+ Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
+
+ proc.Ensures.Add(new Ensures(Token.NoToken, false, invarExpr, "", null));
+
+ var info = new AnnotationInfo();
+ info.filename = proc.tok.filename;
+ info.lineno = proc.Line;
+ info.argnames = names.ToArray();
+ info.type = AnnotationInfo.AnnotationType.ProcedureSummary;
+ annotationInfo.Add(name, info);
+ }
+#endif
+
+ void MarkAllFunctionImplementationsInline()
+ {
+ foreach (var func in program.Functions)
+ {
+ if (func.Body == null && func.DefinitionAxiom != null)
+ {
+ var def = func.DefinitionAxiom.Expr as QuantifierExpr;
+ var bod = def.Body as NAryExpr;
+ func.Body = bod.Args[1];
+ func.DefinitionAxiom = null;
+ }
+ if (func.Body != null)
+ if (func.FindExprAttribute("inline") == null)
+ func.AddAttribute("inline", Expr.Literal(100));
+ }
+ }
+
+ void InlineAll()
+ {
+ foreach (var impl in program.Implementations)
+ {
+ impl.OriginalBlocks = impl.Blocks;
+ impl.OriginalLocVars = impl.LocVars;
+ if(impl.Name != main_proc_name)
+ if(impl.FindExprAttribute("inline") == null)
+ impl.AddAttribute("inline", Expr.Literal(100));
+ }
+ foreach (var impl in program.Implementations)
+ {
+ if (!impl.SkipVerification)
+ {
+ Inliner.ProcessImplementation(program, impl);
+ }
+ }
+ foreach (var impl in program.Implementations)
+ {
+ impl.OriginalBlocks = null;
+ impl.OriginalLocVars = null;
+ }
+ }
+
+ public class LazyInliningInfo
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(impl != null);
+ Contract.Invariant(function != null);
+ Contract.Invariant(controlFlowVariable != null);
+ Contract.Invariant(assertExpr != null);
+ Contract.Invariant(cce.NonNullElements(interfaceVars));
+ Contract.Invariant(incarnationOriginMap == null || cce.NonNullDictionaryAndValues(incarnationOriginMap));
+ }
+
+ public Implementation impl;
+ public int uniqueId;
+ public Function function;
+ public Variable controlFlowVariable;
+ public List<Variable> interfaceVars;
+ public List<List<Variable>> interfaceVarCopies;
+ public Expr assertExpr;
+ public VCExpr vcexpr;
+ public List<VCExprVar> privateVars;
+ public Dictionary<Incarnation, Absy> incarnationOriginMap;
+ public Hashtable /*Variable->Expr*/ exitIncarnationMap;
+ public Hashtable /*GotoCmd->returnCmd*/ gotoCmdOrigins;
+ public Dictionary<int, Absy> label2absy;
+ public VC.ModelViewInfo mvInfo;
+
+ public Dictionary<Block, VCExprVar> reachVars;
+ public List<VCExprLetBinding> reachVarBindings;
+ public Variable inputErrorVariable;
+ public Variable outputErrorVariable;
+
+
+
+ public LazyInliningInfo(Implementation impl, Program program, ProverContext ctxt, int uniqueId, GlobalVariable errorVariable)
+ {
+ Contract.Requires(impl != null);
+ Contract.Requires(program != null);
+ Procedure proc = cce.NonNull(impl.Proc);
+
+ this.impl = impl;
+ this.uniqueId = uniqueId;
+ this.controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "cfc", Microsoft.Boogie.Type.Int));
+ impl.LocVars.Add(controlFlowVariable);
+
+ List<Variable> interfaceVars = new List<Variable>();
+ Expr assertExpr = new LiteralExpr(Token.NoToken, true);
+ Contract.Assert(assertExpr != null);
+ // InParams must be obtained from impl and not proc
+ foreach (Variable v in impl.InParams)
+ {
+ Contract.Assert(v != null);
+ interfaceVars.Add(v);
+ }
+ // OutParams must be obtained from impl and not proc
+ foreach (Variable v in impl.OutParams)
+ {
+ Contract.Assert(v != null);
+ Constant c = new Constant(Token.NoToken,
+ new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
+ interfaceVars.Add(c);
+ Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
+ assertExpr = Expr.And(assertExpr, eqExpr);
+ }
+ foreach (Variable v in program.GlobalVariables)
+ {
+ Contract.Assert(v != null);
+ interfaceVars.Add(v);
+ if (v.Name == "error")
+ inputErrorVariable = v;
+ }
+ if (errorVariable != null)
+ {
+ proc.Modifies.Add(new IdentifierExpr(Token.NoToken, errorVariable));
+ }
+ foreach (IdentifierExpr e in proc.Modifies)
+ {
+ Contract.Assert(e != null);
+ if (e.Decl == null)
+ continue;
+ Variable v = e.Decl;
+ Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
+ interfaceVars.Add(c);
+ if (v.Name == "error")
+ {
+ outputErrorVariable = c;
+ continue;
+ }
+ Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
+ assertExpr = Expr.And(assertExpr, eqExpr);
+ }
+
+ this.interfaceVars = interfaceVars;
+ this.assertExpr = Expr.Not(assertExpr);
+ List<Variable> functionInterfaceVars = new List<Variable>();
+ foreach (Variable v in interfaceVars)
+ {
+ Contract.Assert(v != null);
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, v.Name, v.TypedIdent.Type), true));
+ }
+ TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
+ Contract.Assert(ti != null);
+ Formal returnVar = new Formal(Token.NoToken, ti, false);
+ Contract.Assert(returnVar != null);
+ this.function = new Function(Token.NoToken, proc.Name, functionInterfaceVars, returnVar);
+ ctxt.DeclareFunction(this.function, "");
+
+ interfaceVarCopies = new List<List<Variable>>();
+ int temp = 0;
+ for (int i = 0; i < /* CommandLineOptions.Clo.ProcedureCopyBound */ 0; i++)
+ {
+ interfaceVarCopies.Add(new List<Variable>());
+ foreach (Variable v in interfaceVars)
+ {
+ Constant constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, v.Name + temp++, v.TypedIdent.Type));
+ interfaceVarCopies[i].Add(constant);
+ //program.AddTopLevelDeclaration(constant);
+ }
+ }
+ }
+ }
+
+ public class StratifiedInliningInfo : LazyInliningInfo
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(cce.NonNullElements(privateVars));
+ Contract.Invariant(cce.NonNullElements(interfaceExprVars));
+ Contract.Invariant(cce.NonNullElements(interfaceExprVars));
+ }
+
+ // public StratifiedVCGenBase vcgen;
+ //public Implementation impl;
+ //public Program program;
+ //public ProverContext ctxt;
+ //public int uniqueid;
+ //public Function function;
+ //public Variable controlFlowVariable;
+ //public Expr assertExpr;
+ //public VCExpr vcexpr;
+ //public List<VCExprVar> interfaceExprVars;
+ //public List<VCExprVar> privateExprVars;
+ //public Dictionary<int, Absy> label2absy;
+ //public VC.ModelViewInfo mvInfo;
+ //public Dictionary<Block, List<CallSite>> callSites;
+ //public Dictionary<Block, List<CallSite>> recordProcCallSites;
+ //public IEnumerable<Block> sortedBlocks;
+ //public bool initialized { get; private set; }
+
+
+ public List<VCExprVar> interfaceExprVars;
+ // public List<VCExprVar> privateVars;
+ public VCExpr funcExpr;
+ public VCExpr falseExpr;
+ public RPFP.Transformer F;
+ public RPFP.Node node;
+ public RPFP.Edge edge;
+ public bool isMain = false;
+ public Dictionary<Absy, string> label2absyInv;
+ public ProverContext ctxt;
+ public Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
+ public List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
+
+ public StratifiedInliningInfo(Implementation _impl, Program _program, ProverContext _ctxt, int _uniqueid)
+ : base(_impl,_program,_ctxt,_uniqueid,null){
+ Contract.Requires(_impl != null);
+ Contract.Requires(_program != null);
+ privateVars = new List<VCExprVar>();
+ interfaceExprVars = new List<VCExprVar>();
+ ctxt = _ctxt;
+ }
+
+ }
+
+ protected override void addExitAssert(string implName, Block exitBlock)
+ {
+ if (implName2StratifiedInliningInfo != null
+ && implName2StratifiedInliningInfo.ContainsKey(implName)
+ && !implName2StratifiedInliningInfo[implName].isMain)
+ {
+ if (mode == Mode.Boogie) return;
+ Expr assertExpr = implName2StratifiedInliningInfo[implName].assertExpr;
+ Contract.Assert(assertExpr != null);
+ exitBlock.Cmds.Add(new AssertCmd(Token.NoToken, assertExpr));
+ }
+ }
+
+#if false
+ protected override void storeIncarnationMaps(string implName, Hashtable exitIncarnationMap)
+ {
+ if (implName2StratifiedInliningInfo != null && implName2StratifiedInliningInfo.ContainsKey(implName))
+ {
+ StratifiedInliningInfo info = implName2StratifiedInliningInfo[implName];
+ Contract.Assert(info != null);
+ info.exitIncarnationMap = exitIncarnationMap;
+ info.incarnationOriginMap = this.incarnationOriginMap;
+ }
+ }
+#endif
+
+ public void GenerateVCsForStratifiedInlining()
+ {
+ Contract.Requires(program != null);
+ foreach (var impl in program.Implementations)
+ {
+ Contract.Assert(!impl.Name.StartsWith(recordProcName), "Not allowed to have an implementation for this guy");
+
+ Procedure proc = cce.NonNull(impl.Proc);
+
+ {
+ StratifiedInliningInfo info = new StratifiedInliningInfo(impl, program, boogieContext, QuantifierExpr.GetNextSkolemId());
+ implName2StratifiedInliningInfo[impl.Name] = info;
+ // We don't need controlFlowVariable for stratified Inlining
+ //impl.LocVars.Add(info.controlFlowVariable);
+ List<Expr> exprs = new List<Expr>();
+
+ if (mode != Mode.Boogie && QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
+ {
+ proc.Ensures.Add(new Ensures(Token.NoToken, true, Microsoft.Boogie.Expr.False, "", null));
+ info.assertExpr = Microsoft.Boogie.Expr.False;
+ // info.isMain = true;
+ }
+ else if (mode == Mode.Corral || proc.FindExprAttribute("inline") != null || proc is LoopProcedure)
+ {
+ foreach (Variable v in proc.InParams)
+ {
+ Contract.Assert(v != null);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ foreach (Variable v in proc.OutParams)
+ {
+ Contract.Assert(v != null);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ foreach (Variable v in program.GlobalVariables)
+ {
+ Contract.Assert(v != null);
+ exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
+ }
+ foreach (IdentifierExpr ie in proc.Modifies)
+ {
+ Contract.Assert(ie != null);
+ if (ie.Decl == null)
+ continue;
+ exprs.Add(ie);
+ }
+ Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(info.function), exprs);
+#if true
+ if(mode == Mode.Corral || mode == Mode.OldCorral)
+ proc.Ensures.Add(new Ensures(Token.NoToken, true, freePostExpr, "", new QKeyValue(Token.NoToken, "si_fcall", new List<object>(), null)));
+#endif
+ }
+ else // not marked "inline" must be main
+ {
+ Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(info.function), exprs);
+ info.isMain = true;
+ }
+ }
+ }
+
+ if (mode == Mode.Boogie) return;
+
+ foreach (var proc in program.Procedures)
+ {
+ if (!proc.Name.StartsWith(recordProcName)) continue;
+ Contract.Assert(proc.InParams.Count == 1);
+
+ // Make a new function
+ TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool);
+ Contract.Assert(ti != null);
+ Formal returnVar = new Formal(Token.NoToken, ti, false);
+ Contract.Assert(returnVar != null);
+
+ // Get record type
+ var argtype = proc.InParams[0].TypedIdent.Type;
+
+ var ins = new List<Variable>();
+ ins.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", argtype), true));
+
+ var recordFunc = new Function(Token.NoToken, proc.Name, ins, returnVar);
+ boogieContext.DeclareFunction(recordFunc, "");
+
+ var exprs = new List<Expr>();
+ exprs.Add(new IdentifierExpr(Token.NoToken, proc.InParams[0]));
+
+ Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(recordFunc), exprs);
+ proc.Ensures.Add(new Ensures(true, freePostExpr));
+ }
+ }
+
+ private void FixedPointToSpecs(){
+
+ if(mode != Mode.Corral || CommandLineOptions.Clo.PrintFixedPoint == null)
+ return; // not implemented for other annotation modes yet
+
+ var twr = new TokenTextWriter(CommandLineOptions.Clo.PrintFixedPoint, /*pretty=*/ false);
+ Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node> ();
+
+ foreach (var node in rpfp.nodes)
+ pmap.Add ((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
+
+ foreach (var impl in program.Implementations)
+ {
+ Contract.Assert(!impl.Name.StartsWith(recordProcName), "Not allowed to have an implementation for this guy");
+
+ Procedure proc = cce.NonNull(impl.Proc);
+
+ {
+ StratifiedInliningInfo info = new StratifiedInliningInfo(impl, program, boogieContext, QuantifierExpr.GetNextSkolemId());
+ implName2StratifiedInliningInfo[impl.Name] = info;
+ // We don't need controlFlowVariable for stratified Inlining
+ //impl.LocVars.Add(info.controlFlowVariable);
+ List<Expr> exprs = new List<Expr>();
+
+ {
+ if (pmap.ContainsKey(impl.Name))
+ {
+ RPFP.Node node = pmap[impl.Name];
+ var annot = node.Annotation;
+ EmitProcSpec(twr, proc, info, annot);
+ }
+ }
+ }
+ }
+ twr.Close ();
+ }
+
+ private void EmitProcSpec(TokenTextWriter twr, Procedure proc, StratifiedInliningInfo info, RPFP.Transformer annot)
+ {
+ // last ensures clause will be the symbolic one
+ if (!info.isMain)
+ {
+ var ens = proc.Ensures[proc.Ensures.Count - 1];
+ if (ens.Condition != Expr.False) // this is main
+ {
+ var postExpr = ens.Condition as NAryExpr;
+ var args = postExpr.Args;
+
+ var ind = annot.IndParams;
+ var bound = new Dictionary<VCExpr, Expr>();
+ for (int i = 0; i < args.Count; i++)
+ {
+ bound[ind[i]] = args[i];
+ }
+ var new_ens_cond = VCExprToExpr(annot.Formula, bound);
+ if (new_ens_cond != Expr.True)
+ {
+ var new_ens = new Ensures(false, new_ens_cond);
+ var enslist = new List<Ensures>();
+ enslist.Add(new_ens);
+ var new_proc = new Procedure(proc.tok, proc.Name, proc.TypeParameters, proc.InParams,
+ proc.OutParams, new List<Requires>(), new List<IdentifierExpr>(), enslist);
+ new_proc.Emit(twr, 0);
+ }
+ }
+ }
+ }
+
+ static int ConjectureFileCounter = 0;
+
+ private void ConjecturesToSpecs()
+ {
+
+ if (mode != Mode.Corral || CommandLineOptions.Clo.PrintConjectures == null)
+ return; // not implemented for other annotation modes yet
+
+ var twr = new TokenTextWriter(CommandLineOptions.Clo.PrintConjectures + "." + ConjectureFileCounter.ToString(), /*pretty=*/ false);
+ ConjectureFileCounter++;
+
+ foreach (var c in rpfp.conjectures)
+ {
+ var name = c.node.Name.GetDeclName();
+ if (implName2StratifiedInliningInfo.ContainsKey(name))
+ {
+ StratifiedInliningInfo info = implName2StratifiedInliningInfo[c.node.Name.GetDeclName()];
+ Implementation impl = info.impl;
+ Procedure proc = impl.Proc;
+ EmitProcSpec(twr, proc, info, c.bound);
+ }
+ }
+
+ twr.Close ();
+ }
+
+ private Term ExtractSmallerVCsRec(TermDict< Term> memo, Term t, List<Term> small, Term lbl = null)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ if (f.GetKind() == DeclKind.Implies){
+ var lhs = t.GetAppArgs()[0];
+ if(lhs.GetKind() == TermKind.App){
+ var r = lhs.GetAppDecl();
+ if (r.GetKind() == DeclKind.And)
+ {
+ Term q = t.GetAppArgs()[1];
+ var lhsargs = lhs.GetAppArgs();
+ for (int i = lhsargs.Length-1; i >= 0; --i)
+ {
+ q = ctx.MkImplies(lhsargs[i], q);
+ }
+ res = ExtractSmallerVCsRec(memo, q, small,lbl);
+ goto done;
+ }
+ if (r.GetKind() == DeclKind.Label)
+ {
+ var arg = lhs;
+ arg = lhs.GetAppArgs()[0];
+ if (!(arg.GetKind() == TermKind.App && arg.GetAppDecl().GetKind() == DeclKind.Uninterpreted))
+ goto normal;
+ if (!(annotationInfo.ContainsKey(arg.GetAppDecl().GetDeclName()) && annotationInfo[arg.GetAppDecl().GetDeclName()].type == AnnotationInfo.AnnotationType.LoopInvariant))
+ goto normal;
+ var sm = ctx.MkImplies(lhs, ExtractSmallerVCsRec(memo, t.GetAppArgs()[1], small));
+ if (lbl != null)
+ sm = ctx.MkImplies(lbl, sm);
+ small.Add(sm);
+ res = ctx.MkTrue();
+ goto done;
+ }
+ if (r.GetKind() == DeclKind.Uninterpreted)
+ {
+ var arg = lhs;
+ if (!(annotationInfo.ContainsKey(arg.GetAppDecl().GetDeclName()) && annotationInfo[arg.GetAppDecl().GetDeclName()].type == AnnotationInfo.AnnotationType.LoopInvariant))
+ goto normal;
+ var sm = ctx.MkImplies(lhs,ExtractSmallerVCsRec(memo,t.GetAppArgs()[1],small));
+ if (lbl != null)
+ sm = ctx.MkImplies(lbl, sm);
+ small.Add(sm);
+ res = ctx.MkTrue();
+ goto done;
+ }
+ }
+ normal:
+ Term newlbl = null;
+ if (lhs.IsLabel() && lhs.GetAppArgs()[0] == ctx.MkTrue())
+ newlbl = lhs;
+ res = ctx.MkImplies(lhs,ExtractSmallerVCsRec(memo,t.GetAppArgs()[1],small,newlbl));
+ }
+ else if (f.GetKind() == DeclKind.And)
+ {
+ res = ctx.MkApp(f,t.GetAppArgs().Select(x => ExtractSmallerVCsRec(memo, x, small)).ToArray());
+ }
+ else
+ res = t;
+ }
+ else
+ res = t;
+ done:
+ memo.Add(t, res);
+ return res;
+ }
+
+ private void ExtractSmallerVCs(Term t, List<Term> small){
+ TermDict< Term> memo = new TermDict< Term>();
+ Term top = ExtractSmallerVCsRec(memo, t, small);
+ small.Add(top);
+ }
+
+ private Dictionary<FuncDecl, int> goalNumbering = new Dictionary<FuncDecl, int>();
+
+ private Term NormalizeGoal(Term goal, FuncDecl label)
+ {
+ var f = goal.GetAppDecl();
+ var args = goal.GetAppArgs();
+ int number;
+ if (!goalNumbering.TryGetValue(f, out number))
+ {
+ number = goalNumbering.Count;
+ goalNumbering.Add(f, number);
+ }
+ Term[] tvars = new Term[args.Length];
+ Term[] eqns = new Term[args.Length];
+ AnnotationInfo info = null;
+ annotationInfo.TryGetValue(f.GetDeclName(), out info);
+ for (int i = 0; i < args.Length; i++)
+ {
+ string pname = (info == null) ? i.ToString() : info.argnames[i];
+ tvars[i] = ctx.MkConst("@a" + number.ToString() + "_" + pname, args[i].GetSort());
+ eqns[i] = ctx.MkEq(tvars[i], args[i]);
+ }
+ return ctx.MkImplies(ctx.MkAnd(eqns), ctx.MkApp(label, ctx.MkApp(f, tvars)));
+ }
+
+ private Term MergeGoalsRec(TermDict< Term> memo, Term t)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ var args = t.GetAppArgs();
+ if (f.GetKind() == DeclKind.Implies)
+ {
+ res = ctx.MkImplies(args[0], MergeGoalsRec(memo, args[1]));
+ goto done;
+ }
+ else if (f.GetKind() == DeclKind.And)
+ {
+ args = args.Select(x => MergeGoalsRec(memo, x)).ToArray();
+ res = ctx.MkApp(f, args);
+ goto done;
+ }
+ else if (f.GetKind() == DeclKind.Label)
+ {
+ var arg = t.GetAppArgs()[0];
+ var r = arg.GetAppDecl();
+ if (r.GetKind() == DeclKind.Uninterpreted)
+ {
+ res = NormalizeGoal(arg, f);
+ goto done;
+ }
+ }
+ }
+ res = t;
+ done:
+ memo.Add(t, res);
+ return res;
+ }
+
+ private Term MergeGoals(Term t)
+ {
+ TermDict< Term> memo = new TermDict< Term>();
+ return MergeGoalsRec(memo, t);
+ }
+
+ private Term CollectGoalsRec(TermDict< Term> memo, Term t, List<Term> goals, List<Term> cruft)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ if (f.GetKind() == DeclKind.Implies)
+ {
+ CollectGoalsRec(memo, t.GetAppArgs()[1], goals, cruft);
+ goto done;
+ }
+ else if (f.GetKind() == DeclKind.And)
+ {
+ foreach (var arg in t.GetAppArgs())
+ {
+ CollectGoalsRec(memo, arg, goals, cruft);
+ }
+ goto done;
+ }
+ else if (f.GetKind() == DeclKind.Label)
+ {
+ var arg = t.GetAppArgs()[0];
+ if (arg.GetKind() == TermKind.App && arg.GetAppDecl().GetKind() == DeclKind.Uninterpreted)
+ {
+ var r = arg.GetAppDecl();
+ if (memo.TryGetValue(arg, out res))
+ goto done;
+ if (!annotationInfo.ContainsKey(r.GetDeclName()) && !arg.GetAppDecl().GetDeclName().StartsWith("_solve_"))
+ goto done;
+ goals.Add(arg);
+ memo.Add(arg, arg);
+ goto done;
+ }
+ else
+ return CollectGoalsRec(memo, arg, goals, cruft);
+ }
+ else if (f.GetKind() == DeclKind.Uninterpreted)
+ {
+ string name = f.GetDeclName();
+ if (name.StartsWith("_solve_"))
+ {
+ if (memo.TryGetValue(t, out res))
+ goto done;
+ goals.Add(t);
+ memo.Add(t, t);
+ return t;
+ }
+ }
+ }
+ // else the goal must be cruft
+ cruft.Add(t);
+ done:
+ res = t; // just to return something
+ memo.Add(t, res);
+ return res;
+ }
+
+ private void CollectGoals(Term t, List<Term> goals, List<Term> cruft)
+ {
+ TermDict< Term> memo = new TermDict< Term>();
+ CollectGoalsRec(memo, t.GetAppArgs()[1], goals, cruft);
+ }
+
+ private Term SubstRec(TermDict< Term> memo, Term t)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ // var f = t.GetAppDecl();
+ var args = t.GetAppArgs().Select(x => SubstRec(memo, x)).ToArray();
+ res = ctx.CloneApp(t, args);
+ }
+ else res = t;
+ memo.Add(t, res);
+ return res;
+ }
+
+ private Term SubstRecGoals(TermDict< Term> memo, Term t)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ var args = t.GetAppArgs();
+ if (f.GetKind() == DeclKind.Implies){
+ res = SubstRecGoals(memo, args[1]);
+ if (res != ctx.MkTrue())
+ res = ctx.MkImplies(args[0],res);
+ goto done;
+ }
+ else if (f.GetKind() == DeclKind.And)
+ {
+ args = args.Select(x => SubstRecGoals(memo, x)).ToArray();
+ args = args.Where(x => x != ctx.MkTrue()).ToArray();
+ res = ctx.MkAnd(args);
+ goto done;
+ }
+ else if (f.GetKind() == DeclKind.Label)
+ {
+ var arg = t.GetAppArgs()[0];
+ if (arg.GetKind() == TermKind.App && arg.GetAppDecl().GetKind() == DeclKind.Uninterpreted)
+ {
+ var r = arg.GetAppDecl();
+ if (memo.TryGetValue(arg, out res))
+ {
+ if(res != ctx.MkTrue())
+ res = ctx.MkApp(f, res);
+ goto done;
+ }
+ }
+ else
+ {
+ res = ctx.MkApp(f, SubstRecGoals(memo, arg));
+ goto done;
+ }
+
+ }
+ // what's left could be cruft!
+ if (memo.TryGetValue(t, out res))
+ {
+ goto done;
+ }
+ }
+ res = t;
+ done:
+ memo.Add(t, res);
+ return res;
+ }
+
+ private void FactorVCs(Term t, List<Term> vcs)
+ {
+ List<Term> small = new List<Term>();
+ ExtractSmallerVCs(t, small);
+ foreach (var smm in small)
+ {
+ List<Term> goals = new List<Term>();
+ List<Term> cruft = new List<Term>();
+ var sm = largeblock ? MergeGoals(smm) : smm;
+ CollectGoals(sm, goals,cruft);
+ foreach (var goal in goals)
+ {
+ TermDict< Term> memo = new TermDict< Term>();
+ foreach (var othergoal in goals)
+ memo.Add(othergoal, othergoal.Equals(goal) ? ctx.MkFalse() : ctx.MkTrue());
+ foreach (var thing in cruft)
+ memo.Add(thing, ctx.MkTrue());
+ var vc = SubstRecGoals(memo, sm);
+ vc = ctx.MkImplies(ctx.MkNot(vc), goal);
+ vcs.Add(vc);
+ }
+ {
+ TermDict< Term> memo = new TermDict< Term>();
+ foreach (var othergoal in goals)
+ memo.Add(othergoal, ctx.MkTrue());
+ var vc = SubstRecGoals(memo, sm);
+ if (vc != ctx.MkTrue())
+ {
+ vc = ctx.MkImplies(ctx.MkNot(vc), ctx.MkFalse());
+ vcs.Add(vc);
+ }
+ }
+ }
+ }
+
+
+
+ private void GenerateVCForStratifiedInlining(Program program, StratifiedInliningInfo info, Checker checker)
+ {
+ Contract.Requires(program != null);
+ Contract.Requires(info != null);
+ Contract.Requires(checker != null);
+ Contract.Requires(info.impl != null);
+ Contract.Requires(info.impl.Proc != null);
+
+
+
+ Implementation impl = info.impl;
+ if (mode == Mode.Boogie && style == AnnotationStyle.Flat && impl.Name != main_proc_name)
+ return;
+ Contract.Assert(impl != null);
+ ConvertCFG2DAG(impl,edgesCut);
+ VC.ModelViewInfo mvInfo;
+ PassifyImpl(impl, out mvInfo);
+ Dictionary<int, Absy> label2absy = null;
+ VCExpressionGenerator gen = checker.VCExprGen;
+ Contract.Assert(gen != null);
+ VCExpr vcexpr;
+ if(NoLabels){
+ // int assertionCount = 0;
+ VCExpr startCorrect = null; /* VC.VCGen.LetVC(cce.NonNull(impl.Blocks[0]), null, null, info.blockVariables, info.bindings,
+ info.ctxt, out assertionCount); */
+ vcexpr = gen.Let(info.bindings, startCorrect);
+ }
+ else vcexpr = GenerateVC(impl, null /* info.controlFlowVariable */, out label2absy, info.ctxt);
+ if(mode != Mode.Boogie)
+ vcexpr = gen.Not(vcexpr);
+ Contract.Assert(vcexpr != null);
+ info.label2absy = label2absy;
+ info.mvInfo = mvInfo;
+ List<VCExpr> interfaceExprs = new List<VCExpr>();
+
+ if (true /* was: !info.isMain */)
+ {
+ Boogie2VCExprTranslator translator = checker.TheoremProver.Context.BoogieExprTranslator;
+ Contract.Assert(translator != null);
+ info.privateVars = new List<VCExprVar>();
+ foreach (Variable v in impl.LocVars)
+ {
+ Contract.Assert(v != null);
+ info.privateVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in impl.OutParams)
+ {
+ Contract.Assert(v != null);
+ info.privateVars.Add(translator.LookupVariable(v));
+ }
+
+ info.interfaceExprVars = new List<VCExprVar>();
+
+ foreach (Variable v in info.interfaceVars)
+ {
+ Contract.Assert(v != null);
+ VCExprVar ev = translator.LookupVariable(v);
+ Contract.Assert(ev != null);
+ info.interfaceExprVars.Add(ev);
+ interfaceExprs.Add(ev);
+ }
+ }
+
+ Function function = cce.NonNull(info.function);
+ Contract.Assert(function != null);
+ info.funcExpr = gen.Function(function, interfaceExprs);
+ info.vcexpr = vcexpr;
+
+ if (mode == Mode.Boogie)
+ {
+ Term z3vc = boogieContext.VCExprToTerm(vcexpr, linOptions);
+ FactorVCs(z3vc, DualityVCs);
+ }
+ else
+ {
+ // Index the procedures by relational variable
+ FuncDecl R = boogieContext.VCExprToTerm(info.funcExpr, linOptions).GetAppDecl();
+ relationToProc.Add(R, info);
+ info.node = rpfp.CreateNode(boogieContext.VCExprToTerm(info.funcExpr, linOptions));
+ rpfp.nodes.Add(info.node);
+ if (info.isMain || QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
+ info.node.Bound.Formula = ctx.MkFalse();
+ }
+ }
+
+ // This returns a new FuncDel with same sort as top-level function
+ // of term t, but with numeric suffix appended to name.
+
+ private FuncDecl SuffixFuncDecl(Term t, int n)
+ {
+ var name = t.GetAppDecl().GetDeclName() + "_" + n.ToString();
+ return ctx.MkFuncDecl(name, t.GetAppDecl());
+ }
+
+ // Collect the relational paremeters
+
+ private Term CollectParamsRec(TermDict<Term> memo, Term t, List<FuncDecl> parms, List<RPFP.Node> nodes, Dictionary<Term,Term> done)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ var kind = t.GetKind();
+ if (kind == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ var args = t.GetAppArgs();
+ args = args.Select(x => CollectParamsRec(memo, x, parms, nodes, done)).ToArray();
+ StratifiedInliningInfo info;
+ if (relationToProc.TryGetValue(f, out info))
+ {
+ if (done.ContainsKey(t))
+ res = done[t];
+ else
+ {
+ f = SuffixFuncDecl(t, parms.Count);
+ parms.Add(f);
+ nodes.Add(info.node);
+ res = ctx.MkApp(f, args);
+ done.Add(t,res); // don't count same expression twice!
+ }
+ }
+ else
+ res = ctx.CloneApp(t, args);
+ } // TODO: handle quantifiers
+ else res = t;
+ memo.Add(t, res);
+ return res;
+ }
+
+ public void GetTransformer(StratifiedInliningInfo info)
+ {
+ Term vcTerm = boogieContext.VCExprToTerm(info.vcexpr, linOptions);
+ Term[] paramTerms = info.interfaceExprVars.Select(x => boogieContext.VCExprToTerm(x, linOptions)).ToArray();
+ var relParams = new List<FuncDecl>();
+ var nodeParams = new List<RPFP.Node>();
+ var memo = new TermDict< Term>();
+ var done = new Dictionary<Term,Term>(); // note this hashes on equality, not reference!
+ vcTerm = CollectParamsRec(memo, vcTerm, relParams, nodeParams,done);
+ // var ops = new Util.ContextOps(ctx);
+ // var foo = ops.simplify_lhs(vcTerm);
+ // vcTerm = foo.Item1;
+ info.F = rpfp.CreateTransformer(relParams.ToArray(), paramTerms, vcTerm);
+ info.edge = rpfp.CreateEdge(info.node, info.F, nodeParams.ToArray());
+ rpfp.edges.Add(info.edge);
+ // TODO labels[info.edge.number] = foo.Item2;
+ }
+
+ public RPFP.Node GetNodeOfImpl(Implementation/*!*/ impl)
+ {
+ return implName2StratifiedInliningInfo[impl.Name].node;
+ }
+
+ public class CyclicLiveVariableAnalysis : Microsoft.Boogie.LiveVariableAnalysis
+ {
+ public new static void ComputeLiveVariables(Implementation impl)
+ {
+
+ bool some_change = true;
+ List<Block> sortedNodes = new List<Block>();
+ foreach (var block in impl.Blocks)
+ {
+ sortedNodes.Add(block);
+ }
+ sortedNodes.Reverse();
+
+ while (some_change)
+ {
+ some_change = false;
+ foreach (Block/*!*/ block in sortedNodes)
+ {
+ Contract.Assert(block != null);
+ HashSet<Variable/*!*/>/*!*/ liveVarsAfter = new HashSet<Variable/*!*/>();
+ if (block.TransferCmd is GotoCmd)
+ {
+ GotoCmd gotoCmd = (GotoCmd)block.TransferCmd;
+ if (gotoCmd.labelTargets != null)
+ {
+ foreach (Block/*!*/ succ in gotoCmd.labelTargets)
+ {
+ Contract.Assert(succ != null);
+ if (succ.liveVarsBefore != null)
+ liveVarsAfter.UnionWith(succ.liveVarsBefore);
+ }
+ }
+ }
+
+ List<Cmd> cmds = block.Cmds;
+ int len = cmds.Count;
+ for (int i = len - 1; i >= 0; i--)
+ {
+ if (cmds[i] is CallCmd)
+ {
+ Procedure/*!*/ proc = cce.NonNull(cce.NonNull((CallCmd/*!*/)cmds[i]).Proc);
+ if (InterProcGenKill.HasSummary(proc.Name))
+ {
+ liveVarsAfter =
+ InterProcGenKill.PropagateLiveVarsAcrossCall(cce.NonNull((CallCmd/*!*/)cmds[i]), liveVarsAfter);
+ continue;
+ }
+ }
+ Propagate(cmds[i], liveVarsAfter);
+ }
+
+ if (block.liveVarsBefore == null)
+ block.liveVarsBefore = new HashSet<Variable>();
+ if (!liveVarsAfter.IsSubsetOf(block.liveVarsBefore))
+ {
+ block.liveVarsBefore = liveVarsAfter;
+ some_change = true;
+ }
+ }
+ }
+ }
+ }
+
+ public void Generate()
+ {
+
+ var oldDagOption = CommandLineOptions.Clo.vcVariety;
+ CommandLineOptions.Clo.vcVariety = CommandLineOptions.VCVariety.Dag;
+
+ // MarkAllFunctionImplementationsInline(); // This is for SMACK, which goes crazy with functions
+
+ // Run live variable analysis (TODO: should this be here?)
+#if false
+ if (CommandLineOptions.Clo.LiveVariableAnalysis == 2)
+ {
+ Microsoft.Boogie.InterProcGenKill.ComputeLiveVars(impl, program);
+ }
+#endif
+
+ #region In Boogie mode, annotate the program
+ if (mode == Mode.Boogie)
+ {
+
+ // find the name of the main procedure
+ main_proc_name = null; // default in case no entry point defined
+ foreach (var impl in program.Implementations)
+ {
+ if (QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
+ main_proc_name = impl.Proc.Name;
+ }
+ if (main_proc_name == null)
+ {
+ foreach (var impl in program.Implementations)
+ {
+ if (impl.Proc.Name == "main" || impl.Proc.Name.EndsWith(".main"))
+ main_proc_name = impl.Proc.Name;
+ }
+ }
+ if (main_proc_name == null)
+ main_proc_name = "main";
+
+ if (style == AnnotationStyle.Flat)
+ {
+ InlineAll();
+ Microsoft.Boogie.BlockCoalescer.CoalesceBlocks(program);
+ foreach (var impl in program.Implementations)
+ {
+ if (main_proc_name == impl.Proc.Name)
+ {
+ Microsoft.Boogie.LiveVariableAnalysis.ClearLiveVariables(impl);
+ CyclicLiveVariableAnalysis.ComputeLiveVariables(impl);
+ AnnotateLoops(impl, boogieContext);
+ }
+ }
+ }
+ else
+ {
+
+ if (style == AnnotationStyle.Procedure || style == AnnotationStyle.Call)
+ {
+ foreach (var impl in program.Implementations)
+ {
+ if (!QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
+ AnnotateProcRequires(impl.Proc, impl, boogieContext);
+ AnnotateProcEnsures(impl.Proc, impl, boogieContext);
+ }
+ if (style == AnnotationStyle.Call)
+ {
+
+ }
+ }
+
+ // must do this after annotating procedures, else calls
+ // will be prematurely desugared
+
+ foreach (var impl in program.Implementations)
+ {
+ Microsoft.Boogie.LiveVariableAnalysis.ClearLiveVariables(impl);
+ CyclicLiveVariableAnalysis.ComputeLiveVariables(impl);
+ }
+
+
+ if (style == AnnotationStyle.Flat || style == AnnotationStyle.Call)
+ {
+ foreach (var impl in program.Implementations)
+ {
+ AnnotateLoops(impl, boogieContext);
+ }
+ }
+ if (style == AnnotationStyle.Call)
+ {
+ Dictionary<string, bool> impls = new Dictionary<string, bool>();
+ foreach (var impl in program.Implementations)
+ {
+ impls.Add(impl.Proc.Name, true);
+ }
+ foreach (var impl in program.Implementations)
+ {
+ AnnotateCallSites(impl, boogieContext, impls);
+ }
+ }
+ if (style == AnnotationStyle.Flat)
+ InlineAll();
+ }
+ }
+ #endregion
+
+ /* Generate the VC's */
+ GenerateVCsForStratifiedInlining();
+
+ /* Generate the background axioms */
+ Term background = ctx.MkTrue(); // TODO boogieContext.VCExprToTerm(boogieContext.Axioms, linOptions);
+ rpfp.AssertAxiom(background);
+
+ int save_option = CommandLineOptions.Clo.StratifiedInlining; // need this to get funcall labels
+ CommandLineOptions.Clo.StratifiedInlining = 1;
+
+ /* Create the nodes, indexing procedures by their relational symbols. */
+ foreach (StratifiedInliningInfo info in implName2StratifiedInliningInfo.Values)
+ GenerateVCForStratifiedInlining(program, info, checker);
+
+ CommandLineOptions.Clo.StratifiedInlining = save_option;
+
+ if (mode == Mode.Boogie)
+ {
+ // var ops = new Util.ContextOps(ctx);
+ var vcs = DualityVCs;
+ DualityVCs = new List<Term>();
+ foreach (var vc in vcs)
+ {
+ // var foo = ops.simplify_lhs(vc.GetAppArgs()[0]);
+ var foo = vc.GetAppArgs()[0];
+ if (!foo.IsFalse())
+ DualityVCs.Add(ctx.MkImplies(foo, vc.GetAppArgs()[1]));
+ }
+
+ rpfp.FromClauses(DualityVCs.ToArray());
+ // TODO rpfp.HornClauses = style == AnnotationStyle.Flat;
+ }
+ else
+ {
+ /* Generate the edges. */
+ foreach (StratifiedInliningInfo info in implName2StratifiedInliningInfo.Values)
+ GetTransformer(info);
+ }
+
+ // save some information for debugging purposes
+ // TODO rpfp.ls.SetAnnotationInfo(annotationInfo);
+
+ CommandLineOptions.Clo.vcVariety = oldDagOption;
+ }
+
+
+ private class ErrorHandler : ProverInterface.ErrorHandler
+ {
+ //TODO: anything we need to handle?
+ }
+
+ Dictionary<int, Dictionary<string, string>> varSubst = null;
+
+ /** Check the RPFP, and return a counterexample if there is one. */
+
+ public VC.ConditionGeneration.Outcome Check(ref RPFP.Node cexroot)
+ {
+ var start = DateTime.Now;
+
+ ErrorHandler handler = new ErrorHandler();
+ RPFP.Node cex;
+ varSubst = new Dictionary<int,Dictionary<string,string>>();
+
+#if false
+ int origRecursionBound = CommandLineOptions.Clo.RecursionBound;
+ if (CommandLineOptions.Clo.RecursionBound > 0 && extraRecBound != null)
+ {
+ int maxExtra = 0;
+ foreach (string s in extraRecBound.Keys)
+ {
+ int extra = extraRecBound[s];
+ if (extra > maxExtra) maxExtra = extra;
+ }
+ CommandLineOptions.Clo.RecursionBound += maxExtra;
+ }
+#endif
+
+ ProverInterface.Outcome outcome =
+ checker.TheoremProver.CheckRPFP("name", rpfp, handler, out cex, varSubst, extraRecBound);
+ cexroot = cex;
+
+#if false
+ CommandLineOptions.Clo.RecursionBound = origRecursionBound;
+#endif
+
+ Console.WriteLine("solve: {0}s", (DateTime.Now - start).TotalSeconds);
+
+ switch(outcome)
+ {
+ case ProverInterface.Outcome.Valid:
+ return VC.ConditionGeneration.Outcome.Correct;
+ case ProverInterface.Outcome.Bounded:
+ return VC.ConditionGeneration.Outcome.ReachedBound;
+ case ProverInterface.Outcome.Invalid:
+ return VC.ConditionGeneration.Outcome.Errors;
+ case ProverInterface.Outcome.TimeOut:
+ return VC.ConditionGeneration.Outcome.TimedOut;
+ default:
+ return VC.ConditionGeneration.Outcome.Inconclusive;
+ }
+ }
+
+ private bool generated = false;
+
+ static private Object thisLock = new Object();
+
+ public override VC.VCGen.Outcome VerifyImplementation(Implementation impl, VerifierCallback collector)
+ {
+
+ lock (thisLock)
+ {
+ Procedure proc = impl.Proc;
+
+ // we verify all the impls at once, so we need to execute only once
+ // TODO: make sure needToCheck is true only once
+ bool needToCheck = false;
+ if (mode == Mode.OldCorral)
+ needToCheck = proc.FindExprAttribute("inline") == null && !(proc is LoopProcedure);
+ else if (mode == Mode.Corral || mode == Mode.Boogie)
+ needToCheck = QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint") && !(proc is LoopProcedure);
+ else
+ needToCheck = impl.Name == main_proc_name;
+
+ if (needToCheck)
+ {
+
+ var start = DateTime.Now;
+
+ if (!generated)
+ {
+ Generate();
+ Console.WriteLine("generate: {0}s", (DateTime.Now - start).TotalSeconds);
+ generated = true;
+ }
+
+
+ Console.WriteLine("Verifying {0}...", impl.Name);
+
+ RPFP.Node cexroot = null;
+ // start = DateTime.Now;
+ var checkres = Check(ref cexroot);
+ Console.WriteLine("check: {0}s", (DateTime.Now - start).TotalSeconds);
+ switch (checkres)
+ {
+ case Outcome.Errors:
+ Console.WriteLine("Counterexample found.\n");
+ // start = DateTime.Now;
+ Counterexample cex = CreateBoogieCounterExample(cexroot.owner, cexroot, impl);
+ // cexroot.owner.DisposeDualModel();
+ // cex.Print(0); // just for testing
+ collector.OnCounterexample(cex, "assertion failure");
+ Console.WriteLine("cex: {0}s", (DateTime.Now - start).TotalSeconds);
+ ConjecturesToSpecs();
+ break;
+ case Outcome.Correct:
+ Console.WriteLine("Procedure is correct. (fixed point reached)");
+ FixedPointToSpecs();
+ ConjecturesToSpecs();
+ break;
+ case Outcome.ReachedBound:
+ Console.WriteLine("Procedure is correct. (recursion bound reached)");
+ FixedPointToSpecs();
+ ConjecturesToSpecs();
+ break;
+ default:
+ Console.WriteLine("Inconclusive result.");
+ ConjecturesToSpecs();
+ break;
+ }
+ return checkres;
+
+ }
+
+ return Outcome.Inconclusive;
+ }
+ }
+
+ public void FindLabelsRec(HashSet<Term> memo, Term t, Dictionary<string, Term> res)
+ {
+ if (memo.Contains(t))
+ return;
+ if (t.IsLabel())
+ {
+ string l = t.LabelName();
+ if (!res.ContainsKey(l))
+ res.Add(l, t.GetAppArgs()[0]);
+ }
+ if (t.GetKind() == TermKind.App)
+ {
+ var args = t.GetAppArgs();
+ foreach (var a in args)
+ FindLabelsRec(memo, a, res);
+ } // TODO: handle quantifiers
+
+ memo.Add(t);
+ }
+
+ public void FindLabels()
+ {
+ labels = new Dictionary<string, Term>();
+ foreach(var e in rpfp.edges){
+ int id = e.number;
+ HashSet<Term> memo = new HashSet<Term>(ReferenceComparer<Term>.Instance);
+ FindLabelsRec(memo, e.F.Formula, labels);
+ }
+ }
+
+ public string CodeLabel(Absy code, StratifiedInliningInfo info, string prefix)
+ {
+ if (info.label2absyInv == null)
+ {
+ info.label2absyInv = new Dictionary<Absy, string>();
+ foreach (int foo in info.label2absy.Keys)
+ {
+ Absy bar = info.label2absy[foo] as Absy;
+ string lbl = foo.ToString();
+ info.label2absyInv.Add(bar, lbl);
+ }
+ }
+ if (info.label2absyInv.ContainsKey(code))
+ {
+ string label = info.label2absyInv[code];
+ return prefix+label;
+ }
+ return null;
+ }
+
+ public Term CodeLabeledExpr(RPFP rpfp, RPFP.Node root, Absy code, StratifiedInliningInfo info, string prefix)
+ {
+ string label = CodeLabel(code, info, prefix);
+
+ if (label != null)
+ {
+ var res = labels[label];
+ return res;
+ }
+ else return null;
+ }
+
+ public class LabelNotFound : Exception { };
+
+ public bool CodeLabelTrue(RPFP rpfp, RPFP.Node root, Absy code, StratifiedInliningInfo info, string prefix)
+ {
+ string label = CodeLabel(code, info, prefix);
+
+ if (label == null)
+ throw new LabelNotFound();
+ return root.Outgoing.labels.Contains(label);
+ }
+
+ public bool CodeLabelFalse(RPFP rpfp, RPFP.Node root, Absy code, StratifiedInliningInfo info, string prefix)
+ {
+ return CodeLabelTrue(rpfp, root, code, info, prefix);
+ }
+
+
+ private class StateId
+ {
+ public RPFP.Edge edge;
+ public int capturePoint;
+ public StratifiedInliningInfo info;
+ public StateId(RPFP.Edge e, int c, StratifiedInliningInfo i)
+ {
+ edge = e;
+ capturePoint = c;
+ info = i;
+ }
+ }
+
+
+ public Counterexample CreateBoogieCounterExample(RPFP rpfp, RPFP.Node root, Implementation mainImpl)
+ {
+ FindLabels();
+ var orderedStateIds = new List<StateId>();
+ Counterexample newCounterexample =
+ GenerateTrace(rpfp, root, orderedStateIds, mainImpl,true);
+ if (CommandLineOptions.Clo.ModelViewFile != null)
+ {
+ Model m = root.owner.GetBackgroundModel();
+ GetModelWithStates(m, root, implName2StratifiedInliningInfo[mainImpl.Name],
+ orderedStateIds, varSubst);
+ newCounterexample.Model = m;
+ newCounterexample.ModelHasStatesAlready = true;
+ }
+ return newCounterexample;
+ }
+
+
+
+ private Counterexample GenerateTrace(RPFP rpfp, RPFP.Node root,
+ List<StateId> orderedStateIds, Implementation procImpl, bool toplevel)
+ {
+ Contract.Requires(procImpl != null);
+
+ Contract.Assert(!rpfp.Empty(root));
+
+
+ var info = implName2StratifiedInliningInfo[procImpl.Name];
+ Block entryBlock = cce.NonNull(procImpl.Blocks[0]);
+ Contract.Assert(entryBlock != null);
+
+ List<Block> trace = new List<Block>();
+ trace.Add(entryBlock);
+
+ var calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
+
+ Counterexample newCounterexample =
+ GenerateTraceRec(rpfp, root, orderedStateIds, entryBlock, trace, calleeCounterexamples, info, toplevel);
+
+ return newCounterexample;
+ }
+
+ // TODO: this is a bit cheesy. Rather than finding the argument position
+ // of a relational term in a transformer by linear search, better to index this
+ // somewhere, but where?
+ private int TransformerArgPosition(RPFP rpfp, RPFP.Node root, Term expr)
+ {
+ FuncDecl rel = expr.GetAppDecl();
+ string relname = rel.GetDeclName();
+ var rps = root.Outgoing.F.RelParams;
+ for (int i = 0; i < rps.Length; i++)
+ {
+ string thisname = rps[i].GetDeclName();
+ if (thisname == relname)
+ return i;
+ }
+ return -1;
+ }
+
+ private bool EvalToFalse(RPFP rpfp, RPFP.Node root, Term expr,StratifiedInliningInfo info){
+ Term res = rpfp.Eval(root.Outgoing,expr);
+ return res.Equals(ctx.MkTrue());
+ }
+
+ private Counterexample GenerateTraceRec(
+ RPFP rpfp, RPFP.Node root,
+ List<StateId> orderedStateIds,
+ Block/*!*/ b, List<Block>/*!*/ trace,
+ Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples,
+ StratifiedInliningInfo info,
+ bool toplevel)
+ {
+ Contract.Requires(b != null);
+ Contract.Requires(trace != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(calleeCounterexamples));
+
+ Stack<RPFP.Node> continuation_stack = new Stack<RPFP.Node>();
+
+ // If our block is not present, try diving into precondition
+ // and push a continuation.
+ // TODO: is the precondition always the first child?
+ while (!CodeLabelFalse(rpfp, root, b, info, "+"))
+ {
+ if (root.Outgoing != null && root.Outgoing.Children.Length > 0)
+ {
+ continuation_stack.Push(root);
+ root = root.Outgoing.Children[0];
+ }
+ else
+ {
+ // can't find our block
+ Contract.Assert(false);
+ return null;
+ }
+ }
+
+ // After translation, all potential errors come from asserts.
+ while (true)
+ {
+
+
+ List<Cmd> cmds = b.Cmds;
+ TransferCmd transferCmd = cce.NonNull(b.TransferCmd);
+ for (int i = 0; i < cmds.Count; i++)
+ {
+ Cmd cmd = cce.NonNull(cmds[i]);
+
+ // Skip if 'cmd' not contained in the trace or not an assert
+ if (cmd is AssertCmd)
+ {
+ bool is_failed_assertion = false;
+ if (NoLabels)
+ is_failed_assertion = true; // we assume only assertions on
+ else
+ is_failed_assertion = CodeLabelTrue(rpfp, root, cmd, info, "@");
+
+ if (is_failed_assertion)
+ {
+ if (continuation_stack.Count == 0)
+ {
+ Counterexample newCounterexample =
+ AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, new Microsoft.Boogie.Model(), info.mvInfo,
+ boogieContext);
+ newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
+ return newCounterexample;
+ }
+ root = continuation_stack.Pop();
+ }
+ continue;
+ }
+
+ // Counterexample generation for inlined procedures
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd == null)
+ continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null)
+ continue;
+ string calleeName = naryExpr.Fun.FunctionName;
+ Contract.Assert(calleeName != null);
+
+ // what is this crap???
+ BinaryOperator binOp = naryExpr.Fun as BinaryOperator;
+ if (binOp != null && binOp.Op == BinaryOperator.Opcode.And)
+ {
+ Expr expr = naryExpr.Args[0];
+ NAryExpr mvStateExpr = expr as NAryExpr;
+ if (mvStateExpr != null && mvStateExpr.Fun.FunctionName == VC.ModelViewInfo.MVState_FunctionDef.Name)
+ {
+ LiteralExpr x = mvStateExpr.Args[1] as LiteralExpr;
+ // Debug.Assert(x != null);
+ int foo = x.asBigNum.ToInt;
+ orderedStateIds.Add(new StateId(root.Outgoing,foo,info));
+ }
+ }
+
+ if (calleeName.EndsWith("_summary"))
+ calleeName = calleeName.Substring(0, calleeName.Length - 8);
+
+ if (!implName2StratifiedInliningInfo.ContainsKey(calleeName) && !calleeName.EndsWith("_summary"))
+ continue;
+
+ {
+ Term code = CodeLabeledExpr(rpfp, root, cmd, info, "+si_fcall_");
+ int pos = TransformerArgPosition(rpfp, root, code);
+ if (pos >= 0)
+ {
+ RPFP.Node callee = root.Outgoing.Children[pos];
+ orderedStateIds.Add(new StateId(callee.Outgoing, CALL,info));
+ calleeCounterexamples[new TraceLocation(trace.Count - 1, i)] =
+ new CalleeCounterexampleInfo(
+ cce.NonNull(GenerateTrace(rpfp, callee, orderedStateIds,
+ implName2StratifiedInliningInfo[calleeName].impl, false)),
+ new List<object>());
+ orderedStateIds.Add(new StateId(root.Outgoing, RETURN,info));
+ }
+ }
+ }
+
+ GotoCmd gotoCmd = transferCmd as GotoCmd;
+ List<Block> cuts = null;
+ if (edgesCut.ContainsKey(b))
+ cuts = edgesCut[b];
+ b = null;
+
+ if (gotoCmd != null)
+ {
+
+ foreach (Block bb in cce.NonNull(gotoCmd.labelTargets))
+ {
+ Contract.Assert(bb != null);
+ if (CodeLabelFalse(rpfp, root, bb, info, "+"))
+ {
+ trace.Add(bb);
+ b = bb;
+ break;
+ }
+ }
+ if (b != null) continue;
+ }
+ // HACK: we have to try edges that were cut in generating the VC
+
+ if (cuts != null)
+ foreach (var bb in cuts)
+ {
+ if (CodeLabelFalse(rpfp, root, bb, info, "+"))
+ {
+ trace.Add(bb);
+ b = bb;
+ break;
+ }
+ }
+ if (b != null) continue;
+
+ return null;
+ }
+
+
+ }
+
+ public override Counterexample extractLoopTrace(Counterexample cex, string mainProcName, Program program, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
+ {
+ // Construct the set of inlined procs in the original program
+ var inlinedProcs = new HashSet<string>();
+ foreach (var decl in program.TopLevelDeclarations)
+ {
+ // Implementations
+ if (decl is Implementation)
+ {
+ var impl = decl as Implementation;
+ if (!(impl.Proc is LoopProcedure))
+ {
+ inlinedProcs.Add(impl.Name);
+ }
+ }
+
+ // And recording procedures
+ if (decl is Procedure)
+ {
+ var proc = decl as Procedure;
+ if (proc.Name.StartsWith(recordProcName))
+ {
+ // Debug.Assert(!(decl is LoopProcedure));
+ inlinedProcs.Add(proc.Name);
+ }
+ }
+ }
+ return extractLoopTraceRec(
+ new CalleeCounterexampleInfo(cex, new List<object>()),
+ mainProcName, inlinedProcs, extractLoopMappingInfo).counterexample;
+ }
+
+ protected override bool elIsLoop(string procname)
+ {
+ StratifiedInliningInfo info = null;
+ if (implName2StratifiedInliningInfo.ContainsKey(procname))
+ {
+ info = implName2StratifiedInliningInfo[procname];
+ }
+
+ if (info == null) return false;
+
+ var lp = info.impl.Proc as LoopProcedure;
+
+ if (lp == null) return false;
+ return true;
+ }
+
+ private void NumberCexEdges(RPFP.Node node, Dictionary<int,RPFP.Edge> map)
+ {
+ if (node.Outgoing == null)
+ return; // shouldn't happen
+ RPFP.Edge edge = node.Outgoing;
+ map[edge.number] = edge;
+ foreach (var c in edge.Children)
+ NumberCexEdges(c, map);
+ }
+
+ private void GetModelWithStates(Model m, RPFP.Node cex, StratifiedInliningInfo mainInfo,
+ List<StateId> orderedStateIds,
+ Dictionary<int,Dictionary<string,string>> varSubst)
+ {
+ if (m == null) return;
+ var mvInfo = mainInfo.mvInfo;
+
+
+ foreach (Variable v in mvInfo.AllVariables)
+ {
+ m.InitialState.AddBinding(v.Name, GetModelValue(m, v, varSubst[cex.Outgoing.number]));
+ }
+
+ Dictionary<int, RPFP.Edge> edgeNumbering = new Dictionary<int,RPFP.Edge>();
+ NumberCexEdges(cex, edgeNumbering);
+
+ int lastCandidate = 0;
+ int lastCapturePoint = CALL;
+ for (int i = 0; i < orderedStateIds.Count; ++i)
+ {
+ var s = orderedStateIds[i];
+ RPFP.Edge edge = s.edge;
+ int candidate = edge.number;
+ int capturePoint = s.capturePoint;
+ Dictionary<string, string> subst = varSubst[candidate];
+
+ string implName = edge.Parent.Name.GetDeclName();
+ var info = s.info.mvInfo;
+
+ if (capturePoint == CALL || capturePoint == RETURN)
+ {
+ lastCandidate = candidate;
+ lastCapturePoint = capturePoint;
+ continue;
+ }
+
+ Contract.Assume(0 <= capturePoint && capturePoint < info.CapturePoints.Count);
+ VC.ModelViewInfo.Mapping map = info.CapturePoints[capturePoint];
+ var prevInc = (lastCapturePoint != CALL && lastCapturePoint != RETURN && candidate == lastCandidate)
+ ? info.CapturePoints[lastCapturePoint].IncarnationMap : new Dictionary<Variable, Expr>();
+ var cs = m.MkState(map.Description);
+
+ foreach (Variable v in info.AllVariables)
+ {
+ var e = (Expr)map.IncarnationMap[v];
+
+ if (e == null)
+ {
+ if (lastCapturePoint == CALL || lastCapturePoint == RETURN)
+ {
+ cs.AddBinding(v.Name, GetModelValue(m, v, subst));
+ }
+ continue;
+ }
+
+ if (lastCapturePoint != CALL && lastCapturePoint != RETURN && prevInc[v] == e) continue; // skip unchanged variables
+
+ Model.Element elt;
+ if (e is IdentifierExpr)
+ {
+ IdentifierExpr ide = (IdentifierExpr)e;
+ elt = GetModelValue(m, ide.Decl, subst);
+ }
+ else if (e is LiteralExpr)
+ {
+ LiteralExpr lit = (LiteralExpr)e;
+ elt = m.MkElement(lit.Val.ToString());
+ }
+ else
+ {
+ Contract.Assume(false);
+ elt = m.MkFunc(e.ToString(), 0).GetConstant();
+ }
+ cs.AddBinding(v.Name, elt);
+ }
+
+ lastCandidate = candidate;
+ lastCapturePoint = capturePoint;
+ }
+
+ return;
+ }
+
+
+ public readonly static int CALL = -1;
+ public readonly static int RETURN = -2;
+
+ private Model.Element GetModelValue(Model m, Variable v, Dictionary<string,string> subst)
+ {
+ // first, get the unique name
+ string uniqueName;
+
+ VCExprVar vvar = boogieContext.BoogieExprTranslator.TryLookupVariable(v);
+
+ uniqueName = v.Name;
+
+ if(subst.ContainsKey(uniqueName))
+ return m.MkElement(subst[uniqueName]);
+ return m.MkFunc("@undefined", 0).GetConstant();
+ }
+
+ class InternalError : Exception {
+ }
+
+
+ private BinaryOperator.Opcode VCOpToOp (VCExprOp op)
+ {
+ if (op == VCExpressionGenerator.AddIOp)
+ return BinaryOperator.Opcode.Add;
+ if (op == VCExpressionGenerator.SubIOp)
+ return BinaryOperator.Opcode.Sub;
+ if (op == VCExpressionGenerator.MulIOp)
+ return BinaryOperator.Opcode.Mul;
+ if (op == VCExpressionGenerator.DivIOp)
+ return BinaryOperator.Opcode.Div;
+ if (op == VCExpressionGenerator.EqOp)
+ return BinaryOperator.Opcode.Eq;
+ if (op == VCExpressionGenerator.LeOp)
+ return BinaryOperator.Opcode.Le;
+ if (op == VCExpressionGenerator.LtOp)
+ return BinaryOperator.Opcode.Lt;
+ if (op == VCExpressionGenerator.GeOp)
+ return BinaryOperator.Opcode.Ge;
+ if (op == VCExpressionGenerator.GtOp)
+ return BinaryOperator.Opcode.Gt;
+ if (op == VCExpressionGenerator.AndOp)
+ return BinaryOperator.Opcode.And;
+ if (op == VCExpressionGenerator.OrOp)
+ return BinaryOperator.Opcode.Or;
+ throw new InternalError();
+ }
+
+ private Expr MakeBinary (BinaryOperator.Opcode op, List<Expr> args)
+ {
+ if(args.Count == 0){
+ // with zero args we need the identity of the op
+ switch(op){
+ case BinaryOperator.Opcode.And:
+ return Expr.True;
+ case BinaryOperator.Opcode.Or:
+ return Expr.False;
+ case BinaryOperator.Opcode.Add:
+ return new LiteralExpr(Token.NoToken,Microsoft.Basetypes.BigNum.ZERO);
+ default:
+ throw new InternalError();
+ }
+ }
+ var temp = args[0];
+ for(int i = 1; i < args.Count; i++)
+ temp = Expr.Binary(Token.NoToken,op,temp,args[i]);
+ return temp;
+ }
+
+ private Variable MakeVar(VCExprVar v){
+ var foo = new TypedIdent(Token.NoToken,v.Name.ToString(),v.Type);
+ return new BoundVariable(Token.NoToken,foo);
+ }
+
+ private Expr VCExprToExpr (VCExpr e, Dictionary<VCExpr,Expr> bound)
+ {
+ if (e is VCExprVar) {
+ if(bound.ContainsKey(e))
+ return bound[e];
+ return Expr.Ident(MakeVar(e as VCExprVar)); // TODO: this isn't right
+ }
+ if (e is VCExprIntLit) {
+ var n = e as VCExprIntLit;
+ return new LiteralExpr(Token.NoToken,n.Val);
+ }
+ if (e is VCExprNAry) {
+ var f = e as VCExprNAry;
+ var args = new List<Expr>();
+ for(int i = 0; i < f.Arity; i++){
+ args.Add (VCExprToExpr (f[i],bound));
+ }
+
+ if(f.Op == VCExpressionGenerator.NotOp)
+ return Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, args[0]);
+
+ if(f.Op == VCExpressionGenerator.IfThenElseOp)
+ return new NAryExpr(Token.NoToken,new IfThenElse(Token.NoToken),args);
+
+ if(f.Op is VCExprSelectOp){
+ var idx = new List<Expr>();
+ idx.Add(args[1]);
+ return Expr.Select(args[0],idx);
+ }
+
+ if(f.Op is VCExprStoreOp){
+ var idx = new List<Expr>();
+ idx.Add(args[1]);
+ return Expr.Store(args[0],idx,args[2]);
+ }
+
+ if (f.Op is VCExprBoogieFunctionOp)
+ {
+ return new NAryExpr(Token.NoToken,
+ new FunctionCall((f.Op as VCExprBoogieFunctionOp).Func), args);
+ }
+
+ var op = VCOpToOp (f.Op);
+ return MakeBinary(op,args);
+ }
+
+ if(e is VCExprQuantifier) {
+ var f = e as VCExprQuantifier;
+ var vs = new List<Variable>();
+ var new_bound = new Dictionary<VCExpr,Expr>(bound);
+ foreach(var v in f.BoundVars){
+ var ve = MakeVar(v);
+ vs.Add(ve);
+ new_bound.Add (v,Expr.Ident (ve));
+ }
+ var bd = VCExprToExpr(f.Body,new_bound);
+ if(f.Quan == Quantifier.EX)
+ return new ExistsExpr(Token.NoToken,vs,bd);
+ else
+ return new ForallExpr(Token.NoToken,vs,bd);
+ }
+ if (e == VCExpressionGenerator.True) {
+ return Expr.True;
+ }
+ if (e == VCExpressionGenerator.False) {
+ return Expr.False;
+ }
+ if (e is VCExprLet) {
+
+ }
+
+ throw new InternalError();
+ }
+
+
+ }
+
+
+}
diff --git a/Source/VCGeneration/OrderingAxioms.cs b/Source/VCGeneration/OrderingAxioms.cs
index dbb97764..9284601f 100644
--- a/Source/VCGeneration/OrderingAxioms.cs
+++ b/Source/VCGeneration/OrderingAxioms.cs
@@ -1,338 +1,338 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Linq;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-// Class for constructing and collecting the axioms of the partial
-// order <:. The class also manages "unique" attributes of constants
-// and generated the necessary assumptions for the theorem prover.
-
-// TODO: there should be an interface so that different ways to handle
-// ordering relations can be accessed uniformly
-
-namespace Microsoft.Boogie {
-
- public class OrderingAxiomBuilder {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(Translator != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(OneStepFuns));
- Contract.Invariant(cce.NonNullElements(Constants));
- Contract.Invariant(cce.NonNullElements(CompleteConstantsOpen));
- Contract.Invariant(cce.NonNullElements(AllAxioms));
- Contract.Invariant(cce.NonNullElements(IncAxioms));
- }
-
-
- private readonly VCExpressionGenerator Gen;
- private readonly Boogie2VCExprTranslator Translator;
- private readonly IDictionary<Type, Function> OneStepFuns;
- private readonly List<Constant> Constants = new List<Constant>();
-
- // A list to handle constants whose direct children are fully
- // specified (the "complete" keyword). Constants are removed from
- // the list as soon as the corresponding axiom has been generated,
- // which means that from this point on no further children can be
- // added
- private readonly List<Constant> CompleteConstantsOpen = new List<Constant>();
-
- // list in which all axioms are collected
- private readonly List<VCExpr> AllAxioms = new List<VCExpr>();
-
- // list in which axioms are incrementally collected
- private readonly List<VCExpr> IncAxioms = new List<VCExpr>();
-
-
- public OrderingAxiomBuilder(VCExpressionGenerator gen,
- Boogie2VCExprTranslator translator) {
- Contract.Requires(gen != null);
- Contract.Requires(translator != null);
- this.Gen = gen;
- this.Translator = translator;
- OneStepFuns = new Dictionary<Type, Function>();
- Constants = new List<Constant>();
- CompleteConstantsOpen = new List<Constant>();
- AllAxioms = new List<VCExpr>();
- IncAxioms = new List<VCExpr>();
- }
-
- public OrderingAxiomBuilder(VCExpressionGenerator gen,
- Boogie2VCExprTranslator translator,
- OrderingAxiomBuilder builder) {
- Contract.Requires(gen != null);
- Contract.Requires(translator != null);
- Contract.Requires(builder != null);
- this.Gen = gen;
- this.Translator = translator;
- OneStepFuns = new Dictionary<Type, Function>(builder.OneStepFuns);
- Constants = new List<Constant>(builder.Constants);
- CompleteConstantsOpen = new List<Constant>(builder.CompleteConstantsOpen);
- AllAxioms = new List<VCExpr>(builder.AllAxioms);
- IncAxioms = new List<VCExpr>(builder.IncAxioms);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Used to axiomatise the disjoint-sub-dag specs that are
- // described by parents with the "unique" flag
-
-
- private Function OneStepFunFor(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<Function>() != null);
-
- Function res;
- if (!OneStepFuns.TryGetValue(t, out res)) {
- List<Variable> args = new List<Variable>();
- args.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "arg0", t), true));
- args.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "arg1", t), true));
- Formal result = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "res", t), false);
- res = new Function(Token.NoToken, "oneStep", new List<TypeVariable>(), args, result);
- OneStepFuns.Add(t, res);
- }
- return cce.NonNull(res);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
-
- private void AddAxiom(VCExpr axiom) {
- Contract.Requires(axiom != null);
- if (axiom.Equals(VCExpressionGenerator.True))
- return;
- AllAxioms.Add(axiom);
- IncAxioms.Add(axiom);
- }
-
- // Return all axioms that were added since the last time NewAxioms
- // was called
- public VCExpr GetNewAxioms() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- CloseChildrenCompleteConstants();
- VCExpr res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
- IncAxioms.Clear();
- return res;
- }
-
- // return all axioms
- public VCExpr Axioms {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- CloseChildrenCompleteConstants();
- return Gen.NAry(VCExpressionGenerator.AndOp, AllAxioms);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Generate the normal axioms for a partial order relation
- public void Setup() {
- TypeVariable alpha = new TypeVariable(Token.NoToken, "alpha");
- Contract.Assert(alpha != null);
- List<TypeVariable> typeParams = new List<TypeVariable>();
- typeParams.Add(alpha);
-
- List<VCTrigger> triggers = new List<VCTrigger>();
-
- VCExprVar x = Gen.Variable("x", alpha);
- Contract.Assert(x != null);
- VCExprVar y = Gen.Variable("y", alpha);
- Contract.Assert(y != null);
- VCExprVar z = Gen.Variable("z", alpha);
- Contract.Assert(z != null);
-
- List<VCExprVar> boundVars = new List<VCExprVar>();
-
- // reflexivity
- boundVars.Add(x);
- AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
- new VCQuantifierInfos("bg:subtype-refl", -1, false, null),
- Gen.AtMost(x, x)));
-
- // transitivity
- boundVars = new List<VCExprVar>();
- boundVars.Add(x);
- boundVars.Add(y);
- boundVars.Add(z);
- triggers = new List<VCTrigger>();
- triggers.Add(Gen.Trigger(true, Gen.AtMost(x, y), Gen.AtMost(y, z)));
- VCExpr body = Gen.Implies(Gen.And(Gen.AtMost(x, y), Gen.AtMost(y, z)),
- Gen.AtMost(x, z));
- Contract.Assert(body != null);
- AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
- new VCQuantifierInfos("bg:subtype-trans", -1, false, null),
- body));
-
- // anti-symmetry
- boundVars = new List<VCExprVar>();
- boundVars.Add(x);
- boundVars.Add(y);
- triggers = new List<VCTrigger>();
- triggers.Add(Gen.Trigger(true, Gen.AtMost(x, y), Gen.AtMost(y, x)));
- body = Gen.Implies(Gen.And(Gen.AtMost(x, y), Gen.AtMost(y, x)),
- Gen.Eq(x, y));
- AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
- new VCQuantifierInfos("bg:subtype-antisymm", -1, false, null),
- body));
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void AddConstant(Constant c) {
- Contract.Requires(c != null);
- AddAxiom(GenParentConstraints(c));
- Constants.Add(c);
- if (c.ChildrenComplete)
- CompleteConstantsOpen.Add(c);
-
- // ensure that no further children are added to closed
- // children-complete constants
- Contract.Assert(!(c.Parents != null && Contract.Exists(c.Parents, p => cce.NonNull((Constant)p.Parent.Decl).ChildrenComplete && !CompleteConstantsOpen.Contains((Constant)p.Parent.Decl))));
- }
-
- // Generate the constraints telling that parents of a constant are
- // strictly greater than the constant itself, and are the minimal
- // elements with this property
- private VCExpr GenParentConstraints(Constant c) {
- Contract.Requires(c != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr res = VCExpressionGenerator.True;
-
- if (c.Parents == null)
- return res;
-
- VCExprVar cAsVar = Translator.LookupVariable(c);
- VCExprVar w = Gen.Variable("w", c.TypedIdent.Type);
-
- // Parents of c are proper ancestors of c
- foreach (ConstantParent p in c.Parents) {
- Contract.Assert(p != null);
- VCExprVar par = Translator.LookupVariable(cce.NonNull(p.Parent.Decl));
- res = Gen.AndSimp(res, Gen.Neq(cAsVar, par));
- res = Gen.AndSimp(res, Gen.AtMost(cAsVar, par));
- }
-
- // Parents are direct ancestors of c (no other elements are in
- // between c and a parent)
- foreach (ConstantParent p in c.Parents) {
- Contract.Assert(p != null);
- VCExprVar par = Translator.LookupVariable(cce.NonNull(p.Parent.Decl));
- Contract.Assert(par != null);
- VCExpr antecedent1 = Gen.AtMost(cAsVar, w);
- Contract.Assert(antecedent1 != null);
- VCExpr antecedent2 = Gen.AtMost(w, par);
- Contract.Assert(antecedent2 != null);
- VCExpr body = Gen.Implies(Gen.And(antecedent1, antecedent2),
- Gen.Or(Gen.Eq(cAsVar, w), Gen.Eq(par, w)));
- Contract.Assert(body != null);
- res = Gen.AndSimp(res,
- Gen.Forall(w,
- Gen.Trigger(true, antecedent1, antecedent2),
- body));
- }
-
- // Ancestors of c are only c itself and the ancestors of the
- // parents of c
- VCExpr minAncestors = Gen.Eq(cAsVar, w);
- Contract.Assert(minAncestors != null);
- foreach (ConstantParent p in c.Parents) {
- Contract.Assert(p != null);
- minAncestors =
- Gen.Or(minAncestors,
- Gen.AtMost(Translator.LookupVariable(cce.NonNull(p.Parent.Decl)), w));
- }
- VCExpr antecedent = Gen.AtMost(cAsVar, w);
- Contract.Assert(antecedent != null);
- res = Gen.AndSimp(res,
- Gen.Forall(w,
- Gen.Trigger(true, antecedent),
- Gen.Implies(antecedent, minAncestors)));
-
- // Constraints for unique child-parent edges
- foreach (ConstantParent p in c.Parents) {
- Contract.Assert(p != null);
- if (p.Unique)
- res =
- Gen.AndSimp(res,
- GenUniqueParentConstraint(c, cce.NonNull((Constant)p.Parent.Decl)));
- }
-
- return res;
- }
-
- // Generate axioms that state that all direct children of c are
- // specified; this is the dual of the axiom stating that all direct
- // ancestors of a constant are known
- private VCExpr GenCompleteChildrenConstraints(Constant c) {
- Contract.Requires(c != null);
- Contract.Requires(c.ChildrenComplete);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
-
- VCExprVar cAsVar = Translator.LookupVariable(c);
- VCExprVar w = Gen.Variable("w", c.TypedIdent.Type);
-
- VCExpr maxDescendants = Gen.Eq(cAsVar, w);
- foreach (Constant d in Constants) {
- Contract.Assert(d != null);
- if (d.Parents != null && d.Parents.Any(p => c.Equals(p.Parent.Decl)))
- maxDescendants = Gen.Or(maxDescendants,
- Gen.AtMost(w, Translator.LookupVariable(d)));
- }
-
- VCExpr antecedent = Gen.AtMost(w, cAsVar);
- Contract.Assert(antecedent != null);
- return Gen.Forall(w,
- Gen.Trigger(true, antecedent),
- Gen.Implies(antecedent, maxDescendants));
- }
-
- private void CloseChildrenCompleteConstants() {
- foreach (Constant c in CompleteConstantsOpen) {
- Contract.Assert(c != null);
- AddAxiom(GenCompleteChildrenConstraints(c));
- }
- CompleteConstantsOpen.Clear();
- }
-
- // Generate the axiom ensuring that the sub-dags underneath unique
- // child-parent edges are all disjoint
- private VCExpr GenUniqueParentConstraint(Constant child, Constant parent) {
- Contract.Requires(child != null);
- Contract.Requires(parent != null);
- Contract.Requires(child.TypedIdent.Type.Equals(parent.TypedIdent.Type));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
-
-
- VCExprVar w = Gen.Variable("w", child.TypedIdent.Type);
- Contract.Assert(w != null);
- VCExpr antecedent =
- Gen.AtMost(w, Translator.LookupVariable(child));
- Contract.Assert(antecedent != null);
- VCExpr succedent =
- Gen.Eq(Gen.Function(OneStepFunFor(child.TypedIdent.Type),
- Translator.LookupVariable(parent), w),
- Translator.LookupVariable(child));
- Contract.Assert(succedent != null);
-
- return Gen.Forall(w,
- Gen.Trigger(true, antecedent),
- Gen.Implies(antecedent, succedent));
- }
-
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie.VCExprAST;
+
+// Class for constructing and collecting the axioms of the partial
+// order <:. The class also manages "unique" attributes of constants
+// and generated the necessary assumptions for the theorem prover.
+
+// TODO: there should be an interface so that different ways to handle
+// ordering relations can be accessed uniformly
+
+namespace Microsoft.Boogie {
+
+ public class OrderingAxiomBuilder {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(Translator != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(OneStepFuns));
+ Contract.Invariant(cce.NonNullElements(Constants));
+ Contract.Invariant(cce.NonNullElements(CompleteConstantsOpen));
+ Contract.Invariant(cce.NonNullElements(AllAxioms));
+ Contract.Invariant(cce.NonNullElements(IncAxioms));
+ }
+
+
+ private readonly VCExpressionGenerator Gen;
+ private readonly Boogie2VCExprTranslator Translator;
+ private readonly IDictionary<Type, Function> OneStepFuns;
+ private readonly List<Constant> Constants = new List<Constant>();
+
+ // A list to handle constants whose direct children are fully
+ // specified (the "complete" keyword). Constants are removed from
+ // the list as soon as the corresponding axiom has been generated,
+ // which means that from this point on no further children can be
+ // added
+ private readonly List<Constant> CompleteConstantsOpen = new List<Constant>();
+
+ // list in which all axioms are collected
+ private readonly List<VCExpr> AllAxioms = new List<VCExpr>();
+
+ // list in which axioms are incrementally collected
+ private readonly List<VCExpr> IncAxioms = new List<VCExpr>();
+
+
+ public OrderingAxiomBuilder(VCExpressionGenerator gen,
+ Boogie2VCExprTranslator translator) {
+ Contract.Requires(gen != null);
+ Contract.Requires(translator != null);
+ this.Gen = gen;
+ this.Translator = translator;
+ OneStepFuns = new Dictionary<Type, Function>();
+ Constants = new List<Constant>();
+ CompleteConstantsOpen = new List<Constant>();
+ AllAxioms = new List<VCExpr>();
+ IncAxioms = new List<VCExpr>();
+ }
+
+ public OrderingAxiomBuilder(VCExpressionGenerator gen,
+ Boogie2VCExprTranslator translator,
+ OrderingAxiomBuilder builder) {
+ Contract.Requires(gen != null);
+ Contract.Requires(translator != null);
+ Contract.Requires(builder != null);
+ this.Gen = gen;
+ this.Translator = translator;
+ OneStepFuns = new Dictionary<Type, Function>(builder.OneStepFuns);
+ Constants = new List<Constant>(builder.Constants);
+ CompleteConstantsOpen = new List<Constant>(builder.CompleteConstantsOpen);
+ AllAxioms = new List<VCExpr>(builder.AllAxioms);
+ IncAxioms = new List<VCExpr>(builder.IncAxioms);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Used to axiomatise the disjoint-sub-dag specs that are
+ // described by parents with the "unique" flag
+
+
+ private Function OneStepFunFor(Type t) {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+
+ Function res;
+ if (!OneStepFuns.TryGetValue(t, out res)) {
+ List<Variable> args = new List<Variable>();
+ args.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "arg0", t), true));
+ args.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "arg1", t), true));
+ Formal result = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "res", t), false);
+ res = new Function(Token.NoToken, "oneStep", new List<TypeVariable>(), args, result);
+ OneStepFuns.Add(t, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+
+ private void AddAxiom(VCExpr axiom) {
+ Contract.Requires(axiom != null);
+ if (axiom.Equals(VCExpressionGenerator.True))
+ return;
+ AllAxioms.Add(axiom);
+ IncAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr GetNewAxioms() {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ CloseChildrenCompleteConstants();
+ VCExpr res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
+ IncAxioms.Clear();
+ return res;
+ }
+
+ // return all axioms
+ public VCExpr Axioms {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ CloseChildrenCompleteConstants();
+ return Gen.NAry(VCExpressionGenerator.AndOp, AllAxioms);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Generate the normal axioms for a partial order relation
+ public void Setup() {
+ TypeVariable alpha = new TypeVariable(Token.NoToken, "alpha");
+ Contract.Assert(alpha != null);
+ List<TypeVariable> typeParams = new List<TypeVariable>();
+ typeParams.Add(alpha);
+
+ List<VCTrigger> triggers = new List<VCTrigger>();
+
+ VCExprVar x = Gen.Variable("x", alpha);
+ Contract.Assert(x != null);
+ VCExprVar y = Gen.Variable("y", alpha);
+ Contract.Assert(y != null);
+ VCExprVar z = Gen.Variable("z", alpha);
+ Contract.Assert(z != null);
+
+ List<VCExprVar> boundVars = new List<VCExprVar>();
+
+ // reflexivity
+ boundVars.Add(x);
+ AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
+ new VCQuantifierInfos("bg:subtype-refl", -1, false, null),
+ Gen.AtMost(x, x)));
+
+ // transitivity
+ boundVars = new List<VCExprVar>();
+ boundVars.Add(x);
+ boundVars.Add(y);
+ boundVars.Add(z);
+ triggers = new List<VCTrigger>();
+ triggers.Add(Gen.Trigger(true, Gen.AtMost(x, y), Gen.AtMost(y, z)));
+ VCExpr body = Gen.Implies(Gen.And(Gen.AtMost(x, y), Gen.AtMost(y, z)),
+ Gen.AtMost(x, z));
+ Contract.Assert(body != null);
+ AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
+ new VCQuantifierInfos("bg:subtype-trans", -1, false, null),
+ body));
+
+ // anti-symmetry
+ boundVars = new List<VCExprVar>();
+ boundVars.Add(x);
+ boundVars.Add(y);
+ triggers = new List<VCTrigger>();
+ triggers.Add(Gen.Trigger(true, Gen.AtMost(x, y), Gen.AtMost(y, x)));
+ body = Gen.Implies(Gen.And(Gen.AtMost(x, y), Gen.AtMost(y, x)),
+ Gen.Eq(x, y));
+ AddAxiom(Gen.Forall(typeParams, boundVars, triggers,
+ new VCQuantifierInfos("bg:subtype-antisymm", -1, false, null),
+ body));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void AddConstant(Constant c) {
+ Contract.Requires(c != null);
+ AddAxiom(GenParentConstraints(c));
+ Constants.Add(c);
+ if (c.ChildrenComplete)
+ CompleteConstantsOpen.Add(c);
+
+ // ensure that no further children are added to closed
+ // children-complete constants
+ Contract.Assert(!(c.Parents != null && Contract.Exists(c.Parents, p => cce.NonNull((Constant)p.Parent.Decl).ChildrenComplete && !CompleteConstantsOpen.Contains((Constant)p.Parent.Decl))));
+ }
+
+ // Generate the constraints telling that parents of a constant are
+ // strictly greater than the constant itself, and are the minimal
+ // elements with this property
+ private VCExpr GenParentConstraints(Constant c) {
+ Contract.Requires(c != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr res = VCExpressionGenerator.True;
+
+ if (c.Parents == null)
+ return res;
+
+ VCExprVar cAsVar = Translator.LookupVariable(c);
+ VCExprVar w = Gen.Variable("w", c.TypedIdent.Type);
+
+ // Parents of c are proper ancestors of c
+ foreach (ConstantParent p in c.Parents) {
+ Contract.Assert(p != null);
+ VCExprVar par = Translator.LookupVariable(cce.NonNull(p.Parent.Decl));
+ res = Gen.AndSimp(res, Gen.Neq(cAsVar, par));
+ res = Gen.AndSimp(res, Gen.AtMost(cAsVar, par));
+ }
+
+ // Parents are direct ancestors of c (no other elements are in
+ // between c and a parent)
+ foreach (ConstantParent p in c.Parents) {
+ Contract.Assert(p != null);
+ VCExprVar par = Translator.LookupVariable(cce.NonNull(p.Parent.Decl));
+ Contract.Assert(par != null);
+ VCExpr antecedent1 = Gen.AtMost(cAsVar, w);
+ Contract.Assert(antecedent1 != null);
+ VCExpr antecedent2 = Gen.AtMost(w, par);
+ Contract.Assert(antecedent2 != null);
+ VCExpr body = Gen.Implies(Gen.And(antecedent1, antecedent2),
+ Gen.Or(Gen.Eq(cAsVar, w), Gen.Eq(par, w)));
+ Contract.Assert(body != null);
+ res = Gen.AndSimp(res,
+ Gen.Forall(w,
+ Gen.Trigger(true, antecedent1, antecedent2),
+ body));
+ }
+
+ // Ancestors of c are only c itself and the ancestors of the
+ // parents of c
+ VCExpr minAncestors = Gen.Eq(cAsVar, w);
+ Contract.Assert(minAncestors != null);
+ foreach (ConstantParent p in c.Parents) {
+ Contract.Assert(p != null);
+ minAncestors =
+ Gen.Or(minAncestors,
+ Gen.AtMost(Translator.LookupVariable(cce.NonNull(p.Parent.Decl)), w));
+ }
+ VCExpr antecedent = Gen.AtMost(cAsVar, w);
+ Contract.Assert(antecedent != null);
+ res = Gen.AndSimp(res,
+ Gen.Forall(w,
+ Gen.Trigger(true, antecedent),
+ Gen.Implies(antecedent, minAncestors)));
+
+ // Constraints for unique child-parent edges
+ foreach (ConstantParent p in c.Parents) {
+ Contract.Assert(p != null);
+ if (p.Unique)
+ res =
+ Gen.AndSimp(res,
+ GenUniqueParentConstraint(c, cce.NonNull((Constant)p.Parent.Decl)));
+ }
+
+ return res;
+ }
+
+ // Generate axioms that state that all direct children of c are
+ // specified; this is the dual of the axiom stating that all direct
+ // ancestors of a constant are known
+ private VCExpr GenCompleteChildrenConstraints(Constant c) {
+ Contract.Requires(c != null);
+ Contract.Requires(c.ChildrenComplete);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+
+ VCExprVar cAsVar = Translator.LookupVariable(c);
+ VCExprVar w = Gen.Variable("w", c.TypedIdent.Type);
+
+ VCExpr maxDescendants = Gen.Eq(cAsVar, w);
+ foreach (Constant d in Constants) {
+ Contract.Assert(d != null);
+ if (d.Parents != null && d.Parents.Any(p => c.Equals(p.Parent.Decl)))
+ maxDescendants = Gen.Or(maxDescendants,
+ Gen.AtMost(w, Translator.LookupVariable(d)));
+ }
+
+ VCExpr antecedent = Gen.AtMost(w, cAsVar);
+ Contract.Assert(antecedent != null);
+ return Gen.Forall(w,
+ Gen.Trigger(true, antecedent),
+ Gen.Implies(antecedent, maxDescendants));
+ }
+
+ private void CloseChildrenCompleteConstants() {
+ foreach (Constant c in CompleteConstantsOpen) {
+ Contract.Assert(c != null);
+ AddAxiom(GenCompleteChildrenConstraints(c));
+ }
+ CompleteConstantsOpen.Clear();
+ }
+
+ // Generate the axiom ensuring that the sub-dags underneath unique
+ // child-parent edges are all disjoint
+ private VCExpr GenUniqueParentConstraint(Constant child, Constant parent) {
+ Contract.Requires(child != null);
+ Contract.Requires(parent != null);
+ Contract.Requires(child.TypedIdent.Type.Equals(parent.TypedIdent.Type));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+
+
+ VCExprVar w = Gen.Variable("w", child.TypedIdent.Type);
+ Contract.Assert(w != null);
+ VCExpr antecedent =
+ Gen.AtMost(w, Translator.LookupVariable(child));
+ Contract.Assert(antecedent != null);
+ VCExpr succedent =
+ Gen.Eq(Gen.Function(OneStepFunFor(child.TypedIdent.Type),
+ Translator.LookupVariable(parent), w),
+ Translator.LookupVariable(child));
+ Contract.Assert(succedent != null);
+
+ return Gen.Forall(w,
+ Gen.Trigger(true, antecedent),
+ Gen.Implies(antecedent, succedent));
+ }
+
+ }
+
+}
diff --git a/Source/VCGeneration/RPFP.cs b/Source/VCGeneration/RPFP.cs
index ed3842d5..9d38eb47 100644
--- a/Source/VCGeneration/RPFP.cs
+++ b/Source/VCGeneration/RPFP.cs
@@ -1,609 +1,609 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 2012 Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Term = Microsoft.Boogie.VCExprAST.VCExpr;
-using FuncDecl = Microsoft.Boogie.VCExprAST.VCExprOp;
-using Sort = Microsoft.Boogie.Type;
-using Microsoft.Boogie.VCExprAST;
-
-
-using Microsoft.Boogie.ExprExtensions;
-
-
-namespace Microsoft.Boogie
-{
-
-
-
-
- /** This class represents a relation post-fixed point (RPFP) problem as
- * a "problem graph". The graph consists of Nodes and hyper-edges.
- *
- * A node consists of
- * - Annotation, a symbolic relation
- * - Bound, a symbolic relation giving an upper bound on Annotation
- *
- *
- * A hyper-edge consists of:
- * - Children, a sequence of children Nodes,
- * - F, a symbolic relational transformer,
- * - Parent, a single parent Node.
- *
- * The graph is "solved" when:
- * - For every Node n, n.Annotation subseteq n.Bound
- * - For every hyperedge e, e.F(e.Children.Annotation) subseteq e.Parent.Annotation
- *
- * where, if x is a sequence of Nodes, x.Annotation is the sequences
- * of Annotations of the nodes in the sequence.
- *
- * A symbolic Transformer consists of
- * - RelParams, a sequence of relational symbols
- * - IndParams, a sequence of individual symbols
- * - Formula, a formula over RelParams and IndParams
- *
- * A Transformer t represents a function that takes sequence R of relations
- * and yields the relation lambda (t.Indparams). Formula(R/RelParams).
- *
- * As a special case, a nullary Transformer (where RelParams is the empty sequence)
- * represents a fixed relation.
- *
- * An RPFP consists of
- * - Nodes, a set of Nodes
- * - Edges, a set of hyper-edges
- * - Context, a prover context that contains formula AST's
- *
- * Multiple RPFP's can use the same Context, but you should be careful
- * that only one RPFP asserts constraints in the context at any time.
- *
- * */
- public class RPFP
- {
- /** Symbolic representation of a relational transformer */
- public class Transformer
- {
- public FuncDecl[] RelParams;
- public Term[] IndParams;
- public Term Formula;
- public RPFP owner;
-
- public Transformer Clone()
- {
- return (Transformer)this.MemberwiseClone();
- }
- }
-
- /** Create a symbolic transformer. */
- public Transformer CreateTransformer(FuncDecl[] _RelParams, Term[] _IndParams, Term _Formula)
- {
- Transformer t = new Transformer();
- t.RelParams = _RelParams;
- t.IndParams = _IndParams;
- t.Formula = _Formula;
- t.owner = this;
- return t;
- }
-
- /** Create a relation (nullary relational transformer) */
- public Transformer CreateRelation(Term[] _IndParams, Term _Formula)
- {
- return CreateTransformer(new FuncDecl[0], _IndParams, _Formula);
- }
-
- /** A node in the RPFP graph */
- public class Node
- {
- public FuncDecl Name;
- public Transformer Annotation;
- public Transformer Bound;
- public RPFP owner;
- public int number;
- public Edge Outgoing;
- public List<Edge> Incoming;
- public Term dual;
- public Node map;
- }
-
- /** Create a node in the graph. The input is a term R(v_1...v_n)
- * where R is an arbitrary relational symbol and v_1...v_n are
- * arbitary distinct variables. The names are only of mnemonic value,
- * however, the number and type of arguments determine the type
- * of the relation at this node. */
-
- public Node CreateNode(Term t)
- {
- Node n = new Node();
- // Microsoft.Boogie.VCExprAST.VCExprNAry tn = t as Microsoft.Boogie.VCExprAST.VCExprNAry;
- // Term[] _IndParams = tn.ToArray();
- Term[] _IndParams = t.GetAppArgs();
- FuncDecl Name = t.GetAppDecl();
- n.Annotation = CreateRelation(_IndParams,ctx.MkTrue());
- n.Bound = CreateRelation(_IndParams, ctx.MkTrue());
- n.owner = this;
- n.number = ++nodeCount;
- n.Name = Name; // just to have a unique name
- n.Incoming = new List<Edge>();
- return n;
- }
-
- /** Clone a node (can be from another graph). */
-
- public Node CloneNode(Node old)
- {
- Node n = new Node();
- n.Annotation = old.Annotation.Clone();
- n.Bound = old.Bound.Clone();
- n.owner = this;
- n.number = ++nodeCount;
- n.Name = old.Name; // just to have a unique name
- n.Incoming = new List<Edge>();
- return n;
- }
-
- /** This class represents a hyper-edge in the RPFP graph */
-
- public class Edge
- {
- public Transformer F;
- public Node Parent;
- public Node[] Children;
- public RPFP owner;
- public int number;
- public Edge map;
- public HashSet<string> labels;
- internal Term dual;
- internal TermDict<Term> valuation;
- }
-
-
- /** Create a hyper-edge. */
- public Edge CreateEdge(Node _Parent, Transformer _F, Node[] _Children)
- {
- Edge e = new Edge();
- e.Parent = _Parent;
- e.F = _F;
- e.Children = _Children;
- e.owner = this;
- e.number = ++edgeCount;
- _Parent.Outgoing = e;
- foreach (var c in _Children)
- if(c != null)
- c.Incoming.Add(e);
- return e;
- }
-
- /** Create an edge that lower-bounds its parent. */
- public Edge CreateLowerBoundEdge(Node _Parent)
- {
- return CreateEdge(_Parent, _Parent.Annotation, new RPFP.Node[0]);
- }
-
-
-
-
- /** Assert a background axiom. Background axioms can be used to provide the
- * theory of auxilliary functions or relations. All symbols appearing in
- * background axioms are considered global, and may appear in both transformer
- * and relational solutions. Semantically, a solution to the RPFP gives
- * an interpretation of the unknown relations for each interpretation of the
- * auxilliary symbols that is consistent with the axioms. Axioms should be
- * asserted before any calls to Push. They cannot be de-asserted by Pop. */
-
- public void AssertAxiom(Term t)
- {
- ctx.AddAxiom(t);
- }
-
- /** Do not call this. */
-
- public void RemoveAxiom(Term t)
- {
- ctx.RemoveAxiom(t);
- }
-
- /** Type of solve results */
- public enum LBool { False, True, Undef };
-
-
- /** Solve an RPFP graph. This means either strengthen the annotation
- * so that the bound at the given root node is satisfied, or
- * show that this cannot be done by giving a dual solution
- * (i.e., a counterexample).
- *
- * In the current implementation, this only works for graphs that
- * are:
- * - tree-like
- *
- * - closed.
- *
- * In a tree-like graph, every nod has out most one incoming and one out-going edge,
- * and there are no cycles. In a closed graph, every node has exactly one out-going
- * edge. This means that the leaves of the tree are all hyper-edges with no
- * children. Such an edge represents a relation (nullary transformer) and thus
- * a lower bound on its parent. The parameter root must be the root of this tree.
- *
- * If Solve returns LBool.False, this indicates success. The annotation of the tree
- * has been updated to satisfy the upper bound at the root.
- *
- * If Solve returns LBool.True, this indicates a counterexample. For each edge,
- * you can then call Eval to determine the values of symbols in the transformer formula.
- * You can also call Empty on a node to determine if its value in the counterexample
- * is the empty relation.
- *
- * \param root The root of the tree
- * \param persist Number of context pops through which result should persist
- *
- *
- */
-
- public LBool Solve(Node root, int persist)
- {
- return LBool.False; // TODO
- }
-
-
- /** Dispose of the dual model (counterexample) if there is one. */
-
- public void DisposeDualModel()
- {
- // TODO dualModel = null;
- }
-
-
- /** Determines the value in the counterexample of a symbol occuring in the transformer formula of
- * a given edge. */
-
- public Term Eval(Edge e, Term t)
- {
- if (e.valuation == null)
- e.valuation = new TermDict< Term>();
- if (e.valuation.ContainsKey(t))
- return e.valuation[t];
- return null; // TODO
- }
-
- /** Sets the value in the counterexample of a symbol occuring in the transformer formula of
- * a given edge. */
-
- public void SetValue(Edge e, Term variable, Term value)
- {
- if (e.valuation == null)
- e.valuation = new TermDict< Term>();
- e.valuation.Add(variable, value);
- }
-
-
- /** Returns true if the given node is empty in the primal solution. For proecudure summaries,
- this means that the procedure is not called in the current counter-model. */
-
- public bool Empty(Node p)
- {
- return false; // TODO
- }
-
- /** Push a scope. Assertions made after Push can be undone by Pop. */
-
- public void Push()
- {
- stack.Push(new stack_entry());
- // TODO: do we need push/pop?
- }
-
- /** Pop a scope (see Push). Note, you cannot pop axioms. */
-
- public void Pop(int num_scopes)
- {
- //TODO ctx.Pop((uint)num_scopes);
- for (uint i = 0; i < num_scopes; i++)
- {
- stack_entry back = stack.Pop();
- foreach (var e in back.edges)
- e.dual = null;
- foreach (var n in back.nodes)
- n.dual = null;
- }
- }
-
- public Context ctx;
-
- public class LogicSolver {
- public Context ctx;
- };
-
- public LogicSolver solver;
-
- static public LogicSolver CreateLogicSolver(Context _ctx){
- LogicSolver res = new LogicSolver();
- res.ctx = _ctx;
- return res;
- }
-
- /** This represents a conjecture that a given node is upper-boudned
- by bound. */
- public class Conjecture
- {
- public Node node;
- public Transformer bound;
- }
-
- /** This is a list of conjectures generated during solving. */
-
- public List<Conjecture> conjectures = new List<Conjecture>();
-
- /** Construct an RPFP graph with a given interpolating prover context. It is allowed to
- have multiple RPFP's use the same context, but you should never have teo RPFP's
- with the same conext asserting nodes or edges at the same time. Note, if you create
- axioms in one RPFP, them create a second RPFP with the same context, the second will
- inherit the axioms.
- */
-
- public RPFP(LogicSolver slvr)
- {
- solver = slvr;
- ctx = slvr.ctx;
- stack = new Stack<stack_entry>();
- stack.Push(new stack_entry());
- }
-
-
- /** Convert an array of clauses to an RPFP.
- */
-
- public void FromClauses(Term[] clauses){
- FuncDecl failName = ctx.MkFuncDecl("@Fail", ctx.MkBoolSort());
- foreach(var clause in clauses){
- Node foo = GetNodeFromClause(clause,failName);
- if(foo != null)
- nodes.Add(foo);
- }
- foreach (var clause in clauses)
- edges.Add(GetEdgeFromClause(clause,failName));
- }
-
-
- // This returns a new FuncDel with same sort as top-level function
- // of term t, but with numeric suffix appended to name.
-
- private FuncDecl SuffixFuncDecl(Term t, int n)
- {
- var name = t.GetAppDecl().GetDeclName() + "_" + n.ToString();
- return ctx.MkFuncDecl(name, t.GetAppDecl());
- }
-
- // Collect the relational paremeters
-
- Dictionary<FuncDecl, Node> relationToNode = new Dictionary<FuncDecl, Node>();
-
- private Term CollectParamsRec(TermDict<Term> memo, Term t, List<FuncDecl> parms, List<RPFP.Node> nodes, Dictionary<Term, Term> done)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- if (t.GetKind() == TermKind.App)
- {
- var f = t.GetAppDecl();
- Node node;
- if (relationToNode.TryGetValue(f, out node))
- {
- if (done.ContainsKey(t))
- res = done[t];
- else
- {
- f = SuffixFuncDecl(t, parms.Count);
- parms.Add(f);
- nodes.Add(node);
- done.Add(t,res); // don't count same expression twice!
- }
- }
- var args = t.GetAppArgs();
- args = args.Select(x => CollectParamsRec(memo, x, parms, nodes, done)).ToArray();
- res = ctx.CloneApp(t, args);
- } // TODO: handle quantifiers
- else
- res = t;
- memo.Add(t, res);
- return res;
- }
-
- private bool IsVariable(Term t)
- {
- // TODO: is this right?
- // return t.IsFunctionApp() && t.GetAppArgs().Length == 0;
- return t is VCExprVar && !(t is VCExprConstant);
- }
-
- private Edge GetEdgeFromClause(Term t, FuncDecl failName)
- {
- Term[] args = t.GetAppArgs();
- Term body = args[0];
- Term head = args[1];
- Term[] _IndParams;
- FuncDecl Name;
- if (head.IsFalse())
- {
- Name = failName;
- _IndParams = new Term[0];
- }
- else
- {
- _IndParams = head.GetAppArgs();
- Name = head.GetAppDecl();
- }
- for(int i = 0; i < _IndParams.Length; i++)
- if (!IsVariable(_IndParams[i]))
- {
- Term v = ctx.MkConst("@a" + i.ToString(), _IndParams[i].GetSort());
- body = ctx.MkAnd(body, ctx.MkEq(v, _IndParams[i]));
- _IndParams[i] = v;
- }
- var relParams = new List<FuncDecl>();
- var nodeParams = new List<RPFP.Node>();
- var memo = new TermDict< Term>();
- var done = new Dictionary<Term, Term>(); // note this hashes on equality, not reference!
- body = CollectParamsRec(memo, body, relParams, nodeParams,done);
- Transformer F = CreateTransformer(relParams.ToArray(), _IndParams, body);
- Node parent = relationToNode[Name];
- return CreateEdge(parent, F, nodeParams.ToArray());
- }
-
- private Node GetNodeFromClause(Term t, FuncDecl failName)
- {
- Term[] args = t.GetAppArgs();
- Term body = args[0];
- Term head = args[1];
- FuncDecl Name;
- Term[] _IndParams;
- bool is_query = false;
- if (head.Equals(ctx.MkFalse()))
- {
- Name = failName;
- is_query = true;
- _IndParams = new Term[0];
- }
- else
- {
- Name = head.GetAppDecl();
- _IndParams = head.GetAppArgs();
- }
- if (relationToNode.ContainsKey(Name))
- return null;
- for (int i = 0; i < _IndParams.Length; i++)
- if (!IsVariable(_IndParams[i]))
- {
- Term v = ctx.MkConst("@a" + i.ToString(), _IndParams[i].GetSort());
- _IndParams[i] = v;
- }
- Term foo = ctx.MkApp(Name, _IndParams);
- Node node = CreateNode(foo);
- relationToNode[Name] = node;
- if (is_query)
- node.Bound = CreateRelation(new Term[0], ctx.MkFalse());
- return node;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////////
- // Convert RPFP to Z3 rules
- /////////////////////////////////////////////////////////////////////////////////////////
-
- /** Get the Z3 rule corresponding to an edge */
-
- public Term GetRule(Edge edge)
- {
- Dictionary<FuncDecl, FuncDecl> predSubst = new Dictionary<FuncDecl, FuncDecl>();
- for (int i = 0; i < edge.Children.Length; i++)
- predSubst.Add(edge.F.RelParams[i], edge.Children[i].Name);
- Term body = SubstPreds(predSubst, edge.F.Formula);
- Term head = ctx.MkApp(edge.Parent.Name, edge.F.IndParams);
- var rule = BindVariables(ctx.MkImplies(body, head));
- rule = ctx.Letify(rule); // put in let bindings for theorem prover
- return rule;
- }
-
- /** Get the Z3 query corresponding to the conjunction of the node bounds. */
-
- public Term GetQuery()
- {
- List<Term> conjuncts = new List<Term>();
- foreach (var node in nodes)
- {
- if (node.Bound.Formula != ctx.MkTrue())
- conjuncts.Add(ctx.MkImplies(ctx.MkApp(node.Name, node.Bound.IndParams), node.Bound.Formula));
- }
- Term query = ctx.MkNot(ctx.MkAnd(conjuncts.ToArray()));
- query = BindVariables(query,false); // bind variables existentially
- query = ctx.Letify(query); // put in let bindings for theorem prover
- return query;
- }
-
- private void CollectVariables(TermDict< bool> memo, Term t, List<Term> vars)
- {
- if (memo.ContainsKey(t))
- return;
- if (IsVariable(t))
- vars.Add(t);
- if (t.GetKind() == TermKind.App)
- {
- foreach (var s in t.GetAppArgs())
- CollectVariables(memo, s, vars);
- }
- memo.Add(t, true);
- }
-
- private Term BindVariables(Term t, bool universal = true)
- {
- TermDict< bool> memo = new TermDict<bool>();
- List<Term> vars = new List<Term>();
- CollectVariables(memo,t,vars);
- return universal ? ctx.MkForall(vars.ToArray(), t) : ctx.MkExists(vars.ToArray(), t);
- }
-
- private Term SubstPredsRec(TermDict< Term> memo, Dictionary<FuncDecl,FuncDecl> subst, Term t)
- {
- Term res;
- if (memo.TryGetValue(t, out res))
- return res;
- if (t.GetKind() == TermKind.App)
- {
- var args = t.GetAppArgs();
- args = args.Select(x => SubstPredsRec(memo,subst,x)).ToArray();
- FuncDecl nf = null;
- var f = t.GetAppDecl();
- if (subst.TryGetValue(f, out nf))
- {
- res = ctx.MkApp(nf, args);
- }
- else
- {
- res = ctx.CloneApp(t, args);
- }
- } // TODO: handle quantifiers
- else
- res = t;
- memo.Add(t, res);
- return res;
- }
-
- private Term SubstPreds(Dictionary<FuncDecl, FuncDecl> subst, Term t)
- {
- TermDict< Term> memo = new TermDict< Term>();
- return SubstPredsRec(memo, subst, t);
- }
-
- /* Everything after here is private. */
-
- private class stack_entry
- {
- public List<Edge> edges = new List<Edge>();
- public List<Node> nodes = new List<Node>();
- };
-
- /** Set the model of the background theory used in a counterexample. */
- public void SetBackgroundModel(Model m)
- {
- dualModel = m;
- }
-
- /** Set the model of the background theory used in a counterexample. */
- public Model GetBackgroundModel()
- {
- return dualModel;
- }
-
- private int nodeCount = 0;
- private int edgeCount = 0;
- private Model dualModel;
- // private LabeledLiterals dualLabels;
- private Stack<stack_entry> stack;
- public List<Node> nodes = new List<Node>();
- public List<Edge> edges = new List<Edge>();
-
-
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) 2012 Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Term = Microsoft.Boogie.VCExprAST.VCExpr;
+using FuncDecl = Microsoft.Boogie.VCExprAST.VCExprOp;
+using Sort = Microsoft.Boogie.Type;
+using Microsoft.Boogie.VCExprAST;
+
+
+using Microsoft.Boogie.ExprExtensions;
+
+
+namespace Microsoft.Boogie
+{
+
+
+
+
+ /** This class represents a relation post-fixed point (RPFP) problem as
+ * a "problem graph". The graph consists of Nodes and hyper-edges.
+ *
+ * A node consists of
+ * - Annotation, a symbolic relation
+ * - Bound, a symbolic relation giving an upper bound on Annotation
+ *
+ *
+ * A hyper-edge consists of:
+ * - Children, a sequence of children Nodes,
+ * - F, a symbolic relational transformer,
+ * - Parent, a single parent Node.
+ *
+ * The graph is "solved" when:
+ * - For every Node n, n.Annotation subseteq n.Bound
+ * - For every hyperedge e, e.F(e.Children.Annotation) subseteq e.Parent.Annotation
+ *
+ * where, if x is a sequence of Nodes, x.Annotation is the sequences
+ * of Annotations of the nodes in the sequence.
+ *
+ * A symbolic Transformer consists of
+ * - RelParams, a sequence of relational symbols
+ * - IndParams, a sequence of individual symbols
+ * - Formula, a formula over RelParams and IndParams
+ *
+ * A Transformer t represents a function that takes sequence R of relations
+ * and yields the relation lambda (t.Indparams). Formula(R/RelParams).
+ *
+ * As a special case, a nullary Transformer (where RelParams is the empty sequence)
+ * represents a fixed relation.
+ *
+ * An RPFP consists of
+ * - Nodes, a set of Nodes
+ * - Edges, a set of hyper-edges
+ * - Context, a prover context that contains formula AST's
+ *
+ * Multiple RPFP's can use the same Context, but you should be careful
+ * that only one RPFP asserts constraints in the context at any time.
+ *
+ * */
+ public class RPFP
+ {
+ /** Symbolic representation of a relational transformer */
+ public class Transformer
+ {
+ public FuncDecl[] RelParams;
+ public Term[] IndParams;
+ public Term Formula;
+ public RPFP owner;
+
+ public Transformer Clone()
+ {
+ return (Transformer)this.MemberwiseClone();
+ }
+ }
+
+ /** Create a symbolic transformer. */
+ public Transformer CreateTransformer(FuncDecl[] _RelParams, Term[] _IndParams, Term _Formula)
+ {
+ Transformer t = new Transformer();
+ t.RelParams = _RelParams;
+ t.IndParams = _IndParams;
+ t.Formula = _Formula;
+ t.owner = this;
+ return t;
+ }
+
+ /** Create a relation (nullary relational transformer) */
+ public Transformer CreateRelation(Term[] _IndParams, Term _Formula)
+ {
+ return CreateTransformer(new FuncDecl[0], _IndParams, _Formula);
+ }
+
+ /** A node in the RPFP graph */
+ public class Node
+ {
+ public FuncDecl Name;
+ public Transformer Annotation;
+ public Transformer Bound;
+ public RPFP owner;
+ public int number;
+ public Edge Outgoing;
+ public List<Edge> Incoming;
+ public Term dual;
+ public Node map;
+ }
+
+ /** Create a node in the graph. The input is a term R(v_1...v_n)
+ * where R is an arbitrary relational symbol and v_1...v_n are
+ * arbitary distinct variables. The names are only of mnemonic value,
+ * however, the number and type of arguments determine the type
+ * of the relation at this node. */
+
+ public Node CreateNode(Term t)
+ {
+ Node n = new Node();
+ // Microsoft.Boogie.VCExprAST.VCExprNAry tn = t as Microsoft.Boogie.VCExprAST.VCExprNAry;
+ // Term[] _IndParams = tn.ToArray();
+ Term[] _IndParams = t.GetAppArgs();
+ FuncDecl Name = t.GetAppDecl();
+ n.Annotation = CreateRelation(_IndParams,ctx.MkTrue());
+ n.Bound = CreateRelation(_IndParams, ctx.MkTrue());
+ n.owner = this;
+ n.number = ++nodeCount;
+ n.Name = Name; // just to have a unique name
+ n.Incoming = new List<Edge>();
+ return n;
+ }
+
+ /** Clone a node (can be from another graph). */
+
+ public Node CloneNode(Node old)
+ {
+ Node n = new Node();
+ n.Annotation = old.Annotation.Clone();
+ n.Bound = old.Bound.Clone();
+ n.owner = this;
+ n.number = ++nodeCount;
+ n.Name = old.Name; // just to have a unique name
+ n.Incoming = new List<Edge>();
+ return n;
+ }
+
+ /** This class represents a hyper-edge in the RPFP graph */
+
+ public class Edge
+ {
+ public Transformer F;
+ public Node Parent;
+ public Node[] Children;
+ public RPFP owner;
+ public int number;
+ public Edge map;
+ public HashSet<string> labels;
+ internal Term dual;
+ internal TermDict<Term> valuation;
+ }
+
+
+ /** Create a hyper-edge. */
+ public Edge CreateEdge(Node _Parent, Transformer _F, Node[] _Children)
+ {
+ Edge e = new Edge();
+ e.Parent = _Parent;
+ e.F = _F;
+ e.Children = _Children;
+ e.owner = this;
+ e.number = ++edgeCount;
+ _Parent.Outgoing = e;
+ foreach (var c in _Children)
+ if(c != null)
+ c.Incoming.Add(e);
+ return e;
+ }
+
+ /** Create an edge that lower-bounds its parent. */
+ public Edge CreateLowerBoundEdge(Node _Parent)
+ {
+ return CreateEdge(_Parent, _Parent.Annotation, new RPFP.Node[0]);
+ }
+
+
+
+
+ /** Assert a background axiom. Background axioms can be used to provide the
+ * theory of auxilliary functions or relations. All symbols appearing in
+ * background axioms are considered global, and may appear in both transformer
+ * and relational solutions. Semantically, a solution to the RPFP gives
+ * an interpretation of the unknown relations for each interpretation of the
+ * auxilliary symbols that is consistent with the axioms. Axioms should be
+ * asserted before any calls to Push. They cannot be de-asserted by Pop. */
+
+ public void AssertAxiom(Term t)
+ {
+ ctx.AddAxiom(t);
+ }
+
+ /** Do not call this. */
+
+ public void RemoveAxiom(Term t)
+ {
+ ctx.RemoveAxiom(t);
+ }
+
+ /** Type of solve results */
+ public enum LBool { False, True, Undef };
+
+
+ /** Solve an RPFP graph. This means either strengthen the annotation
+ * so that the bound at the given root node is satisfied, or
+ * show that this cannot be done by giving a dual solution
+ * (i.e., a counterexample).
+ *
+ * In the current implementation, this only works for graphs that
+ * are:
+ * - tree-like
+ *
+ * - closed.
+ *
+ * In a tree-like graph, every nod has out most one incoming and one out-going edge,
+ * and there are no cycles. In a closed graph, every node has exactly one out-going
+ * edge. This means that the leaves of the tree are all hyper-edges with no
+ * children. Such an edge represents a relation (nullary transformer) and thus
+ * a lower bound on its parent. The parameter root must be the root of this tree.
+ *
+ * If Solve returns LBool.False, this indicates success. The annotation of the tree
+ * has been updated to satisfy the upper bound at the root.
+ *
+ * If Solve returns LBool.True, this indicates a counterexample. For each edge,
+ * you can then call Eval to determine the values of symbols in the transformer formula.
+ * You can also call Empty on a node to determine if its value in the counterexample
+ * is the empty relation.
+ *
+ * \param root The root of the tree
+ * \param persist Number of context pops through which result should persist
+ *
+ *
+ */
+
+ public LBool Solve(Node root, int persist)
+ {
+ return LBool.False; // TODO
+ }
+
+
+ /** Dispose of the dual model (counterexample) if there is one. */
+
+ public void DisposeDualModel()
+ {
+ // TODO dualModel = null;
+ }
+
+
+ /** Determines the value in the counterexample of a symbol occuring in the transformer formula of
+ * a given edge. */
+
+ public Term Eval(Edge e, Term t)
+ {
+ if (e.valuation == null)
+ e.valuation = new TermDict< Term>();
+ if (e.valuation.ContainsKey(t))
+ return e.valuation[t];
+ return null; // TODO
+ }
+
+ /** Sets the value in the counterexample of a symbol occuring in the transformer formula of
+ * a given edge. */
+
+ public void SetValue(Edge e, Term variable, Term value)
+ {
+ if (e.valuation == null)
+ e.valuation = new TermDict< Term>();
+ e.valuation.Add(variable, value);
+ }
+
+
+ /** Returns true if the given node is empty in the primal solution. For proecudure summaries,
+ this means that the procedure is not called in the current counter-model. */
+
+ public bool Empty(Node p)
+ {
+ return false; // TODO
+ }
+
+ /** Push a scope. Assertions made after Push can be undone by Pop. */
+
+ public void Push()
+ {
+ stack.Push(new stack_entry());
+ // TODO: do we need push/pop?
+ }
+
+ /** Pop a scope (see Push). Note, you cannot pop axioms. */
+
+ public void Pop(int num_scopes)
+ {
+ //TODO ctx.Pop((uint)num_scopes);
+ for (uint i = 0; i < num_scopes; i++)
+ {
+ stack_entry back = stack.Pop();
+ foreach (var e in back.edges)
+ e.dual = null;
+ foreach (var n in back.nodes)
+ n.dual = null;
+ }
+ }
+
+ public Context ctx;
+
+ public class LogicSolver {
+ public Context ctx;
+ };
+
+ public LogicSolver solver;
+
+ static public LogicSolver CreateLogicSolver(Context _ctx){
+ LogicSolver res = new LogicSolver();
+ res.ctx = _ctx;
+ return res;
+ }
+
+ /** This represents a conjecture that a given node is upper-boudned
+ by bound. */
+ public class Conjecture
+ {
+ public Node node;
+ public Transformer bound;
+ }
+
+ /** This is a list of conjectures generated during solving. */
+
+ public List<Conjecture> conjectures = new List<Conjecture>();
+
+ /** Construct an RPFP graph with a given interpolating prover context. It is allowed to
+ have multiple RPFP's use the same context, but you should never have teo RPFP's
+ with the same conext asserting nodes or edges at the same time. Note, if you create
+ axioms in one RPFP, them create a second RPFP with the same context, the second will
+ inherit the axioms.
+ */
+
+ public RPFP(LogicSolver slvr)
+ {
+ solver = slvr;
+ ctx = slvr.ctx;
+ stack = new Stack<stack_entry>();
+ stack.Push(new stack_entry());
+ }
+
+
+ /** Convert an array of clauses to an RPFP.
+ */
+
+ public void FromClauses(Term[] clauses){
+ FuncDecl failName = ctx.MkFuncDecl("@Fail", ctx.MkBoolSort());
+ foreach(var clause in clauses){
+ Node foo = GetNodeFromClause(clause,failName);
+ if(foo != null)
+ nodes.Add(foo);
+ }
+ foreach (var clause in clauses)
+ edges.Add(GetEdgeFromClause(clause,failName));
+ }
+
+
+ // This returns a new FuncDel with same sort as top-level function
+ // of term t, but with numeric suffix appended to name.
+
+ private FuncDecl SuffixFuncDecl(Term t, int n)
+ {
+ var name = t.GetAppDecl().GetDeclName() + "_" + n.ToString();
+ return ctx.MkFuncDecl(name, t.GetAppDecl());
+ }
+
+ // Collect the relational paremeters
+
+ Dictionary<FuncDecl, Node> relationToNode = new Dictionary<FuncDecl, Node>();
+
+ private Term CollectParamsRec(TermDict<Term> memo, Term t, List<FuncDecl> parms, List<RPFP.Node> nodes, Dictionary<Term, Term> done)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ if (t.GetKind() == TermKind.App)
+ {
+ var f = t.GetAppDecl();
+ Node node;
+ if (relationToNode.TryGetValue(f, out node))
+ {
+ if (done.ContainsKey(t))
+ res = done[t];
+ else
+ {
+ f = SuffixFuncDecl(t, parms.Count);
+ parms.Add(f);
+ nodes.Add(node);
+ done.Add(t,res); // don't count same expression twice!
+ }
+ }
+ var args = t.GetAppArgs();
+ args = args.Select(x => CollectParamsRec(memo, x, parms, nodes, done)).ToArray();
+ res = ctx.CloneApp(t, args);
+ } // TODO: handle quantifiers
+ else
+ res = t;
+ memo.Add(t, res);
+ return res;
+ }
+
+ private bool IsVariable(Term t)
+ {
+ // TODO: is this right?
+ // return t.IsFunctionApp() && t.GetAppArgs().Length == 0;
+ return t is VCExprVar && !(t is VCExprConstant);
+ }
+
+ private Edge GetEdgeFromClause(Term t, FuncDecl failName)
+ {
+ Term[] args = t.GetAppArgs();
+ Term body = args[0];
+ Term head = args[1];
+ Term[] _IndParams;
+ FuncDecl Name;
+ if (head.IsFalse())
+ {
+ Name = failName;
+ _IndParams = new Term[0];
+ }
+ else
+ {
+ _IndParams = head.GetAppArgs();
+ Name = head.GetAppDecl();
+ }
+ for(int i = 0; i < _IndParams.Length; i++)
+ if (!IsVariable(_IndParams[i]))
+ {
+ Term v = ctx.MkConst("@a" + i.ToString(), _IndParams[i].GetSort());
+ body = ctx.MkAnd(body, ctx.MkEq(v, _IndParams[i]));
+ _IndParams[i] = v;
+ }
+ var relParams = new List<FuncDecl>();
+ var nodeParams = new List<RPFP.Node>();
+ var memo = new TermDict< Term>();
+ var done = new Dictionary<Term, Term>(); // note this hashes on equality, not reference!
+ body = CollectParamsRec(memo, body, relParams, nodeParams,done);
+ Transformer F = CreateTransformer(relParams.ToArray(), _IndParams, body);
+ Node parent = relationToNode[Name];
+ return CreateEdge(parent, F, nodeParams.ToArray());
+ }
+
+ private Node GetNodeFromClause(Term t, FuncDecl failName)
+ {
+ Term[] args = t.GetAppArgs();
+ Term body = args[0];
+ Term head = args[1];
+ FuncDecl Name;
+ Term[] _IndParams;
+ bool is_query = false;
+ if (head.Equals(ctx.MkFalse()))
+ {
+ Name = failName;
+ is_query = true;
+ _IndParams = new Term[0];
+ }
+ else
+ {
+ Name = head.GetAppDecl();
+ _IndParams = head.GetAppArgs();
+ }
+ if (relationToNode.ContainsKey(Name))
+ return null;
+ for (int i = 0; i < _IndParams.Length; i++)
+ if (!IsVariable(_IndParams[i]))
+ {
+ Term v = ctx.MkConst("@a" + i.ToString(), _IndParams[i].GetSort());
+ _IndParams[i] = v;
+ }
+ Term foo = ctx.MkApp(Name, _IndParams);
+ Node node = CreateNode(foo);
+ relationToNode[Name] = node;
+ if (is_query)
+ node.Bound = CreateRelation(new Term[0], ctx.MkFalse());
+ return node;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Convert RPFP to Z3 rules
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ /** Get the Z3 rule corresponding to an edge */
+
+ public Term GetRule(Edge edge)
+ {
+ Dictionary<FuncDecl, FuncDecl> predSubst = new Dictionary<FuncDecl, FuncDecl>();
+ for (int i = 0; i < edge.Children.Length; i++)
+ predSubst.Add(edge.F.RelParams[i], edge.Children[i].Name);
+ Term body = SubstPreds(predSubst, edge.F.Formula);
+ Term head = ctx.MkApp(edge.Parent.Name, edge.F.IndParams);
+ var rule = BindVariables(ctx.MkImplies(body, head));
+ rule = ctx.Letify(rule); // put in let bindings for theorem prover
+ return rule;
+ }
+
+ /** Get the Z3 query corresponding to the conjunction of the node bounds. */
+
+ public Term GetQuery()
+ {
+ List<Term> conjuncts = new List<Term>();
+ foreach (var node in nodes)
+ {
+ if (node.Bound.Formula != ctx.MkTrue())
+ conjuncts.Add(ctx.MkImplies(ctx.MkApp(node.Name, node.Bound.IndParams), node.Bound.Formula));
+ }
+ Term query = ctx.MkNot(ctx.MkAnd(conjuncts.ToArray()));
+ query = BindVariables(query,false); // bind variables existentially
+ query = ctx.Letify(query); // put in let bindings for theorem prover
+ return query;
+ }
+
+ private void CollectVariables(TermDict< bool> memo, Term t, List<Term> vars)
+ {
+ if (memo.ContainsKey(t))
+ return;
+ if (IsVariable(t))
+ vars.Add(t);
+ if (t.GetKind() == TermKind.App)
+ {
+ foreach (var s in t.GetAppArgs())
+ CollectVariables(memo, s, vars);
+ }
+ memo.Add(t, true);
+ }
+
+ private Term BindVariables(Term t, bool universal = true)
+ {
+ TermDict< bool> memo = new TermDict<bool>();
+ List<Term> vars = new List<Term>();
+ CollectVariables(memo,t,vars);
+ return universal ? ctx.MkForall(vars.ToArray(), t) : ctx.MkExists(vars.ToArray(), t);
+ }
+
+ private Term SubstPredsRec(TermDict< Term> memo, Dictionary<FuncDecl,FuncDecl> subst, Term t)
+ {
+ Term res;
+ if (memo.TryGetValue(t, out res))
+ return res;
+ if (t.GetKind() == TermKind.App)
+ {
+ var args = t.GetAppArgs();
+ args = args.Select(x => SubstPredsRec(memo,subst,x)).ToArray();
+ FuncDecl nf = null;
+ var f = t.GetAppDecl();
+ if (subst.TryGetValue(f, out nf))
+ {
+ res = ctx.MkApp(nf, args);
+ }
+ else
+ {
+ res = ctx.CloneApp(t, args);
+ }
+ } // TODO: handle quantifiers
+ else
+ res = t;
+ memo.Add(t, res);
+ return res;
+ }
+
+ private Term SubstPreds(Dictionary<FuncDecl, FuncDecl> subst, Term t)
+ {
+ TermDict< Term> memo = new TermDict< Term>();
+ return SubstPredsRec(memo, subst, t);
+ }
+
+ /* Everything after here is private. */
+
+ private class stack_entry
+ {
+ public List<Edge> edges = new List<Edge>();
+ public List<Node> nodes = new List<Node>();
+ };
+
+ /** Set the model of the background theory used in a counterexample. */
+ public void SetBackgroundModel(Model m)
+ {
+ dualModel = m;
+ }
+
+ /** Set the model of the background theory used in a counterexample. */
+ public Model GetBackgroundModel()
+ {
+ return dualModel;
+ }
+
+ private int nodeCount = 0;
+ private int edgeCount = 0;
+ private Model dualModel;
+ // private LabeledLiterals dualLabels;
+ private Stack<stack_entry> stack;
+ public List<Node> nodes = new List<Node>();
+ public List<Edge> edges = new List<Edge>();
+
+
+ }
+}
diff --git a/Source/VCGeneration/StratifiedVC.cs b/Source/VCGeneration/StratifiedVC.cs
index 6f8d3668..789f86f5 100644
--- a/Source/VCGeneration/StratifiedVC.cs
+++ b/Source/VCGeneration/StratifiedVC.cs
@@ -1,2914 +1,2906 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC {
- using Bpl = Microsoft.Boogie;
-
- public class StratifiedVC {
- public StratifiedInliningInfo info;
- public int id;
- public List<VCExprVar> interfaceExprVars;
-
- // boolControlVC (block -> its bool variable)
- public Dictionary<Block, VCExpr> blockToControlVar;
- // While using labels (block -> its label)
- public Dictionary<Absy, string> block2label;
-
- public Dictionary<Block, List<StratifiedCallSite>> callSites;
- public Dictionary<Block, List<StratifiedCallSite>> recordProcCallSites;
- public VCExpr vcexpr;
-
- // Must-Reach Information
- Dictionary<Block, VCExprVar> mustReachVar;
- List<VCExprLetBinding> mustReachBindings;
-
- public StratifiedVC(StratifiedInliningInfo siInfo, HashSet<string> procCalls) {
- info = siInfo;
- info.GenerateVC();
- var vcgen = info.vcgen;
- var prover = vcgen.prover;
- VCExpressionGenerator gen = prover.VCExprGen;
- var bet = prover.Context.BoogieExprTranslator;
-
- vcexpr = info.vcexpr;
- id = vcgen.CreateNewId();
- interfaceExprVars = new List<VCExprVar>();
- Dictionary<VCExprVar, VCExpr> substDict = new Dictionary<VCExprVar, VCExpr>();
- foreach (VCExprVar v in info.interfaceExprVars) {
- VCExprVar newVar = vcgen.CreateNewVar(v.Type);
- interfaceExprVars.Add(newVar);
- substDict.Add(v, newVar);
- }
- foreach (VCExprVar v in info.privateExprVars) {
- substDict.Add(v, vcgen.CreateNewVar(v.Type));
- }
- if(info.controlFlowVariable != null)
- substDict.Add(bet.LookupVariable(info.controlFlowVariable), gen.Integer(BigNum.FromInt(id)));
- VCExprSubstitution subst = new VCExprSubstitution(substDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
- SubstitutingVCExprVisitor substVisitor = new SubstitutingVCExprVisitor(prover.VCExprGen);
- vcexpr = substVisitor.Mutate(vcexpr, subst);
-
- // For BoolControlVC generation
- if (info.blockToControlVar != null)
- {
- blockToControlVar = new Dictionary<Block, VCExpr>();
- foreach (var tup in info.blockToControlVar)
- blockToControlVar.Add(tup.Key, substDict[tup.Value]);
- }
-
- // labels
- if (info.label2absy != null)
- {
- block2label = new Dictionary<Absy, string>();
- vcexpr = RenameVCExprLabels.Apply(vcexpr, info.vcgen.prover.VCExprGen, info.label2absy, block2label);
- }
-
- if(procCalls != null)
- vcexpr = RemoveProcedureCalls.Apply(vcexpr, info.vcgen.prover.VCExprGen, procCalls);
-
- callSites = new Dictionary<Block, List<StratifiedCallSite>>();
- foreach (Block b in info.callSites.Keys) {
- callSites[b] = new List<StratifiedCallSite>();
- foreach (CallSite cs in info.callSites[b]) {
- callSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst));
- }
- }
-
- recordProcCallSites = new Dictionary<Block, List<StratifiedCallSite>>();
- foreach (Block b in info.recordProcCallSites.Keys) {
- recordProcCallSites[b] = new List<StratifiedCallSite>();
- foreach (CallSite cs in info.recordProcCallSites[b]) {
- recordProcCallSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst));
- }
- }
- }
-
- public VCExpr MustReach(Block block)
- {
- Contract.Assert(!CommandLineOptions.Clo.UseLabels);
-
- // This information is computed lazily
- if (mustReachBindings == null)
- {
- var vcgen = info.vcgen;
- var gen = vcgen.prover.VCExprGen;
- var impl = info.impl;
- mustReachVar = new Dictionary<Block, VCExprVar>();
- mustReachBindings = new List<VCExprLetBinding>();
- foreach (Block b in impl.Blocks)
- mustReachVar[b] = vcgen.CreateNewVar(Bpl.Type.Bool);
-
- var dag = new Graph<Block>();
- dag.AddSource(impl.Blocks[0]);
- foreach (Block b in impl.Blocks)
- {
- var gtc = b.TransferCmd as GotoCmd;
- if (gtc != null)
- foreach (Block dest in gtc.labelTargets)
- dag.AddEdge(dest, b);
- }
- IEnumerable sortedNodes = dag.TopologicalSort();
-
- foreach (Block currBlock in dag.TopologicalSort())
- {
- if (currBlock == impl.Blocks[0])
- {
- mustReachBindings.Add(gen.LetBinding(mustReachVar[currBlock], VCExpressionGenerator.True));
- continue;
- }
-
- VCExpr expr = VCExpressionGenerator.False;
- foreach (var pred in dag.Successors(currBlock))
- {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(gen.Integer(BigNum.FromInt(id)), gen.Integer(BigNum.FromInt(pred.UniqueId)));
- VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(currBlock.UniqueId)));
- expr = gen.Or(expr, gen.And(mustReachVar[pred], controlTransferExpr));
- }
- mustReachBindings.Add(gen.LetBinding(mustReachVar[currBlock], expr));
- }
- }
-
- Contract.Assert(mustReachVar.ContainsKey(block));
- return info.vcgen.prover.VCExprGen.Let(mustReachBindings, mustReachVar[block]);
- }
-
- public List<StratifiedCallSite> CallSites {
- get {
- var ret = new List<StratifiedCallSite>();
- foreach (var b in callSites.Keys) {
- foreach (var cs in callSites[b]) {
- ret.Add(cs);
- }
- }
- return ret;
- }
- }
-
- public List<StratifiedCallSite> RecordProcCallSites {
- get {
- var ret = new List<StratifiedCallSite>();
- foreach (var b in recordProcCallSites.Keys) {
- foreach (var cs in recordProcCallSites[b]) {
- ret.Add(cs);
- }
- }
- return ret;
- }
- }
-
- public override string ToString()
- {
- return info.impl.Name;
- }
- }
-
- // Rename all labels in a VC to (globally) fresh labels
- class RenameVCExprLabels : MutatingVCExprVisitor<bool>
- {
- Dictionary<int, Absy> label2absy;
- Dictionary<Absy, string> absy2newlabel;
- static int counter = 11;
-
- RenameVCExprLabels(VCExpressionGenerator gen, Dictionary<int, Absy> label2absy, Dictionary<Absy, string> absy2newlabel)
- : base(gen)
- {
- this.label2absy = label2absy;
- this.absy2newlabel = absy2newlabel;
- }
-
- public static VCExpr Apply(VCExpr expr, VCExpressionGenerator gen, Dictionary<int, Absy> label2absy, Dictionary<Absy, string> absy2newlabel)
- {
- return (new RenameVCExprLabels(gen, label2absy, absy2newlabel)).Mutate(expr, true);
- }
-
- // Finds labels and changes them to a globally unique label:
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
- List<VCExpr/*!*/>/*!*/ newSubExprs,
- bool changed,
- bool arg)
- {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr ret;
- if (changed)
- ret = Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- ret = originalNode;
-
- VCExprLabelOp lop = originalNode.Op as VCExprLabelOp;
- if (lop == null) return ret;
- if (!(ret is VCExprNAry)) return ret;
- VCExprNAry retnary = (VCExprNAry)ret;
-
- // remove the sign
- var nosign = 0;
- if (!Int32.TryParse(lop.label.Substring(1), out nosign))
- return ret;
-
- if (!label2absy.ContainsKey(nosign))
- return ret;
-
- string newLabel = "SI" + counter.ToString();
- counter++;
- absy2newlabel[label2absy[nosign]] = newLabel;
-
- if (lop.pos)
- {
- return Gen.LabelPos(newLabel, retnary[0]);
- }
- else
- {
- return Gen.LabelNeg(newLabel, retnary[0]);
- }
-
- }
- }
-
- // Remove the uninterpreted function calls that substitute procedure calls
- class RemoveProcedureCalls : MutatingVCExprVisitor<bool>
- {
- HashSet<string> procNames;
-
- RemoveProcedureCalls(VCExpressionGenerator gen, HashSet<string> procNames)
- : base(gen)
- {
- this.procNames = procNames;
- }
-
- public static VCExpr Apply(VCExpr expr, VCExpressionGenerator gen, HashSet<string> procNames)
- {
- return (new RemoveProcedureCalls(gen, procNames)).Mutate(expr, true);
- }
-
- // Finds labels and changes them to a globally unique label:
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
- List<VCExpr/*!*/>/*!*/ newSubExprs,
- bool changed,
- bool arg)
- {
- //Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr ret;
- if (changed)
- ret = Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- ret = originalNode;
-
- if (!(ret is VCExprNAry)) return ret;
- VCExprNAry retnary = (VCExprNAry)ret;
- if (!(retnary.Op is VCExprBoogieFunctionOp))
- return ret;
-
- var fcall = (retnary.Op as VCExprBoogieFunctionOp).Func.Name;
- if (procNames.Contains(fcall))
- return VCExpressionGenerator.True;
- return ret;
- }
- }
-
-
- public class CallSite {
- public string calleeName;
- public List<VCExpr> interfaceExprs;
- public Block block;
- public int numInstr; // for TraceLocation
- public VCExprVar callSiteVar;
- public QKeyValue Attributes; // attributes on the call cmd
- public CallSite(string callee, List<VCExpr> interfaceExprs, VCExprVar callSiteVar, Block block, int numInstr, QKeyValue Attributes)
- {
- this.calleeName = callee;
- this.interfaceExprs = interfaceExprs;
- this.callSiteVar = callSiteVar;
- this.block = block;
- this.numInstr = numInstr;
- this.Attributes = Attributes;
- }
- }
-
- public class StratifiedCallSite {
- public CallSite callSite;
- public List<VCExpr> interfaceExprs;
- public VCExpr callSiteExpr;
-
- public StratifiedCallSite(CallSite cs, SubstitutingVCExprVisitor substVisitor, VCExprSubstitution subst) {
- callSite = cs;
- interfaceExprs = new List<VCExpr>();
- foreach (VCExpr v in cs.interfaceExprs) {
- interfaceExprs.Add(substVisitor.Mutate(v, subst));
- }
- if (callSite.callSiteVar != null)
- callSiteExpr = substVisitor.Mutate(callSite.callSiteVar, subst);
- }
-
- public VCExpr Attach(StratifiedVC svc) {
- Contract.Assert(interfaceExprs.Count == svc.interfaceExprVars.Count);
- StratifiedInliningInfo info = svc.info;
- ProverInterface prover = info.vcgen.prover;
- VCExpressionGenerator gen = prover.VCExprGen;
-
- Dictionary<VCExprVar, VCExpr> substDict = new Dictionary<VCExprVar, VCExpr>();
- for (int i = 0; i < svc.interfaceExprVars.Count; i++) {
- VCExprVar v = svc.interfaceExprVars[i];
- substDict.Add(v, interfaceExprs[i]);
- }
- VCExprSubstitution subst = new VCExprSubstitution(substDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
- SubstitutingVCExprVisitor substVisitor = new SubstitutingVCExprVisitor(prover.VCExprGen);
- svc.vcexpr = substVisitor.Mutate(svc.vcexpr, subst);
- foreach (StratifiedCallSite scs in svc.CallSites) {
- List<VCExpr> newInterfaceExprs = new List<VCExpr>();
- foreach (VCExpr expr in scs.interfaceExprs) {
- newInterfaceExprs.Add(substVisitor.Mutate(expr, subst));
- }
- scs.interfaceExprs = newInterfaceExprs;
- }
- foreach (StratifiedCallSite scs in svc.RecordProcCallSites) {
- List<VCExpr> newInterfaceExprs = new List<VCExpr>();
- foreach (VCExpr expr in scs.interfaceExprs) {
- newInterfaceExprs.Add(substVisitor.Mutate(expr, subst));
- }
- scs.interfaceExprs = newInterfaceExprs;
- }
- //return gen.Implies(callSiteExpr, svc.vcexpr);
- return svc.vcexpr;
- }
-
- public override string ToString()
- {
- return callSite.calleeName;
- }
- }
-
- public class StratifiedInliningInfo {
- public StratifiedVCGenBase vcgen;
- public Implementation impl;
- public Function function;
- public Variable controlFlowVariable;
- public Cmd exitAssertCmd;
- public VCExpr vcexpr;
- public List<VCExprVar> interfaceExprVars;
- public List<VCExprVar> privateExprVars;
- public Dictionary<int, Absy> label2absy;
- public ModelViewInfo mvInfo;
- public Dictionary<Block, List<CallSite>> callSites;
- public Dictionary<Block, List<CallSite>> recordProcCallSites;
- public bool initialized { get; private set; }
-
- // boolControlVC (block -> its Bool variable)
- public Dictionary<Block, VCExprVar> blockToControlVar;
-
- public StratifiedInliningInfo(Implementation implementation, StratifiedVCGenBase stratifiedVcGen) {
- vcgen = stratifiedVcGen;
- impl = implementation;
-
- List<Variable> functionInterfaceVars = new List<Variable>();
- foreach (Variable v in vcgen.program.GlobalVariables) {
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
- }
- foreach (Variable v in impl.InParams) {
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
- }
- foreach (Variable v in impl.OutParams) {
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
- }
- foreach (IdentifierExpr e in impl.Proc.Modifies) {
- if (e.Decl == null) continue;
- functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", e.Decl.TypedIdent.Type), true));
- }
- Formal returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false);
- function = new Function(Token.NoToken, impl.Name, functionInterfaceVars, returnVar);
- vcgen.prover.Context.DeclareFunction(function, "");
-
- List<Expr> exprs = new List<Expr>();
- foreach (Variable v in vcgen.program.GlobalVariables) {
- Contract.Assert(v != null);
- exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
- }
- foreach (Variable v in impl.Proc.InParams) {
- Contract.Assert(v != null);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- foreach (Variable v in impl.Proc.OutParams) {
- Contract.Assert(v != null);
- exprs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- foreach (IdentifierExpr ie in impl.Proc.Modifies) {
- Contract.Assert(ie != null);
- if (ie.Decl == null)
- continue;
- exprs.Add(ie);
- }
- Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
- impl.Proc.Ensures.Add(new Ensures(Token.NoToken, true, freePostExpr, "", new QKeyValue(Token.NoToken, "si_fcall", new List<object>(), null)));
-
- initialized = false;
- }
-
- public void GenerateVCBoolControl()
- {
- Debug.Assert(!initialized);
- Debug.Assert(CommandLineOptions.Clo.SIBoolControlVC);
-
- // fix names for exit variables
- var outputVariables = new List<Variable>();
- var assertConjuncts = new List<Expr>();
- foreach (Variable v in impl.OutParams)
- {
- Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
- outputVariables.Add(c);
- Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
- assertConjuncts.Add(eqExpr);
- }
- foreach (IdentifierExpr e in impl.Proc.Modifies)
- {
- if (e.Decl == null) continue;
- Variable v = e.Decl;
- Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
- outputVariables.Add(c);
- Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
- assertConjuncts.Add(eqExpr);
- }
- exitAssertCmd = new AssumeCmd(Token.NoToken, Expr.BinaryTreeAnd(assertConjuncts));
- (exitAssertCmd as AssumeCmd).Attributes = new QKeyValue(Token.NoToken, "exitAssert", new List<object>(), null);
-
- // no need for label2absy
- label2absy = new Dictionary<int, Absy>();
-
- // Passify
- Program program = vcgen.program;
- ProverInterface proverInterface = vcgen.prover;
- vcgen.ConvertCFG2DAG(impl);
- vcgen.PassifyImpl(impl, out mvInfo);
-
- VCExpressionGenerator gen = proverInterface.VCExprGen;
- var exprGen = proverInterface.Context.ExprGen;
- var translator = proverInterface.Context.BoogieExprTranslator;
-
- // add a boolean variable at each call site
- vcgen.InstrumentCallSites(impl);
-
- // typecheck
- var tc = new TypecheckingContext(null);
- impl.Typecheck(tc);
-
- ///////////////////
- // Generate the VC
- ///////////////////
-
- // block -> bool variable
- blockToControlVar = new Dictionary<Block, VCExprVar>();
- foreach (var b in impl.Blocks)
- blockToControlVar.Add(b, gen.Variable(b.Label + "_holds", Bpl.Type.Bool));
-
- vcexpr = VCExpressionGenerator.True;
- foreach (var b in impl.Blocks)
- {
- // conjoin all assume cmds
- VCExpr c = VCExpressionGenerator.True;
- foreach (var cmd in b.Cmds)
- {
- var acmd = cmd as AssumeCmd;
- if (acmd == null)
- {
- Debug.Assert(cmd is AssertCmd && (cmd as AssertCmd).Expr is LiteralExpr &&
- ((cmd as AssertCmd).Expr as LiteralExpr).IsTrue);
- continue;
- }
- var expr = translator.Translate(acmd.Expr);
- // Label the assume if it is a procedure call
- NAryExpr naryExpr = acmd.Expr as NAryExpr;
- if (naryExpr != null && naryExpr.Fun is FunctionCall)
- {
- var id = acmd.UniqueId;
- label2absy[id] = acmd;
- expr = gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), expr);
- }
-
- c = gen.AndSimp(c, expr);
- }
-
- // block implies a disjunction of successors
- Debug.Assert(!(b.TransferCmd is ReturnExprCmd), "Not supported");
- var gc = b.TransferCmd as GotoCmd;
- if (gc != null)
- {
- VCExpr succ = VCExpressionGenerator.False;
- foreach (var sb in gc.labelTargets)
- succ = gen.OrSimp(succ, blockToControlVar[sb]);
- c = gen.AndSimp(c, succ);
- }
- else
- {
- // nothing to do
- }
- vcexpr = gen.AndSimp(vcexpr, gen.Eq(blockToControlVar[b], c));
- }
- // assert start block
- vcexpr = gen.AndSimp(vcexpr, blockToControlVar[impl.Blocks[0]]);
-
- //Console.WriteLine("VC of {0}: {1}", impl.Name, vcexpr);
- // Collect other information
- callSites = vcgen.CollectCallSites(impl);
- recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl);
-
- // record interface variables
- privateExprVars = new List<VCExprVar>();
- foreach (Variable v in impl.LocVars)
- {
- privateExprVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in impl.OutParams)
- {
- privateExprVars.Add(translator.LookupVariable(v));
- }
- privateExprVars.AddRange(blockToControlVar.Values);
-
- interfaceExprVars = new List<VCExprVar>();
- foreach (Variable v in program.GlobalVariables)
- {
- interfaceExprVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in impl.InParams)
- {
- interfaceExprVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in outputVariables)
- {
- interfaceExprVars.Add(translator.LookupVariable(v));
- }
- }
-
- public void GenerateVC() {
- if (initialized) return;
- if (CommandLineOptions.Clo.SIBoolControlVC)
- {
- GenerateVCBoolControl();
- initialized = true;
- return;
- }
- List<Variable> outputVariables = new List<Variable>();
- List<Expr> assertConjuncts = new List<Expr>();
- foreach (Variable v in impl.OutParams) {
- Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
- outputVariables.Add(c);
- Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
- assertConjuncts.Add(eqExpr);
- }
- foreach (IdentifierExpr e in impl.Proc.Modifies) {
- if (e.Decl == null) continue;
- Variable v = e.Decl;
- Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
- outputVariables.Add(c);
- Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
- assertConjuncts.Add(eqExpr);
- }
- exitAssertCmd = new AssertCmd(Token.NoToken, Expr.Not(Expr.BinaryTreeAnd(assertConjuncts)));
-
- Program program = vcgen.program;
- ProverInterface proverInterface = vcgen.prover;
- vcgen.ConvertCFG2DAG(impl);
- vcgen.PassifyImpl(impl, out mvInfo);
-
- VCExpressionGenerator gen = proverInterface.VCExprGen;
- var exprGen = proverInterface.Context.ExprGen;
- var translator = proverInterface.Context.BoogieExprTranslator;
-
- VCExpr controlFlowVariableExpr = null;
- if (!CommandLineOptions.Clo.UseLabels) {
- controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
- controlFlowVariableExpr = translator.LookupVariable(controlFlowVariable);
- }
-
- vcgen.InstrumentCallSites(impl);
-
- label2absy = new Dictionary<int, Absy>();
- VCGen.CodeExprConversionClosure cc = new VCGen.CodeExprConversionClosure(label2absy, proverInterface.Context);
- translator.SetCodeExprConverter(cc.CodeExprToVerificationCondition);
- vcexpr = gen.Not(vcgen.GenerateVCAux(impl, controlFlowVariableExpr, label2absy, proverInterface.Context));
-
- if (controlFlowVariableExpr != null)
- {
- VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(controlFlowVariableExpr, exprGen.Integer(BigNum.ZERO));
- VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
- vcexpr = exprGen.And(eqExpr, vcexpr);
- }
-
- callSites = vcgen.CollectCallSites(impl);
- recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl);
-
- privateExprVars = new List<VCExprVar>();
- foreach (Variable v in impl.LocVars) {
- privateExprVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in impl.OutParams) {
- privateExprVars.Add(translator.LookupVariable(v));
- }
-
- interfaceExprVars = new List<VCExprVar>();
- foreach (Variable v in program.GlobalVariables) {
- interfaceExprVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in impl.InParams) {
- interfaceExprVars.Add(translator.LookupVariable(v));
- }
- foreach (Variable v in outputVariables) {
- interfaceExprVars.Add(translator.LookupVariable(v));
- }
-
- initialized = true;
- }
- }
-
- public abstract class StratifiedVCGenBase : VCGen {
- public readonly static string recordProcName = "boogie_si_record";
- public Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo;
- public ProverInterface prover;
-
- public StratifiedVCGenBase(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
- : base(program, logFilePath, appendLogFile, checkers) {
- implName2StratifiedInliningInfo = new Dictionary<string, StratifiedInliningInfo>();
- prover = ProverInterface.CreateProver(program, logFilePath, appendLogFile, CommandLineOptions.Clo.ProverKillTime);
- foreach (var impl in program.Implementations) {
- implName2StratifiedInliningInfo[impl.Name] = new StratifiedInliningInfo(impl, this);
- }
- GenerateRecordFunctions();
- }
-
- private void GenerateRecordFunctions() {
- foreach (var proc in program.Procedures) {
- if (!proc.Name.StartsWith(recordProcName)) continue;
- Contract.Assert(proc.InParams.Count == 1);
-
- // Make a new function
- TypedIdent ti = new TypedIdent(Token.NoToken, "", Bpl.Type.Bool);
- Contract.Assert(ti != null);
- Formal returnVar = new Formal(Token.NoToken, ti, false);
- Contract.Assert(returnVar != null);
-
- // Get record type
- var argtype = proc.InParams[0].TypedIdent.Type;
-
- var ins = new List<Variable>();
- ins.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", argtype), true));
-
- var recordFunc = new Function(Token.NoToken, proc.Name, ins, returnVar);
- prover.Context.DeclareFunction(recordFunc, "");
-
- var exprs = new List<Expr>();
- exprs.Add(new IdentifierExpr(Token.NoToken, proc.InParams[0]));
-
- Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(recordFunc), exprs);
- proc.Ensures.Add(new Ensures(true, freePostExpr));
- }
- }
-
- public override void Close() {
- prover.Close();
- base.Close();
- }
-
- public void InstrumentCallSites(Implementation implementation) {
- var callSiteId = 0;
- foreach (Block block in implementation.Blocks) {
- List<Cmd> newCmds = new List<Cmd>();
- for (int i = 0; i < block.Cmds.Count; i++) {
- Cmd cmd = block.Cmds[i];
- newCmds.Add(cmd);
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- if (assumeCmd == null) continue;
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- if (naryExpr == null) continue;
- if (!implName2StratifiedInliningInfo.ContainsKey(naryExpr.Fun.FunctionName)) continue;
- Variable callSiteVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "SICS" + callSiteId, Microsoft.Boogie.Type.Bool));
- implementation.LocVars.Add(callSiteVar);
- newCmds.Add(new AssumeCmd(Token.NoToken, new IdentifierExpr(Token.NoToken, callSiteVar)));
- callSiteId++;
- }
- block.Cmds = newCmds;
- }
- }
-
- public Dictionary<Block, List<CallSite>> CollectCallSites(Implementation implementation) {
- var callSites = new Dictionary<Block, List<CallSite>>();
- foreach (Block block in implementation.Blocks) {
- for (int i = 0; i < block.Cmds.Count; i++) {
- Cmd cmd = block.Cmds[i];
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- if (assumeCmd == null) continue;
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- if (naryExpr == null) continue;
- if (!implName2StratifiedInliningInfo.ContainsKey(naryExpr.Fun.FunctionName)) continue;
- List<VCExpr> interfaceExprs = new List<VCExpr>();
- foreach (Expr e in naryExpr.Args) {
- interfaceExprs.Add(prover.Context.BoogieExprTranslator.Translate(e));
- }
- int instr = i;
- i++;
- AssumeCmd callSiteAssumeCmd = (AssumeCmd)block.Cmds[i];
- IdentifierExpr iexpr = (IdentifierExpr) callSiteAssumeCmd.Expr;
- CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, prover.Context.BoogieExprTranslator.LookupVariable(iexpr.Decl), block, instr, assumeCmd.Attributes);
- if (!callSites.ContainsKey(block))
- callSites[block] = new List<CallSite>();
- callSites[block].Add(cs);
- }
- }
- return callSites;
- }
-
- public Dictionary<Block, List<CallSite>> CollectRecordProcedureCallSites(Implementation implementation) {
- var callSites = new Dictionary<Block, List<CallSite>>();
- foreach (Block block in implementation.Blocks) {
- for (int i = 0; i < block.Cmds.Count; i++) {
- AssumeCmd assumeCmd = block.Cmds[i] as AssumeCmd;
- if (assumeCmd == null) continue;
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- if (naryExpr == null) continue;
- if (!naryExpr.Fun.FunctionName.StartsWith(recordProcName)) continue;
- List<VCExpr> interfaceExprs = new List<VCExpr>();
- foreach (Expr e in naryExpr.Args) {
- interfaceExprs.Add(prover.Context.BoogieExprTranslator.Translate(e));
- }
- CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, null, block, i, assumeCmd.Attributes);
- if (!callSites.ContainsKey(block))
- callSites[block] = new List<CallSite>();
- callSites[block].Add(cs);
- }
- }
- return callSites;
- }
-
- private int macroCountForStratifiedInlining = 0;
- public Macro CreateNewMacro() {
- string newName = "SIMacro@" + macroCountForStratifiedInlining.ToString();
- macroCountForStratifiedInlining++;
- return new Macro(Token.NoToken, newName, new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool), false));
- }
- private int varCountForStratifiedInlining = 0;
- public VCExprVar CreateNewVar(Microsoft.Boogie.Type type) {
- string newName = "SIV@" + varCountForStratifiedInlining.ToString();
- varCountForStratifiedInlining++;
- Constant newVar = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, newName, type));
- prover.Context.DeclareConstant(newVar, false, null);
- return prover.VCExprGen.Variable(newVar.Name, type);
- }
- private int idCountForStratifiedInlining = 0;
- public int CreateNewId() {
- return idCountForStratifiedInlining++;
- }
-
- // Used inside PassifyImpl
- protected override void addExitAssert(string implName, Block exitBlock) {
- if (implName2StratifiedInliningInfo != null && implName2StratifiedInliningInfo.ContainsKey(implName)) {
- var exitAssertCmd = implName2StratifiedInliningInfo[implName].exitAssertCmd;
- if(exitAssertCmd != null) exitBlock.Cmds.Add(exitAssertCmd);
- }
- }
-
- public override Counterexample extractLoopTrace(Counterexample cex, string mainProcName, Program program, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo) {
- // Construct the set of inlined procs in the original program
- var inlinedProcs = new HashSet<string>();
- foreach (var decl in program.TopLevelDeclarations) {
- // Implementations
- if (decl is Implementation) {
- var impl = decl as Implementation;
- if (!(impl.Proc is LoopProcedure)) {
- inlinedProcs.Add(impl.Name);
- }
- }
-
- // And recording procedures
- if (decl is Procedure) {
- var proc = decl as Procedure;
- if (proc.Name.StartsWith(recordProcName)) {
- Debug.Assert(!(decl is LoopProcedure));
- inlinedProcs.Add(proc.Name);
- }
- }
- }
-
- return extractLoopTraceRec(
- new CalleeCounterexampleInfo(cex, new List<object>()),
- mainProcName, inlinedProcs, extractLoopMappingInfo).counterexample;
- }
-
- protected override bool elIsLoop(string procname) {
- StratifiedInliningInfo info = null;
- if (implName2StratifiedInliningInfo.ContainsKey(procname)) {
- info = implName2StratifiedInliningInfo[procname];
- }
-
- if (info == null) return false;
-
- var lp = info.impl.Proc as LoopProcedure;
-
- if (lp == null) return false;
- return true;
- }
-
- public abstract Outcome FindLeastToVerify(Implementation impl, ref HashSet<string> allBoolVars);
- }
-
- public class StratifiedVCGen : StratifiedVCGenBase {
- public bool PersistCallTree;
- public static HashSet<string> callTree = null;
- public int numInlined = 0;
- public int vcsize = 0;
- private HashSet<string> procsThatReachedRecBound;
- public HashSet<string> procsToSkip;
- public Dictionary<string, int> extraRecBound;
-
- public StratifiedVCGen(bool usePrevCallTree, HashSet<string> prevCallTree,
- HashSet<string> procsToSkip, Dictionary<string, int> extraRecBound,
- Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
- : this(program, logFilePath, appendLogFile, checkers)
- {
- this.procsToSkip = new HashSet<string>(procsToSkip);
- this.extraRecBound = new Dictionary<string, int>(extraRecBound);
-
- if (usePrevCallTree) {
- callTree = prevCallTree;
- PersistCallTree = true;
- }
- else {
- PersistCallTree = false;
- }
- }
-
- public StratifiedVCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
- : base(program, logFilePath, appendLogFile, checkers) {
- PersistCallTree = false;
- procsThatReachedRecBound = new HashSet<string>();
- procsToSkip = new HashSet<string>();
- extraRecBound = new Dictionary<string, int>();
- }
-
- // Is this procedure to be "skipped"
- // Currently this is experimental
- public bool isSkipped(string procName) {
- return procsToSkip.Contains(procName);
- }
- public bool isSkipped(int candidate, FCallHandler calls) {
- return isSkipped(calls.getProc(candidate));
- }
- // Extra rec bound for procedures
- public int GetExtraRecBound(string procName) {
- if (!extraRecBound.ContainsKey(procName))
- return 0;
- else return extraRecBound[procName];
- }
-
- public class ApiChecker {
- public ProverInterface prover;
- public ProverInterface.ErrorHandler reporter;
-
- public ApiChecker(ProverInterface prover, ProverInterface.ErrorHandler reporter) {
- this.reporter = reporter;
- this.prover = prover;
- }
-
- private Outcome CheckVC() {
- prover.Check();
- ProverInterface.Outcome outcome = prover.CheckOutcomeCore(reporter);
-
- return ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
- }
-
- public Outcome CheckAssumptions(List<VCExpr> assumptions) {
- if (assumptions.Count == 0) {
- return CheckVC();
- }
-
- prover.Push();
- foreach (var a in assumptions) {
- prover.Assert(a, true);
- }
- Outcome ret = CheckVC();
- prover.Pop();
- return ret;
- }
-
- public Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions) {
- List<int> unsatisfiedSoftAssumptions;
- ProverInterface.Outcome outcome = prover.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, reporter);
- return ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
- }
-
- public Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore) {
- ProverInterface.Outcome outcome = prover.CheckAssumptions(assumptions, out unsatCore, reporter);
- return ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
- }
- }
-
- // Store important information related to a single VerifyImplementation query
- public class VerificationState {
- // The call tree
- public FCallHandler calls;
- public ApiChecker checker;
- // For statistics
- public int vcSize;
- public int expansionCount;
-
- public VerificationState(VCExpr vcMain, FCallHandler calls, ProverInterface prover, ProverInterface.ErrorHandler reporter) {
- prover.Assert(vcMain, true);
- this.calls = calls;
- this.checker = new ApiChecker(prover, reporter);
- vcSize = 0;
- expansionCount = 0;
- }
- }
-
- class FindLeastOORException : Exception
- {
- public Outcome outcome;
-
- public FindLeastOORException(string msg, Outcome outcome)
- : base(msg)
- {
- this.outcome = outcome;
- }
- }
-
- public override Outcome FindLeastToVerify(Implementation impl, ref HashSet<string> allBoolVars) {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- // Record current time
- var startTime = DateTime.UtcNow;
-
- // No Max: avoids theorem prover restarts
- CommandLineOptions.Clo.MaxProverMemory = 0;
-
- // Initialize cache
- satQueryCache = new Dictionary<int, List<HashSet<string>>>();
- unsatQueryCache = new Dictionary<int, List<HashSet<string>>>();
-
- Contract.Assert(implName2StratifiedInliningInfo != null);
-
- // Build VCs for all procedures
- implName2StratifiedInliningInfo.Values
- .Iter(info => info.GenerateVC());
-
- // Get the VC of the current procedure
- VCExpr vcMain = implName2StratifiedInliningInfo[impl.Name].vcexpr;
- Dictionary<int, Absy> mainLabel2absy = implName2StratifiedInliningInfo[impl.Name].label2absy;
-
- // Find all procedure calls in vc and put labels on them
- FCallHandler calls = new FCallHandler(prover.VCExprGen, implName2StratifiedInliningInfo, impl.Name, mainLabel2absy);
- calls.setCurrProcAsMain();
- vcMain = calls.Mutate(vcMain, true);
-
- try
- {
-
- // Put all of the necessary state into one object
- var vState = new VerificationState(vcMain, calls, prover, new EmptyErrorHandler());
-
- // We'll restore the original state of the theorem prover at the end
- // of this procedure
- vState.checker.prover.Push();
-
- // Do eager inlining
- while (calls.currCandidates.Count > 0)
- {
- List<int> toExpand = new List<int>();
-
- foreach (int id in calls.currCandidates)
- {
- Debug.Assert(calls.getRecursionBound(id) <= 1, "Recursion not supported");
- toExpand.Add(id);
- }
- DoExpansion(toExpand, vState);
- }
-
- // Find all the boolean constants
- var allConsts = new HashSet<VCExprVar>();
- foreach (var constant in program.Constants)
- {
- if (!allBoolVars.Contains(constant.Name)) continue;
- var v = prover.Context.BoogieExprTranslator.LookupVariable(constant);
- allConsts.Add(v);
- }
-
- // Now, lets start the algo
- var min = refinementLoop(vState.checker, new HashSet<VCExprVar>(), allConsts, allConsts);
-
- var ret = new HashSet<string>();
- foreach (var v in min)
- {
- //Console.WriteLine(v.Name);
- ret.Add(v.Name);
- }
- allBoolVars = ret;
-
- vState.checker.prover.Pop();
-
- return Outcome.Correct;
- }
- catch (FindLeastOORException e)
- {
- Console.WriteLine("Exception in FindLeastToVerify: {0}, {1}", e.Message, e.outcome);
- return e.outcome;
- }
- }
-
- private HashSet<VCExprVar> refinementLoop(ApiChecker apiChecker, HashSet<VCExprVar> trackedVars, HashSet<VCExprVar> trackedVarsUpperBound, HashSet<VCExprVar> allVars) {
- Debug.Assert(trackedVars.IsSubsetOf(trackedVarsUpperBound));
-
- // If we already know the fate of all vars, then we're done.
- if (trackedVars.Count == trackedVarsUpperBound.Count)
- return new HashSet<VCExprVar>(trackedVars);
-
- // See if we already have enough variables tracked
- var success = refinementLoopCheckPath(apiChecker, trackedVars, allVars);
- if (success) {
- // We have enough
- return new HashSet<VCExprVar>(trackedVars);
- }
-
- // If all that remains is 1 variable, then we know that we must track it
- if (trackedVars.Count + 1 == trackedVarsUpperBound.Count)
- return new HashSet<VCExprVar>(trackedVarsUpperBound);
-
- // Partition the remaining set of variables
- HashSet<VCExprVar> part1, part2;
- var temp = new HashSet<VCExprVar>(trackedVarsUpperBound);
- temp.ExceptWith(trackedVars);
- Partition<VCExprVar>(temp, out part1, out part2);
-
- // First half
- var fh = new HashSet<VCExprVar>(trackedVars); fh.UnionWith(part2);
- var s1 = refinementLoop(apiChecker, fh, trackedVarsUpperBound, allVars);
-
- var a = new HashSet<VCExprVar>(part1); a.IntersectWith(s1);
- var b = new HashSet<VCExprVar>(part1); b.ExceptWith(s1);
- var c = new HashSet<VCExprVar>(trackedVarsUpperBound); c.ExceptWith(b);
- a.UnionWith(trackedVars);
-
- // Second half
- return refinementLoop(apiChecker, a, c, allVars);
- }
-
- Dictionary<int, List<HashSet<string>>> satQueryCache;
- Dictionary<int, List<HashSet<string>>> unsatQueryCache;
-
- private bool refinementLoopCheckPath(ApiChecker apiChecker, HashSet<VCExprVar> varsToSet, HashSet<VCExprVar> allVars) {
- var assumptions = new List<VCExpr>();
- var prover = apiChecker.prover;
- var query = new HashSet<string>();
- varsToSet.Iter(v => query.Add(v.Name));
-
- if (checkCache(query, unsatQueryCache)) {
- prover.LogComment("FindLeast: Query Cache Hit");
- return true;
- }
- if (checkCache(query, satQueryCache)) {
- prover.LogComment("FindLeast: Query Cache Hit");
- return false;
- }
-
- prover.LogComment("FindLeast: Query Begin");
-
- foreach (var c in allVars) {
- if (varsToSet.Contains(c)) {
- assumptions.Add(c);
- }
- else {
- assumptions.Add(prover.VCExprGen.Not(c));
- }
- }
-
- var o = apiChecker.CheckAssumptions(assumptions);
- if (o != Outcome.Correct && o != Outcome.Errors)
- {
- throw new FindLeastOORException("OOR", o);
- }
- //Console.WriteLine("Result = " + o.ToString());
- prover.LogComment("FindLeast: Query End");
-
- if (o == Outcome.Correct) {
- insertCache(query, unsatQueryCache);
- return true;
- }
-
- insertCache(query, satQueryCache);
- return false;
- }
-
- private bool checkCache(HashSet<string> q, Dictionary<int, List<HashSet<string>>> cache) {
- if (!cache.ContainsKey(q.Count)) return false;
- foreach (var s in cache[q.Count]) {
- if (q.SetEquals(s)) return true;
- }
- return false;
- }
-
- private void insertCache(HashSet<string> q, Dictionary<int, List<HashSet<string>>> cache) {
- if (!cache.ContainsKey(q.Count)) {
- cache.Add(q.Count, new List<HashSet<string>>());
- }
- cache[q.Count].Add(q);
- }
-
- public static void Partition<T>(HashSet<T> values, out HashSet<T> part1, out HashSet<T> part2) {
- part1 = new HashSet<T>();
- part2 = new HashSet<T>();
- var size = values.Count;
- var crossed = false;
- var curr = 0;
- foreach (var s in values) {
- if (crossed) part2.Add(s);
- else part1.Add(s);
- curr++;
- if (!crossed && curr >= size / 2) crossed = true;
- }
- }
-
- public override Outcome VerifyImplementation(Implementation/*!*/ impl, VerifierCallback/*!*/ callback) {
- Debug.Assert(QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"));
- Debug.Assert(this.program == program);
-
- // Record current time
- var startTime = DateTime.UtcNow;
-
- // Flush any axioms that came with the program before we start SI on this implementation
- prover.AssertAxioms();
-
- // Run live variable analysis
- if (CommandLineOptions.Clo.LiveVariableAnalysis == 2) {
- Microsoft.Boogie.InterProcGenKill.ComputeLiveVars(impl, program);
- }
-
- // Get the VC of the current procedure
- StratifiedInliningInfo info = implName2StratifiedInliningInfo[impl.Name];
- info.GenerateVC();
- VCExpr vc = info.vcexpr;
- Dictionary<int, Absy> mainLabel2absy = info.label2absy;
- var reporter = new StratifiedInliningErrorReporter(implName2StratifiedInliningInfo, prover, callback, info);
-
- // Find all procedure calls in vc and put labels on them
- FCallHandler calls = new FCallHandler(prover.VCExprGen, implName2StratifiedInliningInfo, impl.Name, mainLabel2absy);
- calls.setCurrProcAsMain();
- vc = calls.Mutate(vc, true);
- reporter.SetCandidateHandler(calls);
- calls.id2VC.Add(0, vc);
- calls.extraRecursion = extraRecBound;
- if (CommandLineOptions.Clo.SIBoolControlVC)
- {
- calls.candiate2block2controlVar.Add(0, new Dictionary<Block, VCExpr>());
- implName2StratifiedInliningInfo[impl.Name].blockToControlVar.Iter(tup =>
- calls.candiate2block2controlVar[0].Add(tup.Key, tup.Value));
- }
-
- // We'll restore the original state of the theorem prover at the end
- // of this procedure
- prover.Push();
-
- // Put all of the necessary state into one object
- var vState = new VerificationState(vc, calls, prover, reporter);
- vState.vcSize += SizeComputingVisitor.ComputeSize(vc);
-
- Outcome ret = Outcome.ReachedBound;
-
- #region eager inlining
- for (int i = 1; i < CommandLineOptions.Clo.StratifiedInlining && calls.currCandidates.Count > 0; i++) {
- List<int> toExpand = new List<int>();
-
- foreach (int id in calls.currCandidates) {
- if (calls.getRecursionBound(id) <= CommandLineOptions.Clo.RecursionBound) {
- toExpand.Add(id);
- }
- }
- DoExpansion(toExpand, vState);
- }
- #endregion
-
- #region Repopulate call tree, if there is one
- if (PersistCallTree && callTree != null) {
- bool expand = true;
- while (expand) {
- List<int> toExpand = new List<int>();
- foreach (int id in calls.currCandidates) {
- if (callTree.Contains(calls.getPersistentId(id))) {
- toExpand.Add(id);
- }
- }
- if (toExpand.Count == 0) expand = false;
- else {
- DoExpansion(toExpand, vState);
- }
- }
- }
- #endregion
-
- if (CommandLineOptions.Clo.StratifiedInliningVerbose > 1) {
- Console.WriteLine(">> SI: Size of VC after eager inlining: {0}", vState.vcSize);
- }
-
- // Under-approx query is only needed if something was inlined since
- // the last time an under-approx query was made
- // TODO: introduce this
- // bool underApproxNeeded = true;
-
- // The recursion bound for stratified search
- int bound = CommandLineOptions.Clo.NonUniformUnfolding ? CommandLineOptions.Clo.RecursionBound : 1;
-
- int done = 0;
-
- int iters = 0;
-
- // for blocking candidates (and focusing on a counterexample)
- var block = new HashSet<int>();
-
- // Process tasks while not done. We're done when:
- // case 1: (correct) We didn't find a bug (either an over-approx query was valid
- // or we reached the recursion bound) and the task is "step"
- // case 2: (bug) We find a bug
- // case 3: (internal error) The theorem prover TimesOut of runs OutOfMemory
- while (true)
- {
- // Check timeout
- if (CommandLineOptions.Clo.ProverKillTime != -1)
- {
- if ((DateTime.UtcNow - startTime).TotalSeconds > CommandLineOptions.Clo.ProverKillTime)
- {
- ret = Outcome.TimedOut;
- break;
- }
- }
-
- if (done > 0)
- {
- break;
- }
-
- // Stratified Step
- ret = stratifiedStep(bound, vState, block);
- iters++;
-
- // Sorry, out of luck (time/memory)
- if (ret == Outcome.Inconclusive || ret == Outcome.OutOfMemory || ret == Outcome.TimedOut)
- {
- done = 3;
- continue;
- }
-
- if (ret == Outcome.Errors && reporter.underapproximationMode)
- {
- // Found a bug
- done = 2;
- }
- else if (ret == Outcome.Correct)
- {
- if (block.Count == 0)
- {
- // Correct
- done = 1;
- }
- else
- {
- // reset blocked and continue loop
- block.Clear();
- }
- }
- else if (ret == Outcome.ReachedBound)
- {
- if (block.Count == 0)
- {
- if (CommandLineOptions.Clo.StratifiedInliningVerbose > 0)
- Console.WriteLine(">> SI: Exhausted Bound {0}", bound);
-
- // Increment bound
- bound++;
-
- if (bound > CommandLineOptions.Clo.RecursionBound)
- {
- // Correct under bound
- done = 1;
- }
- }
- else
- {
- // reset blocked and continue loop
- block.Clear();
- }
- }
- else
- {
- // Do inlining
- Debug.Assert(ret == Outcome.Errors && !reporter.underapproximationMode);
- Contract.Assert(reporter.candidatesToExpand.Count != 0);
-
- #region expand call tree
- if (CommandLineOptions.Clo.StratifiedInliningVerbose > 1)
- {
- Console.Write(">> SI Inlining: ");
- reporter.candidatesToExpand
- .Select(c => calls.getProc(c))
- .Iter(c => { if (!isSkipped(c)) Console.Write("{0} ", c); });
-
- Console.WriteLine();
- Console.Write(">> SI Skipping: ");
- reporter.candidatesToExpand
- .Select(c => calls.getProc(c))
- .Iter(c => { if (isSkipped(c)) Console.Write("{0} ", c); });
-
- Console.WriteLine();
-
- }
-
- // Expand and try again
- vState.checker.prover.LogComment(";;;;;;;;;;;; Expansion begin ;;;;;;;;;;");
- DoExpansion(reporter.candidatesToExpand, vState);
- vState.checker.prover.LogComment(";;;;;;;;;;;; Expansion end ;;;;;;;;;;");
-
- #endregion
- }
- }
-
- // Pop off everything that we pushed so that there are no side effects from
- // this call to VerifyImplementation
- vState.checker.prover.Pop();
-
- if (CommandLineOptions.Clo.StratifiedInliningVerbose > 1) {
- Console.WriteLine(">> SI: Expansions performed: {0}", vState.expansionCount);
- Console.WriteLine(">> SI: Candidates left: {0}", calls.currCandidates.Count);
- Console.WriteLine(">> SI: Candidates skipped: {0}", calls.currCandidates.Where(i => isSkipped(i, calls)).Count());
- Console.WriteLine(">> SI: VC Size: {0}", vState.vcSize);
- }
-
- vcsize = vState.vcSize;
- numInlined = (calls.candidateParent.Keys.Count + 1) - (calls.currCandidates.Count);
-
- var rbound = "Procs that reached bound: ";
- foreach (var s in procsThatReachedRecBound) rbound += " " + s;
- if (ret == Outcome.ReachedBound) Helpers.ExtraTraceInformation(rbound);
- if (CommandLineOptions.Clo.StackDepthBound > 0 && ret == Outcome.Correct) ret = Outcome.ReachedBound;
-
- // Store current call tree
- if (PersistCallTree && (ret == Outcome.Correct || ret == Outcome.Errors || ret == Outcome.ReachedBound)) {
- callTree = new HashSet<string>();
- //var persistentNodes = new HashSet<int>(calls.candidateParent.Values);
- var persistentNodes = new HashSet<int>(calls.candidateParent.Keys);
- persistentNodes.Add(0);
- persistentNodes.ExceptWith(calls.currCandidates);
-
- foreach (var id in persistentNodes) {
- var pid = calls.getPersistentId(id);
- Debug.Assert(!callTree.Contains(pid));
- callTree.Add(pid);
- }
- }
- return ret;
- }
-
- // A step of the stratified inlining algorithm: both under-approx and over-approx queries
- private Outcome stratifiedStep(int bound, VerificationState vState, HashSet<int> block) {
- var calls = vState.calls;
- var checker = vState.checker;
- var prover = checker.prover;
- var reporter = checker.reporter as StratifiedInliningErrorReporter;
-
- reporter.underapproximationMode = true;
- prover.LogComment(";;;;;;;;;;;; Underapprox mode begin ;;;;;;;;;;");
- List<VCExpr> assumptions = new List<VCExpr>();
-
- foreach (int id in calls.currCandidates) {
- if (!isSkipped(id, calls))
- assumptions.Add(calls.getFalseExpr(id));
- }
- Outcome ret = checker.CheckAssumptions(assumptions);
- prover.LogComment(";;;;;;;;;;;; Underapprox mode end ;;;;;;;;;;");
-
- if (ret != Outcome.Correct) {
- // Either the query returned an error or it ran out of memory or time.
- // In all cases, we are done.
- return ret;
- }
-
- if (calls.currCandidates.Count == 0) {
- // If we didn't underapproximate, then we're done
- return ret;
- }
-
- prover.LogComment(";;;;;;;;;;;; Overapprox mode begin ;;;;;;;;;;");
-
- // Over-approx query
- reporter.underapproximationMode = false;
-
- // Push "true" for all, except:
- // push "false" for all candidates that have reached
- // the recursion bounds
-
- bool allTrue = true;
- bool allFalse = true;
- List<VCExpr> softAssumptions = new List<VCExpr>();
-
- assumptions = new List<VCExpr>();
- procsThatReachedRecBound.Clear();
-
- foreach (int id in calls.currCandidates) {
- if (isSkipped(id, calls)) continue;
-
- int idBound = calls.getRecursionBound(id);
- int sd = calls.getStackDepth(id);
- if (idBound <= bound && (CommandLineOptions.Clo.StackDepthBound == 0 || sd <= CommandLineOptions.Clo.StackDepthBound)) {
- if (idBound > 1)
- softAssumptions.Add(calls.getFalseExpr(id));
-
- if (block.Contains(id)) {
- assumptions.Add(calls.getFalseExpr(id));
- allTrue = false;
- }
- else {
- allFalse = false;
- }
- }
- else {
- procsThatReachedRecBound.Add(calls.getProc(id));
- assumptions.Add(calls.getFalseExpr(id));
- allTrue = false;
- }
- }
-
- if (allFalse) {
- // If we made all candidates false, then this is the same
- // as the underapprox query. We already know the answer.
- ret = Outcome.Correct;
- }
- else {
- ret = CommandLineOptions.Clo.NonUniformUnfolding
- ? checker.CheckAssumptions(assumptions, softAssumptions)
- : checker.CheckAssumptions(assumptions);
- }
-
- if (ret != Outcome.Correct && ret != Outcome.Errors) {
- // The query ran out of memory or time, that's it,
- // we cannot do better. Give up!
- return ret;
- }
-
- if (ret == Outcome.Correct) {
- // If nothing was made false, then the program is correct
- if (allTrue) {
- return ret;
- }
-
- // Nothing more can be done with current recursion bound.
- return Outcome.ReachedBound;
- }
-
- Contract.Assert(ret == Outcome.Errors);
-
- prover.LogComment(";;;;;;;;;;;; Overapprox mode end ;;;;;;;;;;");
-
- return ret;
- }
-
- // A counter for adding new variables
- static int newVarCnt = 0;
-
- // Does on-demand inlining -- pushes procedure bodies on the theorem prover stack.
- private void DoExpansion(List<int>/*!*/ candidates, VerificationState vState) {
- Contract.Requires(candidates != null);
- Contract.Requires(vState.calls != null);
- Contract.Requires(vState.checker.prover != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- // Skipped calls don't get inlined
- candidates = candidates.FindAll(id => !isSkipped(id, vState.calls));
-
- vState.expansionCount += candidates.Count;
-
- var prover = vState.checker.prover;
- var calls = vState.calls;
-
- VCExpr exprToPush = VCExpressionGenerator.True;
- Contract.Assert(exprToPush != null);
- foreach (int id in candidates) {
- VCExprNAry expr = calls.id2Candidate[id];
- Contract.Assert(expr != null);
- string procName = cce.NonNull(expr.Op as VCExprBoogieFunctionOp).Func.Name;
- if (!implName2StratifiedInliningInfo.ContainsKey(procName)) continue;
-
- StratifiedInliningInfo info = implName2StratifiedInliningInfo[procName];
- info.GenerateVC();
- //Console.WriteLine("Inlining {0}", procName);
- VCExpr expansion = cce.NonNull(info.vcexpr);
-
- // Instantiate the "forall" variables
- Dictionary<VCExprVar, VCExpr> substForallDict = new Dictionary<VCExprVar, VCExpr>();
- Contract.Assert(info.interfaceExprVars.Count == expr.Length);
- for (int i = 0; i < info.interfaceExprVars.Count; i++) {
- substForallDict.Add(info.interfaceExprVars[i], expr[i]);
- }
- VCExprSubstitution substForall = new VCExprSubstitution(substForallDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
-
- SubstitutingVCExprVisitor subst = new SubstitutingVCExprVisitor(prover.VCExprGen);
- Contract.Assert(subst != null);
- expansion = subst.Mutate(expansion, substForall);
-
- // Instantiate and declare the "exists" variables
- Dictionary<VCExprVar, VCExpr> substExistsDict = new Dictionary<VCExprVar, VCExpr>();
- foreach (VCExprVar v in info.privateExprVars) {
- Contract.Assert(v != null);
- string newName = v.Name + "_si_" + newVarCnt.ToString();
- newVarCnt++;
- prover.Context.DeclareConstant(new Constant(Token.NoToken, new TypedIdent(Token.NoToken, newName, v.Type)), false, null);
- substExistsDict.Add(v, prover.VCExprGen.Variable(newName, v.Type));
- }
- if (CommandLineOptions.Clo.SIBoolControlVC)
- {
- // record the mapping for control booleans (for tracing the path later)
- calls.candiate2block2controlVar[id] = new Dictionary<Block, VCExpr>();
- foreach (var tup in info.blockToControlVar)
- {
- calls.candiate2block2controlVar[id].Add(tup.Key,
- substExistsDict[tup.Value]);
- }
- }
- if (CommandLineOptions.Clo.ModelViewFile != null) {
- SaveSubstitution(vState, id, substForallDict, substExistsDict);
- }
- VCExprSubstitution substExists = new VCExprSubstitution(substExistsDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
-
- subst = new SubstitutingVCExprVisitor(prover.VCExprGen);
- expansion = subst.Mutate(expansion, substExists);
-
- if (!calls.currCandidates.Contains(id)) {
- Console.WriteLine("Don't know what we just expanded");
- }
-
- calls.currCandidates.Remove(id);
-
- // Record the new set of candidates and rename absy labels
- calls.currInlineCount = id;
- calls.setCurrProc(procName);
- expansion = calls.Mutate(expansion, true);
-
- //expansion = checker.VCExprGen.Eq(calls.id2ControlVar[id], expansion);
- expansion = prover.VCExprGen.Implies(calls.id2ControlVar[id], expansion);
- calls.id2VC.Add(id, expansion);
-
- exprToPush = prover.VCExprGen.And(exprToPush, expansion);
- }
- vState.checker.prover.Assert(exprToPush, true);
- vState.vcSize += SizeComputingVisitor.ComputeSize(exprToPush);
- }
-
- private void SaveSubstitution(VerificationState vState, int id,
- Dictionary<VCExprVar, VCExpr> substForallDict, Dictionary<VCExprVar, VCExpr> substExistsDict) {
- var prover = vState.checker.prover;
- var calls = vState.calls;
- Boogie2VCExprTranslator translator = prover.Context.BoogieExprTranslator;
- VCExprVar mvStateConstant = translator.LookupVariable(ModelViewInfo.MVState_ConstantDef);
- substExistsDict.Add(mvStateConstant, prover.VCExprGen.Integer(BigNum.FromInt(id)));
- Dictionary<VCExprVar, VCExpr> mapping = new Dictionary<VCExprVar, VCExpr>();
- foreach (var key in substForallDict.Keys)
- mapping[key] = substForallDict[key];
- foreach (var key in substExistsDict.Keys)
- mapping[key] = substExistsDict[key];
- calls.id2Vars[id] = mapping;
- }
-
- // Uniquely identifies a procedure call (the call expr, instance)
- public class BoogieCallExpr : IEquatable<BoogieCallExpr> {
- public NAryExpr expr;
- public int inlineCnt;
-
- public BoogieCallExpr(NAryExpr expr, int inlineCnt) {
- this.expr = expr;
- this.inlineCnt = inlineCnt;
- }
-
- public override int GetHashCode() {
- return expr.GetHashCode() + 131 * inlineCnt.GetHashCode();
- }
-
- public override bool Equals(object obj) {
- BoogieCallExpr that = obj as BoogieCallExpr;
- return (expr == that.expr && inlineCnt == that.inlineCnt);
- }
-
- public bool Equals(BoogieCallExpr that) {
- return (expr == that.expr && inlineCnt == that.inlineCnt);
- }
- }
-
- // This class is used to traverse VCs and do the following:
- // -- collect the set of FunctionCall nodes and label them with a unique string
- // -- Rename all other labels (so that calling this on the same VC results in
- // VCs with different labels each time)
- public class FCallHandler : MutatingVCExprVisitor<bool> {
- Dictionary<string/*!*/, StratifiedInliningInfo/*!*/>/*!*/ implName2StratifiedInliningInfo;
- public readonly Dictionary<int, Absy>/*!*/ mainLabel2absy;
- public Dictionary<BoogieCallExpr/*!*/, int>/*!*/ boogieExpr2Id;
- public Dictionary<BoogieCallExpr/*!*/, VCExpr>/*!*/ recordExpr2Var;
- public Dictionary<int, VCExprNAry/*!*/>/*!*/ id2Candidate;
- public Dictionary<int, VCExprVar/*!*/>/*!*/ id2ControlVar;
- public Dictionary<int, VCExpr> id2VC;
- public Dictionary<string/*!*/, int>/*!*/ label2Id;
- // candidate to block to Bool Control variable
- public Dictionary<int, Dictionary<Block, VCExpr>> candiate2block2controlVar;
- // Stores the candidate from which this one originated
- public Dictionary<int, int> candidateParent;
- // Mapping from candidate Id to the "si_unique_call" id that led to
- // this candidate. This is useful for getting persistent names for
- // candidates
- public Dictionary<int, int> candidate2callId;
- // A cache for candidate id to its persistent name
- public Dictionary<int, string> persistentNameCache;
- // Inverse of the above map
- public Dictionary<string, int> persistentNameInv;
- // Used to record candidates recently added
- public HashSet<int> recentlyAddedCandidates;
- // Name of main procedure
- private string mainProcName;
- // A map from candidate id to the VCExpr that represents its
- // first argument (used for obtaining concrete values in error trace)
- public Dictionary<int, VCExpr> argExprMap;
-
- // map from candidate to summary candidates
- public Dictionary<int, List<Tuple<VCExprVar, VCExpr>>> summaryCandidates;
- private Dictionary<string, List<Tuple<VCExprVar, VCExpr>>> summaryTemp;
- // set of all boolean guards of summaries
- public HashSet<VCExprVar> allSummaryConst;
-
- public HashSet<int> forcedCandidates;
-
- // User info -- to decrease/increase calculation of recursion bound
- public Dictionary<int, int> recursionIncrement;
- public Dictionary<string, int> extraRecursion;
-
- public HashSet<int> currCandidates;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
- Contract.Invariant(mainLabel2absy != null);
- Contract.Invariant(boogieExpr2Id != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(id2Candidate));
- Contract.Invariant(cce.NonNullDictionaryAndValues(id2ControlVar));
- Contract.Invariant(label2Id != null);
- }
-
- // Name of the procedure whose VC we're mutating
- string currProc;
-
- // The 0^th candidate is main
- static int candidateCount = 1;
- public int currInlineCount;
-
- public Dictionary<int, Dictionary<VCExprVar, VCExpr>> id2Vars;
-
- public FCallHandler(VCExpressionGenerator/*!*/ gen,
- Dictionary<string/*!*/, StratifiedInliningInfo/*!*/>/*!*/ implName2StratifiedInliningInfo,
- string mainProcName, Dictionary<int, Absy>/*!*/ mainLabel2absy)
- : base(gen) {
- Contract.Requires(gen != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
- Contract.Requires(mainLabel2absy != null);
- this.implName2StratifiedInliningInfo = implName2StratifiedInliningInfo;
- this.mainProcName = mainProcName;
- this.mainLabel2absy = mainLabel2absy;
- id2Candidate = new Dictionary<int, VCExprNAry>();
- id2ControlVar = new Dictionary<int, VCExprVar>();
- boogieExpr2Id = new Dictionary<BoogieCallExpr, int>();
- label2Id = new Dictionary<string, int>();
- currCandidates = new HashSet<int>();
- currInlineCount = 0;
- currProc = null;
- labelRenamer = new Dictionary<string, int>();
- labelRenamerInv = new Dictionary<string, string>();
- candidateParent = new Dictionary<int, int>();
- //callGraphMapping = new Dictionary<int, int>();
- recursionIncrement = new Dictionary<int, int>();
- candidate2callId = new Dictionary<int, int>();
- persistentNameCache = new Dictionary<int, string>();
- persistentNameInv = new Dictionary<string, int>();
- persistentNameCache[0] = "0";
- persistentNameInv["0"] = 0;
- recentlyAddedCandidates = new HashSet<int>();
- argExprMap = new Dictionary<int, VCExpr>();
- recordExpr2Var = new Dictionary<BoogieCallExpr, VCExpr>();
- candiate2block2controlVar = new Dictionary<int, Dictionary<Block, VCExpr>>();
-
- forcedCandidates = new HashSet<int>();
- extraRecursion = new Dictionary<string, int>();
-
- id2Vars = new Dictionary<int, Dictionary<VCExprVar, VCExpr>>();
- summaryCandidates = new Dictionary<int, List<Tuple<VCExprVar, VCExpr>>>();
- summaryTemp = new Dictionary<string, List<Tuple<VCExprVar, VCExpr>>>();
- allSummaryConst = new HashSet<VCExprVar>();
- id2VC = new Dictionary<int, VCExpr>();
- }
-
- public void Clear() {
- currCandidates = new HashSet<int>();
- }
-
- // Return the set of all candidates
- public HashSet<int> getAllCandidates() {
- var ret = new HashSet<int>(candidateParent.Keys);
- ret.Add(0);
- return ret;
- }
-
- // Given a candidate "id", let proc(id) be the
- // procedure corresponding to id. This procedure returns
- // the number of times proc(id) appears as an ancestor
- // of id. This is the same as the number of times we've
- // recursed on proc(id)
- public int getRecursionBound(int id) {
- int ret = 1;
- var str = getProc(id);
-
- while (candidateParent.ContainsKey(id)) {
- if (recursionIncrement.ContainsKey(id)) ret += recursionIncrement[id];
- id = candidateParent[id];
- if (getProc(id) == str && !forcedCandidates.Contains(id)) ret++;
- }
-
- // Usual
- if (!extraRecursion.ContainsKey(str))
- return ret;
-
- // Usual
- if (ret <= CommandLineOptions.Clo.RecursionBound - 1)
- return ret;
-
- // Special
- if (ret >= CommandLineOptions.Clo.RecursionBound &&
- ret <= CommandLineOptions.Clo.RecursionBound + extraRecursion[str] - 1)
- return CommandLineOptions.Clo.RecursionBound - 1;
-
- // Special
- return ret - extraRecursion[str];
- }
-
- // This procedure returns the stack depth of the candidate
- // (distance from main)
- public int getStackDepth(int id)
- {
- int ret = 1;
-
- while (candidateParent.ContainsKey(id))
- {
- ret++;
- id = candidateParent[id];
- }
-
- return ret;
- }
-
- // Set user-define increment/decrement to recursionBound
- public void setRecursionIncrement(int id, int incr) {
- if (recursionIncrement.ContainsKey(id))
- recursionIncrement[id] = incr;
- else
- recursionIncrement.Add(id, incr);
- }
-
- // Returns the name of the procedure corresponding to candidate id
- public string getProc(int id) {
- if (id == 0) return mainProcName;
-
- return (id2Candidate[id].Op as VCExprBoogieFunctionOp).Func.Name;
- }
-
- // Get a unique id for this candidate (dependent only on the Call
- // graph of the program). The persistent id is:
- // 0: for main
- // a_b_c: where a is the persistent id of parent, and b is the procedure name
- // and c is the unique call id (if any)
- public string getPersistentId(int top_id) {
- if (top_id == 0) return "0";
- Debug.Assert(candidateParent.ContainsKey(top_id));
- if (persistentNameCache.ContainsKey(top_id))
- return persistentNameCache[top_id];
-
- var parent_id = getPersistentId(candidateParent[top_id]);
- var call_id = candidate2callId.ContainsKey(top_id) ? candidate2callId[top_id] : -1;
- var ret = string.Format("{0}_131_{1}_131_{2}", parent_id, getProc(top_id), call_id);
- persistentNameCache[top_id] = ret;
- persistentNameInv[ret] = top_id;
- return ret;
- }
-
- public int getCandidateFromGraphNode(string n) {
- if (!persistentNameInv.ContainsKey(n)) {
- return -1;
- }
- return persistentNameInv[n];
- }
-
- private int GetNewId(VCExprNAry vc) {
- Contract.Requires(vc != null);
- int id = candidateCount;
-
- id2Candidate[id] = vc;
- id2ControlVar[id] = Gen.Variable("si_control_var_bool_" + id.ToString(), Microsoft.Boogie.Type.Bool);
-
- candidateCount++;
- currCandidates.Add(id);
- recentlyAddedCandidates.Add(id);
-
- return id;
- }
-
- private string GetLabel(int id) {
- Contract.Ensures(Contract.Result<string>() != null);
-
- string ret = "si_fcall_" + id.ToString();
- if (!label2Id.ContainsKey(ret))
- label2Id[ret] = id;
-
- return ret;
- }
-
- public int GetId(string label) {
- Contract.Requires(label != null);
- if (!label2Id.ContainsKey(label))
- return -1;
- return label2Id[label];
- }
-
- Dictionary<string, int> labelRenamer;
- Dictionary<string, string> labelRenamerInv;
-
- public string RenameAbsyLabel(string label) {
- Contract.Requires(label != null);
- Contract.Requires(label.Length >= 1);
- Contract.Ensures(Contract.Result<string>() != null);
-
- // Remove the sign from the label
- string nosign = label.Substring(1);
- var ret = "si_inline_" + currInlineCount.ToString() + "_" + nosign;
-
- if (!labelRenamer.ContainsKey(ret)) {
- var c = labelRenamer.Count + 11; // two digit labels only
- labelRenamer.Add(ret, c);
- labelRenamerInv.Add(c.ToString(), ret);
- }
- return labelRenamer[ret].ToString();
- }
-
- public string ParseRenamedAbsyLabel(string label, int cnt) {
- Contract.Requires(label != null);
- if (!labelRenamerInv.ContainsKey(label)) {
- return null;
- }
- var str = labelRenamerInv[label];
- var prefix = "si_inline_" + cnt.ToString() + "_";
- if (!str.StartsWith(prefix)) return null;
- return str.Substring(prefix.Length);
- }
-
- public void setCurrProc(string name) {
- Contract.Requires(name != null);
- currProc = name;
- Contract.Assert(implName2StratifiedInliningInfo.ContainsKey(name));
- }
-
- public void setCurrProcAsMain() {
- currProc = "";
- }
-
- // Return the formula (candidate IFF false)
- public VCExpr getFalseExpr(int candidateId) {
- //return Gen.Eq(VCExpressionGenerator.False, id2ControlVar[candidateId]);
- return Gen.Not(id2ControlVar[candidateId]);
- }
-
- // Return the formula (candidate IFF true)
- public VCExpr getTrueExpr(int candidateId) {
- return Gen.Eq(VCExpressionGenerator.True, id2ControlVar[candidateId]);
- }
-
- public Dictionary<int, Absy> getLabel2absy() {
- Contract.Ensures(Contract.Result<Dictionary<int, Absy>>() != null);
-
- Contract.Assert(currProc != null);
- if (currProc == "") {
- return mainLabel2absy;
- }
- return cce.NonNull(implName2StratifiedInliningInfo[currProc].label2absy);
- }
-
- // Finds labels and changes them:
- // si_fcall_id: if "id" corresponds to a tracked procedure call, then
- // si_control_var_candidateId
- // si_fcall_id: if "id" does not corresponds to a tracked procedure call, then
- // delete
- // num: si_inline_num
- //
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
- List<VCExpr/*!*/>/*!*/ newSubExprs,
- // has any of the subexpressions changed?
- bool changed,
- bool arg) {
- //Contract.Requires(originalNode != null);
- //Contract.Requires(cce.NonNullElements(newSubExprs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr ret;
- if (changed)
- ret = Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- ret = originalNode;
-
- VCExprLabelOp lop = originalNode.Op as VCExprLabelOp;
- if (lop == null) return ret;
- if (!(ret is VCExprNAry)) return ret;
-
- VCExprNAry retnary = (VCExprNAry)ret;
- Contract.Assert(retnary != null);
- string prefix = "si_fcall_"; // from Wlp.ssc::Cmd(...)
- if (lop.label.Substring(1).StartsWith(prefix)) {
- int id = Int32.Parse(lop.label.Substring(prefix.Length + 1));
- Dictionary<int, Absy> label2absy = getLabel2absy();
- Absy cmd = label2absy[id] as Absy;
- //label2absy.Remove(id);
-
- Contract.Assert(cmd != null);
- AssumeCmd acmd = cmd as AssumeCmd;
- Contract.Assert(acmd != null);
- NAryExpr naryExpr = acmd.Expr as NAryExpr;
- Contract.Assert(naryExpr != null);
-
- string calleeName = naryExpr.Fun.FunctionName;
-
- VCExprNAry callExpr = retnary[0] as VCExprNAry;
-
- if (implName2StratifiedInliningInfo.ContainsKey(calleeName)) {
- Contract.Assert(callExpr != null);
- int candidateId = GetNewId(callExpr);
- boogieExpr2Id[new BoogieCallExpr(naryExpr, currInlineCount)] = candidateId;
- candidateParent[candidateId] = currInlineCount;
- candiate2block2controlVar[candidateId] = new Dictionary<Block, VCExpr>();
-
- string label = GetLabel(candidateId);
- var unique_call_id = QKeyValue.FindIntAttribute(acmd.Attributes, "si_unique_call", -1);
- if (unique_call_id != -1)
- candidate2callId[candidateId] = unique_call_id;
-
- //return Gen.LabelPos(label, callExpr);
- return Gen.LabelPos(label, id2ControlVar[candidateId]);
- }
- else if (calleeName.StartsWith(recordProcName)) {
- Contract.Assert(callExpr != null);
- Debug.Assert(callExpr.Length == 1);
- Debug.Assert(callExpr[0] != null);
- recordExpr2Var[new BoogieCallExpr(naryExpr, currInlineCount)] = callExpr[0];
- return callExpr;
- }
- else {
- // callExpr can be null; this happens when the FunctionCall was on a
- // pure function (not procedure) and the function got inlined
- return retnary[0];
- }
- }
-
- // Else, rename label
- string newLabel = RenameAbsyLabel(lop.label);
- if (lop.pos) {
- return Gen.LabelPos(newLabel, retnary[0]);
- }
- else {
- return Gen.LabelNeg(newLabel, retnary[0]);
- }
-
- }
-
- // Upgrades summaryTemp to summaryCandidates by matching ensure clauses with
- // the appropriate candidate they came from
- public void matchSummaries() {
- var id2Set = new Dictionary<string, List<Tuple<int, HashSet<VCExprVar>>>>();
- foreach (var id in recentlyAddedCandidates) {
- var collect = new CollectVCVars();
- var proc = getProc(id);
- if (!id2Set.ContainsKey(proc)) id2Set.Add(proc, new List<Tuple<int, HashSet<VCExprVar>>>());
- id2Set[proc].Add(Tuple.Create(id, collect.Collect(id2Candidate[id], true)));
- }
-
- foreach (var kvp in summaryTemp) {
- Contract.Assert(id2Set.ContainsKey(kvp.Key));
- var ls = id2Set[kvp.Key];
- foreach (var tup in kvp.Value) {
- var collect = new CollectVCVars();
- var s1 = collect.Collect(tup.Item2, true);
- var found = false;
- foreach (var t in ls) {
- var s2 = t.Item2;
- if (s1.IsSubsetOf(s2)) {
- if (!summaryCandidates.ContainsKey(t.Item1))
- summaryCandidates.Add(t.Item1, new List<Tuple<VCExprVar, VCExpr>>());
- summaryCandidates[t.Item1].Add(tup);
- allSummaryConst.Add(tup.Item1);
- found = true;
- break;
- }
- }
- Contract.Assert(found);
- }
- }
- summaryTemp.Clear();
- }
-
- public IEnumerable<int> getInlinedCandidates() {
- return candidateParent.Keys.Except(currCandidates).Union(new int[] { 0 });
- }
-
- } // end FCallHandler
-
- // Collects the set of all VCExprVar in a given VCExpr
- class CollectVCVars : CollectingVCExprVisitor<HashSet<VCExprVar>, bool> {
- public override HashSet<VCExprVar> Visit(VCExprVar node, bool arg) {
- var ret = new HashSet<VCExprVar>();
- ret.Add(node);
- return ret;
- }
-
- protected override HashSet<VCExprVar> CombineResults(List<HashSet<VCExprVar>> results, bool arg) {
- var ret = new HashSet<VCExprVar>();
- results.Iter(s => ret.UnionWith(s));
- return ret;
- }
- }
-
- public class FCallInliner : MutatingVCExprVisitor<bool> {
- public Dictionary<int, VCExpr/*!*/>/*!*/ subst;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(subst));
- }
-
-
- public FCallInliner(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
- subst = new Dictionary<int, VCExpr>();
- }
-
- public void Clear() {
- subst = new Dictionary<int, VCExpr>();
- }
-
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
- List<VCExpr/*!*/>/*!*/ newSubExprs,
- // has any of the subexpressions changed?
- bool changed,
- bool arg) {
- //Contract.Requires(originalNode != null);Contract.Requires(newSubExprs != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr ret;
- if (changed)
- ret = Gen.Function(originalNode.Op, newSubExprs, originalNode.TypeArguments);
- else
- ret = originalNode;
-
- VCExprLabelOp lop = originalNode.Op as VCExprLabelOp;
- if (lop == null) return ret;
- if (!(ret is VCExprNAry)) return ret;
-
- string prefix = "si_fcall_"; // from FCallHandler::GetLabel
- if (lop.label.Substring(1).StartsWith(prefix)) {
- int id = Int32.Parse(lop.label.Substring(prefix.Length + 1));
- if (subst.ContainsKey(id)) {
- return subst[id];
- }
- }
- return ret;
- }
-
- } // end FCallInliner
-
-
-
- public class StratifiedInliningErrorReporter : ProverInterface.ErrorHandler {
- Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo;
- ProverInterface theoremProver;
- VerifierCallback callback;
- FCallHandler calls;
- StratifiedInliningInfo mainInfo;
- StratifiedVC mainVC;
-
- public bool underapproximationMode;
- public List<int> candidatesToExpand;
- public List<StratifiedCallSite> callSitesToExpand;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(candidatesToExpand != null);
- Contract.Invariant(mainInfo != null);
- Contract.Invariant(callback != null);
- Contract.Invariant(theoremProver != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
- }
-
-
- public StratifiedInliningErrorReporter(Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo,
- ProverInterface theoremProver, VerifierCallback callback,
- StratifiedInliningInfo mainInfo) {
- Contract.Requires(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
- Contract.Requires(theoremProver != null);
- Contract.Requires(callback != null);
- Contract.Requires(mainInfo != null);
- this.implName2StratifiedInliningInfo = implName2StratifiedInliningInfo;
- this.theoremProver = theoremProver;
- this.callback = callback;
- this.mainInfo = mainInfo;
- this.underapproximationMode = false;
- this.calls = null;
- this.candidatesToExpand = new List<int>();
- }
-
- public StratifiedInliningErrorReporter(Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo,
- ProverInterface theoremProver, VerifierCallback callback,
- StratifiedVC mainVC) {
- Contract.Requires(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
- Contract.Requires(theoremProver != null);
- Contract.Requires(callback != null);
- Contract.Requires(mainVC != null);
- this.implName2StratifiedInliningInfo = implName2StratifiedInliningInfo;
- this.theoremProver = theoremProver;
- this.callback = callback;
- this.mainVC = mainVC;
- this.underapproximationMode = false;
- this.candidatesToExpand = new List<int>();
- }
-
- public void SetCandidateHandler(FCallHandler calls) {
- Contract.Requires(calls != null);
- this.calls = calls;
- }
-
- List<Tuple<int, int>> orderedStateIds;
-
- private Model.Element GetModelValue(Model m, Variable v, int candidateId) {
- // first, get the unique name
- string uniqueName;
-
- VCExprVar vvar = theoremProver.Context.BoogieExprTranslator.TryLookupVariable(v);
- if (vvar == null) {
- uniqueName = v.Name;
- }
- else {
- if (candidateId != 0) {
- Dictionary<VCExprVar, VCExpr> mapping = calls.id2Vars[candidateId];
- if (mapping.ContainsKey(vvar)) {
- VCExpr e = mapping[vvar];
- if (e is VCExprLiteral) {
- VCExprLiteral lit = (VCExprLiteral)e;
- return m.MkElement(lit.ToString());
- }
- vvar = (VCExprVar)mapping[vvar];
- }
- }
- uniqueName = theoremProver.Context.Lookup(vvar);
- }
-
- var f = m.TryGetFunc(uniqueName);
- if (f == null)
- return m.MkFunc("@undefined", 0).GetConstant();
- return f.GetConstant();
- }
-
- public readonly static int CALL = -1;
- public readonly static int RETURN = -2;
-
- public void PrintModel(Model model) {
- var filename = CommandLineOptions.Clo.ModelViewFile;
- if (model == null || filename == null) return;
-
- if (filename == "-") {
- model.Write(Console.Out);
- Console.Out.Flush();
- }
- else {
- using (var wr = new StreamWriter(filename, !Counterexample.firstModelFile)) {
- Counterexample.firstModelFile = false;
- model.Write(wr);
- }
- }
- }
-
- private void GetModelWithStates(Model m) {
- if (m == null) return;
- var mvInfo = mainInfo.mvInfo;
- var mvstates = m.TryGetFunc("$mv_state");
- if (mvstates == null)
- return;
-
- Contract.Assert(mvstates.Arity == 2);
-
- foreach (Variable v in mvInfo.AllVariables) {
- m.InitialState.AddBinding(v.Name, GetModelValue(m, v, 0));
- }
-
- int lastCandidate = 0;
- int lastCapturePoint = CALL;
- for (int i = 0; i < this.orderedStateIds.Count; ++i) {
- var s = orderedStateIds[i];
- int candidate = s.Item1;
- int capturePoint = s.Item2;
- string implName = calls.getProc(candidate);
- ModelViewInfo info = candidate == 0 ? mvInfo : implName2StratifiedInliningInfo[implName].mvInfo;
-
- if (capturePoint == CALL || capturePoint == RETURN) {
- lastCandidate = candidate;
- lastCapturePoint = capturePoint;
- continue;
- }
-
- Contract.Assume(0 <= capturePoint && capturePoint < info.CapturePoints.Count);
- VC.ModelViewInfo.Mapping map = info.CapturePoints[capturePoint];
- var prevInc = (lastCapturePoint != CALL && lastCapturePoint != RETURN && candidate == lastCandidate)
- ? info.CapturePoints[lastCapturePoint].IncarnationMap : new Dictionary<Variable, Expr>();
- var cs = m.MkState(map.Description);
-
- foreach (Variable v in info.AllVariables) {
- var e = (Expr)map.IncarnationMap[v];
-
- if (e == null) {
- if (lastCapturePoint == CALL || lastCapturePoint == RETURN) {
- cs.AddBinding(v.Name, GetModelValue(m, v, candidate));
- }
- continue;
- }
-
- if (lastCapturePoint != CALL && lastCapturePoint != RETURN && prevInc[v] == e) continue; // skip unchanged variables
-
- Model.Element elt;
- if (e is IdentifierExpr) {
- IdentifierExpr ide = (IdentifierExpr)e;
- elt = GetModelValue(m, ide.Decl, candidate);
- }
- else if (e is LiteralExpr) {
- LiteralExpr lit = (LiteralExpr)e;
- elt = m.MkElement(lit.Val.ToString());
- }
- else {
- Contract.Assume(false);
- elt = m.MkFunc(e.ToString(), 0).GetConstant();
- }
- cs.AddBinding(v.Name, elt);
- }
-
- lastCandidate = candidate;
- lastCapturePoint = capturePoint;
- }
-
- return;
- }
-
- public override void OnResourceExceeded(string message)
- {
- //Contract.Requires(message != null);
- }
-
- public override void OnModel(IList<string/*!*/>/*!*/ labels, Model model, ProverInterface.Outcome proverOutcome) {
- if (CommandLineOptions.Clo.PrintErrorModel >= 1 && model != null) {
- model.Write(ErrorReporter.ModelWriter);
- ErrorReporter.ModelWriter.Flush();
- }
-
- // Timeout?
- if (proverOutcome != ProverInterface.Outcome.Invalid)
- return;
-
- candidatesToExpand = new List<int>();
- orderedStateIds = new List<Tuple<int, int>>();
- var cex = GenerateTrace(labels, model, 0, mainInfo.impl, mainInfo.mvInfo);
-
- if (underapproximationMode && cex != null) {
- //Debug.Assert(candidatesToExpand.All(calls.isSkipped));
- GetModelWithStates(model);
- callback.OnCounterexample(cex, null);
- this.PrintModel(model);
- }
- }
-
- private Counterexample GenerateTrace(IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel,
- int candidateId, Implementation procImpl, ModelViewInfo mvInfo) {
- Contract.Requires(cce.NonNullElements(labels));
- Contract.Requires(procImpl != null);
-
- Hashtable traceNodes = new Hashtable();
-
- if (!CommandLineOptions.Clo.SIBoolControlVC)
- {
- foreach (string s in labels)
- {
- Contract.Assert(s != null);
- var absylabel = calls.ParseRenamedAbsyLabel(s, candidateId);
-
- if (absylabel == null) continue;
-
- Absy absy;
-
- if (candidateId == 0)
- {
- absy = Label2Absy(absylabel);
- }
- else
- {
- absy = Label2Absy(procImpl.Name, absylabel);
- }
-
- if (traceNodes.ContainsKey(absy))
- System.Console.WriteLine("Warning: duplicate label: " + s + " read while tracing nodes");
- else
- traceNodes.Add(absy, null);
- }
- }
- else
- {
- Debug.Assert(CommandLineOptions.Clo.UseProverEvaluate, "Must use prover evaluate option with boolControlVC");
- var block = procImpl.Blocks[0];
- traceNodes.Add(block, null);
- while (true)
- {
- var gc = block.TransferCmd as GotoCmd;
- if (gc == null) break;
- Block next = null;
- foreach (var succ in gc.labelTargets)
- {
- var succtaken = (bool) theoremProver.Evaluate(calls.candiate2block2controlVar[candidateId][succ]);
- if (succtaken)
- {
- next = succ;
- traceNodes.Add(succ, null);
- break;
- }
- }
- Debug.Assert(next != null, "Must find a successor");
- Debug.Assert(traceNodes.ContainsKey(next), "CFG cannot be cyclic");
- block = next;
- }
- }
-
- List<Block> trace = new List<Block>();
- Block entryBlock = cce.NonNull(procImpl.Blocks[0]);
- Contract.Assert(entryBlock != null);
- Contract.Assert(traceNodes.Contains(entryBlock));
- trace.Add(entryBlock);
-
- var calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
- Counterexample newCounterexample = GenerateTraceRec(labels, errModel, mvInfo, candidateId, entryBlock, traceNodes, trace, calleeCounterexamples);
-
- return newCounterexample;
- }
-
- private Counterexample GenerateTraceRec(
- IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel, ModelViewInfo mvInfo,
- int candidateId,
- Block/*!*/ b, Hashtable/*!*/ traceNodes, List<Block>/*!*/ trace,
- Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples) {
- Contract.Requires(cce.NonNullElements(labels));
- Contract.Requires(b != null);
- Contract.Requires(traceNodes != null);
- Contract.Requires(trace != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(calleeCounterexamples));
- // After translation, all potential errors come from asserts.
- while (true) {
- List<Cmd> cmds = b.Cmds;
- TransferCmd transferCmd = cce.NonNull(b.TransferCmd);
- for (int i = 0; i < cmds.Count; i++) {
- Cmd cmd = cce.NonNull(cmds[i]);
-
- // Skip if 'cmd' not contained in the trace or not an assert
- if ((cmd is AssertCmd && traceNodes.Contains(cmd)) ||
- (cmd is AssumeCmd && QKeyValue.FindBoolAttribute((cmd as AssumeCmd).Attributes, "exitAssert")))
- {
- var acmd = cmd as AssertCmd;
- if (acmd == null) { acmd = new AssertCmd(Token.NoToken, Expr.True); }
- Counterexample newCounterexample = AssertCmdToCounterexample(acmd, transferCmd, trace, errModel, mvInfo, theoremProver.Context);
- newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
- return newCounterexample;
- }
-
- // Counterexample generation for inlined procedures
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- if (assumeCmd == null)
- continue;
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- if (naryExpr == null)
- continue;
- string calleeName = naryExpr.Fun.FunctionName;
- Contract.Assert(calleeName != null);
-
- BinaryOperator binOp = naryExpr.Fun as BinaryOperator;
- if (binOp != null && binOp.Op == BinaryOperator.Opcode.And) {
- Expr expr = naryExpr.Args[0];
- NAryExpr mvStateExpr = expr as NAryExpr;
- if (mvStateExpr != null && mvStateExpr.Fun.FunctionName == ModelViewInfo.MVState_FunctionDef.Name) {
- LiteralExpr x = mvStateExpr.Args[1] as LiteralExpr;
- orderedStateIds.Add(new Tuple<int, int>(candidateId, x.asBigNum.ToInt));
- }
- }
-
- if (calleeName.StartsWith(recordProcName) && (errModel != null || CommandLineOptions.Clo.UseProverEvaluate)) {
- var expr = calls.recordExpr2Var[new BoogieCallExpr(naryExpr, candidateId)];
-
- // Record concrete value of the argument to this procedure
- var args = new List<object>();
- if (errModel == null && CommandLineOptions.Clo.UseProverEvaluate)
- {
- object exprv;
- try
- {
- exprv = theoremProver.Evaluate(expr);
- }
- catch (Exception)
- {
- exprv = null;
- }
- args.Add(exprv);
- }
- else
- {
- if (expr is VCExprIntLit)
- {
- args.Add(errModel.MkElement((expr as VCExprIntLit).Val.ToString()));
- }
- else if (expr == VCExpressionGenerator.True)
- {
- args.Add(errModel.MkElement("true"));
- }
- else if (expr == VCExpressionGenerator.False)
- {
- args.Add(errModel.MkElement("false"));
- }
- else if (expr is VCExprVar)
- {
- var idExpr = expr as VCExprVar;
- string name = theoremProver.Context.Lookup(idExpr);
- Contract.Assert(name != null);
- Model.Func f = errModel.TryGetFunc(name);
- if (f != null)
- {
- args.Add(f.GetConstant());
- }
- }
- else
- {
- Contract.Assert(false);
- }
- }
- calleeCounterexamples[new TraceLocation(trace.Count - 1, i)] =
- new CalleeCounterexampleInfo(null, args);
- continue;
- }
-
- if (!implName2StratifiedInliningInfo.ContainsKey(calleeName))
- continue;
-
- Contract.Assert(calls != null);
-
- int calleeId = calls.boogieExpr2Id[new BoogieCallExpr(naryExpr, candidateId)];
-
- if (calls.currCandidates.Contains(calleeId)) {
- candidatesToExpand.Add(calleeId);
- }
- else {
- orderedStateIds.Add(new Tuple<int, int>(calleeId, StratifiedInliningErrorReporter.CALL));
- var calleeInfo = implName2StratifiedInliningInfo[calleeName];
- calleeCounterexamples[new TraceLocation(trace.Count - 1, i)] =
- new CalleeCounterexampleInfo(GenerateTrace(labels, errModel, calleeId, calleeInfo.impl, calleeInfo.mvInfo), new List<object>());
- orderedStateIds.Add(new Tuple<int, int>(candidateId, StratifiedInliningErrorReporter.RETURN));
- }
- }
-
- GotoCmd gotoCmd = transferCmd as GotoCmd;
- if (gotoCmd != null) {
- b = null;
- foreach (Block bb in cce.NonNull(gotoCmd.labelTargets)) {
- Contract.Assert(bb != null);
- if (traceNodes.Contains(bb)) {
- trace.Add(bb);
- b = bb;
- break;
- }
- }
- if (b != null) continue;
- }
- return null;
- }
- }
-
- public override Absy Label2Absy(string label) {
- //Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- int id = int.Parse(label);
- Contract.Assert(calls != null);
- return cce.NonNull((Absy)calls.mainLabel2absy[id]);
- }
-
- public Absy Label2Absy(string procName, string label) {
- Contract.Requires(label != null);
- Contract.Requires(procName != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- int id = int.Parse(label);
- Dictionary<int, Absy> l2a = cce.NonNull(implName2StratifiedInliningInfo[procName]).label2absy;
- return cce.NonNull((Absy)l2a[id]);
- }
-
- public override void OnProverWarning(string msg) {
- //Contract.Requires(msg != null);
- callback.OnWarning(msg);
- }
- }
-
- } // class StratifiedVCGen
-
- public class EmptyErrorHandler : ProverInterface.ErrorHandler
- {
- public override void OnModel(IList<string> labels, Model model, ProverInterface.Outcome proverOutcome)
- { }
- }
-
- public class InvalidProgramForSecureVc : Exception
- {
- public InvalidProgramForSecureVc(string msg) :
- base(msg) { }
- }
-
- public class SecureVCGen : VCGen
- {
- // Z3
- ProverInterface prover;
- // Handler
- ErrorReporter handler;
- // dump file
- public static TokenTextWriter outfile = null;
-
-
- public SecureVCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
- : base(program, logFilePath, appendLogFile, checkers)
- {
- prover = null;
- handler = null;
- if (CommandLineOptions.Clo.SecureVcGen != "" && outfile == null)
- {
- outfile = new TokenTextWriter(new StreamWriter(CommandLineOptions.Clo.SecureVcGen));
- CommandLineOptions.Clo.PrintInstrumented = true;
- var implsToVerify = new HashSet<string>(
- program.TopLevelDeclarations.OfType<Implementation>()
- .Where(impl => !impl.SkipVerification)
- .Select(impl => impl.Name));
-
- foreach (var decl in program.TopLevelDeclarations)
- {
- if (decl is NamedDeclaration && implsToVerify.Contains((decl as NamedDeclaration).Name))
- continue;
- decl.Emit(outfile, 0);
- }
- }
- }
-
- private Block GetExitBlock(Implementation impl)
- {
- var exitblocks = impl.Blocks.Where(blk => blk.TransferCmd is ReturnCmd);
- if (exitblocks.Count() == 1)
- return exitblocks.First();
- // create a new exit block
- var eb = new Block(Token.NoToken, "SVCeb", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- foreach (var b in exitblocks)
- {
- b.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { eb });
- }
- impl.Blocks.Add(eb);
- return eb;
- }
-
- //static int LocalVarCounter = 0;
- private LocalVariable GetNewLocal(Variable v, string suffix)
- {
- return new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
- string.Format("svc_{0}_{1}", v.Name, suffix), v.TypedIdent.Type));
- }
-
- private void GenVc(Implementation impl, VerifierCallback collector)
- {
- if (impl.Proc.Requires.Any())
- throw new InvalidProgramForSecureVc("SecureVc: Requires not supported");
- if(impl.LocVars.Any(v => isVisible(v)))
- throw new InvalidProgramForSecureVc("SecureVc: Visible Local variables not allowed");
-
- // Gather spec, remove existing ensures
- var secureAsserts = new List<AssertCmd>();
- var logicalAsserts = new List<AssertCmd>();
-
- foreach (var ens in impl.Proc.Ensures)
- {
- if(ens.Free)
- throw new InvalidProgramForSecureVc("SecureVc: Free Ensures not supported");
- var dd = new Duplicator();
- secureAsserts.Add(new AssertCmd(ens.tok, Expr.Not(ens.Condition)));
- logicalAsserts.Add(dd.VisitAssertCmd(new AssertCmd(ens.tok, ens.Condition)) as AssertCmd);
- }
- impl.Proc.Ensures.Clear();
-
- // Make a copy of the impl
- var dup = new Duplicator();
- var implDup = dup.VisitImplementation(impl);
-
- // Get exit block
- var eb = GetExitBlock(impl);
-
- // Create two blocks: one for secureAsserts, one for logical asserts
- var ebSecure = new Block(Token.NoToken, "svc_secure_asserts", new List<Cmd>(), new ReturnCmd(Token.NoToken));
- var ebLogical = new Block(Token.NoToken, "svc_logical_asserts", new List<Cmd>(), new ReturnCmd(Token.NoToken));
-
- eb.TransferCmd = new GotoCmd(eb.TransferCmd.tok, new List<Block> { ebSecure, ebLogical });
- impl.Blocks.Add(ebSecure);
- impl.Blocks.Add(ebLogical);
-
- // Rename spec, while create copies of the hidden variables
- var substOld = new Dictionary<Variable, Expr>();
- var substVarSpec = new Dictionary<Variable, Expr>();
- var substVarPath = new Dictionary<Variable, Expr>();
- foreach (var g in program.GlobalVariables)
- {
- if (!isHidden(g)) continue;
- var lv = GetNewLocal(g, "In");
- impl.LocVars.Add(lv);
- substOld.Add(g, Expr.Ident(lv));
- }
-
- for(int i = 0; i < impl.InParams.Count; i++)
- {
- var v = impl.Proc.InParams[i];
- if (!isHidden(v))
- {
- substVarSpec.Add(impl.Proc.InParams[i], Expr.Ident(impl.InParams[i]));
- continue;
- }
-
- var lv = GetNewLocal(v, "In");
- impl.LocVars.Add(lv);
- substVarSpec.Add(v, Expr.Ident(lv));
- substVarPath.Add(impl.InParams[i], Expr.Ident(lv));
- }
-
- for (int i = 0; i < impl.OutParams.Count; i++)
- {
- var v = impl.Proc.OutParams[i];
- if (!isHidden(v))
- {
- substVarSpec.Add(impl.Proc.OutParams[i], Expr.Ident(impl.OutParams[i]));
- continue;
- }
-
- var lv = GetNewLocal(v, "Out");
- impl.LocVars.Add(lv);
- substVarSpec.Add(v, Expr.Ident(lv));
- substVarPath.Add(impl.OutParams[i], Expr.Ident(lv));
- }
-
- foreach (var g in program.GlobalVariables)
- {
- if (!isHidden(g)) continue;
- if (!impl.Proc.Modifies.Any(ie => ie.Name == g.Name)) continue;
-
- var lv = GetNewLocal(g, "Out");
- impl.LocVars.Add(lv);
- substVarSpec.Add(g, Expr.Ident(lv));
- substVarPath.Add(g, Expr.Ident(lv));
- }
-
- secureAsserts = secureAsserts.ConvertAll(ac =>
- Substituter.ApplyReplacingOldExprs(
- Substituter.SubstitutionFromHashtable(substVarSpec),
- Substituter.SubstitutionFromHashtable(substOld),
- ac) as AssertCmd);
-
- var substVarProcToImpl = new Dictionary<Variable, Expr>();
- for (int i = 0; i < impl.InParams.Count; i++)
- substVarProcToImpl.Add(impl.Proc.InParams[i], Expr.Ident(impl.InParams[i]));
-
- for (int i = 0; i < impl.OutParams.Count; i++)
- substVarProcToImpl.Add(impl.Proc.OutParams[i], Expr.Ident(impl.OutParams[i]));
-
- logicalAsserts = logicalAsserts.ConvertAll(ac =>
- Substituter.Apply(Substituter.SubstitutionFromHashtable(substVarProcToImpl), ac)
- as AssertCmd);
-
- // Paths
- foreach (var path in GetAllPaths(implDup))
- {
- var wp = ComputeWP(implDup, path);
-
- // replace hidden variables to match those used in the spec
- wp = Substituter.ApplyReplacingOldExprs(
- Substituter.SubstitutionFromHashtable(substVarPath),
- Substituter.SubstitutionFromHashtable(substOld),
- wp);
-
- ebSecure.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(wp)));
- }
-
- ebSecure.Cmds.AddRange(secureAsserts);
- ebLogical.Cmds.AddRange(logicalAsserts);
-
- if (outfile != null)
- {
- impl.Proc.Emit(outfile, 0);
- impl.Emit(outfile, 0);
- }
-
- ModelViewInfo mvInfo;
- ConvertCFG2DAG(impl);
- var gotoCmdOrigins = PassifyImpl(impl, out mvInfo);
-
- var gen = prover.VCExprGen;
- var exprGen = prover.Context.ExprGen;
- var translator = prover.Context.BoogieExprTranslator;
-
- var label2absy = new Dictionary<int, Absy>();
- VCGen.CodeExprConversionClosure cc = new VCGen.CodeExprConversionClosure(label2absy, prover.Context);
- translator.SetCodeExprConverter(cc.CodeExprToVerificationCondition);
- var implVc = gen.Not(GenerateVCAux(impl, null, label2absy, prover.Context));
-
- handler = new VCGen.ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, incarnationOriginMap, collector, mvInfo, prover.Context, program);
-
- prover.Assert(implVc, true);
- }
-
- Expr ComputeWP(Implementation impl, List<Cmd> path)
- {
- Expr expr = Expr.True;
-
- // create constants for out varibles
- var subst = new Dictionary<Variable, Expr>();
- foreach (var g in impl.Proc.Modifies)
- {
- var c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
- "svc_out_const_" + g.Name, g.Decl.TypedIdent.Type));
- subst.Add(c, g);
- expr = Expr.And(expr, Expr.Eq(Expr.Ident(c), g));
- }
-
- foreach (var v in impl.OutParams)
- {
- var c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
- "svc_out_const_" + v.Name, v.TypedIdent.Type));
- subst.Add(c, Expr.Ident(v));
- expr = Expr.And(expr, Expr.Eq(Expr.Ident(c), Expr.Ident(v)));
- }
-
- // we need this technicality
- var subst1 = new Dictionary<Variable, Expr>();
- foreach (var g in program.GlobalVariables)
- {
- subst1.Add(g, new OldExpr(Token.NoToken, Expr.Ident(g)));
- }
-
- // Implicitly close with havoc of all the locals and OutParams
- path.Insert(0, new HavocCmd(Token.NoToken, new List<IdentifierExpr>(
- impl.LocVars.Select(v => Expr.Ident(v)).Concat(
- impl.OutParams.Select(v => Expr.Ident(v))))));
-
- for (int i = path.Count - 1; i >= 0; i--)
- {
- var cmd = path[i];
- if (cmd is AssumeCmd)
- {
- expr = Expr.And(expr, (cmd as AssumeCmd).Expr);
- }
- else if (cmd is AssignCmd)
- {
- var h = new Dictionary<Variable, Expr>();
- var acmd = cmd as AssignCmd;
- for (int j = 0; j < acmd.Lhss.Count; j++)
- {
- h.Add(acmd.Lhss[j].DeepAssignedVariable, acmd.Rhss[j]);
- }
- var s = Substituter.SubstitutionFromHashtable(h);
- expr = Substituter.Apply(s, expr);
- }
- else if (cmd is HavocCmd)
- {
- var h = new Dictionary<Variable, Expr>();
- var formals = new List<Variable>();
-
- var vc = new VariableCollector();
- vc.VisitExpr(expr);
-
- foreach (var ie in (cmd as HavocCmd).Vars)
- {
- if (!vc.usedVars.Contains(ie.Decl)) continue;
- var f = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken,
- ie.Decl.Name + "_formal", ie.Decl.TypedIdent.Type));
- h.Add(ie.Decl, Expr.Ident(f));
- formals.Add(f);
- }
- if (!formals.Any())
- continue;
- var s = Substituter.SubstitutionFromHashtable(h);
- expr = Substituter.Apply(s, expr);
- expr = new ExistsExpr(Token.NoToken, formals, expr);
- }
- else
- {
- throw new InvalidProgramForSecureVc(string.Format("Unhandled cmd: {0}", cmd));
- }
- }
-
- // Implicitly close with havoc of all the locals and OutParams
-
-
-
- expr = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst1), expr);
- expr = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst),
- Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()), expr);
- expr.Typecheck(new TypecheckingContext(null));
- return expr;
- }
-
- // Generate all paths in the impl
- IEnumerable<List<Cmd>> GetAllPaths(Implementation impl)
- {
- var stk = new Stack<Tuple<Block, int>>();
- stk.Push(Tuple.Create(impl.Blocks[0], 0));
-
- while (stk.Any())
- {
- var tup = stk.Peek();
- if (tup.Item1.TransferCmd is ReturnCmd)
- {
- var ret = new List<Cmd>();
- var ls = stk.ToList();
- ls.Iter(t => ret.AddRange(t.Item1.Cmds));
- yield return ret;
-
- stk.Pop();
- continue;
- }
-
- stk.Pop();
-
- var gc = tup.Item1.TransferCmd as GotoCmd;
- if (gc.labelTargets.Count <= tup.Item2)
- continue;
-
- stk.Push(Tuple.Create(tup.Item1, tup.Item2 + 1));
- stk.Push(Tuple.Create(gc.labelTargets[tup.Item2], 0));
- }
- yield break;
- }
-
- bool isHidden(Variable v)
- {
- return QKeyValue.FindBoolAttribute(v.Attributes, "hidden");
- }
-
- bool isVisible(Variable v)
- {
- return !isHidden(v);
- }
-
- public override Outcome VerifyImplementation(Implementation/*!*/ impl, VerifierCallback/*!*/ callback)
- {
- Debug.Assert(this.program == program);
-
- // Record current time
- var startTime = DateTime.UtcNow;
-
- CommandLineOptions.Clo.ProverCCLimit = 1;
- prover = ProverInterface.CreateProver(program, logFilePath, appendLogFile, CommandLineOptions.Clo.ProverKillTime);
-
- // Flush any axioms that came with the program before we start SI on this implementation
- prover.AssertAxioms();
-
- GenVc(impl, callback);
-
- prover.Check();
- var outcome = prover.CheckOutcomeCore(handler);
- //var outcome = ProverInterface.Outcome.Valid;
-
- prover.Close();
-
-
-
- //Console.WriteLine("Answer = {0}", outcome);
-
- return ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
- }
- }
-
-} // namespace VC
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC {
+ using Bpl = Microsoft.Boogie;
+
+ public class StratifiedVC {
+ public StratifiedInliningInfo info;
+ public int id;
+ public List<VCExprVar> interfaceExprVars;
+
+ // boolControlVC (block -> its bool variable)
+ public Dictionary<Block, VCExpr> blockToControlVar;
+ // While using labels (block -> its label)
+ public Dictionary<Absy, string> block2label;
+
+ public Dictionary<Block, List<StratifiedCallSite>> callSites;
+ public Dictionary<Block, List<StratifiedCallSite>> recordProcCallSites;
+ public VCExpr vcexpr;
+
+ // Must-Reach Information
+ Dictionary<Block, VCExprVar> mustReachVar;
+ List<VCExprLetBinding> mustReachBindings;
+
+ public StratifiedVC(StratifiedInliningInfo siInfo, HashSet<string> procCalls) {
+ info = siInfo;
+ info.GenerateVC();
+ var vcgen = info.vcgen;
+ var prover = vcgen.prover;
+ VCExpressionGenerator gen = prover.VCExprGen;
+ var bet = prover.Context.BoogieExprTranslator;
+
+ vcexpr = info.vcexpr;
+ id = vcgen.CreateNewId();
+ interfaceExprVars = new List<VCExprVar>();
+ Dictionary<VCExprVar, VCExpr> substDict = new Dictionary<VCExprVar, VCExpr>();
+ foreach (VCExprVar v in info.interfaceExprVars) {
+ VCExprVar newVar = vcgen.CreateNewVar(v.Type);
+ interfaceExprVars.Add(newVar);
+ substDict.Add(v, newVar);
+ }
+ foreach (VCExprVar v in info.privateExprVars) {
+ substDict.Add(v, vcgen.CreateNewVar(v.Type));
+ }
+ if(info.controlFlowVariable != null)
+ substDict.Add(bet.LookupVariable(info.controlFlowVariable), gen.Integer(BigNum.FromInt(id)));
+ VCExprSubstitution subst = new VCExprSubstitution(substDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
+ SubstitutingVCExprVisitor substVisitor = new SubstitutingVCExprVisitor(prover.VCExprGen);
+ vcexpr = substVisitor.Mutate(vcexpr, subst);
+
+ // For BoolControlVC generation
+ if (info.blockToControlVar != null)
+ {
+ blockToControlVar = new Dictionary<Block, VCExpr>();
+ foreach (var tup in info.blockToControlVar)
+ blockToControlVar.Add(tup.Key, substDict[tup.Value]);
+ }
+
+ // labels
+ if (info.label2absy != null)
+ {
+ block2label = new Dictionary<Absy, string>();
+ vcexpr = RenameVCExprLabels.Apply(vcexpr, info.vcgen.prover.VCExprGen, info.label2absy, block2label);
+ }
+
+ if(procCalls != null)
+ vcexpr = RemoveProcedureCalls.Apply(vcexpr, info.vcgen.prover.VCExprGen, procCalls);
+
+ callSites = new Dictionary<Block, List<StratifiedCallSite>>();
+ foreach (Block b in info.callSites.Keys) {
+ callSites[b] = new List<StratifiedCallSite>();
+ foreach (CallSite cs in info.callSites[b]) {
+ callSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst));
+ }
+ }
+
+ recordProcCallSites = new Dictionary<Block, List<StratifiedCallSite>>();
+ foreach (Block b in info.recordProcCallSites.Keys) {
+ recordProcCallSites[b] = new List<StratifiedCallSite>();
+ foreach (CallSite cs in info.recordProcCallSites[b]) {
+ recordProcCallSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst));
+ }
+ }
+ }
+
+ public VCExpr MustReach(Block block)
+ {
+ Contract.Assert(!CommandLineOptions.Clo.UseLabels);
+
+ // This information is computed lazily
+ if (mustReachBindings == null)
+ {
+ var vcgen = info.vcgen;
+ var gen = vcgen.prover.VCExprGen;
+ var impl = info.impl;
+ mustReachVar = new Dictionary<Block, VCExprVar>();
+ mustReachBindings = new List<VCExprLetBinding>();
+ foreach (Block b in impl.Blocks)
+ mustReachVar[b] = vcgen.CreateNewVar(Bpl.Type.Bool);
+
+ var dag = new Graph<Block>();
+ dag.AddSource(impl.Blocks[0]);
+ foreach (Block b in impl.Blocks)
+ {
+ var gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null)
+ foreach (Block dest in gtc.labelTargets)
+ dag.AddEdge(dest, b);
+ }
+ IEnumerable sortedNodes = dag.TopologicalSort();
+
+ foreach (Block currBlock in dag.TopologicalSort())
+ {
+ if (currBlock == impl.Blocks[0])
+ {
+ mustReachBindings.Add(gen.LetBinding(mustReachVar[currBlock], VCExpressionGenerator.True));
+ continue;
+ }
+
+ VCExpr expr = VCExpressionGenerator.False;
+ foreach (var pred in dag.Successors(currBlock))
+ {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(gen.Integer(BigNum.FromInt(id)), gen.Integer(BigNum.FromInt(pred.UniqueId)));
+ VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(currBlock.UniqueId)));
+ expr = gen.Or(expr, gen.And(mustReachVar[pred], controlTransferExpr));
+ }
+ mustReachBindings.Add(gen.LetBinding(mustReachVar[currBlock], expr));
+ }
+ }
+
+ Contract.Assert(mustReachVar.ContainsKey(block));
+ return info.vcgen.prover.VCExprGen.Let(mustReachBindings, mustReachVar[block]);
+ }
+
+ public List<StratifiedCallSite> CallSites {
+ get {
+ var ret = new List<StratifiedCallSite>();
+ foreach (var b in callSites.Keys) {
+ foreach (var cs in callSites[b]) {
+ ret.Add(cs);
+ }
+ }
+ return ret;
+ }
+ }
+
+ public List<StratifiedCallSite> RecordProcCallSites {
+ get {
+ var ret = new List<StratifiedCallSite>();
+ foreach (var b in recordProcCallSites.Keys) {
+ foreach (var cs in recordProcCallSites[b]) {
+ ret.Add(cs);
+ }
+ }
+ return ret;
+ }
+ }
+
+ public override string ToString()
+ {
+ return info.impl.Name;
+ }
+ }
+
+ // Rename all labels in a VC to (globally) fresh labels
+ class RenameVCExprLabels : MutatingVCExprVisitor<bool>
+ {
+ Dictionary<int, Absy> label2absy;
+ Dictionary<Absy, string> absy2newlabel;
+ static int counter = 11;
+
+ RenameVCExprLabels(VCExpressionGenerator gen, Dictionary<int, Absy> label2absy, Dictionary<Absy, string> absy2newlabel)
+ : base(gen)
+ {
+ this.label2absy = label2absy;
+ this.absy2newlabel = absy2newlabel;
+ }
+
+ public static VCExpr Apply(VCExpr expr, VCExpressionGenerator gen, Dictionary<int, Absy> label2absy, Dictionary<Absy, string> absy2newlabel)
+ {
+ return (new RenameVCExprLabels(gen, label2absy, absy2newlabel)).Mutate(expr, true);
+ }
+
+ // Finds labels and changes them to a globally unique label:
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
+ List<VCExpr/*!*/>/*!*/ newSubExprs,
+ bool changed,
+ bool arg)
+ {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr ret;
+ if (changed)
+ ret = Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ ret = originalNode;
+
+ VCExprLabelOp lop = originalNode.Op as VCExprLabelOp;
+ if (lop == null) return ret;
+ if (!(ret is VCExprNAry)) return ret;
+ VCExprNAry retnary = (VCExprNAry)ret;
+
+ // remove the sign
+ var nosign = 0;
+ if (!Int32.TryParse(lop.label.Substring(1), out nosign))
+ return ret;
+
+ if (!label2absy.ContainsKey(nosign))
+ return ret;
+
+ string newLabel = "SI" + counter.ToString();
+ counter++;
+ absy2newlabel[label2absy[nosign]] = newLabel;
+
+ if (lop.pos)
+ {
+ return Gen.LabelPos(newLabel, retnary[0]);
+ }
+ else
+ {
+ return Gen.LabelNeg(newLabel, retnary[0]);
+ }
+
+ }
+ }
+
+ // Remove the uninterpreted function calls that substitute procedure calls
+ class RemoveProcedureCalls : MutatingVCExprVisitor<bool>
+ {
+ HashSet<string> procNames;
+
+ RemoveProcedureCalls(VCExpressionGenerator gen, HashSet<string> procNames)
+ : base(gen)
+ {
+ this.procNames = procNames;
+ }
+
+ public static VCExpr Apply(VCExpr expr, VCExpressionGenerator gen, HashSet<string> procNames)
+ {
+ return (new RemoveProcedureCalls(gen, procNames)).Mutate(expr, true);
+ }
+
+ // Finds labels and changes them to a globally unique label:
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
+ List<VCExpr/*!*/>/*!*/ newSubExprs,
+ bool changed,
+ bool arg)
+ {
+ //Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr ret;
+ if (changed)
+ ret = Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ ret = originalNode;
+
+ if (!(ret is VCExprNAry)) return ret;
+ VCExprNAry retnary = (VCExprNAry)ret;
+ if (!(retnary.Op is VCExprBoogieFunctionOp))
+ return ret;
+
+ var fcall = (retnary.Op as VCExprBoogieFunctionOp).Func.Name;
+ if (procNames.Contains(fcall))
+ return VCExpressionGenerator.True;
+ return ret;
+ }
+ }
+
+
+ public class CallSite {
+ public string calleeName;
+ public List<VCExpr> interfaceExprs;
+ public Block block;
+ public int numInstr; // for TraceLocation
+ public VCExprVar callSiteVar;
+ public QKeyValue Attributes; // attributes on the call cmd
+ public CallSite(string callee, List<VCExpr> interfaceExprs, VCExprVar callSiteVar, Block block, int numInstr, QKeyValue Attributes)
+ {
+ this.calleeName = callee;
+ this.interfaceExprs = interfaceExprs;
+ this.callSiteVar = callSiteVar;
+ this.block = block;
+ this.numInstr = numInstr;
+ this.Attributes = Attributes;
+ }
+ }
+
+ public class StratifiedCallSite {
+ public CallSite callSite;
+ public List<VCExpr> interfaceExprs;
+ public VCExpr callSiteExpr;
+
+ public StratifiedCallSite(CallSite cs, SubstitutingVCExprVisitor substVisitor, VCExprSubstitution subst) {
+ callSite = cs;
+ interfaceExprs = new List<VCExpr>();
+ foreach (VCExpr v in cs.interfaceExprs) {
+ interfaceExprs.Add(substVisitor.Mutate(v, subst));
+ }
+ if (callSite.callSiteVar != null)
+ callSiteExpr = substVisitor.Mutate(callSite.callSiteVar, subst);
+ }
+
+ public VCExpr Attach(StratifiedVC svc) {
+ Contract.Assert(interfaceExprs.Count == svc.interfaceExprVars.Count);
+ StratifiedInliningInfo info = svc.info;
+ ProverInterface prover = info.vcgen.prover;
+ VCExpressionGenerator gen = prover.VCExprGen;
+
+ Dictionary<VCExprVar, VCExpr> substDict = new Dictionary<VCExprVar, VCExpr>();
+ for (int i = 0; i < svc.interfaceExprVars.Count; i++) {
+ VCExprVar v = svc.interfaceExprVars[i];
+ substDict.Add(v, interfaceExprs[i]);
+ }
+ VCExprSubstitution subst = new VCExprSubstitution(substDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
+ SubstitutingVCExprVisitor substVisitor = new SubstitutingVCExprVisitor(prover.VCExprGen);
+ svc.vcexpr = substVisitor.Mutate(svc.vcexpr, subst);
+ foreach (StratifiedCallSite scs in svc.CallSites) {
+ List<VCExpr> newInterfaceExprs = new List<VCExpr>();
+ foreach (VCExpr expr in scs.interfaceExprs) {
+ newInterfaceExprs.Add(substVisitor.Mutate(expr, subst));
+ }
+ scs.interfaceExprs = newInterfaceExprs;
+ }
+ foreach (StratifiedCallSite scs in svc.RecordProcCallSites) {
+ List<VCExpr> newInterfaceExprs = new List<VCExpr>();
+ foreach (VCExpr expr in scs.interfaceExprs) {
+ newInterfaceExprs.Add(substVisitor.Mutate(expr, subst));
+ }
+ scs.interfaceExprs = newInterfaceExprs;
+ }
+ //return gen.Implies(callSiteExpr, svc.vcexpr);
+ return svc.vcexpr;
+ }
+
+ public override string ToString()
+ {
+ return callSite.calleeName;
+ }
+ }
+
+ public class StratifiedInliningInfo {
+ public StratifiedVCGenBase vcgen;
+ public Implementation impl;
+ public Function function;
+ public Variable controlFlowVariable;
+ public Cmd exitAssertCmd;
+ public VCExpr vcexpr;
+ public List<VCExprVar> interfaceExprVars;
+ public List<VCExprVar> privateExprVars;
+ public Dictionary<int, Absy> label2absy;
+ public ModelViewInfo mvInfo;
+ public Dictionary<Block, List<CallSite>> callSites;
+ public Dictionary<Block, List<CallSite>> recordProcCallSites;
+ public bool initialized { get; private set; }
+ // Instrumentation to apply after PassiveImpl, but before VCGen
+ Action<Implementation> PassiveImplInstrumentation;
+
+ // boolControlVC (block -> its Bool variable)
+ public Dictionary<Block, VCExprVar> blockToControlVar;
+
+ public StratifiedInliningInfo(Implementation implementation, StratifiedVCGenBase stratifiedVcGen, Action<Implementation> PassiveImplInstrumentation) {
+ vcgen = stratifiedVcGen;
+ impl = implementation;
+ this.PassiveImplInstrumentation = PassiveImplInstrumentation;
+
+ List<Variable> functionInterfaceVars = new List<Variable>();
+ foreach (Variable v in vcgen.program.GlobalVariables) {
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
+ }
+ foreach (Variable v in impl.InParams) {
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
+ }
+ foreach (Variable v in impl.OutParams) {
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true));
+ }
+ foreach (IdentifierExpr e in impl.Proc.Modifies) {
+ if (e.Decl == null) continue;
+ functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", e.Decl.TypedIdent.Type), true));
+ }
+ Formal returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false);
+ function = new Function(Token.NoToken, impl.Name, functionInterfaceVars, returnVar);
+ vcgen.prover.Context.DeclareFunction(function, "");
+
+ List<Expr> exprs = new List<Expr>();
+ foreach (Variable v in vcgen.program.GlobalVariables) {
+ Contract.Assert(v != null);
+ exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v)));
+ }
+ foreach (Variable v in impl.Proc.InParams) {
+ Contract.Assert(v != null);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ foreach (Variable v in impl.Proc.OutParams) {
+ Contract.Assert(v != null);
+ exprs.Add(new IdentifierExpr(Token.NoToken, v));
+ }
+ foreach (IdentifierExpr ie in impl.Proc.Modifies) {
+ Contract.Assert(ie != null);
+ if (ie.Decl == null)
+ continue;
+ exprs.Add(ie);
+ }
+ Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs);
+ impl.Proc.Ensures.Add(new Ensures(Token.NoToken, true, freePostExpr, "", new QKeyValue(Token.NoToken, "si_fcall", new List<object>(), null)));
+
+ initialized = false;
+ }
+
+ public void GenerateVCBoolControl()
+ {
+ Debug.Assert(!initialized);
+ Debug.Assert(CommandLineOptions.Clo.SIBoolControlVC);
+
+ // fix names for exit variables
+ var outputVariables = new List<Variable>();
+ var assertConjuncts = new List<Expr>();
+ foreach (Variable v in impl.OutParams)
+ {
+ Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
+ outputVariables.Add(c);
+ Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
+ assertConjuncts.Add(eqExpr);
+ }
+ foreach (IdentifierExpr e in impl.Proc.Modifies)
+ {
+ if (e.Decl == null) continue;
+ Variable v = e.Decl;
+ Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
+ outputVariables.Add(c);
+ Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
+ assertConjuncts.Add(eqExpr);
+ }
+ exitAssertCmd = new AssumeCmd(Token.NoToken, Expr.BinaryTreeAnd(assertConjuncts));
+ (exitAssertCmd as AssumeCmd).Attributes = new QKeyValue(Token.NoToken, "exitAssert", new List<object>(), null);
+
+ // no need for label2absy
+ label2absy = new Dictionary<int, Absy>();
+
+ // Passify
+ Program program = vcgen.program;
+ ProverInterface proverInterface = vcgen.prover;
+ vcgen.ConvertCFG2DAG(impl);
+ vcgen.PassifyImpl(impl, out mvInfo);
+
+ VCExpressionGenerator gen = proverInterface.VCExprGen;
+ var exprGen = proverInterface.Context.ExprGen;
+ var translator = proverInterface.Context.BoogieExprTranslator;
+
+ // add a boolean variable at each call site
+ vcgen.InstrumentCallSites(impl);
+
+ // typecheck
+ var tc = new TypecheckingContext(null);
+ impl.Typecheck(tc);
+
+ ///////////////////
+ // Generate the VC
+ ///////////////////
+
+ // block -> bool variable
+ blockToControlVar = new Dictionary<Block, VCExprVar>();
+ foreach (var b in impl.Blocks)
+ blockToControlVar.Add(b, gen.Variable(b.Label + "_holds", Bpl.Type.Bool));
+
+ vcexpr = VCExpressionGenerator.True;
+ foreach (var b in impl.Blocks)
+ {
+ // conjoin all assume cmds
+ VCExpr c = VCExpressionGenerator.True;
+ foreach (var cmd in b.Cmds)
+ {
+ var acmd = cmd as AssumeCmd;
+ if (acmd == null)
+ {
+ Debug.Assert(cmd is AssertCmd && (cmd as AssertCmd).Expr is LiteralExpr &&
+ ((cmd as AssertCmd).Expr as LiteralExpr).IsTrue);
+ continue;
+ }
+ var expr = translator.Translate(acmd.Expr);
+ // Label the assume if it is a procedure call
+ NAryExpr naryExpr = acmd.Expr as NAryExpr;
+ if (naryExpr != null && naryExpr.Fun is FunctionCall)
+ {
+ var id = acmd.UniqueId;
+ label2absy[id] = acmd;
+ expr = gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), expr);
+ }
+
+ c = gen.AndSimp(c, expr);
+ }
+
+ // block implies a disjunction of successors
+ Debug.Assert(!(b.TransferCmd is ReturnExprCmd), "Not supported");
+ var gc = b.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ VCExpr succ = VCExpressionGenerator.False;
+ foreach (var sb in gc.labelTargets)
+ succ = gen.OrSimp(succ, blockToControlVar[sb]);
+ c = gen.AndSimp(c, succ);
+ }
+ else
+ {
+ // nothing to do
+ }
+ vcexpr = gen.AndSimp(vcexpr, gen.Eq(blockToControlVar[b], c));
+ }
+ // assert start block
+ vcexpr = gen.AndSimp(vcexpr, blockToControlVar[impl.Blocks[0]]);
+
+ //Console.WriteLine("VC of {0}: {1}", impl.Name, vcexpr);
+ // Collect other information
+ callSites = vcgen.CollectCallSites(impl);
+ recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl);
+
+ // record interface variables
+ privateExprVars = new List<VCExprVar>();
+ foreach (Variable v in impl.LocVars)
+ {
+ privateExprVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in impl.OutParams)
+ {
+ privateExprVars.Add(translator.LookupVariable(v));
+ }
+ privateExprVars.AddRange(blockToControlVar.Values);
+
+ interfaceExprVars = new List<VCExprVar>();
+ foreach (Variable v in program.GlobalVariables)
+ {
+ interfaceExprVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in impl.InParams)
+ {
+ interfaceExprVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in outputVariables)
+ {
+ interfaceExprVars.Add(translator.LookupVariable(v));
+ }
+ }
+
+ public void GenerateVC() {
+ if (initialized) return;
+ if (CommandLineOptions.Clo.SIBoolControlVC)
+ {
+ GenerateVCBoolControl();
+ initialized = true;
+ return;
+ }
+ List<Variable> outputVariables = new List<Variable>();
+ List<Expr> assertConjuncts = new List<Expr>();
+ foreach (Variable v in impl.OutParams) {
+ Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
+ outputVariables.Add(c);
+ Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
+ assertConjuncts.Add(eqExpr);
+ }
+ foreach (IdentifierExpr e in impl.Proc.Modifies) {
+ if (e.Decl == null) continue;
+ Variable v = e.Decl;
+ Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
+ outputVariables.Add(c);
+ Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
+ assertConjuncts.Add(eqExpr);
+ }
+ exitAssertCmd = new AssertCmd(Token.NoToken, Expr.Not(Expr.BinaryTreeAnd(assertConjuncts)));
+
+ Program program = vcgen.program;
+ ProverInterface proverInterface = vcgen.prover;
+ vcgen.ConvertCFG2DAG(impl);
+ vcgen.PassifyImpl(impl, out mvInfo);
+
+ VCExpressionGenerator gen = proverInterface.VCExprGen;
+ var exprGen = proverInterface.Context.ExprGen;
+ var translator = proverInterface.Context.BoogieExprTranslator;
+
+ VCExpr controlFlowVariableExpr = null;
+ if (!CommandLineOptions.Clo.UseLabels) {
+ controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
+ controlFlowVariableExpr = translator.LookupVariable(controlFlowVariable);
+ }
+
+ vcgen.InstrumentCallSites(impl);
+
+ if (PassiveImplInstrumentation != null)
+ PassiveImplInstrumentation(impl);
+
+ label2absy = new Dictionary<int, Absy>();
+ VCGen.CodeExprConversionClosure cc = new VCGen.CodeExprConversionClosure(label2absy, proverInterface.Context);
+ translator.SetCodeExprConverter(cc.CodeExprToVerificationCondition);
+ vcexpr = gen.Not(vcgen.GenerateVCAux(impl, controlFlowVariableExpr, label2absy, proverInterface.Context));
+
+ if (controlFlowVariableExpr != null)
+ {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(controlFlowVariableExpr, exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vcexpr = exprGen.And(eqExpr, vcexpr);
+ }
+
+ callSites = vcgen.CollectCallSites(impl);
+ recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl);
+
+ privateExprVars = new List<VCExprVar>();
+ foreach (Variable v in impl.LocVars) {
+ privateExprVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in impl.OutParams) {
+ privateExprVars.Add(translator.LookupVariable(v));
+ }
+
+ interfaceExprVars = new List<VCExprVar>();
+ foreach (Variable v in program.GlobalVariables) {
+ interfaceExprVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in impl.InParams) {
+ interfaceExprVars.Add(translator.LookupVariable(v));
+ }
+ foreach (Variable v in outputVariables) {
+ interfaceExprVars.Add(translator.LookupVariable(v));
+ }
+
+ initialized = true;
+ }
+ }
+
+ public abstract class StratifiedVCGenBase : VCGen {
+ public readonly static string recordProcName = "boogie_si_record";
+ public readonly static string callSiteVarAttr = "callSiteVar";
+ public Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo;
+ public ProverInterface prover;
+
+ public StratifiedVCGenBase(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers, Action<Implementation> PassiveImplInstrumentation)
+ : base(program, logFilePath, appendLogFile, checkers) {
+ implName2StratifiedInliningInfo = new Dictionary<string, StratifiedInliningInfo>();
+ prover = ProverInterface.CreateProver(program, logFilePath, appendLogFile, CommandLineOptions.Clo.ProverKillTime);
+ foreach (var impl in program.Implementations) {
+ implName2StratifiedInliningInfo[impl.Name] = new StratifiedInliningInfo(impl, this, PassiveImplInstrumentation);
+ }
+ GenerateRecordFunctions();
+ }
+
+ private void GenerateRecordFunctions() {
+ foreach (var proc in program.Procedures) {
+ if (!proc.Name.StartsWith(recordProcName)) continue;
+ Contract.Assert(proc.InParams.Count == 1);
+
+ // Make a new function
+ TypedIdent ti = new TypedIdent(Token.NoToken, "", Bpl.Type.Bool);
+ Contract.Assert(ti != null);
+ Formal returnVar = new Formal(Token.NoToken, ti, false);
+ Contract.Assert(returnVar != null);
+
+ // Get record type
+ var argtype = proc.InParams[0].TypedIdent.Type;
+
+ var ins = new List<Variable>();
+ ins.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", argtype), true));
+
+ var recordFunc = new Function(Token.NoToken, proc.Name, ins, returnVar);
+ prover.Context.DeclareFunction(recordFunc, "");
+
+ var exprs = new List<Expr>();
+ exprs.Add(new IdentifierExpr(Token.NoToken, proc.InParams[0]));
+
+ Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(recordFunc), exprs);
+ proc.Ensures.Add(new Ensures(true, freePostExpr));
+ }
+ }
+
+ public override void Close() {
+ prover.Close();
+ base.Close();
+ }
+
+ public void InstrumentCallSites(Implementation implementation) {
+ var callSiteId = 0;
+ foreach (Block block in implementation.Blocks) {
+ List<Cmd> newCmds = new List<Cmd>();
+ for (int i = 0; i < block.Cmds.Count; i++) {
+ Cmd cmd = block.Cmds[i];
+ newCmds.Add(cmd);
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd == null) continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null) continue;
+ if (!implName2StratifiedInliningInfo.ContainsKey(naryExpr.Fun.FunctionName)) continue;
+ Variable callSiteVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "SICS" + callSiteId, Microsoft.Boogie.Type.Bool));
+ implementation.LocVars.Add(callSiteVar);
+ var toInsert = new AssumeCmd(Token.NoToken, new IdentifierExpr(Token.NoToken, callSiteVar),
+ new QKeyValue(Token.NoToken, callSiteVarAttr, new List<object>(), null));
+ newCmds.Add(toInsert);
+ callSiteId++;
+ }
+ block.Cmds = newCmds;
+ }
+ }
+
+ public Dictionary<Block, List<CallSite>> CollectCallSites(Implementation implementation) {
+ var callSites = new Dictionary<Block, List<CallSite>>();
+ foreach (Block block in implementation.Blocks) {
+ for (int i = 0; i < block.Cmds.Count; i++) {
+ Cmd cmd = block.Cmds[i];
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd == null) continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null) continue;
+ if (!implName2StratifiedInliningInfo.ContainsKey(naryExpr.Fun.FunctionName)) continue;
+ List<VCExpr> interfaceExprs = new List<VCExpr>();
+ foreach (Expr e in naryExpr.Args) {
+ interfaceExprs.Add(prover.Context.BoogieExprTranslator.Translate(e));
+ }
+ int instr = i;
+ i++;
+ AssumeCmd callSiteAssumeCmd = (AssumeCmd)block.Cmds[i];
+ IdentifierExpr iexpr = (IdentifierExpr) callSiteAssumeCmd.Expr;
+ CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, prover.Context.BoogieExprTranslator.LookupVariable(iexpr.Decl), block, instr, assumeCmd.Attributes);
+ if (!callSites.ContainsKey(block))
+ callSites[block] = new List<CallSite>();
+ callSites[block].Add(cs);
+ }
+ }
+ return callSites;
+ }
+
+ public Dictionary<Block, List<CallSite>> CollectRecordProcedureCallSites(Implementation implementation) {
+ var callSites = new Dictionary<Block, List<CallSite>>();
+ foreach (Block block in implementation.Blocks) {
+ for (int i = 0; i < block.Cmds.Count; i++) {
+ AssumeCmd assumeCmd = block.Cmds[i] as AssumeCmd;
+ if (assumeCmd == null) continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null) continue;
+ if (!naryExpr.Fun.FunctionName.StartsWith(recordProcName)) continue;
+ List<VCExpr> interfaceExprs = new List<VCExpr>();
+ foreach (Expr e in naryExpr.Args) {
+ interfaceExprs.Add(prover.Context.BoogieExprTranslator.Translate(e));
+ }
+ CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, null, block, i, assumeCmd.Attributes);
+ if (!callSites.ContainsKey(block))
+ callSites[block] = new List<CallSite>();
+ callSites[block].Add(cs);
+ }
+ }
+ return callSites;
+ }
+
+ private int macroCountForStratifiedInlining = 0;
+ public Macro CreateNewMacro() {
+ string newName = "SIMacro@" + macroCountForStratifiedInlining.ToString();
+ macroCountForStratifiedInlining++;
+ return new Macro(Token.NoToken, newName, new List<Variable>(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool), false));
+ }
+ private int varCountForStratifiedInlining = 0;
+ public VCExprVar CreateNewVar(Microsoft.Boogie.Type type) {
+ string newName = "SIV@" + varCountForStratifiedInlining.ToString();
+ varCountForStratifiedInlining++;
+ Constant newVar = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, newName, type));
+ prover.Context.DeclareConstant(newVar, false, null);
+ return prover.VCExprGen.Variable(newVar.Name, type);
+ }
+ private int idCountForStratifiedInlining = 0;
+ public int CreateNewId() {
+ return idCountForStratifiedInlining++;
+ }
+
+ // Used inside PassifyImpl
+ protected override void addExitAssert(string implName, Block exitBlock) {
+ if (implName2StratifiedInliningInfo != null && implName2StratifiedInliningInfo.ContainsKey(implName)) {
+ var exitAssertCmd = implName2StratifiedInliningInfo[implName].exitAssertCmd;
+ if(exitAssertCmd != null) exitBlock.Cmds.Add(exitAssertCmd);
+ }
+ }
+
+ public override Counterexample extractLoopTrace(Counterexample cex, string mainProcName, Program program, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo) {
+ // Construct the set of inlined procs in the original program
+ var inlinedProcs = new HashSet<string>();
+ foreach (var decl in program.TopLevelDeclarations) {
+ // Implementations
+ if (decl is Implementation) {
+ var impl = decl as Implementation;
+ if (!(impl.Proc is LoopProcedure)) {
+ inlinedProcs.Add(impl.Name);
+ }
+ }
+
+ // And recording procedures
+ if (decl is Procedure) {
+ var proc = decl as Procedure;
+ if (proc.Name.StartsWith(recordProcName)) {
+ Debug.Assert(!(decl is LoopProcedure));
+ inlinedProcs.Add(proc.Name);
+ }
+ }
+ }
+
+ return extractLoopTraceRec(
+ new CalleeCounterexampleInfo(cex, new List<object>()),
+ mainProcName, inlinedProcs, extractLoopMappingInfo).counterexample;
+ }
+
+ protected override bool elIsLoop(string procname) {
+ StratifiedInliningInfo info = null;
+ if (implName2StratifiedInliningInfo.ContainsKey(procname)) {
+ info = implName2StratifiedInliningInfo[procname];
+ }
+
+ if (info == null) return false;
+
+ var lp = info.impl.Proc as LoopProcedure;
+
+ if (lp == null) return false;
+ return true;
+ }
+
+ public abstract Outcome FindLeastToVerify(Implementation impl, ref HashSet<string> allBoolVars);
+ }
+
+ public class StratifiedVCGen : StratifiedVCGenBase {
+ public bool PersistCallTree;
+ public static HashSet<string> callTree = null;
+ public int numInlined = 0;
+ public int vcsize = 0;
+ private HashSet<string> procsThatReachedRecBound;
+ private Dictionary<string, int> extraRecBound;
+
+ public StratifiedVCGen(bool usePrevCallTree, HashSet<string> prevCallTree,
+ Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
+ : this(program, logFilePath, appendLogFile, checkers)
+ {
+ if (usePrevCallTree) {
+ callTree = prevCallTree;
+ PersistCallTree = true;
+ }
+ else {
+ PersistCallTree = false;
+ }
+ }
+
+ public StratifiedVCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
+ : base(program, logFilePath, appendLogFile, checkers, null) {
+ PersistCallTree = false;
+ procsThatReachedRecBound = new HashSet<string>();
+
+ extraRecBound = new Dictionary<string, int>();
+ program.TopLevelDeclarations.OfType<Implementation>()
+ .Iter(impl =>
+ {
+ var b = QKeyValue.FindIntAttribute(impl.Attributes, "SIextraRecBound", -1);
+ if (b != -1) extraRecBound.Add(impl.Name, b);
+ });
+ }
+
+ // Extra rec bound for procedures
+ public int GetExtraRecBound(string procName) {
+ if (!extraRecBound.ContainsKey(procName))
+ return 0;
+ else return extraRecBound[procName];
+ }
+
+ public class ApiChecker {
+ public ProverInterface prover;
+ public ProverInterface.ErrorHandler reporter;
+
+ public ApiChecker(ProverInterface prover, ProverInterface.ErrorHandler reporter) {
+ this.reporter = reporter;
+ this.prover = prover;
+ }
+
+ private Outcome CheckVC() {
+ prover.Check();
+ ProverInterface.Outcome outcome = prover.CheckOutcomeCore(reporter);
+
+ return ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
+ }
+
+ public Outcome CheckAssumptions(List<VCExpr> assumptions) {
+ if (assumptions.Count == 0) {
+ return CheckVC();
+ }
+
+ prover.Push();
+ foreach (var a in assumptions) {
+ prover.Assert(a, true);
+ }
+ Outcome ret = CheckVC();
+ prover.Pop();
+ return ret;
+ }
+
+ public Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions) {
+ List<int> unsatisfiedSoftAssumptions;
+ ProverInterface.Outcome outcome = prover.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, reporter);
+ return ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
+ }
+
+ public Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore) {
+ ProverInterface.Outcome outcome = prover.CheckAssumptions(assumptions, out unsatCore, reporter);
+ return ConditionGeneration.ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
+ }
+ }
+
+ // Store important information related to a single VerifyImplementation query
+ public class VerificationState {
+ // The call tree
+ public FCallHandler calls;
+ public ApiChecker checker;
+ // For statistics
+ public int vcSize;
+ public int expansionCount;
+
+ public VerificationState(VCExpr vcMain, FCallHandler calls, ProverInterface prover, ProverInterface.ErrorHandler reporter) {
+ prover.Assert(vcMain, true);
+ this.calls = calls;
+ this.checker = new ApiChecker(prover, reporter);
+ vcSize = 0;
+ expansionCount = 0;
+ }
+ }
+
+ class FindLeastOORException : Exception
+ {
+ public Outcome outcome;
+
+ public FindLeastOORException(string msg, Outcome outcome)
+ : base(msg)
+ {
+ this.outcome = outcome;
+ }
+ }
+
+ public override Outcome FindLeastToVerify(Implementation impl, ref HashSet<string> allBoolVars) {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ // Record current time
+ var startTime = DateTime.UtcNow;
+
+ // No Max: avoids theorem prover restarts
+ CommandLineOptions.Clo.MaxProverMemory = 0;
+
+ // Initialize cache
+ satQueryCache = new Dictionary<int, List<HashSet<string>>>();
+ unsatQueryCache = new Dictionary<int, List<HashSet<string>>>();
+
+ Contract.Assert(implName2StratifiedInliningInfo != null);
+
+ // Build VCs for all procedures
+ implName2StratifiedInliningInfo.Values
+ .Iter(info => info.GenerateVC());
+
+ // Get the VC of the current procedure
+ VCExpr vcMain = implName2StratifiedInliningInfo[impl.Name].vcexpr;
+ Dictionary<int, Absy> mainLabel2absy = implName2StratifiedInliningInfo[impl.Name].label2absy;
+
+ // Find all procedure calls in vc and put labels on them
+ FCallHandler calls = new FCallHandler(prover.VCExprGen, implName2StratifiedInliningInfo, impl.Name, mainLabel2absy);
+ calls.setCurrProcAsMain();
+ vcMain = calls.Mutate(vcMain, true);
+
+ try
+ {
+
+ // Put all of the necessary state into one object
+ var vState = new VerificationState(vcMain, calls, prover, new EmptyErrorHandler());
+
+ // We'll restore the original state of the theorem prover at the end
+ // of this procedure
+ vState.checker.prover.Push();
+
+ // Do eager inlining
+ while (calls.currCandidates.Count > 0)
+ {
+ List<int> toExpand = new List<int>();
+
+ foreach (int id in calls.currCandidates)
+ {
+ Debug.Assert(calls.getRecursionBound(id) <= 1, "Recursion not supported");
+ toExpand.Add(id);
+ }
+ DoExpansion(toExpand, vState);
+ }
+
+ // Find all the boolean constants
+ var allConsts = new HashSet<VCExprVar>();
+ foreach (var constant in program.Constants)
+ {
+ if (!allBoolVars.Contains(constant.Name)) continue;
+ var v = prover.Context.BoogieExprTranslator.LookupVariable(constant);
+ allConsts.Add(v);
+ }
+
+ // Now, lets start the algo
+ var min = refinementLoop(vState.checker, new HashSet<VCExprVar>(), allConsts, allConsts);
+
+ var ret = new HashSet<string>();
+ foreach (var v in min)
+ {
+ //Console.WriteLine(v.Name);
+ ret.Add(v.Name);
+ }
+ allBoolVars = ret;
+
+ vState.checker.prover.Pop();
+
+ return Outcome.Correct;
+ }
+ catch (FindLeastOORException e)
+ {
+ Console.WriteLine("Exception in FindLeastToVerify: {0}, {1}", e.Message, e.outcome);
+ return e.outcome;
+ }
+ }
+
+ private HashSet<VCExprVar> refinementLoop(ApiChecker apiChecker, HashSet<VCExprVar> trackedVars, HashSet<VCExprVar> trackedVarsUpperBound, HashSet<VCExprVar> allVars) {
+ Debug.Assert(trackedVars.IsSubsetOf(trackedVarsUpperBound));
+
+ // If we already know the fate of all vars, then we're done.
+ if (trackedVars.Count == trackedVarsUpperBound.Count)
+ return new HashSet<VCExprVar>(trackedVars);
+
+ // See if we already have enough variables tracked
+ var success = refinementLoopCheckPath(apiChecker, trackedVars, allVars);
+ if (success) {
+ // We have enough
+ return new HashSet<VCExprVar>(trackedVars);
+ }
+
+ // If all that remains is 1 variable, then we know that we must track it
+ if (trackedVars.Count + 1 == trackedVarsUpperBound.Count)
+ return new HashSet<VCExprVar>(trackedVarsUpperBound);
+
+ // Partition the remaining set of variables
+ HashSet<VCExprVar> part1, part2;
+ var temp = new HashSet<VCExprVar>(trackedVarsUpperBound);
+ temp.ExceptWith(trackedVars);
+ Partition<VCExprVar>(temp, out part1, out part2);
+
+ // First half
+ var fh = new HashSet<VCExprVar>(trackedVars); fh.UnionWith(part2);
+ var s1 = refinementLoop(apiChecker, fh, trackedVarsUpperBound, allVars);
+
+ var a = new HashSet<VCExprVar>(part1); a.IntersectWith(s1);
+ var b = new HashSet<VCExprVar>(part1); b.ExceptWith(s1);
+ var c = new HashSet<VCExprVar>(trackedVarsUpperBound); c.ExceptWith(b);
+ a.UnionWith(trackedVars);
+
+ // Second half
+ return refinementLoop(apiChecker, a, c, allVars);
+ }
+
+ Dictionary<int, List<HashSet<string>>> satQueryCache;
+ Dictionary<int, List<HashSet<string>>> unsatQueryCache;
+
+ private bool refinementLoopCheckPath(ApiChecker apiChecker, HashSet<VCExprVar> varsToSet, HashSet<VCExprVar> allVars) {
+ var assumptions = new List<VCExpr>();
+ var prover = apiChecker.prover;
+ var query = new HashSet<string>();
+ varsToSet.Iter(v => query.Add(v.Name));
+
+ if (checkCache(query, unsatQueryCache)) {
+ prover.LogComment("FindLeast: Query Cache Hit");
+ return true;
+ }
+ if (checkCache(query, satQueryCache)) {
+ prover.LogComment("FindLeast: Query Cache Hit");
+ return false;
+ }
+
+ prover.LogComment("FindLeast: Query Begin");
+
+ foreach (var c in allVars) {
+ if (varsToSet.Contains(c)) {
+ assumptions.Add(c);
+ }
+ else {
+ assumptions.Add(prover.VCExprGen.Not(c));
+ }
+ }
+
+ var o = apiChecker.CheckAssumptions(assumptions);
+ if (o != Outcome.Correct && o != Outcome.Errors)
+ {
+ throw new FindLeastOORException("OOR", o);
+ }
+ //Console.WriteLine("Result = " + o.ToString());
+ prover.LogComment("FindLeast: Query End");
+
+ if (o == Outcome.Correct) {
+ insertCache(query, unsatQueryCache);
+ return true;
+ }
+
+ insertCache(query, satQueryCache);
+ return false;
+ }
+
+ private bool checkCache(HashSet<string> q, Dictionary<int, List<HashSet<string>>> cache) {
+ if (!cache.ContainsKey(q.Count)) return false;
+ foreach (var s in cache[q.Count]) {
+ if (q.SetEquals(s)) return true;
+ }
+ return false;
+ }
+
+ private void insertCache(HashSet<string> q, Dictionary<int, List<HashSet<string>>> cache) {
+ if (!cache.ContainsKey(q.Count)) {
+ cache.Add(q.Count, new List<HashSet<string>>());
+ }
+ cache[q.Count].Add(q);
+ }
+
+ public static void Partition<T>(HashSet<T> values, out HashSet<T> part1, out HashSet<T> part2) {
+ part1 = new HashSet<T>();
+ part2 = new HashSet<T>();
+ var size = values.Count;
+ var crossed = false;
+ var curr = 0;
+ foreach (var s in values) {
+ if (crossed) part2.Add(s);
+ else part1.Add(s);
+ curr++;
+ if (!crossed && curr >= size / 2) crossed = true;
+ }
+ }
+
+ public override Outcome VerifyImplementation(Implementation/*!*/ impl, VerifierCallback/*!*/ callback) {
+ Debug.Assert(QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"));
+ Debug.Assert(this.program == program);
+
+ // Record current time
+ var startTime = DateTime.UtcNow;
+
+ // Flush any axioms that came with the program before we start SI on this implementation
+ prover.AssertAxioms();
+
+ // Run live variable analysis
+ if (CommandLineOptions.Clo.LiveVariableAnalysis == 2) {
+ Microsoft.Boogie.InterProcGenKill.ComputeLiveVars(impl, program);
+ }
+
+ // Get the VC of the current procedure
+ StratifiedInliningInfo info = implName2StratifiedInliningInfo[impl.Name];
+ info.GenerateVC();
+ VCExpr vc = info.vcexpr;
+ Dictionary<int, Absy> mainLabel2absy = info.label2absy;
+ var reporter = new StratifiedInliningErrorReporter(implName2StratifiedInliningInfo, prover, callback, info);
+
+ // Find all procedure calls in vc and put labels on them
+ FCallHandler calls = new FCallHandler(prover.VCExprGen, implName2StratifiedInliningInfo, impl.Name, mainLabel2absy);
+ calls.setCurrProcAsMain();
+ vc = calls.Mutate(vc, true);
+ reporter.SetCandidateHandler(calls);
+ calls.id2VC.Add(0, vc);
+ calls.extraRecursion = extraRecBound;
+ if (CommandLineOptions.Clo.SIBoolControlVC)
+ {
+ calls.candiate2block2controlVar.Add(0, new Dictionary<Block, VCExpr>());
+ implName2StratifiedInliningInfo[impl.Name].blockToControlVar.Iter(tup =>
+ calls.candiate2block2controlVar[0].Add(tup.Key, tup.Value));
+ }
+
+ // We'll restore the original state of the theorem prover at the end
+ // of this procedure
+ prover.Push();
+
+ // Put all of the necessary state into one object
+ var vState = new VerificationState(vc, calls, prover, reporter);
+ vState.vcSize += SizeComputingVisitor.ComputeSize(vc);
+
+ Outcome ret = Outcome.ReachedBound;
+
+ #region eager inlining
+ for (int i = 1; i < CommandLineOptions.Clo.StratifiedInlining && calls.currCandidates.Count > 0; i++) {
+ List<int> toExpand = new List<int>();
+
+ foreach (int id in calls.currCandidates) {
+ if (calls.getRecursionBound(id) <= CommandLineOptions.Clo.RecursionBound) {
+ toExpand.Add(id);
+ }
+ }
+ DoExpansion(toExpand, vState);
+ }
+ #endregion
+
+ #region Repopulate call tree, if there is one
+ if (PersistCallTree && callTree != null) {
+ bool expand = true;
+ while (expand) {
+ List<int> toExpand = new List<int>();
+ foreach (int id in calls.currCandidates) {
+ if (callTree.Contains(calls.getPersistentId(id))) {
+ toExpand.Add(id);
+ }
+ }
+ if (toExpand.Count == 0) expand = false;
+ else {
+ DoExpansion(toExpand, vState);
+ }
+ }
+ }
+ #endregion
+
+ if (CommandLineOptions.Clo.StratifiedInliningVerbose > 1) {
+ Console.WriteLine(">> SI: Size of VC after eager inlining: {0}", vState.vcSize);
+ }
+
+ // Under-approx query is only needed if something was inlined since
+ // the last time an under-approx query was made
+ // TODO: introduce this
+ // bool underApproxNeeded = true;
+
+ // The recursion bound for stratified search
+ int bound = CommandLineOptions.Clo.NonUniformUnfolding ? CommandLineOptions.Clo.RecursionBound : 1;
+
+ int done = 0;
+
+ int iters = 0;
+
+ // for blocking candidates (and focusing on a counterexample)
+ var block = new HashSet<int>();
+
+ // Process tasks while not done. We're done when:
+ // case 1: (correct) We didn't find a bug (either an over-approx query was valid
+ // or we reached the recursion bound) and the task is "step"
+ // case 2: (bug) We find a bug
+ // case 3: (internal error) The theorem prover TimesOut of runs OutOfMemory
+ while (true)
+ {
+ // Check timeout
+ if (CommandLineOptions.Clo.ProverKillTime != -1)
+ {
+ if ((DateTime.UtcNow - startTime).TotalSeconds > CommandLineOptions.Clo.ProverKillTime)
+ {
+ ret = Outcome.TimedOut;
+ break;
+ }
+ }
+
+ if (done > 0)
+ {
+ break;
+ }
+
+ // Stratified Step
+ ret = stratifiedStep(bound, vState, block);
+ iters++;
+
+ // Sorry, out of luck (time/memory)
+ if (ret == Outcome.Inconclusive || ret == Outcome.OutOfMemory || ret == Outcome.TimedOut)
+ {
+ done = 3;
+ continue;
+ }
+
+ if (ret == Outcome.Errors && reporter.underapproximationMode)
+ {
+ // Found a bug
+ done = 2;
+ }
+ else if (ret == Outcome.Correct)
+ {
+ if (block.Count == 0)
+ {
+ // Correct
+ done = 1;
+ }
+ else
+ {
+ // reset blocked and continue loop
+ block.Clear();
+ }
+ }
+ else if (ret == Outcome.ReachedBound)
+ {
+ if (block.Count == 0)
+ {
+ if (CommandLineOptions.Clo.StratifiedInliningVerbose > 0)
+ Console.WriteLine(">> SI: Exhausted Bound {0}", bound);
+
+ // Increment bound
+ bound++;
+
+ if (bound > CommandLineOptions.Clo.RecursionBound)
+ {
+ // Correct under bound
+ done = 1;
+ }
+ }
+ else
+ {
+ // reset blocked and continue loop
+ block.Clear();
+ }
+ }
+ else
+ {
+ // Do inlining
+ Debug.Assert(ret == Outcome.Errors && !reporter.underapproximationMode);
+ Contract.Assert(reporter.candidatesToExpand.Count != 0);
+
+ #region expand call tree
+ if (CommandLineOptions.Clo.StratifiedInliningVerbose > 1)
+ {
+ Console.Write(">> SI Inlining: ");
+ reporter.candidatesToExpand
+ .Select(c => calls.getProc(c))
+ .Iter(c => Console.Write("{0} ", c));
+
+ Console.WriteLine();
+ }
+
+ // Expand and try again
+ vState.checker.prover.LogComment(";;;;;;;;;;;; Expansion begin ;;;;;;;;;;");
+ DoExpansion(reporter.candidatesToExpand, vState);
+ vState.checker.prover.LogComment(";;;;;;;;;;;; Expansion end ;;;;;;;;;;");
+
+ #endregion
+ }
+ }
+
+ // Pop off everything that we pushed so that there are no side effects from
+ // this call to VerifyImplementation
+ vState.checker.prover.Pop();
+
+ if (CommandLineOptions.Clo.StratifiedInliningVerbose > 1) {
+ Console.WriteLine(">> SI: Expansions performed: {0}", vState.expansionCount);
+ Console.WriteLine(">> SI: Candidates left: {0}", calls.currCandidates.Count);
+ Console.WriteLine(">> SI: VC Size: {0}", vState.vcSize);
+ }
+
+ vcsize = vState.vcSize;
+ numInlined = (calls.candidateParent.Keys.Count + 1) - (calls.currCandidates.Count);
+
+ var rbound = "Procs that reached bound: ";
+ foreach (var s in procsThatReachedRecBound) rbound += " " + s;
+ if (ret == Outcome.ReachedBound) Helpers.ExtraTraceInformation(rbound);
+ if (CommandLineOptions.Clo.StackDepthBound > 0 && ret == Outcome.Correct) ret = Outcome.ReachedBound;
+
+ // Store current call tree
+ if (PersistCallTree && (ret == Outcome.Correct || ret == Outcome.Errors || ret == Outcome.ReachedBound)) {
+ callTree = new HashSet<string>();
+ //var persistentNodes = new HashSet<int>(calls.candidateParent.Values);
+ var persistentNodes = new HashSet<int>(calls.candidateParent.Keys);
+ persistentNodes.Add(0);
+ persistentNodes.ExceptWith(calls.currCandidates);
+
+ foreach (var id in persistentNodes) {
+ var pid = calls.getPersistentId(id);
+ Debug.Assert(!callTree.Contains(pid));
+ callTree.Add(pid);
+ }
+ }
+ return ret;
+ }
+
+ // A step of the stratified inlining algorithm: both under-approx and over-approx queries
+ private Outcome stratifiedStep(int bound, VerificationState vState, HashSet<int> block) {
+ var calls = vState.calls;
+ var checker = vState.checker;
+ var prover = checker.prover;
+ var reporter = checker.reporter as StratifiedInliningErrorReporter;
+
+ reporter.underapproximationMode = true;
+ prover.LogComment(";;;;;;;;;;;; Underapprox mode begin ;;;;;;;;;;");
+ List<VCExpr> assumptions = new List<VCExpr>();
+
+ foreach (int id in calls.currCandidates) {
+ assumptions.Add(calls.getFalseExpr(id));
+ }
+ Outcome ret = checker.CheckAssumptions(assumptions);
+ prover.LogComment(";;;;;;;;;;;; Underapprox mode end ;;;;;;;;;;");
+
+ if (ret != Outcome.Correct) {
+ // Either the query returned an error or it ran out of memory or time.
+ // In all cases, we are done.
+ return ret;
+ }
+
+ if (calls.currCandidates.Count == 0) {
+ // If we didn't underapproximate, then we're done
+ return ret;
+ }
+
+ prover.LogComment(";;;;;;;;;;;; Overapprox mode begin ;;;;;;;;;;");
+
+ // Over-approx query
+ reporter.underapproximationMode = false;
+
+ // Push "true" for all, except:
+ // push "false" for all candidates that have reached
+ // the recursion bounds
+
+ bool allTrue = true;
+ bool allFalse = true;
+ List<VCExpr> softAssumptions = new List<VCExpr>();
+
+ assumptions = new List<VCExpr>();
+ procsThatReachedRecBound.Clear();
+
+ foreach (int id in calls.currCandidates) {
+
+ int idBound = calls.getRecursionBound(id);
+ int sd = calls.getStackDepth(id);
+ if (idBound <= bound && (CommandLineOptions.Clo.StackDepthBound == 0 || sd <= CommandLineOptions.Clo.StackDepthBound)) {
+ if (idBound > 1)
+ softAssumptions.Add(calls.getFalseExpr(id));
+
+ if (block.Contains(id)) {
+ assumptions.Add(calls.getFalseExpr(id));
+ allTrue = false;
+ }
+ else {
+ allFalse = false;
+ }
+ }
+ else {
+ procsThatReachedRecBound.Add(calls.getProc(id));
+ assumptions.Add(calls.getFalseExpr(id));
+ allTrue = false;
+ }
+ }
+
+ if (allFalse) {
+ // If we made all candidates false, then this is the same
+ // as the underapprox query. We already know the answer.
+ ret = Outcome.Correct;
+ }
+ else {
+ ret = CommandLineOptions.Clo.NonUniformUnfolding
+ ? checker.CheckAssumptions(assumptions, softAssumptions)
+ : checker.CheckAssumptions(assumptions);
+ }
+
+ if (ret != Outcome.Correct && ret != Outcome.Errors) {
+ // The query ran out of memory or time, that's it,
+ // we cannot do better. Give up!
+ return ret;
+ }
+
+ if (ret == Outcome.Correct) {
+ // If nothing was made false, then the program is correct
+ if (allTrue) {
+ return ret;
+ }
+
+ // Nothing more can be done with current recursion bound.
+ return Outcome.ReachedBound;
+ }
+
+ Contract.Assert(ret == Outcome.Errors);
+
+ prover.LogComment(";;;;;;;;;;;; Overapprox mode end ;;;;;;;;;;");
+
+ return ret;
+ }
+
+ // A counter for adding new variables
+ static int newVarCnt = 0;
+
+ // Does on-demand inlining -- pushes procedure bodies on the theorem prover stack.
+ private void DoExpansion(List<int>/*!*/ candidates, VerificationState vState) {
+ Contract.Requires(candidates != null);
+ Contract.Requires(vState.calls != null);
+ Contract.Requires(vState.checker.prover != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ vState.expansionCount += candidates.Count;
+
+ var prover = vState.checker.prover;
+ var calls = vState.calls;
+
+ VCExpr exprToPush = VCExpressionGenerator.True;
+ Contract.Assert(exprToPush != null);
+ foreach (int id in candidates) {
+ VCExprNAry expr = calls.id2Candidate[id];
+ Contract.Assert(expr != null);
+ string procName = cce.NonNull(expr.Op as VCExprBoogieFunctionOp).Func.Name;
+ if (!implName2StratifiedInliningInfo.ContainsKey(procName)) continue;
+
+ StratifiedInliningInfo info = implName2StratifiedInliningInfo[procName];
+ info.GenerateVC();
+ //Console.WriteLine("Inlining {0}", procName);
+ VCExpr expansion = cce.NonNull(info.vcexpr);
+
+ // Instantiate the "forall" variables
+ Dictionary<VCExprVar, VCExpr> substForallDict = new Dictionary<VCExprVar, VCExpr>();
+ Contract.Assert(info.interfaceExprVars.Count == expr.Length);
+ for (int i = 0; i < info.interfaceExprVars.Count; i++) {
+ substForallDict.Add(info.interfaceExprVars[i], expr[i]);
+ }
+ VCExprSubstitution substForall = new VCExprSubstitution(substForallDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
+
+ SubstitutingVCExprVisitor subst = new SubstitutingVCExprVisitor(prover.VCExprGen);
+ Contract.Assert(subst != null);
+ expansion = subst.Mutate(expansion, substForall);
+
+ // Instantiate and declare the "exists" variables
+ Dictionary<VCExprVar, VCExpr> substExistsDict = new Dictionary<VCExprVar, VCExpr>();
+ foreach (VCExprVar v in info.privateExprVars) {
+ Contract.Assert(v != null);
+ string newName = v.Name + "_si_" + newVarCnt.ToString();
+ newVarCnt++;
+ prover.Context.DeclareConstant(new Constant(Token.NoToken, new TypedIdent(Token.NoToken, newName, v.Type)), false, null);
+ substExistsDict.Add(v, prover.VCExprGen.Variable(newName, v.Type));
+ }
+ if (CommandLineOptions.Clo.SIBoolControlVC)
+ {
+ // record the mapping for control booleans (for tracing the path later)
+ calls.candiate2block2controlVar[id] = new Dictionary<Block, VCExpr>();
+ foreach (var tup in info.blockToControlVar)
+ {
+ calls.candiate2block2controlVar[id].Add(tup.Key,
+ substExistsDict[tup.Value]);
+ }
+ }
+ if (CommandLineOptions.Clo.ModelViewFile != null) {
+ SaveSubstitution(vState, id, substForallDict, substExistsDict);
+ }
+ VCExprSubstitution substExists = new VCExprSubstitution(substExistsDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
+
+ subst = new SubstitutingVCExprVisitor(prover.VCExprGen);
+ expansion = subst.Mutate(expansion, substExists);
+
+ if (!calls.currCandidates.Contains(id)) {
+ Console.WriteLine("Don't know what we just expanded");
+ }
+
+ calls.currCandidates.Remove(id);
+
+ // Record the new set of candidates and rename absy labels
+ calls.currInlineCount = id;
+ calls.setCurrProc(procName);
+ expansion = calls.Mutate(expansion, true);
+
+ //expansion = checker.VCExprGen.Eq(calls.id2ControlVar[id], expansion);
+ expansion = prover.VCExprGen.Implies(calls.id2ControlVar[id], expansion);
+ calls.id2VC.Add(id, expansion);
+
+ exprToPush = prover.VCExprGen.And(exprToPush, expansion);
+ }
+ vState.checker.prover.Assert(exprToPush, true);
+ vState.vcSize += SizeComputingVisitor.ComputeSize(exprToPush);
+ }
+
+ private void SaveSubstitution(VerificationState vState, int id,
+ Dictionary<VCExprVar, VCExpr> substForallDict, Dictionary<VCExprVar, VCExpr> substExistsDict) {
+ var prover = vState.checker.prover;
+ var calls = vState.calls;
+ Boogie2VCExprTranslator translator = prover.Context.BoogieExprTranslator;
+ VCExprVar mvStateConstant = translator.LookupVariable(ModelViewInfo.MVState_ConstantDef);
+ substExistsDict.Add(mvStateConstant, prover.VCExprGen.Integer(BigNum.FromInt(id)));
+ Dictionary<VCExprVar, VCExpr> mapping = new Dictionary<VCExprVar, VCExpr>();
+ foreach (var key in substForallDict.Keys)
+ mapping[key] = substForallDict[key];
+ foreach (var key in substExistsDict.Keys)
+ mapping[key] = substExistsDict[key];
+ calls.id2Vars[id] = mapping;
+ }
+
+ // Uniquely identifies a procedure call (the call expr, instance)
+ public class BoogieCallExpr : IEquatable<BoogieCallExpr> {
+ public NAryExpr expr;
+ public int inlineCnt;
+
+ public BoogieCallExpr(NAryExpr expr, int inlineCnt) {
+ this.expr = expr;
+ this.inlineCnt = inlineCnt;
+ }
+
+ public override int GetHashCode() {
+ return expr.GetHashCode() + 131 * inlineCnt.GetHashCode();
+ }
+
+ public override bool Equals(object obj) {
+ BoogieCallExpr that = obj as BoogieCallExpr;
+ return (expr == that.expr && inlineCnt == that.inlineCnt);
+ }
+
+ public bool Equals(BoogieCallExpr that) {
+ return (expr == that.expr && inlineCnt == that.inlineCnt);
+ }
+ }
+
+ // This class is used to traverse VCs and do the following:
+ // -- collect the set of FunctionCall nodes and label them with a unique string
+ // -- Rename all other labels (so that calling this on the same VC results in
+ // VCs with different labels each time)
+ public class FCallHandler : MutatingVCExprVisitor<bool> {
+ Dictionary<string/*!*/, StratifiedInliningInfo/*!*/>/*!*/ implName2StratifiedInliningInfo;
+ public readonly Dictionary<int, Absy>/*!*/ mainLabel2absy;
+ public Dictionary<BoogieCallExpr/*!*/, int>/*!*/ boogieExpr2Id;
+ public Dictionary<BoogieCallExpr/*!*/, VCExpr>/*!*/ recordExpr2Var;
+ public Dictionary<int, VCExprNAry/*!*/>/*!*/ id2Candidate;
+ public Dictionary<int, VCExprVar/*!*/>/*!*/ id2ControlVar;
+ public Dictionary<int, VCExpr> id2VC;
+ public Dictionary<string/*!*/, int>/*!*/ label2Id;
+ // candidate to block to Bool Control variable
+ public Dictionary<int, Dictionary<Block, VCExpr>> candiate2block2controlVar;
+ // Stores the candidate from which this one originated
+ public Dictionary<int, int> candidateParent;
+ // Mapping from candidate Id to the "si_unique_call" id that led to
+ // this candidate. This is useful for getting persistent names for
+ // candidates
+ public Dictionary<int, int> candidate2callId;
+ // A cache for candidate id to its persistent name
+ public Dictionary<int, string> persistentNameCache;
+ // Inverse of the above map
+ public Dictionary<string, int> persistentNameInv;
+ // Used to record candidates recently added
+ public HashSet<int> recentlyAddedCandidates;
+ // Name of main procedure
+ private string mainProcName;
+ // A map from candidate id to the VCExpr that represents its
+ // first argument (used for obtaining concrete values in error trace)
+ public Dictionary<int, VCExpr> argExprMap;
+
+ // map from candidate to summary candidates
+ public Dictionary<int, List<Tuple<VCExprVar, VCExpr>>> summaryCandidates;
+ private Dictionary<string, List<Tuple<VCExprVar, VCExpr>>> summaryTemp;
+ // set of all boolean guards of summaries
+ public HashSet<VCExprVar> allSummaryConst;
+
+ public HashSet<int> forcedCandidates;
+
+ // User info -- to decrease/increase calculation of recursion bound
+ public Dictionary<int, int> recursionIncrement;
+ public Dictionary<string, int> extraRecursion;
+
+ public HashSet<int> currCandidates;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
+ Contract.Invariant(mainLabel2absy != null);
+ Contract.Invariant(boogieExpr2Id != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(id2Candidate));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(id2ControlVar));
+ Contract.Invariant(label2Id != null);
+ }
+
+ // Name of the procedure whose VC we're mutating
+ string currProc;
+
+ // The 0^th candidate is main
+ static int candidateCount = 1;
+ public int currInlineCount;
+
+ public Dictionary<int, Dictionary<VCExprVar, VCExpr>> id2Vars;
+
+ public FCallHandler(VCExpressionGenerator/*!*/ gen,
+ Dictionary<string/*!*/, StratifiedInliningInfo/*!*/>/*!*/ implName2StratifiedInliningInfo,
+ string mainProcName, Dictionary<int, Absy>/*!*/ mainLabel2absy)
+ : base(gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
+ Contract.Requires(mainLabel2absy != null);
+ this.implName2StratifiedInliningInfo = implName2StratifiedInliningInfo;
+ this.mainProcName = mainProcName;
+ this.mainLabel2absy = mainLabel2absy;
+ id2Candidate = new Dictionary<int, VCExprNAry>();
+ id2ControlVar = new Dictionary<int, VCExprVar>();
+ boogieExpr2Id = new Dictionary<BoogieCallExpr, int>();
+ label2Id = new Dictionary<string, int>();
+ currCandidates = new HashSet<int>();
+ currInlineCount = 0;
+ currProc = null;
+ labelRenamer = new Dictionary<string, int>();
+ labelRenamerInv = new Dictionary<string, string>();
+ candidateParent = new Dictionary<int, int>();
+ //callGraphMapping = new Dictionary<int, int>();
+ recursionIncrement = new Dictionary<int, int>();
+ candidate2callId = new Dictionary<int, int>();
+ persistentNameCache = new Dictionary<int, string>();
+ persistentNameInv = new Dictionary<string, int>();
+ persistentNameCache[0] = "0";
+ persistentNameInv["0"] = 0;
+ recentlyAddedCandidates = new HashSet<int>();
+ argExprMap = new Dictionary<int, VCExpr>();
+ recordExpr2Var = new Dictionary<BoogieCallExpr, VCExpr>();
+ candiate2block2controlVar = new Dictionary<int, Dictionary<Block, VCExpr>>();
+
+ forcedCandidates = new HashSet<int>();
+ extraRecursion = new Dictionary<string, int>();
+
+ id2Vars = new Dictionary<int, Dictionary<VCExprVar, VCExpr>>();
+ summaryCandidates = new Dictionary<int, List<Tuple<VCExprVar, VCExpr>>>();
+ summaryTemp = new Dictionary<string, List<Tuple<VCExprVar, VCExpr>>>();
+ allSummaryConst = new HashSet<VCExprVar>();
+ id2VC = new Dictionary<int, VCExpr>();
+ }
+
+ public void Clear() {
+ currCandidates = new HashSet<int>();
+ }
+
+ // Return the set of all candidates
+ public HashSet<int> getAllCandidates() {
+ var ret = new HashSet<int>(candidateParent.Keys);
+ ret.Add(0);
+ return ret;
+ }
+
+ // Given a candidate "id", let proc(id) be the
+ // procedure corresponding to id. This procedure returns
+ // the number of times proc(id) appears as an ancestor
+ // of id. This is the same as the number of times we've
+ // recursed on proc(id)
+ public int getRecursionBound(int id) {
+ int ret = 1;
+ var str = getProc(id);
+
+ while (candidateParent.ContainsKey(id)) {
+ if (recursionIncrement.ContainsKey(id)) ret += recursionIncrement[id];
+ id = candidateParent[id];
+ if (getProc(id) == str && !forcedCandidates.Contains(id)) ret++;
+ }
+
+ // Usual
+ if (!extraRecursion.ContainsKey(str))
+ return ret;
+
+ // Usual
+ if (ret <= CommandLineOptions.Clo.RecursionBound - 1)
+ return ret;
+
+ // Special
+ if (ret >= CommandLineOptions.Clo.RecursionBound &&
+ ret <= CommandLineOptions.Clo.RecursionBound + extraRecursion[str] - 1)
+ return CommandLineOptions.Clo.RecursionBound - 1;
+
+ // Special
+ return ret - extraRecursion[str];
+ }
+
+ // This procedure returns the stack depth of the candidate
+ // (distance from main)
+ public int getStackDepth(int id)
+ {
+ int ret = 1;
+
+ while (candidateParent.ContainsKey(id))
+ {
+ ret++;
+ id = candidateParent[id];
+ }
+
+ return ret;
+ }
+
+ // Set user-define increment/decrement to recursionBound
+ public void setRecursionIncrement(int id, int incr) {
+ if (recursionIncrement.ContainsKey(id))
+ recursionIncrement[id] = incr;
+ else
+ recursionIncrement.Add(id, incr);
+ }
+
+ // Returns the name of the procedure corresponding to candidate id
+ public string getProc(int id) {
+ if (id == 0) return mainProcName;
+
+ return (id2Candidate[id].Op as VCExprBoogieFunctionOp).Func.Name;
+ }
+
+ // Get a unique id for this candidate (dependent only on the Call
+ // graph of the program). The persistent id is:
+ // 0: for main
+ // a_b_c: where a is the persistent id of parent, and b is the procedure name
+ // and c is the unique call id (if any)
+ public string getPersistentId(int top_id) {
+ if (top_id == 0) return "0";
+ Debug.Assert(candidateParent.ContainsKey(top_id));
+ if (persistentNameCache.ContainsKey(top_id))
+ return persistentNameCache[top_id];
+
+ var parent_id = getPersistentId(candidateParent[top_id]);
+ var call_id = candidate2callId.ContainsKey(top_id) ? candidate2callId[top_id] : -1;
+ var ret = string.Format("{0}_131_{1}_131_{2}", parent_id, getProc(top_id), call_id);
+ persistentNameCache[top_id] = ret;
+ persistentNameInv[ret] = top_id;
+ return ret;
+ }
+
+ public int getCandidateFromGraphNode(string n) {
+ if (!persistentNameInv.ContainsKey(n)) {
+ return -1;
+ }
+ return persistentNameInv[n];
+ }
+
+ private int GetNewId(VCExprNAry vc) {
+ Contract.Requires(vc != null);
+ int id = candidateCount;
+
+ id2Candidate[id] = vc;
+ id2ControlVar[id] = Gen.Variable("si_control_var_bool_" + id.ToString(), Microsoft.Boogie.Type.Bool);
+
+ candidateCount++;
+ currCandidates.Add(id);
+ recentlyAddedCandidates.Add(id);
+
+ return id;
+ }
+
+ private string GetLabel(int id) {
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ string ret = "si_fcall_" + id.ToString();
+ if (!label2Id.ContainsKey(ret))
+ label2Id[ret] = id;
+
+ return ret;
+ }
+
+ public int GetId(string label) {
+ Contract.Requires(label != null);
+ if (!label2Id.ContainsKey(label))
+ return -1;
+ return label2Id[label];
+ }
+
+ Dictionary<string, int> labelRenamer;
+ Dictionary<string, string> labelRenamerInv;
+
+ public string RenameAbsyLabel(string label) {
+ Contract.Requires(label != null);
+ Contract.Requires(label.Length >= 1);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ // Remove the sign from the label
+ string nosign = label.Substring(1);
+ var ret = "si_inline_" + currInlineCount.ToString() + "_" + nosign;
+
+ if (!labelRenamer.ContainsKey(ret)) {
+ var c = labelRenamer.Count + 11; // two digit labels only
+ labelRenamer.Add(ret, c);
+ labelRenamerInv.Add(c.ToString(), ret);
+ }
+ return labelRenamer[ret].ToString();
+ }
+
+ public string ParseRenamedAbsyLabel(string label, int cnt) {
+ Contract.Requires(label != null);
+ if (!labelRenamerInv.ContainsKey(label)) {
+ return null;
+ }
+ var str = labelRenamerInv[label];
+ var prefix = "si_inline_" + cnt.ToString() + "_";
+ if (!str.StartsWith(prefix)) return null;
+ return str.Substring(prefix.Length);
+ }
+
+ public void setCurrProc(string name) {
+ Contract.Requires(name != null);
+ currProc = name;
+ Contract.Assert(implName2StratifiedInliningInfo.ContainsKey(name));
+ }
+
+ public void setCurrProcAsMain() {
+ currProc = "";
+ }
+
+ // Return the formula (candidate IFF false)
+ public VCExpr getFalseExpr(int candidateId) {
+ //return Gen.Eq(VCExpressionGenerator.False, id2ControlVar[candidateId]);
+ return Gen.Not(id2ControlVar[candidateId]);
+ }
+
+ // Return the formula (candidate IFF true)
+ public VCExpr getTrueExpr(int candidateId) {
+ return Gen.Eq(VCExpressionGenerator.True, id2ControlVar[candidateId]);
+ }
+
+ public Dictionary<int, Absy> getLabel2absy() {
+ Contract.Ensures(Contract.Result<Dictionary<int, Absy>>() != null);
+
+ Contract.Assert(currProc != null);
+ if (currProc == "") {
+ return mainLabel2absy;
+ }
+ return cce.NonNull(implName2StratifiedInliningInfo[currProc].label2absy);
+ }
+
+ // Finds labels and changes them:
+ // si_fcall_id: if "id" corresponds to a tracked procedure call, then
+ // si_control_var_candidateId
+ // si_fcall_id: if "id" does not corresponds to a tracked procedure call, then
+ // delete
+ // num: si_inline_num
+ //
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
+ List<VCExpr/*!*/>/*!*/ newSubExprs,
+ // has any of the subexpressions changed?
+ bool changed,
+ bool arg) {
+ //Contract.Requires(originalNode != null);
+ //Contract.Requires(cce.NonNullElements(newSubExprs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr ret;
+ if (changed)
+ ret = Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ ret = originalNode;
+
+ VCExprLabelOp lop = originalNode.Op as VCExprLabelOp;
+ if (lop == null) return ret;
+ if (!(ret is VCExprNAry)) return ret;
+
+ VCExprNAry retnary = (VCExprNAry)ret;
+ Contract.Assert(retnary != null);
+ string prefix = "si_fcall_"; // from Wlp.ssc::Cmd(...)
+ if (lop.label.Substring(1).StartsWith(prefix)) {
+ int id = Int32.Parse(lop.label.Substring(prefix.Length + 1));
+ Dictionary<int, Absy> label2absy = getLabel2absy();
+ Absy cmd = label2absy[id] as Absy;
+ //label2absy.Remove(id);
+
+ Contract.Assert(cmd != null);
+ AssumeCmd acmd = cmd as AssumeCmd;
+ Contract.Assert(acmd != null);
+ NAryExpr naryExpr = acmd.Expr as NAryExpr;
+ Contract.Assert(naryExpr != null);
+
+ string calleeName = naryExpr.Fun.FunctionName;
+
+ VCExprNAry callExpr = retnary[0] as VCExprNAry;
+
+ if (implName2StratifiedInliningInfo.ContainsKey(calleeName)) {
+ Contract.Assert(callExpr != null);
+ int candidateId = GetNewId(callExpr);
+ boogieExpr2Id[new BoogieCallExpr(naryExpr, currInlineCount)] = candidateId;
+ candidateParent[candidateId] = currInlineCount;
+ candiate2block2controlVar[candidateId] = new Dictionary<Block, VCExpr>();
+
+ string label = GetLabel(candidateId);
+ var unique_call_id = QKeyValue.FindIntAttribute(acmd.Attributes, "si_unique_call", -1);
+ if (unique_call_id != -1)
+ candidate2callId[candidateId] = unique_call_id;
+
+ //return Gen.LabelPos(label, callExpr);
+ return Gen.LabelPos(label, id2ControlVar[candidateId]);
+ }
+ else if (calleeName.StartsWith(recordProcName)) {
+ Contract.Assert(callExpr != null);
+ Debug.Assert(callExpr.Length == 1);
+ Debug.Assert(callExpr[0] != null);
+ recordExpr2Var[new BoogieCallExpr(naryExpr, currInlineCount)] = callExpr[0];
+ return callExpr;
+ }
+ else {
+ // callExpr can be null; this happens when the FunctionCall was on a
+ // pure function (not procedure) and the function got inlined
+ return retnary[0];
+ }
+ }
+
+ // Else, rename label
+ string newLabel = RenameAbsyLabel(lop.label);
+ if (lop.pos) {
+ return Gen.LabelPos(newLabel, retnary[0]);
+ }
+ else {
+ return Gen.LabelNeg(newLabel, retnary[0]);
+ }
+
+ }
+
+ // Upgrades summaryTemp to summaryCandidates by matching ensure clauses with
+ // the appropriate candidate they came from
+ public void matchSummaries() {
+ var id2Set = new Dictionary<string, List<Tuple<int, HashSet<VCExprVar>>>>();
+ foreach (var id in recentlyAddedCandidates) {
+ var collect = new CollectVCVars();
+ var proc = getProc(id);
+ if (!id2Set.ContainsKey(proc)) id2Set.Add(proc, new List<Tuple<int, HashSet<VCExprVar>>>());
+ id2Set[proc].Add(Tuple.Create(id, collect.Collect(id2Candidate[id], true)));
+ }
+
+ foreach (var kvp in summaryTemp) {
+ Contract.Assert(id2Set.ContainsKey(kvp.Key));
+ var ls = id2Set[kvp.Key];
+ foreach (var tup in kvp.Value) {
+ var collect = new CollectVCVars();
+ var s1 = collect.Collect(tup.Item2, true);
+ var found = false;
+ foreach (var t in ls) {
+ var s2 = t.Item2;
+ if (s1.IsSubsetOf(s2)) {
+ if (!summaryCandidates.ContainsKey(t.Item1))
+ summaryCandidates.Add(t.Item1, new List<Tuple<VCExprVar, VCExpr>>());
+ summaryCandidates[t.Item1].Add(tup);
+ allSummaryConst.Add(tup.Item1);
+ found = true;
+ break;
+ }
+ }
+ Contract.Assert(found);
+ }
+ }
+ summaryTemp.Clear();
+ }
+
+ public IEnumerable<int> getInlinedCandidates() {
+ return candidateParent.Keys.Except(currCandidates).Union(new int[] { 0 });
+ }
+
+ } // end FCallHandler
+
+ // Collects the set of all VCExprVar in a given VCExpr
+ class CollectVCVars : CollectingVCExprVisitor<HashSet<VCExprVar>, bool> {
+ public override HashSet<VCExprVar> Visit(VCExprVar node, bool arg) {
+ var ret = new HashSet<VCExprVar>();
+ ret.Add(node);
+ return ret;
+ }
+
+ protected override HashSet<VCExprVar> CombineResults(List<HashSet<VCExprVar>> results, bool arg) {
+ var ret = new HashSet<VCExprVar>();
+ results.Iter(s => ret.UnionWith(s));
+ return ret;
+ }
+ }
+
+ public class FCallInliner : MutatingVCExprVisitor<bool> {
+ public Dictionary<int, VCExpr/*!*/>/*!*/ subst;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(subst));
+ }
+
+
+ public FCallInliner(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+ subst = new Dictionary<int, VCExpr>();
+ }
+
+ public void Clear() {
+ subst = new Dictionary<int, VCExpr>();
+ }
+
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode,
+ List<VCExpr/*!*/>/*!*/ newSubExprs,
+ // has any of the subexpressions changed?
+ bool changed,
+ bool arg) {
+ //Contract.Requires(originalNode != null);Contract.Requires(newSubExprs != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr ret;
+ if (changed)
+ ret = Gen.Function(originalNode.Op, newSubExprs, originalNode.TypeArguments);
+ else
+ ret = originalNode;
+
+ VCExprLabelOp lop = originalNode.Op as VCExprLabelOp;
+ if (lop == null) return ret;
+ if (!(ret is VCExprNAry)) return ret;
+
+ string prefix = "si_fcall_"; // from FCallHandler::GetLabel
+ if (lop.label.Substring(1).StartsWith(prefix)) {
+ int id = Int32.Parse(lop.label.Substring(prefix.Length + 1));
+ if (subst.ContainsKey(id)) {
+ return subst[id];
+ }
+ }
+ return ret;
+ }
+
+ } // end FCallInliner
+
+
+
+ public class StratifiedInliningErrorReporter : ProverInterface.ErrorHandler {
+ Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo;
+ ProverInterface theoremProver;
+ VerifierCallback callback;
+ FCallHandler calls;
+ StratifiedInliningInfo mainInfo;
+ StratifiedVC mainVC;
+
+ public bool underapproximationMode;
+ public List<int> candidatesToExpand;
+ public List<StratifiedCallSite> callSitesToExpand;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(candidatesToExpand != null);
+ Contract.Invariant(mainInfo != null);
+ Contract.Invariant(callback != null);
+ Contract.Invariant(theoremProver != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
+ }
+
+
+ public StratifiedInliningErrorReporter(Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo,
+ ProverInterface theoremProver, VerifierCallback callback,
+ StratifiedInliningInfo mainInfo) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
+ Contract.Requires(theoremProver != null);
+ Contract.Requires(callback != null);
+ Contract.Requires(mainInfo != null);
+ this.implName2StratifiedInliningInfo = implName2StratifiedInliningInfo;
+ this.theoremProver = theoremProver;
+ this.callback = callback;
+ this.mainInfo = mainInfo;
+ this.underapproximationMode = false;
+ this.calls = null;
+ this.candidatesToExpand = new List<int>();
+ }
+
+ public StratifiedInliningErrorReporter(Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo,
+ ProverInterface theoremProver, VerifierCallback callback,
+ StratifiedVC mainVC) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(implName2StratifiedInliningInfo));
+ Contract.Requires(theoremProver != null);
+ Contract.Requires(callback != null);
+ Contract.Requires(mainVC != null);
+ this.implName2StratifiedInliningInfo = implName2StratifiedInliningInfo;
+ this.theoremProver = theoremProver;
+ this.callback = callback;
+ this.mainVC = mainVC;
+ this.underapproximationMode = false;
+ this.candidatesToExpand = new List<int>();
+ }
+
+ public void SetCandidateHandler(FCallHandler calls) {
+ Contract.Requires(calls != null);
+ this.calls = calls;
+ }
+
+ List<Tuple<int, int>> orderedStateIds;
+
+ private Model.Element GetModelValue(Model m, Variable v, int candidateId) {
+ // first, get the unique name
+ string uniqueName;
+
+ VCExprVar vvar = theoremProver.Context.BoogieExprTranslator.TryLookupVariable(v);
+ if (vvar == null) {
+ uniqueName = v.Name;
+ }
+ else {
+ if (candidateId != 0) {
+ Dictionary<VCExprVar, VCExpr> mapping = calls.id2Vars[candidateId];
+ if (mapping.ContainsKey(vvar)) {
+ VCExpr e = mapping[vvar];
+ if (e is VCExprLiteral) {
+ VCExprLiteral lit = (VCExprLiteral)e;
+ return m.MkElement(lit.ToString());
+ }
+ vvar = (VCExprVar)mapping[vvar];
+ }
+ }
+ uniqueName = theoremProver.Context.Lookup(vvar);
+ }
+
+ var f = m.TryGetFunc(uniqueName);
+ if (f == null)
+ return m.MkFunc("@undefined", 0).GetConstant();
+ return f.GetConstant();
+ }
+
+ public readonly static int CALL = -1;
+ public readonly static int RETURN = -2;
+
+ public void PrintModel(Model model) {
+ var filename = CommandLineOptions.Clo.ModelViewFile;
+ if (model == null || filename == null) return;
+
+ if (filename == "-") {
+ model.Write(Console.Out);
+ Console.Out.Flush();
+ }
+ else {
+ using (var wr = new StreamWriter(filename, !Counterexample.firstModelFile)) {
+ Counterexample.firstModelFile = false;
+ model.Write(wr);
+ }
+ }
+ }
+
+ private void GetModelWithStates(Model m) {
+ if (m == null) return;
+ var mvInfo = mainInfo.mvInfo;
+ var mvstates = m.TryGetFunc("$mv_state");
+ if (mvstates == null)
+ return;
+
+ Contract.Assert(mvstates.Arity == 2);
+
+ foreach (Variable v in mvInfo.AllVariables) {
+ m.InitialState.AddBinding(v.Name, GetModelValue(m, v, 0));
+ }
+
+ int lastCandidate = 0;
+ int lastCapturePoint = CALL;
+ for (int i = 0; i < this.orderedStateIds.Count; ++i) {
+ var s = orderedStateIds[i];
+ int candidate = s.Item1;
+ int capturePoint = s.Item2;
+ string implName = calls.getProc(candidate);
+ ModelViewInfo info = candidate == 0 ? mvInfo : implName2StratifiedInliningInfo[implName].mvInfo;
+
+ if (capturePoint == CALL || capturePoint == RETURN) {
+ lastCandidate = candidate;
+ lastCapturePoint = capturePoint;
+ continue;
+ }
+
+ Contract.Assume(0 <= capturePoint && capturePoint < info.CapturePoints.Count);
+ VC.ModelViewInfo.Mapping map = info.CapturePoints[capturePoint];
+ var prevInc = (lastCapturePoint != CALL && lastCapturePoint != RETURN && candidate == lastCandidate)
+ ? info.CapturePoints[lastCapturePoint].IncarnationMap : new Dictionary<Variable, Expr>();
+ var cs = m.MkState(map.Description);
+
+ foreach (Variable v in info.AllVariables) {
+ var e = (Expr)map.IncarnationMap[v];
+
+ if (e == null) {
+ if (lastCapturePoint == CALL || lastCapturePoint == RETURN) {
+ cs.AddBinding(v.Name, GetModelValue(m, v, candidate));
+ }
+ continue;
+ }
+
+ if (lastCapturePoint != CALL && lastCapturePoint != RETURN && prevInc[v] == e) continue; // skip unchanged variables
+
+ Model.Element elt;
+ if (e is IdentifierExpr) {
+ IdentifierExpr ide = (IdentifierExpr)e;
+ elt = GetModelValue(m, ide.Decl, candidate);
+ }
+ else if (e is LiteralExpr) {
+ LiteralExpr lit = (LiteralExpr)e;
+ elt = m.MkElement(lit.Val.ToString());
+ }
+ else {
+ Contract.Assume(false);
+ elt = m.MkFunc(e.ToString(), 0).GetConstant();
+ }
+ cs.AddBinding(v.Name, elt);
+ }
+
+ lastCandidate = candidate;
+ lastCapturePoint = capturePoint;
+ }
+
+ return;
+ }
+
+ public override void OnResourceExceeded(string message, IEnumerable<Tuple<AssertCmd, TransferCmd>> assertCmds = null)
+ {
+ //Contract.Requires(message != null);
+ }
+
+ public override void OnModel(IList<string/*!*/>/*!*/ labels, Model model, ProverInterface.Outcome proverOutcome) {
+ if (CommandLineOptions.Clo.PrintErrorModel >= 1 && model != null) {
+ model.Write(ErrorReporter.ModelWriter);
+ ErrorReporter.ModelWriter.Flush();
+ }
+
+ // Timeout?
+ if (proverOutcome != ProverInterface.Outcome.Invalid)
+ return;
+
+ candidatesToExpand = new List<int>();
+ orderedStateIds = new List<Tuple<int, int>>();
+ var cex = GenerateTrace(labels, model, 0, mainInfo.impl, mainInfo.mvInfo);
+
+ if (underapproximationMode && cex != null) {
+ //Debug.Assert(candidatesToExpand.All(calls.isSkipped));
+ GetModelWithStates(model);
+ callback.OnCounterexample(cex, null);
+ this.PrintModel(model);
+ }
+ }
+
+ private Counterexample GenerateTrace(IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel,
+ int candidateId, Implementation procImpl, ModelViewInfo mvInfo) {
+ Contract.Requires(cce.NonNullElements(labels));
+ Contract.Requires(procImpl != null);
+
+ Hashtable traceNodes = new Hashtable();
+
+ if (!CommandLineOptions.Clo.SIBoolControlVC)
+ {
+ foreach (string s in labels)
+ {
+ Contract.Assert(s != null);
+ var absylabel = calls.ParseRenamedAbsyLabel(s, candidateId);
+
+ if (absylabel == null) continue;
+
+ Absy absy;
+
+ if (candidateId == 0)
+ {
+ absy = Label2Absy(absylabel);
+ }
+ else
+ {
+ absy = Label2Absy(procImpl.Name, absylabel);
+ }
+
+ if (traceNodes.ContainsKey(absy))
+ System.Console.WriteLine("Warning: duplicate label: " + s + " read while tracing nodes");
+ else
+ traceNodes.Add(absy, null);
+ }
+ }
+ else
+ {
+ Debug.Assert(CommandLineOptions.Clo.UseProverEvaluate, "Must use prover evaluate option with boolControlVC");
+ var block = procImpl.Blocks[0];
+ traceNodes.Add(block, null);
+ while (true)
+ {
+ var gc = block.TransferCmd as GotoCmd;
+ if (gc == null) break;
+ Block next = null;
+ foreach (var succ in gc.labelTargets)
+ {
+ var succtaken = (bool) theoremProver.Evaluate(calls.candiate2block2controlVar[candidateId][succ]);
+ if (succtaken)
+ {
+ next = succ;
+ traceNodes.Add(succ, null);
+ break;
+ }
+ }
+ Debug.Assert(next != null, "Must find a successor");
+ Debug.Assert(traceNodes.ContainsKey(next), "CFG cannot be cyclic");
+ block = next;
+ }
+ }
+
+ List<Block> trace = new List<Block>();
+ Block entryBlock = cce.NonNull(procImpl.Blocks[0]);
+ Contract.Assert(entryBlock != null);
+ Contract.Assert(traceNodes.Contains(entryBlock));
+ trace.Add(entryBlock);
+
+ var calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
+ Counterexample newCounterexample = GenerateTraceRec(labels, errModel, mvInfo, candidateId, entryBlock, traceNodes, trace, calleeCounterexamples);
+
+ return newCounterexample;
+ }
+
+ private Counterexample GenerateTraceRec(
+ IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel, ModelViewInfo mvInfo,
+ int candidateId,
+ Block/*!*/ b, Hashtable/*!*/ traceNodes, List<Block>/*!*/ trace,
+ Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples) {
+ Contract.Requires(cce.NonNullElements(labels));
+ Contract.Requires(b != null);
+ Contract.Requires(traceNodes != null);
+ Contract.Requires(trace != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(calleeCounterexamples));
+ // After translation, all potential errors come from asserts.
+ while (true) {
+ List<Cmd> cmds = b.Cmds;
+ TransferCmd transferCmd = cce.NonNull(b.TransferCmd);
+ for (int i = 0; i < cmds.Count; i++) {
+ Cmd cmd = cce.NonNull(cmds[i]);
+
+ // Skip if 'cmd' not contained in the trace or not an assert
+ if ((cmd is AssertCmd && traceNodes.Contains(cmd)) ||
+ (cmd is AssumeCmd && QKeyValue.FindBoolAttribute((cmd as AssumeCmd).Attributes, "exitAssert")))
+ {
+ var acmd = cmd as AssertCmd;
+ if (acmd == null) { acmd = new AssertCmd(Token.NoToken, Expr.True); }
+ Counterexample newCounterexample = AssertCmdToCounterexample(acmd, transferCmd, trace, errModel, mvInfo, theoremProver.Context);
+ newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
+ return newCounterexample;
+ }
+
+ // Counterexample generation for inlined procedures
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd == null)
+ continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null)
+ continue;
+ string calleeName = naryExpr.Fun.FunctionName;
+ Contract.Assert(calleeName != null);
+
+ BinaryOperator binOp = naryExpr.Fun as BinaryOperator;
+ if (binOp != null && binOp.Op == BinaryOperator.Opcode.And) {
+ Expr expr = naryExpr.Args[0];
+ NAryExpr mvStateExpr = expr as NAryExpr;
+ if (mvStateExpr != null && mvStateExpr.Fun.FunctionName == ModelViewInfo.MVState_FunctionDef.Name) {
+ LiteralExpr x = mvStateExpr.Args[1] as LiteralExpr;
+ orderedStateIds.Add(new Tuple<int, int>(candidateId, x.asBigNum.ToInt));
+ }
+ }
+
+ if (calleeName.StartsWith(recordProcName) && (errModel != null || CommandLineOptions.Clo.UseProverEvaluate)) {
+ var expr = calls.recordExpr2Var[new BoogieCallExpr(naryExpr, candidateId)];
+
+ // Record concrete value of the argument to this procedure
+ var args = new List<object>();
+ if (errModel == null && CommandLineOptions.Clo.UseProverEvaluate)
+ {
+ object exprv;
+ try
+ {
+ exprv = theoremProver.Evaluate(expr);
+ }
+ catch (Exception)
+ {
+ exprv = null;
+ }
+ args.Add(exprv);
+ }
+ else
+ {
+ if (expr is VCExprIntLit)
+ {
+ args.Add(errModel.MkElement((expr as VCExprIntLit).Val.ToString()));
+ }
+ else if (expr == VCExpressionGenerator.True)
+ {
+ args.Add(errModel.MkElement("true"));
+ }
+ else if (expr == VCExpressionGenerator.False)
+ {
+ args.Add(errModel.MkElement("false"));
+ }
+ else if (expr is VCExprVar)
+ {
+ var idExpr = expr as VCExprVar;
+ string name = theoremProver.Context.Lookup(idExpr);
+ Contract.Assert(name != null);
+ Model.Func f = errModel.TryGetFunc(name);
+ if (f != null)
+ {
+ args.Add(f.GetConstant());
+ }
+ }
+ else
+ {
+ Contract.Assert(false);
+ }
+ }
+ calleeCounterexamples[new TraceLocation(trace.Count - 1, i)] =
+ new CalleeCounterexampleInfo(null, args);
+ continue;
+ }
+
+ if (!implName2StratifiedInliningInfo.ContainsKey(calleeName))
+ continue;
+
+ Contract.Assert(calls != null);
+
+ int calleeId = calls.boogieExpr2Id[new BoogieCallExpr(naryExpr, candidateId)];
+
+ if (calls.currCandidates.Contains(calleeId)) {
+ candidatesToExpand.Add(calleeId);
+ }
+ else {
+ orderedStateIds.Add(new Tuple<int, int>(calleeId, StratifiedInliningErrorReporter.CALL));
+ var calleeInfo = implName2StratifiedInliningInfo[calleeName];
+ calleeCounterexamples[new TraceLocation(trace.Count - 1, i)] =
+ new CalleeCounterexampleInfo(GenerateTrace(labels, errModel, calleeId, calleeInfo.impl, calleeInfo.mvInfo), new List<object>());
+ orderedStateIds.Add(new Tuple<int, int>(candidateId, StratifiedInliningErrorReporter.RETURN));
+ }
+ }
+
+ GotoCmd gotoCmd = transferCmd as GotoCmd;
+ if (gotoCmd != null) {
+ b = null;
+ foreach (Block bb in cce.NonNull(gotoCmd.labelTargets)) {
+ Contract.Assert(bb != null);
+ if (traceNodes.Contains(bb)) {
+ trace.Add(bb);
+ b = bb;
+ break;
+ }
+ }
+ if (b != null) continue;
+ }
+ return null;
+ }
+ }
+
+ public override Absy Label2Absy(string label) {
+ //Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ int id = int.Parse(label);
+ Contract.Assert(calls != null);
+ return cce.NonNull((Absy)calls.mainLabel2absy[id]);
+ }
+
+ public Absy Label2Absy(string procName, string label) {
+ Contract.Requires(label != null);
+ Contract.Requires(procName != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ int id = int.Parse(label);
+ Dictionary<int, Absy> l2a = cce.NonNull(implName2StratifiedInliningInfo[procName]).label2absy;
+ return cce.NonNull((Absy)l2a[id]);
+ }
+
+ public override void OnProverWarning(string msg) {
+ //Contract.Requires(msg != null);
+ callback.OnWarning(msg);
+ }
+ }
+
+ } // class StratifiedVCGen
+
+ public class EmptyErrorHandler : ProverInterface.ErrorHandler
+ {
+ public override void OnModel(IList<string> labels, Model model, ProverInterface.Outcome proverOutcome)
+ { }
+ }
+
+ public class InvalidProgramForSecureVc : Exception
+ {
+ public InvalidProgramForSecureVc(string msg) :
+ base(msg) { }
+ }
+
+ public class SecureVCGen : VCGen
+ {
+ // Z3
+ ProverInterface prover;
+ // Handler
+ ErrorReporter handler;
+ // dump file
+ public static TokenTextWriter outfile = null;
+
+
+ public SecureVCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
+ : base(program, logFilePath, appendLogFile, checkers)
+ {
+ prover = null;
+ handler = null;
+ if (CommandLineOptions.Clo.SecureVcGen != "" && outfile == null)
+ {
+ outfile = new TokenTextWriter(new StreamWriter(CommandLineOptions.Clo.SecureVcGen));
+ CommandLineOptions.Clo.PrintInstrumented = true;
+ var implsToVerify = new HashSet<string>(
+ program.TopLevelDeclarations.OfType<Implementation>()
+ .Where(impl => !impl.SkipVerification)
+ .Select(impl => impl.Name));
+
+ foreach (var decl in program.TopLevelDeclarations)
+ {
+ if (decl is NamedDeclaration && implsToVerify.Contains((decl as NamedDeclaration).Name))
+ continue;
+ decl.Emit(outfile, 0);
+ }
+ }
+ }
+
+ private Block GetExitBlock(Implementation impl)
+ {
+ var exitblocks = impl.Blocks.Where(blk => blk.TransferCmd is ReturnCmd);
+ if (exitblocks.Count() == 1)
+ return exitblocks.First();
+ // create a new exit block
+ var eb = new Block(Token.NoToken, "SVCeb", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ foreach (var b in exitblocks)
+ {
+ b.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { eb });
+ }
+ impl.Blocks.Add(eb);
+ return eb;
+ }
+
+ //static int LocalVarCounter = 0;
+ private LocalVariable GetNewLocal(Variable v, string suffix)
+ {
+ return new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
+ string.Format("svc_{0}_{1}", v.Name, suffix), v.TypedIdent.Type));
+ }
+
+ private void GenVc(Implementation impl, VerifierCallback collector)
+ {
+ if (impl.Proc.Requires.Any())
+ throw new InvalidProgramForSecureVc("SecureVc: Requires not supported");
+ if(impl.LocVars.Any(v => isVisible(v)))
+ throw new InvalidProgramForSecureVc("SecureVc: Visible Local variables not allowed");
+
+ // Desugar procedure calls
+ DesugarCalls(impl);
+
+ // Gather spec, remove existing ensures
+ var secureAsserts = new List<AssertCmd>();
+ var logicalAsserts = new List<AssertCmd>();
+
+ foreach (var ens in impl.Proc.Ensures)
+ {
+ if(ens.Free)
+ throw new InvalidProgramForSecureVc("SecureVc: Free Ensures not supported");
+ var dd = new Duplicator();
+ secureAsserts.Add(new AssertCmd(ens.tok, Expr.Not(ens.Condition)));
+ logicalAsserts.Add(dd.VisitAssertCmd(new AssertCmd(ens.tok, ens.Condition)) as AssertCmd);
+ }
+ impl.Proc.Ensures.Clear();
+
+ // Make a copy of the impl
+ var dup = new Duplicator();
+ var implDup = dup.VisitImplementation(impl);
+
+ // Get exit block
+ var eb = GetExitBlock(impl);
+
+ // Create two blocks: one for secureAsserts, one for logical asserts
+ var ebSecure = new Block(Token.NoToken, "svc_secure_asserts", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+ var ebLogical = new Block(Token.NoToken, "svc_logical_asserts", new List<Cmd>(), new ReturnCmd(Token.NoToken));
+
+ eb.TransferCmd = new GotoCmd(eb.TransferCmd.tok, new List<Block> { ebSecure, ebLogical });
+ impl.Blocks.Add(ebSecure);
+ impl.Blocks.Add(ebLogical);
+
+ // Rename spec, while create copies of the hidden variables
+ var substOld = new Dictionary<Variable, Expr>();
+ var substVarSpec = new Dictionary<Variable, Expr>();
+ var substVarPath = new Dictionary<Variable, Expr>();
+ foreach (var g in program.GlobalVariables)
+ {
+ if (!isHidden(g)) continue;
+ var lv = GetNewLocal(g, "In");
+ impl.LocVars.Add(lv);
+ substOld.Add(g, Expr.Ident(lv));
+ }
+
+ for(int i = 0; i < impl.InParams.Count; i++)
+ {
+ var v = impl.Proc.InParams[i];
+ if (!isHidden(v))
+ {
+ substVarSpec.Add(impl.Proc.InParams[i], Expr.Ident(impl.InParams[i]));
+ continue;
+ }
+
+ var lv = GetNewLocal(v, "In");
+ impl.LocVars.Add(lv);
+ substVarSpec.Add(v, Expr.Ident(lv));
+ substVarPath.Add(impl.InParams[i], Expr.Ident(lv));
+ }
+
+ for (int i = 0; i < impl.OutParams.Count; i++)
+ {
+ var v = impl.Proc.OutParams[i];
+ if (!isHidden(v))
+ {
+ substVarSpec.Add(impl.Proc.OutParams[i], Expr.Ident(impl.OutParams[i]));
+ continue;
+ }
+
+ var lv = GetNewLocal(v, "Out");
+ impl.LocVars.Add(lv);
+ substVarSpec.Add(v, Expr.Ident(lv));
+ substVarPath.Add(impl.OutParams[i], Expr.Ident(lv));
+ }
+
+ foreach (var g in program.GlobalVariables)
+ {
+ if (!isHidden(g)) continue;
+ if (!impl.Proc.Modifies.Any(ie => ie.Name == g.Name)) continue;
+
+ var lv = GetNewLocal(g, "Out");
+ impl.LocVars.Add(lv);
+ substVarSpec.Add(g, Expr.Ident(lv));
+ substVarPath.Add(g, Expr.Ident(lv));
+ }
+
+ secureAsserts = secureAsserts.ConvertAll(ac =>
+ Substituter.ApplyReplacingOldExprs(
+ Substituter.SubstitutionFromHashtable(substVarSpec),
+ Substituter.SubstitutionFromHashtable(substOld),
+ ac) as AssertCmd);
+
+ var substVarProcToImpl = new Dictionary<Variable, Expr>();
+ for (int i = 0; i < impl.InParams.Count; i++)
+ substVarProcToImpl.Add(impl.Proc.InParams[i], Expr.Ident(impl.InParams[i]));
+
+ for (int i = 0; i < impl.OutParams.Count; i++)
+ substVarProcToImpl.Add(impl.Proc.OutParams[i], Expr.Ident(impl.OutParams[i]));
+
+ logicalAsserts = logicalAsserts.ConvertAll(ac =>
+ Substituter.Apply(Substituter.SubstitutionFromHashtable(substVarProcToImpl), ac)
+ as AssertCmd);
+
+ // Paths
+ foreach (var path in GetAllPaths(implDup))
+ {
+ var wp = ComputeWP(implDup, path);
+
+ // replace hidden variables to match those used in the spec
+ wp = Substituter.ApplyReplacingOldExprs(
+ Substituter.SubstitutionFromHashtable(substVarPath),
+ Substituter.SubstitutionFromHashtable(substOld),
+ wp);
+
+ ebSecure.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(wp)));
+ }
+
+ ebSecure.Cmds.AddRange(secureAsserts);
+ ebLogical.Cmds.AddRange(logicalAsserts);
+
+ if (outfile != null)
+ {
+ impl.Proc.Emit(outfile, 0);
+ impl.Emit(outfile, 0);
+ }
+
+ ModelViewInfo mvInfo;
+ ConvertCFG2DAG(impl);
+ var gotoCmdOrigins = PassifyImpl(impl, out mvInfo);
+
+ var gen = prover.VCExprGen;
+ var exprGen = prover.Context.ExprGen;
+ var translator = prover.Context.BoogieExprTranslator;
+
+ var label2absy = new Dictionary<int, Absy>();
+ VCGen.CodeExprConversionClosure cc = new VCGen.CodeExprConversionClosure(label2absy, prover.Context);
+ translator.SetCodeExprConverter(cc.CodeExprToVerificationCondition);
+ var implVc = gen.Not(GenerateVCAux(impl, null, label2absy, prover.Context));
+
+ handler = new VCGen.ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, incarnationOriginMap, collector, mvInfo, prover.Context, program);
+
+ prover.Assert(implVc, true);
+ }
+
+ Expr ComputeWP(Implementation impl, List<Cmd> path)
+ {
+ Expr expr = Expr.True;
+
+ // create constants for out varibles
+ var subst = new Dictionary<Variable, Expr>();
+ foreach (var g in impl.Proc.Modifies)
+ {
+ var c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
+ "svc_out_const_" + g.Name, g.Decl.TypedIdent.Type));
+ subst.Add(c, g);
+ expr = Expr.And(expr, Expr.Eq(Expr.Ident(c), g));
+ }
+
+ foreach (var v in impl.OutParams)
+ {
+ var c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
+ "svc_out_const_" + v.Name, v.TypedIdent.Type));
+ subst.Add(c, Expr.Ident(v));
+ expr = Expr.And(expr, Expr.Eq(Expr.Ident(c), Expr.Ident(v)));
+ }
+
+ // we need this technicality
+ var subst1 = new Dictionary<Variable, Expr>();
+ foreach (var g in program.GlobalVariables)
+ {
+ subst1.Add(g, new OldExpr(Token.NoToken, Expr.Ident(g)));
+ }
+
+ // Implicitly close with havoc of all the locals and OutParams
+ path.Insert(0, new HavocCmd(Token.NoToken, new List<IdentifierExpr>(
+ impl.LocVars.Select(v => Expr.Ident(v)).Concat(
+ impl.OutParams.Select(v => Expr.Ident(v))))));
+
+ for (int i = path.Count - 1; i >= 0; i--)
+ {
+ var cmd = path[i];
+ if (cmd is AssumeCmd)
+ {
+ expr = Expr.And(expr, (cmd as AssumeCmd).Expr);
+ }
+ else if (cmd is AssignCmd)
+ {
+ var h = new Dictionary<Variable, Expr>();
+ var acmd = cmd as AssignCmd;
+ for (int j = 0; j < acmd.Lhss.Count; j++)
+ {
+ h.Add(acmd.Lhss[j].DeepAssignedVariable, acmd.Rhss[j]);
+ }
+ var s = Substituter.SubstitutionFromHashtable(h);
+ expr = Substituter.Apply(s, expr);
+ }
+ else if (cmd is HavocCmd)
+ {
+ var h = new Dictionary<Variable, Expr>();
+ var formals = new List<Variable>();
+
+ var vc = new VariableCollector();
+ vc.VisitExpr(expr);
+
+ foreach (var ie in (cmd as HavocCmd).Vars)
+ {
+ if (!vc.usedVars.Contains(ie.Decl)) continue;
+ var f = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken,
+ ie.Decl.Name + "_formal", ie.Decl.TypedIdent.Type));
+ h.Add(ie.Decl, Expr.Ident(f));
+ formals.Add(f);
+ }
+ if (!formals.Any())
+ continue;
+ var s = Substituter.SubstitutionFromHashtable(h);
+ expr = Substituter.Apply(s, expr);
+ expr = new ExistsExpr(Token.NoToken, formals, expr);
+ }
+ else
+ {
+ throw new InvalidProgramForSecureVc(string.Format("Unhandled cmd: {0}", cmd));
+ }
+ }
+
+ // Implicitly close with havoc of all the locals and OutParams
+
+
+
+ expr = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst1), expr);
+ expr = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst),
+ Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()), expr);
+ expr.Typecheck(new TypecheckingContext(null));
+ return expr;
+ }
+
+ // Generate all paths in the impl
+ IEnumerable<List<Cmd>> GetAllPaths(Implementation impl)
+ {
+ var stk = new Stack<Tuple<Block, int>>();
+ stk.Push(Tuple.Create(impl.Blocks[0], 0));
+
+ while (stk.Any())
+ {
+ var tup = stk.Peek();
+ if (tup.Item1.TransferCmd is ReturnCmd)
+ {
+ var ret = new List<Cmd>();
+ var ls = stk.ToList();
+ ls.Iter(t => ret.AddRange(t.Item1.Cmds));
+ yield return ret;
+
+ stk.Pop();
+ continue;
+ }
+
+ stk.Pop();
+
+ var gc = tup.Item1.TransferCmd as GotoCmd;
+ if (gc.labelTargets.Count <= tup.Item2)
+ continue;
+
+ stk.Push(Tuple.Create(tup.Item1, tup.Item2 + 1));
+ stk.Push(Tuple.Create(gc.labelTargets[tup.Item2], 0));
+ }
+ yield break;
+ }
+
+ bool isHidden(Variable v)
+ {
+ return QKeyValue.FindBoolAttribute(v.Attributes, "hidden");
+ }
+
+ bool isVisible(Variable v)
+ {
+ return !isHidden(v);
+ }
+
+ public override Outcome VerifyImplementation(Implementation/*!*/ impl, VerifierCallback/*!*/ callback)
+ {
+ Debug.Assert(this.program == program);
+
+ // Record current time
+ var startTime = DateTime.UtcNow;
+
+ CommandLineOptions.Clo.ProverCCLimit = 1;
+ prover = ProverInterface.CreateProver(program, logFilePath, appendLogFile, CommandLineOptions.Clo.ProverKillTime);
+
+ // Flush any axioms that came with the program before we start SI on this implementation
+ prover.AssertAxioms();
+
+ GenVc(impl, callback);
+
+ prover.Check();
+ var outcome = prover.CheckOutcomeCore(handler);
+ //var outcome = ProverInterface.Outcome.Valid;
+
+ prover.Close();
+
+
+
+ //Console.WriteLine("Answer = {0}", outcome);
+
+ return ProverInterfaceOutcomeToConditionGenerationOutcome(outcome);
+ }
+ }
+
+} // namespace VC
diff --git a/Source/VCGeneration/VC.cs b/Source/VCGeneration/VC.cs
index 560f55b4..6e43e917 100644
--- a/Source/VCGeneration/VC.cs
+++ b/Source/VCGeneration/VC.cs
@@ -1,3893 +1,4134 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using System.IO;
-using Microsoft.Boogie;
-using Microsoft.Boogie.GraphUtil;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace VC {
- using Bpl = Microsoft.Boogie;
- using System.Threading.Tasks;
-
- public class VCGen : ConditionGeneration {
- private const bool _print_time = false;
- /// <summary>
- /// Constructor. Initializes the theorem prover.
- /// </summary>
- [NotDelayed]
- public VCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
- : base(program, checkers)
- {
- Contract.Requires(program != null);
- this.appendLogFile = appendLogFile;
- this.logFilePath = logFilePath;
- }
-
- private static AssumeCmd AssertTurnedIntoAssume(AssertCmd assrt) {
- Contract.Requires(assrt != null);
- Contract.Ensures(Contract.Result<AssumeCmd>() != null);
-
- Expr expr = assrt.Expr;
- Contract.Assert(expr != null);
- switch (Wlp.Subsumption(assrt)) {
- case CommandLineOptions.SubsumptionOption.Never:
- expr = Expr.True;
- break;
- case CommandLineOptions.SubsumptionOption.Always:
- break;
- case CommandLineOptions.SubsumptionOption.NotForQuantifiers:
- if (expr is QuantifierExpr) {
- expr = Expr.True;
- }
- break;
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException(); // unexpected case
- }
-
- return new AssumeCmd(assrt.tok, expr);
- }
-
- #region Soundness smoke tester
- class SmokeTester {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(parent != null);
- Contract.Invariant(impl != null);
- Contract.Invariant(initial != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(copies));
- Contract.Invariant(cce.NonNull(visited));
- Contract.Invariant(callback != null);
- }
-
- VCGen parent;
- Implementation impl;
- Block initial;
- int id;
- Dictionary<Block, Block> copies = new Dictionary<Block, Block>();
- HashSet<Block> visited = new HashSet<Block>();
- VerifierCallback callback;
-
- internal SmokeTester(VCGen par, Implementation i, VerifierCallback callback) {
- Contract.Requires(par != null);
- Contract.Requires(i != null);
- Contract.Requires(callback != null);
- parent = par;
- impl = i;
- initial = i.Blocks[0];
- this.callback = callback;
- }
-
- internal void Copy() {
- CloneBlock(impl.Blocks[0]);
- initial = GetCopiedBlocks()[0];
- }
-
- internal void Test() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- DFS(initial);
- }
-
- void TopologicalSortImpl() {
- Graph<Block> dag = new Graph<Block>();
- dag.AddSource(cce.NonNull(impl.Blocks[0])); // there is always at least one node in the graph
- foreach (Block b in impl.Blocks) {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- Contract.Assume(gtc.labelTargets != null);
- foreach (Block dest in gtc.labelTargets) {
- Contract.Assert(dest != null);
- dag.AddEdge(b, dest);
- }
- }
- }
- impl.Blocks = new List<Block>();
- foreach (Block b in dag.TopologicalSort()) {
- Contract.Assert(b != null);
- impl.Blocks.Add(b);
- }
- }
-
- void Emit() {
- TopologicalSortImpl();
- EmitImpl(impl, false);
- }
-
- // this one copies forward
- Block CloneBlock(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<Block>() != null);
-
- Block fake_res;
- if (copies.TryGetValue(b, out fake_res)) {
- return cce.NonNull(fake_res);
- }
- Block res = new Block(b.tok, b.Label, new List<Cmd>(b.Cmds), null);
- copies[b] = res;
- if (b.TransferCmd is GotoCmd) {
- foreach (Block ch in cce.NonNull((GotoCmd)b.TransferCmd).labelTargets) {
- Contract.Assert(ch != null);
- CloneBlock(ch);
- }
- }
- foreach (Block p in b.Predecessors) {
- Contract.Assert(p != null);
- res.Predecessors.Add(CloneBlock(p));
- }
- return res;
- }
-
- // this one copies backwards
- Block CopyBlock(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<Block>() != null);
-
- Block fake_res;
- if (copies.TryGetValue(b, out fake_res)) {
- // fake_res should be Block! but the compiler fails
- return cce.NonNull(fake_res);
- }
- Block res;
- List<Cmd> seq = new List<Cmd>();
- foreach (Cmd c in b.Cmds) {
- Contract.Assert(c != null);
- AssertCmd turn = c as AssertCmd;
- if (!turnAssertIntoAssumes || turn == null) {
- seq.Add(c);
- } else {
- seq.Add(AssertTurnedIntoAssume(turn));
- }
- }
- res = new Block(b.tok, b.Label, seq, null);
- copies[b] = res;
- foreach (Block p in b.Predecessors) {
- Contract.Assert(p != null);
- res.Predecessors.Add(CopyBlock(p));
- }
- return res;
- }
-
- List<Block> GetCopiedBlocks() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
-
- // the order of nodes in res is random (except for the first one, being the entry)
- List<Block> res = new List<Block>();
- res.Add(copies[initial]);
-
- foreach (KeyValuePair<Block, Block> kv in copies) {
- Contract.Assert(kv.Key != null&&kv.Value!=null);
- GotoCmd go = kv.Key.TransferCmd as GotoCmd;
- ReturnCmd ret = kv.Key.TransferCmd as ReturnCmd;
- if (kv.Key != initial) {
- res.Add(kv.Value);
- }
- if (go != null) {
- GotoCmd copy = new GotoCmd(go.tok, new List<String>(), new List<Block>());
- kv.Value.TransferCmd = copy;
- foreach (Block b in cce.NonNull(go.labelTargets)) {
- Contract.Assert(b != null);
- Block c;
- if (copies.TryGetValue(b, out c)) {
- copy.AddTarget(cce.NonNull(c));
- }
- }
- } else if (ret != null) {
- kv.Value.TransferCmd = ret;
- } else {
- Contract.Assume(false);
- throw new cce.UnreachableException();
- }
- }
-
- copies.Clear();
-
- return res;
- }
-
- // check if e is true, false, !true, !false
- // if so return true and the value of the expression in val
- bool BooleanEval(Expr e, ref bool val) {
- Contract.Requires(e != null);
- LiteralExpr lit = e as LiteralExpr;
- NAryExpr call = e as NAryExpr;
-
- if (lit != null && lit.isBool) {
- val = lit.asBool;
- return true;
- } else if (call != null &&
- call.Fun is UnaryOperator &&
- ((UnaryOperator)call.Fun).Op == UnaryOperator.Opcode.Not &&
- BooleanEval(cce.NonNull(call.Args[0]), ref val)) {
- val = !val;
- return true;
- }
- // this is for the 0bv32 != 0bv32 generated by vcc
- else if (call != null &&
- call.Fun is BinaryOperator &&
- ((BinaryOperator)call.Fun).Op == BinaryOperator.Opcode.Neq &&
- call.Args[0] is LiteralExpr &&
- cce.NonNull(call.Args[0]).Equals(call.Args[1])) {
- val = false;
- return true;
- }
-
- return false;
- }
-
- bool IsFalse(Expr e) {
- Contract.Requires(e != null);
- bool val = false;
- return BooleanEval(e, ref val) && !val;
- }
-
- bool CheckUnreachable(Block cur, List<Cmd> seq)
- {
- Contract.Requires(cur != null);
- Contract.Requires(seq != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- foreach (Cmd cmd in seq)
- {
- AssertCmd assrt = cmd as AssertCmd;
- if (assrt != null && QKeyValue.FindBoolAttribute(assrt.Attributes, "PossiblyUnreachable"))
- return false;
- }
-
- DateTime start = DateTime.UtcNow;
- if (CommandLineOptions.Clo.Trace)
- {
- System.Console.Write(" soundness smoke test #{0} ... ", id);
- }
- callback.OnProgress("smoke", id, id, 0.0);
-
- Token tok = new Token();
- tok.val = "soundness smoke test assertion";
- seq.Add(new AssertCmd(tok, Expr.False));
- Block copy = CopyBlock(cur);
- Contract.Assert(copy != null);
- copy.Cmds = seq;
- List<Block> backup = impl.Blocks;
- Contract.Assert(backup != null);
- impl.Blocks = GetCopiedBlocks();
- copy.TransferCmd = new ReturnCmd(Token.NoToken);
- if (CommandLineOptions.Clo.TraceVerify)
- {
- System.Console.WriteLine();
- System.Console.WriteLine(" --- smoke #{0}, before passify", id);
- Emit();
- }
- parent.CurrentLocalVariables = impl.LocVars;
- ModelViewInfo mvInfo;
- parent.PassifyImpl(impl, out mvInfo);
- Dictionary<int, Absy> label2Absy;
- Checker ch = parent.FindCheckerFor(CommandLineOptions.Clo.SmokeTimeout);
- Contract.Assert(ch != null);
-
- ProverInterface.Outcome outcome = ProverInterface.Outcome.Undetermined;
- try
- {
- lock (ch)
- {
- var exprGen = ch.TheoremProver.Context.ExprGen;
- VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
-
- VCExpr vc = parent.GenerateVC(impl, controlFlowVariableExpr, out label2Absy, ch.TheoremProver.Context);
- Contract.Assert(vc != null);
-
- if (!CommandLineOptions.Clo.UseLabels)
- {
- VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
- VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
- vc = exprGen.Implies(eqExpr, vc);
- }
-
- impl.Blocks = backup;
-
- if (CommandLineOptions.Clo.TraceVerify)
- {
- System.Console.WriteLine(" --- smoke #{0}, after passify", id);
- Emit();
- }
-
- ch.BeginCheck(cce.NonNull(impl.Name + "_smoke" + id++), vc, new ErrorHandler(label2Absy, this.callback));
- }
-
- ch.ProverTask.Wait();
-
- lock (ch)
- {
- outcome = ch.ReadOutcome();
- }
- }
- finally
- {
- ch.GoBackToIdle();
- }
-
- parent.CurrentLocalVariables = null;
-
- DateTime end = DateTime.UtcNow;
- TimeSpan elapsed = end - start;
- if (CommandLineOptions.Clo.Trace)
- {
- System.Console.WriteLine(" [{0} s] {1}", elapsed.TotalSeconds,
- outcome == ProverInterface.Outcome.Valid ? "OOPS" :
- "OK" + (outcome == ProverInterface.Outcome.Invalid ? "" : " (" + outcome + ")"));
- }
-
- if (outcome == ProverInterface.Outcome.Valid)
- {
- // copy it again, so we get the version with calls, assignments and such
- copy = CopyBlock(cur);
- copy.Cmds = seq;
- impl.Blocks = GetCopiedBlocks();
- TopologicalSortImpl();
- callback.OnUnreachableCode(impl);
- impl.Blocks = backup;
- return true;
- }
- return false;
- }
-
- const bool turnAssertIntoAssumes = false;
-
- void DFS(Block cur) {
- Contract.Requires(cur != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- if (visited.Contains(cur))
- return;
- visited.Add(cur);
-
- List<Cmd> seq = new List<Cmd>();
- foreach (Cmd cmd_ in cur.Cmds) {
- Cmd cmd = cmd_;
- Contract.Assert(cmd != null);
- AssertCmd assrt = cmd as AssertCmd;
- AssumeCmd assm = cmd as AssumeCmd;
- CallCmd call = cmd as CallCmd;
-
- bool assumeFalse = false;
-
- if (assrt != null) {
- // we're not going any further
- // it's clear the user expected unreachable code here
- // it's not clear where did he expect it, maybe it would be right to insert
- // a check just one command before
- if (IsFalse(assrt.Expr))
- return;
-
-#if TURN_ASSERT_INFO_ASSUMES
- if (turnAssertIntoAssumes) {
- cmd = AssertTurnedIntoAssume(assrt);
- }
-#endif
- } else if (assm != null) {
- if (IsFalse(assm.Expr))
- assumeFalse = true;
- } else if (call != null) {
- foreach (Ensures e in (cce.NonNull(call.Proc)).Ensures) {
- Contract.Assert(e != null);
- if (IsFalse(e.Condition))
- assumeFalse = true;
- }
- }
-
- if (assumeFalse) {
- CheckUnreachable(cur, seq);
- return;
- }
-
- seq.Add(cmd);
- }
-
-
- GotoCmd go = cur.TransferCmd as GotoCmd;
- ReturnCmd ret = cur.TransferCmd as ReturnCmd;
-
- Contract.Assume(!(go != null && go.labelTargets == null && go.labelNames != null && go.labelNames.Count > 0));
-
- if (ret != null || (go != null && cce.NonNull(go.labelTargets).Count == 0)) {
- // we end in return, so there will be no more places to check
- CheckUnreachable(cur, seq);
- } else if (go != null) {
- bool needToCheck = true;
- // if all of our children have more than one parent, then
- // we're in the right place to check
- foreach (Block target in cce.NonNull(go.labelTargets)) {
- Contract.Assert(target != null);
- if (target.Predecessors.Count == 1) {
- needToCheck = false;
- }
- }
- if (needToCheck) {
- CheckUnreachable(cur, seq);
- }
- foreach (Block target in go.labelTargets) {
- Contract.Assert(target != null);
- DFS(target);
- }
- }
- }
-
- class ErrorHandler : ProverInterface.ErrorHandler {
- Dictionary<int, Absy> label2Absy;
- VerifierCallback callback;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(label2Absy != null);
- Contract.Invariant(callback != null);
- }
-
-
- public ErrorHandler(Dictionary<int, Absy> label2Absy, VerifierCallback callback) {
- Contract.Requires(label2Absy != null);
- Contract.Requires(callback != null);
- this.label2Absy = label2Absy;
- this.callback = callback;
- }
-
- public override Absy Label2Absy(string label) {
- //Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- int id = int.Parse(label);
- return cce.NonNull((Absy)label2Absy[id]);
- }
-
- public override void OnProverWarning(string msg) {
- //Contract.Requires(msg != null);
- this.callback.OnWarning(msg);
- }
- }
- }
-
-
- #endregion
-
- #region Splitter
- class Split {
- class BlockStats {
- public bool big_block;
- public int id;
- public double assertion_cost;
- public double assumption_cost; // before multiplier
- public double incomming_paths;
- public List<Block>/*!>!*/ virtual_successors = new List<Block>();
- public List<Block>/*!>!*/ virtual_predecesors = new List<Block>();
- public HashSet<Block> reachable_blocks;
- public readonly Block block;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(virtual_successors));
- Contract.Invariant(cce.NonNullElements(virtual_predecesors));
- Contract.Invariant(block != null);
- }
-
-
- public BlockStats(Block b, int i) {
- Contract.Requires(b != null);
- block = b;
- assertion_cost = -1;
- id = i;
- }
- }
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(blocks));
- Contract.Invariant(cce.NonNullElements(big_blocks));
- Contract.Invariant(cce.NonNullDictionaryAndValues(stats));
- Contract.Invariant(cce.NonNullElements(assumized_branches));
- Contract.Invariant(gotoCmdOrigins != null);
- Contract.Invariant(parent != null);
- Contract.Invariant(impl != null);
- Contract.Invariant(copies != null);
- Contract.Invariant(cce.NonNull(protected_from_assert_to_assume));
- Contract.Invariant(cce.NonNull(keep_at_all));
- }
-
-
- readonly List<Block> blocks;
- readonly List<Block> big_blocks = new List<Block>();
- readonly Dictionary<Block/*!*/, BlockStats/*!*/>/*!*/ stats = new Dictionary<Block/*!*/, BlockStats/*!*/>();
- readonly int id;
- static int current_id = -1;
- Block split_block;
- bool assert_to_assume;
- List<Block/*!*/>/*!*/ assumized_branches = new List<Block/*!*/>();
-
- double score;
- bool score_computed;
- double total_cost;
- int assertion_count;
- double assertion_cost; // without multiplication by paths
- Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins;
- readonly public VCGen/*!*/ parent;
- Implementation/*!*/ impl;
-
- Dictionary<Block/*!*/, Block/*!*/>/*!*/ copies = new Dictionary<Block/*!*/, Block/*!*/>();
- bool doing_slice;
- double slice_initial_limit;
- double slice_limit;
- bool slice_pos;
- HashSet<Block/*!*/>/*!*/ protected_from_assert_to_assume = new HashSet<Block/*!*/>();
- HashSet<Block/*!*/>/*!*/ keep_at_all = new HashSet<Block/*!*/>();
-
- // async interface
- private Checker checker;
- private int splitNo;
- internal ErrorReporter reporter;
-
- public Split(List<Block/*!*/>/*!*/ blocks, Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins, VCGen/*!*/ par, Implementation/*!*/ impl) {
- Contract.Requires(cce.NonNullElements(blocks));
- Contract.Requires(gotoCmdOrigins != null);
- Contract.Requires(par != null);
- Contract.Requires(impl != null);
- this.blocks = blocks;
- this.gotoCmdOrigins = gotoCmdOrigins;
- this.parent = par;
- this.impl = impl;
- this.id = Interlocked.Increment(ref current_id);
- }
-
- public double Cost {
- get {
- ComputeBestSplit();
- return total_cost;
- }
- }
-
- public bool LastChance {
- get {
- ComputeBestSplit();
- return assertion_count == 1 && score < 0;
- }
- }
-
- public string Stats {
- get {
- ComputeBestSplit();
- return string.Format("(cost:{0:0}/{1:0}{2})", total_cost, assertion_cost, LastChance ? " last" : "");
- }
- }
-
- public void DumpDot(int no) {
- using (System.IO.StreamWriter sw = System.IO.File.CreateText(string.Format("split.{0}.dot", no))) {
- sw.WriteLine("digraph G {");
-
- ComputeBestSplit();
- List<Block> saved = assumized_branches;
- Contract.Assert(saved != null);
- assumized_branches = new List<Block>();
- DoComputeScore(false);
- assumized_branches = saved;
-
- foreach (Block b in big_blocks) {
- Contract.Assert(b != null);
- BlockStats s = GetBlockStats(b);
- foreach (Block t in s.virtual_successors) {
- Contract.Assert(t != null);
- sw.WriteLine("n{0} -> n{1};", s.id, GetBlockStats(t).id);
- }
- sw.WriteLine("n{0} [label=\"{1}:\\n({2:0.0}+{3:0.0})*{4:0.0}\"{5}];",
- s.id, b.Label,
- s.assertion_cost, s.assumption_cost, s.incomming_paths,
- s.assertion_cost > 0 ? ",shape=box" : "");
-
- }
- sw.WriteLine("}");
- sw.Close();
- }
-
- string filename = string.Format("split.{0}.bpl", no);
- using (System.IO.StreamWriter sw = System.IO.File.CreateText(filename)) {
- int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
- CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
- bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
- CommandLineOptions.Clo.PrintDesugarings = false;
- List<Block> backup = impl.Blocks;
- Contract.Assert(backup != null);
- impl.Blocks = blocks;
- impl.Emit(new TokenTextWriter(filename, sw, /*setTokens=*/ false, /*pretty=*/ false), 0);
- impl.Blocks = backup;
- CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
- CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
- }
- }
-
- int bsid;
- BlockStats GetBlockStats(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<BlockStats>() != null);
-
- BlockStats s;
- if (!stats.TryGetValue(b, out s)) {
- s = new BlockStats(b, bsid++);
- stats[b] = s;
- }
- return cce.NonNull(s);
- }
-
- double AssertionCost(PredicateCmd c) {
- return 1.0;
- }
-
- void CountAssertions(Block b) {
- Contract.Requires(b != null);
- BlockStats s = GetBlockStats(b);
- if (s.assertion_cost >= 0)
- return; // already done
- s.big_block = true;
- s.assertion_cost = 0;
- s.assumption_cost = 0;
- foreach (Cmd c in b.Cmds) {
- if (c is AssertCmd) {
- double cost = AssertionCost((AssertCmd)c);
- s.assertion_cost += cost;
- assertion_count++;
- assertion_cost += cost;
- } else if (c is AssumeCmd) {
- s.assumption_cost += AssertionCost((AssumeCmd)c);
- }
- }
- foreach (Block c in Exits(b)) {
- Contract.Assert(c != null);
- s.virtual_successors.Add(c);
- }
- if (s.virtual_successors.Count == 1) {
- Block next = s.virtual_successors[0];
- BlockStats se = GetBlockStats(next);
- CountAssertions(next);
- if (next.Predecessors.Count > 1 || se.virtual_successors.Count != 1)
- return;
- s.virtual_successors[0] = se.virtual_successors[0];
- s.assertion_cost += se.assertion_cost;
- s.assumption_cost += se.assumption_cost;
- se.big_block = false;
- }
- }
-
- HashSet<Block/*!*/>/*!*/ ComputeReachableNodes(Block/*!*/ b) {
- Contract.Requires(b != null);
- Contract.Ensures(cce.NonNull(Contract.Result<HashSet<Block/*!*/>>()));
- BlockStats s = GetBlockStats(b);
- if (s.reachable_blocks != null) {
- return s.reachable_blocks;
- }
- HashSet<Block/*!*/> blocks = new HashSet<Block/*!*/>();
- s.reachable_blocks = blocks;
- blocks.Add(b);
- foreach (Block/*!*/ succ in Exits(b)) {
- Contract.Assert(succ != null);
- foreach (Block r in ComputeReachableNodes(succ)) {
- Contract.Assert(r != null);
- blocks.Add(r);
- }
- }
- return blocks;
- }
-
- double ProverCost(double vc_cost) {
- return vc_cost * vc_cost;
- }
-
- void ComputeBestSplit() {
- if (score_computed)
- return;
- score_computed = true;
-
- assertion_count = 0;
-
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- CountAssertions(b);
- }
-
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- BlockStats bs = GetBlockStats(b);
- if (bs.big_block) {
- big_blocks.Add(b);
- foreach (Block ch in bs.virtual_successors) {
- Contract.Assert(ch != null);
- BlockStats chs = GetBlockStats(ch);
- if (!chs.big_block) {
- Console.WriteLine("non-big {0} accessed from {1}", ch, b);
- DumpDot(-1);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- chs.virtual_predecesors.Add(b);
- }
- }
- }
-
- assumized_branches.Clear();
- total_cost = ProverCost(DoComputeScore(false));
-
- score = double.PositiveInfinity;
- Block best_split = null;
- List<Block> saved_branches = new List<Block>();
-
- foreach (Block b in big_blocks) {
- Contract.Assert(b != null);
- GotoCmd gt = b.TransferCmd as GotoCmd;
- if (gt == null)
- continue;
- List<Block> targ = cce.NonNull(gt.labelTargets);
- if (targ.Count < 2)
- continue;
- // caution, we only consider two first exits
-
- double left0, right0, left1, right1;
- split_block = b;
-
- assumized_branches.Clear();
- assumized_branches.Add(cce.NonNull(targ[0]));
- left0 = DoComputeScore(true);
- right0 = DoComputeScore(false);
-
- assumized_branches.Clear();
- for (int idx = 1; idx < targ.Count; idx++) {
- assumized_branches.Add(cce.NonNull(targ[idx]));
- }
- left1 = DoComputeScore(true);
- right1 = DoComputeScore(false);
-
- double current_score = ProverCost(left1) + ProverCost(right1);
- double other_score = ProverCost(left0) + ProverCost(right0);
-
- if (other_score < current_score) {
- current_score = other_score;
- assumized_branches.Clear();
- assumized_branches.Add(cce.NonNull(targ[0]));
- }
-
- if (current_score < score) {
- score = current_score;
- best_split = split_block;
- saved_branches.Clear();
- saved_branches.AddRange(assumized_branches);
- }
- }
-
- if (CommandLineOptions.Clo.VcsPathSplitMult * score > total_cost) {
- split_block = null;
- score = -1;
- } else {
- assumized_branches = saved_branches;
- split_block = best_split;
- }
- }
-
- void UpdateIncommingPaths(BlockStats s) {
- Contract.Requires(s != null);
- if (s.incomming_paths < 0.0) {
- int count = 0;
- s.incomming_paths = 0.0;
- if (!keep_at_all.Contains(s.block))
- return;
- foreach (Block b in s.virtual_predecesors) {
- Contract.Assert(b != null);
- BlockStats ch = GetBlockStats(b);
- Contract.Assert(ch != null);
- UpdateIncommingPaths(ch);
- if (ch.incomming_paths > 0.0) {
- s.incomming_paths += ch.incomming_paths;
- count++;
- }
- }
- if (count > 1) {
- s.incomming_paths *= CommandLineOptions.Clo.VcsPathJoinMult;
- }
- }
- }
-
- void ComputeBlockSetsHelper(Block b, bool allow_small) {
- Contract.Requires(b != null);
- if (keep_at_all.Contains(b))
- return;
- keep_at_all.Add(b);
-
- if (allow_small) {
- foreach (Block ch in Exits(b)) {
- Contract.Assert(ch != null);
- if (b == split_block && assumized_branches.Contains(ch))
- continue;
- ComputeBlockSetsHelper(ch, allow_small);
- }
- } else {
- foreach (Block ch in GetBlockStats(b).virtual_successors) {
- Contract.Assert(ch != null);
- if (b == split_block && assumized_branches.Contains(ch))
- continue;
- ComputeBlockSetsHelper(ch, allow_small);
- }
- }
- }
-
- void ComputeBlockSets(bool allow_small) {
- protected_from_assert_to_assume.Clear();
- keep_at_all.Clear();
-
- Debug.Assert(split_block == null || GetBlockStats(split_block).big_block);
- Debug.Assert(GetBlockStats(blocks[0]).big_block);
-
- if (assert_to_assume) {
- foreach (Block b in allow_small ? blocks : big_blocks) {
- Contract.Assert(b != null);
- if (ComputeReachableNodes(b).Contains(cce.NonNull(split_block))) {
- keep_at_all.Add(b);
- }
- }
-
- foreach (Block b in assumized_branches) {
- Contract.Assert(b != null);
- foreach (Block r in ComputeReachableNodes(b)) {
- Contract.Assert(r != null);
- if (allow_small || GetBlockStats(r).big_block) {
- keep_at_all.Add(r);
- protected_from_assert_to_assume.Add(r);
- }
- }
- }
- } else {
- ComputeBlockSetsHelper(blocks[0], allow_small);
- }
- }
-
- bool ShouldAssumize(Block b) {
- Contract.Requires(b != null);
- return assert_to_assume && !protected_from_assert_to_assume.Contains(b);
- }
-
- double DoComputeScore(bool aa) {
- assert_to_assume = aa;
- ComputeBlockSets(false);
-
- foreach (Block b in big_blocks) {
- Contract.Assert(b != null);
- GetBlockStats(b).incomming_paths = -1.0;
- }
-
- GetBlockStats(blocks[0]).incomming_paths = 1.0;
-
- double cost = 0.0;
- foreach (Block b in big_blocks) {
- Contract.Assert(b != null);
- if (keep_at_all.Contains(b)) {
- BlockStats s = GetBlockStats(b);
- UpdateIncommingPaths(s);
- double local = s.assertion_cost;
- if (ShouldAssumize(b)) {
- local = (s.assertion_cost + s.assumption_cost) * CommandLineOptions.Clo.VcsAssumeMult;
- } else {
- local = s.assumption_cost * CommandLineOptions.Clo.VcsAssumeMult + s.assertion_cost;
- }
- local = local + local * s.incomming_paths * CommandLineOptions.Clo.VcsPathCostMult;
- cost += local;
- }
- }
-
- return cost;
- }
-
- List<Cmd> SliceCmds(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
-
- List<Cmd> seq = b.Cmds;
- Contract.Assert(seq != null);
- if (!doing_slice && !ShouldAssumize(b))
- return seq;
- List<Cmd> res = new List<Cmd>();
- foreach (Cmd c in seq) {
- Contract.Assert(c != null);
- AssertCmd a = c as AssertCmd;
- Cmd the_new = c;
- bool swap = false;
- if (a != null) {
- if (doing_slice) {
- double cost = AssertionCost(a);
- bool first = (slice_limit - cost) >= 0 || slice_initial_limit == slice_limit;
- slice_limit -= cost;
- swap = slice_pos == first;
- } else if (assert_to_assume) {
- swap = true;
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- if (swap) {
- the_new = AssertTurnedIntoAssume(a);
- }
- }
- res.Add(the_new);
- }
- return res;
- }
-
- Block CloneBlock(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<Block>() != null);
-
- Block res;
- if (copies.TryGetValue(b, out res)) {
- return cce.NonNull(res);
- }
- res = new Block(b.tok, b.Label, SliceCmds(b), b.TransferCmd);
- GotoCmd gt = b.TransferCmd as GotoCmd;
- copies[b] = res;
- if (gt != null) {
- GotoCmd newGoto = new GotoCmd(gt.tok, new List<String>(), new List<Block>());
- res.TransferCmd = newGoto;
- int pos = 0;
- foreach (Block ch in cce.NonNull(gt.labelTargets)) {
- Contract.Assert(ch != null);
- Contract.Assert(doing_slice ||
- (assert_to_assume || (keep_at_all.Contains(ch) || assumized_branches.Contains(ch))));
- if (doing_slice ||
- ((b != split_block || assumized_branches.Contains(ch) == assert_to_assume) &&
- keep_at_all.Contains(ch))) {
- newGoto.AddTarget(CloneBlock(ch));
- }
- pos++;
- }
- }
- return res;
- }
-
- Split DoSplit() {
- Contract.Ensures(Contract.Result<Split>() != null);
-
- copies.Clear();
- CloneBlock(blocks[0]);
- List<Block> newBlocks = new List<Block>();
- Dictionary<TransferCmd, ReturnCmd> newGotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>();
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- Block tmp;
- if (copies.TryGetValue(b, out tmp)) {
- newBlocks.Add(cce.NonNull(tmp));
- if (gotoCmdOrigins.ContainsKey(b.TransferCmd)) {
- newGotoCmdOrigins[tmp.TransferCmd] = gotoCmdOrigins[b.TransferCmd];
- }
-
- foreach (Block p in b.Predecessors) {
- Contract.Assert(p != null);
- Block tmp2;
- if (copies.TryGetValue(p, out tmp2)) {
- tmp.Predecessors.Add(tmp2);
- }
- }
- }
- }
-
- return new Split(newBlocks, newGotoCmdOrigins, parent, impl);
- }
-
- Split SplitAt(int idx) {
- Contract.Ensures(Contract.Result<Split>() != null);
-
- assert_to_assume = idx == 0;
- doing_slice = false;
- ComputeBlockSets(true);
-
- return DoSplit();
- }
-
- Split SliceAsserts(double limit, bool pos) {
- Contract.Ensures(Contract.Result<Split>() != null);
-
- slice_pos = pos;
- slice_limit = limit;
- slice_initial_limit = limit;
- doing_slice = true;
- Split r = DoSplit();
- /*
- Console.WriteLine("split {0} / {1} -->", limit, pos);
- List<Block!> tmp = impl.Blocks;
- impl.Blocks = r.blocks;
- EmitImpl(impl, false);
- impl.Blocks = tmp;
- */
-
- return r;
- }
-
- void Print() {
- List<Block> tmp = impl.Blocks;
- Contract.Assert(tmp != null);
- impl.Blocks = blocks;
- EmitImpl(impl, false);
- impl.Blocks = tmp;
- }
-
- public Counterexample ToCounterexample(ProverContext context) {
- Contract.Requires(context != null);
- Contract.Ensures(Contract.Result<Counterexample>() != null);
-
- List<Block> trace = new List<Block>();
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- trace.Add(b);
- }
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- foreach (Cmd c in b.Cmds) {
- Contract.Assert(c != null);
- if (c is AssertCmd) {
- return AssertCmdToCounterexample((AssertCmd)c, cce.NonNull(b.TransferCmd), trace, null, null, context);
- }
- }
- }
- Contract.Assume(false);
- throw new cce.UnreachableException();
- }
-
- /// <summary>
- /// Starting from the 0-index "split_here" annotation in begin, verifies until it reaches a subsequent "split_here" annotation
- /// Returns a list of blocks where all code not verified has asserts converted into assumes
- /// </summary>
- /// <param name="blocks">Implementation's collection of blocks</param>
- /// <param name="begin">Block containing the first split_here from which to start verifying</param>
- /// <param name="begin_split_id">0-based ID of the "split_here" annotation within begin at which to start verifying</param>
- /// <param name="blockInternalSplit">True if the entire split is contained within block begin</param>
- /// <param name="endPoints">Set of all blocks containing a "split_here" annotation</param>
- /// <returns></returns>
- // Note: Current implementation may over report errors.
- // For example, if the control flow graph is a diamond (e.g., A -> B, C, B->D, C->D),
- // and there is a split in B and an error in D, then D will be verified twice and hence report the error twice.
- // Best solution may be to memoize blocks that have been fully verified and be sure not to verify them again
- private static List<Block> DoManualSplit(List<Block> blocks, Block begin, int begin_split_id, bool blockInternalSplit, IEnumerable<Block> endPoints) {
- // Compute the set of blocks reachable from begin but not included in endPoints. These will be verified in their entirety.
- var blocksToVerifyEntirely = new HashSet<Block>();
- var reachableEndPoints = new HashSet<Block>(); // Reachable end points will be verified up to their first split point
- var todo = new Stack<Block>();
- todo.Push(begin);
- while (todo.Count > 0) {
- var currentBlock = todo.Pop();
- if (blocksToVerifyEntirely.Contains(currentBlock)) continue;
- blocksToVerifyEntirely.Add(currentBlock);
- var exit = currentBlock.TransferCmd as GotoCmd;
- if (exit != null)
- foreach (Block targetBlock in exit.labelTargets) {
- if (!endPoints.Contains(targetBlock)) {
- todo.Push(targetBlock);
- } else {
- reachableEndPoints.Add(targetBlock);
- }
- }
-
- }
- blocksToVerifyEntirely.Remove(begin);
-
- // Convert assumes to asserts in "unreachable" blocks, including portions of blocks containing "split_here"
- var newBlocks = new List<Block>(blocks.Count()); // Copies of the original blocks
- var duplicator = new Duplicator();
- var oldToNewBlockMap = new Dictionary<Block, Block>(blocks.Count()); // Maps original blocks to their new copies in newBlocks
-
- foreach (var currentBlock in blocks) {
- var newBlock = (Block)duplicator.VisitBlock(currentBlock);
- oldToNewBlockMap[currentBlock] = newBlock;
- newBlocks.Add(newBlock);
-
- if (!blockInternalSplit && blocksToVerifyEntirely.Contains(currentBlock)) continue; // All reachable blocks must be checked in their entirety, so don't change anything
- // Otherwise, we only verify a portion of the current block, so we'll need to look at each of its commands
-
- // !verify -> convert assert to assume
- var verify = (currentBlock == begin && begin_split_id == -1) // -1 tells us to start verifying from the very beginning (i.e., there is no split in the begin block)
- || (reachableEndPoints.Contains(currentBlock) // This endpoint is reachable from begin, so we verify until we hit the first split point
- && !blockInternalSplit); // Don't bother verifying if all of the splitting is within the begin block
- var newCmds = new List<Cmd>();
- var split_here_count = 0;
-
- foreach (Cmd c in currentBlock.Cmds) {
- var p = c as PredicateCmd;
- if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "split_here")) {
- if (currentBlock == begin) { // Verify everything between the begin_split_id we were given and the next split
- if (split_here_count == begin_split_id) {
- verify = true;
- } else if (split_here_count == begin_split_id + 1) {
- verify = false;
- }
- } else { // We're in an endPoint so we stop verifying as soon as we hit a "split_here"
- verify = false;
- }
- split_here_count++;
- }
-
- var asrt = c as AssertCmd;
- if (verify || asrt == null)
- newCmds.Add(c);
- else
- newCmds.Add(AssertTurnedIntoAssume(asrt));
- }
-
- newBlock.Cmds = newCmds;
- }
-
- // Patch the edges between the new blocks
- foreach (var oldBlock in blocks) {
- if (oldBlock.TransferCmd is ReturnCmd) { continue; }
- var gotoCmd = (GotoCmd)oldBlock.TransferCmd;
- var newLabelTargets = new List<Block>(gotoCmd.labelTargets.Count());
- var newLabelNames = new List<string>(gotoCmd.labelTargets.Count());
- foreach (var target in gotoCmd.labelTargets) {
- newLabelTargets.Add(oldToNewBlockMap[target]);
- newLabelNames.Add(oldToNewBlockMap[target].Label);
- }
- oldToNewBlockMap[oldBlock].TransferCmd = new GotoCmd(gotoCmd.tok, newLabelNames, newLabelTargets);
- }
-
- return newBlocks;
- }
-
- public static List<Split/*!*/> FindManualSplits(Implementation/*!*/ impl, Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins, VCGen/*!*/ par) {
- Contract.Requires(impl != null);
- Contract.Ensures(Contract.Result<List<Split>>() == null || cce.NonNullElements(Contract.Result<List<Split>>()));
-
- var splitPoints = new Dictionary<Block,int>();
- foreach (var b in impl.Blocks) {
- foreach (Cmd c in b.Cmds) {
- var p = c as PredicateCmd;
- if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "split_here")) {
- int count;
- splitPoints.TryGetValue(b, out count);
- splitPoints[b] = count + 1;
- }
- }
- }
-
- if (splitPoints.Count() == 0) { // No manual split points here
- return null;
- }
-
- List<Split> splits = new List<Split>();
- Block entryPoint = impl.Blocks[0];
- var newEntryBlocks = DoManualSplit(impl.Blocks, entryPoint, -1, splitPoints.Keys.Contains(entryPoint), splitPoints.Keys);
- splits.Add(new Split(newEntryBlocks, gotoCmdOrigins, par, impl)); // REVIEW: Does gotoCmdOrigins need to be changed at all?
-
- foreach (KeyValuePair<Block,int> pair in splitPoints) {
- for (int i = 0; i < pair.Value; i++) {
- bool blockInternalSplit = i < pair.Value - 1; // There's at least one more split, after this one, in the current block
- var newBlocks = DoManualSplit(impl.Blocks, pair.Key, i, blockInternalSplit, splitPoints.Keys);
- Split s = new Split(newBlocks, gotoCmdOrigins, par, impl); // REVIEW: Does gotoCmdOrigins need to be changed at all?
- splits.Add(s);
- }
- }
-
- return splits;
- }
-
- public static List<Split/*!*/>/*!*/ DoSplit(Split initial, double max_cost, int max) {
- Contract.Requires(initial != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Split>>()));
-
- List<Split> res = new List<Split>();
- res.Add(initial);
-
- while (res.Count < max) {
- Split best = null;
- int best_idx = 0, pos = 0;
- foreach (Split s in res) {
- Contract.Assert(s != null);
- s.ComputeBestSplit(); // TODO check total_cost first
- if (s.total_cost > max_cost &&
- (best == null || best.total_cost < s.total_cost) &&
- (s.assertion_count > 1 || s.split_block != null)) {
- best = s;
- best_idx = pos;
- }
- pos++;
- }
-
- if (best == null)
- break; // no split found
-
- Split s0, s1;
-
- bool split_stats = CommandLineOptions.Clo.TraceVerify;
-
- if (split_stats) {
- Console.WriteLine("{0} {1} -->", best.split_block == null ? "SLICE" : ("SPLIT@" + best.split_block.Label), best.Stats);
- if (best.split_block != null) {
- GotoCmd g = best.split_block.TransferCmd as GotoCmd;
- if (g != null) {
- Console.Write(" exits: ");
- foreach (Block b in cce.NonNull(g.labelTargets)) {
- Contract.Assert(b != null);
- Console.Write("{0} ", b.Label);
- }
- Console.WriteLine("");
- Console.Write(" assumized: ");
- foreach (Block b in best.assumized_branches) {
- Contract.Assert(b != null);
- Console.Write("{0} ", b.Label);
- }
- Console.WriteLine("");
- }
- }
- }
-
- if (best.split_block != null) {
- s0 = best.SplitAt(0);
- s1 = best.SplitAt(1);
- } else {
- best.split_block = null;
- s0 = best.SliceAsserts(best.assertion_cost / 2, true);
- s1 = best.SliceAsserts(best.assertion_cost / 2, false);
- }
-
- if (true) {
- List<Block> ss = new List<Block>();
- ss.Add(s0.blocks[0]);
- ss.Add(s1.blocks[0]);
- try {
- best.SoundnessCheck(new HashSet<List<Block>>(new BlockListComparer()), best.blocks[0], ss);
- } catch (System.Exception e) {
- Console.WriteLine(e);
- best.DumpDot(-1);
- s0.DumpDot(-2);
- s1.DumpDot(-3);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- if (split_stats) {
- s0.ComputeBestSplit();
- s1.ComputeBestSplit();
- Console.WriteLine(" --> {0}", s0.Stats);
- Console.WriteLine(" --> {0}", s1.Stats);
- }
-
- if (CommandLineOptions.Clo.TraceVerify) {
- best.Print();
- }
-
- res[best_idx] = s0;
- res.Add(s1);
- }
-
- return res;
- }
-
- class BlockListComparer : IEqualityComparer<List<Block>>
- {
- public bool Equals(List<Block> x, List<Block> y)
- {
- return x == y || x.SequenceEqual(y);
- }
-
- public int GetHashCode(List<Block> obj)
- {
- int h = 0;
- Contract.Assume(obj != null);
- foreach (var b in obj)
- {
- if (b != null)
- {
- h += b.GetHashCode();
- }
- }
- return h;
- }
- }
-
- public Checker Checker {
- get {
- Contract.Ensures(Contract.Result<Checker>() != null);
-
- Contract.Assert(checker != null);
- return checker;
- }
- }
-
- public Task ProverTask {
- get {
- Contract.Assert(checker != null);
- return checker.ProverTask;
- }
- }
-
- public void ReadOutcome(ref Outcome cur_outcome, out bool prover_failed) {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- ProverInterface.Outcome outcome = cce.NonNull(checker).ReadOutcome();
-
- if (CommandLineOptions.Clo.Trace && splitNo >= 0) {
- System.Console.WriteLine(" --> split #{0} done, [{1} s] {2}", splitNo, checker.ProverRunTime.TotalSeconds, outcome);
- }
-
- if (CommandLineOptions.Clo.VcsDumpSplits) {
- DumpDot(splitNo);
- }
-
- prover_failed = false;
-
- switch (outcome) {
- case ProverInterface.Outcome.Valid:
- return;
- case ProverInterface.Outcome.Invalid:
- cur_outcome = Outcome.Errors;
- return;
- case ProverInterface.Outcome.OutOfMemory:
- prover_failed = true;
- if (cur_outcome != Outcome.Errors && cur_outcome != Outcome.Inconclusive)
- cur_outcome = Outcome.OutOfMemory;
- return;
- case ProverInterface.Outcome.TimeOut:
- prover_failed = true;
- if (cur_outcome != Outcome.Errors && cur_outcome != Outcome.Inconclusive)
- cur_outcome = Outcome.TimedOut;
- return;
- case ProverInterface.Outcome.Undetermined:
- if (cur_outcome != Outcome.Errors)
- cur_outcome = Outcome.Inconclusive;
- return;
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- /// <summary>
- /// As a side effect, updates "this.parent.CumulativeAssertionCount".
- /// </summary>
- public void BeginCheck(Checker checker, VerifierCallback callback, ModelViewInfo mvInfo, int no, int timeout)
- {
- Contract.Requires(checker != null);
- Contract.Requires(callback != null);
-
- splitNo = no;
-
- impl.Blocks = blocks;
-
- this.checker = checker;
-
- Dictionary<int, Absy> label2absy = new Dictionary<int, Absy>();
-
- ProverContext ctx = checker.TheoremProver.Context;
- Boogie2VCExprTranslator bet = ctx.BoogieExprTranslator;
- CodeExprConversionClosure cc = new CodeExprConversionClosure(label2absy, ctx);
- bet.SetCodeExprConverter(cc.CodeExprToVerificationCondition);
-
- var exprGen = ctx.ExprGen;
- VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
-
- VCExpr vc = parent.GenerateVCAux(impl, controlFlowVariableExpr, label2absy, checker.TheoremProver.Context);
- Contract.Assert(vc != null);
-
- if (!CommandLineOptions.Clo.UseLabels)
- {
- VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
- VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
- vc = exprGen.Implies(eqExpr, vc);
- }
-
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local)
- {
- reporter = new ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, parent.incarnationOriginMap, callback, mvInfo, cce.NonNull(this.Checker.TheoremProver.Context), parent.program);
- }
- else
- {
- reporter = new ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, parent.incarnationOriginMap, callback, mvInfo, this.Checker.TheoremProver.Context, parent.program);
- }
-
- if (CommandLineOptions.Clo.TraceVerify && no >= 0)
- {
- Console.WriteLine("-- after split #{0}", no);
- Print();
- }
-
- string desc = cce.NonNull(impl.Name);
- if (no >= 0)
- desc += "_split" + no;
- checker.BeginCheck(desc, vc, reporter);
- }
-
- private void SoundnessCheck(HashSet<List<Block>/*!*/>/*!*/ cache, Block/*!*/ orig, List<Block/*!*/>/*!*/ copies) {
- Contract.Requires(cce.NonNull(cache));
- Contract.Requires(orig != null);
- Contract.Requires(copies != null);
- {
- var t = new List<Block> { orig };
- foreach (Block b in copies) {
- Contract.Assert(b != null);
- t.Add(b);
- }
- if (cache.Contains(t)) {
- return;
- }
- cache.Add(t);
- }
-
- for (int i = 0; i < orig.Cmds.Count; ++i) {
- Cmd cmd = orig.Cmds[i];
- if (cmd is AssertCmd) {
- int found = 0;
- foreach (Block c in copies) {
- Contract.Assert(c != null);
- if (c.Cmds[i] == cmd) {
- found++;
- }
- }
- if (found == 0) {
- throw new System.Exception(string.Format("missing assertion: {0}({1})", cmd.tok.filename, cmd.tok.line));
- }
- }
- }
-
- foreach (Block exit in Exits(orig)) {
- Contract.Assert(exit != null);
- List<Block> newcopies = new List<Block>();
- foreach (Block c in copies) {
- foreach (Block cexit in Exits(c)) {
- Contract.Assert(cexit != null);
- if (cexit.Label == exit.Label) {
- newcopies.Add(cexit);
- }
- }
- }
- if (newcopies.Count == 0) {
- throw new System.Exception("missing exit " + exit.Label);
- }
- SoundnessCheck(cache, exit, newcopies);
- }
- }
- }
- #endregion
-
-
- public class CodeExprConversionClosure
- {
- Dictionary<int, Absy> label2absy;
- ProverContext ctx;
- public CodeExprConversionClosure(Dictionary<int, Absy> label2absy, ProverContext ctx)
- {
- this.label2absy = label2absy;
- this.ctx = ctx;
- }
-
- public VCExpr CodeExprToVerificationCondition(CodeExpr codeExpr, Hashtable blockVariables, List<VCExprLetBinding> bindings, bool isPositiveContext)
- {
- VCGen vcgen = new VCGen(new Program(), null, false, new List<Checker>());
- vcgen.variable2SequenceNumber = new Dictionary<Variable, int>();
- vcgen.incarnationOriginMap = new Dictionary<Incarnation, Absy>();
- vcgen.CurrentLocalVariables = codeExpr.LocVars;
-
- ResetPredecessors(codeExpr.Blocks);
- vcgen.AddBlocksBetween(codeExpr.Blocks);
- Dictionary<Variable, Expr> gotoCmdOrigins = vcgen.ConvertBlocks2PassiveCmd(codeExpr.Blocks, new List<IdentifierExpr>(), new ModelViewInfo(codeExpr));
- int ac; // computed, but then ignored for this CodeExpr
- VCExpr startCorrect = VCGen.LetVCIterative(codeExpr.Blocks, null, label2absy, ctx, out ac, isPositiveContext);
- VCExpr vce = ctx.ExprGen.Let(bindings, startCorrect);
- if (vcgen.CurrentLocalVariables.Count != 0)
- {
- Boogie2VCExprTranslator translator = ctx.BoogieExprTranslator;
- List<VCExprVar> boundVars = new List<VCExprVar>();
- foreach (Variable v in vcgen.CurrentLocalVariables)
- {
- Contract.Assert(v != null);
- VCExprVar ev = translator.LookupVariable(v);
- Contract.Assert(ev != null);
- boundVars.Add(ev);
- if (v.TypedIdent.Type.Equals(Bpl.Type.Bool))
- {
- // add an antecedent (tickleBool ev) to help the prover find a possible trigger
- vce = ctx.ExprGen.Implies(ctx.ExprGen.Function(VCExpressionGenerator.TickleBoolOp, ev), vce);
- }
- }
- vce = ctx.ExprGen.Forall(boundVars, new List<VCTrigger>(), vce);
- }
- if (isPositiveContext)
- {
- vce = ctx.ExprGen.Not(vce);
- }
- return vce;
- }
- }
-
- public VCExpr GenerateVC(Implementation/*!*/ impl, VCExpr controlFlowVariableExpr, out Dictionary<int, Absy>/*!*/ label2absy, ProverContext proverContext)
- {
- Contract.Requires(impl != null);
- Contract.Requires(proverContext != null);
- Contract.Ensures(Contract.ValueAtReturn(out label2absy) != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- label2absy = new Dictionary<int, Absy>();
- return GenerateVCAux(impl, controlFlowVariableExpr, label2absy, proverContext);
- }
-
- public VCExpr GenerateVCAux(Implementation/*!*/ impl, VCExpr controlFlowVariableExpr, Dictionary<int, Absy>/*!*/ label2absy, ProverContext proverContext) {
- Contract.Requires(impl != null);
- Contract.Requires(proverContext != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- TypecheckingContext tc = new TypecheckingContext(null);
- impl.Typecheck(tc);
-
- VCExpr vc;
- int assertionCount;
- switch (CommandLineOptions.Clo.vcVariety) {
- case CommandLineOptions.VCVariety.Structured:
- vc = VCViaStructuredProgram(impl, label2absy, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.Block:
- vc = FlatBlockVC(impl, label2absy, false, false, false, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.BlockReach:
- vc = FlatBlockVC(impl, label2absy, false, true, false, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.Local:
- vc = FlatBlockVC(impl, label2absy, true, false, false, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.BlockNested:
- vc = NestedBlockVC(impl, label2absy, false, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.BlockNestedReach:
- vc = NestedBlockVC(impl, label2absy, true, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.Dag:
- if (cce.NonNull(CommandLineOptions.Clo.TheProverFactory).SupportsDags || CommandLineOptions.Clo.FixedPointEngine != null) {
- vc = DagVC(cce.NonNull(impl.Blocks[0]), controlFlowVariableExpr, label2absy, new Hashtable/*<Block, VCExpr!>*/(), proverContext, out assertionCount);
- } else {
- vc = LetVC(cce.NonNull(impl.Blocks[0]), controlFlowVariableExpr, label2absy, proverContext, out assertionCount);
- }
- break;
- case CommandLineOptions.VCVariety.DagIterative:
- vc = LetVCIterative(impl.Blocks, controlFlowVariableExpr, label2absy, proverContext, out assertionCount);
- break;
- case CommandLineOptions.VCVariety.Doomed:
- vc = FlatBlockVC(impl, label2absy, false, false, true, proverContext, out assertionCount);
- break;
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException(); // unexpected enumeration value
- }
- CumulativeAssertionCount += assertionCount;
- return vc;
- }
-
- void CheckIntAttributeOnImpl(Implementation impl, string name, ref int val) {
- Contract.Requires(impl != null);
- Contract.Requires(name != null);
- if (!(cce.NonNull(impl.Proc).CheckIntAttribute(name, ref val) || !impl.CheckIntAttribute(name, ref val))) {
- Console.WriteLine("ignoring ill-formed {:{0} ...} attribute on {1}, parameter should be an int", name, impl.Name);
- }
- }
-
- public override Outcome VerifyImplementation(Implementation/*!*/ impl, VerifierCallback/*!*/ callback) {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- if (impl.SkipVerification) {
- return Outcome.Inconclusive; // not sure about this one
- }
-
- callback.OnProgress("VCgen", 0, 0, 0.0);
-
- Stopwatch watch = new Stopwatch();
- if (_print_time)
- {
- Console.WriteLine("Checking function {0}", impl.Name);
- watch.Reset();
- watch.Start();
- }
-
- ConvertCFG2DAG(impl);
-
- SmokeTester smoke_tester = null;
- if (CommandLineOptions.Clo.SoundnessSmokeTest) {
- smoke_tester = new SmokeTester(this, impl, callback);
- smoke_tester.Copy();
- }
-
- ModelViewInfo mvInfo;
- var gotoCmdOrigins = PassifyImpl(impl, out mvInfo);
-
- // If "expand" attribute is supplied, expand any assertion of conjunctions into multiple assertions, one per conjunct
- foreach (var b in impl.Blocks)
- {
- List<Cmd> newCmds = new List<Cmd>();
- bool changed = false;
- foreach (var c in b.Cmds)
- {
- var a = c as AssertCmd;
- var ar = c as AssertRequiresCmd;
- var ae = c as AssertEnsuresCmd;
- var ai = c as LoopInitAssertCmd;
- var am = c as LoopInvMaintainedAssertCmd;
- // TODO:
- //use Duplicator and Substituter rather than new
- //nested IToken?
- //document expand attribute (search for {:ignore}, for example)
- //fix up new CallCmd, new Requires, new Ensures in OwickiGries.cs
- Func<Expr,Expr,Expr> withType = (Expr from, Expr to) =>
- {
- NAryExpr nFrom = from as NAryExpr;
- NAryExpr nTo = to as NAryExpr;
- to.Type = from.Type;
- if (nFrom != null && nTo != null) nTo.TypeParameters = nFrom.TypeParameters;
- return to;
- };
-
- Action<int,Expr,Action<Expr>> traverse = null;
- traverse = (depth, e, act) =>
- {
- ForallExpr forall = e as ForallExpr;
- NAryExpr nary = e as NAryExpr;
- if (forall != null)
- {
- traverse(depth, forall.Body, e1 => act(withType(forall,
- new ForallExpr(e1.tok, forall.TypeParameters, forall.Dummies, forall.Attributes, forall.Triggers, e1))));
- return;
- }
- if (nary != null)
- {
- var args = nary.Args;
- IAppliable fun = nary.Fun;
- BinaryOperator bop = fun as BinaryOperator;
- FunctionCall call = fun as FunctionCall;
- if (bop != null)
- {
- switch (bop.Op)
- {
- case BinaryOperator.Opcode.And:
- traverse(depth, args[0], act);
- traverse(depth, args[1], act);
- return;
- case BinaryOperator.Opcode.Imp:
- traverse(depth, args[1], e1 => act(withType(nary,
- new NAryExpr(e1.tok, fun, new List<Expr>() { args[0], e1 }))));
- return;
- }
- }
- if (depth > 0 && call != null && call.Func != null)
- {
- Function cf = call.Func;
- Expr body = cf.Body;
- List<Variable> ins = cf.InParams;
- if (body == null && cf.DefinitionAxiom != null)
- {
- ForallExpr all = cf.DefinitionAxiom.Expr as ForallExpr;
- if (all != null)
- {
- NAryExpr def = all.Body as NAryExpr;
- if (def != null && def.Fun is BinaryOperator && ((BinaryOperator) (def.Fun)).Op == BinaryOperator.Opcode.Iff)
- {
- body = def.Args[1];
- ins = all.Dummies;
- }
- }
- }
- if (body != null)
- {
- Func<Expr,Expr> new_f = e1 =>
- {
- Function f = new Function(cf.tok, "expand<" + cf.Name + ">", cf.TypeParameters, ins, cf.OutParams[0], cf.Comment);
- f.Body = e1;
- Token tok = new Token(e1.tok.line, e1.tok.col);
- tok.filename = e.tok.filename + "(" + e.tok.line + "," + e.tok.col + ") --> " + e1.tok.filename;
- return withType(nary, new NAryExpr(tok, new FunctionCall(f), args));
- };
- traverse(depth - 1, body, e1 => act(new_f(e1)));
- return;
- }
- }
- }
- act(e);
- };
-
- if (a != null)
- {
- var attr = a.Attributes;
- if (ar != null && ar.Requires.Attributes != null) attr = ar.Requires.Attributes;
- if (ar != null && ar.Call.Attributes != null) attr = ar.Call.Attributes;
- if (ae != null && ae.Ensures.Attributes != null) attr = ae.Ensures.Attributes;
- if (QKeyValue.FindExprAttribute(attr, "expand") != null || QKeyValue.FindBoolAttribute(attr, "expand"))
- {
- int depth = QKeyValue.FindIntAttribute(attr, "expand", 100);
- Func<Expr,Expr> fe = e => Expr.Or(a.Expr, e);
- //traverse(depth, a.Expr, e => System.Console.WriteLine(e.GetType() + " :: " + e + " @ " + e.tok.line + ", " + e.tok.col));
- traverse(depth, a.Expr, e =>
- {
- AssertCmd new_c =
- (ar != null) ? new AssertRequiresCmd(ar.Call, new Requires(e.tok, ar.Requires.Free, fe(e), ar.Requires.Comment)) :
- (ae != null) ? new AssertEnsuresCmd(new Ensures(e.tok, ae.Ensures.Free, fe(e), ae.Ensures.Comment)) :
- (ai != null) ? new LoopInitAssertCmd(e.tok, fe(e)) :
- (am != null) ? new LoopInvMaintainedAssertCmd(e.tok, fe(e)) :
- new AssertCmd(e.tok, fe(e));
- new_c.Attributes = new QKeyValue(e.tok, "subsumption", new List<object>() { new LiteralExpr(e.tok, BigNum.FromInt(0)) }, a.Attributes);
- newCmds.Add(new_c);
- });
- }
- newCmds.Add(c);
- changed = true;
- }
- else
- {
- newCmds.Add(c);
- }
- }
- if (changed) b.Cmds = newCmds;
- }
-
- double max_vc_cost = CommandLineOptions.Clo.VcsMaxCost;
- int tmp_max_vc_cost = -1, max_splits = CommandLineOptions.Clo.VcsMaxSplits,
- max_kg_splits = CommandLineOptions.Clo.VcsMaxKeepGoingSplits;
- CheckIntAttributeOnImpl(impl, "vcs_max_cost", ref tmp_max_vc_cost);
- CheckIntAttributeOnImpl(impl, "vcs_max_splits", ref max_splits);
- CheckIntAttributeOnImpl(impl, "vcs_max_keep_going_splits", ref max_kg_splits);
- if (tmp_max_vc_cost >= 0) {
- max_vc_cost = tmp_max_vc_cost;
- }
-
- Outcome outcome = Outcome.Correct;
-
- // Report all recycled failing assertions for this implementation.
- if (impl.RecycledFailingAssertions != null && impl.RecycledFailingAssertions.Any())
- {
- outcome = Outcome.Errors;
- foreach (var a in impl.RecycledFailingAssertions)
- {
- var checksum = a.Checksum;
- var oldCex = impl.ErrorChecksumToCachedError[checksum] as Counterexample;
- if (oldCex != null)
- {
- callback.OnCounterexample(oldCex, null);
- }
- }
- }
-
- Cores = CommandLineOptions.Clo.VcsCores;
- Stack<Split> work = new Stack<Split>();
- List<Split> currently_running = new List<Split>();
- ResetPredecessors(impl.Blocks);
- List<Split> manual_splits = Split.FindManualSplits(impl, gotoCmdOrigins, this);
- if (manual_splits != null) {
- foreach (var split in manual_splits) {
- work.Push(split);
- }
- } else {
- work.Push(new Split(impl.Blocks, gotoCmdOrigins, this, impl));
- }
-
- bool keep_going = max_kg_splits > 1;
- int total = 0;
- int no = max_splits == 1 && !keep_going ? -1 : 0;
- bool first_round = true;
- bool do_splitting = keep_going || max_splits > 1;
- double remaining_cost = 0.0, proven_cost = 0.0;
-
- if (do_splitting) {
- remaining_cost = work.Peek().Cost;
- }
-
- while (work.Any() || currently_running.Any())
- {
- bool prover_failed = false;
- Split s = null;
- var isWaiting = !work.Any();
-
- if (!isWaiting)
- {
- s = work.Peek();
-
- if (first_round && max_splits > 1)
- {
- prover_failed = true;
- remaining_cost -= s.Cost;
- }
- else
- {
- var timeout = (keep_going && s.LastChance) ? CommandLineOptions.Clo.VcsFinalAssertTimeout :
- keep_going ? CommandLineOptions.Clo.VcsKeepGoingTimeout :
- impl.TimeLimit;
-
- var checker = s.parent.FindCheckerFor(timeout, false);
- try
- {
- if (checker == null)
- {
- isWaiting = true;
- goto waiting;
- }
- else
- {
- s = work.Pop();
- }
-
- if (CommandLineOptions.Clo.Trace && no >= 0)
- {
- System.Console.WriteLine(" checking split {1}/{2}, {3:0.00}%, {0} ...",
- s.Stats, no + 1, total, 100 * proven_cost / (proven_cost + remaining_cost));
- }
- callback.OnProgress("VCprove", no < 0 ? 0 : no, total, proven_cost / (remaining_cost + proven_cost));
-
- Contract.Assert(s.parent == this);
- lock (checker)
- {
- s.BeginCheck(checker, callback, mvInfo, no, timeout);
- }
-
- no++;
-
- currently_running.Add(s);
- }
- catch (Exception)
- {
- checker.GoBackToIdle();
- throw;
- }
- }
- }
-
- waiting:
- if (isWaiting)
- {
- // Wait for one split to terminate.
- var tasks = currently_running.Select(splt => splt.ProverTask).ToArray();
-
- if (tasks.Any())
- {
- try
- {
- int index = Task.WaitAny(tasks);
- s = currently_running[index];
- currently_running.RemoveAt(index);
-
- if (do_splitting)
- {
- remaining_cost -= s.Cost;
- }
-
- lock (s.Checker)
- {
- s.ReadOutcome(ref outcome, out prover_failed);
- }
-
- if (do_splitting)
- {
- if (prover_failed)
- {
- // even if the prover fails, we have learned something, i.e., it is
- // annoying to watch Boogie say Timeout, 0.00% a couple of times
- proven_cost += s.Cost / 100;
- }
- else
- {
- proven_cost += s.Cost;
- }
- }
- callback.OnProgress("VCprove", no < 0 ? 0 : no, total, proven_cost / (remaining_cost + proven_cost));
-
- if (prover_failed && !first_round && s.LastChance)
- {
- string msg = "some timeout";
- if (s.reporter != null && s.reporter.resourceExceededMessage != null)
- {
- msg = s.reporter.resourceExceededMessage;
- }
- callback.OnCounterexample(s.ToCounterexample(s.Checker.TheoremProver.Context), msg);
- outcome = Outcome.Errors;
- break;
- }
- }
- finally
- {
- s.Checker.GoBackToIdle();
- }
-
- Contract.Assert(prover_failed || outcome == Outcome.Correct || outcome == Outcome.Errors || outcome == Outcome.Inconclusive);
- }
- }
-
- if (prover_failed)
- {
- int splits = first_round && max_splits > 1 ? max_splits : max_kg_splits;
-
- if (splits > 1)
- {
- List<Split> tmp = Split.DoSplit(s, max_vc_cost, splits);
- Contract.Assert(tmp != null);
- max_vc_cost = 1.0; // for future
- first_round = false;
- //tmp.Sort(new Comparison<Split!>(Split.Compare));
- foreach (Split a in tmp)
- {
- Contract.Assert(a != null);
- work.Push(a);
- total++;
- remaining_cost += a.Cost;
- }
- if (outcome != Outcome.Errors)
- {
- outcome = Outcome.Correct;
- }
- }
- else
- {
- Contract.Assert(outcome != Outcome.Correct);
- if (outcome == Outcome.TimedOut)
- {
- string msg = "some timeout";
- if (s.reporter != null && s.reporter.resourceExceededMessage != null)
- {
- msg = s.reporter.resourceExceededMessage;
- }
- callback.OnTimeout(msg);
- }
- else if (outcome == Outcome.OutOfMemory)
- {
- string msg = "out of memory";
- if (s.reporter != null && s.reporter.resourceExceededMessage != null)
- {
- msg = s.reporter.resourceExceededMessage;
- }
- callback.OnOutOfMemory(msg);
- }
-
- break;
- }
- }
- }
-
- if (outcome == Outcome.Correct && smoke_tester != null) {
- smoke_tester.Test();
- }
-
- callback.OnProgress("done", 0, 0, 1.0);
-
- if (_print_time)
- {
- watch.Stop();
- Console.WriteLine("Total time for this method: {0}", watch.Elapsed.ToString());
- }
-
- return outcome;
- }
-
- public class ErrorReporter : ProverInterface.ErrorHandler {
- Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins;
- Dictionary<int, Absy>/*!*/ label2absy;
- List<Block/*!*/>/*!*/ blocks;
- protected Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap;
- protected VerifierCallback/*!*/ callback;
- protected ModelViewInfo MvInfo;
- internal string resourceExceededMessage;
- static System.IO.TextWriter modelWriter;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(gotoCmdOrigins != null);
- Contract.Invariant(label2absy != null);
- Contract.Invariant(cce.NonNullElements(blocks));
- Contract.Invariant(cce.NonNullDictionaryAndValues(incarnationOriginMap));
- Contract.Invariant(callback != null);
- Contract.Invariant(context != null);
- Contract.Invariant(program != null);
- }
-
-
- public static TextWriter ModelWriter {
- get {
- Contract.Ensures(Contract.Result<TextWriter>() != null);
-
- if (ErrorReporter.modelWriter == null)
- ErrorReporter.modelWriter = CommandLineOptions.Clo.PrintErrorModelFile == null ? Console.Out : new StreamWriter(CommandLineOptions.Clo.PrintErrorModelFile, false);
- return ErrorReporter.modelWriter;
- }
- }
-
- protected ProverContext/*!*/ context;
- Program/*!*/ program;
-
- public ErrorReporter(Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins,
- Dictionary<int, Absy>/*!*/ label2absy,
- List<Block/*!*/>/*!*/ blocks,
- Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap,
- VerifierCallback/*!*/ callback,
- ModelViewInfo mvInfo,
- ProverContext/*!*/ context,
- Program/*!*/ program) {
- Contract.Requires(gotoCmdOrigins != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(cce.NonNullElements(blocks));
- Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
- Contract.Requires(callback != null);
- Contract.Requires(context!=null);
- Contract.Requires(program!=null);
- this.gotoCmdOrigins = gotoCmdOrigins;
- this.label2absy = label2absy;
- this.blocks = blocks;
- this.incarnationOriginMap = incarnationOriginMap;
- this.callback = callback;
- this.MvInfo = mvInfo;
-
- this.context = context;
- this.program = program;
- }
-
- public override void OnModel(IList<string/*!*/>/*!*/ labels, Model model, ProverInterface.Outcome proverOutcome) {
- //Contract.Requires(cce.NonNullElements(labels));
- if (CommandLineOptions.Clo.PrintErrorModel >= 1 && model != null) {
- if (VC.ConditionGeneration.errorModelList != null)
- {
- VC.ConditionGeneration.errorModelList.Add(model);
- }
-
- model.Write(ErrorReporter.ModelWriter);
- ErrorReporter.ModelWriter.Flush();
- }
-
- Hashtable traceNodes = new Hashtable();
- foreach (string s in labels) {
- Contract.Assert(s != null);
- Absy absy = Label2Absy(s);
- Contract.Assert(absy != null);
- if (traceNodes.ContainsKey(absy))
- System.Console.WriteLine("Warning: duplicate label: " + s + " read while tracing nodes");
- else
- traceNodes.Add(absy, null);
- }
-
- List<Block> trace = new List<Block>();
- Block entryBlock = cce.NonNull(this.blocks[0]);
- Contract.Assert(traceNodes.Contains(entryBlock));
- trace.Add(entryBlock);
-
- Counterexample newCounterexample = TraceCounterexample(entryBlock, traceNodes, trace, model, MvInfo, incarnationOriginMap, context, new Dictionary<TraceLocation, CalleeCounterexampleInfo>());
-
- if (newCounterexample == null)
- return;
-
- #region Map passive program errors back to original program errors
- ReturnCounterexample returnExample = newCounterexample as ReturnCounterexample;
- if (returnExample != null) {
- foreach (Block b in returnExample.Trace) {
- Contract.Assert(b != null);
- Contract.Assume(b.TransferCmd != null);
- ReturnCmd cmd = gotoCmdOrigins.ContainsKey(b.TransferCmd) ? gotoCmdOrigins[b.TransferCmd] : null;
- if (cmd != null) {
- returnExample.FailingReturn = cmd;
- break;
- }
- }
- }
- #endregion
- callback.OnCounterexample(newCounterexample, null);
- }
-
- public override Absy Label2Absy(string label) {
- //Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- int id = int.Parse(label);
- return cce.NonNull((Absy)label2absy[id]);
- }
-
- public override void OnResourceExceeded(string msg) {
- //Contract.Requires(msg != null);
- resourceExceededMessage = msg;
- }
-
- public override void OnProverWarning(string msg) {
- //Contract.Requires(msg != null);
- callback.OnWarning(msg);
- }
- }
-
- public class ErrorReporterLocal : ErrorReporter {
- public ErrorReporterLocal(Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins,
- Dictionary<int, Absy>/*!*/ label2absy,
- List<Block/*!*/>/*!*/ blocks,
- Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap,
- VerifierCallback/*!*/ callback,
- ModelViewInfo mvInfo,
- ProverContext/*!*/ context,
- Program/*!*/ program)
- : base(gotoCmdOrigins, label2absy, blocks, incarnationOriginMap, callback, mvInfo, context, program) // here for aesthetic purposes //TODO: Maybe nix?
- {
- Contract.Requires(gotoCmdOrigins != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(cce.NonNullElements(blocks));
- Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
- Contract.Requires(callback != null);
- Contract.Requires(context != null);
- Contract.Requires(program != null);
- }
-
- public override void OnModel(IList<string/*!*/>/*!*/ labels, Model model, ProverInterface.Outcome proverOutcome) {
- //Contract.Requires(cce.NonNullElements(labels));
- // We ignore the error model here for enhanced error message purposes.
- // It is only printed to the command line.
- if (CommandLineOptions.Clo.PrintErrorModel >= 1 && model != null) {
- if (CommandLineOptions.Clo.PrintErrorModelFile != null) {
- model.Write(ErrorReporter.ModelWriter);
- ErrorReporter.ModelWriter.Flush();
- }
- }
- List<Block> traceNodes = new List<Block>();
- List<AssertCmd> assertNodes = new List<AssertCmd>();
- foreach (string s in labels) {
- Contract.Assert(s != null);
- Absy node = Label2Absy(s);
- if (node is Block) {
- Block b = (Block)node;
- traceNodes.Add(b);
- } else {
- AssertCmd a = (AssertCmd)node;
- assertNodes.Add(a);
- }
- }
- Contract.Assert(assertNodes.Count > 0);
- Contract.Assert(traceNodes.Count == assertNodes.Count);
-
- foreach (AssertCmd a in assertNodes) {
- // find the corresponding Block (assertNodes.Count is likely to be 1, or small in any case, so just do a linear search here)
- foreach (Block b in traceNodes) {
- if (b.Cmds.Contains(a)) {
- List<Block> trace = new List<Block>();
- trace.Add(b);
- Counterexample newCounterexample = AssertCmdToCounterexample(a, cce.NonNull(b.TransferCmd), trace, model, MvInfo, context);
- callback.OnCounterexample(newCounterexample, null);
- goto NEXT_ASSERT;
- }
- }
- Contract.Assert(false);
- throw new cce.UnreachableException(); // there was no block that contains the assert
- NEXT_ASSERT: {
- }
- }
- }
- }
-
- private void RecordCutEdge(Dictionary<Block,List<Block>> edgesCut, Block from, Block to){
- if (edgesCut != null)
- {
- if (!edgesCut.ContainsKey(from))
- edgesCut.Add(from, new List<Block>());
- edgesCut[from].Add(to);
- }
- }
-
- public void ConvertCFG2DAG(Implementation impl, Dictionary<Block,List<Block>> edgesCut = null, int taskID = -1)
- {
- Contract.Requires(impl != null);
- impl.PruneUnreachableBlocks(); // This is needed for VCVariety.BlockNested, and is otherwise just an optimization
-
- CurrentLocalVariables = impl.LocVars;
- variable2SequenceNumber = new Dictionary<Variable, int>();
- incarnationOriginMap = new Dictionary<Incarnation, Absy>();
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("original implementation");
- EmitImpl(impl, false);
- }
- #endregion
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("after desugaring sugared commands like procedure calls");
- EmitImpl(impl, true);
- }
- #endregion
-
- // Recompute the predecessors, but first insert a dummy start node that is sure not to be the target of any goto (because the cutting of back edges
- // below assumes that the start node has no predecessor)
- impl.Blocks.Insert(0, new Block(new Token(-17, -4), "0", new List<Cmd>(), new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] })));
- ResetPredecessors(impl.Blocks);
-
- if(CommandLineOptions.Clo.KInductionDepth < 0) {
- ConvertCFG2DAGStandard(impl, edgesCut, taskID);
- } else {
- ConvertCFG2DAGKInduction(impl, edgesCut, taskID);
- }
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("after conversion into a DAG");
- EmitImpl(impl, true);
- }
- #endregion
- }
-
- private void ConvertCFG2DAGStandard(Implementation impl, Dictionary<Block, List<Block>> edgesCut, int taskID)
- {
- #region Convert program CFG into a DAG
-
- #region Use the graph library to figure out where the (natural) loops are
-
- #region Create the graph by adding the source node and each edge
- Graph<Block> g = Program.GraphFromImpl(impl);
- #endregion
-
- //Graph<Block> g = program.ProcessLoops(impl);
-
- g.ComputeLoops(); // this is the call that does all of the processing
- if (!g.Reducible)
- {
- throw new VCGenException("Irreducible flow graphs are unsupported.");
- }
-
- #endregion
-
- #region Cut the backedges, push assert/assume statements from loop header into predecessors, change them all into assume statements at top of loop, introduce havoc statements
- foreach (Block header in cce.NonNull(g.Headers))
- {
- Contract.Assert(header != null);
- IDictionary<Block, object> backEdgeNodes = new Dictionary<Block, object>();
- foreach (Block b in cce.NonNull(g.BackEdgeNodes(header)))
- {
- Contract.Assert(b != null);
- backEdgeNodes.Add(b, null);
- }
-
- #region Find the (possibly empty) prefix of assert commands in the header, replace each assert with an assume of the same condition
- List<Cmd> prefixOfPredicateCmdsInit = new List<Cmd>();
- List<Cmd> prefixOfPredicateCmdsMaintained = new List<Cmd>();
- for (int i = 0, n = header.Cmds.Count; i < n; i++)
- {
- PredicateCmd a = header.Cmds[i] as PredicateCmd;
- if (a != null)
- {
- if (a is AssertCmd)
- {
- AssertCmd c = (AssertCmd)a;
- AssertCmd b = null;
-
- if (CommandLineOptions.Clo.ConcurrentHoudini)
- {
- Contract.Assert(taskID >= 0);
- if (CommandLineOptions.Clo.Cho[taskID].DisableLoopInvEntryAssert)
- b = new LoopInitAssertCmd(c.tok, Expr.True);
- else
- b = new LoopInitAssertCmd(c.tok, c.Expr);
- }
- else
- {
- b = new LoopInitAssertCmd(c.tok, c.Expr);
- }
-
- b.Attributes = c.Attributes;
- b.ErrorData = c.ErrorData;
- prefixOfPredicateCmdsInit.Add(b);
-
- if (CommandLineOptions.Clo.ConcurrentHoudini)
- {
- Contract.Assert(taskID >= 0);
- if (CommandLineOptions.Clo.Cho[taskID].DisableLoopInvMaintainedAssert)
- b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, Expr.True);
- else
- b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, c.Expr);
- }
- else
- {
- b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, c.Expr);
- }
-
- b.Attributes = c.Attributes;
- b.ErrorData = c.ErrorData;
- prefixOfPredicateCmdsMaintained.Add(b);
- header.Cmds[i] = new AssumeCmd(c.tok, c.Expr);
- }
- else
- {
- Contract.Assert(a is AssumeCmd);
- if (Bpl.CommandLineOptions.Clo.AlwaysAssumeFreeLoopInvariants)
- {
- // Usually, "free" stuff, like free loop invariants (and the assume statements
- // that stand for such loop invariants) are ignored on the checking side. This
- // command-line option changes that behavior to always assume the conditions.
- prefixOfPredicateCmdsInit.Add(a);
- prefixOfPredicateCmdsMaintained.Add(a);
- }
- }
- }
- else if (header.Cmds[i] is CommentCmd)
- {
- // ignore
- }
- else
- {
- break; // stop when an assignment statement (or any other non-predicate cmd) is encountered
- }
- }
- #endregion
-
- #region Copy the prefix of predicate commands into each predecessor. Do this *before* cutting the backedge!!
- for (int predIndex = 0, n = header.Predecessors.Count; predIndex < n; predIndex++)
- {
- Block pred = cce.NonNull(header.Predecessors[predIndex]);
-
- // Create a block between header and pred for the predicate commands if pred has more than one successor
- GotoCmd gotocmd = cce.NonNull((GotoCmd)pred.TransferCmd);
- Contract.Assert(gotocmd.labelNames != null); // if "pred" is really a predecessor, it may be a GotoCmd with at least one label
- if (gotocmd.labelNames.Count > 1)
- {
- Block newBlock = CreateBlockBetween(predIndex, header);
- impl.Blocks.Add(newBlock);
-
- // if pred is a back edge node, then now newBlock is the back edge node
- if (backEdgeNodes.ContainsKey(pred))
- {
- backEdgeNodes.Remove(pred);
- backEdgeNodes.Add(newBlock, null);
- }
-
- pred = newBlock;
- }
- // Add the predicate commands
- if (backEdgeNodes.ContainsKey(pred))
- {
- pred.Cmds.AddRange(prefixOfPredicateCmdsMaintained);
- }
- else
- {
- pred.Cmds.AddRange(prefixOfPredicateCmdsInit);
- }
- }
- #endregion
-
- #region Cut the back edge
- foreach (Block backEdgeNode in cce.NonNull(backEdgeNodes.Keys))
- {
- Contract.Assert(backEdgeNode != null);
- Debug.Assert(backEdgeNode.TransferCmd is GotoCmd, "An node was identified as the source for a backedge, but it does not have a goto command.");
- GotoCmd gtc = backEdgeNode.TransferCmd as GotoCmd;
- if (gtc != null && gtc.labelTargets != null && gtc.labelTargets.Count > 1)
- {
- // then remove the backedge by removing the target block from the list of gotos
- List<Block> remainingTargets = new List<Block>();
- List<String> remainingLabels = new List<String>();
- Contract.Assume(gtc.labelNames != null);
- for (int i = 0, n = gtc.labelTargets.Count; i < n; i++)
- {
- if (gtc.labelTargets[i] != header)
- {
- remainingTargets.Add(gtc.labelTargets[i]);
- remainingLabels.Add(gtc.labelNames[i]);
- }
- else
- RecordCutEdge(edgesCut, backEdgeNode, header);
- }
- gtc.labelTargets = remainingTargets;
- gtc.labelNames = remainingLabels;
- }
- else
- {
- // This backedge is the only out-going edge from this node.
- // Add an "assume false" statement to the end of the statements
- // inside of the block and change the goto command to a return command.
- AssumeCmd ac = new AssumeCmd(Token.NoToken, Expr.False);
- backEdgeNode.Cmds.Add(ac);
- backEdgeNode.TransferCmd = new ReturnCmd(Token.NoToken);
- if (gtc != null && gtc.labelTargets != null && gtc.labelTargets.Count == 1)
- RecordCutEdge(edgesCut, backEdgeNode, gtc.labelTargets[0]);
- }
- #region Remove the backedge node from the list of predecessor nodes in the header
- List<Block> newPreds = new List<Block>();
- foreach (Block p in header.Predecessors)
- {
- if (p != backEdgeNode)
- newPreds.Add(p);
- }
- header.Predecessors = newPreds;
- #endregion
- }
- #endregion
-
- #region Collect all variables that are assigned to in all of the natural loops for which this is the header
- List<Variable> varsToHavoc = VarsAssignedInLoop(g, header);
- List<IdentifierExpr> havocExprs = new List<IdentifierExpr>();
- foreach (Variable v in varsToHavoc)
- {
- Contract.Assert(v != null);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
- if (!havocExprs.Contains(ie))
- havocExprs.Add(ie);
- }
- // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
- // the source location for this later on
- HavocCmd hc = new HavocCmd(header.tok, havocExprs);
- List<Cmd> newCmds = new List<Cmd>();
- newCmds.Add(hc);
- foreach (Cmd c in header.Cmds)
- {
- newCmds.Add(c);
- }
- header.Cmds = newCmds;
- #endregion
- }
- #endregion
- #endregion Convert program CFG into a DAG
- }
-
- public static List<Variable> VarsAssignedInLoop(Graph<Block> g, Block header)
- {
- List<Variable> varsToHavoc = new List<Variable>();
- foreach (Block backEdgeNode in cce.NonNull(g.BackEdgeNodes(header)))
- {
- Contract.Assert(backEdgeNode != null);
- foreach (Block b in g.NaturalLoops(header, backEdgeNode))
- {
- Contract.Assert(b != null);
- foreach (Cmd c in b.Cmds)
- {
- Contract.Assert(c != null);
- c.AddAssignedVariables(varsToHavoc);
- }
- }
- }
- return varsToHavoc;
- }
-
- public static IEnumerable<Variable> VarsReferencedInLoop(Graph<Block> g, Block header)
- {
- HashSet<Variable> referencedVars = new HashSet<Variable>();
- foreach (Block backEdgeNode in cce.NonNull(g.BackEdgeNodes(header)))
- {
- Contract.Assert(backEdgeNode != null);
- foreach (Block b in g.NaturalLoops(header, backEdgeNode))
- {
- Contract.Assert(b != null);
- foreach (Cmd c in b.Cmds)
- {
- Contract.Assert(c != null);
- var Collector = new VariableCollector();
- Collector.Visit(c);
- foreach(var v in Collector.usedVars) {
- referencedVars.Add(v);
- }
- }
- }
- }
- return referencedVars;
- }
-
- private void ConvertCFG2DAGKInduction(Implementation impl, Dictionary<Block, List<Block>> edgesCut, int taskID) {
-
- // K-induction has not been adapted to be aware of these parameters which standard CFG to DAG transformation uses
- Contract.Requires(edgesCut == null);
- Contract.Requires(taskID == -1);
-
- int inductionK = CommandLineOptions.Clo.KInductionDepth;
- Contract.Assume(inductionK >= 0);
-
- bool contRuleApplication = true;
- while (contRuleApplication) {
- contRuleApplication = false;
-
- #region Use the graph library to figure out where the (natural) loops are
-
- #region Create the graph by adding the source node and each edge
- Graph<Block> g = Program.GraphFromImpl(impl);
- #endregion
-
- g.ComputeLoops(); // this is the call that does all of the processing
- if (!g.Reducible) {
- throw new VCGenException("Irreducible flow graphs are unsupported.");
- }
-
- #endregion
-
- foreach (Block header in cce.NonNull(g.Headers)) {
- Contract.Assert(header != null);
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("Applying k-induction rule with k=" + inductionK);
- }
- #endregion
-
- #region generate the step case
- Block newHeader = DuplicateLoop(impl, g, header, null,
- false, false, "_step_assertion");
- for (int i = 0; i < inductionK; ++i)
- {
- newHeader = DuplicateLoop(impl, g, header, newHeader,
- true, true,
- "_step_" + (inductionK - i));
- }
- #endregion
-
- #region havoc variables that can be assigned in the loop
-
- List<Variable> varsToHavoc = VarsAssignedInLoop(g, header);
- List<IdentifierExpr> havocExprs = new List<IdentifierExpr>();
- foreach (Variable v in varsToHavoc)
- {
- Contract.Assert(v != null);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
- if (!havocExprs.Contains(ie))
- havocExprs.Add(ie);
- }
- // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
- // the source location for this later on
- HavocCmd hc = new HavocCmd(newHeader.tok, havocExprs);
- List<Cmd> havocCmds = new List<Cmd>();
- havocCmds.Add(hc);
-
- Block havocBlock = new Block(newHeader.tok, newHeader.Label + "_havoc", havocCmds,
- new GotoCmd (newHeader.tok, new List<Block> { newHeader }));
-
- impl.Blocks.Add(havocBlock);
- newHeader.Predecessors.Add(havocBlock);
- newHeader = havocBlock;
-
- #endregion
-
- #region generate the base case loop copies
- for (int i = 0; i < inductionK; ++i)
- {
- newHeader = DuplicateLoop(impl, g, header, newHeader,
- false, false,
- "_base_" + (inductionK - i));
- }
- #endregion
-
- #region redirect into the new loop copies and remove the original loop (but don't redirect back-edges)
-
- IDictionary<Block, object> backEdgeNodes = new Dictionary<Block, object>();
- foreach (Block b in cce.NonNull(g.BackEdgeNodes(header))) { Contract.Assert(b != null); backEdgeNodes.Add(b, null); }
-
- for (int predIndex = 0, n = header.Predecessors.Count(); predIndex < n; predIndex++)
- {
- Block pred = cce.NonNull(header.Predecessors[predIndex]);
- if (!backEdgeNodes.ContainsKey(pred))
- {
- GotoCmd gc = pred.TransferCmd as GotoCmd;
- Contract.Assert(gc != null);
- for (int i = 0; i < gc.labelTargets.Count(); ++i)
- {
- if (gc.labelTargets[i] == header)
- {
- gc.labelTargets[i] = newHeader;
- gc.labelNames[i] = newHeader.Label;
- newHeader.Predecessors.Add(pred);
- }
- }
- }
- }
- impl.PruneUnreachableBlocks();
-
- #endregion
-
- contRuleApplication = true;
- break;
- }
-
- }
-
- ResetPredecessors(impl.Blocks);
- impl.FreshenCaptureStates();
-
- }
-
- private Block DuplicateLoop(Implementation impl, Graph<Block> g,
- Block header, Block nextHeader, bool cutExits,
- bool toAssumptions, string suffix)
- {
- IDictionary<Block, Block> ori2CopiedBlocks = new Dictionary<Block, Block>();
- Duplicator duplicator = new Duplicator();
-
- #region create copies of all blocks in the loop
- foreach (Block backEdgeNode in cce.NonNull(g.BackEdgeNodes(header)))
- {
- Contract.Assert(backEdgeNode != null);
- foreach (Block b in g.NaturalLoops(header, backEdgeNode))
- {
- Contract.Assert(b != null);
- if (!ori2CopiedBlocks.ContainsKey(b))
- {
- Block copy = (Block)duplicator.Visit(b);
- copy.Cmds = new List<Cmd>(copy.Cmds); // Philipp Ruemmer commented that this was necessary due to a bug in the Duplicator. That was a long time; worth checking whether this has been fixed
- copy.Predecessors = new List<Block>();
- copy.Label = copy.Label + suffix;
-
- #region turn asserts into assumptions
- if (toAssumptions)
- {
- for (int i = 0; i < copy.Cmds.Count(); ++i)
- {
- AssertCmd ac = copy.Cmds[i] as AssertCmd;
- if (ac != null)
- {
- copy.Cmds[i] = new AssumeCmd(ac.tok, ac.Expr);
- }
- }
- }
- #endregion
-
- impl.Blocks.Add(copy);
- ori2CopiedBlocks.Add(b, copy);
- }
- }
- }
- #endregion
-
- #region adjust the transfer commands of the newly created blocks
- foreach (KeyValuePair<Block, Block> pair in ori2CopiedBlocks)
- {
- Block copy = pair.Value;
- GotoCmd gc = copy.TransferCmd as GotoCmd;
- if (gc != null)
- {
- List<Block> newTargets = new List<Block>();
- List<string> newLabels = new List<string>();
-
- for (int i = 0; i < gc.labelTargets.Count(); ++i)
- {
- Block newTarget;
- if (gc.labelTargets[i] == header)
- {
- if (nextHeader != null)
- {
- newTargets.Add(nextHeader);
- newLabels.Add(nextHeader.Label);
- nextHeader.Predecessors.Add(copy);
- }
- }
- else if (ori2CopiedBlocks.TryGetValue(gc.labelTargets[i], out newTarget))
- {
- newTargets.Add(newTarget);
- newLabels.Add(newTarget.Label);
- newTarget.Predecessors.Add(copy);
- }
- else if (!cutExits)
- {
- newTargets.Add(gc.labelTargets[i]);
- newLabels.Add(gc.labelNames[i]);
- gc.labelTargets[i].Predecessors.Add(copy);
- }
- }
-
- if (newTargets.Count() == 0)
- {
- // if no targets are left, we assume false and return
- copy.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
- copy.TransferCmd = new ReturnCmd(Token.NoToken);
- }
- else
- {
- copy.TransferCmd = new GotoCmd(gc.tok, newLabels, newTargets);
- }
- }
- else if (cutExits && (copy.TransferCmd is ReturnCmd))
- {
- // because return is a kind of exit from the loop, we
- // assume false to cut this path
- copy.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
- }
- }
- #endregion
-
- return ori2CopiedBlocks[header];
- }
-
- public void DesugarCalls(Implementation impl) {
- foreach (Block block in impl.Blocks) {
- List<Cmd> newCmds = new List<Cmd>();
- foreach (Cmd cmd in block.Cmds) {
- SugaredCmd sugaredCmd = cmd as SugaredCmd;
- if (sugaredCmd != null) {
- StateCmd stateCmd = sugaredCmd.Desugaring as StateCmd;
- foreach (Variable v in stateCmd.Locals) {
- impl.LocVars.Add(v);
- }
- newCmds.AddRange(stateCmd.Cmds);
- }
- else {
- newCmds.Add(cmd);
- }
- }
- block.Cmds = newCmds;
- }
- }
-
- public Dictionary<TransferCmd, ReturnCmd> PassifyImpl(Implementation impl, out ModelViewInfo mvInfo)
- {
- Contract.Requires(impl != null);
- Contract.Requires(program != null);
- Contract.Ensures(Contract.Result<Dictionary<TransferCmd, ReturnCmd>>() != null);
-
- Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>();
- Block exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins);
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("after creating a unified exit block");
- EmitImpl(impl, true);
- }
- #endregion
-
- #region Insert pre- and post-conditions and where clauses as assume and assert statements
- {
- List<Cmd> cc = new List<Cmd>();
- // where clauses of global variables
- lock (program.TopLevelDeclarations)
- {
- foreach (var gvar in program.GlobalVariables)
- {
- if (gvar != null && gvar.TypedIdent.WhereExpr != null)
- {
- Cmd c = new AssumeCmd(gvar.tok, gvar.TypedIdent.WhereExpr);
- cc.Add(c);
- }
- }
- }
- // where clauses of in- and out-parameters
- cc.AddRange(GetParamWhereClauses(impl));
- // where clauses of local variables
- foreach (Variable lvar in impl.LocVars) {Contract.Assert(lvar != null);
- if (lvar.TypedIdent.WhereExpr != null) {
- Cmd c = new AssumeCmd(lvar.tok, lvar.TypedIdent.WhereExpr);
- cc.Add(c);
- } else if (QKeyValue.FindBoolAttribute(lvar.Attributes, "assumption")) {
- cc.Add(new AssumeCmd(lvar.tok, new IdentifierExpr(lvar.tok, lvar), new QKeyValue(lvar.tok, "assumption_variable_initialization", new List<object>(), null)));
- }
- }
- // add cc and the preconditions to new blocks preceding impl.Blocks[0]
- InjectPreconditions(impl, cc);
-
- // append postconditions, starting in exitBlock and continuing into other blocks, if needed
- InjectPostConditions(impl, exitBlock, gotoCmdOrigins);
- }
- #endregion
-
- #region Support for stratified inlining
- addExitAssert(impl.Name, exitBlock);
- #endregion
-
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("after inserting pre- and post-conditions");
- EmitImpl(impl, true);
- }
- #endregion
-
- AddBlocksBetween(impl.Blocks);
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("after adding empty blocks as needed to catch join assumptions");
- EmitImpl(impl, true);
- }
- #endregion
-
- if (CommandLineOptions.Clo.LiveVariableAnalysis > 0) {
- Microsoft.Boogie.LiveVariableAnalysis.ComputeLiveVariables(impl);
- }
-
- mvInfo = new ModelViewInfo(program, impl);
- Convert2PassiveCmd(impl, mvInfo);
-
- #region Peep-hole optimizations
- if (CommandLineOptions.Clo.RemoveEmptyBlocks){
- #region Get rid of empty blocks
- {
- RemoveEmptyBlocksIterative(impl.Blocks);
- impl.PruneUnreachableBlocks();
- }
- #endregion Get rid of empty blocks
-
- #region Debug Tracing
- if (CommandLineOptions.Clo.TraceVerify)
- {
- Console.WriteLine("after peep-hole optimizations");
- EmitImpl(impl, true);
- }
- #endregion
- }
- #endregion Peep-hole optimizations
-
- HandleSelectiveChecking(impl);
-
-
-// #region Constant Folding
-// #endregion
-// #region Debug Tracing
-// if (CommandLineOptions.Clo.TraceVerify)
-// {
-// Console.WriteLine("after constant folding");
-// EmitImpl(impl, true);
-// }
-// #endregion
-
- return gotoCmdOrigins;
- }
-
- private static void HandleSelectiveChecking(Implementation impl)
- {
- if (QKeyValue.FindBoolAttribute(impl.Attributes, "selective_checking") ||
- QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "selective_checking")) {
-
- var startPoints = new List<Block>();
- foreach (var b in impl.Blocks) {
- foreach (Cmd c in b.Cmds) {
- var p = c as PredicateCmd;
- if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "start_checking_here")) {
- startPoints.Add(b);
- break;
- }
- }
- }
-
- // Compute the set of blocks reachable from blocks containing "start_checking_here"
- var blocksToCheck = new HashSet<Block>();
- foreach (var b in startPoints) {
- var todo = new Stack<Block>();
- var wasThere = blocksToCheck.Contains(b);
- todo.Push(b);
- while (todo.Count > 0) {
- var x = todo.Pop();
- if (blocksToCheck.Contains(x)) continue;
- blocksToCheck.Add(x);
- var ex = x.TransferCmd as GotoCmd;
- if (ex != null)
- foreach (Block e in ex.labelTargets)
- todo.Push(e);
- }
- if (!wasThere) blocksToCheck.Remove(b);
- }
-
- // Convert asserts to assumes in "unreachable" blocks, as well as in portions of blocks before we reach "start_checking_here"
- foreach (var b in impl.Blocks) {
- if (blocksToCheck.Contains(b)) continue; // All reachable blocks must be checked in their entirety, so don't change anything
- var newCmds = new List<Cmd>();
- var copyMode = false;
- foreach (Cmd c in b.Cmds) {
- var p = c as PredicateCmd;
- if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "start_checking_here"))
- copyMode = true;
- var asrt = c as AssertCmd;
- if (copyMode || asrt == null)
- newCmds.Add(c);
- else
- newCmds.Add(AssertTurnedIntoAssume(asrt));
- }
-
- b.Cmds = newCmds;
- }
- }
- }
-
- // Used by stratified inlining
- protected virtual void addExitAssert(string implName, Block exitBlock)
- {
- }
-
- public virtual Counterexample extractLoopTrace(Counterexample cex, string mainProcName, Program program, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
- {
- // Construct the set of inlined procs in the original program
- var inlinedProcs = new HashSet<string>();
- foreach (var proc in program.Procedures)
- {
- if (!(proc is LoopProcedure))
- {
- inlinedProcs.Add(proc.Name);
- }
- }
-
- return extractLoopTraceRec(
- new CalleeCounterexampleInfo(cex, new List<object>()),
- mainProcName, inlinedProcs, extractLoopMappingInfo).counterexample;
- }
-
- protected CalleeCounterexampleInfo extractLoopTraceRec(
- CalleeCounterexampleInfo cexInfo, string currProc,
- HashSet<string> inlinedProcs,
- Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
- {
- Contract.Requires(currProc != null);
- if (cexInfo.counterexample == null) return cexInfo;
-
- var cex = cexInfo.counterexample;
- // Go through all blocks in the trace, map them back to blocks in the original program (if there is one)
- var ret = cex.Clone();
- ret.Trace = new List<Block>();
- ret.calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
-
- for (int numBlock = 0; numBlock < cex.Trace.Count; numBlock ++ )
- {
- Block block = cex.Trace[numBlock];
- var origBlock = elGetBlock(currProc, block, extractLoopMappingInfo);
- if (origBlock != null) ret.Trace.Add(origBlock);
- var callCnt = 1;
- for (int numInstr = 0; numInstr < block.Cmds.Count; numInstr ++) {
- Cmd cmd = block.Cmds[numInstr];
- var loc = new TraceLocation(numBlock, numInstr);
- if (!cex.calleeCounterexamples.ContainsKey(loc))
- {
- if (getCallee(cex.getTraceCmd(loc), inlinedProcs) != null) callCnt++;
- continue;
- }
- string callee = cex.getCalledProcName(cex.getTraceCmd(loc));
- Contract.Assert(callee != null);
- var calleeTrace = cex.calleeCounterexamples[loc];
- Debug.Assert(calleeTrace != null);
-
- var origTrace = extractLoopTraceRec(calleeTrace, callee, inlinedProcs, extractLoopMappingInfo);
-
- if (elIsLoop(callee))
- {
- // Absorb the trace into the current trace
-
- int currLen = ret.Trace.Count;
- ret.Trace.AddRange(origTrace.counterexample.Trace);
-
- foreach (var kvp in origTrace.counterexample.calleeCounterexamples)
- {
- var newloc = new TraceLocation(kvp.Key.numBlock + currLen, kvp.Key.numInstr);
- ret.calleeCounterexamples.Add(newloc, kvp.Value);
- }
-
- }
- else
- {
- var origLoc = new TraceLocation(ret.Trace.Count - 1, getCallCmdPosition(origBlock, callCnt, inlinedProcs, callee));
- ret.calleeCounterexamples.Add(origLoc, origTrace);
- callCnt++;
- }
- }
- }
- return new CalleeCounterexampleInfo(ret, cexInfo.args);
- }
-
- // return the position of the i^th CallCmd in the block (count only those Calls that call a procedure in inlinedProcs).
- // Assert failure if there isn't any.
- // Assert that the CallCmd found calls "callee"
- private int getCallCmdPosition(Block block, int i, HashSet<string> inlinedProcs, string callee)
- {
- Debug.Assert(i >= 1);
- for (int pos = 0; pos < block.Cmds.Count; pos++)
- {
- Cmd cmd = block.Cmds[pos];
- string procCalled = getCallee(cmd, inlinedProcs);
-
- if (procCalled != null)
- {
- if (i == 1)
- {
- Debug.Assert(procCalled == callee);
- return pos;
- }
- i--;
- }
- }
-
- Debug.Assert(false, "Didn't find the i^th call cmd");
- return -1;
- }
-
- private string getCallee(Cmd cmd, HashSet<string> inlinedProcs)
- {
- string procCalled = null;
- if (cmd is CallCmd)
- {
- var cc = (CallCmd)cmd;
- if (inlinedProcs.Contains(cc.Proc.Name))
- {
- procCalled = cc.Proc.Name;
- }
- }
-
- if (cmd is AssumeCmd)
- {
- var expr = (cmd as AssumeCmd).Expr as NAryExpr;
- if (expr != null)
- {
- if (inlinedProcs.Contains(expr.Fun.FunctionName))
- {
- procCalled = expr.Fun.FunctionName;
- }
- }
- }
- return procCalled;
- }
-
- protected virtual bool elIsLoop(string procname)
- {
- return false;
- }
-
- private Block elGetBlock(string procname, Block block, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
- {
- Contract.Requires(procname != null);
-
- if (!extractLoopMappingInfo.ContainsKey(procname))
- return block;
-
- if (!extractLoopMappingInfo[procname].ContainsKey(block.Label))
- return null;
-
- return extractLoopMappingInfo[procname][block.Label];
- }
-
- static Counterexample TraceCounterexample(
- Block/*!*/ b, Hashtable/*!*/ traceNodes, List<Block>/*!*/ trace, Model errModel, ModelViewInfo mvInfo,
- Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap,
- ProverContext/*!*/ context,
- Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples)
- {
- Contract.Requires(b != null);
- Contract.Requires(traceNodes != null);
- Contract.Requires(trace != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
- Contract.Requires(context != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(calleeCounterexamples));
- // After translation, all potential errors come from asserts.
-
- while (true)
- {
- List<Cmd> cmds = b.Cmds;
- Contract.Assert(cmds != null);
- TransferCmd transferCmd = cce.NonNull(b.TransferCmd);
- for (int i = 0; i < cmds.Count; i++)
- {
- Cmd cmd = cce.NonNull(cmds[i]);
-
- // Skip if 'cmd' not contained in the trace or not an assert
- if (cmd is AssertCmd && traceNodes.Contains(cmd))
- {
- Counterexample newCounterexample = AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, mvInfo, context);
- Contract.Assert(newCounterexample != null);
- newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
- return newCounterexample;
- }
- }
-
- GotoCmd gotoCmd = transferCmd as GotoCmd;
- if (gotoCmd == null) return null;
- Block foundBlock = null;
- foreach (Block bb in cce.NonNull(gotoCmd.labelTargets))
- {
- Contract.Assert(bb != null);
- if (traceNodes.Contains(bb))
- {
- foundBlock = bb;
- break;
- }
- }
- if (foundBlock == null) return null;
- trace.Add(foundBlock);
- b = foundBlock;
- }
- }
-
- public static Counterexample AssertCmdToCounterexample(AssertCmd cmd, TransferCmd transferCmd, List<Block> trace, Model errModel, ModelViewInfo mvInfo, ProverContext context)
- {
- Contract.Requires(cmd != null);
- Contract.Requires(transferCmd != null);
- Contract.Requires(trace != null);
- Contract.Requires(context != null);
- Contract.Ensures(Contract.Result<Counterexample>() != null);
-
- List<string> relatedInformation = new List<string>();
-
- // See if it is a special assert inserted in translation
- if (cmd is AssertRequiresCmd)
- {
- AssertRequiresCmd assertCmd = (AssertRequiresCmd)cmd;
- Contract.Assert(assertCmd != null);
- CallCounterexample cc = new CallCounterexample(trace, assertCmd.Call, assertCmd.Requires, errModel, mvInfo, context, assertCmd.Checksum);
- cc.relatedInformation = relatedInformation;
- return cc;
- }
- else if (cmd is AssertEnsuresCmd)
- {
- AssertEnsuresCmd assertCmd = (AssertEnsuresCmd)cmd;
- Contract.Assert(assertCmd != null);
- ReturnCounterexample rc = new ReturnCounterexample(trace, transferCmd, assertCmd.Ensures, errModel, mvInfo, context, cmd.Checksum);
- rc.relatedInformation = relatedInformation;
- return rc;
- }
- else
- {
- AssertCounterexample ac = new AssertCounterexample(trace, (AssertCmd)cmd, errModel, mvInfo, context);
- ac.relatedInformation = relatedInformation;
- return ac;
- }
- }
-
- static VCExpr LetVC(Block startBlock,
- VCExpr controlFlowVariableExpr,
- Dictionary<int, Absy> label2absy,
- ProverContext proverCtxt,
- out int assertionCount) {
- Contract.Requires(startBlock != null);
- Contract.Requires(proverCtxt != null);
-
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
- List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
- VCExpr startCorrect = LetVC(startBlock, controlFlowVariableExpr, label2absy, blockVariables, bindings, proverCtxt, out assertionCount);
- return proverCtxt.ExprGen.Let(bindings, startCorrect);
- }
-
- static VCExpr LetVCIterative(List<Block> blocks,
- VCExpr controlFlowVariableExpr,
- Dictionary<int, Absy> label2absy,
- ProverContext proverCtxt,
- out int assertionCount,
- bool isPositiveContext = true)
- {
- Contract.Requires(blocks != null);
- Contract.Requires(proverCtxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- assertionCount = 0;
-
- Graph<Block> dag = new Graph<Block>();
- dag.AddSource(blocks[0]);
- foreach (Block b in blocks) {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- Contract.Assume(gtc.labelTargets != null);
- foreach (Block dest in gtc.labelTargets) {
- Contract.Assert(dest != null);
- dag.AddEdge(dest, b);
- }
- }
- }
- IEnumerable sortedNodes = dag.TopologicalSort();
- Contract.Assert(sortedNodes != null);
-
- Dictionary<Block, VCExprVar> blockVariables = new Dictionary<Block, VCExprVar>();
- List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
- VCExpressionGenerator gen = proverCtxt.ExprGen;
- Contract.Assert(gen != null);
- foreach (Block block in sortedNodes) {
- VCExpr SuccCorrect;
- GotoCmd gotocmd = block.TransferCmd as GotoCmd;
- if (gotocmd == null) {
- ReturnExprCmd re = block.TransferCmd as ReturnExprCmd;
- if (re == null) {
- SuccCorrect = VCExpressionGenerator.True;
- }
- else {
- SuccCorrect = proverCtxt.BoogieExprTranslator.Translate(re.Expr);
- if (isPositiveContext)
- {
- SuccCorrect = gen.Not(SuccCorrect);
- }
- }
- }
- else {
- Contract.Assert(gotocmd.labelTargets != null);
- List<VCExpr> SuccCorrectVars = new List<VCExpr>(gotocmd.labelTargets.Count);
- foreach (Block successor in gotocmd.labelTargets) {
- Contract.Assert(successor != null);
- VCExpr s = blockVariables[successor];
- if (controlFlowVariableExpr != null) {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
- VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
- s = gen.Implies(controlTransferExpr, s);
- }
- SuccCorrectVars.Add(s);
- }
- SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
- }
-
- VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr, isPositiveContext);
- VCExpr vc = Wlp.Block(block, SuccCorrect, context);
- assertionCount += context.AssertionCount;
-
- VCExprVar v = gen.Variable(block.Label + "_correct", Bpl.Type.Bool);
- bindings.Add(gen.LetBinding(v, vc));
- blockVariables.Add(block, v);
- }
-
- return proverCtxt.ExprGen.Let(bindings, blockVariables[blocks[0]]);
- }
-
- static VCExpr LetVC(Block block,
- VCExpr controlFlowVariableExpr,
- Dictionary<int, Absy> label2absy,
- Hashtable/*<Block, VCExprVar!>*/ blockVariables,
- List<VCExprLetBinding/*!*/>/*!*/ bindings,
- ProverContext proverCtxt,
- out int assertionCount)
- {
- Contract.Requires(block != null);
- Contract.Requires(blockVariables!= null);
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Requires(proverCtxt != null);
-
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- assertionCount = 0;
-
- VCExpressionGenerator gen = proverCtxt.ExprGen;
- Contract.Assert(gen != null);
- VCExprVar v = (VCExprVar)blockVariables[block];
- if (v == null) {
- /*
- * For block A (= block), generate:
- * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct))
- * with the side effect of adding the let bindings to "bindings" for any
- * successor not yet visited.
- */
- VCExpr SuccCorrect;
- GotoCmd gotocmd = block.TransferCmd as GotoCmd;
- if (gotocmd == null) {
- ReturnExprCmd re = block.TransferCmd as ReturnExprCmd;
- if (re == null) {
- SuccCorrect = VCExpressionGenerator.True;
- } else {
- SuccCorrect = proverCtxt.BoogieExprTranslator.Translate(re.Expr);
- }
- } else {
- Contract.Assert( gotocmd.labelTargets != null);
- List<VCExpr> SuccCorrectVars = new List<VCExpr>(gotocmd.labelTargets.Count);
- foreach (Block successor in gotocmd.labelTargets) {
- Contract.Assert(successor != null);
- int ac;
- VCExpr s = LetVC(successor, controlFlowVariableExpr, label2absy, blockVariables, bindings, proverCtxt, out ac);
- assertionCount += ac;
- if (controlFlowVariableExpr != null)
- {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
- VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
- s = gen.Implies(controlTransferExpr, s);
- }
- SuccCorrectVars.Add(s);
- }
- SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
- }
-
-
- VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
- VCExpr vc = Wlp.Block(block, SuccCorrect, context);
- assertionCount += context.AssertionCount;
-
- v = gen.Variable(block.Label + "_correct", Bpl.Type.Bool);
- bindings.Add(gen.LetBinding(v, vc));
- blockVariables.Add(block, v);
- }
- return v;
- }
-
- static VCExpr DagVC(Block block,
- VCExpr controlFlowVariableExpr,
- Dictionary<int, Absy> label2absy,
- Hashtable/*<Block, VCExpr!>*/ blockEquations,
- ProverContext proverCtxt,
- out int assertionCount)
- {
- Contract.Requires(block != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(blockEquations != null);
- Contract.Requires(proverCtxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- assertionCount = 0;
- VCExpressionGenerator gen = proverCtxt.ExprGen;
- Contract.Assert(gen != null);
- VCExpr vc = (VCExpr)blockEquations[block];
- if (vc != null) {
- return vc;
- }
-
- /*
- * For block A (= block), generate:
- * wp(A_body, (/\ S \in Successors(A) :: DagVC(S)))
- */
- VCExpr SuccCorrect = null;
- GotoCmd gotocmd = block.TransferCmd as GotoCmd;
- if (gotocmd != null)
- {
- foreach (Block successor in cce.NonNull(gotocmd.labelTargets)) {
- Contract.Assert(successor != null);
- int ac;
- VCExpr c = DagVC(successor, controlFlowVariableExpr, label2absy, blockEquations, proverCtxt, out ac);
- assertionCount += ac;
- if (controlFlowVariableExpr != null) {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
- VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
- c = gen.Implies(controlTransferExpr, c);
- }
- SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
- }
- }
- if (SuccCorrect == null) {
- SuccCorrect = VCExpressionGenerator.True;
- }
-
- VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
- vc = Wlp.Block(block, SuccCorrect, context);
- assertionCount += context.AssertionCount;
-
- // gen.MarkAsSharedFormula(vc); PR: don't know yet what to do with this guy
-
- blockEquations.Add(block, vc);
- return vc;
- }
-
- static VCExpr FlatBlockVC(Implementation impl,
- Dictionary<int, Absy> label2absy,
- bool local, bool reach, bool doomed,
- ProverContext proverCtxt,
- out int assertionCount)
- {
- Contract.Requires(impl != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(proverCtxt != null);
- Contract.Requires( !local || !reach); // "reach" must be false for local
-
- VCExpressionGenerator gen = proverCtxt.ExprGen;
- Contract.Assert(gen != null);
- Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
- Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
-
- List<Block> blocks = impl.Blocks;
- Contract.Assert(blocks != null);
- // block sorting is now done on the VCExpr
- // if (!local && (cce.NonNull(CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
- // blocks = SortBlocks(blocks);
- // }
-
- VCExpr proofObligation;
- if (!local) {
- proofObligation = cce.NonNull((VCExprVar)BlkCorrect[impl.Blocks[0]]);
- } else {
- List<VCExpr> conjuncts = new List<VCExpr>(blocks.Count);
- foreach (Block b in blocks) {Contract.Assert(b != null);
- VCExpr v = cce.NonNull((VCExprVar)BlkCorrect[b]);
- conjuncts.Add(v);
- }
- proofObligation = gen.NAry(VCExpressionGenerator.AndOp, conjuncts);
- }
-
- VCContext context = new VCContext(label2absy, proverCtxt);
- Contract.Assert(context != null);
-
- List<VCExprLetBinding> programSemantics = new List<VCExprLetBinding>(blocks.Count);
- foreach (Block b in blocks) {Contract.Assert(b != null);
- /*
- * In block mode,
- * For a return block A, generate:
- * A_correct <== wp(A_body, true) [post-condition has been translated into an assert]
- * For all other blocks, generate:
- * A_correct <== wp(A_body, (/\ S \in Successors(A) :: S_correct))
- *
- * In doomed mode, proceed as in block mode, except for a return block A, generate:
- * A_correct <== wp(A_body, false) [post-condition has been translated into an assert]
- *
- * In block reach mode, the wp(A_body,...) in the equations above change to:
- * A_reached ==> wp(A_body,...)
- * and the conjunction above changes to:
- * (/\ S \in Successors(A) :: S_correct \/ (\/ T \in Successors(A) && T != S :: T_reached))
- *
- * In local mode, generate:
- * A_correct <== wp(A_body, true)
- */
- VCExpr SuccCorrect;
- if (local) {
- SuccCorrect = VCExpressionGenerator.True;
- } else {
- SuccCorrect = SuccessorsCorrect(b, BlkCorrect, BlkReached, doomed, gen);
- }
-
- VCExpr wlp = Wlp.Block(b, SuccCorrect, context);
- if (BlkReached != null) {
- wlp = gen.Implies(cce.NonNull((VCExprVar)BlkReached[b]), wlp);
- }
-
- VCExprVar okVar = cce.NonNull((VCExprVar)BlkCorrect[b]);
- VCExprLetBinding binding = gen.LetBinding(okVar, wlp);
- programSemantics.Add(binding);
- }
-
- assertionCount = context.AssertionCount;
- return gen.Let(programSemantics, proofObligation);
- }
-
- private static Hashtable/* Block --> VCExprVar */ BlockVariableMap(List<Block/*!*/>/*!*/ blocks, string suffix,
- Microsoft.Boogie.VCExpressionGenerator gen) {
- Contract.Requires(cce.NonNullElements(blocks));
- Contract.Requires(suffix != null);
- Contract.Requires(gen != null);
- Contract.Ensures(Contract.Result<Hashtable>() != null);
-
- Hashtable/* Block --> VCExprVar */ map = new Hashtable/* Block --> (Let)Variable */();
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- VCExprVar v = gen.Variable(b.Label + suffix, Bpl.Type.Bool);
- Contract.Assert(v != null);
- map.Add(b, v);
- }
- return map;
- }
-
- private static VCExpr SuccessorsCorrect(
- Block b,
- Hashtable/* Block --> VCExprVar */ BlkCorrect,
- Hashtable/* Block --> VCExprVar */ BlkReached,
- bool doomed,
- Microsoft.Boogie.VCExpressionGenerator gen) {
- Contract.Requires(b != null);
- Contract.Requires(BlkCorrect != null);
- Contract.Requires(gen != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr SuccCorrect = null;
- GotoCmd gotocmd = b.TransferCmd as GotoCmd;
- if (gotocmd != null) {
- foreach (Block successor in cce.NonNull(gotocmd.labelTargets)) {
- Contract.Assert(successor != null);
- // c := S_correct
- VCExpr c = (VCExprVar)BlkCorrect[successor];
- Contract.Assert(c != null);
- if (BlkReached != null) {
- // c := S_correct \/ Sibling0_reached \/ Sibling1_reached \/ ...;
- foreach (Block successorSibling in gotocmd.labelTargets) {
- Contract.Assert(successorSibling != null);
- if (successorSibling != successor) {
- c = gen.Or(c, cce.NonNull((VCExprVar)BlkReached[successorSibling]));
- }
- }
- }
- SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
- }
- }
- if (SuccCorrect == null) {
- return VCExpressionGenerator.True;
- } else if (doomed) {
- return VCExpressionGenerator.False;
- } else {
- return SuccCorrect;
- }
- }
-
- static VCExpr NestedBlockVC(Implementation impl,
- Dictionary<int, Absy> label2absy,
- bool reach,
- ProverContext proverCtxt,
- out int assertionCount){
- Contract.Requires(impl != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(proverCtxt != null);
- Contract.Requires( impl.Blocks.Count != 0);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpressionGenerator gen = proverCtxt.ExprGen;
- Contract.Assert(gen != null);
- Graph<Block> g = Program.GraphFromImpl(impl);
-
- Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
- Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
-
- Block startBlock = cce.NonNull( impl.Blocks[0]);
- VCExpr proofObligation = (VCExprVar)BlkCorrect[startBlock];
- Contract.Assert(proofObligation != null);
- VCContext context = new VCContext(label2absy, proverCtxt);
-
- Hashtable/*Block->int*/ totalOrder = new Hashtable/*Block->int*/();
- {
- List<Block> blocks = impl.Blocks;
-
- // block sorting is now done on the VCExpr
- // if (((!)CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
- // blocks = SortBlocks(blocks);
- // }
- int i = 0;
- foreach (Block b in blocks) {
- Contract.Assert(b != null);
- totalOrder[b] = i;
- i++;
- }
- }
-
- VCExprLetBinding programSemantics = NestedBlockEquation(cce.NonNull(impl.Blocks[0]), BlkCorrect, BlkReached, totalOrder, context, g, gen);
- List<VCExprLetBinding> ps = new List<VCExprLetBinding>(1);
- ps.Add(programSemantics);
-
- assertionCount = context.AssertionCount;
- return gen.Let(ps, proofObligation);
- }
-
- private static VCExprLetBinding NestedBlockEquation(Block b,
- Hashtable/*Block-->VCExprVar*/ BlkCorrect,
- Hashtable/*Block-->VCExprVar*/ BlkReached,
- Hashtable/*Block->int*/ totalOrder,
- VCContext context,
- Graph<Block> g,
- Microsoft.Boogie.VCExpressionGenerator gen) {
- Contract.Requires(b != null);
- Contract.Requires(BlkCorrect != null);
- Contract.Requires(totalOrder != null);
- Contract.Requires(g != null);
- Contract.Requires(context != null);
-
- Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
-
- /*
- * For a block b, return:
- * LET_BINDING b_correct = wp(b_body, X)
- * where X is:
- * LET (THOSE d \in DirectDominates(b) :: BlockEquation(d))
- * IN (/\ s \in Successors(b) :: s_correct)
- *
- * When the VC-expression generator does not support LET expresions, this
- * will eventually turn into:
- * b_correct <== wp(b_body, X)
- * where X is:
- * (/\ s \in Successors(b) :: s_correct)
- * <==
- * (/\ d \in DirectDominatees(b) :: BlockEquation(d))
- *
- * In both cases above, if BlkReached is non-null, then the wp expression
- * is instead:
- * b_reached ==> wp(b_body, X)
- */
-
- VCExpr SuccCorrect = SuccessorsCorrect(b, BlkCorrect, null, false, gen);
- Contract.Assert(SuccCorrect != null);
-
- List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
- foreach (Block dominee in GetSortedBlocksImmediatelyDominatedBy(g, b, totalOrder)) {
- Contract.Assert(dominee != null);
- VCExprLetBinding c = NestedBlockEquation(dominee, BlkCorrect, BlkReached, totalOrder, context, g, gen);
- bindings.Add(c);
- }
-
- VCExpr X = gen.Let(bindings, SuccCorrect);
- VCExpr wlp = Wlp.Block(b, X, context);
- if (BlkReached != null) {
- wlp = gen.Implies((VCExprVar)BlkReached[b], wlp);
- Contract.Assert(wlp != null);
- }
- VCExprVar okVar = cce.NonNull((VCExprVar)BlkCorrect[b]);
- return gen.LetBinding(okVar, wlp);
- }
-
- /// <summary>
- /// Returns a list of g.ImmediatelyDominatedBy(b), but in a sorted order, hoping to steer around
- /// the nondeterminism problems we've been seeing by using just this call.
- /// </summary>
- static List<Block/*!*/>/*!*/ GetSortedBlocksImmediatelyDominatedBy(Graph<Block>/*!*/ g, Block/*!*/ b, Hashtable/*Block->int*//*!*/ totalOrder) {
- Contract.Requires(g != null);
- Contract.Requires(b != null);
- Contract.Requires(totalOrder != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
-
- List<Block> list = new List<Block>();
- foreach (Block dominee in g.ImmediatelyDominatedBy(b)) {
- Contract.Assert(dominee != null);
- list.Add(dominee);
- }
- list.Sort(new Comparison<Block>(delegate(Block x, Block y) {
- return (int)cce.NonNull(totalOrder[x]) - (int)cce.NonNull(totalOrder[y]);
- }));
- return list;
- }
-
- static VCExpr VCViaStructuredProgram
- (Implementation impl, Dictionary<int, Absy> label2absy,
- ProverContext proverCtxt,
- out int assertionCount)
- {
- Contract.Requires(impl != null);
- Contract.Requires(label2absy != null);
- Contract.Requires(proverCtxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- #region Convert block structure back to a "regular expression"
- RE r = DAG2RE.Transform(cce.NonNull(impl.Blocks[0]));
- Contract.Assert(r != null);
- #endregion
-
- VCContext ctxt = new VCContext(label2absy, proverCtxt);
- Contract.Assert(ctxt != null);
- #region Send wlp(program,true) to Simplify
- var vcexp = Wlp.RegExpr(r, VCExpressionGenerator.True, ctxt);
- assertionCount = ctxt.AssertionCount;
- return vcexp;
- #endregion
- }
-
- /// <summary>
- /// Remove empty blocks reachable from the startBlock of the CFG
- /// </summary>
- static void RemoveEmptyBlocksIterative(List<Block> blocks) {
- // postorder traversal of cfg
- // noting loop heads in [keep] and
- // generating token information in [renameInfo]
- Block startBlock = blocks[0];
- var postorder = new List<Block>();
- var keep = new HashSet<Block>();
- var visited = new HashSet<Block>();
- var grey = new HashSet<Block>();
- var stack = new Stack<Block>();
- Dictionary<Block, Block> renameInfo = new Dictionary<Block, Block>();
-
- stack.Push(startBlock);
- visited.Add(startBlock);
- while (stack.Count != 0) {
- var curr = stack.Pop();
- if (grey.Contains(curr)) {
- postorder.Add(curr);
-
- // generate renameInfoForStartBlock
- GotoCmd gtc = curr.TransferCmd as GotoCmd;
- renameInfo[curr] = null;
- if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Count == 0) {
- if (curr.Cmds.Count == 0 && curr.tok.IsValid) {
- renameInfo[curr] = curr;
- }
- } else {
- if (curr.Cmds.Count == 0 || curr == startBlock) {
- if (curr.tok.IsValid) {
- renameInfo[curr] = curr;
- } else {
- HashSet<Block> successorRenameInfo = new HashSet<Block>();
- foreach (Block s in gtc.labelTargets) {
- if (keep.Contains(s)) {
- successorRenameInfo.Add(null);
- } else {
- successorRenameInfo.Add(renameInfo[s]);
- }
- }
- if (successorRenameInfo.Count == 1) {
- renameInfo[curr] = successorRenameInfo.Single();
- }
- }
- }
- }
- // end generate renameInfoForStartBlock
-
- } else {
- grey.Add(curr);
- stack.Push(curr);
- GotoCmd gtc = curr.TransferCmd as GotoCmd;
- if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Count == 0) continue;
- foreach (Block s in gtc.labelTargets) {
- if (!visited.Contains(s)) {
- visited.Add(s);
- stack.Push(s);
- } else if (grey.Contains(s) && !postorder.Contains(s)) { // s is a loop head
- keep.Add(s);
- }
- }
- }
- }
- keep.Add(startBlock);
-
- foreach (Block b in postorder) {
- if (!keep.Contains(b) && b.Cmds.Count == 0) {
- GotoCmd bGtc = b.TransferCmd as GotoCmd;
- foreach (Block p in b.Predecessors) {
- GotoCmd pGtc = p.TransferCmd as GotoCmd;
- Contract.Assert(pGtc != null);
- pGtc.labelTargets.Remove(b);
- pGtc.labelNames.Remove(b.Label);
- }
- if (bGtc == null || bGtc.labelTargets == null || bGtc.labelTargets.Count == 0) {
- continue;
- }
-
- List<Block> successors = bGtc.labelTargets;
-
- // Try to push token information if possible
- if (b.tok.IsValid && successors.Count == 1 && b != renameInfo[startBlock]) {
- var s = successors.Single();
- if (!s.tok.IsValid) {
- foreach (Block p in s.Predecessors) {
- if (p != b) {
- GotoCmd pGtc = p.TransferCmd as GotoCmd;
- Contract.Assert(pGtc != null);
- pGtc.labelTargets.Remove(s);
- pGtc.labelNames.Remove(s.Label);
- pGtc.labelTargets.Add(s);
- pGtc.labelNames.Add(b.Label);
- }
- }
- s.tok = b.tok;
- s.Label = b.Label;
- }
- }
-
- foreach (Block p in b.Predecessors) {
- GotoCmd pGtc = p.TransferCmd as GotoCmd;
- Contract.Assert(pGtc != null);
- foreach (Block s in successors) {
- if (!pGtc.labelTargets.Contains(s)) {
- pGtc.labelTargets.Add(s);
- pGtc.labelNames.Add(s.Label);
- }
- }
- }
- }
- }
-
- if (!startBlock.tok.IsValid && startBlock.Cmds.All(c => c is AssumeCmd)) {
- if (renameInfo[startBlock] != null) {
- startBlock.tok = renameInfo[startBlock].tok;
- startBlock.Label = renameInfo[startBlock].Label;
- }
- }
-
- }
-
- /// <summary>
- /// Remove the empty blocks reachable from the block.
- /// It changes the visiting state of the blocks, so that if you want to visit again the blocks, you have to reset them...
- /// </summary>
- static List<Block> RemoveEmptyBlocks(Block b) {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
-
- Contract.Assert(b.TraversingStatus == Block.VisitState.ToVisit);
- Block renameInfo;
- List<Block> retVal = removeEmptyBlocksWorker(b, true, out renameInfo);
- if (renameInfo != null && !b.tok.IsValid) {
- bool onlyAssumes = true;
- foreach (Cmd c in b.Cmds) {
- if (!(c is AssumeCmd)) {
- onlyAssumes = false;
- break;
- }
- }
- if (onlyAssumes) {
- b.tok = renameInfo.tok;
- b.Label = renameInfo.Label;
- }
- }
- return retVal;
- }
-
- /// <summary>
- /// For every not-yet-visited block n reachable from b, change n's successors to skip empty nodes.
- /// Return the *set* of blocks reachable from b without passing through a nonempty block.
- /// The target of any backedge is counted as a nonempty block.
- /// If renameInfoForStartBlock is non-null, it denotes an empty block with location information, and that
- /// information would be appropriate to display
- /// </summary>
- private static List<Block> removeEmptyBlocksWorker(Block b, bool startNode, out Block renameInfoForStartBlock)
- {
- Contract.Requires(b != null);
- Contract.Ensures(Contract.ValueAtReturn(out renameInfoForStartBlock) == null || Contract.ValueAtReturn(out renameInfoForStartBlock).tok.IsValid);
- // ensures: b in result ==> renameInfoForStartBlock == null;
-
- renameInfoForStartBlock = null;
- List<Block> bs = new List<Block>();
- GotoCmd gtc = b.TransferCmd as GotoCmd;
-
- // b has no successors
- if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Count == 0)
- {
- if (b.Cmds.Count != 0){ // only empty blocks are removed...
- bs.Add(b);
- } else if (b.tok.IsValid) {
- renameInfoForStartBlock = b;
- }
- return bs;
- }
- else if (b.TraversingStatus == Block.VisitState.ToVisit) // if b has some successors and we have not seen it so far...
- {
- b.TraversingStatus = Block.VisitState.BeingVisited;
-
- // Before recursing down to successors, make a sobering observation:
- // If b has no commands and is not the start node, then it will see
- // extinction (because it will not be included in the "return setOfSuccessors"
- // statement below). In that case, if b has a location, then the location
- // information would be lost. Hence, make an attempt to save the location
- // by pushing the location onto b's successor. This can be done if (0) b has
- // exactly one successor, (1) that successor has no location of its own, and
- // (2) that successor has no other predecessors.
- if (b.Cmds.Count == 0 && !startNode) {
- // b is about to become extinct; try to save its name and location, if possible
- if (b.tok.IsValid && gtc.labelTargets.Count == 1) {
- Block succ = cce.NonNull(gtc.labelTargets[0]);
- if (!succ.tok.IsValid && succ.Predecessors.Count == 1) {
- succ.tok = b.tok;
- succ.Label = b.Label;
- }
- }
- }
-
- // recursively call this method on each successor
- // merge result into a *set* of blocks
- HashSet<Block> mergedSuccessors = new HashSet<Block>();
- int m = 0; // in the following loop, set renameInfoForStartBlock to the value that all recursive calls agree on, if possible; otherwise, null
- foreach (Block dest in gtc.labelTargets){Contract.Assert(dest != null);
- Block renameInfo;
- List<Block> ys = removeEmptyBlocksWorker(dest, false, out renameInfo);
- Contract.Assert(ys != null);
- if (m == 0) {
- renameInfoForStartBlock = renameInfo;
- } else if (renameInfoForStartBlock != renameInfo) {
- renameInfoForStartBlock = null;
- }
- foreach (Block successor in ys){
- if (!mergedSuccessors.Contains(successor))
- mergedSuccessors.Add(successor);
- }
- m++;
- }
- b.TraversingStatus = Block.VisitState.AlreadyVisited;
-
- List<Block> setOfSuccessors = new List<Block>();
- foreach (Block d in mergedSuccessors)
- setOfSuccessors.Add(d);
- if (b.Cmds.Count == 0 && !startNode) {
- // b is about to become extinct
- if (b.tok.IsValid) {
- renameInfoForStartBlock = b;
- }
- return setOfSuccessors;
- }
- // otherwise, update the list of successors of b to be the blocks in setOfSuccessors
- gtc.labelTargets = setOfSuccessors;
- gtc.labelNames = new List<String>();
- foreach (Block d in setOfSuccessors){
- Contract.Assert(d != null);
- gtc.labelNames.Add(d.Label);}
- if (!startNode) {
- renameInfoForStartBlock = null;
- }
- return new List<Block> { b };
- }
- else // b has some successors, but we are already visiting it, or we have already visited it...
- {
- return new List<Block> { b };
- }
- }
-
- static void DumpMap(Hashtable /*Variable->Expr*/ map) {
- Contract.Requires(map != null);
- foreach (DictionaryEntry de in map) {
- Variable v = (Variable)de.Key;
- Contract.Assert(v != null);
- Expr e = (Expr)de.Value;
- Contract.Assert(e != null);
- Console.Write(" ");
- v.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false), 0);
- Console.Write(" --> ");
- e.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false));
- Console.WriteLine();
- }
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.IO;
+using Microsoft.Boogie;
+using Microsoft.Boogie.GraphUtil;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+namespace VC {
+ using Bpl = Microsoft.Boogie;
+ using System.Threading.Tasks;
+
+ public class VCGen : ConditionGeneration {
+ private const bool _print_time = false;
+ /// <summary>
+ /// Constructor. Initializes the theorem prover.
+ /// </summary>
+ [NotDelayed]
+ public VCGen(Program program, string/*?*/ logFilePath, bool appendLogFile, List<Checker> checkers)
+ : base(program, checkers)
+ {
+ Contract.Requires(program != null);
+ this.appendLogFile = appendLogFile;
+ this.logFilePath = logFilePath;
+ }
+
+ private static AssumeCmd AssertTurnedIntoAssume(AssertCmd assrt) {
+ Contract.Requires(assrt != null);
+ Contract.Ensures(Contract.Result<AssumeCmd>() != null);
+
+ Expr expr = assrt.Expr;
+ Contract.Assert(expr != null);
+ switch (Wlp.Subsumption(assrt)) {
+ case CommandLineOptions.SubsumptionOption.Never:
+ expr = Expr.True;
+ break;
+ case CommandLineOptions.SubsumptionOption.Always:
+ break;
+ case CommandLineOptions.SubsumptionOption.NotForQuantifiers:
+ if (expr is QuantifierExpr) {
+ expr = Expr.True;
+ }
+ break;
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // unexpected case
+ }
+
+ return new AssumeCmd(assrt.tok, expr);
+ }
+
+ #region Soundness smoke tester
+ class SmokeTester {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(parent != null);
+ Contract.Invariant(impl != null);
+ Contract.Invariant(initial != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(copies));
+ Contract.Invariant(cce.NonNull(visited));
+ Contract.Invariant(callback != null);
+ }
+
+ VCGen parent;
+ Implementation impl;
+ Block initial;
+ int id;
+ Dictionary<Block, Block> copies = new Dictionary<Block, Block>();
+ HashSet<Block> visited = new HashSet<Block>();
+ VerifierCallback callback;
+
+ internal SmokeTester(VCGen par, Implementation i, VerifierCallback callback) {
+ Contract.Requires(par != null);
+ Contract.Requires(i != null);
+ Contract.Requires(callback != null);
+ parent = par;
+ impl = i;
+ initial = i.Blocks[0];
+ this.callback = callback;
+ }
+
+ internal void Copy() {
+ CloneBlock(impl.Blocks[0]);
+ initial = GetCopiedBlocks()[0];
+ }
+
+ internal void Test() {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ DFS(initial);
+ }
+
+ void TopologicalSortImpl() {
+ Graph<Block> dag = new Graph<Block>();
+ dag.AddSource(cce.NonNull(impl.Blocks[0])); // there is always at least one node in the graph
+ foreach (Block b in impl.Blocks) {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null) {
+ Contract.Assume(gtc.labelTargets != null);
+ foreach (Block dest in gtc.labelTargets) {
+ Contract.Assert(dest != null);
+ dag.AddEdge(b, dest);
+ }
+ }
+ }
+ impl.Blocks = new List<Block>();
+ foreach (Block b in dag.TopologicalSort()) {
+ Contract.Assert(b != null);
+ impl.Blocks.Add(b);
+ }
+ }
+
+ void Emit() {
+ TopologicalSortImpl();
+ EmitImpl(impl, false);
+ }
+
+ // this one copies forward
+ Block CloneBlock(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+
+ Block fake_res;
+ if (copies.TryGetValue(b, out fake_res)) {
+ return cce.NonNull(fake_res);
+ }
+ Block res = new Block(b.tok, b.Label, new List<Cmd>(b.Cmds), null);
+ copies[b] = res;
+ if (b.TransferCmd is GotoCmd) {
+ foreach (Block ch in cce.NonNull((GotoCmd)b.TransferCmd).labelTargets) {
+ Contract.Assert(ch != null);
+ CloneBlock(ch);
+ }
+ }
+ foreach (Block p in b.Predecessors) {
+ Contract.Assert(p != null);
+ res.Predecessors.Add(CloneBlock(p));
+ }
+ return res;
+ }
+
+ // this one copies backwards
+ Block CopyBlock(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+
+ Block fake_res;
+ if (copies.TryGetValue(b, out fake_res)) {
+ // fake_res should be Block! but the compiler fails
+ return cce.NonNull(fake_res);
+ }
+ Block res;
+ List<Cmd> seq = new List<Cmd>();
+ foreach (Cmd c in b.Cmds) {
+ Contract.Assert(c != null);
+ AssertCmd turn = c as AssertCmd;
+ if (!turnAssertIntoAssumes || turn == null) {
+ seq.Add(c);
+ } else {
+ seq.Add(AssertTurnedIntoAssume(turn));
+ }
+ }
+ res = new Block(b.tok, b.Label, seq, null);
+ copies[b] = res;
+ foreach (Block p in b.Predecessors) {
+ Contract.Assert(p != null);
+ res.Predecessors.Add(CopyBlock(p));
+ }
+ return res;
+ }
+
+ List<Block> GetCopiedBlocks() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
+
+ // the order of nodes in res is random (except for the first one, being the entry)
+ List<Block> res = new List<Block>();
+ res.Add(copies[initial]);
+
+ foreach (KeyValuePair<Block, Block> kv in copies) {
+ Contract.Assert(kv.Key != null&&kv.Value!=null);
+ GotoCmd go = kv.Key.TransferCmd as GotoCmd;
+ ReturnCmd ret = kv.Key.TransferCmd as ReturnCmd;
+ if (kv.Key != initial) {
+ res.Add(kv.Value);
+ }
+ if (go != null) {
+ GotoCmd copy = new GotoCmd(go.tok, new List<String>(), new List<Block>());
+ kv.Value.TransferCmd = copy;
+ foreach (Block b in cce.NonNull(go.labelTargets)) {
+ Contract.Assert(b != null);
+ Block c;
+ if (copies.TryGetValue(b, out c)) {
+ copy.AddTarget(cce.NonNull(c));
+ }
+ }
+ } else if (ret != null) {
+ kv.Value.TransferCmd = ret;
+ } else {
+ Contract.Assume(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ copies.Clear();
+
+ return res;
+ }
+
+ // check if e is true, false, !true, !false
+ // if so return true and the value of the expression in val
+ bool BooleanEval(Expr e, ref bool val) {
+ Contract.Requires(e != null);
+ LiteralExpr lit = e as LiteralExpr;
+ NAryExpr call = e as NAryExpr;
+
+ if (lit != null && lit.isBool) {
+ val = lit.asBool;
+ return true;
+ } else if (call != null &&
+ call.Fun is UnaryOperator &&
+ ((UnaryOperator)call.Fun).Op == UnaryOperator.Opcode.Not &&
+ BooleanEval(cce.NonNull(call.Args[0]), ref val)) {
+ val = !val;
+ return true;
+ }
+ // this is for the 0bv32 != 0bv32 generated by vcc
+ else if (call != null &&
+ call.Fun is BinaryOperator &&
+ ((BinaryOperator)call.Fun).Op == BinaryOperator.Opcode.Neq &&
+ call.Args[0] is LiteralExpr &&
+ cce.NonNull(call.Args[0]).Equals(call.Args[1])) {
+ val = false;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool IsFalse(Expr e) {
+ Contract.Requires(e != null);
+ bool val = false;
+ return BooleanEval(e, ref val) && !val;
+ }
+
+ bool CheckUnreachable(Block cur, List<Cmd> seq)
+ {
+ Contract.Requires(cur != null);
+ Contract.Requires(seq != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ foreach (Cmd cmd in seq)
+ {
+ AssertCmd assrt = cmd as AssertCmd;
+ if (assrt != null && QKeyValue.FindBoolAttribute(assrt.Attributes, "PossiblyUnreachable"))
+ return false;
+ }
+
+ DateTime start = DateTime.UtcNow;
+ if (CommandLineOptions.Clo.Trace)
+ {
+ System.Console.Write(" soundness smoke test #{0} ... ", id);
+ }
+ callback.OnProgress("smoke", id, id, 0.0);
+
+ Token tok = new Token();
+ tok.val = "soundness smoke test assertion";
+ seq.Add(new AssertCmd(tok, Expr.False));
+ Block copy = CopyBlock(cur);
+ Contract.Assert(copy != null);
+ copy.Cmds = seq;
+ List<Block> backup = impl.Blocks;
+ Contract.Assert(backup != null);
+ impl.Blocks = GetCopiedBlocks();
+ copy.TransferCmd = new ReturnCmd(Token.NoToken);
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ System.Console.WriteLine();
+ System.Console.WriteLine(" --- smoke #{0}, before passify", id);
+ Emit();
+ }
+ parent.CurrentLocalVariables = impl.LocVars;
+ ModelViewInfo mvInfo;
+ parent.PassifyImpl(impl, out mvInfo);
+ Dictionary<int, Absy> label2Absy;
+ Checker ch = parent.FindCheckerFor(CommandLineOptions.Clo.SmokeTimeout);
+ Contract.Assert(ch != null);
+
+ ProverInterface.Outcome outcome = ProverInterface.Outcome.Undetermined;
+ try
+ {
+ lock (ch)
+ {
+ var exprGen = ch.TheoremProver.Context.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+
+ VCExpr vc = parent.GenerateVC(impl, controlFlowVariableExpr, out label2Absy, ch.TheoremProver.Context);
+ Contract.Assert(vc != null);
+
+ if (!CommandLineOptions.Clo.UseLabels)
+ {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vc = exprGen.Implies(eqExpr, vc);
+ }
+
+ impl.Blocks = backup;
+
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ System.Console.WriteLine(" --- smoke #{0}, after passify", id);
+ Emit();
+ }
+
+ ch.BeginCheck(cce.NonNull(impl.Name + "_smoke" + id++), vc, new ErrorHandler(label2Absy, this.callback));
+ }
+
+ ch.ProverTask.Wait();
+
+ lock (ch)
+ {
+ outcome = ch.ReadOutcome();
+ }
+ }
+ finally
+ {
+ ch.GoBackToIdle();
+ }
+
+ parent.CurrentLocalVariables = null;
+
+ DateTime end = DateTime.UtcNow;
+ TimeSpan elapsed = end - start;
+ if (CommandLineOptions.Clo.Trace)
+ {
+ System.Console.WriteLine(" [{0} s] {1}", elapsed.TotalSeconds,
+ outcome == ProverInterface.Outcome.Valid ? "OOPS" :
+ "OK" + (outcome == ProverInterface.Outcome.Invalid ? "" : " (" + outcome + ")"));
+ }
+
+ if (outcome == ProverInterface.Outcome.Valid)
+ {
+ // copy it again, so we get the version with calls, assignments and such
+ copy = CopyBlock(cur);
+ copy.Cmds = seq;
+ impl.Blocks = GetCopiedBlocks();
+ TopologicalSortImpl();
+ callback.OnUnreachableCode(impl);
+ impl.Blocks = backup;
+ return true;
+ }
+ return false;
+ }
+
+ const bool turnAssertIntoAssumes = false;
+
+ void DFS(Block cur) {
+ Contract.Requires(cur != null);
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ if (visited.Contains(cur))
+ return;
+ visited.Add(cur);
+
+ List<Cmd> seq = new List<Cmd>();
+ foreach (Cmd cmd_ in cur.Cmds) {
+ Cmd cmd = cmd_;
+ Contract.Assert(cmd != null);
+ AssertCmd assrt = cmd as AssertCmd;
+ AssumeCmd assm = cmd as AssumeCmd;
+ CallCmd call = cmd as CallCmd;
+
+ bool assumeFalse = false;
+
+ if (assrt != null) {
+ // we're not going any further
+ // it's clear the user expected unreachable code here
+ // it's not clear where did he expect it, maybe it would be right to insert
+ // a check just one command before
+ if (IsFalse(assrt.Expr))
+ return;
+
+#if TURN_ASSERT_INFO_ASSUMES
+ if (turnAssertIntoAssumes) {
+ cmd = AssertTurnedIntoAssume(assrt);
+ }
+#endif
+ } else if (assm != null) {
+ if (IsFalse(assm.Expr))
+ assumeFalse = true;
+ } else if (call != null) {
+ foreach (Ensures e in (cce.NonNull(call.Proc)).Ensures) {
+ Contract.Assert(e != null);
+ if (IsFalse(e.Condition))
+ assumeFalse = true;
+ }
+ }
+
+ if (assumeFalse) {
+ CheckUnreachable(cur, seq);
+ return;
+ }
+
+ seq.Add(cmd);
+ }
+
+
+ GotoCmd go = cur.TransferCmd as GotoCmd;
+ ReturnCmd ret = cur.TransferCmd as ReturnCmd;
+
+ Contract.Assume(!(go != null && go.labelTargets == null && go.labelNames != null && go.labelNames.Count > 0));
+
+ if (ret != null || (go != null && cce.NonNull(go.labelTargets).Count == 0)) {
+ // we end in return, so there will be no more places to check
+ CheckUnreachable(cur, seq);
+ } else if (go != null) {
+ bool needToCheck = true;
+ // if all of our children have more than one parent, then
+ // we're in the right place to check
+ foreach (Block target in cce.NonNull(go.labelTargets)) {
+ Contract.Assert(target != null);
+ if (target.Predecessors.Count == 1) {
+ needToCheck = false;
+ }
+ }
+ if (needToCheck) {
+ CheckUnreachable(cur, seq);
+ }
+ foreach (Block target in go.labelTargets) {
+ Contract.Assert(target != null);
+ DFS(target);
+ }
+ }
+ }
+
+ class ErrorHandler : ProverInterface.ErrorHandler {
+ Dictionary<int, Absy> label2Absy;
+ VerifierCallback callback;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(label2Absy != null);
+ Contract.Invariant(callback != null);
+ }
+
+
+ public ErrorHandler(Dictionary<int, Absy> label2Absy, VerifierCallback callback) {
+ Contract.Requires(label2Absy != null);
+ Contract.Requires(callback != null);
+ this.label2Absy = label2Absy;
+ this.callback = callback;
+ }
+
+ public override Absy Label2Absy(string label) {
+ //Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ int id = int.Parse(label);
+ return cce.NonNull((Absy)label2Absy[id]);
+ }
+
+ public override void OnProverWarning(string msg) {
+ //Contract.Requires(msg != null);
+ this.callback.OnWarning(msg);
+ }
+ }
+ }
+
+
+ #endregion
+
+ #region Splitter
+ class Split {
+ class BlockStats {
+ public bool big_block;
+ public int id;
+ public double assertion_cost;
+ public double assumption_cost; // before multiplier
+ public double incomming_paths;
+ public List<Block>/*!>!*/ virtual_successors = new List<Block>();
+ public List<Block>/*!>!*/ virtual_predecesors = new List<Block>();
+ public HashSet<Block> reachable_blocks;
+ public readonly Block block;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(virtual_successors));
+ Contract.Invariant(cce.NonNullElements(virtual_predecesors));
+ Contract.Invariant(block != null);
+ }
+
+
+ public BlockStats(Block b, int i) {
+ Contract.Requires(b != null);
+ block = b;
+ assertion_cost = -1;
+ id = i;
+ }
+ }
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(blocks));
+ Contract.Invariant(cce.NonNullElements(big_blocks));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(stats));
+ Contract.Invariant(cce.NonNullElements(assumized_branches));
+ Contract.Invariant(gotoCmdOrigins != null);
+ Contract.Invariant(parent != null);
+ Contract.Invariant(impl != null);
+ Contract.Invariant(copies != null);
+ Contract.Invariant(cce.NonNull(protected_from_assert_to_assume));
+ Contract.Invariant(cce.NonNull(keep_at_all));
+ }
+
+
+ readonly List<Block> blocks;
+ readonly List<Block> big_blocks = new List<Block>();
+ readonly Dictionary<Block/*!*/, BlockStats/*!*/>/*!*/ stats = new Dictionary<Block/*!*/, BlockStats/*!*/>();
+ readonly int id;
+ static int current_id = -1;
+ Block split_block;
+ bool assert_to_assume;
+ List<Block/*!*/>/*!*/ assumized_branches = new List<Block/*!*/>();
+
+ double score;
+ bool score_computed;
+ double total_cost;
+ int assertion_count;
+ double assertion_cost; // without multiplication by paths
+ Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins;
+ readonly public VCGen/*!*/ parent;
+ Implementation/*!*/ impl;
+
+ Dictionary<Block/*!*/, Block/*!*/>/*!*/ copies = new Dictionary<Block/*!*/, Block/*!*/>();
+ bool doing_slice;
+ double slice_initial_limit;
+ double slice_limit;
+ bool slice_pos;
+ HashSet<Block/*!*/>/*!*/ protected_from_assert_to_assume = new HashSet<Block/*!*/>();
+ HashSet<Block/*!*/>/*!*/ keep_at_all = new HashSet<Block/*!*/>();
+
+ // async interface
+ private Checker checker;
+ private int splitNo;
+ internal ErrorReporter reporter;
+
+ public Split(List<Block/*!*/>/*!*/ blocks, Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins, VCGen/*!*/ par, Implementation/*!*/ impl) {
+ Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Requires(gotoCmdOrigins != null);
+ Contract.Requires(par != null);
+ Contract.Requires(impl != null);
+ this.blocks = blocks;
+ this.gotoCmdOrigins = gotoCmdOrigins;
+ this.parent = par;
+ this.impl = impl;
+ this.id = Interlocked.Increment(ref current_id);
+ }
+
+ public double Cost {
+ get {
+ ComputeBestSplit();
+ return total_cost;
+ }
+ }
+
+ public bool LastChance {
+ get {
+ ComputeBestSplit();
+ return assertion_count == 1 && score < 0;
+ }
+ }
+
+ public string Stats {
+ get {
+ ComputeBestSplit();
+ return string.Format("(cost:{0:0}/{1:0}{2})", total_cost, assertion_cost, LastChance ? " last" : "");
+ }
+ }
+
+ public void DumpDot(int no) {
+ using (System.IO.StreamWriter sw = System.IO.File.CreateText(string.Format("split.{0}.dot", no))) {
+ sw.WriteLine("digraph G {");
+
+ ComputeBestSplit();
+ List<Block> saved = assumized_branches;
+ Contract.Assert(saved != null);
+ assumized_branches = new List<Block>();
+ DoComputeScore(false);
+ assumized_branches = saved;
+
+ foreach (Block b in big_blocks) {
+ Contract.Assert(b != null);
+ BlockStats s = GetBlockStats(b);
+ foreach (Block t in s.virtual_successors) {
+ Contract.Assert(t != null);
+ sw.WriteLine("n{0} -> n{1};", s.id, GetBlockStats(t).id);
+ }
+ sw.WriteLine("n{0} [label=\"{1}:\\n({2:0.0}+{3:0.0})*{4:0.0}\"{5}];",
+ s.id, b.Label,
+ s.assertion_cost, s.assumption_cost, s.incomming_paths,
+ s.assertion_cost > 0 ? ",shape=box" : "");
+
+ }
+ sw.WriteLine("}");
+ sw.Close();
+ }
+
+ string filename = string.Format("split.{0}.bpl", no);
+ using (System.IO.StreamWriter sw = System.IO.File.CreateText(filename)) {
+ int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured;
+ CommandLineOptions.Clo.PrintUnstructured = 2; // print only the unstructured program
+ bool oldPrintDesugaringSetting = CommandLineOptions.Clo.PrintDesugarings;
+ CommandLineOptions.Clo.PrintDesugarings = false;
+ List<Block> backup = impl.Blocks;
+ Contract.Assert(backup != null);
+ impl.Blocks = blocks;
+ impl.Emit(new TokenTextWriter(filename, sw, /*setTokens=*/ false, /*pretty=*/ false), 0);
+ impl.Blocks = backup;
+ CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaringSetting;
+ CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured;
+ }
+ }
+
+ int bsid;
+ BlockStats GetBlockStats(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<BlockStats>() != null);
+
+ BlockStats s;
+ if (!stats.TryGetValue(b, out s)) {
+ s = new BlockStats(b, bsid++);
+ stats[b] = s;
+ }
+ return cce.NonNull(s);
+ }
+
+ double AssertionCost(PredicateCmd c) {
+ return 1.0;
+ }
+
+ void CountAssertions(Block b) {
+ Contract.Requires(b != null);
+ BlockStats s = GetBlockStats(b);
+ if (s.assertion_cost >= 0)
+ return; // already done
+ s.big_block = true;
+ s.assertion_cost = 0;
+ s.assumption_cost = 0;
+ foreach (Cmd c in b.Cmds) {
+ if (c is AssertCmd) {
+ double cost = AssertionCost((AssertCmd)c);
+ s.assertion_cost += cost;
+ assertion_count++;
+ assertion_cost += cost;
+ } else if (c is AssumeCmd) {
+ s.assumption_cost += AssertionCost((AssumeCmd)c);
+ }
+ }
+ foreach (Block c in Exits(b)) {
+ Contract.Assert(c != null);
+ s.virtual_successors.Add(c);
+ }
+ if (s.virtual_successors.Count == 1) {
+ Block next = s.virtual_successors[0];
+ BlockStats se = GetBlockStats(next);
+ CountAssertions(next);
+ if (next.Predecessors.Count > 1 || se.virtual_successors.Count != 1)
+ return;
+ s.virtual_successors[0] = se.virtual_successors[0];
+ s.assertion_cost += se.assertion_cost;
+ s.assumption_cost += se.assumption_cost;
+ se.big_block = false;
+ }
+ }
+
+ HashSet<Block/*!*/>/*!*/ ComputeReachableNodes(Block/*!*/ b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(cce.NonNull(Contract.Result<HashSet<Block/*!*/>>()));
+ BlockStats s = GetBlockStats(b);
+ if (s.reachable_blocks != null) {
+ return s.reachable_blocks;
+ }
+ HashSet<Block/*!*/> blocks = new HashSet<Block/*!*/>();
+ s.reachable_blocks = blocks;
+ blocks.Add(b);
+ foreach (Block/*!*/ succ in Exits(b)) {
+ Contract.Assert(succ != null);
+ foreach (Block r in ComputeReachableNodes(succ)) {
+ Contract.Assert(r != null);
+ blocks.Add(r);
+ }
+ }
+ return blocks;
+ }
+
+ double ProverCost(double vc_cost) {
+ return vc_cost * vc_cost;
+ }
+
+ void ComputeBestSplit() {
+ if (score_computed)
+ return;
+ score_computed = true;
+
+ assertion_count = 0;
+
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ CountAssertions(b);
+ }
+
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ BlockStats bs = GetBlockStats(b);
+ if (bs.big_block) {
+ big_blocks.Add(b);
+ foreach (Block ch in bs.virtual_successors) {
+ Contract.Assert(ch != null);
+ BlockStats chs = GetBlockStats(ch);
+ if (!chs.big_block) {
+ Console.WriteLine("non-big {0} accessed from {1}", ch, b);
+ DumpDot(-1);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ chs.virtual_predecesors.Add(b);
+ }
+ }
+ }
+
+ assumized_branches.Clear();
+ total_cost = ProverCost(DoComputeScore(false));
+
+ score = double.PositiveInfinity;
+ Block best_split = null;
+ List<Block> saved_branches = new List<Block>();
+
+ foreach (Block b in big_blocks) {
+ Contract.Assert(b != null);
+ GotoCmd gt = b.TransferCmd as GotoCmd;
+ if (gt == null)
+ continue;
+ List<Block> targ = cce.NonNull(gt.labelTargets);
+ if (targ.Count < 2)
+ continue;
+ // caution, we only consider two first exits
+
+ double left0, right0, left1, right1;
+ split_block = b;
+
+ assumized_branches.Clear();
+ assumized_branches.Add(cce.NonNull(targ[0]));
+ left0 = DoComputeScore(true);
+ right0 = DoComputeScore(false);
+
+ assumized_branches.Clear();
+ for (int idx = 1; idx < targ.Count; idx++) {
+ assumized_branches.Add(cce.NonNull(targ[idx]));
+ }
+ left1 = DoComputeScore(true);
+ right1 = DoComputeScore(false);
+
+ double current_score = ProverCost(left1) + ProverCost(right1);
+ double other_score = ProverCost(left0) + ProverCost(right0);
+
+ if (other_score < current_score) {
+ current_score = other_score;
+ assumized_branches.Clear();
+ assumized_branches.Add(cce.NonNull(targ[0]));
+ }
+
+ if (current_score < score) {
+ score = current_score;
+ best_split = split_block;
+ saved_branches.Clear();
+ saved_branches.AddRange(assumized_branches);
+ }
+ }
+
+ if (CommandLineOptions.Clo.VcsPathSplitMult * score > total_cost) {
+ split_block = null;
+ score = -1;
+ } else {
+ assumized_branches = saved_branches;
+ split_block = best_split;
+ }
+ }
+
+ void UpdateIncommingPaths(BlockStats s) {
+ Contract.Requires(s != null);
+ if (s.incomming_paths < 0.0) {
+ int count = 0;
+ s.incomming_paths = 0.0;
+ if (!keep_at_all.Contains(s.block))
+ return;
+ foreach (Block b in s.virtual_predecesors) {
+ Contract.Assert(b != null);
+ BlockStats ch = GetBlockStats(b);
+ Contract.Assert(ch != null);
+ UpdateIncommingPaths(ch);
+ if (ch.incomming_paths > 0.0) {
+ s.incomming_paths += ch.incomming_paths;
+ count++;
+ }
+ }
+ if (count > 1) {
+ s.incomming_paths *= CommandLineOptions.Clo.VcsPathJoinMult;
+ }
+ }
+ }
+
+ void ComputeBlockSetsHelper(Block b, bool allow_small) {
+ Contract.Requires(b != null);
+ if (keep_at_all.Contains(b))
+ return;
+ keep_at_all.Add(b);
+
+ if (allow_small) {
+ foreach (Block ch in Exits(b)) {
+ Contract.Assert(ch != null);
+ if (b == split_block && assumized_branches.Contains(ch))
+ continue;
+ ComputeBlockSetsHelper(ch, allow_small);
+ }
+ } else {
+ foreach (Block ch in GetBlockStats(b).virtual_successors) {
+ Contract.Assert(ch != null);
+ if (b == split_block && assumized_branches.Contains(ch))
+ continue;
+ ComputeBlockSetsHelper(ch, allow_small);
+ }
+ }
+ }
+
+ void ComputeBlockSets(bool allow_small) {
+ protected_from_assert_to_assume.Clear();
+ keep_at_all.Clear();
+
+ Debug.Assert(split_block == null || GetBlockStats(split_block).big_block);
+ Debug.Assert(GetBlockStats(blocks[0]).big_block);
+
+ if (assert_to_assume) {
+ foreach (Block b in allow_small ? blocks : big_blocks) {
+ Contract.Assert(b != null);
+ if (ComputeReachableNodes(b).Contains(cce.NonNull(split_block))) {
+ keep_at_all.Add(b);
+ }
+ }
+
+ foreach (Block b in assumized_branches) {
+ Contract.Assert(b != null);
+ foreach (Block r in ComputeReachableNodes(b)) {
+ Contract.Assert(r != null);
+ if (allow_small || GetBlockStats(r).big_block) {
+ keep_at_all.Add(r);
+ protected_from_assert_to_assume.Add(r);
+ }
+ }
+ }
+ } else {
+ ComputeBlockSetsHelper(blocks[0], allow_small);
+ }
+ }
+
+ bool ShouldAssumize(Block b) {
+ Contract.Requires(b != null);
+ return assert_to_assume && !protected_from_assert_to_assume.Contains(b);
+ }
+
+ double DoComputeScore(bool aa) {
+ assert_to_assume = aa;
+ ComputeBlockSets(false);
+
+ foreach (Block b in big_blocks) {
+ Contract.Assert(b != null);
+ GetBlockStats(b).incomming_paths = -1.0;
+ }
+
+ GetBlockStats(blocks[0]).incomming_paths = 1.0;
+
+ double cost = 0.0;
+ foreach (Block b in big_blocks) {
+ Contract.Assert(b != null);
+ if (keep_at_all.Contains(b)) {
+ BlockStats s = GetBlockStats(b);
+ UpdateIncommingPaths(s);
+ double local = s.assertion_cost;
+ if (ShouldAssumize(b)) {
+ local = (s.assertion_cost + s.assumption_cost) * CommandLineOptions.Clo.VcsAssumeMult;
+ } else {
+ local = s.assumption_cost * CommandLineOptions.Clo.VcsAssumeMult + s.assertion_cost;
+ }
+ local = local + local * s.incomming_paths * CommandLineOptions.Clo.VcsPathCostMult;
+ cost += local;
+ }
+ }
+
+ return cost;
+ }
+
+ List<Cmd> SliceCmds(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<List<Cmd>>() != null);
+
+ List<Cmd> seq = b.Cmds;
+ Contract.Assert(seq != null);
+ if (!doing_slice && !ShouldAssumize(b))
+ return seq;
+ List<Cmd> res = new List<Cmd>();
+ foreach (Cmd c in seq) {
+ Contract.Assert(c != null);
+ AssertCmd a = c as AssertCmd;
+ Cmd the_new = c;
+ bool swap = false;
+ if (a != null) {
+ if (doing_slice) {
+ double cost = AssertionCost(a);
+ bool first = (slice_limit - cost) >= 0 || slice_initial_limit == slice_limit;
+ slice_limit -= cost;
+ swap = slice_pos == first;
+ } else if (assert_to_assume) {
+ swap = true;
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ if (swap) {
+ the_new = AssertTurnedIntoAssume(a);
+ }
+ }
+ res.Add(the_new);
+ }
+ return res;
+ }
+
+ Block CloneBlock(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<Block>() != null);
+
+ Block res;
+ if (copies.TryGetValue(b, out res)) {
+ return cce.NonNull(res);
+ }
+ res = new Block(b.tok, b.Label, SliceCmds(b), b.TransferCmd);
+ GotoCmd gt = b.TransferCmd as GotoCmd;
+ copies[b] = res;
+ if (gt != null) {
+ GotoCmd newGoto = new GotoCmd(gt.tok, new List<String>(), new List<Block>());
+ res.TransferCmd = newGoto;
+ int pos = 0;
+ foreach (Block ch in cce.NonNull(gt.labelTargets)) {
+ Contract.Assert(ch != null);
+ Contract.Assert(doing_slice ||
+ (assert_to_assume || (keep_at_all.Contains(ch) || assumized_branches.Contains(ch))));
+ if (doing_slice ||
+ ((b != split_block || assumized_branches.Contains(ch) == assert_to_assume) &&
+ keep_at_all.Contains(ch))) {
+ newGoto.AddTarget(CloneBlock(ch));
+ }
+ pos++;
+ }
+ }
+ return res;
+ }
+
+ Split DoSplit() {
+ Contract.Ensures(Contract.Result<Split>() != null);
+
+ copies.Clear();
+ CloneBlock(blocks[0]);
+ List<Block> newBlocks = new List<Block>();
+ Dictionary<TransferCmd, ReturnCmd> newGotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>();
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ Block tmp;
+ if (copies.TryGetValue(b, out tmp)) {
+ newBlocks.Add(cce.NonNull(tmp));
+ if (gotoCmdOrigins.ContainsKey(b.TransferCmd)) {
+ newGotoCmdOrigins[tmp.TransferCmd] = gotoCmdOrigins[b.TransferCmd];
+ }
+
+ foreach (Block p in b.Predecessors) {
+ Contract.Assert(p != null);
+ Block tmp2;
+ if (copies.TryGetValue(p, out tmp2)) {
+ tmp.Predecessors.Add(tmp2);
+ }
+ }
+ }
+ }
+
+ return new Split(newBlocks, newGotoCmdOrigins, parent, impl);
+ }
+
+ Split SplitAt(int idx) {
+ Contract.Ensures(Contract.Result<Split>() != null);
+
+ assert_to_assume = idx == 0;
+ doing_slice = false;
+ ComputeBlockSets(true);
+
+ return DoSplit();
+ }
+
+ Split SliceAsserts(double limit, bool pos) {
+ Contract.Ensures(Contract.Result<Split>() != null);
+
+ slice_pos = pos;
+ slice_limit = limit;
+ slice_initial_limit = limit;
+ doing_slice = true;
+ Split r = DoSplit();
+ /*
+ Console.WriteLine("split {0} / {1} -->", limit, pos);
+ List<Block!> tmp = impl.Blocks;
+ impl.Blocks = r.blocks;
+ EmitImpl(impl, false);
+ impl.Blocks = tmp;
+ */
+
+ return r;
+ }
+
+ void Print() {
+ List<Block> tmp = impl.Blocks;
+ Contract.Assert(tmp != null);
+ impl.Blocks = blocks;
+ EmitImpl(impl, false);
+ impl.Blocks = tmp;
+ }
+
+ public Counterexample ToCounterexample(ProverContext context) {
+ Contract.Requires(context != null);
+ Contract.Ensures(Contract.Result<Counterexample>() != null);
+
+ List<Block> trace = new List<Block>();
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ trace.Add(b);
+ }
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ foreach (Cmd c in b.Cmds) {
+ Contract.Assert(c != null);
+ if (c is AssertCmd) {
+ return AssertCmdToCounterexample((AssertCmd)c, cce.NonNull(b.TransferCmd), trace, null, null, context);
+ }
+ }
+ }
+ Contract.Assume(false);
+ throw new cce.UnreachableException();
+ }
+
+ /// <summary>
+ /// Starting from the 0-index "split_here" annotation in begin, verifies until it reaches a subsequent "split_here" annotation
+ /// Returns a list of blocks where all code not verified has asserts converted into assumes
+ /// </summary>
+ /// <param name="blocks">Implementation's collection of blocks</param>
+ /// <param name="begin">Block containing the first split_here from which to start verifying</param>
+ /// <param name="begin_split_id">0-based ID of the "split_here" annotation within begin at which to start verifying</param>
+ /// <param name="blockInternalSplit">True if the entire split is contained within block begin</param>
+ /// <param name="endPoints">Set of all blocks containing a "split_here" annotation</param>
+ /// <returns></returns>
+ // Note: Current implementation may over report errors.
+ // For example, if the control flow graph is a diamond (e.g., A -> B, C, B->D, C->D),
+ // and there is a split in B and an error in D, then D will be verified twice and hence report the error twice.
+ // Best solution may be to memoize blocks that have been fully verified and be sure not to verify them again
+ private static List<Block> DoManualSplit(List<Block> blocks, Block begin, int begin_split_id, bool blockInternalSplit, IEnumerable<Block> endPoints) {
+ // Compute the set of blocks reachable from begin but not included in endPoints. These will be verified in their entirety.
+ var blocksToVerifyEntirely = new HashSet<Block>();
+ var reachableEndPoints = new HashSet<Block>(); // Reachable end points will be verified up to their first split point
+ var todo = new Stack<Block>();
+ todo.Push(begin);
+ while (todo.Count > 0) {
+ var currentBlock = todo.Pop();
+ if (blocksToVerifyEntirely.Contains(currentBlock)) continue;
+ blocksToVerifyEntirely.Add(currentBlock);
+ var exit = currentBlock.TransferCmd as GotoCmd;
+ if (exit != null)
+ foreach (Block targetBlock in exit.labelTargets) {
+ if (!endPoints.Contains(targetBlock)) {
+ todo.Push(targetBlock);
+ } else {
+ reachableEndPoints.Add(targetBlock);
+ }
+ }
+
+ }
+ blocksToVerifyEntirely.Remove(begin);
+
+ // Convert assumes to asserts in "unreachable" blocks, including portions of blocks containing "split_here"
+ var newBlocks = new List<Block>(blocks.Count()); // Copies of the original blocks
+ var duplicator = new Duplicator();
+ var oldToNewBlockMap = new Dictionary<Block, Block>(blocks.Count()); // Maps original blocks to their new copies in newBlocks
+
+ foreach (var currentBlock in blocks) {
+ var newBlock = (Block)duplicator.VisitBlock(currentBlock);
+ oldToNewBlockMap[currentBlock] = newBlock;
+ newBlocks.Add(newBlock);
+
+ if (!blockInternalSplit && blocksToVerifyEntirely.Contains(currentBlock)) continue; // All reachable blocks must be checked in their entirety, so don't change anything
+ // Otherwise, we only verify a portion of the current block, so we'll need to look at each of its commands
+
+ // !verify -> convert assert to assume
+ var verify = (currentBlock == begin && begin_split_id == -1) // -1 tells us to start verifying from the very beginning (i.e., there is no split in the begin block)
+ || (reachableEndPoints.Contains(currentBlock) // This endpoint is reachable from begin, so we verify until we hit the first split point
+ && !blockInternalSplit); // Don't bother verifying if all of the splitting is within the begin block
+ var newCmds = new List<Cmd>();
+ var split_here_count = 0;
+
+ foreach (Cmd c in currentBlock.Cmds) {
+ var p = c as PredicateCmd;
+ if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "split_here")) {
+ if (currentBlock == begin) { // Verify everything between the begin_split_id we were given and the next split
+ if (split_here_count == begin_split_id) {
+ verify = true;
+ } else if (split_here_count == begin_split_id + 1) {
+ verify = false;
+ }
+ } else { // We're in an endPoint so we stop verifying as soon as we hit a "split_here"
+ verify = false;
+ }
+ split_here_count++;
+ }
+
+ var asrt = c as AssertCmd;
+ if (verify || asrt == null)
+ newCmds.Add(c);
+ else
+ newCmds.Add(AssertTurnedIntoAssume(asrt));
+ }
+
+ newBlock.Cmds = newCmds;
+ }
+
+ // Patch the edges between the new blocks
+ foreach (var oldBlock in blocks) {
+ if (oldBlock.TransferCmd is ReturnCmd) { continue; }
+ var gotoCmd = (GotoCmd)oldBlock.TransferCmd;
+ var newLabelTargets = new List<Block>(gotoCmd.labelTargets.Count());
+ var newLabelNames = new List<string>(gotoCmd.labelTargets.Count());
+ foreach (var target in gotoCmd.labelTargets) {
+ newLabelTargets.Add(oldToNewBlockMap[target]);
+ newLabelNames.Add(oldToNewBlockMap[target].Label);
+ }
+ oldToNewBlockMap[oldBlock].TransferCmd = new GotoCmd(gotoCmd.tok, newLabelNames, newLabelTargets);
+ }
+
+ return newBlocks;
+ }
+
+ public static List<Split/*!*/> FindManualSplits(Implementation/*!*/ impl, Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins, VCGen/*!*/ par) {
+ Contract.Requires(impl != null);
+ Contract.Ensures(Contract.Result<List<Split>>() == null || cce.NonNullElements(Contract.Result<List<Split>>()));
+
+ var splitPoints = new Dictionary<Block,int>();
+ foreach (var b in impl.Blocks) {
+ foreach (Cmd c in b.Cmds) {
+ var p = c as PredicateCmd;
+ if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "split_here")) {
+ int count;
+ splitPoints.TryGetValue(b, out count);
+ splitPoints[b] = count + 1;
+ }
+ }
+ }
+
+ if (splitPoints.Count() == 0) { // No manual split points here
+ return null;
+ }
+
+ List<Split> splits = new List<Split>();
+ Block entryPoint = impl.Blocks[0];
+ var newEntryBlocks = DoManualSplit(impl.Blocks, entryPoint, -1, splitPoints.Keys.Contains(entryPoint), splitPoints.Keys);
+ splits.Add(new Split(newEntryBlocks, gotoCmdOrigins, par, impl)); // REVIEW: Does gotoCmdOrigins need to be changed at all?
+
+ foreach (KeyValuePair<Block,int> pair in splitPoints) {
+ for (int i = 0; i < pair.Value; i++) {
+ bool blockInternalSplit = i < pair.Value - 1; // There's at least one more split, after this one, in the current block
+ var newBlocks = DoManualSplit(impl.Blocks, pair.Key, i, blockInternalSplit, splitPoints.Keys);
+ Split s = new Split(newBlocks, gotoCmdOrigins, par, impl); // REVIEW: Does gotoCmdOrigins need to be changed at all?
+ splits.Add(s);
+ }
+ }
+
+ return splits;
+ }
+
+ public static List<Split/*!*/>/*!*/ DoSplit(Split initial, double max_cost, int max) {
+ Contract.Requires(initial != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Split>>()));
+
+ List<Split> res = new List<Split>();
+ res.Add(initial);
+
+ while (res.Count < max) {
+ Split best = null;
+ int best_idx = 0, pos = 0;
+ foreach (Split s in res) {
+ Contract.Assert(s != null);
+ s.ComputeBestSplit(); // TODO check total_cost first
+ if (s.total_cost > max_cost &&
+ (best == null || best.total_cost < s.total_cost) &&
+ (s.assertion_count > 1 || s.split_block != null)) {
+ best = s;
+ best_idx = pos;
+ }
+ pos++;
+ }
+
+ if (best == null)
+ break; // no split found
+
+ Split s0, s1;
+
+ bool split_stats = CommandLineOptions.Clo.TraceVerify;
+
+ if (split_stats) {
+ Console.WriteLine("{0} {1} -->", best.split_block == null ? "SLICE" : ("SPLIT@" + best.split_block.Label), best.Stats);
+ if (best.split_block != null) {
+ GotoCmd g = best.split_block.TransferCmd as GotoCmd;
+ if (g != null) {
+ Console.Write(" exits: ");
+ foreach (Block b in cce.NonNull(g.labelTargets)) {
+ Contract.Assert(b != null);
+ Console.Write("{0} ", b.Label);
+ }
+ Console.WriteLine("");
+ Console.Write(" assumized: ");
+ foreach (Block b in best.assumized_branches) {
+ Contract.Assert(b != null);
+ Console.Write("{0} ", b.Label);
+ }
+ Console.WriteLine("");
+ }
+ }
+ }
+
+ if (best.split_block != null) {
+ s0 = best.SplitAt(0);
+ s1 = best.SplitAt(1);
+ } else {
+ best.split_block = null;
+ s0 = best.SliceAsserts(best.assertion_cost / 2, true);
+ s1 = best.SliceAsserts(best.assertion_cost / 2, false);
+ }
+
+ if (true) {
+ List<Block> ss = new List<Block>();
+ ss.Add(s0.blocks[0]);
+ ss.Add(s1.blocks[0]);
+ try {
+ best.SoundnessCheck(new HashSet<List<Block>>(new BlockListComparer()), best.blocks[0], ss);
+ } catch (System.Exception e) {
+ Console.WriteLine(e);
+ best.DumpDot(-1);
+ s0.DumpDot(-2);
+ s1.DumpDot(-3);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ if (split_stats) {
+ s0.ComputeBestSplit();
+ s1.ComputeBestSplit();
+ Console.WriteLine(" --> {0}", s0.Stats);
+ Console.WriteLine(" --> {0}", s1.Stats);
+ }
+
+ if (CommandLineOptions.Clo.TraceVerify) {
+ best.Print();
+ }
+
+ res[best_idx] = s0;
+ res.Add(s1);
+ }
+
+ return res;
+ }
+
+ class BlockListComparer : IEqualityComparer<List<Block>>
+ {
+ public bool Equals(List<Block> x, List<Block> y)
+ {
+ return x == y || x.SequenceEqual(y);
+ }
+
+ public int GetHashCode(List<Block> obj)
+ {
+ int h = 0;
+ Contract.Assume(obj != null);
+ foreach (var b in obj)
+ {
+ if (b != null)
+ {
+ h += b.GetHashCode();
+ }
+ }
+ return h;
+ }
+ }
+
+ public Checker Checker {
+ get {
+ Contract.Ensures(Contract.Result<Checker>() != null);
+
+ Contract.Assert(checker != null);
+ return checker;
+ }
+ }
+
+ public Task ProverTask {
+ get {
+ Contract.Assert(checker != null);
+ return checker.ProverTask;
+ }
+ }
+
+ public void ReadOutcome(ref Outcome cur_outcome, out bool prover_failed) {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+ ProverInterface.Outcome outcome = cce.NonNull(checker).ReadOutcome();
+
+ if (CommandLineOptions.Clo.Trace && splitNo >= 0) {
+ System.Console.WriteLine(" --> split #{0} done, [{1} s] {2}", splitNo, checker.ProverRunTime.TotalSeconds, outcome);
+ }
+
+ if (CommandLineOptions.Clo.VcsDumpSplits) {
+ DumpDot(splitNo);
+ }
+
+ prover_failed = false;
+
+ switch (outcome) {
+ case ProverInterface.Outcome.Valid:
+ return;
+ case ProverInterface.Outcome.Invalid:
+ cur_outcome = Outcome.Errors;
+ return;
+ case ProverInterface.Outcome.OutOfMemory:
+ prover_failed = true;
+ if (cur_outcome != Outcome.Errors && cur_outcome != Outcome.Inconclusive)
+ cur_outcome = Outcome.OutOfMemory;
+ return;
+ case ProverInterface.Outcome.TimeOut:
+ prover_failed = true;
+ if (cur_outcome != Outcome.Errors && cur_outcome != Outcome.Inconclusive)
+ cur_outcome = Outcome.TimedOut;
+ return;
+ case ProverInterface.Outcome.Undetermined:
+ if (cur_outcome != Outcome.Errors)
+ cur_outcome = Outcome.Inconclusive;
+ return;
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+
+ /// <summary>
+ /// As a side effect, updates "this.parent.CumulativeAssertionCount".
+ /// </summary>
+ public void BeginCheck(Checker checker, VerifierCallback callback, ModelViewInfo mvInfo, int no, int timeout)
+ {
+ Contract.Requires(checker != null);
+ Contract.Requires(callback != null);
+
+ splitNo = no;
+
+ impl.Blocks = blocks;
+
+ this.checker = checker;
+
+ Dictionary<int, Absy> label2absy = new Dictionary<int, Absy>();
+
+ ProverContext ctx = checker.TheoremProver.Context;
+ Boogie2VCExprTranslator bet = ctx.BoogieExprTranslator;
+ CodeExprConversionClosure cc = new CodeExprConversionClosure(label2absy, ctx);
+ bet.SetCodeExprConverter(cc.CodeExprToVerificationCondition);
+
+ var exprGen = ctx.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+
+ VCExpr vc = parent.GenerateVCAux(impl, controlFlowVariableExpr, label2absy, checker.TheoremProver.Context);
+ Contract.Assert(vc != null);
+
+ if (!CommandLineOptions.Clo.UseLabels)
+ {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vc = exprGen.Implies(eqExpr, vc);
+ }
+
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local)
+ {
+ reporter = new ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, parent.incarnationOriginMap, callback, mvInfo, cce.NonNull(this.Checker.TheoremProver.Context), parent.program);
+ }
+ else
+ {
+ reporter = new ErrorReporter(gotoCmdOrigins, label2absy, impl.Blocks, parent.incarnationOriginMap, callback, mvInfo, this.Checker.TheoremProver.Context, parent.program);
+ }
+
+ if (CommandLineOptions.Clo.TraceVerify && no >= 0)
+ {
+ Console.WriteLine("-- after split #{0}", no);
+ Print();
+ }
+
+ string desc = cce.NonNull(impl.Name);
+ if (no >= 0)
+ desc += "_split" + no;
+ checker.BeginCheck(desc, vc, reporter);
+ }
+
+ private void SoundnessCheck(HashSet<List<Block>/*!*/>/*!*/ cache, Block/*!*/ orig, List<Block/*!*/>/*!*/ copies) {
+ Contract.Requires(cce.NonNull(cache));
+ Contract.Requires(orig != null);
+ Contract.Requires(copies != null);
+ {
+ var t = new List<Block> { orig };
+ foreach (Block b in copies) {
+ Contract.Assert(b != null);
+ t.Add(b);
+ }
+ if (cache.Contains(t)) {
+ return;
+ }
+ cache.Add(t);
+ }
+
+ for (int i = 0; i < orig.Cmds.Count; ++i) {
+ Cmd cmd = orig.Cmds[i];
+ if (cmd is AssertCmd) {
+ int found = 0;
+ foreach (Block c in copies) {
+ Contract.Assert(c != null);
+ if (c.Cmds[i] == cmd) {
+ found++;
+ }
+ }
+ if (found == 0) {
+ throw new System.Exception(string.Format("missing assertion: {0}({1})", cmd.tok.filename, cmd.tok.line));
+ }
+ }
+ }
+
+ foreach (Block exit in Exits(orig)) {
+ Contract.Assert(exit != null);
+ List<Block> newcopies = new List<Block>();
+ foreach (Block c in copies) {
+ foreach (Block cexit in Exits(c)) {
+ Contract.Assert(cexit != null);
+ if (cexit.Label == exit.Label) {
+ newcopies.Add(cexit);
+ }
+ }
+ }
+ if (newcopies.Count == 0) {
+ throw new System.Exception("missing exit " + exit.Label);
+ }
+ SoundnessCheck(cache, exit, newcopies);
+ }
+ }
+ }
+ #endregion
+
+
+ public class CodeExprConversionClosure
+ {
+ Dictionary<int, Absy> label2absy;
+ ProverContext ctx;
+ public CodeExprConversionClosure(Dictionary<int, Absy> label2absy, ProverContext ctx)
+ {
+ this.label2absy = label2absy;
+ this.ctx = ctx;
+ }
+
+ public VCExpr CodeExprToVerificationCondition(CodeExpr codeExpr, Hashtable blockVariables, List<VCExprLetBinding> bindings, bool isPositiveContext)
+ {
+ VCGen vcgen = new VCGen(new Program(), null, false, new List<Checker>());
+ vcgen.variable2SequenceNumber = new Dictionary<Variable, int>();
+ vcgen.incarnationOriginMap = new Dictionary<Incarnation, Absy>();
+ vcgen.CurrentLocalVariables = codeExpr.LocVars;
+
+ ResetPredecessors(codeExpr.Blocks);
+ vcgen.AddBlocksBetween(codeExpr.Blocks);
+ Dictionary<Variable, Expr> gotoCmdOrigins = vcgen.ConvertBlocks2PassiveCmd(codeExpr.Blocks, new List<IdentifierExpr>(), new ModelViewInfo(codeExpr));
+ int ac; // computed, but then ignored for this CodeExpr
+ VCExpr startCorrect = VCGen.LetVCIterative(codeExpr.Blocks, null, label2absy, ctx, out ac, isPositiveContext);
+ VCExpr vce = ctx.ExprGen.Let(bindings, startCorrect);
+ if (vcgen.CurrentLocalVariables.Count != 0)
+ {
+ Boogie2VCExprTranslator translator = ctx.BoogieExprTranslator;
+ List<VCExprVar> boundVars = new List<VCExprVar>();
+ foreach (Variable v in vcgen.CurrentLocalVariables)
+ {
+ Contract.Assert(v != null);
+ VCExprVar ev = translator.LookupVariable(v);
+ Contract.Assert(ev != null);
+ boundVars.Add(ev);
+ if (v.TypedIdent.Type.Equals(Bpl.Type.Bool))
+ {
+ // add an antecedent (tickleBool ev) to help the prover find a possible trigger
+ vce = ctx.ExprGen.Implies(ctx.ExprGen.Function(VCExpressionGenerator.TickleBoolOp, ev), vce);
+ }
+ }
+ vce = ctx.ExprGen.Forall(boundVars, new List<VCTrigger>(), vce);
+ }
+ if (isPositiveContext)
+ {
+ vce = ctx.ExprGen.Not(vce);
+ }
+ return vce;
+ }
+ }
+
+ public VCExpr GenerateVC(Implementation/*!*/ impl, VCExpr controlFlowVariableExpr, out Dictionary<int, Absy>/*!*/ label2absy, ProverContext proverContext, IList<VCExprVar> namedAssumeVars = null)
+ {
+ Contract.Requires(impl != null);
+ Contract.Requires(proverContext != null);
+ Contract.Ensures(Contract.ValueAtReturn(out label2absy) != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ label2absy = new Dictionary<int, Absy>();
+ return GenerateVCAux(impl, controlFlowVariableExpr, label2absy, proverContext, namedAssumeVars: namedAssumeVars);
+ }
+
+ public VCExpr GenerateVCAux(Implementation/*!*/ impl, VCExpr controlFlowVariableExpr, Dictionary<int, Absy>/*!*/ label2absy, ProverContext proverContext, IList<VCExprVar> namedAssumeVars = null) {
+ Contract.Requires(impl != null);
+ Contract.Requires(proverContext != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ TypecheckingContext tc = new TypecheckingContext(null);
+ impl.Typecheck(tc);
+
+ VCExpr vc;
+ int assertionCount;
+ switch (CommandLineOptions.Clo.vcVariety) {
+ case CommandLineOptions.VCVariety.Structured:
+ vc = VCViaStructuredProgram(impl, label2absy, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.Block:
+ vc = FlatBlockVC(impl, label2absy, false, false, false, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.BlockReach:
+ vc = FlatBlockVC(impl, label2absy, false, true, false, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.Local:
+ vc = FlatBlockVC(impl, label2absy, true, false, false, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.BlockNested:
+ vc = NestedBlockVC(impl, label2absy, false, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.BlockNestedReach:
+ vc = NestedBlockVC(impl, label2absy, true, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.Dag:
+ if (cce.NonNull(CommandLineOptions.Clo.TheProverFactory).SupportsDags || CommandLineOptions.Clo.FixedPointEngine != null) {
+ vc = DagVC(cce.NonNull(impl.Blocks[0]), controlFlowVariableExpr, label2absy, new Hashtable/*<Block, VCExpr!>*/(), proverContext, out assertionCount);
+ } else {
+ vc = LetVC(cce.NonNull(impl.Blocks[0]), controlFlowVariableExpr, label2absy, proverContext, out assertionCount);
+ }
+ break;
+ case CommandLineOptions.VCVariety.DagIterative:
+ vc = LetVCIterative(impl.Blocks, controlFlowVariableExpr, label2absy, proverContext, out assertionCount);
+ break;
+ case CommandLineOptions.VCVariety.Doomed:
+ vc = FlatBlockVC(impl, label2absy, false, false, true, proverContext, out assertionCount);
+ break;
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // unexpected enumeration value
+ }
+ CumulativeAssertionCount += assertionCount;
+ return vc;
+ }
+
+ void CheckIntAttributeOnImpl(Implementation impl, string name, ref int val) {
+ Contract.Requires(impl != null);
+ Contract.Requires(name != null);
+ if (!(cce.NonNull(impl.Proc).CheckIntAttribute(name, ref val) || !impl.CheckIntAttribute(name, ref val))) {
+ Console.WriteLine("ignoring ill-formed {:{0} ...} attribute on {1}, parameter should be an int", name, impl.Name);
+ }
+ }
+
+ public override Outcome VerifyImplementation(Implementation/*!*/ impl, VerifierCallback/*!*/ callback) {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ if (impl.SkipVerification) {
+ return Outcome.Inconclusive; // not sure about this one
+ }
+
+ callback.OnProgress("VCgen", 0, 0, 0.0);
+
+ Stopwatch watch = new Stopwatch();
+ if (_print_time)
+ {
+ Console.WriteLine("Checking function {0}", impl.Name);
+ watch.Reset();
+ watch.Start();
+ }
+
+ ConvertCFG2DAG(impl);
+
+ SmokeTester smoke_tester = null;
+ if (CommandLineOptions.Clo.SoundnessSmokeTest) {
+ smoke_tester = new SmokeTester(this, impl, callback);
+ smoke_tester.Copy();
+ }
+
+ ModelViewInfo mvInfo;
+ var gotoCmdOrigins = PassifyImpl(impl, out mvInfo);
+
+ // If "expand" attribute is supplied, expand any assertion of conjunctions into multiple assertions, one per conjunct
+ foreach (var b in impl.Blocks)
+ {
+ List<Cmd> newCmds = new List<Cmd>();
+ bool changed = false;
+ foreach (var c in b.Cmds)
+ {
+ var a = c as AssertCmd;
+ var ar = c as AssertRequiresCmd;
+ var ae = c as AssertEnsuresCmd;
+ var ai = c as LoopInitAssertCmd;
+ var am = c as LoopInvMaintainedAssertCmd;
+ // TODO:
+ //use Duplicator and Substituter rather than new
+ //nested IToken?
+ //document expand attribute (search for {:ignore}, for example)
+ //fix up new CallCmd, new Requires, new Ensures in CivlRefinement.cs
+ Func<Expr,Expr,Expr> withType = (Expr from, Expr to) =>
+ {
+ NAryExpr nFrom = from as NAryExpr;
+ NAryExpr nTo = to as NAryExpr;
+ to.Type = from.Type;
+ if (nFrom != null && nTo != null) nTo.TypeParameters = nFrom.TypeParameters;
+ return to;
+ };
+
+ Action<int,Expr,Action<Expr>> traverse = null;
+ traverse = (depth, e, act) =>
+ {
+ ForallExpr forall = e as ForallExpr;
+ NAryExpr nary = e as NAryExpr;
+ if (forall != null)
+ {
+ traverse(depth, forall.Body, e1 => act(withType(forall,
+ new ForallExpr(e1.tok, forall.TypeParameters, forall.Dummies, forall.Attributes, forall.Triggers, e1))));
+ return;
+ }
+ if (nary != null)
+ {
+ var args = nary.Args;
+ IAppliable fun = nary.Fun;
+ BinaryOperator bop = fun as BinaryOperator;
+ FunctionCall call = fun as FunctionCall;
+ if (bop != null)
+ {
+ switch (bop.Op)
+ {
+ case BinaryOperator.Opcode.And:
+ traverse(depth, args[0], act);
+ traverse(depth, args[1], act);
+ return;
+ case BinaryOperator.Opcode.Imp:
+ traverse(depth, args[1], e1 => act(withType(nary,
+ new NAryExpr(e1.tok, fun, new List<Expr>() { args[0], e1 }))));
+ return;
+ }
+ }
+ if (depth > 0 && call != null && call.Func != null)
+ {
+ Function cf = call.Func;
+ Expr body = cf.Body;
+ List<Variable> ins = cf.InParams;
+ if (body == null && cf.DefinitionAxiom != null)
+ {
+ ForallExpr all = cf.DefinitionAxiom.Expr as ForallExpr;
+ if (all != null)
+ {
+ NAryExpr def = all.Body as NAryExpr;
+ if (def != null && def.Fun is BinaryOperator && ((BinaryOperator) (def.Fun)).Op == BinaryOperator.Opcode.Iff)
+ {
+ body = def.Args[1];
+ ins = all.Dummies;
+ }
+ }
+ }
+ if (body != null)
+ {
+ Func<Expr,Expr> new_f = e1 =>
+ {
+ Function f = new Function(cf.tok, "expand<" + cf.Name + ">", cf.TypeParameters, ins, cf.OutParams[0], cf.Comment);
+ f.Body = e1;
+ Token tok = new Token(e1.tok.line, e1.tok.col);
+ tok.filename = e.tok.filename + "(" + e.tok.line + "," + e.tok.col + ") --> " + e1.tok.filename;
+ return withType(nary, new NAryExpr(tok, new FunctionCall(f), args));
+ };
+ traverse(depth - 1, body, e1 => act(new_f(e1)));
+ return;
+ }
+ }
+ }
+ act(e);
+ };
+
+ if (a != null)
+ {
+ var attr = a.Attributes;
+ if (ar != null && ar.Requires.Attributes != null) attr = ar.Requires.Attributes;
+ if (ar != null && ar.Call.Attributes != null) attr = ar.Call.Attributes;
+ if (ae != null && ae.Ensures.Attributes != null) attr = ae.Ensures.Attributes;
+ if (QKeyValue.FindExprAttribute(attr, "expand") != null || QKeyValue.FindBoolAttribute(attr, "expand"))
+ {
+ int depth = QKeyValue.FindIntAttribute(attr, "expand", 100);
+ Func<Expr,Expr> fe = e => Expr.Or(a.Expr, e);
+ //traverse(depth, a.Expr, e => System.Console.WriteLine(e.GetType() + " :: " + e + " @ " + e.tok.line + ", " + e.tok.col));
+ traverse(depth, a.Expr, e =>
+ {
+ AssertCmd new_c =
+ (ar != null) ? new AssertRequiresCmd(ar.Call, new Requires(e.tok, ar.Requires.Free, fe(e), ar.Requires.Comment)) :
+ (ae != null) ? new AssertEnsuresCmd(new Ensures(e.tok, ae.Ensures.Free, fe(e), ae.Ensures.Comment)) :
+ (ai != null) ? new LoopInitAssertCmd(e.tok, fe(e)) :
+ (am != null) ? new LoopInvMaintainedAssertCmd(e.tok, fe(e)) :
+ new AssertCmd(e.tok, fe(e));
+ new_c.Attributes = new QKeyValue(e.tok, "subsumption", new List<object>() { new LiteralExpr(e.tok, BigNum.FromInt(0)) }, a.Attributes);
+ newCmds.Add(new_c);
+ });
+ }
+ newCmds.Add(c);
+ changed = true;
+ }
+ else
+ {
+ newCmds.Add(c);
+ }
+ }
+ if (changed) b.Cmds = newCmds;
+ }
+
+ double max_vc_cost = CommandLineOptions.Clo.VcsMaxCost;
+ int tmp_max_vc_cost = -1, max_splits = CommandLineOptions.Clo.VcsMaxSplits,
+ max_kg_splits = CommandLineOptions.Clo.VcsMaxKeepGoingSplits;
+ CheckIntAttributeOnImpl(impl, "vcs_max_cost", ref tmp_max_vc_cost);
+ CheckIntAttributeOnImpl(impl, "vcs_max_splits", ref max_splits);
+ CheckIntAttributeOnImpl(impl, "vcs_max_keep_going_splits", ref max_kg_splits);
+ if (tmp_max_vc_cost >= 0) {
+ max_vc_cost = tmp_max_vc_cost;
+ }
+
+ Outcome outcome = Outcome.Correct;
+
+ // Report all recycled failing assertions for this implementation.
+ if (impl.RecycledFailingAssertions != null && impl.RecycledFailingAssertions.Any())
+ {
+ outcome = Outcome.Errors;
+ foreach (var a in impl.RecycledFailingAssertions)
+ {
+ var checksum = a.Checksum;
+ var oldCex = impl.ErrorChecksumToCachedError[checksum] as Counterexample;
+ if (oldCex != null) {
+ if (CommandLineOptions.Clo.VerifySnapshots < 3) {
+ callback.OnCounterexample(oldCex, null);
+ } else {
+ // If possible, we use the old counterexample, but with the location information of "a"
+ var cex = AssertCmdToCloneCounterexample(a, oldCex);
+ callback.OnCounterexample(cex, null);
+ // OnCounterexample may have had side effects on the RequestId and OriginalRequestId fields. We make
+ // any such updates available in oldCex. (Is this really a good design? --KRML)
+ oldCex.RequestId = cex.RequestId;
+ oldCex.OriginalRequestId = cex.OriginalRequestId;
+ }
+ }
+ }
+ }
+
+ Cores = CommandLineOptions.Clo.VcsCores;
+ Stack<Split> work = new Stack<Split>();
+ List<Split> currently_running = new List<Split>();
+ ResetPredecessors(impl.Blocks);
+ List<Split> manual_splits = Split.FindManualSplits(impl, gotoCmdOrigins, this);
+ if (manual_splits != null) {
+ foreach (var split in manual_splits) {
+ work.Push(split);
+ }
+ } else {
+ work.Push(new Split(impl.Blocks, gotoCmdOrigins, this, impl));
+ }
+
+ bool keep_going = max_kg_splits > 1;
+ int total = 0;
+ int no = max_splits == 1 && !keep_going ? -1 : 0;
+ bool first_round = true;
+ bool do_splitting = keep_going || max_splits > 1;
+ double remaining_cost = 0.0, proven_cost = 0.0;
+
+ if (do_splitting) {
+ remaining_cost = work.Peek().Cost;
+ }
+
+ while (work.Any() || currently_running.Any())
+ {
+ bool prover_failed = false;
+ Split s = null;
+ var isWaiting = !work.Any();
+
+ if (!isWaiting)
+ {
+ s = work.Peek();
+
+ if (first_round && max_splits > 1)
+ {
+ prover_failed = true;
+ remaining_cost -= s.Cost;
+ }
+ else
+ {
+ var timeout = (keep_going && s.LastChance) ? CommandLineOptions.Clo.VcsFinalAssertTimeout :
+ keep_going ? CommandLineOptions.Clo.VcsKeepGoingTimeout :
+ impl.TimeLimit;
+
+ var checker = s.parent.FindCheckerFor(timeout, false);
+ try
+ {
+ if (checker == null)
+ {
+ isWaiting = true;
+ goto waiting;
+ }
+ else
+ {
+ s = work.Pop();
+ }
+
+ if (CommandLineOptions.Clo.Trace && no >= 0)
+ {
+ System.Console.WriteLine(" checking split {1}/{2}, {3:0.00}%, {0} ...",
+ s.Stats, no + 1, total, 100 * proven_cost / (proven_cost + remaining_cost));
+ }
+ callback.OnProgress("VCprove", no < 0 ? 0 : no, total, proven_cost / (remaining_cost + proven_cost));
+
+ Contract.Assert(s.parent == this);
+ lock (checker)
+ {
+ s.BeginCheck(checker, callback, mvInfo, no, timeout);
+ }
+
+ no++;
+
+ currently_running.Add(s);
+ }
+ catch (Exception)
+ {
+ checker.GoBackToIdle();
+ throw;
+ }
+ }
+ }
+
+ waiting:
+ if (isWaiting)
+ {
+ // Wait for one split to terminate.
+ var tasks = currently_running.Select(splt => splt.ProverTask).ToArray();
+
+ if (tasks.Any())
+ {
+ try
+ {
+ int index = Task.WaitAny(tasks);
+ s = currently_running[index];
+ currently_running.RemoveAt(index);
+
+ if (do_splitting)
+ {
+ remaining_cost -= s.Cost;
+ }
+
+ lock (s.Checker)
+ {
+ s.ReadOutcome(ref outcome, out prover_failed);
+ }
+
+ if (do_splitting)
+ {
+ if (prover_failed)
+ {
+ // even if the prover fails, we have learned something, i.e., it is
+ // annoying to watch Boogie say Timeout, 0.00% a couple of times
+ proven_cost += s.Cost / 100;
+ }
+ else
+ {
+ proven_cost += s.Cost;
+ }
+ }
+ callback.OnProgress("VCprove", no < 0 ? 0 : no, total, proven_cost / (remaining_cost + proven_cost));
+
+ if (prover_failed && !first_round && s.LastChance)
+ {
+ string msg = "some timeout";
+ if (s.reporter != null && s.reporter.resourceExceededMessage != null)
+ {
+ msg = s.reporter.resourceExceededMessage;
+ }
+ callback.OnCounterexample(s.ToCounterexample(s.Checker.TheoremProver.Context), msg);
+ outcome = Outcome.Errors;
+ break;
+ }
+ }
+ finally
+ {
+ s.Checker.GoBackToIdle();
+ }
+
+ Contract.Assert(prover_failed || outcome == Outcome.Correct || outcome == Outcome.Errors || outcome == Outcome.Inconclusive);
+ }
+ }
+
+ if (prover_failed)
+ {
+ int splits = first_round && max_splits > 1 ? max_splits : max_kg_splits;
+
+ if (splits > 1)
+ {
+ List<Split> tmp = Split.DoSplit(s, max_vc_cost, splits);
+ Contract.Assert(tmp != null);
+ max_vc_cost = 1.0; // for future
+ first_round = false;
+ //tmp.Sort(new Comparison<Split!>(Split.Compare));
+ foreach (Split a in tmp)
+ {
+ Contract.Assert(a != null);
+ work.Push(a);
+ total++;
+ remaining_cost += a.Cost;
+ }
+ if (outcome != Outcome.Errors)
+ {
+ outcome = Outcome.Correct;
+ }
+ }
+ else
+ {
+ Contract.Assert(outcome != Outcome.Correct);
+ if (outcome == Outcome.TimedOut)
+ {
+ string msg = "some timeout";
+ if (s.reporter != null && s.reporter.resourceExceededMessage != null)
+ {
+ msg = s.reporter.resourceExceededMessage;
+ }
+ callback.OnTimeout(msg);
+ }
+ else if (outcome == Outcome.OutOfMemory)
+ {
+ string msg = "out of memory";
+ if (s.reporter != null && s.reporter.resourceExceededMessage != null)
+ {
+ msg = s.reporter.resourceExceededMessage;
+ }
+ callback.OnOutOfMemory(msg);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (outcome == Outcome.Correct && smoke_tester != null) {
+ smoke_tester.Test();
+ }
+
+ callback.OnProgress("done", 0, 0, 1.0);
+
+ if (_print_time)
+ {
+ watch.Stop();
+ Console.WriteLine("Total time for this method: {0}", watch.Elapsed.ToString());
+ }
+
+ return outcome;
+ }
+
+ public class ErrorReporter : ProverInterface.ErrorHandler {
+ Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins;
+ Dictionary<int, Absy>/*!*/ label2absy;
+ List<Block/*!*/>/*!*/ blocks;
+ protected Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap;
+ protected VerifierCallback/*!*/ callback;
+ protected ModelViewInfo MvInfo;
+ internal string resourceExceededMessage;
+ static System.IO.TextWriter modelWriter;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(gotoCmdOrigins != null);
+ Contract.Invariant(label2absy != null);
+ Contract.Invariant(cce.NonNullElements(blocks));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(incarnationOriginMap));
+ Contract.Invariant(callback != null);
+ Contract.Invariant(context != null);
+ Contract.Invariant(program != null);
+ }
+
+
+ public static TextWriter ModelWriter {
+ get {
+ Contract.Ensures(Contract.Result<TextWriter>() != null);
+
+ if (ErrorReporter.modelWriter == null)
+ ErrorReporter.modelWriter = CommandLineOptions.Clo.PrintErrorModelFile == null ? Console.Out : new StreamWriter(CommandLineOptions.Clo.PrintErrorModelFile, false);
+ return ErrorReporter.modelWriter;
+ }
+ }
+
+ protected ProverContext/*!*/ context;
+ Program/*!*/ program;
+
+ public IEnumerable<string> NecessaryAssumes
+ {
+ get { return program.NecessaryAssumes; }
+ }
+
+ public void AddNecessaryAssume(string id)
+ {
+ program.NecessaryAssumes.Add(id);
+ }
+
+ public ErrorReporter(Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins,
+ Dictionary<int, Absy>/*!*/ label2absy,
+ List<Block/*!*/>/*!*/ blocks,
+ Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap,
+ VerifierCallback/*!*/ callback,
+ ModelViewInfo mvInfo,
+ ProverContext/*!*/ context,
+ Program/*!*/ program) {
+ Contract.Requires(gotoCmdOrigins != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
+ Contract.Requires(callback != null);
+ Contract.Requires(context!=null);
+ Contract.Requires(program!=null);
+ this.gotoCmdOrigins = gotoCmdOrigins;
+ this.label2absy = label2absy;
+ this.blocks = blocks;
+ this.incarnationOriginMap = incarnationOriginMap;
+ this.callback = callback;
+ this.MvInfo = mvInfo;
+
+ this.context = context;
+ this.program = program;
+ }
+
+ public override void OnModel(IList<string/*!*/>/*!*/ labels, Model model, ProverInterface.Outcome proverOutcome) {
+ //Contract.Requires(cce.NonNullElements(labels));
+ if (CommandLineOptions.Clo.PrintErrorModel >= 1 && model != null) {
+ if (VC.ConditionGeneration.errorModelList != null)
+ {
+ VC.ConditionGeneration.errorModelList.Add(model);
+ }
+
+ model.Write(ErrorReporter.ModelWriter);
+ ErrorReporter.ModelWriter.Flush();
+ }
+
+ Hashtable traceNodes = new Hashtable();
+ foreach (string s in labels) {
+ Contract.Assert(s != null);
+ Absy absy = Label2Absy(s);
+ Contract.Assert(absy != null);
+ if (traceNodes.ContainsKey(absy))
+ System.Console.WriteLine("Warning: duplicate label: " + s + " read while tracing nodes");
+ else
+ traceNodes.Add(absy, null);
+ }
+
+ List<Block> trace = new List<Block>();
+ Block entryBlock = cce.NonNull(this.blocks[0]);
+ Contract.Assert(traceNodes.Contains(entryBlock));
+ trace.Add(entryBlock);
+
+ Counterexample newCounterexample = TraceCounterexample(entryBlock, traceNodes, trace, model, MvInfo, incarnationOriginMap, context, new Dictionary<TraceLocation, CalleeCounterexampleInfo>());
+
+ if (newCounterexample == null)
+ return;
+
+ #region Map passive program errors back to original program errors
+ ReturnCounterexample returnExample = newCounterexample as ReturnCounterexample;
+ if (returnExample != null) {
+ foreach (Block b in returnExample.Trace) {
+ Contract.Assert(b != null);
+ Contract.Assume(b.TransferCmd != null);
+ ReturnCmd cmd = gotoCmdOrigins.ContainsKey(b.TransferCmd) ? gotoCmdOrigins[b.TransferCmd] : null;
+ if (cmd != null) {
+ returnExample.FailingReturn = cmd;
+ break;
+ }
+ }
+ }
+ #endregion
+ callback.OnCounterexample(newCounterexample, null);
+ }
+
+ public override Absy Label2Absy(string label) {
+ //Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<Absy>() != null);
+
+ int id = int.Parse(label);
+ return cce.NonNull((Absy)label2absy[id]);
+ }
+
+ public override void OnResourceExceeded(string msg, IEnumerable<Tuple<AssertCmd, TransferCmd>> assertCmds = null) {
+ //Contract.Requires(msg != null);
+ resourceExceededMessage = msg;
+ if (assertCmds != null)
+ {
+ foreach (var cmd in assertCmds)
+ {
+ Counterexample cex = AssertCmdToCounterexample(cmd.Item1, cmd.Item2 , new List<Block>(), null, null, context);
+ cex.IsAuxiliaryCexForDiagnosingTimeouts = true;
+ callback.OnCounterexample(cex, msg);
+ }
+ }
+ }
+
+ public override void OnProverWarning(string msg) {
+ //Contract.Requires(msg != null);
+ callback.OnWarning(msg);
+ }
+ }
+
+ public class ErrorReporterLocal : ErrorReporter {
+ public ErrorReporterLocal(Dictionary<TransferCmd, ReturnCmd>/*!*/ gotoCmdOrigins,
+ Dictionary<int, Absy>/*!*/ label2absy,
+ List<Block/*!*/>/*!*/ blocks,
+ Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap,
+ VerifierCallback/*!*/ callback,
+ ModelViewInfo mvInfo,
+ ProverContext/*!*/ context,
+ Program/*!*/ program)
+ : base(gotoCmdOrigins, label2absy, blocks, incarnationOriginMap, callback, mvInfo, context, program) // here for aesthetic purposes //TODO: Maybe nix?
+ {
+ Contract.Requires(gotoCmdOrigins != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
+ Contract.Requires(callback != null);
+ Contract.Requires(context != null);
+ Contract.Requires(program != null);
+ }
+
+ public override void OnModel(IList<string/*!*/>/*!*/ labels, Model model, ProverInterface.Outcome proverOutcome) {
+ //Contract.Requires(cce.NonNullElements(labels));
+ // We ignore the error model here for enhanced error message purposes.
+ // It is only printed to the command line.
+ if (CommandLineOptions.Clo.PrintErrorModel >= 1 && model != null) {
+ if (CommandLineOptions.Clo.PrintErrorModelFile != null) {
+ model.Write(ErrorReporter.ModelWriter);
+ ErrorReporter.ModelWriter.Flush();
+ }
+ }
+ List<Block> traceNodes = new List<Block>();
+ List<AssertCmd> assertNodes = new List<AssertCmd>();
+ foreach (string s in labels) {
+ Contract.Assert(s != null);
+ Absy node = Label2Absy(s);
+ if (node is Block) {
+ Block b = (Block)node;
+ traceNodes.Add(b);
+ } else {
+ AssertCmd a = (AssertCmd)node;
+ assertNodes.Add(a);
+ }
+ }
+ Contract.Assert(assertNodes.Count > 0);
+ Contract.Assert(traceNodes.Count == assertNodes.Count);
+
+ foreach (AssertCmd a in assertNodes) {
+ // find the corresponding Block (assertNodes.Count is likely to be 1, or small in any case, so just do a linear search here)
+ foreach (Block b in traceNodes) {
+ if (b.Cmds.Contains(a)) {
+ List<Block> trace = new List<Block>();
+ trace.Add(b);
+ Counterexample newCounterexample = AssertCmdToCounterexample(a, cce.NonNull(b.TransferCmd), trace, model, MvInfo, context);
+ callback.OnCounterexample(newCounterexample, null);
+ goto NEXT_ASSERT;
+ }
+ }
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // there was no block that contains the assert
+ NEXT_ASSERT: {
+ }
+ }
+ }
+ }
+
+ private void RecordCutEdge(Dictionary<Block,List<Block>> edgesCut, Block from, Block to){
+ if (edgesCut != null)
+ {
+ if (!edgesCut.ContainsKey(from))
+ edgesCut.Add(from, new List<Block>());
+ edgesCut[from].Add(to);
+ }
+ }
+
+ public void ConvertCFG2DAG(Implementation impl, Dictionary<Block,List<Block>> edgesCut = null, int taskID = -1)
+ {
+ Contract.Requires(impl != null);
+ impl.PruneUnreachableBlocks(); // This is needed for VCVariety.BlockNested, and is otherwise just an optimization
+
+ CurrentLocalVariables = impl.LocVars;
+ variable2SequenceNumber = new Dictionary<Variable, int>();
+ incarnationOriginMap = new Dictionary<Incarnation, Absy>();
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("original implementation");
+ EmitImpl(impl, false);
+ }
+ #endregion
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after desugaring sugared commands like procedure calls");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ // Recompute the predecessors, but first insert a dummy start node that is sure not to be the target of any goto (because the cutting of back edges
+ // below assumes that the start node has no predecessor)
+ impl.Blocks.Insert(0, new Block(new Token(-17, -4), "0", new List<Cmd>(), new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] })));
+ ResetPredecessors(impl.Blocks);
+
+ var k = Math.Max(CommandLineOptions.Clo.KInductionDepth, QKeyValue.FindIntAttribute(impl.Attributes, "kInductionDepth", -1));
+ if(k < 0) {
+ ConvertCFG2DAGStandard(impl, edgesCut, taskID);
+ } else {
+ ConvertCFG2DAGKInduction(impl, edgesCut, taskID, k);
+ }
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after conversion into a DAG");
+ EmitImpl(impl, true);
+ }
+ #endregion
+ }
+
+ private void ConvertCFG2DAGStandard(Implementation impl, Dictionary<Block, List<Block>> edgesCut, int taskID)
+ {
+ #region Convert program CFG into a DAG
+
+ #region Use the graph library to figure out where the (natural) loops are
+
+ #region Create the graph by adding the source node and each edge
+ Graph<Block> g = Program.GraphFromImpl(impl);
+ #endregion
+
+ //Graph<Block> g = program.ProcessLoops(impl);
+
+ g.ComputeLoops(); // this is the call that does all of the processing
+ if (!g.Reducible)
+ {
+ throw new VCGenException("Irreducible flow graphs are unsupported.");
+ }
+
+ #endregion
+
+ #region Cut the backedges, push assert/assume statements from loop header into predecessors, change them all into assume statements at top of loop, introduce havoc statements
+ foreach (Block header in cce.NonNull(g.Headers))
+ {
+ Contract.Assert(header != null);
+ IDictionary<Block, object> backEdgeNodes = new Dictionary<Block, object>();
+ foreach (Block b in cce.NonNull(g.BackEdgeNodes(header)))
+ {
+ Contract.Assert(b != null);
+ backEdgeNodes.Add(b, null);
+ }
+
+ #region Find the (possibly empty) prefix of assert commands in the header, replace each assert with an assume of the same condition
+ List<Cmd> prefixOfPredicateCmdsInit = new List<Cmd>();
+ List<Cmd> prefixOfPredicateCmdsMaintained = new List<Cmd>();
+ for (int i = 0, n = header.Cmds.Count; i < n; i++)
+ {
+ PredicateCmd a = header.Cmds[i] as PredicateCmd;
+ if (a != null)
+ {
+ if (a is AssertCmd)
+ {
+ AssertCmd c = (AssertCmd)a;
+ AssertCmd b = null;
+
+ if (CommandLineOptions.Clo.ConcurrentHoudini)
+ {
+ Contract.Assert(taskID >= 0);
+ if (CommandLineOptions.Clo.Cho[taskID].DisableLoopInvEntryAssert)
+ b = new LoopInitAssertCmd(c.tok, Expr.True);
+ else
+ b = new LoopInitAssertCmd(c.tok, c.Expr);
+ }
+ else
+ {
+ b = new LoopInitAssertCmd(c.tok, c.Expr);
+ }
+
+ b.Attributes = c.Attributes;
+ b.ErrorData = c.ErrorData;
+ prefixOfPredicateCmdsInit.Add(b);
+
+ if (CommandLineOptions.Clo.ConcurrentHoudini)
+ {
+ Contract.Assert(taskID >= 0);
+ if (CommandLineOptions.Clo.Cho[taskID].DisableLoopInvMaintainedAssert)
+ b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, Expr.True);
+ else
+ b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, c.Expr);
+ }
+ else
+ {
+ b = new Bpl.LoopInvMaintainedAssertCmd(c.tok, c.Expr);
+ }
+
+ b.Attributes = c.Attributes;
+ b.ErrorData = c.ErrorData;
+ prefixOfPredicateCmdsMaintained.Add(b);
+ header.Cmds[i] = new AssumeCmd(c.tok, c.Expr);
+ }
+ else
+ {
+ Contract.Assert(a is AssumeCmd);
+ if (Bpl.CommandLineOptions.Clo.AlwaysAssumeFreeLoopInvariants)
+ {
+ // Usually, "free" stuff, like free loop invariants (and the assume statements
+ // that stand for such loop invariants) are ignored on the checking side. This
+ // command-line option changes that behavior to always assume the conditions.
+ prefixOfPredicateCmdsInit.Add(a);
+ prefixOfPredicateCmdsMaintained.Add(a);
+ }
+ }
+ }
+ else if (header.Cmds[i] is CommentCmd)
+ {
+ // ignore
+ }
+ else
+ {
+ break; // stop when an assignment statement (or any other non-predicate cmd) is encountered
+ }
+ }
+ #endregion
+
+ #region Copy the prefix of predicate commands into each predecessor. Do this *before* cutting the backedge!!
+ for (int predIndex = 0, n = header.Predecessors.Count; predIndex < n; predIndex++)
+ {
+ Block pred = cce.NonNull(header.Predecessors[predIndex]);
+
+ // Create a block between header and pred for the predicate commands if pred has more than one successor
+ GotoCmd gotocmd = cce.NonNull((GotoCmd)pred.TransferCmd);
+ Contract.Assert(gotocmd.labelNames != null); // if "pred" is really a predecessor, it may be a GotoCmd with at least one label
+ if (gotocmd.labelNames.Count > 1)
+ {
+ Block newBlock = CreateBlockBetween(predIndex, header);
+ impl.Blocks.Add(newBlock);
+
+ // if pred is a back edge node, then now newBlock is the back edge node
+ if (backEdgeNodes.ContainsKey(pred))
+ {
+ backEdgeNodes.Remove(pred);
+ backEdgeNodes.Add(newBlock, null);
+ }
+
+ pred = newBlock;
+ }
+ // Add the predicate commands
+ if (backEdgeNodes.ContainsKey(pred))
+ {
+ pred.Cmds.AddRange(prefixOfPredicateCmdsMaintained);
+ }
+ else
+ {
+ pred.Cmds.AddRange(prefixOfPredicateCmdsInit);
+ }
+ }
+ #endregion
+
+ #region Cut the back edge
+ foreach (Block backEdgeNode in cce.NonNull(backEdgeNodes.Keys))
+ {
+ Contract.Assert(backEdgeNode != null);
+ Debug.Assert(backEdgeNode.TransferCmd is GotoCmd, "An node was identified as the source for a backedge, but it does not have a goto command.");
+ GotoCmd gtc = backEdgeNode.TransferCmd as GotoCmd;
+ if (gtc != null && gtc.labelTargets != null && gtc.labelTargets.Count > 1)
+ {
+ // then remove the backedge by removing the target block from the list of gotos
+ List<Block> remainingTargets = new List<Block>();
+ List<String> remainingLabels = new List<String>();
+ Contract.Assume(gtc.labelNames != null);
+ for (int i = 0, n = gtc.labelTargets.Count; i < n; i++)
+ {
+ if (gtc.labelTargets[i] != header)
+ {
+ remainingTargets.Add(gtc.labelTargets[i]);
+ remainingLabels.Add(gtc.labelNames[i]);
+ }
+ else
+ RecordCutEdge(edgesCut, backEdgeNode, header);
+ }
+ gtc.labelTargets = remainingTargets;
+ gtc.labelNames = remainingLabels;
+ }
+ else
+ {
+ // This backedge is the only out-going edge from this node.
+ // Add an "assume false" statement to the end of the statements
+ // inside of the block and change the goto command to a return command.
+ AssumeCmd ac = new AssumeCmd(Token.NoToken, Expr.False);
+ backEdgeNode.Cmds.Add(ac);
+ backEdgeNode.TransferCmd = new ReturnCmd(Token.NoToken);
+ if (gtc != null && gtc.labelTargets != null && gtc.labelTargets.Count == 1)
+ RecordCutEdge(edgesCut, backEdgeNode, gtc.labelTargets[0]);
+ }
+ #region Remove the backedge node from the list of predecessor nodes in the header
+ List<Block> newPreds = new List<Block>();
+ foreach (Block p in header.Predecessors)
+ {
+ if (p != backEdgeNode)
+ newPreds.Add(p);
+ }
+ header.Predecessors = newPreds;
+ #endregion
+ }
+ #endregion
+
+ #region Collect all variables that are assigned to in all of the natural loops for which this is the header
+ List<Variable> varsToHavoc = VarsAssignedInLoop(g, header);
+ List<IdentifierExpr> havocExprs = new List<IdentifierExpr>();
+ foreach (Variable v in varsToHavoc)
+ {
+ Contract.Assert(v != null);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
+ if (!havocExprs.Contains(ie))
+ havocExprs.Add(ie);
+ }
+ // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
+ // the source location for this later on
+ HavocCmd hc = new HavocCmd(header.tok, havocExprs);
+ List<Cmd> newCmds = new List<Cmd>();
+ newCmds.Add(hc);
+ foreach (Cmd c in header.Cmds)
+ {
+ newCmds.Add(c);
+ }
+ header.Cmds = newCmds;
+ #endregion
+ }
+ #endregion
+ #endregion Convert program CFG into a DAG
+ }
+
+ public static List<Variable> VarsAssignedInLoop(Graph<Block> g, Block header)
+ {
+ List<Variable> varsToHavoc = new List<Variable>();
+ foreach (Block backEdgeNode in cce.NonNull(g.BackEdgeNodes(header)))
+ {
+ Contract.Assert(backEdgeNode != null);
+ foreach (Block b in g.NaturalLoops(header, backEdgeNode))
+ {
+ Contract.Assert(b != null);
+ foreach (Cmd c in b.Cmds)
+ {
+ Contract.Assert(c != null);
+ c.AddAssignedVariables(varsToHavoc);
+ }
+ }
+ }
+ return varsToHavoc;
+ }
+
+ public static IEnumerable<Variable> VarsReferencedInLoop(Graph<Block> g, Block header)
+ {
+ HashSet<Variable> referencedVars = new HashSet<Variable>();
+ foreach (Block backEdgeNode in cce.NonNull(g.BackEdgeNodes(header)))
+ {
+ Contract.Assert(backEdgeNode != null);
+ foreach (Block b in g.NaturalLoops(header, backEdgeNode))
+ {
+ Contract.Assert(b != null);
+ foreach (Cmd c in b.Cmds)
+ {
+ Contract.Assert(c != null);
+ var Collector = new VariableCollector();
+ Collector.Visit(c);
+ foreach(var v in Collector.usedVars) {
+ referencedVars.Add(v);
+ }
+ }
+ }
+ }
+ return referencedVars;
+ }
+
+ private void ConvertCFG2DAGKInduction(Implementation impl, Dictionary<Block, List<Block>> edgesCut, int taskID, int inductionK) {
+
+ // K-induction has not been adapted to be aware of these parameters which standard CFG to DAG transformation uses
+ Contract.Requires(edgesCut == null);
+ Contract.Requires(taskID == -1);
+ Contract.Requires(0 <= inductionK);
+
+ bool contRuleApplication = true;
+ while (contRuleApplication) {
+ contRuleApplication = false;
+
+ #region Use the graph library to figure out where the (natural) loops are
+
+ #region Create the graph by adding the source node and each edge
+ Graph<Block> g = Program.GraphFromImpl(impl);
+ #endregion
+
+ g.ComputeLoops(); // this is the call that does all of the processing
+ if (!g.Reducible) {
+ throw new VCGenException("Irreducible flow graphs are unsupported.");
+ }
+
+ #endregion
+
+ foreach (Block header in cce.NonNull(g.Headers)) {
+ Contract.Assert(header != null);
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("Applying k-induction rule with k=" + inductionK);
+ }
+ #endregion
+
+ #region generate the step case
+ Block newHeader = DuplicateLoop(impl, g, header, null,
+ false, false, "_step_assertion");
+ for (int i = 0; i < inductionK; ++i)
+ {
+ newHeader = DuplicateLoop(impl, g, header, newHeader,
+ true, true,
+ "_step_" + (inductionK - i));
+ }
+ #endregion
+
+ #region havoc variables that can be assigned in the loop
+
+ List<Variable> varsToHavoc = VarsAssignedInLoop(g, header);
+ List<IdentifierExpr> havocExprs = new List<IdentifierExpr>();
+ foreach (Variable v in varsToHavoc)
+ {
+ Contract.Assert(v != null);
+ IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v);
+ if (!havocExprs.Contains(ie))
+ havocExprs.Add(ie);
+ }
+ // pass the token of the enclosing loop header to the HavocCmd so we can reconstruct
+ // the source location for this later on
+ HavocCmd hc = new HavocCmd(newHeader.tok, havocExprs);
+ List<Cmd> havocCmds = new List<Cmd>();
+ havocCmds.Add(hc);
+
+ Block havocBlock = new Block(newHeader.tok, newHeader.Label + "_havoc", havocCmds,
+ new GotoCmd (newHeader.tok, new List<Block> { newHeader }));
+
+ impl.Blocks.Add(havocBlock);
+ newHeader.Predecessors.Add(havocBlock);
+ newHeader = havocBlock;
+
+ #endregion
+
+ #region generate the base case loop copies
+ for (int i = 0; i < inductionK; ++i)
+ {
+ newHeader = DuplicateLoop(impl, g, header, newHeader,
+ false, false,
+ "_base_" + (inductionK - i));
+ }
+ #endregion
+
+ #region redirect into the new loop copies and remove the original loop (but don't redirect back-edges)
+
+ IDictionary<Block, object> backEdgeNodes = new Dictionary<Block, object>();
+ foreach (Block b in cce.NonNull(g.BackEdgeNodes(header))) { Contract.Assert(b != null); backEdgeNodes.Add(b, null); }
+
+ for (int predIndex = 0, n = header.Predecessors.Count(); predIndex < n; predIndex++)
+ {
+ Block pred = cce.NonNull(header.Predecessors[predIndex]);
+ if (!backEdgeNodes.ContainsKey(pred))
+ {
+ GotoCmd gc = pred.TransferCmd as GotoCmd;
+ Contract.Assert(gc != null);
+ for (int i = 0; i < gc.labelTargets.Count(); ++i)
+ {
+ if (gc.labelTargets[i] == header)
+ {
+ gc.labelTargets[i] = newHeader;
+ gc.labelNames[i] = newHeader.Label;
+ newHeader.Predecessors.Add(pred);
+ }
+ }
+ }
+ }
+ impl.PruneUnreachableBlocks();
+
+ #endregion
+
+ contRuleApplication = true;
+ break;
+ }
+
+ }
+
+ ResetPredecessors(impl.Blocks);
+ impl.FreshenCaptureStates();
+
+ }
+
+ private Block DuplicateLoop(Implementation impl, Graph<Block> g,
+ Block header, Block nextHeader, bool cutExits,
+ bool toAssumptions, string suffix)
+ {
+ IDictionary<Block, Block> ori2CopiedBlocks = new Dictionary<Block, Block>();
+ Duplicator duplicator = new Duplicator();
+
+ #region create copies of all blocks in the loop
+ foreach (Block backEdgeNode in cce.NonNull(g.BackEdgeNodes(header)))
+ {
+ Contract.Assert(backEdgeNode != null);
+ foreach (Block b in g.NaturalLoops(header, backEdgeNode))
+ {
+ Contract.Assert(b != null);
+ if (!ori2CopiedBlocks.ContainsKey(b))
+ {
+ Block copy = (Block)duplicator.Visit(b);
+ copy.Cmds = new List<Cmd>(copy.Cmds); // Philipp Ruemmer commented that this was necessary due to a bug in the Duplicator. That was a long time; worth checking whether this has been fixed
+ copy.Predecessors = new List<Block>();
+ copy.Label = copy.Label + suffix;
+
+ #region turn asserts into assumptions
+ if (toAssumptions)
+ {
+ for (int i = 0; i < copy.Cmds.Count(); ++i)
+ {
+ AssertCmd ac = copy.Cmds[i] as AssertCmd;
+ if (ac != null)
+ {
+ copy.Cmds[i] = new AssumeCmd(ac.tok, ac.Expr);
+ }
+ }
+ }
+ #endregion
+
+ impl.Blocks.Add(copy);
+ ori2CopiedBlocks.Add(b, copy);
+ }
+ }
+ }
+ #endregion
+
+ #region adjust the transfer commands of the newly created blocks
+ foreach (KeyValuePair<Block, Block> pair in ori2CopiedBlocks)
+ {
+ Block copy = pair.Value;
+ GotoCmd gc = copy.TransferCmd as GotoCmd;
+ if (gc != null)
+ {
+ List<Block> newTargets = new List<Block>();
+ List<string> newLabels = new List<string>();
+
+ for (int i = 0; i < gc.labelTargets.Count(); ++i)
+ {
+ Block newTarget;
+ if (gc.labelTargets[i] == header)
+ {
+ if (nextHeader != null)
+ {
+ newTargets.Add(nextHeader);
+ newLabels.Add(nextHeader.Label);
+ nextHeader.Predecessors.Add(copy);
+ }
+ }
+ else if (ori2CopiedBlocks.TryGetValue(gc.labelTargets[i], out newTarget))
+ {
+ newTargets.Add(newTarget);
+ newLabels.Add(newTarget.Label);
+ newTarget.Predecessors.Add(copy);
+ }
+ else if (!cutExits)
+ {
+ newTargets.Add(gc.labelTargets[i]);
+ newLabels.Add(gc.labelNames[i]);
+ gc.labelTargets[i].Predecessors.Add(copy);
+ }
+ }
+
+ if (newTargets.Count() == 0)
+ {
+ // if no targets are left, we assume false and return
+ copy.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
+ copy.TransferCmd = new ReturnCmd(Token.NoToken);
+ }
+ else
+ {
+ copy.TransferCmd = new GotoCmd(gc.tok, newLabels, newTargets);
+ }
+ }
+ else if (cutExits && (copy.TransferCmd is ReturnCmd))
+ {
+ // because return is a kind of exit from the loop, we
+ // assume false to cut this path
+ copy.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
+ }
+ }
+ #endregion
+
+ return ori2CopiedBlocks[header];
+ }
+
+ public void DesugarCalls(Implementation impl) {
+ foreach (Block block in impl.Blocks) {
+ List<Cmd> newCmds = new List<Cmd>();
+ foreach (Cmd cmd in block.Cmds) {
+ SugaredCmd sugaredCmd = cmd as SugaredCmd;
+ if (sugaredCmd != null) {
+ StateCmd stateCmd = sugaredCmd.Desugaring as StateCmd;
+ foreach (Variable v in stateCmd.Locals) {
+ impl.LocVars.Add(v);
+ }
+ newCmds.AddRange(stateCmd.Cmds);
+ }
+ else {
+ newCmds.Add(cmd);
+ }
+ }
+ block.Cmds = newCmds;
+ }
+ }
+
+ public Dictionary<TransferCmd, ReturnCmd> PassifyImpl(Implementation impl, out ModelViewInfo mvInfo)
+ {
+ Contract.Requires(impl != null);
+ Contract.Requires(program != null);
+ Contract.Ensures(Contract.Result<Dictionary<TransferCmd, ReturnCmd>>() != null);
+
+ Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>();
+ Block exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins);
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after creating a unified exit block");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ #region Insert pre- and post-conditions and where clauses as assume and assert statements
+ {
+ List<Cmd> cc = new List<Cmd>();
+ // where clauses of global variables
+ lock (program.TopLevelDeclarations)
+ {
+ foreach (var gvar in program.GlobalVariables)
+ {
+ if (gvar != null && gvar.TypedIdent.WhereExpr != null)
+ {
+ Cmd c = new AssumeCmd(gvar.tok, gvar.TypedIdent.WhereExpr);
+ cc.Add(c);
+ }
+ }
+ }
+ // where clauses of in- and out-parameters
+ cc.AddRange(GetParamWhereClauses(impl));
+ // where clauses of local variables
+ foreach (Variable lvar in impl.LocVars) {Contract.Assert(lvar != null);
+ if (lvar.TypedIdent.WhereExpr != null) {
+ Cmd c = new AssumeCmd(lvar.tok, lvar.TypedIdent.WhereExpr);
+ cc.Add(c);
+ } else if (QKeyValue.FindBoolAttribute(lvar.Attributes, "assumption")) {
+ cc.Add(new AssumeCmd(lvar.tok, new IdentifierExpr(lvar.tok, lvar), new QKeyValue(lvar.tok, "assumption_variable_initialization", new List<object>(), null)));
+ }
+ }
+ // add cc and the preconditions to new blocks preceding impl.Blocks[0]
+ InjectPreconditions(impl, cc);
+
+ // append postconditions, starting in exitBlock and continuing into other blocks, if needed
+ InjectPostConditions(impl, exitBlock, gotoCmdOrigins);
+ }
+ #endregion
+
+ #region Support for stratified inlining
+ addExitAssert(impl.Name, exitBlock);
+ #endregion
+
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after inserting pre- and post-conditions");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ AddBlocksBetween(impl.Blocks);
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after adding empty blocks as needed to catch join assumptions");
+ EmitImpl(impl, true);
+ }
+ #endregion
+
+ if (CommandLineOptions.Clo.LiveVariableAnalysis > 0) {
+ Microsoft.Boogie.LiveVariableAnalysis.ComputeLiveVariables(impl);
+ }
+
+ mvInfo = new ModelViewInfo(program, impl);
+ Convert2PassiveCmd(impl, mvInfo);
+
+ if (QKeyValue.FindBoolAttribute(impl.Attributes, "may_unverified_instrumentation"))
+ {
+ InstrumentWithMayUnverifiedConditions(impl, exitBlock);
+ }
+
+ #region Peep-hole optimizations
+ if (CommandLineOptions.Clo.RemoveEmptyBlocks){
+ #region Get rid of empty blocks
+ {
+ RemoveEmptyBlocksIterative(impl.Blocks);
+ impl.PruneUnreachableBlocks();
+ }
+ #endregion Get rid of empty blocks
+
+ #region Debug Tracing
+ if (CommandLineOptions.Clo.TraceVerify)
+ {
+ Console.WriteLine("after peep-hole optimizations");
+ EmitImpl(impl, true);
+ }
+ #endregion
+ }
+ #endregion Peep-hole optimizations
+
+ HandleSelectiveChecking(impl);
+
+
+// #region Constant Folding
+// #endregion
+// #region Debug Tracing
+// if (CommandLineOptions.Clo.TraceVerify)
+// {
+// Console.WriteLine("after constant folding");
+// EmitImpl(impl, true);
+// }
+// #endregion
+
+ return gotoCmdOrigins;
+ }
+
+ #region Simplified May-Unverified Analysis and Instrumentation
+
+ static void InstrumentWithMayUnverifiedConditions(Implementation impl, Block unifiedExitBlock)
+ {
+ var q = new Queue<Block>();
+ q.Enqueue(unifiedExitBlock);
+ var conditionOnBlockEntry = new Dictionary<Block, HashSet<Variable>>();
+ while (q.Any())
+ {
+ var block = q.Dequeue();
+
+ if (conditionOnBlockEntry.ContainsKey(block))
+ {
+ continue;
+ }
+
+ var gotoCmd = block.TransferCmd as GotoCmd;
+ if (gotoCmd != null && gotoCmd.labelTargets.Any(b => !conditionOnBlockEntry.ContainsKey(b)))
+ {
+ q.Enqueue(block);
+ continue;
+ }
+
+ HashSet<Variable> cond = new HashSet<Variable>();
+ if (gotoCmd != null)
+ {
+ var mayInstrs = new List<Block>();
+ bool noInstr = true;
+ foreach (var succ in gotoCmd.labelTargets)
+ {
+ var c = conditionOnBlockEntry[succ];
+ if (c != null)
+ {
+ mayInstrs.Add(succ);
+ }
+ else
+ {
+ noInstr = false;
+ }
+ cond = JoinVariableSets(cond, c);
+ }
+ if (!noInstr)
+ {
+ foreach (var instr in mayInstrs)
+ {
+ InstrumentWithCondition(instr, 0, conditionOnBlockEntry[instr]);
+ }
+ }
+ }
+
+ for (int i = block.Cmds.Count - 1; 0 <= i; i--)
+ {
+ var cmd = block.Cmds[i];
+ if (cond == null) { break; }
+
+ var assertCmd = cmd as AssertCmd;
+ if (assertCmd != null)
+ {
+ var litExpr = assertCmd.Expr as LiteralExpr;
+ if (litExpr != null && litExpr.IsTrue)
+ {
+ continue;
+ }
+
+ HashSet<Variable> vu = null;
+ if (assertCmd.VerifiedUnder == null)
+ {
+ vu = null;
+ }
+ else
+ {
+ HashSet<Variable> vars;
+ if (IsConjunctionOfAssumptionVariables(assertCmd.VerifiedUnder, out vars))
+ {
+ vu = vars;
+ // TODO(wuestholz): Maybe drop the :verified_under attribute.
+ }
+ else
+ {
+ vu = null;
+ }
+ }
+
+ if (vu == null)
+ {
+ InstrumentWithCondition(block, i + 1, cond);
+ }
+
+ cond = JoinVariableSets(cond, vu);
+ }
+ }
+
+ if (cond != null && block.Predecessors.Count == 0)
+ {
+ // TODO(wuestholz): Should we rather instrument each block?
+ InstrumentWithCondition(block, 0, cond);
+ }
+
+ foreach (var pred in block.Predecessors)
+ {
+ q.Enqueue(pred);
+ }
+
+ conditionOnBlockEntry[block] = cond;
+ }
+ }
+
+ private static void InstrumentWithCondition(Block block, int idx, HashSet<Variable> condition)
+ {
+ var conj = Expr.BinaryTreeAnd(condition.Select(v => (Expr)new IdentifierExpr(Token.NoToken, v)).ToList());
+ block.Cmds.Insert(idx, new AssumeCmd(Token.NoToken, Expr.Not(conj)));
+ }
+
+ static HashSet<Variable> JoinVariableSets(HashSet<Variable> c0, HashSet<Variable> c1)
+ {
+ // We use the following lattice:
+ // - Top: null (i.e., true)
+ // - Bottom: new HashSet<Variable>() (i.e., false)
+ // - Other Elements: new HashSet<Variable>(...) (i.e., conjunctions of assumption variables)
+
+ if (c0 == null || c1 == null)
+ {
+ return null;
+ }
+ var result = new HashSet<Variable>(c0);
+ result.UnionWith(c1);
+ return result;
+ }
+
+ static bool IsAssumptionVariableOrIncarnation(Variable v)
+ {
+ if (QKeyValue.FindBoolAttribute(v.Attributes, "assumption")) { return true; }
+ var incar = v as Incarnation;
+ return incar == null || QKeyValue.FindBoolAttribute(incar.OriginalVariable.Attributes, "assumption");
+ }
+
+ static bool IsConjunctionOfAssumptionVariables(Expr expr, out HashSet<Variable> variables)
+ {
+ Contract.Requires(expr != null);
+
+ variables = null;
+ var litExpr = expr as LiteralExpr;
+ if (litExpr != null && (litExpr.IsFalse || litExpr.IsTrue))
+ {
+ if (litExpr.IsTrue)
+ {
+ variables = new HashSet<Variable>();
+ }
+ return true;
+ }
+
+ var idExpr = expr as IdentifierExpr;
+ if (idExpr != null && IsAssumptionVariableOrIncarnation(idExpr.Decl))
+ {
+ variables = new HashSet<Variable>();
+ variables.Add(idExpr.Decl);
+ return true;
+ }
+
+ var andExpr = expr as NAryExpr;
+ if (andExpr != null)
+ {
+ var fun = andExpr.Fun as BinaryOperator;
+ if (fun != null && fun.Op == BinaryOperator.Opcode.And && andExpr.Args != null)
+ {
+ bool res = true;
+ variables = new HashSet<Variable>();
+ foreach (var op in andExpr.Args)
+ {
+ HashSet<Variable> vars;
+ var r = IsConjunctionOfAssumptionVariables(op, out vars);
+ res &= r;
+ variables = JoinVariableSets(variables, vars);
+ if (!res) { break; }
+ }
+ return res;
+ }
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ private static void HandleSelectiveChecking(Implementation impl)
+ {
+ if (QKeyValue.FindBoolAttribute(impl.Attributes, "selective_checking") ||
+ QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "selective_checking")) {
+
+ var startPoints = new List<Block>();
+ foreach (var b in impl.Blocks) {
+ foreach (Cmd c in b.Cmds) {
+ var p = c as PredicateCmd;
+ if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "start_checking_here")) {
+ startPoints.Add(b);
+ break;
+ }
+ }
+ }
+
+ // Compute the set of blocks reachable from blocks containing "start_checking_here"
+ var blocksToCheck = new HashSet<Block>();
+ foreach (var b in startPoints) {
+ var todo = new Stack<Block>();
+ var wasThere = blocksToCheck.Contains(b);
+ todo.Push(b);
+ while (todo.Count > 0) {
+ var x = todo.Pop();
+ if (blocksToCheck.Contains(x)) continue;
+ blocksToCheck.Add(x);
+ var ex = x.TransferCmd as GotoCmd;
+ if (ex != null)
+ foreach (Block e in ex.labelTargets)
+ todo.Push(e);
+ }
+ if (!wasThere) blocksToCheck.Remove(b);
+ }
+
+ // Convert asserts to assumes in "unreachable" blocks, as well as in portions of blocks before we reach "start_checking_here"
+ foreach (var b in impl.Blocks) {
+ if (blocksToCheck.Contains(b)) continue; // All reachable blocks must be checked in their entirety, so don't change anything
+ var newCmds = new List<Cmd>();
+ var copyMode = false;
+ foreach (Cmd c in b.Cmds) {
+ var p = c as PredicateCmd;
+ if (p != null && QKeyValue.FindBoolAttribute(p.Attributes, "start_checking_here"))
+ copyMode = true;
+ var asrt = c as AssertCmd;
+ if (copyMode || asrt == null)
+ newCmds.Add(c);
+ else
+ newCmds.Add(AssertTurnedIntoAssume(asrt));
+ }
+
+ b.Cmds = newCmds;
+ }
+ }
+ }
+
+ // Used by stratified inlining
+ protected virtual void addExitAssert(string implName, Block exitBlock)
+ {
+ }
+
+ public virtual Counterexample extractLoopTrace(Counterexample cex, string mainProcName, Program program, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
+ {
+ // Construct the set of inlined procs in the original program
+ var inlinedProcs = new HashSet<string>();
+ foreach (var proc in program.Procedures)
+ {
+ if (!(proc is LoopProcedure))
+ {
+ inlinedProcs.Add(proc.Name);
+ }
+ }
+
+ return extractLoopTraceRec(
+ new CalleeCounterexampleInfo(cex, new List<object>()),
+ mainProcName, inlinedProcs, extractLoopMappingInfo).counterexample;
+ }
+
+ protected CalleeCounterexampleInfo extractLoopTraceRec(
+ CalleeCounterexampleInfo cexInfo, string currProc,
+ HashSet<string> inlinedProcs,
+ Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
+ {
+ Contract.Requires(currProc != null);
+ if (cexInfo.counterexample == null) return cexInfo;
+
+ var cex = cexInfo.counterexample;
+ // Go through all blocks in the trace, map them back to blocks in the original program (if there is one)
+ var ret = cex.Clone();
+ ret.Trace = new List<Block>();
+ ret.calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
+
+ for (int numBlock = 0; numBlock < cex.Trace.Count; numBlock ++ )
+ {
+ Block block = cex.Trace[numBlock];
+ var origBlock = elGetBlock(currProc, block, extractLoopMappingInfo);
+ if (origBlock != null) ret.Trace.Add(origBlock);
+ var callCnt = 1;
+ for (int numInstr = 0; numInstr < block.Cmds.Count; numInstr ++) {
+ Cmd cmd = block.Cmds[numInstr];
+ var loc = new TraceLocation(numBlock, numInstr);
+ if (!cex.calleeCounterexamples.ContainsKey(loc))
+ {
+ if (getCallee(cex.getTraceCmd(loc), inlinedProcs) != null) callCnt++;
+ continue;
+ }
+ string callee = cex.getCalledProcName(cex.getTraceCmd(loc));
+ Contract.Assert(callee != null);
+ var calleeTrace = cex.calleeCounterexamples[loc];
+ Debug.Assert(calleeTrace != null);
+
+ var origTrace = extractLoopTraceRec(calleeTrace, callee, inlinedProcs, extractLoopMappingInfo);
+
+ if (elIsLoop(callee))
+ {
+ // Absorb the trace into the current trace
+
+ int currLen = ret.Trace.Count;
+ ret.Trace.AddRange(origTrace.counterexample.Trace);
+
+ foreach (var kvp in origTrace.counterexample.calleeCounterexamples)
+ {
+ var newloc = new TraceLocation(kvp.Key.numBlock + currLen, kvp.Key.numInstr);
+ ret.calleeCounterexamples.Add(newloc, kvp.Value);
+ }
+
+ }
+ else
+ {
+ var origLoc = new TraceLocation(ret.Trace.Count - 1, getCallCmdPosition(origBlock, callCnt, inlinedProcs, callee));
+ ret.calleeCounterexamples.Add(origLoc, origTrace);
+ callCnt++;
+ }
+ }
+ }
+ return new CalleeCounterexampleInfo(ret, cexInfo.args);
+ }
+
+ // return the position of the i^th CallCmd in the block (count only those Calls that call a procedure in inlinedProcs).
+ // Assert failure if there isn't any.
+ // Assert that the CallCmd found calls "callee"
+ private int getCallCmdPosition(Block block, int i, HashSet<string> inlinedProcs, string callee)
+ {
+ Debug.Assert(i >= 1);
+ for (int pos = 0; pos < block.Cmds.Count; pos++)
+ {
+ Cmd cmd = block.Cmds[pos];
+ string procCalled = getCallee(cmd, inlinedProcs);
+
+ if (procCalled != null)
+ {
+ if (i == 1)
+ {
+ Debug.Assert(procCalled == callee);
+ return pos;
+ }
+ i--;
+ }
+ }
+
+ Debug.Assert(false, "Didn't find the i^th call cmd");
+ return -1;
+ }
+
+ private string getCallee(Cmd cmd, HashSet<string> inlinedProcs)
+ {
+ string procCalled = null;
+ if (cmd is CallCmd)
+ {
+ var cc = (CallCmd)cmd;
+ if (inlinedProcs.Contains(cc.Proc.Name))
+ {
+ procCalled = cc.Proc.Name;
+ }
+ }
+
+ if (cmd is AssumeCmd)
+ {
+ var expr = (cmd as AssumeCmd).Expr as NAryExpr;
+ if (expr != null)
+ {
+ if (inlinedProcs.Contains(expr.Fun.FunctionName))
+ {
+ procCalled = expr.Fun.FunctionName;
+ }
+ }
+ }
+ return procCalled;
+ }
+
+ protected virtual bool elIsLoop(string procname)
+ {
+ return false;
+ }
+
+ private Block elGetBlock(string procname, Block block, Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo)
+ {
+ Contract.Requires(procname != null);
+
+ if (!extractLoopMappingInfo.ContainsKey(procname))
+ return block;
+
+ if (!extractLoopMappingInfo[procname].ContainsKey(block.Label))
+ return null;
+
+ return extractLoopMappingInfo[procname][block.Label];
+ }
+
+ static Counterexample TraceCounterexample(
+ Block/*!*/ b, Hashtable/*!*/ traceNodes, List<Block>/*!*/ trace, Model errModel, ModelViewInfo mvInfo,
+ Dictionary<Incarnation, Absy/*!*/>/*!*/ incarnationOriginMap,
+ ProverContext/*!*/ context,
+ Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples)
+ {
+ Contract.Requires(b != null);
+ Contract.Requires(traceNodes != null);
+ Contract.Requires(trace != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
+ Contract.Requires(context != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(calleeCounterexamples));
+ // After translation, all potential errors come from asserts.
+
+ while (true)
+ {
+ List<Cmd> cmds = b.Cmds;
+ Contract.Assert(cmds != null);
+ TransferCmd transferCmd = cce.NonNull(b.TransferCmd);
+ for (int i = 0; i < cmds.Count; i++)
+ {
+ Cmd cmd = cce.NonNull(cmds[i]);
+
+ // Skip if 'cmd' not contained in the trace or not an assert
+ if (cmd is AssertCmd && traceNodes.Contains(cmd))
+ {
+ Counterexample newCounterexample = AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, mvInfo, context);
+ Contract.Assert(newCounterexample != null);
+ newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
+ return newCounterexample;
+ }
+ }
+
+ GotoCmd gotoCmd = transferCmd as GotoCmd;
+ if (gotoCmd == null) return null;
+ Block foundBlock = null;
+ foreach (Block bb in cce.NonNull(gotoCmd.labelTargets))
+ {
+ Contract.Assert(bb != null);
+ if (traceNodes.Contains(bb))
+ {
+ foundBlock = bb;
+ break;
+ }
+ }
+ if (foundBlock == null) return null;
+ trace.Add(foundBlock);
+ b = foundBlock;
+ }
+ }
+
+ public static Counterexample AssertCmdToCounterexample(AssertCmd cmd, TransferCmd transferCmd, List<Block> trace, Model errModel, ModelViewInfo mvInfo, ProverContext context)
+ {
+ Contract.Requires(cmd != null);
+ Contract.Requires(transferCmd != null);
+ Contract.Requires(trace != null);
+ Contract.Requires(context != null);
+ Contract.Ensures(Contract.Result<Counterexample>() != null);
+
+ List<string> relatedInformation = new List<string>();
+
+ // See if it is a special assert inserted in translation
+ if (cmd is AssertRequiresCmd)
+ {
+ AssertRequiresCmd assertCmd = (AssertRequiresCmd)cmd;
+ Contract.Assert(assertCmd != null);
+ CallCounterexample cc = new CallCounterexample(trace, assertCmd.Call, assertCmd.Requires, errModel, mvInfo, context, assertCmd.Checksum);
+ cc.relatedInformation = relatedInformation;
+ return cc;
+ }
+ else if (cmd is AssertEnsuresCmd)
+ {
+ AssertEnsuresCmd assertCmd = (AssertEnsuresCmd)cmd;
+ Contract.Assert(assertCmd != null);
+ ReturnCounterexample rc = new ReturnCounterexample(trace, transferCmd, assertCmd.Ensures, errModel, mvInfo, context, cmd.Checksum);
+ rc.relatedInformation = relatedInformation;
+ return rc;
+ }
+ else
+ {
+ AssertCounterexample ac = new AssertCounterexample(trace, (AssertCmd)cmd, errModel, mvInfo, context);
+ ac.relatedInformation = relatedInformation;
+ return ac;
+ }
+ }
+
+ /// <summary>
+ /// Returns a clone of "cex", but with the location stored in "cex" replaced by those from "assrt".
+ /// </summary>
+ public static Counterexample AssertCmdToCloneCounterexample(AssertCmd assrt, Counterexample cex) {
+ Contract.Requires(assrt != null);
+ Contract.Requires(cex != null);
+ Contract.Ensures(Contract.Result<Counterexample>() != null);
+
+ List<string> relatedInformation = new List<string>();
+
+ Counterexample cc;
+ if (assrt is AssertRequiresCmd) {
+ var aa = (AssertRequiresCmd)assrt;
+ cc = new CallCounterexample(cex.Trace, aa.Call, aa.Requires, cex.Model, cex.MvInfo, cex.Context, aa.Checksum);
+ } else if (assrt is AssertEnsuresCmd && cex is ReturnCounterexample) {
+ var aa = (AssertEnsuresCmd)assrt;
+ var oldCex = (ReturnCounterexample)cex;
+ cc = new ReturnCounterexample(cex.Trace, oldCex.FailingReturn, aa.Ensures, cex.Model, cex.MvInfo, cex.Context, aa.Checksum);
+ } else {
+ cc = new AssertCounterexample(cex.Trace, assrt, cex.Model, cex.MvInfo, cex.Context);
+ }
+ cc.relatedInformation = relatedInformation;
+ return cc;
+ }
+
+ static VCExpr LetVC(Block startBlock,
+ VCExpr controlFlowVariableExpr,
+ Dictionary<int, Absy> label2absy,
+ ProverContext proverCtxt,
+ out int assertionCount) {
+ Contract.Requires(startBlock != null);
+ Contract.Requires(proverCtxt != null);
+
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
+ List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
+ VCExpr startCorrect = LetVC(startBlock, controlFlowVariableExpr, label2absy, blockVariables, bindings, proverCtxt, out assertionCount);
+ return proverCtxt.ExprGen.Let(bindings, startCorrect);
+ }
+
+ static VCExpr LetVCIterative(List<Block> blocks,
+ VCExpr controlFlowVariableExpr,
+ Dictionary<int, Absy> label2absy,
+ ProverContext proverCtxt,
+ out int assertionCount,
+ bool isPositiveContext = true)
+ {
+ Contract.Requires(blocks != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ assertionCount = 0;
+
+ Graph<Block> dag = new Graph<Block>();
+ dag.AddSource(blocks[0]);
+ foreach (Block b in blocks) {
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+ if (gtc != null) {
+ Contract.Assume(gtc.labelTargets != null);
+ foreach (Block dest in gtc.labelTargets) {
+ Contract.Assert(dest != null);
+ dag.AddEdge(dest, b);
+ }
+ }
+ }
+ IEnumerable sortedNodes = dag.TopologicalSort();
+ Contract.Assert(sortedNodes != null);
+
+ Dictionary<Block, VCExprVar> blockVariables = new Dictionary<Block, VCExprVar>();
+ List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
+ VCExpressionGenerator gen = proverCtxt.ExprGen;
+ Contract.Assert(gen != null);
+ foreach (Block block in sortedNodes) {
+ VCExpr SuccCorrect;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd == null) {
+ ReturnExprCmd re = block.TransferCmd as ReturnExprCmd;
+ if (re == null) {
+ SuccCorrect = VCExpressionGenerator.True;
+ }
+ else {
+ SuccCorrect = proverCtxt.BoogieExprTranslator.Translate(re.Expr);
+ if (isPositiveContext)
+ {
+ SuccCorrect = gen.Not(SuccCorrect);
+ }
+ }
+ }
+ else {
+ Contract.Assert(gotocmd.labelTargets != null);
+ List<VCExpr> SuccCorrectVars = new List<VCExpr>(gotocmd.labelTargets.Count);
+ foreach (Block successor in gotocmd.labelTargets) {
+ Contract.Assert(successor != null);
+ VCExpr s = blockVariables[successor];
+ if (controlFlowVariableExpr != null) {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
+ VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
+ s = gen.Implies(controlTransferExpr, s);
+ }
+ SuccCorrectVars.Add(s);
+ }
+ SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr, isPositiveContext);
+ VCExpr vc = Wlp.Block(block, SuccCorrect, context);
+ assertionCount += context.AssertionCount;
+
+ VCExprVar v = gen.Variable(block.Label + "_correct", Bpl.Type.Bool);
+ bindings.Add(gen.LetBinding(v, vc));
+ blockVariables.Add(block, v);
+ }
+
+ return proverCtxt.ExprGen.Let(bindings, blockVariables[blocks[0]]);
+ }
+
+ static VCExpr LetVC(Block block,
+ VCExpr controlFlowVariableExpr,
+ Dictionary<int, Absy> label2absy,
+ Hashtable/*<Block, VCExprVar!>*/ blockVariables,
+ List<VCExprLetBinding/*!*/>/*!*/ bindings,
+ ProverContext proverCtxt,
+ out int assertionCount)
+ {
+ Contract.Requires(block != null);
+ Contract.Requires(blockVariables!= null);
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Requires(proverCtxt != null);
+
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ assertionCount = 0;
+
+ VCExpressionGenerator gen = proverCtxt.ExprGen;
+ Contract.Assert(gen != null);
+ VCExprVar v = (VCExprVar)blockVariables[block];
+ if (v == null) {
+ /*
+ * For block A (= block), generate:
+ * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct))
+ * with the side effect of adding the let bindings to "bindings" for any
+ * successor not yet visited.
+ */
+ VCExpr SuccCorrect;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd == null) {
+ ReturnExprCmd re = block.TransferCmd as ReturnExprCmd;
+ if (re == null) {
+ SuccCorrect = VCExpressionGenerator.True;
+ } else {
+ SuccCorrect = proverCtxt.BoogieExprTranslator.Translate(re.Expr);
+ }
+ } else {
+ Contract.Assert( gotocmd.labelTargets != null);
+ List<VCExpr> SuccCorrectVars = new List<VCExpr>(gotocmd.labelTargets.Count);
+ foreach (Block successor in gotocmd.labelTargets) {
+ Contract.Assert(successor != null);
+ int ac;
+ VCExpr s = LetVC(successor, controlFlowVariableExpr, label2absy, blockVariables, bindings, proverCtxt, out ac);
+ assertionCount += ac;
+ if (controlFlowVariableExpr != null)
+ {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
+ VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
+ s = gen.Implies(controlTransferExpr, s);
+ }
+ SuccCorrectVars.Add(s);
+ }
+ SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
+ }
+
+
+ VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
+ VCExpr vc = Wlp.Block(block, SuccCorrect, context);
+ assertionCount += context.AssertionCount;
+
+ v = gen.Variable(block.Label + "_correct", Bpl.Type.Bool);
+ bindings.Add(gen.LetBinding(v, vc));
+ blockVariables.Add(block, v);
+ }
+ return v;
+ }
+
+ static VCExpr DagVC(Block block,
+ VCExpr controlFlowVariableExpr,
+ Dictionary<int, Absy> label2absy,
+ Hashtable/*<Block, VCExpr!>*/ blockEquations,
+ ProverContext proverCtxt,
+ out int assertionCount)
+ {
+ Contract.Requires(block != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(blockEquations != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ assertionCount = 0;
+ VCExpressionGenerator gen = proverCtxt.ExprGen;
+ Contract.Assert(gen != null);
+ VCExpr vc = (VCExpr)blockEquations[block];
+ if (vc != null) {
+ return vc;
+ }
+
+ /*
+ * For block A (= block), generate:
+ * wp(A_body, (/\ S \in Successors(A) :: DagVC(S)))
+ */
+ VCExpr SuccCorrect = null;
+ GotoCmd gotocmd = block.TransferCmd as GotoCmd;
+ if (gotocmd != null)
+ {
+ foreach (Block successor in cce.NonNull(gotocmd.labelTargets)) {
+ Contract.Assert(successor != null);
+ int ac;
+ VCExpr c = DagVC(successor, controlFlowVariableExpr, label2absy, blockEquations, proverCtxt, out ac);
+ assertionCount += ac;
+ if (controlFlowVariableExpr != null) {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
+ VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
+ c = gen.Implies(controlTransferExpr, c);
+ }
+ SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
+ }
+ }
+ if (SuccCorrect == null) {
+ SuccCorrect = VCExpressionGenerator.True;
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
+ vc = Wlp.Block(block, SuccCorrect, context);
+ assertionCount += context.AssertionCount;
+
+ // gen.MarkAsSharedFormula(vc); PR: don't know yet what to do with this guy
+
+ blockEquations.Add(block, vc);
+ return vc;
+ }
+
+ static VCExpr FlatBlockVC(Implementation impl,
+ Dictionary<int, Absy> label2absy,
+ bool local, bool reach, bool doomed,
+ ProverContext proverCtxt,
+ out int assertionCount)
+ {
+ Contract.Requires(impl != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Requires( !local || !reach); // "reach" must be false for local
+
+ VCExpressionGenerator gen = proverCtxt.ExprGen;
+ Contract.Assert(gen != null);
+ Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
+ Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
+
+ List<Block> blocks = impl.Blocks;
+ Contract.Assert(blocks != null);
+ // block sorting is now done on the VCExpr
+ // if (!local && (cce.NonNull(CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
+ // blocks = SortBlocks(blocks);
+ // }
+
+ VCExpr proofObligation;
+ if (!local) {
+ proofObligation = cce.NonNull((VCExprVar)BlkCorrect[impl.Blocks[0]]);
+ } else {
+ List<VCExpr> conjuncts = new List<VCExpr>(blocks.Count);
+ foreach (Block b in blocks) {Contract.Assert(b != null);
+ VCExpr v = cce.NonNull((VCExprVar)BlkCorrect[b]);
+ conjuncts.Add(v);
+ }
+ proofObligation = gen.NAry(VCExpressionGenerator.AndOp, conjuncts);
+ }
+
+ VCContext context = new VCContext(label2absy, proverCtxt);
+ Contract.Assert(context != null);
+
+ List<VCExprLetBinding> programSemantics = new List<VCExprLetBinding>(blocks.Count);
+ foreach (Block b in blocks) {Contract.Assert(b != null);
+ /*
+ * In block mode,
+ * For a return block A, generate:
+ * A_correct <== wp(A_body, true) [post-condition has been translated into an assert]
+ * For all other blocks, generate:
+ * A_correct <== wp(A_body, (/\ S \in Successors(A) :: S_correct))
+ *
+ * In doomed mode, proceed as in block mode, except for a return block A, generate:
+ * A_correct <== wp(A_body, false) [post-condition has been translated into an assert]
+ *
+ * In block reach mode, the wp(A_body,...) in the equations above change to:
+ * A_reached ==> wp(A_body,...)
+ * and the conjunction above changes to:
+ * (/\ S \in Successors(A) :: S_correct \/ (\/ T \in Successors(A) && T != S :: T_reached))
+ *
+ * In local mode, generate:
+ * A_correct <== wp(A_body, true)
+ */
+ VCExpr SuccCorrect;
+ if (local) {
+ SuccCorrect = VCExpressionGenerator.True;
+ } else {
+ SuccCorrect = SuccessorsCorrect(b, BlkCorrect, BlkReached, doomed, gen);
+ }
+
+ VCExpr wlp = Wlp.Block(b, SuccCorrect, context);
+ if (BlkReached != null) {
+ wlp = gen.Implies(cce.NonNull((VCExprVar)BlkReached[b]), wlp);
+ }
+
+ VCExprVar okVar = cce.NonNull((VCExprVar)BlkCorrect[b]);
+ VCExprLetBinding binding = gen.LetBinding(okVar, wlp);
+ programSemantics.Add(binding);
+ }
+
+ assertionCount = context.AssertionCount;
+ return gen.Let(programSemantics, proofObligation);
+ }
+
+ private static Hashtable/* Block --> VCExprVar */ BlockVariableMap(List<Block/*!*/>/*!*/ blocks, string suffix,
+ Microsoft.Boogie.VCExpressionGenerator gen) {
+ Contract.Requires(cce.NonNullElements(blocks));
+ Contract.Requires(suffix != null);
+ Contract.Requires(gen != null);
+ Contract.Ensures(Contract.Result<Hashtable>() != null);
+
+ Hashtable/* Block --> VCExprVar */ map = new Hashtable/* Block --> (Let)Variable */();
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ VCExprVar v = gen.Variable(b.Label + suffix, Bpl.Type.Bool);
+ Contract.Assert(v != null);
+ map.Add(b, v);
+ }
+ return map;
+ }
+
+ private static VCExpr SuccessorsCorrect(
+ Block b,
+ Hashtable/* Block --> VCExprVar */ BlkCorrect,
+ Hashtable/* Block --> VCExprVar */ BlkReached,
+ bool doomed,
+ Microsoft.Boogie.VCExpressionGenerator gen) {
+ Contract.Requires(b != null);
+ Contract.Requires(BlkCorrect != null);
+ Contract.Requires(gen != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr SuccCorrect = null;
+ GotoCmd gotocmd = b.TransferCmd as GotoCmd;
+ if (gotocmd != null) {
+ foreach (Block successor in cce.NonNull(gotocmd.labelTargets)) {
+ Contract.Assert(successor != null);
+ // c := S_correct
+ VCExpr c = (VCExprVar)BlkCorrect[successor];
+ Contract.Assert(c != null);
+ if (BlkReached != null) {
+ // c := S_correct \/ Sibling0_reached \/ Sibling1_reached \/ ...;
+ foreach (Block successorSibling in gotocmd.labelTargets) {
+ Contract.Assert(successorSibling != null);
+ if (successorSibling != successor) {
+ c = gen.Or(c, cce.NonNull((VCExprVar)BlkReached[successorSibling]));
+ }
+ }
+ }
+ SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
+ }
+ }
+ if (SuccCorrect == null) {
+ return VCExpressionGenerator.True;
+ } else if (doomed) {
+ return VCExpressionGenerator.False;
+ } else {
+ return SuccCorrect;
+ }
+ }
+
+ static VCExpr NestedBlockVC(Implementation impl,
+ Dictionary<int, Absy> label2absy,
+ bool reach,
+ ProverContext proverCtxt,
+ out int assertionCount){
+ Contract.Requires(impl != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Requires( impl.Blocks.Count != 0);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpressionGenerator gen = proverCtxt.ExprGen;
+ Contract.Assert(gen != null);
+ Graph<Block> g = Program.GraphFromImpl(impl);
+
+ Hashtable/* Block --> VCExprVar */ BlkCorrect = BlockVariableMap(impl.Blocks, "_correct", gen);
+ Hashtable/* Block --> VCExprVar */ BlkReached = reach ? BlockVariableMap(impl.Blocks, "_reached", gen) : null;
+
+ Block startBlock = cce.NonNull( impl.Blocks[0]);
+ VCExpr proofObligation = (VCExprVar)BlkCorrect[startBlock];
+ Contract.Assert(proofObligation != null);
+ VCContext context = new VCContext(label2absy, proverCtxt);
+
+ Hashtable/*Block->int*/ totalOrder = new Hashtable/*Block->int*/();
+ {
+ List<Block> blocks = impl.Blocks;
+
+ // block sorting is now done on the VCExpr
+ // if (((!)CommandLineOptions.Clo.TheProverFactory).NeedsBlockSorting) {
+ // blocks = SortBlocks(blocks);
+ // }
+ int i = 0;
+ foreach (Block b in blocks) {
+ Contract.Assert(b != null);
+ totalOrder[b] = i;
+ i++;
+ }
+ }
+
+ VCExprLetBinding programSemantics = NestedBlockEquation(cce.NonNull(impl.Blocks[0]), BlkCorrect, BlkReached, totalOrder, context, g, gen);
+ List<VCExprLetBinding> ps = new List<VCExprLetBinding>(1);
+ ps.Add(programSemantics);
+
+ assertionCount = context.AssertionCount;
+ return gen.Let(ps, proofObligation);
+ }
+
+ private static VCExprLetBinding NestedBlockEquation(Block b,
+ Hashtable/*Block-->VCExprVar*/ BlkCorrect,
+ Hashtable/*Block-->VCExprVar*/ BlkReached,
+ Hashtable/*Block->int*/ totalOrder,
+ VCContext context,
+ Graph<Block> g,
+ Microsoft.Boogie.VCExpressionGenerator gen) {
+ Contract.Requires(b != null);
+ Contract.Requires(BlkCorrect != null);
+ Contract.Requires(totalOrder != null);
+ Contract.Requires(g != null);
+ Contract.Requires(context != null);
+
+ Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
+
+ /*
+ * For a block b, return:
+ * LET_BINDING b_correct = wp(b_body, X)
+ * where X is:
+ * LET (THOSE d \in DirectDominates(b) :: BlockEquation(d))
+ * IN (/\ s \in Successors(b) :: s_correct)
+ *
+ * When the VC-expression generator does not support LET expresions, this
+ * will eventually turn into:
+ * b_correct <== wp(b_body, X)
+ * where X is:
+ * (/\ s \in Successors(b) :: s_correct)
+ * <==
+ * (/\ d \in DirectDominatees(b) :: BlockEquation(d))
+ *
+ * In both cases above, if BlkReached is non-null, then the wp expression
+ * is instead:
+ * b_reached ==> wp(b_body, X)
+ */
+
+ VCExpr SuccCorrect = SuccessorsCorrect(b, BlkCorrect, null, false, gen);
+ Contract.Assert(SuccCorrect != null);
+
+ List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
+ foreach (Block dominee in GetSortedBlocksImmediatelyDominatedBy(g, b, totalOrder)) {
+ Contract.Assert(dominee != null);
+ VCExprLetBinding c = NestedBlockEquation(dominee, BlkCorrect, BlkReached, totalOrder, context, g, gen);
+ bindings.Add(c);
+ }
+
+ VCExpr X = gen.Let(bindings, SuccCorrect);
+ VCExpr wlp = Wlp.Block(b, X, context);
+ if (BlkReached != null) {
+ wlp = gen.Implies((VCExprVar)BlkReached[b], wlp);
+ Contract.Assert(wlp != null);
+ }
+ VCExprVar okVar = cce.NonNull((VCExprVar)BlkCorrect[b]);
+ return gen.LetBinding(okVar, wlp);
+ }
+
+ /// <summary>
+ /// Returns a list of g.ImmediatelyDominatedBy(b), but in a sorted order, hoping to steer around
+ /// the nondeterminism problems we've been seeing by using just this call.
+ /// </summary>
+ static List<Block/*!*/>/*!*/ GetSortedBlocksImmediatelyDominatedBy(Graph<Block>/*!*/ g, Block/*!*/ b, Hashtable/*Block->int*//*!*/ totalOrder) {
+ Contract.Requires(g != null);
+ Contract.Requires(b != null);
+ Contract.Requires(totalOrder != null);
+ Contract.Ensures(Contract.Result<List<Block>>() != null);
+
+ List<Block> list = new List<Block>();
+ foreach (Block dominee in g.ImmediatelyDominatedBy(b)) {
+ Contract.Assert(dominee != null);
+ list.Add(dominee);
+ }
+ list.Sort(new Comparison<Block>(delegate(Block x, Block y) {
+ return (int)cce.NonNull(totalOrder[x]) - (int)cce.NonNull(totalOrder[y]);
+ }));
+ return list;
+ }
+
+ static VCExpr VCViaStructuredProgram
+ (Implementation impl, Dictionary<int, Absy> label2absy,
+ ProverContext proverCtxt,
+ out int assertionCount)
+ {
+ Contract.Requires(impl != null);
+ Contract.Requires(label2absy != null);
+ Contract.Requires(proverCtxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ #region Convert block structure back to a "regular expression"
+ RE r = DAG2RE.Transform(cce.NonNull(impl.Blocks[0]));
+ Contract.Assert(r != null);
+ #endregion
+
+ VCContext ctxt = new VCContext(label2absy, proverCtxt);
+ Contract.Assert(ctxt != null);
+ #region Send wlp(program,true) to Simplify
+ var vcexp = Wlp.RegExpr(r, VCExpressionGenerator.True, ctxt);
+ assertionCount = ctxt.AssertionCount;
+ return vcexp;
+ #endregion
+ }
+
+ /// <summary>
+ /// Remove empty blocks reachable from the startBlock of the CFG
+ /// </summary>
+ static void RemoveEmptyBlocksIterative(List<Block> blocks) {
+ // postorder traversal of cfg
+ // noting loop heads in [keep] and
+ // generating token information in [renameInfo]
+ Block startBlock = blocks[0];
+ var postorder = new List<Block>();
+ var keep = new HashSet<Block>();
+ var visited = new HashSet<Block>();
+ var grey = new HashSet<Block>();
+ var stack = new Stack<Block>();
+ Dictionary<Block, Block> renameInfo = new Dictionary<Block, Block>();
+
+ stack.Push(startBlock);
+ visited.Add(startBlock);
+ while (stack.Count != 0) {
+ var curr = stack.Pop();
+ if (grey.Contains(curr)) {
+ postorder.Add(curr);
+
+ // generate renameInfoForStartBlock
+ GotoCmd gtc = curr.TransferCmd as GotoCmd;
+ renameInfo[curr] = null;
+ if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Count == 0) {
+ if (curr.Cmds.Count == 0 && curr.tok.IsValid) {
+ renameInfo[curr] = curr;
+ }
+ } else {
+ if (curr.Cmds.Count == 0 || curr == startBlock) {
+ if (curr.tok.IsValid) {
+ renameInfo[curr] = curr;
+ } else {
+ HashSet<Block> successorRenameInfo = new HashSet<Block>();
+ foreach (Block s in gtc.labelTargets) {
+ if (keep.Contains(s)) {
+ successorRenameInfo.Add(null);
+ } else {
+ successorRenameInfo.Add(renameInfo[s]);
+ }
+ }
+ if (successorRenameInfo.Count == 1) {
+ renameInfo[curr] = successorRenameInfo.Single();
+ }
+ }
+ }
+ }
+ // end generate renameInfoForStartBlock
+
+ } else {
+ grey.Add(curr);
+ stack.Push(curr);
+ GotoCmd gtc = curr.TransferCmd as GotoCmd;
+ if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Count == 0) continue;
+ foreach (Block s in gtc.labelTargets) {
+ if (!visited.Contains(s)) {
+ visited.Add(s);
+ stack.Push(s);
+ } else if (grey.Contains(s) && !postorder.Contains(s)) { // s is a loop head
+ keep.Add(s);
+ }
+ }
+ }
+ }
+ keep.Add(startBlock);
+
+ foreach (Block b in postorder) {
+ if (!keep.Contains(b) && b.Cmds.Count == 0) {
+ GotoCmd bGtc = b.TransferCmd as GotoCmd;
+ foreach (Block p in b.Predecessors) {
+ GotoCmd pGtc = p.TransferCmd as GotoCmd;
+ Contract.Assert(pGtc != null);
+ pGtc.labelTargets.Remove(b);
+ pGtc.labelNames.Remove(b.Label);
+ }
+ if (bGtc == null || bGtc.labelTargets == null || bGtc.labelTargets.Count == 0) {
+ continue;
+ }
+
+ List<Block> successors = bGtc.labelTargets;
+
+ // Try to push token information if possible
+ if (b.tok.IsValid && successors.Count == 1 && b != renameInfo[startBlock]) {
+ var s = successors.Single();
+ if (!s.tok.IsValid) {
+ foreach (Block p in s.Predecessors) {
+ if (p != b) {
+ GotoCmd pGtc = p.TransferCmd as GotoCmd;
+ Contract.Assert(pGtc != null);
+ pGtc.labelTargets.Remove(s);
+ pGtc.labelNames.Remove(s.Label);
+ pGtc.labelTargets.Add(s);
+ pGtc.labelNames.Add(b.Label);
+ }
+ }
+ s.tok = b.tok;
+ s.Label = b.Label;
+ }
+ }
+
+ foreach (Block p in b.Predecessors) {
+ GotoCmd pGtc = p.TransferCmd as GotoCmd;
+ Contract.Assert(pGtc != null);
+ foreach (Block s in successors) {
+ if (!pGtc.labelTargets.Contains(s)) {
+ pGtc.labelTargets.Add(s);
+ pGtc.labelNames.Add(s.Label);
+ }
+ }
+ }
+ }
+ }
+
+ if (!startBlock.tok.IsValid && startBlock.Cmds.All(c => c is AssumeCmd)) {
+ if (renameInfo[startBlock] != null) {
+ startBlock.tok = renameInfo[startBlock].tok;
+ startBlock.Label = renameInfo[startBlock].Label;
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Remove the empty blocks reachable from the block.
+ /// It changes the visiting state of the blocks, so that if you want to visit again the blocks, you have to reset them...
+ /// </summary>
+ static List<Block> RemoveEmptyBlocks(Block b) {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.Result<List<Block>>() != null);
+
+ Contract.Assert(b.TraversingStatus == Block.VisitState.ToVisit);
+ Block renameInfo;
+ List<Block> retVal = removeEmptyBlocksWorker(b, true, out renameInfo);
+ if (renameInfo != null && !b.tok.IsValid) {
+ bool onlyAssumes = true;
+ foreach (Cmd c in b.Cmds) {
+ if (!(c is AssumeCmd)) {
+ onlyAssumes = false;
+ break;
+ }
+ }
+ if (onlyAssumes) {
+ b.tok = renameInfo.tok;
+ b.Label = renameInfo.Label;
+ }
+ }
+ return retVal;
+ }
+
+ /// <summary>
+ /// For every not-yet-visited block n reachable from b, change n's successors to skip empty nodes.
+ /// Return the *set* of blocks reachable from b without passing through a nonempty block.
+ /// The target of any backedge is counted as a nonempty block.
+ /// If renameInfoForStartBlock is non-null, it denotes an empty block with location information, and that
+ /// information would be appropriate to display
+ /// </summary>
+ private static List<Block> removeEmptyBlocksWorker(Block b, bool startNode, out Block renameInfoForStartBlock)
+ {
+ Contract.Requires(b != null);
+ Contract.Ensures(Contract.ValueAtReturn(out renameInfoForStartBlock) == null || Contract.ValueAtReturn(out renameInfoForStartBlock).tok.IsValid);
+ // ensures: b in result ==> renameInfoForStartBlock == null;
+
+ renameInfoForStartBlock = null;
+ List<Block> bs = new List<Block>();
+ GotoCmd gtc = b.TransferCmd as GotoCmd;
+
+ // b has no successors
+ if (gtc == null || gtc.labelTargets == null || gtc.labelTargets.Count == 0)
+ {
+ if (b.Cmds.Count != 0){ // only empty blocks are removed...
+ bs.Add(b);
+ } else if (b.tok.IsValid) {
+ renameInfoForStartBlock = b;
+ }
+ return bs;
+ }
+ else if (b.TraversingStatus == Block.VisitState.ToVisit) // if b has some successors and we have not seen it so far...
+ {
+ b.TraversingStatus = Block.VisitState.BeingVisited;
+
+ // Before recursing down to successors, make a sobering observation:
+ // If b has no commands and is not the start node, then it will see
+ // extinction (because it will not be included in the "return setOfSuccessors"
+ // statement below). In that case, if b has a location, then the location
+ // information would be lost. Hence, make an attempt to save the location
+ // by pushing the location onto b's successor. This can be done if (0) b has
+ // exactly one successor, (1) that successor has no location of its own, and
+ // (2) that successor has no other predecessors.
+ if (b.Cmds.Count == 0 && !startNode) {
+ // b is about to become extinct; try to save its name and location, if possible
+ if (b.tok.IsValid && gtc.labelTargets.Count == 1) {
+ Block succ = cce.NonNull(gtc.labelTargets[0]);
+ if (!succ.tok.IsValid && succ.Predecessors.Count == 1) {
+ succ.tok = b.tok;
+ succ.Label = b.Label;
+ }
+ }
+ }
+
+ // recursively call this method on each successor
+ // merge result into a *set* of blocks
+ HashSet<Block> mergedSuccessors = new HashSet<Block>();
+ int m = 0; // in the following loop, set renameInfoForStartBlock to the value that all recursive calls agree on, if possible; otherwise, null
+ foreach (Block dest in gtc.labelTargets){Contract.Assert(dest != null);
+ Block renameInfo;
+ List<Block> ys = removeEmptyBlocksWorker(dest, false, out renameInfo);
+ Contract.Assert(ys != null);
+ if (m == 0) {
+ renameInfoForStartBlock = renameInfo;
+ } else if (renameInfoForStartBlock != renameInfo) {
+ renameInfoForStartBlock = null;
+ }
+ foreach (Block successor in ys){
+ if (!mergedSuccessors.Contains(successor))
+ mergedSuccessors.Add(successor);
+ }
+ m++;
+ }
+ b.TraversingStatus = Block.VisitState.AlreadyVisited;
+
+ List<Block> setOfSuccessors = new List<Block>();
+ foreach (Block d in mergedSuccessors)
+ setOfSuccessors.Add(d);
+ if (b.Cmds.Count == 0 && !startNode) {
+ // b is about to become extinct
+ if (b.tok.IsValid) {
+ renameInfoForStartBlock = b;
+ }
+ return setOfSuccessors;
+ }
+ // otherwise, update the list of successors of b to be the blocks in setOfSuccessors
+ gtc.labelTargets = setOfSuccessors;
+ gtc.labelNames = new List<String>();
+ foreach (Block d in setOfSuccessors){
+ Contract.Assert(d != null);
+ gtc.labelNames.Add(d.Label);}
+ if (!startNode) {
+ renameInfoForStartBlock = null;
+ }
+ return new List<Block> { b };
+ }
+ else // b has some successors, but we are already visiting it, or we have already visited it...
+ {
+ return new List<Block> { b };
+ }
+ }
+
+ static void DumpMap(Hashtable /*Variable->Expr*/ map) {
+ Contract.Requires(map != null);
+ foreach (DictionaryEntry de in map) {
+ Variable v = (Variable)de.Key;
+ Contract.Assert(v != null);
+ Expr e = (Expr)de.Value;
+ Contract.Assert(e != null);
+ Console.Write(" ");
+ v.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false), 0);
+ Console.Write(" --> ");
+ e.Emit(new TokenTextWriter("<console>", Console.Out, /*setTokens=*/ false, /*pretty=*/ false));
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/Source/VCGeneration/VCGeneration.csproj b/Source/VCGeneration/VCGeneration.csproj
index 74e1eef8..4d4fc374 100644
--- a/Source/VCGeneration/VCGeneration.csproj
+++ b/Source/VCGeneration/VCGeneration.csproj
@@ -1,230 +1,230 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>VCGeneration</RootNamespace>
- <AssemblyName>VCGeneration</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for VCGeneration.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\VCGeneration.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Check.cs" />
- <Compile Include="ConditionGeneration.cs" />
- <Compile Include="Context.cs" />
- <Compile Include="ExprExtensions.cs" />
- <Compile Include="FixedpointVC.cs" />
- <Compile Include="OrderingAxioms.cs" />
- <Compile Include="RPFP.cs" />
- <Compile Include="StratifiedVC.cs" />
- <Compile Include="VC.cs" />
- <Compile Include="..\version.cs" />
- <Compile Include="Wlp.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>VCGeneration</RootNamespace>
+ <AssemblyName>BoogieVCGeneration</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'">Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for VCGeneration.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\VCGeneration.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Check.cs" />
+ <Compile Include="ConditionGeneration.cs" />
+ <Compile Include="Context.cs" />
+ <Compile Include="ExprExtensions.cs" />
+ <Compile Include="FixedpointVC.cs" />
+ <Compile Include="OrderingAxioms.cs" />
+ <Compile Include="RPFP.cs" />
+ <Compile Include="StratifiedVC.cs" />
+ <Compile Include="VC.cs" />
+ <Compile Include="..\version.cs" />
+ <Compile Include="Wlp.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Graph\Graph.csproj">
+ <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
+ <Name>Graph</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Model\Model.csproj">
+ <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
+ <Name>Model</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\VCExpr\VCExpr.csproj">
+ <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
+ <Name>VCExpr</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
- -->
-</Project>
+ -->
+</Project> \ No newline at end of file
diff --git a/Source/VCGeneration/Wlp.cs b/Source/VCGeneration/Wlp.cs
index 45e511f0..cad5914b 100644
--- a/Source/VCGeneration/Wlp.cs
+++ b/Source/VCGeneration/Wlp.cs
@@ -1,244 +1,286 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using System.Diagnostics.Contracts;
-using System.Collections.Generic;
-using Microsoft.Basetypes;
-
-namespace VC {
- public class VCContext
- {
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Ctxt != null);
- }
-
- [Rep] public readonly Dictionary<int, Absy> Label2absy;
- [Rep] public readonly ProverContext Ctxt;
- public readonly VCExpr ControlFlowVariableExpr;
- public int AssertionCount; // counts the number of assertions for which Wlp has been computed
- public bool isPositiveContext;
-
- public VCContext(Dictionary<int, Absy> label2absy, ProverContext ctxt, bool isPositiveContext = true)
- {
- Contract.Requires(ctxt != null);
- this.Label2absy = label2absy;
- this.Ctxt = ctxt;
- this.isPositiveContext = isPositiveContext;
- }
-
- public VCContext(Dictionary<int, Absy> label2absy, ProverContext ctxt, VCExpr controlFlowVariableExpr, bool isPositiveContext = true)
- {
- Contract.Requires(ctxt != null);
- this.Label2absy = label2absy;
- this.Ctxt = ctxt;
- this.ControlFlowVariableExpr = controlFlowVariableExpr;
- this.isPositiveContext = isPositiveContext;
- }
- }
-
- #region A class to compute wlp of a passive command program
-
- public class Wlp
- {
- public static VCExpr Block(Block b, VCExpr N, VCContext ctxt)
- //modifies ctxt.*;
- {
- Contract.Requires(b != null);
- Contract.Requires(N != null);
- Contract.Requires(ctxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpressionGenerator gen = ctxt.Ctxt.ExprGen;
- Contract.Assert(gen != null);
-
- VCExpr res = N;
-
- for (int i = b.Cmds.Count; --i >= 0; )
- {
- res = Cmd(b, cce.NonNull( b.Cmds[i]), res, ctxt);
- }
-
- int id = b.UniqueId;
- if (ctxt.Label2absy != null) {
- ctxt.Label2absy[id] = b;
- }
-
- try {
- cce.BeginExpose(ctxt);
- if (ctxt.Label2absy == null) {
- return res;
- }
- else {
- return gen.Implies(gen.LabelPos(cce.NonNull(id.ToString()), VCExpressionGenerator.True), res);
- }
- } finally {
- cce.EndExpose();
- }
- }
-
- /// <summary>
- /// Computes the wlp for an assert or assume command "cmd".
- /// </summary>
- public static VCExpr Cmd(Block b, Cmd cmd, VCExpr N, VCContext ctxt) {
- Contract.Requires(cmd != null);
- Contract.Requires(N != null);
- Contract.Requires(ctxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpressionGenerator gen = ctxt.Ctxt.ExprGen;
- Contract.Assert(gen != null);
- if (cmd is AssertCmd) {
- AssertCmd ac = (AssertCmd)cmd;
-
- var isFullyVerified = false;
- if (ac.VerifiedUnder != null)
- {
- var litExpr = ac.VerifiedUnder as LiteralExpr;
- isFullyVerified = litExpr != null && litExpr.IsTrue;
- }
-
- if (!isFullyVerified)
- {
- ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext;
- }
-
- VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr);
-
- VCExpr VU = null;
- if (!isFullyVerified)
- {
- if (ac.VerifiedUnder != null)
- {
- VU = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.VerifiedUnder);
- }
- ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext;
- }
-
- VCExpr R = null;
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
- R = gen.Implies(C, N);
- } else {
- var subsumption = Subsumption(ac);
- if (subsumption == CommandLineOptions.SubsumptionOption.Always
- || (subsumption == CommandLineOptions.SubsumptionOption.NotForQuantifiers && !(C is VCExprQuantifier)))
- {
- N = gen.ImpliesSimp(C, N, false);
- }
-
- if (isFullyVerified)
- {
- return N;
- }
- else if (VU != null)
- {
- C = gen.OrSimp(VU, C);
- }
-
- int id = ac.UniqueId;
- if (ctxt.Label2absy != null)
- {
- ctxt.Label2absy[id] = ac;
- }
-
- ctxt.AssertionCount++;
-
- if (ctxt.ControlFlowVariableExpr == null) {
- Contract.Assert(ctxt.Label2absy != null);
- R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N);
- } else {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId)));
- Contract.Assert(controlFlowFunctionAppl != null);
- VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId)));
- if (ctxt.Label2absy == null) {
- R = gen.AndSimp(gen.Implies(assertFailure, C), N);
- } else {
- R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), gen.Implies(assertFailure, C)), N);
- }
- }
- }
- return R;
- } else if (cmd is AssumeCmd) {
- AssumeCmd ac = (AssumeCmd)cmd;
-
- if (CommandLineOptions.Clo.StratifiedInlining > 0) {
- // Label the assume if it is a procedure call
- NAryExpr naryExpr = ac.Expr as NAryExpr;
- if (naryExpr != null) {
- if (naryExpr.Fun is FunctionCall) {
- int id = ac.UniqueId;
- ctxt.Label2absy[id] = ac;
- return gen.ImpliesSimp(gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N);
- }
- }
- }
- return gen.ImpliesSimp(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N);
- } else {
- Console.WriteLine(cmd.ToString());
- Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command
- }
- }
-
- public static CommandLineOptions.SubsumptionOption Subsumption(AssertCmd ac) {
- Contract.Requires(ac != null);
- int n = QKeyValue.FindIntAttribute(ac.Attributes, "subsumption", -1);
- switch (n) {
- case 0: return CommandLineOptions.SubsumptionOption.Never;
- case 1: return CommandLineOptions.SubsumptionOption.NotForQuantifiers;
- case 2: return CommandLineOptions.SubsumptionOption.Always;
- default: return CommandLineOptions.Clo.UseSubsumption;
- }
- }
-
- public static VCExpr RegExpr(RE r, VCExpr N, VCContext ctxt)
- {
- Contract.Requires(r != null);
- Contract.Requires(N != null);
- Contract.Requires(ctxt != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if ( r is AtomicRE )
- {
- AtomicRE ar = (AtomicRE) r;
- return Block(ar.b, N, ctxt);
- }
- else if ( r is Sequential )
- {
- Sequential s = (Sequential) r;
- return RegExpr(s.first, RegExpr(s.second, N, ctxt), ctxt);
- }
- else if ( r is Choice )
- {
- Choice ch = (Choice) r;
- VCExpr res;
- if (ch.rs == null || ch.rs.Count==0)
- {
- res = N;
- }
- else
- {
- VCExpr currentWLP = RegExpr(cce.NonNull(ch.rs[0]), N, ctxt);
- for (int i = 1, n = ch.rs.Count; i < n; i++)
- {
- currentWLP = ctxt.Ctxt.ExprGen.And(currentWLP, RegExpr(cce.NonNull(ch.rs[i]), N, ctxt));
- }
- res = currentWLP;
- }
- return res;
- }
- else
- {
- Contract.Assert(false);throw new cce.UnreachableException(); // unexpected RE subtype
- }
- }
- }
- #endregion
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections;
+using Microsoft.Boogie;
+using Microsoft.Boogie.VCExprAST;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+using Microsoft.Basetypes;
+
+namespace VC {
+ public class VCContext
+ {
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(Ctxt != null);
+ }
+
+ [Rep] public readonly Dictionary<int, Absy> Label2absy;
+ [Rep] public readonly ProverContext Ctxt;
+ public readonly VCExpr ControlFlowVariableExpr;
+ public int AssertionCount; // counts the number of assertions for which Wlp has been computed
+ public bool isPositiveContext;
+
+ public VCContext(Dictionary<int, Absy> label2absy, ProverContext ctxt, bool isPositiveContext = true)
+ {
+ Contract.Requires(ctxt != null);
+ this.Label2absy = label2absy;
+ this.Ctxt = ctxt;
+ this.isPositiveContext = isPositiveContext;
+ }
+
+ public VCContext(Dictionary<int, Absy> label2absy, ProverContext ctxt, VCExpr controlFlowVariableExpr, bool isPositiveContext = true)
+ {
+ Contract.Requires(ctxt != null);
+ this.Label2absy = label2absy;
+ this.Ctxt = ctxt;
+ this.ControlFlowVariableExpr = controlFlowVariableExpr;
+ this.isPositiveContext = isPositiveContext;
+ }
+ }
+
+ #region A class to compute wlp of a passive command program
+
+ public class Wlp
+ {
+ public static VCExpr Block(Block b, VCExpr N, VCContext ctxt)
+ //modifies ctxt.*;
+ {
+ Contract.Requires(b != null);
+ Contract.Requires(N != null);
+ Contract.Requires(ctxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpressionGenerator gen = ctxt.Ctxt.ExprGen;
+ Contract.Assert(gen != null);
+
+ VCExpr res = N;
+
+ for (int i = b.Cmds.Count; --i >= 0; )
+ {
+ res = Cmd(b, cce.NonNull( b.Cmds[i]), res, ctxt);
+ }
+
+ int id = b.UniqueId;
+ if (ctxt.Label2absy != null) {
+ ctxt.Label2absy[id] = b;
+ }
+
+ try {
+ cce.BeginExpose(ctxt);
+ if (ctxt.Label2absy == null) {
+ return res;
+ }
+ else {
+ return gen.Implies(gen.LabelPos(cce.NonNull(id.ToString()), VCExpressionGenerator.True), res);
+ }
+ } finally {
+ cce.EndExpose();
+ }
+ }
+
+ /// <summary>
+ /// Computes the wlp for an assert or assume command "cmd".
+ /// </summary>
+ internal static VCExpr Cmd(Block b, Cmd cmd, VCExpr N, VCContext ctxt) {
+ Contract.Requires(cmd != null);
+ Contract.Requires(N != null);
+ Contract.Requires(ctxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpressionGenerator gen = ctxt.Ctxt.ExprGen;
+ Contract.Assert(gen != null);
+ if (cmd is AssertCmd) {
+ AssertCmd ac = (AssertCmd)cmd;
+
+ var isFullyVerified = false;
+ if (ac.VerifiedUnder != null)
+ {
+ var litExpr = ac.VerifiedUnder as LiteralExpr;
+ isFullyVerified = litExpr != null && litExpr.IsTrue;
+ }
+
+ if (!isFullyVerified)
+ {
+ ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext;
+ }
+
+ VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr);
+
+ VCExpr VU = null;
+ if (!isFullyVerified)
+ {
+ if (ac.VerifiedUnder != null)
+ {
+ VU = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.VerifiedUnder);
+
+ if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout)
+ {
+ ctxt.Ctxt.TimeoutDiagnosticIDToAssertion[ctxt.Ctxt.TimoutDiagnosticsCount] = new Tuple<AssertCmd,TransferCmd>(ac, b.TransferCmd);
+ VU = gen.Or(VU, gen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, gen.Integer(BigNum.FromInt(ctxt.Ctxt.TimoutDiagnosticsCount++))));
+ }
+ }
+ else if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout)
+ {
+ ctxt.Ctxt.TimeoutDiagnosticIDToAssertion[ctxt.Ctxt.TimoutDiagnosticsCount] = new Tuple<AssertCmd,TransferCmd>(ac, b.TransferCmd);
+ VU = gen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, gen.Integer(BigNum.FromInt(ctxt.Ctxt.TimoutDiagnosticsCount++)));
+ }
+ ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext;
+ }
+
+ VCExpr R = null;
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ R = gen.Implies(C, N);
+ } else {
+ var subsumption = Subsumption(ac);
+ if (subsumption == CommandLineOptions.SubsumptionOption.Always
+ || (subsumption == CommandLineOptions.SubsumptionOption.NotForQuantifiers && !(C is VCExprQuantifier)))
+ {
+ N = gen.ImpliesSimp(C, N, false);
+ }
+
+ if (isFullyVerified)
+ {
+ return N;
+ }
+ else if (VU != null)
+ {
+ C = gen.OrSimp(VU, C);
+ }
+
+ int id = ac.UniqueId;
+ if (ctxt.Label2absy != null)
+ {
+ ctxt.Label2absy[id] = ac;
+ }
+
+ ctxt.AssertionCount++;
+
+ if (ctxt.ControlFlowVariableExpr == null) {
+ Contract.Assert(ctxt.Label2absy != null);
+ R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N);
+ } else {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId)));
+ Contract.Assert(controlFlowFunctionAppl != null);
+ VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId)));
+ if (ctxt.Label2absy == null) {
+ R = gen.AndSimp(gen.Implies(assertFailure, C), N);
+ } else {
+ R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), gen.Implies(assertFailure, C)), N);
+ }
+ }
+ }
+ return R;
+ } else if (cmd is AssumeCmd) {
+ AssumeCmd ac = (AssumeCmd)cmd;
+
+ if (CommandLineOptions.Clo.StratifiedInlining > 0) {
+ // Label the assume if it is a procedure call
+ NAryExpr naryExpr = ac.Expr as NAryExpr;
+ if (naryExpr != null) {
+ if (naryExpr.Fun is FunctionCall) {
+ int id = ac.UniqueId;
+ ctxt.Label2absy[id] = ac;
+ return MaybeWrapWithOptimization(ctxt, gen, ac.Attributes, gen.ImpliesSimp(gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N));
+ }
+ }
+ }
+ var expr = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr);
+
+ var aid = QKeyValue.FindStringAttribute(ac.Attributes, "id");
+ if (aid != null)
+ {
+ var isTry = QKeyValue.FindBoolAttribute(ac.Attributes, "try");
+ var v = gen.Variable((isTry ? "try$$" : "assume$$") + aid, Microsoft.Boogie.Type.Bool);
+ expr = gen.Function(VCExpressionGenerator.NamedAssumeOp, v, gen.ImpliesSimp(v, expr));
+ }
+ var soft = QKeyValue.FindBoolAttribute(ac.Attributes, "soft");
+ var softWeight = QKeyValue.FindIntAttribute(ac.Attributes, "soft", 0);
+ if ((soft || 0 < softWeight) && aid != null)
+ {
+ var v = gen.Variable("soft$$" + aid, Microsoft.Boogie.Type.Bool);
+ expr = gen.Function(new VCExprSoftOp(Math.Max(softWeight, 1)), v, gen.ImpliesSimp(v, expr));
+ }
+ return MaybeWrapWithOptimization(ctxt, gen, ac.Attributes, gen.ImpliesSimp(expr, N));
+ } else {
+ Console.WriteLine(cmd.ToString());
+ Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command
+ }
+ }
+
+ private static VCExpr MaybeWrapWithOptimization(VCContext ctxt, VCExpressionGenerator gen, QKeyValue attrs, VCExpr expr)
+ {
+ var min = QKeyValue.FindExprAttribute(attrs, "minimize");
+ if (min != null)
+ {
+ expr = gen.Function(VCExpressionGenerator.MinimizeOp, ctxt.Ctxt.BoogieExprTranslator.Translate(min), expr);
+ }
+ var max = QKeyValue.FindExprAttribute(attrs, "maximize");
+ if (max != null)
+ {
+ expr = gen.Function(VCExpressionGenerator.MaximizeOp, ctxt.Ctxt.BoogieExprTranslator.Translate(max), expr);
+ }
+ return expr;
+ }
+
+ public static CommandLineOptions.SubsumptionOption Subsumption(AssertCmd ac) {
+ Contract.Requires(ac != null);
+ int n = QKeyValue.FindIntAttribute(ac.Attributes, "subsumption", -1);
+ switch (n) {
+ case 0: return CommandLineOptions.SubsumptionOption.Never;
+ case 1: return CommandLineOptions.SubsumptionOption.NotForQuantifiers;
+ case 2: return CommandLineOptions.SubsumptionOption.Always;
+ default: return CommandLineOptions.Clo.UseSubsumption;
+ }
+ }
+
+ public static VCExpr RegExpr(RE r, VCExpr N, VCContext ctxt)
+ {
+ Contract.Requires(r != null);
+ Contract.Requires(N != null);
+ Contract.Requires(ctxt != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if ( r is AtomicRE )
+ {
+ AtomicRE ar = (AtomicRE) r;
+ return Block(ar.b, N, ctxt);
+ }
+ else if ( r is Sequential )
+ {
+ Sequential s = (Sequential) r;
+ return RegExpr(s.first, RegExpr(s.second, N, ctxt), ctxt);
+ }
+ else if ( r is Choice )
+ {
+ Choice ch = (Choice) r;
+ VCExpr res;
+ if (ch.rs == null || ch.rs.Count==0)
+ {
+ res = N;
+ }
+ else
+ {
+ VCExpr currentWLP = RegExpr(cce.NonNull(ch.rs[0]), N, ctxt);
+ for (int i = 1, n = ch.rs.Count; i < n; i++)
+ {
+ currentWLP = ctxt.Ctxt.ExprGen.And(currentWLP, RegExpr(cce.NonNull(ch.rs[i]), N, ctxt));
+ }
+ res = currentWLP;
+ }
+ return res;
+ }
+ else
+ {
+ Contract.Assert(false);throw new cce.UnreachableException(); // unexpected RE subtype
+ }
+ }
+ }
+ #endregion
+
+}
diff --git a/Source/VCGeneration/cce.cs b/Source/VCGeneration/cce.cs
index 23d79815..42cabfcb 100644
--- a/Source/VCGeneration/cce.cs
+++ b/Source/VCGeneration/cce.cs
@@ -1,105 +1,105 @@
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-using Microsoft.Boogie;
-
- /// <summary>
- /// A class containing static methods to extend the functionality of Code Contracts
- /// </summary>
-
-public static class cce {
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && NonNullElements(collection.Keys) && NonNullElements(collection.Values);
- }
- [Pure]
- public static bool NonNullElements(VariableSeq collection) {
- return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- }
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
-
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
-}
-
-public class PeerAttribute : System.Attribute {
-}
-public class RepAttribute : System.Attribute {
-}
-public class CapturedAttribute : System.Attribute {
-}
-public class NotDelayedAttribute : System.Attribute {
-}
-public class NoDefaultContractAttribute : System.Attribute {
-}
-public class VerifyAttribute : System.Attribute {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : System.Attribute {
- }
-public class AdditiveAttribute : System.Attribute {
-}
-public class ReadsAttribute : System.Attribute {
- public enum Reads {
- Nothing,
- };
- public ReadsAttribute(object o) {
- }
-}
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+using Microsoft.Boogie;
+
+ /// <summary>
+ /// A class containing static methods to extend the functionality of Code Contracts
+ /// </summary>
+
+public static class cce {
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && NonNullElements(collection.Keys) && NonNullElements(collection.Values);
+ }
+ [Pure]
+ public static bool NonNullElements(VariableSeq collection) {
+ return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ }
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+}
+
+public class PeerAttribute : System.Attribute {
+}
+public class RepAttribute : System.Attribute {
+}
+public class CapturedAttribute : System.Attribute {
+}
+public class NotDelayedAttribute : System.Attribute {
+}
+public class NoDefaultContractAttribute : System.Attribute {
+}
+public class VerifyAttribute : System.Attribute {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : System.Attribute {
+ }
+public class AdditiveAttribute : System.Attribute {
+}
+public class ReadsAttribute : System.Attribute {
+ public enum Reads {
+ Nothing,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
diff --git a/Source/version.cs b/Source/version.cs
index b5d63a7f..1a41797f 100644
--- a/Source/version.cs
+++ b/Source/version.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
-// Version 2.3.0; year 2008+6, month 10, day 16
-[assembly: AssemblyVersion("2.3.0.61016")]
-[assembly: AssemblyFileVersion("2.3.0.61016")]
+using System.Reflection;
+// Version 2.3.0; year 2008+6, month 10, day 16
+[assembly: AssemblyVersion("2.3.0.61016")]
+[assembly: AssemblyFileVersion("2.3.0.61016")]
diff --git a/Source/version.ssc b/Source/version.ssc
deleted file mode 100644
index fd211b1c..00000000
--- a/Source/version.ssc
+++ /dev/null
@@ -1,12 +0,0 @@
-// ==++==
-//
-//
-//
-// ==--==
-// Warning: Automatically generated file. DO NOT EDIT
-// Generated at Dienstag, 5. Juli 2011 11:26:45
-
-using System.Reflection;
-[assembly: AssemblyVersion("2.2.30705.1126")]
-[assembly: AssemblyFileVersion("2.2.30705.1126")]
-