diff options
author | Marek Safar <marek.safar@gmail.com> | 2012-08-21 15:58:28 +0400 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2012-08-21 15:58:28 +0400 |
commit | 2097b533c65e51c81c225663b71f293c1f5efb07 (patch) | |
tree | 9c1fff10cd828f497b1ead6079b950ff7ad2b8a2 /mcs/class/Mono.CodeContracts | |
parent | 31e9b802013bd3a42d057513a11ad55550604eee (diff) |
Merge Alexander Chebaturkin SoC 2012 changes
During the Google Summer of Code, I was required to implement Interval Analysis for Code Contracts static verifier (cccheck tool). Please see information of changes at http://chebaturkin.blogspot.com/2012/08/code-contracts-static-verifier.html.
Diffstat (limited to 'mcs/class/Mono.CodeContracts')
174 files changed, 12821 insertions, 2861 deletions
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_0.csproj b/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_0.csproj index d58d47d2e46..981026d9d69 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_0.csproj +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_0.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?>
+<?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>
@@ -10,7 +10,7 @@ <NoWarn>1699</NoWarn>
<OutputPath>./../../class/lib/net_4_0</OutputPath>
<NoStdLib>true</NoStdLib>
-
+
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace></RootNamespace>
<AssemblyName>Mono.CodeContracts</AssemblyName>
@@ -38,327 +38,383 @@ </PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ItemGroup>
- <Compile Include="..\..\build\common\Consts.cs" /> - <Compile Include="Assembly\AssemblyInfo.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\AssemblyRef.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ConditionTextExtractor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ContractRequiresInfo.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ContractsRuntime.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\Decompile.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ExprGen.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\MethodInfo.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\PerformRewrite.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\Rewriter.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\RewriterOptions.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\RewriterResults.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\TransformContractsVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprAdd.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpArithmetic.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpComparison.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOp.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBlock.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBox.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCall.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareEqual.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareGreaterThan.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareLessThan.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprConv.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\Expr.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadArg.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadConstant.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprNop.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprReturn.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprSub.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprType.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\Sn.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\CompileVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\ExprVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\InstructionExtentVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\SourcePositionVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\AnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicAnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicMethodDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\CodeContractsAnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicAnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicMethodDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysisFixPoint.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodResult.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\FullExpressionDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\IFullExpressionDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\QueryVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsBinaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsInst.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsNull.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsUnaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForSizeOf.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForUnderlyingVariable.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForValueOf.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariable.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariablesIn.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\BinaryExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\ConstExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\Expr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\IsInstExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\NullExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\SizeOfExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\UnaryExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AnalysisDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AssumeDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExprDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionAnalysisFacade.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoderAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionPrinterFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ILDecoderAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ValueAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\AccessPathFilter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\IVisibilityCheck.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\MethodCallPathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\ParameterPathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElementBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement`1.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElementKind.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\AbstractDomainUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EdgeUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EliminateEdgeUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityPair.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\IMergeInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MergeInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdge.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdgeUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraphTerm.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\Update.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AbstractType.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AnalysisDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Domain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\FunctionsTable.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\HeapAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IAbstractDomainForEGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IConstantInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ISymGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\LabeledSymbol.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\MethodWrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ParameterWrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\StackToSymbolicAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymbolicValue.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymFunction.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymValue.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\TypeCache.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Wrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Analysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Domain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssertDischarger.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssumeDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullAnalysisFacade.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\APCMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\SequenceGenerator.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo`1.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayer.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayerFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\ICodeLayer.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\ILPrinter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\PrinterFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\CodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\DefaultNodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IAggregateVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ICodeConsumer.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IExpressionILVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IILVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ILVisitorBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IMethodCodeConsumer.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISymbolicExpressionVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISyntheticILVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeInspector.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ValueCodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\ArrayTypeNode.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\AssemblyNode.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\AssignmentStatement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BinaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BinaryOperator.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Block.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BlockExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BodyParser.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Branch.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\CatchFilter.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Class.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Construct.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\CoreSystemTypes.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\EndFinally.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Ensures.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\ExceptionHandler.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Expression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\ExpressionStatement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\FaultHandler.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Field.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Literal.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Local.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Member.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MemberBinding.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Method.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MethodCall.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MethodContract.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MethodContractElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Module.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\NaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Node.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\NodeType.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\OperatorExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Parameter.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Property.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Reference.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Requires.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Return.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Statement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\This.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\TypeNode.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\UnaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\UnaryOperator.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Variable.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractExtractor.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractNodes.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\GatherLocals.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\HelperMethods.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\RepresentationForAttribute.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\AssumeBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockWithLabels.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\CatchFilterEntryBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EnsuresBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryExitBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\LabelAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\MethodCallBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\NewObjCallBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockStartGatherer.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\EnsuresFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\RequiresFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SimpleSubroutineBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineWithHandlersBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\EnsuresSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultFinallySubroutineBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FinallySubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodContractSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldScanStateMachine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldValueSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\RequiresSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SimpleSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineFacade.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineWithHandlers.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\APC.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\APCDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\CFGBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\ContractFilteredCFG.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\ControlFlowGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\Edge.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTag.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTagExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\ICFG.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IConstantInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IHandlerFilter.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IMethodInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IStackInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\RemoveBranchDelegator.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\Subroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\SubroutineKind.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\DataFlowAnalysisBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeBasedWidening.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeConverter.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardDataFlowAnalysisBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IFixPointInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IWidenStrategy.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\Joiner.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\StepWidening.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\AbstractWorkList.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DecoratorHelper.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DepthFirst.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleDictionary.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleImmutableMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Dummy.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\EdgeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\GraphWrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableIntMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableSet.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IIndexable.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntKeyMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSet.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSetExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Indexable.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ITypedProperties.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IWorkList.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\LispList.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\LispListExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Optional.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Pair.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\PriorityQueue.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedKey.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedProperties.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\VisitStatus.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\WorkList.cs" /> - <Compile Include="Mono.CodeContracts.Static.Extensions\Extensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\EnvironmentDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\FlatDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\IAbstractDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\SetDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\CodeContractDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\CodeProviderImpl.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\ICodeProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IContractProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IILDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IMetaDataProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IMethodCodeProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\MetaDataProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\AssertionFinder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\BasicFacts.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpressionExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\ComposedFactQuery.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\ConstantPropagationFactQuery.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\IFactBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\IFactQuery.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\SimpleLogicInference.cs" /> - <Compile Include="Mono.CodeContracts.Static\CheckResults.cs" /> - <Compile Include="Mono.CodeContracts.Static\CheckOptions.cs" /> - <Compile Include="Mono.CodeContracts.Static\Checker.cs" /> - <Compile Include="Mono.CodeContracts.Static\DebugOptions.cs" /> - <Compile Include="Mono.CodeContracts.Static\ProofOutcome.cs" /> - <Compile Include="Mono.CodeContracts.Static\ProofOutcomeExtensions.cs" /> -
+ <Compile Include="..\..\build\common\Consts.cs" />
+ <Compile Include="Assembly\AssemblyInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\AssemblyRef.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ConditionTextExtractor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ContractRequiresInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ContractsRuntime.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\Decompile.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ExprGen.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\MethodInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\PerformRewrite.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\Rewriter.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\RewriterOptions.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\RewriterResults.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\TransformContractsVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprAdd.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpArithmetic.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpComparison.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOp.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBox.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCall.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareEqual.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareGreaterThan.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareLessThan.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprConv.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\Expr.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadArg.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadConstant.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprNop.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprReturn.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprSub.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprType.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\Sn.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\CompileVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\ExprVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\InstructionExtentVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\SourcePositionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\AnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicAnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicMethodDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\CodeContractsAnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicAnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicMethodDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysisFixPoint.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodResult.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\FullExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\IFullExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\QueryVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsBinaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsInst.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsNull.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsUnaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForSizeOf.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForUnderlyingVariable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForValueOf.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariablesIn.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\BinaryExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\ConstExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\Expr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\IsInstExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\NullExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\SizeOfExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\UnaryExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AnalysisDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AssumeDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExprDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionAnalysisFacade.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoderAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionPrinterFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ILDecoderAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ValueAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\AccessPathFilter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\IVisibilityCheck.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\MethodCallPathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\ParameterPathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElementBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement`1.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElementKind.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\AbstractDomainUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EdgeUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EliminateEdgeUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityPair.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\IMergeInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MergeInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdge.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdgeUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraphTerm.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\Update.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AbstractType.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AnalysisDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Domain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\FunctionsTable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\HeapAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IAbstractDomainForEGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IConstantInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ISymGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\LabeledSymbol.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\MethodWrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ParameterWrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\StackToSymbolicAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymbolicValue.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymFunction.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymValue.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\TypeCache.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Wrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Analysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssertDischarger.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssumeDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullAnalysisFacade.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\AbstractInterpretationException.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysers.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.GenericValueAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.ConstantEvaluator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.GenericNumericalAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\BoxedExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\BoxedExpressionEncoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\BoxedVariable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Counter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisInterval.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisIntervalAssumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisIntervalContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ConstToIntervalEvaluator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisIntervalEnvironment.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\EvaluateExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ExpressionType.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\GetThresholdVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IExpressionEncoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IIntervalEnvironment.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalContextBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalEnvironment.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalInference.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalRationalAssumerBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalRationalContextBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumeFalseVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumeTrueVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumerBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\LongToIntegerConstantEvaluator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\EvaluateArithmeticWithOverflow.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ExpressionOperator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ExpressionViaStringComparer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ConstantEvaluatorVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\GenericExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\GenericTypeExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IEnvironmentDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Interval.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalEnvironmentBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Monomial.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ObjectExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Polynomial.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Rational.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\AssumeFalseVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\AssumeTrueVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\RationalThreshold.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Threshold.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\TresholdDB.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ValueExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\APCMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\SequenceGenerator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo`1.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayerFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\ICodeLayer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\ILPrinter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\PrinterFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\CodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\DefaultNodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IAggregateVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ICodeConsumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IExpressionILVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IILVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ILVisitorBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IMethodCodeConsumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISymbolicExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISyntheticILVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeInspector.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ValueCodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\ArrayTypeNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\AssemblyNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\AssignmentStatement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BinaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BinaryOperator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Block.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BlockExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BodyParser.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Branch.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\CatchFilter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Class.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Construct.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\CoreSystemTypes.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\EndFinally.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Ensures.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\ExceptionHandler.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Expression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\ExpressionStatement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\FaultHandler.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Field.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Literal.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Local.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Member.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MemberBinding.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Method.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MethodCall.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MethodContract.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MethodContractElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Module.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\NaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Node.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\NodeType.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\OperatorExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Parameter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Property.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Reference.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Requires.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Return.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Statement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\This.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\TypeNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\UnaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\UnaryOperator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Variable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractExtractor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractNodes.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\GatherLocals.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\HelperMethods.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\RepresentationForAttribute.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\AssumeBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockWithLabels.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\CatchFilterEntryBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EnsuresBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryExitBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\LabelAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\MethodCallBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\NewObjCallBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockStartGatherer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\EnsuresFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\RequiresFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SimpleSubroutineBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineWithHandlersBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\EnsuresSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultFinallySubroutineBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FinallySubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodContractSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldScanStateMachine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldValueSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\RequiresSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SimpleSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineFacade.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineWithHandlers.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\APC.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\APCDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\CFGBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\ContractFilteredCFG.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\ControlFlowGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\Edge.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTag.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTagExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\ICFG.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IConstantInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IHandlerFilter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IMethodInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IStackInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\RemoveBranchDelegator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\Subroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\SubroutineKind.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\DataFlowAnalysisBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeBasedWidening.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeConverter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardDataFlowAnalysisBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IFixPointInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IWidenStrategy.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\Joiner.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\StepWidening.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\BranchNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\EmptyNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\LeafNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\PatriciaTrieNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\AbstractWorkList.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\BooleanExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DecoratorHelper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DepthFirst.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleDictionary.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleImmutableMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Dummy.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\EdgeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\GraphWrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableIntMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableSet.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IIndexable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntKeyMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSet.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSetExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Indexable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IPropertyCollection.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IWorkList.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Sequence.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\SequenceExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Optional.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Pair.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\PriorityQueue.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedKey.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\PropertyCollection.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\VisitStatus.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\WorkList.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Extensions\Extensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\AbstractDomainExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\EnvironmentDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\FlatDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\IAbstractDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\SetDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\CodeContractDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\CodeProviderImpl.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\ICodeProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IContractProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IILDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IMetaDataProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IMethodCodeProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\MetaDataProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\AssertionFinder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\BasicFacts.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpressionExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\ComposedFactQuery.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\ConstantPropagationFactQuery.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\IFactBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\IFactQuery.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\SimpleLogicInference.cs" />
+ <Compile Include="Mono.CodeContracts.Static\CheckResults.cs" />
+ <Compile Include="Mono.CodeContracts.Static\CheckOptions.cs" />
+ <Compile Include="Mono.CodeContracts.Static\Checker.cs" />
+ <Compile Include="Mono.CodeContracts.Static\DebugOptions.cs" />
+ <Compile Include="Mono.CodeContracts.Static\ProofOutcome.cs" />
</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.
@@ -371,31 +427,30 @@ <PreBuildEvent></PreBuildEvent>
</PropertyGroup>
<ItemGroup>
- <Reference Include="mscorlib.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>mscorlib.dll</HintPath> - </Reference> - <Reference Include="System"> - <SpecificVersion>False</SpecificVersion> - <HintPath>System</HintPath> - </Reference> - <Reference Include="System.Core"> - <SpecificVersion>False</SpecificVersion> - <HintPath>System.Core</HintPath> - </Reference> - <Reference Include="Mono.Cecil.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>Mono.Cecil.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil.Mdb.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>Mono.Cecil.Mdb.dll</HintPath> - </Reference> + <Reference Include="mscorlib.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="System">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>System</HintPath>
+ </Reference>
+ <Reference Include="System.Core">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>System.Core</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>Mono.Cecil.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Mdb.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>Mono.Cecil.Mdb.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
-
+
</Project>
- diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_5.csproj b/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_5.csproj index 98fd6142931..6fe85ab37cd 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_5.csproj +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_5.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?>
+<?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>
@@ -10,7 +10,7 @@ <NoWarn>1699</NoWarn>
<OutputPath>./../../class/lib/net_4_5</OutputPath>
<NoStdLib>true</NoStdLib>
-
+
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace></RootNamespace>
<AssemblyName>Mono.CodeContracts</AssemblyName>
@@ -42,327 +42,383 @@ </PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ItemGroup>
- <Compile Include="..\..\build\common\Consts.cs" /> - <Compile Include="Assembly\AssemblyInfo.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\AssemblyRef.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ConditionTextExtractor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ContractRequiresInfo.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ContractsRuntime.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\Decompile.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\ExprGen.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\MethodInfo.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\PerformRewrite.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\Rewriter.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\RewriterOptions.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\RewriterResults.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite\TransformContractsVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprAdd.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpArithmetic.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpComparison.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOp.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBlock.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBox.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCall.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareEqual.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareGreaterThan.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareLessThan.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprConv.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\Expr.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadArg.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadConstant.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprNop.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprReturn.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprSub.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprType.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.Ast\Sn.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\CompileVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\ExprVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\InstructionExtentVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\SourcePositionVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\AnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicAnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicMethodDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\CodeContractsAnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicAnalysisDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicMethodDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysisFixPoint.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodDriver.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodResult.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\FullExpressionDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\IFullExpressionDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\QueryVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsBinaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsInst.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsNull.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsUnaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForSizeOf.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForUnderlyingVariable.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForValueOf.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariable.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariablesIn.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\BinaryExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\ConstExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\Expr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\IsInstExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\NullExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\SizeOfExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\UnaryExpr.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AnalysisDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AssumeDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExprDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionAnalysisFacade.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoderAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionPrinterFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ILDecoderAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ValueAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\AccessPathFilter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\IVisibilityCheck.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\MethodCallPathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\ParameterPathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElementBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement`1.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElementKind.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\AbstractDomainUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EdgeUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EliminateEdgeUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityPair.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\IMergeInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MergeInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdge.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdgeUpdate.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraphTerm.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\Update.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AbstractType.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AnalysisDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Domain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\FunctionsTable.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\HeapAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IAbstractDomainForEGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IConstantInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ISymGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\LabeledSymbol.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\MethodWrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ParameterWrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\StackToSymbolicAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymbolicValue.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymFunction.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymValue.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\TypeCache.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Wrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Analysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Domain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssertDischarger.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssumeDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullAnalysisFacade.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\APCMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\SequenceGenerator.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo`1.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayer.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayerFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\ICodeLayer.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\ILPrinter.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContext.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContextProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Analysis\PrinterFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\CodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\DefaultNodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IAggregateVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ICodeConsumer.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IExpressionILVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IILVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ILVisitorBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IMethodCodeConsumer.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISymbolicExpressionVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISyntheticILVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeInspector.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ValueCodeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\ArrayTypeNode.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\AssemblyNode.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\AssignmentStatement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BinaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BinaryOperator.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Block.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BlockExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\BodyParser.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Branch.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\CatchFilter.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Class.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Construct.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\CoreSystemTypes.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\EndFinally.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Ensures.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\ExceptionHandler.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Expression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\ExpressionStatement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\FaultHandler.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Field.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Literal.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Local.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Member.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MemberBinding.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Method.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MethodCall.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MethodContract.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\MethodContractElement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Module.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\NaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Node.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\NodeType.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\OperatorExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Parameter.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Property.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Reference.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Requires.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Return.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Statement.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\This.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\TypeNode.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\UnaryExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\UnaryOperator.cs" /> - <Compile Include="Mono.CodeContracts.Static.AST\Variable.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractExtractor.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractNodes.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\GatherLocals.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\HelperMethods.cs" /> - <Compile Include="Mono.CodeContracts.Static.ContractExtraction\RepresentationForAttribute.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\AssumeBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockWithLabels.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\CatchFilterEntryBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EnsuresBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryExitBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\LabelAdapter.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\MethodCallBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\NewObjCallBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockStartGatherer.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\EnsuresFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\RequiresFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SimpleSubroutineBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineFactory.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineWithHandlersBuilder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\EnsuresSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultFinallySubroutineBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FinallySubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodContractSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldScanStateMachine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldValueSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\RequiresSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SimpleSubroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineFacade.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineWithHandlers.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\APC.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\APCDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\CFGBlock.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\ContractFilteredCFG.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\ControlFlowGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\Edge.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTag.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTagExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\ICFG.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IConstantInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IHandlerFilter.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IMethodInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\IStackInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\RemoveBranchDelegator.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\Subroutine.cs" /> - <Compile Include="Mono.CodeContracts.Static.ControlFlow\SubroutineKind.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\DataFlowAnalysisBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeBasedWidening.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeConverter.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardDataFlowAnalysisBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IAnalysis.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IFixPointInfo.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IWidenStrategy.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\Joiner.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\StepWidening.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\AbstractWorkList.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DecoratorHelper.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DepthFirst.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleDictionary.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleImmutableMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Dummy.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\EdgeVisitor.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\GraphWrapper.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IGraph.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableIntMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableSet.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IIndexable.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntKeyMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableMap.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSet.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSetExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Indexable.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\ITypedProperties.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\IWorkList.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\LispList.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\LispListExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Optional.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\Pair.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\PriorityQueue.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedKey.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedProperties.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\VisitStatus.cs" /> - <Compile Include="Mono.CodeContracts.Static.DataStructures\WorkList.cs" /> - <Compile Include="Mono.CodeContracts.Static.Extensions\Extensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\EnvironmentDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\FlatDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\IAbstractDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Lattices\SetDomain.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\CodeContractDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\CodeProviderImpl.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\ICodeProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IContractProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IILDecoder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IMetaDataProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\IMethodCodeProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Providers\MetaDataProvider.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\AssertionFinder.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\BasicFacts.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpression.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpressionExtensions.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\ComposedFactQuery.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\ConstantPropagationFactQuery.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\IFactBase.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\IFactQuery.cs" /> - <Compile Include="Mono.CodeContracts.Static.Proving\SimpleLogicInference.cs" /> - <Compile Include="Mono.CodeContracts.Static\CheckResults.cs" /> - <Compile Include="Mono.CodeContracts.Static\CheckOptions.cs" /> - <Compile Include="Mono.CodeContracts.Static\Checker.cs" /> - <Compile Include="Mono.CodeContracts.Static\DebugOptions.cs" /> - <Compile Include="Mono.CodeContracts.Static\ProofOutcome.cs" /> - <Compile Include="Mono.CodeContracts.Static\ProofOutcomeExtensions.cs" /> -
+ <Compile Include="..\..\build\common\Consts.cs" />
+ <Compile Include="Assembly\AssemblyInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\AssemblyRef.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ConditionTextExtractor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ContractRequiresInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ContractsRuntime.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\Decompile.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\ExprGen.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\MethodInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\PerformRewrite.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\Rewriter.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\RewriterOptions.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\RewriterResults.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite\TransformContractsVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprAdd.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpArithmetic.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpComparison.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOp.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBox.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCall.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareEqual.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareGreaterThan.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareLessThan.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprConv.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\Expr.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadArg.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadConstant.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprNop.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprReturn.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprSub.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprType.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.Ast\Sn.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\CompileVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\ExprVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\InstructionExtentVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\SourcePositionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\AnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicAnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicMethodDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\CodeContractsAnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicAnalysisDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicMethodDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysisFixPoint.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodDriver.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodResult.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\FullExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\IFullExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\QueryVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsBinaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsInst.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsNull.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsUnaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForSizeOf.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForUnderlyingVariable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForValueOf.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariablesIn.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\BinaryExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\ConstExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\Expr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\IsInstExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\NullExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\SizeOfExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\UnaryExpr.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AnalysisDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AssumeDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExprDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionAnalysisFacade.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoderAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionPrinterFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ILDecoderAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ValueAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\AccessPathFilter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\IVisibilityCheck.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\MethodCallPathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\ParameterPathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElementBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement`1.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElementKind.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\AbstractDomainUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EdgeUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EliminateEdgeUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityPair.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\IMergeInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MergeInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdge.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdgeUpdate.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraphTerm.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\Update.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AbstractType.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AnalysisDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Domain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\FunctionsTable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\HeapAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IAbstractDomainForEGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IConstantInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ISymGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\LabeledSymbol.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\MethodWrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ParameterWrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\StackToSymbolicAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymbolicValue.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymFunction.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymValue.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\TypeCache.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Wrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Analysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssertDischarger.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssumeDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullAnalysisFacade.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\AbstractInterpretationException.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysers.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.GenericValueAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.ConstantEvaluator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Analysis.GenericNumericalAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\BoxedExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\BoxedExpressionEncoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\BoxedVariable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Counter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisInterval.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisIntervalAssumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisIntervalContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ConstToIntervalEvaluator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\DisIntervalEnvironment.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\EvaluateExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ExpressionType.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\GetThresholdVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IExpressionEncoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IIntervalEnvironment.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalContextBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalEnvironment.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalInference.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalRationalAssumerBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalRationalContextBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumeFalseVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumeTrueVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalAssumerBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\LongToIntegerConstantEvaluator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\EvaluateArithmeticWithOverflow.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ExpressionOperator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ExpressionViaStringComparer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ConstantEvaluatorVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\GenericExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\GenericTypeExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IEnvironmentDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Interval.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\IntervalEnvironmentBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Monomial.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ObjectExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Polynomial.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Rational.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\AssumeFalseVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\AssumeTrueVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\RationalThreshold.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\Threshold.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\TresholdDB.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.Numerical\ValueExpressionDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\APCMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\SequenceGenerator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo`1.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayerFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\ICodeLayer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\ILPrinter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContext.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContextProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Analysis\PrinterFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\CodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\DefaultNodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IAggregateVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ICodeConsumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IExpressionILVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IILVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ILVisitorBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IMethodCodeConsumer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISymbolicExpressionVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISyntheticILVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeInspector.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ValueCodeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\ArrayTypeNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\AssemblyNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\AssignmentStatement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BinaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BinaryOperator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Block.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BlockExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\BodyParser.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Branch.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\CatchFilter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Class.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Construct.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\CoreSystemTypes.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\EndFinally.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Ensures.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\ExceptionHandler.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Expression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\ExpressionStatement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\FaultHandler.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Field.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Literal.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Local.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Member.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MemberBinding.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Method.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MethodCall.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MethodContract.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\MethodContractElement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Module.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\NaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Node.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\NodeType.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\OperatorExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Parameter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Property.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Reference.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Requires.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Return.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Statement.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\This.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\TypeNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\UnaryExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\UnaryOperator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.AST\Variable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractExtractor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractNodes.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\GatherLocals.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\HelperMethods.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ContractExtraction\RepresentationForAttribute.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\AssumeBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockWithLabels.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\CatchFilterEntryBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EnsuresBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryExitBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\LabelAdapter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\MethodCallBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\NewObjCallBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockStartGatherer.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\EnsuresFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\RequiresFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SimpleSubroutineBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineFactory.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineWithHandlersBuilder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\EnsuresSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultFinallySubroutineBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FinallySubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodContractSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldScanStateMachine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldValueSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\RequiresSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SimpleSubroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineFacade.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineWithHandlers.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\APC.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\APCDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\CFGBlock.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\ContractFilteredCFG.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\ControlFlowGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\Edge.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTag.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTagExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\ICFG.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IConstantInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IHandlerFilter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IMethodInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\IStackInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\RemoveBranchDelegator.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\Subroutine.cs" />
+ <Compile Include="Mono.CodeContracts.Static.ControlFlow\SubroutineKind.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\DataFlowAnalysisBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeBasedWidening.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeConverter.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardDataFlowAnalysisBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IAnalysis.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IFixPointInfo.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IWidenStrategy.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\Joiner.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\StepWidening.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\BranchNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\EmptyNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\LeafNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures.Patricia\PatriciaTrieNode.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\AbstractWorkList.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\BooleanExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DecoratorHelper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DepthFirst.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleDictionary.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleImmutableMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Dummy.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\EdgeVisitor.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\GraphWrapper.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IGraph.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableIntMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableSet.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IIndexable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntKeyMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableMap.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSet.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSetExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Indexable.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IPropertyCollection.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\IWorkList.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Sequence.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\SequenceExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Optional.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\Pair.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\PriorityQueue.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedKey.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\PropertyCollection.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\VisitStatus.cs" />
+ <Compile Include="Mono.CodeContracts.Static.DataStructures\WorkList.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Extensions\Extensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\AbstractDomainExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\EnvironmentDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\FlatDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\IAbstractDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Lattices\SetDomain.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\CodeContractDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\CodeProviderImpl.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\ICodeProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IContractProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IILDecoder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IMetaDataProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\IMethodCodeProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Providers\MetaDataProvider.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\AssertionFinder.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\BasicFacts.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpression.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpressionExtensions.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\ComposedFactQuery.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\ConstantPropagationFactQuery.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\IFactBase.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\IFactQuery.cs" />
+ <Compile Include="Mono.CodeContracts.Static.Proving\SimpleLogicInference.cs" />
+ <Compile Include="Mono.CodeContracts.Static\CheckResults.cs" />
+ <Compile Include="Mono.CodeContracts.Static\CheckOptions.cs" />
+ <Compile Include="Mono.CodeContracts.Static\Checker.cs" />
+ <Compile Include="Mono.CodeContracts.Static\DebugOptions.cs" />
+ <Compile Include="Mono.CodeContracts.Static\ProofOutcome.cs" />
</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.
@@ -375,31 +431,30 @@ <PreBuildEvent></PreBuildEvent>
</PropertyGroup>
<ItemGroup>
- <Reference Include="mscorlib.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>mscorlib.dll</HintPath> - </Reference> - <Reference Include="System.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>System.dll</HintPath> - </Reference> - <Reference Include="System.Core.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>System.Core.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>Mono.Cecil.dll</HintPath> - </Reference> - <Reference Include="Mono.Cecil.Mdb.dll"> - <SpecificVersion>False</SpecificVersion> - <HintPath>Mono.Cecil.Mdb.dll</HintPath> - </Reference> + <Reference Include="mscorlib.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="System.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>System.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Core.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>System.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>Mono.Cecil.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Mdb.dll">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>Mono.Cecil.Mdb.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
-
+
</Project>
- diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/Rewriter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/Rewriter.cs index 15a353c19da..36d6822f611 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/Rewriter.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Rewrite/Rewriter.cs @@ -33,7 +33,6 @@ using System.Text; using Mono.Cecil.Cil; using Mono.Cecil; using System.IO; -using Mono.CompilerServices.SymbolWriter; namespace Mono.CodeContracts.Rewrite { public class Rewriter { @@ -52,8 +51,6 @@ namespace Mono.CodeContracts.Rewrite { private RewriterOptions options; private List<string> warnings = new List<string> (); private List<string> errors = new List<string> (); - private bool usingMdb = false; - private bool usingPdb = false; private RewriterResults RewriteImpl () { diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/CodeVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/CodeVisitor.cs index efd7c4c2939..f6b702aace3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/CodeVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/CodeVisitor.cs @@ -1,3 +1,31 @@ +// +// CodeVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using System.IO; using Mono.CodeContracts.Static.Analysis; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/DefaultNodeVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/DefaultNodeVisitor.cs index 133fb576c07..44abdc46e2a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/DefaultNodeVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/DefaultNodeVisitor.cs @@ -170,8 +170,8 @@ namespace Mono.CodeContracts.Static.AST.Visitors { if (node == null) return node; - node.Operand1 = VisitExpression (node.Operand1); - node.Operand2 = VisitExpression (node.Operand2); + node.Left = VisitExpression (node.Left); + node.Right = VisitExpression (node.Right); return node; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IILVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IILVisitor.cs index dfbbc0c8a77..a7be66009dd 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IILVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IILVisitor.cs @@ -30,73 +30,73 @@ using System.Collections.Generic; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.AST.Visitors { - interface IILVisitor<Label, Source, Dest, Data, Result> : - IExpressionILVisitor<Label, Source, Dest, Data, Result>, - ISyntheticILVisitor<Label, Source, Dest, Data, Result> { - Result Arglist (Label pc, Dest dest, Data data); - Result Branch (Label pc, Label target, bool leavesExceptionBlock, Data data); - Result BranchCond (Label pc, Label target, BranchOperator bop, Source value1, Source value2, Data data); - Result BranchTrue (Label pc, Label target, Source cond, Data data); - Result BranchFalse (Label pc, Label target, Source cond, Data data); - Result Break (Label pc, Data data); + interface IILVisitor<TLabel, TSource, TDest, TData, TResult> : + IExpressionILVisitor<TLabel, TSource, TDest, TData, TResult>, + ISyntheticILVisitor<TLabel, TSource, TDest, TData, TResult> { + TResult Arglist (TLabel pc, TDest dest, TData data); + TResult Branch (TLabel pc, TLabel target, bool leavesExceptionBlock, TData data); + TResult BranchCond (TLabel pc, TLabel target, BranchOperator bop, TSource value1, TSource value2, TData data); + TResult BranchTrue (TLabel pc, TLabel target, TSource cond, TData data); + TResult BranchFalse (TLabel pc, TLabel target, TSource cond, TData data); + TResult Break (TLabel pc, TData data); - Result Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dest dest, ArgList args, Data data) + TResult Call<TypeList, ArgList> (TLabel pc, Method method, bool virt, TypeList extraVarargs, TDest dest, ArgList args, TData data) where TypeList : IIndexable<TypeNode> - where ArgList : IIndexable<Source>; + where ArgList : IIndexable<TSource>; - Result Calli<TypeList, ArgList> (Label pc, TypeNode returnType, TypeList argTypes, bool instance, Dest dest, Source functionPointer, ArgList args, Data data) + TResult Calli<TypeList, ArgList> (TLabel pc, TypeNode returnType, TypeList argTypes, bool instance, TDest dest, TSource functionPointer, ArgList args, TData data) where TypeList : IIndexable<TypeNode> - where ArgList : IIndexable<Source>; + where ArgList : IIndexable<TSource>; - Result CheckFinite (Label pc, Dest dest, Source source, Data data); - Result CopyBlock (Label pc, Source destAddress, Source srcAddress, Source len, Data data); - Result EndFilter (Label pc, Source decision, Data data); - Result EndFinally (Label pc, Data data); - Result Jmp (Label pc, Method method, Data data); - Result LoadArg (Label pc, Parameter argument, bool isOld, Dest dest, Data data); - Result LoadArgAddress (Label pc, Parameter argument, bool isOld, Dest dest, Data data); - Result LoadLocal (Label pc, Local local, Dest dest, Data data); - Result LoadLocalAddress (Label pc, Local local, Dest dest, Data data); - Result Nop (Label pc, Data data); - Result Pop (Label pc, Source source, Data data); - Result Return (Label pc, Source source, Data data); - Result StoreArg (Label pc, Parameter argument, Source source, Data data); - Result StoreLocal (Label pc, Local local, Source source, Data data); - Result Switch (Label pc, TypeNode type, IEnumerable<Pair<object, Label>> cases, Source value, Data data); - Result Box (Label pc, TypeNode type, Dest dest, Source source, Data data); + TResult CheckFinite (TLabel pc, TDest dest, TSource source, TData data); + TResult CopyBlock (TLabel pc, TSource destAddress, TSource srcAddress, TSource len, TData data); + TResult EndFilter (TLabel pc, TSource decision, TData data); + TResult EndFinally (TLabel pc, TData data); + TResult Jmp (TLabel pc, Method method, TData data); + TResult LoadArg (TLabel pc, Parameter argument, bool isOld, TDest dest, TData data); + TResult LoadArgAddress (TLabel pc, Parameter argument, bool isOld, TDest dest, TData data); + TResult LoadLocal (TLabel pc, Local local, TDest dest, TData data); + TResult LoadLocalAddress (TLabel pc, Local local, TDest dest, TData data); + TResult Nop (TLabel pc, TData data); + TResult Pop (TLabel pc, TSource source, TData data); + TResult Return (TLabel pc, TSource source, TData data); + TResult StoreArg (TLabel pc, Parameter argument, TSource source, TData data); + TResult StoreLocal (TLabel pc, Local local, TSource source, TData data); + TResult Switch (TLabel pc, TypeNode type, IEnumerable<Pair<object, TLabel>> cases, TSource value, TData data); + TResult Box (TLabel pc, TypeNode type, TDest dest, TSource source, TData data); - Result ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dest dest, ArgList args, Data data) + TResult ConstrainedCallvirt<TypeList, ArgList> (TLabel pc, Method method, TypeNode constraint, TypeList extraVarargs, TDest dest, ArgList args, TData data) where TypeList : IIndexable<TypeNode> - where ArgList : IIndexable<Source>; + where ArgList : IIndexable<TSource>; - Result CastClass (Label pc, TypeNode type, Dest dest, Source obj, Data data); - Result CopyObj (Label pc, TypeNode type, Source destPtr, Source sourcePtr, Data data); - Result Initobj (Label pc, TypeNode type, Source ptr, Data data); - Result LoadElement (Label pc, TypeNode type, Dest dest, Source array, Source index, Data data); - Result LoadField (Label pc, Field field, Dest dest, Source obj, Data data); - Result LoadFieldAddress (Label pc, Field field, Dest dest, Source obj, Data data); - Result LoadLength (Label pc, Dest dest, Source array, Data data); - Result LoadStaticField (Label pc, Field field, Dest dest, Data data); - Result LoadStaticFieldAddress (Label pc, Field field, Dest dest, Data data); - Result LoadTypeToken (Label pc, TypeNode type, Dest dest, Data data); - Result LoadFieldToken (Label pc, Field type, Dest dest, Data data); - Result LoadMethodToken (Label pc, Method type, Dest dest, Data data); + TResult CastClass (TLabel pc, TypeNode type, TDest dest, TSource obj, TData data); + TResult CopyObj (TLabel pc, TypeNode type, TSource destPtr, TSource sourcePtr, TData data); + TResult Initobj (TLabel pc, TypeNode type, TSource ptr, TData data); + TResult LoadElement (TLabel pc, TypeNode type, TDest dest, TSource array, TSource index, TData data); + TResult LoadField (TLabel pc, Field field, TDest dest, TSource obj, TData data); + TResult LoadFieldAddress (TLabel pc, Field field, TDest dest, TSource obj, TData data); + TResult LoadLength (TLabel pc, TDest dest, TSource array, TData data); + TResult LoadStaticField (TLabel pc, Field field, TDest dest, TData data); + TResult LoadStaticFieldAddress (TLabel pc, Field field, TDest dest, TData data); + TResult LoadTypeToken (TLabel pc, TypeNode type, TDest dest, TData data); + TResult LoadFieldToken (TLabel pc, Field type, TDest dest, TData data); + TResult LoadMethodToken (TLabel pc, Method type, TDest dest, TData data); - Result NewArray<ArgList> (Label pc, TypeNode type, Dest dest, ArgList lengths, Data data) - where ArgList : IIndexable<Source>; + TResult NewArray<ArgList> (TLabel pc, TypeNode type, TDest dest, ArgList lengths, TData data) + where ArgList : IIndexable<TSource>; - Result NewObj<ArgList> (Label pc, Method ctor, Dest dest, ArgList args, Data data) - where ArgList : IIndexable<Source>; + TResult NewObj<ArgList> (TLabel pc, Method ctor, TDest dest, ArgList args, TData data) + where ArgList : IIndexable<TSource>; - Result MkRefAny (Label pc, TypeNode type, Dest dest, Source obj, Data data); - Result RefAnyType (Label pc, Dest dest, Source source, Data data); - Result RefAnyVal (Label pc, TypeNode type, Dest dest, Source source, Data data); - Result Rethrow (Label pc, Data data); - Result StoreElement (Label pc, TypeNode type, Source array, Source index, Source value, Data data); - Result StoreField (Label pc, Field field, Source obj, Source value, Data data); - Result StoreStaticField (Label pc, Field field, Source value, Data data); - Result Throw (Label pc, Source exception, Data data); - Result Unbox (Label pc, TypeNode type, Dest dest, Source obj, Data data); - Result UnboxAny (Label pc, TypeNode type, Dest dest, Source obj, Data data); - } + TResult MkRefAny (TLabel pc, TypeNode type, TDest dest, TSource obj, TData data); + TResult RefAnyType (TLabel pc, TDest dest, TSource source, TData data); + TResult RefAnyVal (TLabel pc, TypeNode type, TDest dest, TSource source, TData data); + TResult Rethrow (TLabel pc, TData data); + TResult StoreElement (TLabel pc, TypeNode type, TSource array, TSource index, TSource value, TData data); + TResult StoreField (TLabel pc, Field field, TSource obj, TSource value, TData data); + TResult StoreStaticField (TLabel pc, Field field, TSource value, TData data); + TResult Throw (TLabel pc, TSource exception, TData data); + TResult Unbox (TLabel pc, TypeNode type, TDest dest, TSource obj, TData data); + TResult UnboxAny (TLabel pc, TypeNode type, TDest dest, TSource obj, TData data); + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeInspector.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeInspector.cs index b1f1ae2983e..5a6f3152463 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeInspector.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeInspector.cs @@ -181,8 +181,8 @@ namespace Mono.CodeContracts.Static.AST.Visitors { if (node == null) return; - VisitExpression (node.Operand1); - VisitExpression (node.Operand2); + VisitExpression (node.Left); + VisitExpression (node.Right); } public virtual void VisitBlock (Block node) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ValueCodeVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ValueCodeVisitor.cs index 00d366f06f6..6184442faec 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ValueCodeVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ValueCodeVisitor.cs @@ -31,6 +31,6 @@ using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.AST.Visitors { class ValueCodeVisitor<Variable> : - CodeVisitor<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, LispList<Variable>>> { + CodeVisitor<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, Sequence<Variable>>> { } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs index 5d6cf08153d..4bd71b19baf 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs @@ -32,25 +32,25 @@ namespace Mono.CodeContracts.Static.AST { { } - public BinaryExpression (NodeType nodeType, Expression operand1, Expression operand2) : base (nodeType) + public BinaryExpression (NodeType nodeType, Expression left, Expression right) : base (nodeType) { - Operand1 = operand1; - Operand2 = operand2; + Left = left; + Right = right; } - public BinaryExpression (NodeType nodeType, Expression operand1, Expression operand2, TypeNode type) + public BinaryExpression (NodeType nodeType, Expression left, Expression right, TypeNode type) : base (nodeType, type) { - Operand1 = operand1; - Operand2 = operand2; + Left = left; + Right = right; } - public Expression Operand1 { get; set; } - public Expression Operand2 { get; set; } + public Expression Left { get; set; } + public Expression Right { get; set; } public override string ToString () { - return string.Format ("({1} :{0}: {2})", NodeType, Operand1, Operand2); + return string.Format ("({1} :{0}: {2})", NodeType, Left, Right); } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs index 1b3a9f03ad0..8277eacf12f 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs @@ -26,6 +26,10 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; + +using Mono.CodeContracts.Static.Analysis.Numerical; + namespace Mono.CodeContracts.Static.AST { enum BinaryOperator { Add, @@ -61,4 +65,48 @@ namespace Mono.CodeContracts.Static.AST { Sub_Ovf_Un, Xor } + + static class BinaryOperatorExtensions { + public static ExpressionOperator ToExpressionOperator(this BinaryOperator op) + { + switch (op) { + case BinaryOperator.Add: + return ExpressionOperator.Add; + case BinaryOperator.And: + return ExpressionOperator.And; + case BinaryOperator.Ceq: + return ExpressionOperator.Equal; + case BinaryOperator.Cobjeq: + return ExpressionOperator.Equal_Obj; + case BinaryOperator.Cne_Un: + return ExpressionOperator.NotEqual; + case BinaryOperator.Cge: + return ExpressionOperator.GreaterEqualThan; + case BinaryOperator.Cgt: + return ExpressionOperator.GreaterThan; + case BinaryOperator.Cle: + return ExpressionOperator.LessEqualThan; + case BinaryOperator.Clt: + return ExpressionOperator.LessThan; + case BinaryOperator.Div: + return ExpressionOperator.Div; + case BinaryOperator.LogicalAnd: + return ExpressionOperator.LogicalAnd; + case BinaryOperator.LogicalOr: + return ExpressionOperator.LogicalOr; + case BinaryOperator.Mul: + return ExpressionOperator.Mult; + case BinaryOperator.Or: + return ExpressionOperator.Or; + case BinaryOperator.Rem: + return ExpressionOperator.Mod; + case BinaryOperator.Sub: + return ExpressionOperator.Sub; + case BinaryOperator.Xor: + return ExpressionOperator.Xor; + default: + return ExpressionOperator.Unknown; + } + } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs index e9e8103e12d..024d0109f4a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs @@ -28,8 +28,8 @@ namespace Mono.CodeContracts.Static.AST { sealed class Literal : Expression { - public static Literal Null = new Literal (null); - public object Value; + public static readonly Literal Null = new Literal (null); + public readonly object Value; public Literal () : base (NodeType.Literal) { diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/CodeContractsAnalysisDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/CodeContractsAnalysisDriver.cs index 275c3013cbc..b1ca5153cb5 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/CodeContractsAnalysisDriver.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/CodeContractsAnalysisDriver.cs @@ -1,3 +1,31 @@ +// +// CodeContractsAnalysisDriver.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis; @@ -5,6 +33,7 @@ using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding; using Mono.CodeContracts.Static.Analysis.HeapAnalysis; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; using Mono.CodeContracts.Static.Providers; using Mono.CodeContracts.Static.Proving; @@ -41,12 +70,12 @@ namespace Mono.CodeContracts.Static.Analysis.Drivers { } #region IFactBase<SymbolicValue> Members - public ProofOutcome IsNull (APC pc, SymbolicValue variable) + public FlatDomain<bool> IsNull (APC pc, SymbolicValue variable) { return ProofOutcome.Top; } - public ProofOutcome IsNonNull (APC pc, SymbolicValue variable) + public FlatDomain<bool> IsNonNull(APC pc, SymbolicValue variable) { return ProofOutcome.Top; } @@ -60,15 +89,15 @@ namespace Mono.CodeContracts.Static.Analysis.Drivers { #region IMethodDriver<LabeledSymbol<APC,SymbolicValue>,SymbolicValue> Members public ICodeLayer<SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, - IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> ValueLayer { get; private set; } + IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> ValueLayer { get; private set; } public ICodeLayer<LabeledSymbol<APC, SymbolicValue>, SymbolicValue, IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>, - IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> ExpressionLayer { get; private set; } + IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> ExpressionLayer { get; private set; } public ICodeLayer<SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, - IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> HybridLayer { get; private set; } + IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> HybridLayer { get; private set; } public IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> ContextProvider { @@ -107,7 +136,7 @@ namespace Mono.CodeContracts.Static.Analysis.Drivers { ValueLayer = CodeLayerFactory.Create ( this.heap_analysis.GetDecoder (StackLayer.ILDecoder), StackLayer.MetaDataProvider, StackLayer.ContractProvider, source => source.ToString (), dest => dest.ToString ()); - var expressionAnalysis = new ExpressionAnalysisFacade<SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> + var expressionAnalysis = new ExpressionAnalysisFacade<SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> (ValueLayer, this.heap_analysis.IsUnreachable); ValueLayer.CreateForward (expressionAnalysis.CreateExpressionAnalysis ()) (expressionAnalysis.InitialValue (SymbolicValue.GetUniqueKey)); @@ -118,7 +147,7 @@ namespace Mono.CodeContracts.Static.Analysis.Drivers { } IILDecoder - <APC, LabeledSymbol<APC, SymbolicValue>, SymbolicValue, IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> + <APC, LabeledSymbol<APC, SymbolicValue>, SymbolicValue, IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>, IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> decoder = expressionAnalysis.GetDecoder (ValueLayer.ILDecoder); this.expr2String = ExpressionPrinterFactory.Printer (decoder.ContextProvider, this); ExpressionLayer = CodeLayerFactory.Create (decoder, ValueLayer.MetaDataProvider, ValueLayer.ContractProvider, @@ -140,7 +169,7 @@ namespace Mono.CodeContracts.Static.Analysis.Drivers { return SymbolicValue.GetUniqueKey (var); } #endregion - } + } #endregion - } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysisFixPoint.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysisFixPoint.cs index 7c9b52065b2..2763503c542 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysisFixPoint.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysisFixPoint.cs @@ -27,11 +27,12 @@ // using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.Lattices; using Mono.CodeContracts.Static.Proving; namespace Mono.CodeContracts.Static.Analysis.Drivers { interface IMethodAnalysisFixPoint<Variable> { IFactQuery<BoxedExpression, Variable> FactQuery { get; } - ProofOutcome ValidateExplicitAssertion (APC pc, Variable value); + FlatDomain<bool> ValidateExplicitAssertion (APC pc, Variable value); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodDriver.cs index 7a09747b607..73132f38eca 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodDriver.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodDriver.cs @@ -35,9 +35,9 @@ using Mono.CodeContracts.Static.Proving; namespace Mono.CodeContracts.Static.Analysis.Drivers { interface IMethodDriver<Expression, Variable> : IBasicMethodDriver { - ICodeLayer<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, LispList<Variable>>> ValueLayer { get; } - ICodeLayer<Expression, Variable, IExpressionContextProvider<Expression, Variable>, IImmutableMap<Variable, LispList<Variable>>> ExpressionLayer { get; } - ICodeLayer<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, LispList<Variable>>> HybridLayer { get; } + ICodeLayer<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, Sequence<Variable>>> ValueLayer { get; } + ICodeLayer<Expression, Variable, IExpressionContextProvider<Expression, Variable>, IImmutableMap<Variable, Sequence<Variable>>> ExpressionLayer { get; } + ICodeLayer<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, Sequence<Variable>>> HybridLayer { get; } IExpressionContextProvider<Expression, Variable> ContextProvider { get; } IMetaDataProvider MetaDataProvider { get; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/FullExpressionDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/FullExpressionDecoder.cs index 4e3f4bc8fb6..a217e3c827e 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/FullExpressionDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/FullExpressionDecoder.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths; +using Mono.CodeContracts.Static.Analysis.Numerical; using Mono.CodeContracts.Static.DataStructures; using Mono.CodeContracts.Static.Lattices; using Mono.CodeContracts.Static.Providers; @@ -47,7 +48,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { public readonly VisitorForValueOf<V, E> ValueOfVisitor; public readonly VisitorForVariable<V, E> VariableVisitor; public readonly VisitorForVariablesIn<V, E> VariablesInVisitor; - private readonly IMetaDataProvider meta_data_provider; + protected readonly IMetaDataProvider MetaDataProvider; #region Implementation of IFullExpressionDecoder<V,E> public bool IsVariable (E expr, out object variable) @@ -99,7 +100,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { VisitorForVariablesIn<V, E>.AddFreeVariables (expr, set, this); } - public LispList<PathElement> GetVariableAccessPath (E expr) + public Sequence<PathElement> GetVariableAccessPath (E expr) { return ContextProvider.ValueContext.AccessPathList (ContextProvider.ExpressionContext.GetPC (expr), ContextProvider.ExpressionContext.Unrefine (expr), true, false); } @@ -107,8 +108,8 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { public bool TryGetType (E expr, out TypeNode type) { FlatDomain<TypeNode> aType = ContextProvider.ExpressionContext.GetType (expr); - if (aType.IsNormal) { - type = aType.Concrete; + if (aType.IsNormal()) { + type = aType.Value; return true; } @@ -121,11 +122,11 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { return TrySizeOf (expr, out sizeAsConstant); } - private bool TrySizeOf (E expr, out int sizeAsConstant) + private bool TrySizeOf (E expr, out int sizeAsConstant) { TypeNode type; if (VisitorForSizeOf<V, E>.IsSizeOf (expr, out type, this)) { - int size = this.meta_data_provider.TypeSize (type); + int size = this.MetaDataProvider.TypeSize (type); if (size != -1) { sizeAsConstant = size; return true; @@ -140,7 +141,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { public FullExpressionDecoder (IMetaDataProvider metaDataProvider, IExpressionContextProvider<E, V> contextProvider) { ContextProvider = contextProvider; - this.meta_data_provider = metaDataProvider; + this.MetaDataProvider = metaDataProvider; this.VariableVisitor = new VisitorForVariable<V, E> (); this.UnderlyingVariableVisitor = new VisitorForUnderlyingVariable<V, E> (); this.UnaryExpressionVisitor = new VisitorForIsUnaryExpression<V, E> (); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/IFullExpressionDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/IFullExpressionDecoder.cs index b9dc54a52e1..f5aed227ccf 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/IFullExpressionDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/IFullExpressionDecoder.cs @@ -29,6 +29,7 @@ using System.Collections.Generic; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths; +using Mono.CodeContracts.Static.Analysis.Numerical; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { @@ -42,7 +43,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { bool IsUnaryExpression (Expression expr, out UnaryOperator op, out Expression arg); bool IsBinaryExpression (Expression expr, out BinaryOperator op, out Expression left, out Expression right); void AddFreeVariables (Expression expr, ISet<Expression> set); - LispList<PathElement> GetVariableAccessPath (Expression expr); + Sequence<PathElement> GetVariableAccessPath (Expression expr); bool TryGetType (Expression expr, out TypeNode type); bool TrySizeOfAsConstant (Expression expr, out int sizeAsConstant); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/QueryVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/QueryVisitor.cs index 99372a733c1..fb349411fd1 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/QueryVisitor.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/QueryVisitor.cs @@ -32,7 +32,10 @@ using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { - abstract class QueryVisitor<V, E> : ISymbolicExpressionVisitor<E, E, V, Dummy, bool> where V : IEquatable<V> where E : IEquatable<E> { + abstract class QueryVisitor<V, E> : ISymbolicExpressionVisitor<E, E, V, Dummy, bool> + where V : IEquatable<V> + where E : IEquatable<E> + { #region ISymbolicExpressionVisitor<E,E,V,Dummy,bool> Members public virtual bool Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, Dummy data) { diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsNull.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsNull.cs index e694d4b5b3c..3ed70c4acd6 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsNull.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsNull.cs @@ -36,9 +36,8 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { public static bool IsNull (E expr, FullExpressionDecoder<V, E> decoder) { VisitorForIsNull<V, E> v = decoder.IsNullVisitor; - bool res = Decode (expr, v, decoder); - return res; + return Decode (expr, v, decoder); } public override bool LoadNull (E pc, V dest, Dummy polarity) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForSizeOf.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForSizeOf.cs index ae19934db05..d26a112014b 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForSizeOf.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForSizeOf.cs @@ -34,20 +34,21 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding { class VisitorForSizeOf<V, E> : QueryVisitor<V, E> where V : IEquatable<V> where E : IEquatable<E> { - private TypeNode Type; + + private TypeNode result; public static bool IsSizeOf (E expr, out TypeNode type, FullExpressionDecoder<V, E> decoder) { VisitorForSizeOf<V, E> v = decoder.SizeOfVisitor; bool res = Decode (expr, v, decoder); - type = v.Type; + type = v.result; return res; } public override bool Sizeof (E pc, TypeNode type, V dest, Dummy data) { - this.Type = type; + this.result = type; return true; } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/BinaryExpr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/BinaryExpr.cs index 8902d8bf9f6..cd662327bee 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/BinaryExpr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/BinaryExpr.cs @@ -62,7 +62,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { return visitor.Binary (pc, this.Operator, dest, this.Left, this.Right, data); } - public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions) + public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions) { if (substitutions.ContainsKey (this.Left) && substitutions.ContainsKey (this.Right)) return new BinaryExpr<TSymbolicValue> (substitutions [this.Left].Head, substitutions [this.Right].Head, this.Operator); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/ConstExpr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/ConstExpr.cs index 69cfccc01b3..b1807631678 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/ConstExpr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/ConstExpr.cs @@ -54,7 +54,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { return visitor.LoadConst (pc, this.Type, this.value, dest, data); } - public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions) + public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions) { return this; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/Expr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/Expr.cs index 542094f854b..db7eb34461a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/Expr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/Expr.cs @@ -43,7 +43,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { public abstract Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data) where Visitor : IExpressionILVisitor<APC, TSymbolicValue, TSymbolicValue, Data, Result>; - public abstract Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions); + public abstract Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions); /// <summary> /// Specifies that current expression is partially contained in candidates diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/IsInstExpr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/IsInstExpr.cs index 08220926689..0f537b342ff 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/IsInstExpr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/IsInstExpr.cs @@ -54,7 +54,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { return visitor.Isinst (pc, this.Type, dest, this.Argument, data); } - public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions) + public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions) { if (substitutions.ContainsKey (this.Argument)) return new IsInstExpr<TSymbolicValue> (substitutions [this.Argument].Head, this.Type); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/NullExpr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/NullExpr.cs index fc9e8de69d9..57f218c905f 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/NullExpr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/NullExpr.cs @@ -50,7 +50,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { return visitor.LoadNull (pc, dest, data); } - public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions) + public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions) { return this; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/SizeOfExpr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/SizeOfExpr.cs index 106880d15b4..4d87d49ecc0 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/SizeOfExpr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/SizeOfExpr.cs @@ -54,7 +54,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { return visitor.Sizeof (pc, this.Type, dest, data); } - public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions) + public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions) { return this; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/UnaryExpr.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/UnaryExpr.cs index 8dd288accc4..f1d2821292f 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/UnaryExpr.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/UnaryExpr.cs @@ -56,7 +56,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions { return visitor.Unary (pc, this.Operator, this.Unsigned, dest, this.Source, data); } - public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions) + public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> substitutions) { if (substitutions.ContainsKey (this.Source)) return new UnaryExpr<TSymbolicValue> (substitutions [this.Source].Head, this.Operator, this.Unsigned); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AnalysisDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AnalysisDecoder.cs index b87e83abf9a..8fb742d1b0a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AnalysisDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AnalysisDecoder.cs @@ -45,9 +45,9 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { { FlatDomain<Expr<TSymValue>> aExpression = data [condition]; - if (aExpression.IsNormal) { + if (aExpression.IsNormal()) { bool truth = tag != EdgeTag.False; - data = aExpression.Concrete.Decode<ExprDomain<TSymValue>, ExprDomain<TSymValue>, AssumeDecoder<TSymValue>> + data = aExpression.Value.Decode<ExprDomain<TSymValue>, ExprDomain<TSymValue>, AssumeDecoder<TSymValue>> (pc, condition, new AssumeDecoder<TSymValue> (truth), data); } @@ -57,8 +57,8 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { public override ExprDomain<TSymValue> Assert (APC pc, EdgeTag tag, TSymValue condition, ExprDomain<TSymValue> data) { FlatDomain<Expr<TSymValue>> expression = data [condition]; - if (expression.IsNormal) { - data = expression.Concrete.Decode<ExprDomain<TSymValue>, ExprDomain<TSymValue>, AssumeDecoder<TSymValue>> + if (expression.IsNormal()) { + data = expression.Value.Decode<ExprDomain<TSymValue>, ExprDomain<TSymValue>, AssumeDecoder<TSymValue>> (pc, condition, new AssumeDecoder<TSymValue> (true), data); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AssumeDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AssumeDecoder.cs index 4780fbdfc09..11a97f638ba 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AssumeDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AssumeDecoder.cs @@ -49,23 +49,23 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { if (this.truth && op.IsEqualityOperator ()) { if (!data.HasRefinement (s1)) { FlatDomain<Expr<SymbolicValue>> expression2 = data [s2]; - if (expression2.IsNormal && !data.IsReachableFrom (s2, s1)) - return data.Add (s1, expression2.Concrete); + if (expression2.IsNormal() && !data.IsReachableFrom (s2, s1)) + return data.Add (s1, expression2.Value); } else if (!data.HasRefinement (s2)) { FlatDomain<Expr<SymbolicValue>> expression1 = data [s1]; - if (expression1.IsNormal && !data.IsReachableFrom (s1, s2)) - return data.Add (s2, expression1.Concrete); + if (expression1.IsNormal() && !data.IsReachableFrom (s1, s2)) + return data.Add (s2, expression1.Value); } } if (!this.truth && op == BinaryOperator.Cne_Un) { if (!data.HasRefinement (s1)) { FlatDomain<Expr<SymbolicValue>> expression2 = data [s2]; - if (expression2.IsNormal && !data.IsReachableFrom (s2, s1)) - return data.Add (s1, expression2.Concrete); + if (expression2.IsNormal() && !data.IsReachableFrom (s2, s1)) + return data.Add (s1, expression2.Value); } else if (!data.HasRefinement (s2)) { FlatDomain<Expr<SymbolicValue>> expression1 = data [s1]; - if (expression1.IsNormal && !data.IsReachableFrom (s1, s2)) - return data.Add (s2, expression1.Concrete); + if (expression1.IsNormal() && !data.IsReachableFrom (s1, s2)) + return data.Add (s2, expression1.Value); } } return data; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExprDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExprDomain.cs index f596be99e3e..fa9136ca70f 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExprDomain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExprDomain.cs @@ -26,7 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // - using System; using System.Collections.Generic; using System.IO; @@ -63,7 +62,9 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { public IEnumerable<Pair<Dummy, TSymValue>> Successors(TSymValue node) { FlatDomain<Expr<TSymValue>> expr = this.expressions[node]; - if (expr.IsNormal) foreach (TSymValue sv in expr.Concrete.Variables) yield return new Pair<Dummy, TSymValue> (Dummy.Value, sv); + if (expr.IsNormal()) + foreach (TSymValue sv in expr.Value.Variables) + yield return new Pair<Dummy, TSymValue> (Dummy.Value, sv); } #endregion @@ -77,19 +78,19 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { return new ExprDomain<TSymValue> (this.expressions.Join (that.expressions, widening, out weaker)); } - public static ExprDomain<TSymValue> TopValue(Func<TSymValue, int> keyConverter ) + public static ExprDomain<TSymValue> TopValue(Func<TSymValue, int> keyConverter) { return new ExprDomain<TSymValue> (EnvironmentDomain<TSymValue, FlatDomain<Expr<TSymValue>>>.TopValue (keyConverter)); } public ExprDomain<TSymValue> Add (TSymValue sv, Expr<TSymValue> expr) { - return new ExprDomain<TSymValue> (this.expressions.Add (sv, expr)); + return new ExprDomain<TSymValue> (this.expressions.With (sv, expr)); } public ExprDomain<TSymValue> Remove(TSymValue sv) { - return new ExprDomain<TSymValue> (this.expressions.Remove (sv)); + return new ExprDomain<TSymValue> (this.expressions.Without (sv)); } public ExprDomain<TSymValue> Empty() @@ -108,7 +109,8 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { DepthFirst.Visit (this, source, sv => { if (sv.Equals (target)) reachable = true; - return true; + + return !reachable; // break if reachable }, null); return reachable; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionAnalysisFacade.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionAnalysisFacade.cs index 026a460edd4..2923e26b238 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionAnalysisFacade.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionAnalysisFacade.cs @@ -38,7 +38,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { class ExpressionAnalysisFacade<TSymValue, TContext, TEdgeData> where TSymValue : IEquatable<TSymValue> where TContext : IValueContextProvider<TSymValue> - where TEdgeData : IImmutableMap<TSymValue, LispList<TSymValue>> { + where TEdgeData : IImmutableMap<TSymValue, Sequence<TSymValue>> { public readonly Predicate<APC> IsUnreachable; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoder.cs index 3fc058118f7..54fbb76698e 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoder.cs @@ -43,7 +43,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { IExpressionContext<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue> where TSymbolicValue : IEquatable<TSymbolicValue> where TContext : IValueContextProvider<TSymbolicValue> - where TEdgeData : IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> { + where TEdgeData : IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> { private readonly IILDecoder<APC, TSymbolicValue, TSymbolicValue, IValueContextProvider<TSymbolicValue>, TEdgeData> value_decoder; private readonly ExpressionAnalysisFacade<TSymbolicValue, TContext, TEdgeData> parent; private readonly IValueContextProvider<TSymbolicValue> underlying; @@ -75,10 +75,9 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { return visitor.SymbolicConstant (expr, expr.Symbol, data); FlatDomain<Expr<TSymbolicValue>> aExpr = ifFound [expr.Symbol]; - if (aExpr.IsNormal) { - return aExpr.Concrete.Decode<Data, Result, ExpressionDecoderAdapter<TSymbolicValue, Data, Result, Visitor>> - (expr.ReadAt, expr.Symbol, - new ExpressionDecoderAdapter<TSymbolicValue, Data, Result, Visitor> (visitor), data); + if (aExpr.IsNormal()) { + return aExpr.Value.Decode<Data, Result, ExpressionDecoderAdapter<TSymbolicValue, Data, Result, Visitor>> + (expr.ReadAt, expr.Symbol, new ExpressionDecoderAdapter<TSymbolicValue, Data, Result, Visitor> (visitor), data); } TypeNode type; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoderAdapter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoderAdapter.cs index 53a24a47d60..212349fbe03 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoderAdapter.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoderAdapter.cs @@ -1,3 +1,31 @@ +// +// ExpressionDecoderAdapter.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.AST.Visitors; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ValueAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ValueAnalysis.cs index 47cd464b7ba..712974f570d 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ValueAnalysis.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ValueAnalysis.cs @@ -1,3 +1,31 @@ +// +// ValueAnalysis.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using System.IO; using Mono.CodeContracts.Static.AST.Visitors; @@ -12,7 +40,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { IILVisitor<APC, SymbolicValue, SymbolicValue, ExprDomain<SymbolicValue>, ExprDomain<SymbolicValue>>, EdgeData> where SymbolicValue : IEquatable<SymbolicValue> where Context : IValueContextProvider<SymbolicValue> - where EdgeData : IImmutableMap<SymbolicValue, LispList<SymbolicValue>> { + where EdgeData : IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> { private readonly ExpressionAnalysisFacade<SymbolicValue, Context, EdgeData> parent; public ValueAnalysis (ExpressionAnalysisFacade<SymbolicValue, Context, EdgeData> parent) @@ -37,15 +65,15 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { ExprDomain<SymbolicValue> domain = originalState.Empty (); foreach (SymbolicValue sv in originalState.Keys) { - Expr<SymbolicValue> expression = originalState [sv].Concrete.Substitute (sourceTargetMap); + Expr<SymbolicValue> expression = originalState [sv].Value.Substitute (sourceTargetMap); if (expression != null) domain = domain.Add (sv, expression); } foreach (SymbolicValue sv in sourceTargetMap.Keys) { FlatDomain<Expr<SymbolicValue>> expressionDomain = domain [sv]; - if (expressionDomain.IsNormal) { - Expr<SymbolicValue> expression = expressionDomain.Concrete; + if (expressionDomain.IsNormal()) { + Expr<SymbolicValue> expression = expressionDomain.Value; foreach (SymbolicValue sub in sourceTargetMap [sv].AsEnumerable ()) result = result.Add (sub, expression); } @@ -94,7 +122,7 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { pair.Key.Dump (pair.Value); } - private void DumpMap (IImmutableMap<SymbolicValue, LispList<SymbolicValue>> sourceTargetMap) + private void DumpMap (IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> sourceTargetMap) { Console.WriteLine ("Source-Target assignment"); foreach (SymbolicValue key in sourceTargetMap.Keys) { @@ -109,8 +137,8 @@ namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis { Console.WriteLine ("--- {0} ---", header); foreach (SymbolicValue index in state.Keys) { FlatDomain<Expr<SymbolicValue>> domain = state [index]; - if (domain.IsNormal) - Console.WriteLine ("{0} -> {1}", index, domain.Concrete); + if (domain.IsNormal()) + Console.WriteLine ("{0} -> {1}", index, domain.Value); else if (domain.IsTop) Console.WriteLine ("{0} -> (Top)", index); else if (domain.IsBottom) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathExtensions.cs index bd2ecc5e0ef..6e99136d279 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathExtensions.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathExtensions.cs @@ -34,7 +34,7 @@ using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths { static class PathExtensions { - public static HashSet<Field> FieldsIn (this LispList<PathElement> path) + public static HashSet<Field> FieldsIn (this Sequence<PathElement> path) { var result = new HashSet<Field> (); if (path != null) { @@ -52,7 +52,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths { return PathToString (path); } - public static string ToCodeString (this LispList<PathElement> path) + public static string ToCodeString (this Sequence<PathElement> path) { return PathToString (path.AsEnumerable ()); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/IMergeInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/IMergeInfo.cs index bb0702b2d2e..a3e7d34b754 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/IMergeInfo.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/IMergeInfo.cs @@ -35,8 +35,8 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { interface IMergeInfo { bool Changed { get; } IEnumerable<Tuple<SymValue, SymValue, SymValue>> MergeTriples { get; } - IImmutableMap<SymValue, LispList<SymValue>> ForwardG1Map { get; } - IImmutableMap<SymValue, LispList<SymValue>> ForwardG2Map { get; } + IImmutableMap<SymValue, Sequence<SymValue>> ForwardG1Map { get; } + IImmutableMap<SymValue, Sequence<SymValue>> ForwardG2Map { get; } bool IsResultGraph<TFunc, TAbstractDomain> (SymGraph<TFunc, TAbstractDomain> graph) where TFunc : IEquatable<TFunc>, IConstantInfo diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MergeInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MergeInfo.cs index dacf94bb5f1..38b6c07f364 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MergeInfo.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MergeInfo.cs @@ -50,7 +50,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { private DoubleImmutableMap<SymValue, SymValue, SymValue> mappings; private IImmutableSet<SymValue> visited_key1; - private LispList<Tuple<SymValue, SymValue, SymValue>> merge_triples; + private Sequence<Tuple<SymValue, SymValue, SymValue>> merge_triples; public MergeInfo (SymGraph<TFunc, TADomain> result, SymGraph<TFunc, TADomain> g1, @@ -79,12 +79,12 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { get { return this.merge_triples.AsEnumerable (); } } - public IImmutableMap<SymValue, LispList<SymValue>> ForwardG1Map + public IImmutableMap<SymValue, Sequence<SymValue>> ForwardG1Map { get { return GetForwardGraphMap ((t) => t.Item1); } } - public IImmutableMap<SymValue, LispList<SymValue>> ForwardG2Map + public IImmutableMap<SymValue, Sequence<SymValue>> ForwardG2Map { get { return GetForwardGraphMap ((t) => t.Item2); } } @@ -320,8 +320,8 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { if (!this.visited_multi_edges.Add (key)) return; - LispList<SymValue> list1 = this.Graph1.MultiEdgeMap [sv1, edge]; - LispList<SymValue> list2 = this.Graph2.MultiEdgeMap [sv2, edge]; + Sequence<SymValue> list1 = this.Graph1.MultiEdgeMap [sv1, edge]; + Sequence<SymValue> list2 = this.Graph2.MultiEdgeMap [sv2, edge]; if (list2.IsEmpty ()) return; foreach (SymValue v1 in list1.AsEnumerable ()) { @@ -404,9 +404,9 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { } } - private IImmutableMap<SymValue, LispList<SymValue>> GetForwardGraphMap (Func<Tuple<SymValue, SymValue, SymValue>, SymValue> sourceSelector) + private IImmutableMap<SymValue, Sequence<SymValue>> GetForwardGraphMap (Func<Tuple<SymValue, SymValue, SymValue>, SymValue> sourceSelector) { - IImmutableMap<SymValue, LispList<SymValue>> res = ImmutableIntKeyMap<SymValue, LispList<SymValue>>.Empty (SymValue.GetUniqueKey); + IImmutableMap<SymValue, Sequence<SymValue>> res = ImmutableIntKeyMap<SymValue, Sequence<SymValue>>.Empty (SymValue.GetUniqueKey); foreach (var tuple in this.merge_triples.AsEnumerable ()) { SymValue sv = sourceSelector (tuple); if (sv != null) @@ -478,7 +478,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { private void PrimeMapWithCommon () { - LispList<SymValue> rest = null; + Sequence<SymValue> rest = null; foreach (SymValue sv in this.Graph1.EqualTermsMap.Keys) { if (IsCommon (sv) && (this.Graph2.EqualTermsMap.ContainsKey (sv) || this.Graph2.EqualMultiTermsMap.ContainsKey (sv))) { if (this.Graph1.MultiEdgeMap.ContainsKey1 (sv)) @@ -501,13 +501,13 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { } } - private void Replay (LispList<Update<TFunc, TADomain>> updates, LispList<Update<TFunc, TADomain>> common) + private void Replay (Sequence<Update<TFunc, TADomain>> updates, Sequence<Update<TFunc, TADomain>> common) { for (Update<TFunc, TADomain> update = Update<TFunc, TADomain>.Reverse (updates, common); update != null; update = update.Next) update.Replay (this); } - private void ReplayEliminations (LispList<Update<TFunc, TADomain>> updates, LispList<Update<TFunc, TADomain>> common) + private void ReplayEliminations (Sequence<Update<TFunc, TADomain>> updates, Sequence<Update<TFunc, TADomain>> common) { for (Update<TFunc, TADomain> update = Update<TFunc, TADomain>.Reverse (updates, common); update != null; update = update.Next) update.ReplayElimination (this); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraph.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraph.cs index 6f6bd38b04c..e4b0b12ba32 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraph.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraph.cs @@ -69,10 +69,10 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { this.const_root = FreshSymbol (); TermMap = DoubleImmutableMap<SymValue, TFunc, SymValue>.Empty (SymValue.GetUniqueKey); - MultiEdgeMap = DoubleImmutableMap<SymValue, MultiEdge<TFunc, TADomain>, LispList<SymValue>>.Empty (SymValue.GetUniqueKey); + MultiEdgeMap = DoubleImmutableMap<SymValue, MultiEdge<TFunc, TADomain>, Sequence<SymValue>>.Empty (SymValue.GetUniqueKey); this.abs_map = ImmutableIntKeyMap<SymValue, TADomain>.Empty (SymValue.GetUniqueKey); this.forw_map = ImmutableIntKeyMap<SymValue, SymValue>.Empty (SymValue.GetUniqueKey); - EqualTermsMap = ImmutableIntKeyMap<SymValue, LispList<SymGraphTerm<TFunc>>>.Empty (SymValue.GetUniqueKey); + EqualTermsMap = ImmutableIntKeyMap<SymValue, Sequence<SymGraphTerm<TFunc>>>.Empty (SymValue.GetUniqueKey); EqualMultiTermsMap = ImmutableIntKeyMap<SymValue, SymGraphTerm<TFunc>>.Empty (SymValue.GetUniqueKey); this.BottomPlaceHolder = FreshSymbol (); @@ -109,11 +109,11 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { } public IImmutableMap<SymValue, SymGraphTerm<TFunc>> EqualMultiTermsMap { get; private set; } - public IImmutableMap<SymValue, LispList<SymGraphTerm<TFunc>>> EqualTermsMap { get; private set; } - public DoubleImmutableMap<SymValue, MultiEdge<TFunc, TADomain>, LispList<SymValue>> MultiEdgeMap { get; private set; } + public IImmutableMap<SymValue, Sequence<SymGraphTerm<TFunc>>> EqualTermsMap { get; private set; } + public DoubleImmutableMap<SymValue, MultiEdge<TFunc, TADomain>, Sequence<SymValue>> MultiEdgeMap { get; private set; } public DoubleImmutableMap<SymValue, TFunc, SymValue> TermMap { get; private set; } public int IdGenerator { get; private set; } - public LispList<Update<TFunc, TADomain>> Updates { get; private set; } + public Sequence<Update<TFunc, TADomain>> Updates { get; private set; } public bool IsImmutable { @@ -164,8 +164,8 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { for (int i = 0; i < len; i++) { var edge = new MultiEdge<TFunc, TADomain> (function, i, len); - LispList<SymValue> list = MultiEdgeMap [args [i], edge]; - if (isTermEqual && !LispList<SymValue>.Contains (list, value)) + Sequence<SymValue> list = MultiEdgeMap [args [i], edge]; + if (isTermEqual && !Sequence<SymValue>.Contains (list, value)) isTermEqual = false; if (!isTermEqual) MultiEdgeMap = MultiEdgeMap.Add (args [i], edge, list.Cons (value)); @@ -192,7 +192,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { if (sv == null) { key = FreshSymbol (); TermMap = TermMap.Add (source, function, key); - EqualTermsMap = EqualTermsMap.Add (key, LispList<SymGraphTerm<TFunc>>.Cons (new SymGraphTerm<TFunc> (function, source), null)); + EqualTermsMap = EqualTermsMap.Add (key, Sequence<SymGraphTerm<TFunc>>.Cons (new SymGraphTerm<TFunc> (function, source), null)); AddEdgeUpdate (source, function); } else key = Find (sv); @@ -205,7 +205,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { value = Find (value); TermMap = TermMap.Add (source, function, value); - LispList<SymGraphTerm<TFunc>> rest = EqualTermsMap [value]; + Sequence<SymGraphTerm<TFunc>> rest = EqualTermsMap [value]; if (rest.IsEmpty () || (!rest.Head.Function.Equals (function) || rest.Head.Args [0] != source)) EqualTermsMap = EqualTermsMap.Add (value, rest.Cons (new SymGraphTerm<TFunc> (function, source))); @@ -376,7 +376,12 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { return new SymGraph<TFunc, TADomain> (this); } - public SymGraph<TFunc, TADomain> Join (SymGraph<TFunc, TADomain> that, bool widening, out bool weaker) + public SymGraph<TFunc, TADomain> Join(SymGraph<TFunc, TADomain> that) + { + throw new NotImplementedException(); + } + + public SymGraph<TFunc, TADomain> Join (SymGraph<TFunc, TADomain> that, bool widening, out bool weaker) { IMergeInfo info; SymGraph<TFunc, TADomain> join = Join (that, out info, widening); @@ -384,16 +389,19 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { return join; } - public SymGraph<TFunc, TADomain> Join (SymGraph<TFunc, TADomain> that, out IMergeInfo mergeInfo, bool widen) + public SymGraph<TFunc, TADomain> Widen(SymGraph<TFunc, TADomain> that) + { + throw new NotImplementedException(); + } + + public SymGraph<TFunc, TADomain> Join (SymGraph<TFunc, TADomain> that, out IMergeInfo mergeInfo, bool widen) { SymGraph<TFunc, TADomain> egraph = this; int updateSize; SymGraph<TFunc, TADomain> commonTail = ComputeCommonTail (egraph, that, out updateSize); - bool hasCommonTail = true; - if (commonTail == null) - hasCommonTail = false; + bool hasCommonTail = commonTail != null; - bool doingIncrementalJoin = hasCommonTail & commonTail != egraph.root_graph & !widen & DoIncrementalJoin; + bool doingIncrementalJoin = hasCommonTail & commonTail != egraph.root_graph & !widen & DoIncrementalJoin; //debug @@ -494,7 +502,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { public bool LessEqual (SymGraph<TFunc, TADomain> that) { - IImmutableMap<SymValue, LispList<SymValue>> forwardMap; + IImmutableMap<SymValue, Sequence<SymValue>> forwardMap; IImmutableMap<SymValue, SymValue> backwardMap; return LessEqual (that, out forwardMap, out backwardMap); @@ -507,7 +515,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { } public bool LessEqual (SymGraph<TFunc, TADomain> that, - out IImmutableMap<SymValue, LispList<SymValue>> forward, + out IImmutableMap<SymValue, Sequence<SymValue>> forward, out IImmutableMap<SymValue, SymValue> backward) { if (!IsSameEGraph (that)) @@ -591,7 +599,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { { int length = args.Length; var multiEdge = new MultiEdge<TFunc, TADomain> (function, 0, length); - for (LispList<SymValue> list = MultiEdgeMap [args [0], multiEdge]; list != null; list = list.Tail) { + for (Sequence<SymValue> list = MultiEdgeMap [args [0], multiEdge]; list != null; list = list.Tail) { SymGraphTerm<TFunc> term = EqualMultiTermsMap [list.Head]; if (term.Args.Length == length) { bool found = true; @@ -700,7 +708,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { } private static bool InternalLessEqual (SymGraph<TFunc, TADomain> thisG, SymGraph<TFunc, TADomain> thatG, - out IImmutableMap<SymValue, LispList<SymValue>> forward, + out IImmutableMap<SymValue, Sequence<SymValue>> forward, out IImmutableMap<SymValue, SymValue> backward) { int updateSize; @@ -712,7 +720,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { workList.Add (new EqualityPair<TFunc, TADomain> (thisG.const_root, thatG.const_root)); IImmutableSet<SymValue> backwardManifested = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey); IImmutableMap<SymValue, SymValue> backwardMap = ImmutableIntKeyMap<SymValue, SymValue>.Empty (SymValue.GetUniqueKey); - IImmutableMap<SymValue, LispList<SymValue>> forwardMap = ImmutableIntKeyMap<SymValue, LispList<SymValue>>.Empty (SymValue.GetUniqueKey); + IImmutableMap<SymValue, Sequence<SymValue>> forwardMap = ImmutableIntKeyMap<SymValue, Sequence<SymValue>>.Empty (SymValue.GetUniqueKey); IImmutableMap<SymValue, int> triggers = ImmutableIntKeyMap<SymValue, int>.Empty (SymValue.GetUniqueKey); while (!workList.IsEmpty ()) { @@ -896,11 +904,11 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { } #endregion - public IImmutableMap<SymValue, LispList<SymValue>> GetForwardIdentityMap () + public IImmutableMap<SymValue, Sequence<SymValue>> GetForwardIdentityMap () { - var res = ImmutableIntKeyMap<SymValue, LispList<SymValue>>.Empty (SymValue.GetUniqueKey); + var res = ImmutableIntKeyMap<SymValue, Sequence<SymValue>>.Empty (SymValue.GetUniqueKey); foreach (var sv in this.EqualTermsMap.Keys.Union (this.EqualMultiTermsMap.Keys)) { - res = res.Add (sv, LispList<SymValue>.Cons (sv, null)); + res = res.Add (sv, Sequence<SymValue>.Cons (sv, null)); } return res; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/Update.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/Update.cs index ed63b1541d9..6cf773af1c5 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/Update.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/Update.cs @@ -38,8 +38,8 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph { public abstract void Replay (MergeInfo<TFunc, TAbstractDomain> merge); public abstract void ReplayElimination (MergeInfo<TFunc, TAbstractDomain> merge); - public static Update<TFunc, TAbstractDomain> Reverse (LispList<Update<TFunc, TAbstractDomain>> updates, - LispList<Update<TFunc, TAbstractDomain>> common) + public static Update<TFunc, TAbstractDomain> Reverse (Sequence<Update<TFunc, TAbstractDomain>> updates, + Sequence<Update<TFunc, TAbstractDomain>> common) { Update<TFunc, TAbstractDomain> last = null; for (; updates != common; updates = updates.Tail) { diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AbstractType.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AbstractType.cs index e9a4955683f..cdbcbfe670e 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AbstractType.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AbstractType.cs @@ -53,12 +53,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { public TypeNode ConcreteType { - get { return this.value.Concrete; } - } - - public bool IsNormal - { - get { return this.value.IsNormal; } + get { return this.value.Value; } } private static AbstractType ForManifestedFieldValue @@ -96,7 +91,12 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { get { return IsZero && this.value.IsBottom; } } - public AbstractType Join (AbstractType that, bool widening, out bool weaker) + public AbstractType Join(AbstractType that) + { + throw new NotImplementedException(); + } + + public AbstractType Join (AbstractType that, bool widening, out bool weaker) { if (that.IsZero) { weaker = false; @@ -115,7 +115,12 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return new AbstractType (resultType, false); } - public AbstractType Meet (AbstractType that) + public AbstractType Widen(AbstractType that) + { + throw new NotImplementedException(); + } + + public AbstractType Meet (AbstractType that) { return new AbstractType (this.value.Meet (that.value), IsZero || that.IsZero); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AnalysisDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AnalysisDecoder.cs index 2a2b2b61ef9..60543b330e0 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AnalysisDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AnalysisDecoder.cs @@ -183,7 +183,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { if (derefThis) loc = data.Value (loc); AbstractType aType = data.GetType (loc); - if (aType.IsNormal) + if (aType.IsNormal()) DevirtualizeImplementingMethod (aType.ConcreteType, ref method); } } @@ -1100,7 +1100,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { else { SymValue sv = data.Value (num); AbstractType aType = data.GetType (sv); - type = aType.IsNormal ? aType.ConcreteType : MetaDataProvider.System_Object; + type = aType.IsNormal() ? aType.ConcreteType : MetaDataProvider.System_Object; } } else type = argTypes [i]; @@ -1151,7 +1151,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { if (!MetaDataProvider.IsStruct (type)) { SymValue sv = data.Value (array); AbstractType aType = data.GetType (sv); - if (aType.IsNormal && MetaDataProvider.IsArray (aType.ConcreteType)) { + if (aType.IsNormal() && MetaDataProvider.IsArray (aType.ConcreteType)) { t = MetaDataProvider.ElementType (aType.ConcreteType); if (t == null) t = type; @@ -1167,7 +1167,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { SymValue ptr; if (MetaDataProvider.IsStruct (MetaDataProvider.DeclaringType (field))) { AbstractType abstractType = data.GetType (data.Address (obj)); - ptr = abstractType.IsNormal + ptr = abstractType.IsNormal() && MetaDataProvider.IsManagedPointer (abstractType.ConcreteType) && MetaDataProvider.IsStruct (MetaDataProvider.ElementType (abstractType.ConcreteType)) ? data.Address (obj) @@ -1251,7 +1251,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { public static Domain FindOldState (APC pc, Domain data) { - for (LispList<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) { + for (Sequence<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) { Edge<CFGBlock, EdgeTag> pair = list.Head; if (pair.Tag == EdgeTag.Exit || pair.Tag.Is (EdgeTag.AfterMask)) return data.GetStateAt (new APC (pair.From.Subroutine.EntryAfterRequires, 0, list.Tail)); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Domain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Domain.cs index c2889579cd5..455e20562c2 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Domain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Domain.cs @@ -154,7 +154,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { } #endregion - public static bool IsRootedInParameter (LispList<PathElement> path) + public static bool IsRootedInParameter (Sequence<PathElement> path) { return path.Head is PathElement<Parameter>; } @@ -215,7 +215,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { private void AssignValue (SymValue address, FlatDomain<TypeNode> type) { Havoc (address); - SetType (address, type.IsNormal ? MetaDataProvider.ManagedPointer (type.Concrete) : type); + SetType (address, type.IsNormal() ? MetaDataProvider.ManagedPointer (type.Value) : type); if (IsStructWithFields (type)) return; @@ -223,10 +223,10 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { SetType (fresh, type); this.egraph [this.Functions.ValueOf, address] = fresh; - if (!type.IsNormal) + if (!type.IsNormal()) return; - if (NeedsArrayLengthManifested (type.Concrete)) + if (NeedsArrayLengthManifested (type.Value)) ManifestArrayLength (fresh); } @@ -271,7 +271,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { { var args = new[] {Value (op1), Value (op2)}; SymFunction c = this.Functions.For (op); - TypeNode type = !typeOpt.IsNormal ? MetaDataProvider.System_Int32 : typeOpt.Concrete; + TypeNode type = !typeOpt.IsNormal() ? MetaDataProvider.System_Int32 : typeOpt.Value; bool fresh; @@ -285,7 +285,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { public void AssignPureUnary (int dest, UnaryOperator op, FlatDomain<TypeNode> typeOpt, int operand) { SymFunction c = this.Functions.For (op); - TypeNode type = !typeOpt.IsNormal ? MetaDataProvider.System_Int32 : typeOpt.Concrete; + TypeNode type = !typeOpt.IsNormal() ? MetaDataProvider.System_Int32 : typeOpt.Value; SymValue unaryOperand = this.egraph [c, Value (operand)]; SymValue sv = Address (dest); @@ -319,7 +319,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { private void HavocIfStruct (SymValue address) { AbstractType aType = this.egraph [address]; - if (aType.IsBottom || (aType.IsNormal && MetaDataProvider.IsStruct (aType.ConcreteType))) + if (aType.IsBottom || (aType.IsNormal() && MetaDataProvider.IsStruct (aType.ConcreteType))) Havoc (address); } @@ -464,8 +464,8 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { FlatDomain<TypeNode> targetType = TargetType (addrType); if (IsStructWithFields (targetType)) - CopyOldStructValue (pc, destAddr, srcAddr, targetType.Concrete, target, atEndOld); - else if (atEndOld && targetType.IsNormal && MetaDataProvider.IsManagedPointer (targetType.Concrete)) { + CopyOldStructValue (pc, destAddr, srcAddr, targetType.Value, target, atEndOld); + else if (atEndOld && targetType.IsNormal() && MetaDataProvider.IsManagedPointer (targetType.Value)) { srcAddr = TryValue (srcAddr); if (srcAddr == null) return; @@ -499,13 +499,13 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { } } - private IEnumerable<LispList<PathElementBase>> GetAccessPathsRaw (SymValue sv, AccessPathFilter<Method> filter, bool compress) + private IEnumerable<Sequence<PathElementBase>> GetAccessPathsRaw (SymValue sv, AccessPathFilter<Method> filter, bool compress) { var visited = new HashSet<SymValue> (); return GetAccessPathsRaw (sv, null, visited, filter, compress); } - private IEnumerable<LispList<PathElementBase>> GetAccessPathsRaw (SymValue sv, LispList<PathElementBase> path, HashSet<SymValue> visited, AccessPathFilter<Method> filter, bool compress) + private IEnumerable<Sequence<PathElementBase>> GetAccessPathsRaw (SymValue sv, Sequence<PathElementBase> path, HashSet<SymValue> visited, AccessPathFilter<Method> filter, bool compress) { if (sv == this.egraph.ConstRoot) yield return path; @@ -515,7 +515,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { if (!(term.Function is Wrapper<object>) && !(term.Function is Wrapper<int>)) { PathElementBase next = term.Function.ToPathElement (compress); if (next != null && !filter.FilterOutPathElement (term.Function)) { - LispList<PathElementBase> newPath; + Sequence<PathElementBase> newPath; if (path == null || !compress || (!(next is PathElement<Method>))) newPath = path.Cons (next); @@ -530,11 +530,11 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { } } - private LispList<PathElementBase> GetBestAccessPath (SymValue sv, AccessPathFilter<Method> filter, bool compress, bool allowLocal, bool preferLocal) + private Sequence<PathElementBase> GetBestAccessPath (SymValue sv, AccessPathFilter<Method> filter, bool compress, bool allowLocal, bool preferLocal) { - LispList<PathElementBase> bestParameterPath = null; - LispList<PathElementBase> bestLocalPath = null; - LispList<PathElementBase> bestFieldMethodPath = null; + Sequence<PathElementBase> bestParameterPath = null; + Sequence<PathElementBase> bestLocalPath = null; + Sequence<PathElementBase> bestFieldMethodPath = null; foreach (var path in GetAccessPathsFiltered (sv, filter, compress)) { if (path != null) { @@ -563,12 +563,12 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return bestFieldMethodPath; } - public IEnumerable<LispList<PathElementBase>> GetAccessPathsFiltered (SymValue sv, AccessPathFilter<Method> filter, bool compress) + public IEnumerable<Sequence<PathElementBase>> GetAccessPathsFiltered (SymValue sv, AccessPathFilter<Method> filter, bool compress) { return GetAccessPathsTyped (sv, filter, compress).Where (path => PathIsVisibleAccordingToFilter (path, filter)); } - private bool PathIsVisibleAccordingToFilter (LispList<PathElementBase> path, AccessPathFilter<Method> filter) + private bool PathIsVisibleAccordingToFilter (Sequence<PathElementBase> path, AccessPathFilter<Method> filter) { if (path.Length () == 0 || !filter.HasVisibilityMember) return true; @@ -614,7 +614,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return true; } - private bool TryPropagateTypeInfo (LispList<PathElementBase> path, out LispList<PathElementBase> result) + private bool TryPropagateTypeInfo (Sequence<PathElementBase> path, out Sequence<PathElementBase> result) { if (path == null) { result = null; @@ -627,7 +627,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return false; } - LispList<PathElementBase> result1; + Sequence<PathElementBase> result1; if (!TryPropagateTypeInfoRecurse (path.Tail, prevType, out result1)) { result = null; return false; @@ -642,7 +642,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return true; } - private bool TryPropagateTypeInfoRecurse (LispList<PathElementBase> path, TypeNode prevType, out LispList<PathElementBase> result) + private bool TryPropagateTypeInfoRecurse (Sequence<PathElementBase> path, TypeNode prevType, out Sequence<PathElementBase> result) { if (path == null) { result = null; @@ -650,7 +650,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { } PathElementBase head = path.Head; if (head.TrySetType (prevType, MetaDataProvider, out prevType)) { - LispList<PathElementBase> updatedPath; + Sequence<PathElementBase> updatedPath; if (TryPropagateTypeInfoRecurse (path.Tail, prevType, out updatedPath)) { result = updatedPath.Cons (head); return true; @@ -661,11 +661,11 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return false; } - private IEnumerable<LispList<PathElementBase>> GetAccessPathsTyped (SymValue sv, AccessPathFilter<Method> filter, bool compress) + private IEnumerable<Sequence<PathElementBase>> GetAccessPathsTyped (SymValue sv, AccessPathFilter<Method> filter, bool compress) { var visited = new HashSet<SymValue> (); foreach (var path in GetAccessPathsRaw (sv, null, visited, filter, compress)) { - LispList<PathElementBase> result; + Sequence<PathElementBase> result; if (TryPropagateTypeInfo (path, out result)) yield return result; } @@ -697,7 +697,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { { FlatDomain<TypeNode> type = TargetType (addrType); if (IsStructWithFields (type)) - CopyStructValue (destAddr, sourceAddr, type.Concrete); + CopyStructValue (destAddr, sourceAddr, type.Value); CopyPrimValue (destAddr, sourceAddr, cast, type); } @@ -710,8 +710,8 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { else SetTypeIfUnknown (value, elementType); - if (elementType.IsNormal) { - if (NeedsArrayLengthManifested (elementType.Concrete)) + if (elementType.IsNormal()) { + if (NeedsArrayLengthManifested (elementType.Value)) ManifestArrayLength (value); } @@ -724,7 +724,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { SymValue srcAddress = Address (source); AbstractType aType = GetType (srcAddress); - TypeNode addrType = aType.IsNormal ? aType.ConcreteType : MetaDataProvider.ManagedPointer (type); + TypeNode addrType = aType.IsNormal() ? aType.ConcreteType : MetaDataProvider.ManagedPointer (type); CopyValueToOldState (pc, addrType, destAddress, srcAddress, target); } @@ -772,10 +772,10 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { SymValue fresh = this.egraph.FreshSymbol (); SetType (fresh, targetType); this.egraph [this.Functions.ValueOf, destAddress] = fresh; - if (!targetType.IsNormal) + if (!targetType.IsNormal()) return; - if (NeedsArrayLengthManifested (targetType.Concrete)) + if (NeedsArrayLengthManifested (targetType.Value)) ManifestArrayLength (fresh); } @@ -970,18 +970,18 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { private bool IsStructWithFields (FlatDomain<TypeNode> type) { - if (!type.IsNormal) + if (!type.IsNormal()) return false; - return !MetaDataProvider.HasValueRepresentation (type.Concrete); + return !MetaDataProvider.HasValueRepresentation (type.Value); } private FlatDomain<TypeNode> TargetType (FlatDomain<TypeNode> type) { - if (!type.IsNormal) + if (!type.IsNormal()) return type; - TypeNode normalType = type.Concrete; + TypeNode normalType = type.Value; if (MetaDataProvider.IsManagedPointer (normalType)) return MetaDataProvider.ElementType (normalType); @@ -1001,7 +1001,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { { AbstractType abstractType = this.egraph [sv]; - if (!abstractType.IsZero && (!abstractType.Type.IsNormal || abstractType.Type.Equals (MetaDataProvider.System_IntPtr))) + if (!abstractType.IsZero && (!abstractType.Type.IsNormal() || abstractType.Type.Equals (MetaDataProvider.System_IntPtr))) this.egraph [sv] = abstractType.With (type); } @@ -1066,7 +1066,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { private bool IsStructAddress (AbstractType abstractType) { - if (!abstractType.IsNormal) + if (!abstractType.IsNormal()) return false; TypeNode normalType = abstractType.ConcreteType; @@ -1183,13 +1183,13 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { FlatDomain<TypeNode> type = aType.Type; if (!IsStructWithFields (type)) { SymValue ptrValue = this.egraph.FreshSymbol (); - if (type.IsNormal) + if (type.IsNormal()) aType = new AbstractType (!unsigned ? MetaDataProvider.System_IntPtr : MetaDataProvider.System_UIntPtr, aType.IsZero); - SetType (address, type.IsNormal ? MetaDataProvider.ManagedPointer (type.Concrete) : type); + SetType (address, type.IsNormal() ? MetaDataProvider.ManagedPointer (type.Value) : type); this.egraph [ptrValue] = aType; this.egraph [this.Functions.ValueOf, address] = ptrValue; } else - SetType (address, type.IsNormal ? MetaDataProvider.ManagedPointer (type.Concrete) : type); + SetType (address, type.IsNormal() ? MetaDataProvider.ManagedPointer (type.Value) : type); } public TypeNode UnaryResultType (UnaryOperator op, AbstractType type) @@ -1212,7 +1212,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { case UnaryOperator.Conv_u8: return MetaDataProvider.System_UInt64; default: - if (type.IsNormal) + if (type.IsNormal()) return type.ConcreteType; return MetaDataProvider.System_Int32; } @@ -1223,7 +1223,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { SymValue srcAddr = Address (temporaryForWhichAddressIsTaken); this.egraph [this.Functions.ValueOf, destAddr] = srcAddr; AbstractType aType = CurrentType (srcAddr); - FlatDomain<TypeNode> t = !aType.IsNormal ? new FlatDomain<TypeNode> () : MetaDataProvider.ManagedPointer (aType.Type.Concrete); + FlatDomain<TypeNode> t = !aType.IsNormal() ? new FlatDomain<TypeNode> () : MetaDataProvider.ManagedPointer (aType.Type.Value); SetType (destAddr, t); } @@ -1458,19 +1458,19 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { public string GetAccessPath (SymValue sv) { - LispList<PathElementBase> bestAccessPath = GetBestAccessPath (sv, AccessPathFilter<Method>.NoFilter, true, true, false); + Sequence<PathElementBase> bestAccessPath = GetBestAccessPath (sv, AccessPathFilter<Method>.NoFilter, true, true, false); if (bestAccessPath == null) return null; return bestAccessPath.Select (i => (PathElement) i).ToCodeString (); } - public LispList<PathElement> GetAccessPathList (SymValue symbol, AccessPathFilter<Method> filter, bool allowLocal, bool preferLocal) + public Sequence<PathElement> GetAccessPathList (SymValue symbol, AccessPathFilter<Method> filter, bool allowLocal, bool preferLocal) { return GetBestAccessPath (symbol, filter, true, allowLocal, preferLocal).Coerce<PathElementBase, PathElement> (); } - public bool LessEqual (Domain that, out IImmutableMap<SymValue, LispList<SymValue>> forward, out IImmutableMap<SymValue, SymValue> backward) + public bool LessEqual (Domain that, out IImmutableMap<SymValue, Sequence<SymValue>> forward, out IImmutableMap<SymValue, SymValue> backward) { return this.egraph.LessEqual (that.egraph, out forward, out backward); } @@ -1490,7 +1490,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return mi.IsGraph2 (this.egraph); } - public IImmutableMap<SymValue, LispList<SymValue>> GetForwardIdentityMap () + public IImmutableMap<SymValue, Sequence<SymValue>> GetForwardIdentityMap () { return this.egraph.GetForwardIdentityMap (); } @@ -1608,13 +1608,23 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { } } - public Domain Join (Domain that, bool widening, out bool weaker) + public Domain Join(Domain that) + { + throw new NotImplementedException(); + } + + public Domain Join (Domain that, bool widening, out bool weaker) { IMergeInfo mergeInfo; return Join (that, widening, out weaker, out mergeInfo); } - public Domain Meet (Domain that) + public Domain Widen(Domain that) + { + throw new NotImplementedException(); + } + + public Domain Meet (Domain that) { SymGraph<SymFunction, AbstractType> graph = this.egraph.Meet (that.egraph); return new Domain (graph, RecomputeConstantMap (graph), this.unmodifiedSinceEntry, this.unmodifiedFieldsSinceEntry, null, this, OldDomain); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/HeapAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/HeapAnalysis.cs index f7015fa750f..b23da5b0934 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/HeapAnalysis.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/HeapAnalysis.cs @@ -38,8 +38,8 @@ using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { class HeapAnalysis : IAnalysis<APC, Domain, IILVisitor<APC, int, int, Domain, Domain>, Dummy> { - private readonly Dictionary<Pair<APC, APC>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> forwardRenamings = - new Dictionary<Pair<APC, APC>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> (); + private readonly Dictionary<Pair<APC, APC>, IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> forwardRenamings = + new Dictionary<Pair<APC, APC>, IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> (); public readonly Dictionary<APC, IMergeInfo> MergeInfoCache = new Dictionary<APC, IMergeInfo> (); public readonly DoubleDictionary<APC, APC, Dummy> RenamePoints = new DoubleDictionary<APC, APC, Dummy> (); @@ -163,7 +163,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return new Domain (this); } - public IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> + public IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> GetDecoder<Context>(IILDecoder<APC, int, int, Context, Dummy> underlying) where Context : IStackContextProvider { @@ -179,14 +179,14 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return false; } - public IImmutableMap<SymbolicValue, LispList<SymbolicValue>> EdgeRenaming (Pair<APC, APC> edge, bool isJoinPoint) + public IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> EdgeRenaming (Pair<APC, APC> edge, bool isJoinPoint) { - IImmutableMap<SymbolicValue, LispList<SymbolicValue>> forwardRenaming; + IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> forwardRenaming; if (this.forwardRenamings.TryGetValue (edge, out forwardRenaming)) return forwardRenaming; - IImmutableMap<SymbolicValue, LispList<SymbolicValue>> renaming = null; + IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> renaming = null; Domain afterBegin; PostStateLookup (edge.Key, out afterBegin); if (afterBegin == null || afterBegin.IsBottom) @@ -194,7 +194,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { Domain beforeEnd; PreStateLookup (edge.Value, out beforeEnd); if (beforeEnd != null) { - IImmutableMap<SymValue, LispList<SymValue>> forward; + IImmutableMap<SymValue, Sequence<SymValue>> forward; if (!TryComputeFromJoinCache (afterBegin, beforeEnd, edge.Value, out forward)) { IImmutableMap<SymValue, SymValue> backward; if (!afterBegin.LessEqual (beforeEnd, out forward, out backward)) @@ -203,9 +203,9 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { forward = afterBegin.GetForwardIdentityMap (); } if (forward != null) { - renaming = ImmutableIntKeyMap<SymbolicValue, LispList<SymbolicValue>>.Empty (SymbolicValue.GetUniqueKey); + renaming = ImmutableIntKeyMap<SymbolicValue, Sequence<SymbolicValue>>.Empty (SymbolicValue.GetUniqueKey); foreach (SymValue sv in forward.Keys) { - LispList<SymbolicValue> targets = null; + Sequence<SymbolicValue> targets = null; foreach (SymValue target in forward [sv].AsEnumerable ()) targets = targets.Cons (new SymbolicValue (target)); if (targets != null) @@ -217,7 +217,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return renaming; } - private bool TryComputeFromJoinCache (Domain inDomain, Domain outDomain, APC joinPoint, out IImmutableMap<SymValue, LispList<SymValue>> forward) + private bool TryComputeFromJoinCache (Domain inDomain, Domain outDomain, APC joinPoint, out IImmutableMap<SymValue, Sequence<SymValue>> forward) { forward = null; IMergeInfo mi; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ISymGraph.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ISymGraph.cs index 7a39cca2593..3f9b1a0f5fc 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ISymGraph.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ISymGraph.cs @@ -57,7 +57,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { TGraph Join (TGraph that, out IMergeInfo mergeInfo, bool widen); - bool LessEqual (TGraph that, out IImmutableMap<SymValue, LispList<SymValue>> forward, + bool LessEqual (TGraph that, out IImmutableMap<SymValue, Sequence<SymValue>> forward, out IImmutableMap<SymValue, SymValue> backward); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueContextProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueContextProvider.cs index cf3e81753c7..a48ff79a3eb 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueContextProvider.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueContextProvider.cs @@ -118,7 +118,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return arrayLength; } - public LispList<PathElement> AccessPathList (APC at, SymbolicValue sv, bool allowLocal, bool preferLocal) + public Sequence<PathElement> AccessPathList (APC at, SymbolicValue sv, bool allowLocal, bool preferLocal) { Domain domain; if (!this.parent.PreStateLookup (at, out domain)) @@ -161,7 +161,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return domain.GetAccessPath (sv.Symbol); } - public IEnumerable<LispList<PathElement>> AccessPaths (APC at, SymValue value, AccessPathFilter<Method> filter) + public IEnumerable<Sequence<PathElement>> AccessPaths (APC at, SymValue value, AccessPathFilter<Method> filter) { Domain domain; if (!this.parent.PreStateLookup (at, out domain)) @@ -170,7 +170,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return domain.GetAccessPathsFiltered (value, filter, true).Select (path => path.Coerce<PathElementBase, PathElement> ()); } - public LispList<PathElement> VisibleAccessPathList (APC at, SymbolicValue value) + public Sequence<PathElement> VisibleAccessPathList (APC at, SymbolicValue value) { Domain domain; if (!this.parent.PreStateLookup (at, out domain)) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueDecoder.cs index 70f331ef8fd..60ecfb5ffb3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueDecoder.cs @@ -34,7 +34,7 @@ using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { class ValueDecoder<TContext> : - IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> + IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, Sequence<SymbolicValue>>> where TContext : IStackContextProvider { private readonly HeapAnalysis parent; @@ -48,7 +48,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { this.stack_decoder = stackDecoder; } - #region Implementation of IILDecoder<APC,SymbolicValue,SymbolicValue,IValueContext<SymbolicValue>,IImmutableMap<SymbolicValue,LispList<SymbolicValue>>> + #region Implementation of IILDecoder<APC,SymbolicValue,SymbolicValue,IValueContext<SymbolicValue>,IImmutableMap<SymbolicValue,Sequence<SymbolicValue>>> public IValueContextProvider<SymbolicValue> ContextProvider { get { return context.Value; } } public Result ForwardDecode<Data, Result, Visitor>(APC pc, Visitor visitor, Data state) @@ -63,7 +63,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return this.parent.IsUnreachable (pc); } - public IImmutableMap<SymbolicValue, LispList<SymbolicValue>> EdgeData(APC from, APC to) + public IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> EdgeData(APC from, APC to) { if (!this.parent.RenamePoints.ContainsKey(from, to)) return null; @@ -73,7 +73,7 @@ namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis { return this.parent.EdgeRenaming (new Pair<APC, APC> (from, to), this.ContextProvider.MethodContext.CFG.IsJoinPoint (to)); } - public void Dump(TextWriter tw, string prefix, IImmutableMap<SymValue, LispList<SymValue>> edgeData ) + public void Dump(TextWriter tw, string prefix, IImmutableMap<SymValue, Sequence<SymValue>> edgeData ) { if (edgeData == null) return; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Analysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Analysis.cs index 0f674020a07..5d81f510b63 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Analysis.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Analysis.cs @@ -29,6 +29,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; + using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.Analysis.Drivers; @@ -40,13 +42,15 @@ using Mono.CodeContracts.Static.Providers; using Mono.CodeContracts.Static.Proving; namespace Mono.CodeContracts.Static.Analysis.NonNull { - class Analysis<E, V> : - ILVisitorBase<APC, V, V, Domain<E, V>, Domain<E, V>>, - IAnalysis<APC, Domain<E, V>, IILVisitor<APC, V, V, Domain<E, V>, Domain<E, V>>, IImmutableMap<V, LispList<V>>>, - IMethodResult<V>, IFactBase<V> where E : IEquatable<E> where V : IEquatable<V> { - private readonly Dictionary<APC, Domain<E, V>> callSiteCache = new Dictionary<APC, Domain<E, V>> (); + class Analysis<E, V> : ILVisitorBase<APC, V, V, NonNullDomain<V>, NonNullDomain<V>>, + IAnalysis<APC, NonNullDomain<V>, IILVisitor<APC, V, V, NonNullDomain<V>, NonNullDomain<V>>, IImmutableMap<V, Sequence<V>>>, + IMethodResult<V>, IFactBase<V> + where E : IEquatable<E> + where V : IEquatable<V> + { + private readonly Dictionary<APC, NonNullDomain<V>> callSiteCache = new Dictionary<APC, NonNullDomain<V>> (); private readonly IMethodDriver<E, V> method_driver; - private IFixPointInfo<APC, Domain<E, V>> fix_point_info; + private IFixPointInfo<APC, NonNullDomain<V>> fix_point_info; public Analysis (IMethodDriver<E, V> mdriver) { @@ -63,13 +67,13 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { get { return this.method_driver.MetaDataProvider; } } - #region IAnalysis<APC,Domain<E,V>,IILVisitor<APC,V,V,Domain<E,V>,Domain<E,V>>,IImmutableMap<V,LispList<V>>> Members - public IILVisitor<APC, V, V, Domain<E, V>, Domain<E, V>> GetVisitor () + #region IAnalysis<APC,Domain<V>,IILVisitor<APC,V,V,Domain<V>,Domain<V>>,IImmutableMap<V,Sequence<V>>> Members + public IILVisitor<APC, V, V, NonNullDomain<V>, NonNullDomain<V>> GetVisitor () { return this; } - public Domain<E, V> Join (Pair<APC, APC> edge, Domain<E, V> newstate, Domain<E, V> prevstate, out bool weaker, bool widen) + public NonNullDomain<V> Join (Pair<APC, APC> edge, NonNullDomain<V> newstate, NonNullDomain<V> prevstate, out bool weaker, bool widen) { bool nonNullWeaker; SetDomain<V> nonNulls = prevstate.NonNulls.Join (newstate.NonNulls, widen, out nonNullWeaker); @@ -77,20 +81,20 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { SetDomain<V> nulls = prevstate.Nulls.Join (newstate.Nulls, widen, out nullWeaker); weaker = nonNullWeaker || nullWeaker; - return new Domain<E, V> (nonNulls, nulls); + return new NonNullDomain<V> (nonNulls, nulls); } - public Domain<E, V> ImmutableVersion (Domain<E, V> state) + public NonNullDomain<V> ImmutableVersion (NonNullDomain<V> state) { return state; } - public Domain<E, V> MutableVersion (Domain<E, V> state) + public NonNullDomain<V> MutableVersion (NonNullDomain<V> state) { return state; } - public Domain<E, V> EdgeConversion (APC from, APC to, bool isJoinPoint, IImmutableMap<V, LispList<V>> data, Domain<E, V> state) + public NonNullDomain<V> EdgeConversion (APC from, APC to, bool isJoinPoint, IImmutableMap<V, Sequence<V>> data, NonNullDomain<V> state) { if (data == null) return state; @@ -106,22 +110,22 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { if (nonNullContains || nullContains) { foreach (V anotherVariable in data [variable].AsEnumerable ()) { if (nonNullContains) - nonNulls = nonNulls.Add (anotherVariable); + nonNulls = nonNulls.With (anotherVariable); if (nullContains) - nulls = nulls.Add (anotherVariable); + nulls = nulls.With (anotherVariable); } } } - return new Domain<E, V> (nonNulls, nulls); + return new NonNullDomain<V> (nonNulls, nulls); } - public bool IsBottom (APC pc, Domain<E, V> state) + public bool IsBottom (APC pc, NonNullDomain<V> state) { return state.NonNulls.IsBottom; } - public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, Domain<E, V>> fixPointInfo) + public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, NonNullDomain<V>> fixPointInfo) { this.fix_point_info = fixPointInfo; @@ -129,7 +133,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return pc => true; } - public void Dump (Pair<Domain<E, V>, TextWriter> pair) + public void Dump (Pair<NonNullDomain<V>, TextWriter> pair) { TextWriter tw = pair.Value; tw.Write ("NonNulls: "); @@ -140,12 +144,12 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { #endregion #region IFactBase<V> Members - public ProofOutcome IsNull (APC pc, V variable) + public FlatDomain<bool> IsNull(APC pc, V variable) { if (ContextProvider.ValueContext.IsZero (pc, variable)) return ProofOutcome.True; - Domain<E, V> domain; + NonNullDomain<V> domain; if (!PreStateLookup (pc, out domain) || domain.NonNulls.IsBottom) return ProofOutcome.Bottom; if (domain.IsNonNull (variable)) @@ -156,9 +160,9 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return ProofOutcome.Top; } - public ProofOutcome IsNonNull (APC pc, V variable) + public FlatDomain<bool> IsNonNull(APC pc, V variable) { - Domain<E, V> domain; + NonNullDomain<V> domain; if (!PreStateLookup (pc, out domain) || domain.NonNulls.IsBottom) return ProofOutcome.Bottom; if (domain.IsNonNull (variable)) @@ -167,7 +171,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return ProofOutcome.False; FlatDomain<TypeNode> aType = ContextProvider.ValueContext.GetType (pc, variable); - if (aType.IsNormal && MetaDataProvider.IsManagedPointer (aType.Concrete)) + if (aType.IsNormal() && MetaDataProvider.IsManagedPointer (aType.Value)) return ProofOutcome.True; return ProofOutcome.Top; @@ -175,7 +179,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { public bool IsUnreachable (APC pc) { - Domain<E, V> domain; + NonNullDomain<V> domain; if (!PreStateLookup (pc, out domain) || domain.NonNulls.IsBottom) return true; @@ -183,46 +187,48 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { } #endregion - public override Domain<E, V> DefaultVisit (APC pc, Domain<E, V> data) + public override NonNullDomain<V> DefaultVisit (APC pc, NonNullDomain<V> data) { return data; } - public static Domain<E, V> AssumeNonNull (V dest, Domain<E, V> before) + public static NonNullDomain<V> AssumeNonNull (V dest, NonNullDomain<V> domain) { - if (!before.NonNulls.Contains (dest)) - return new Domain<E, V> (before.NonNulls.Add (dest), before.Nulls); - return before; + if (!domain.NonNulls.Contains (dest)) + return new NonNullDomain<V> (domain.NonNulls.With (dest), domain.Nulls); + + return domain; } - public static Domain<E, V> AssumeNull (V dest, Domain<E, V> before) + public static NonNullDomain<V> AssumeNull (V dest, NonNullDomain<V> before) { if (!before.Nulls.Contains (dest)) - return new Domain<E, V> (before.NonNulls, before.Nulls.Add (dest)); + return new NonNullDomain<V> (before.NonNulls, before.Nulls.With (dest)); + return before; } - public override Domain<E, V> Assert (APC pc, EdgeTag tag, V condition, Domain<E, V> data) - { - return ContextProvider.ExpressionContext. - Decode<Pair<bool, Domain<E, V>>, Domain<E, V>, ExpressionAssumeDecoder<E, V>> - ( - ContextProvider.ExpressionContext.Refine (pc, condition), - new ExpressionAssumeDecoder<E, V> (ContextProvider), - new Pair<bool, Domain<E, V>> (true, data)); - } + public override NonNullDomain<V> Assert(APC pc, EdgeTag tag, V condition, NonNullDomain<V> data) + { + return ContextProvider.ExpressionContext.Decode + <Pair<bool, NonNullDomain<V>>, NonNullDomain<V>, ExpressionAssumeDecoder<E, V>> + ( + ContextProvider.ExpressionContext.Refine (pc, condition), + new ExpressionAssumeDecoder<E, V> (ContextProvider), + new Pair<bool, NonNullDomain<V>> (true, data)); + } - public override Domain<E, V> Assume (APC pc, EdgeTag tag, V condition, Domain<E, V> data) + public override NonNullDomain<V> Assume (APC pc, EdgeTag tag, V condition, NonNullDomain<V> data) { IExpressionContext<E, V> exprCtx = ContextProvider.ExpressionContext; E expr = exprCtx.Refine (pc, condition); - return exprCtx.Decode<Pair<bool, Domain<E, V>>, Domain<E, V>, ExpressionAssumeDecoder<E, V>> + return exprCtx.Decode<Pair<bool, NonNullDomain<V>>, NonNullDomain<V>, ExpressionAssumeDecoder<E, V>> (expr, new ExpressionAssumeDecoder<E, V> (ContextProvider), - new Pair<bool, Domain<E, V>> (tag != EdgeTag.False, data)); + new Pair<bool, NonNullDomain<V>> (tag != EdgeTag.False, data)); } - public override Domain<E, V> Unary (APC pc, UnaryOperator op, bool unsigned, V dest, V source, Domain<E, V> data) + public override NonNullDomain<V> Unary (APC pc, UnaryOperator op, bool unsigned, V dest, V source, NonNullDomain<V> data) { switch (op) { case UnaryOperator.Conv_i: @@ -234,7 +240,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return data; } - public override Domain<E, V> Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, V dest, ArgList args, Domain<E, V> data) + public override NonNullDomain<V> Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, V dest, ArgList args, NonNullDomain<V> data) { this.callSiteCache [pc] = data; if (!MetaDataProvider.IsStatic (method)) @@ -243,7 +249,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return data; } - public override Domain<E, V> CastClass (APC pc, TypeNode type, V dest, V obj, Domain<E, V> data) + public override NonNullDomain<V> CastClass (APC pc, TypeNode type, V dest, V obj, NonNullDomain<V> data) { if (data.NonNulls.Contains (obj)) return AssumeNonNull (dest, data); @@ -251,10 +257,10 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return data; } - public override Domain<E, V> Entry (APC pc, Method method, Domain<E, V> data) + public override NonNullDomain<V> Entry (APC pc, Method method, NonNullDomain<V> data) { APC at = ContextProvider.MethodContext.CFG.Next (pc); - Domain<E, V> domain = data; + NonNullDomain<V> domain = data; IIndexable<Parameter> parameters = MetaDataProvider.Parameters (method); TypeNode eventArgsType; bool systemType = MetaDataProvider.TryGetSystemType ("System.EventArgs", out eventArgsType); @@ -284,9 +290,9 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return domain; } - public override Domain<E, V> LoadStack (APC pc, int offset, V dest, V source, bool isOld, Domain<E, V> data) + public override NonNullDomain<V> LoadStack (APC pc, int offset, V dest, V source, bool isOld, NonNullDomain<V> data) { - Domain<E, V> old; + NonNullDomain<V> old; if (isOld && TryFindOldState (pc, out old)) { if (old.IsNonNull (source)) return AssumeNonNull (dest, data); @@ -297,22 +303,22 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return data; } - public override Domain<E, V> Isinst (APC pc, TypeNode type, V dest, V obj, Domain<E, V> data) + public override NonNullDomain<V> Isinst (APC pc, TypeNode type, V dest, V obj, NonNullDomain<V> data) { if (data.IsNonNull (obj)) { FlatDomain<TypeNode> aType = ContextProvider.ValueContext.GetType (pc, obj); - if (aType.IsNormal && MetaDataProvider.DerivesFrom (aType.Concrete, type)) + if (aType.IsNormal() && MetaDataProvider.DerivesFrom (aType.Value, type)) return AssumeNonNull (dest, data); } return data; } - public override Domain<E, V> LoadArgAddress (APC pc, Parameter argument, bool isOld, V dest, Domain<E, V> data) + public override NonNullDomain<V> LoadArgAddress (APC pc, Parameter argument, bool isOld, V dest, NonNullDomain<V> data) { return AssumeNonNull (dest, data); } - public override Domain<E, V> LoadConst (APC pc, TypeNode type, object constant, V dest, Domain<E, V> data) + public override NonNullDomain<V> LoadConst (APC pc, TypeNode type, object constant, V dest, NonNullDomain<V> data) { if (constant is string) return AssumeNonNull (dest, data); @@ -320,71 +326,68 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { return data; } - public override Domain<E, V> LoadElement (APC pc, TypeNode type, V dest, V array, V index, Domain<E, V> data) + public override NonNullDomain<V> LoadElement (APC pc, TypeNode type, V dest, V array, V index, NonNullDomain<V> data) { return AssumeNonNull (array, data); } - public override Domain<E, V> LoadField (APC pc, Field field, V dest, V obj, Domain<E, V> data) + public override NonNullDomain<V> LoadField (APC pc, Field field, V dest, V obj, NonNullDomain<V> data) { - Domain<E, V> domain = AssumeNonNull (obj, data); + NonNullDomain<V> domain = AssumeNonNull (obj, data); FlatDomain<TypeNode> aType = ContextProvider.ValueContext.GetType (ContextProvider.MethodContext.CFG.Next (pc), dest); - if (aType.IsNormal && MetaDataProvider.IsManagedPointer (aType.Concrete)) + if (aType.IsNormal() && MetaDataProvider.IsManagedPointer (aType.Value)) domain = AssumeNonNull (dest, domain); return domain; } - public override Domain<E, V> LoadFieldAddress (APC pc, Field field, V dest, V obj, Domain<E, V> data) + public override NonNullDomain<V> LoadFieldAddress (APC pc, Field field, V dest, V obj, NonNullDomain<V> data) { - Domain<E, V> domain = AssumeNonNull (obj, data); + NonNullDomain<V> domain = AssumeNonNull (obj, data); return AssumeNonNull (dest, domain); } - public override Domain<E, V> LoadStaticFieldAddress (APC pc, Field field, V dest, Domain<E, V> data) + public override NonNullDomain<V> LoadStaticFieldAddress (APC pc, Field field, V dest, NonNullDomain<V> data) { return AssumeNonNull (dest, data); } - public override Domain<E, V> LoadLength (APC pc, V dest, V array, Domain<E, V> data) + public override NonNullDomain<V> LoadLength (APC pc, V dest, V array, NonNullDomain<V> data) { return AssumeNonNull (array, data); } - public override Domain<E, V> NewArray<ArgList> (APC pc, TypeNode type, V dest, ArgList lengths, Domain<E, V> data) + public override NonNullDomain<V> NewArray<ArgList> (APC pc, TypeNode type, V dest, ArgList lengths, NonNullDomain<V> data) { return AssumeNonNull (dest, data); } - public override Domain<E, V> NewObj<ArgList> (APC pc, Method ctor, V dest, ArgList args, Domain<E, V> data) + public override NonNullDomain<V> NewObj<ArgList> (APC pc, Method ctor, V dest, ArgList args, NonNullDomain<V> data) { return AssumeNonNull (dest, data); } - public override Domain<E, V> StoreElement (APC pc, TypeNode type, V array, V index, V value, Domain<E, V> data) + public override NonNullDomain<V> StoreElement (APC pc, TypeNode type, V array, V index, V value, NonNullDomain<V> data) { return AssumeNonNull (array, data); } - public override Domain<E, V> StoreField (APC pc, Field field, V obj, V value, Domain<E, V> data) + public override NonNullDomain<V> StoreField (APC pc, Field field, V obj, V value, NonNullDomain<V> data) { return AssumeNonNull (obj, data); } - private bool TryFindOldState (APC pc, out Domain<E, V> old) + private bool TryFindOldState (APC pc, out NonNullDomain<V> old) { - for (LispList<Edge<CFGBlock, EdgeTag>> flist = pc.SubroutineContext; flist != null; flist = flist.Tail) { - Edge<CFGBlock, EdgeTag> head = flist.Head; - if (head.Tag.Is (EdgeTag.AfterMask)) - return this.callSiteCache.TryGetValue (pc, out old); - } - old = new Domain<E, V> (); - return false; + if (pc.SubroutineContext.AsEnumerable().Any (edge => edge.Tag.Is (EdgeTag.AfterMask))) + return this.callSiteCache.TryGetValue (pc, out old); + + return false.Without (out old); } - public Domain<E, V> InitialValue (Func<V, int> keyConverter) + public NonNullDomain<V> InitialValue (Func<V, int> keyConverter) { - return new Domain<E, V> (new SetDomain<V> (keyConverter), new SetDomain<V> (keyConverter)); + return new NonNullDomain<V> (new SetDomain<V> (keyConverter), new SetDomain<V> (keyConverter)); } #region Implementation of IMethodResult<Variable> @@ -399,17 +402,17 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { get { return new SimpleLogicInference<E, V> (ContextProvider, this, this.method_driver.BasicFacts.IsUnreachable); } } - public ProofOutcome ValidateExplicitAssertion (APC pc, V value) + public FlatDomain<bool> ValidateExplicitAssertion(APC pc, V value) { - Domain<E, V> domain; + NonNullDomain<V> domain; if (PreStateLookup (pc, out domain) && !domain.NonNulls.IsBottom) { IExpressionContext<E, V> exprCtx = ContextProvider.ExpressionContext; - return exprCtx.Decode<bool, ProofOutcome, ExpressionAssertDischarger<E, V>> (exprCtx.Refine (pc, value), new ExpressionAssertDischarger<E, V> (this, pc), true); + return exprCtx.Decode<bool, FlatDomain<bool>, ExpressionAssertDischarger<E, V>>(exprCtx.Refine(pc, value), new ExpressionAssertDischarger<E, V>(this, pc), true); } return ProofOutcome.Bottom; } - private bool PreStateLookup (APC pc, out Domain<E, V> domain) + private bool PreStateLookup (APC pc, out NonNullDomain<V> domain) { return this.fix_point_info.PreStateLookup (pc, out domain); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssertDischarger.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssertDischarger.cs index ba6a87b281b..e238de0f01c 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssertDischarger.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssertDischarger.cs @@ -30,10 +30,11 @@ using System; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Analysis.NonNull { - struct ExpressionAssertDischarger<E, V> - : ISymbolicExpressionVisitor<E, E, V, bool, ProofOutcome> + struct ExpressionAssertDischarger<E, V> + : ISymbolicExpressionVisitor<E, E, V, bool, FlatDomain<bool>> where E : IEquatable<E> where V : IEquatable<V> { private readonly Analysis<E, V> analysis; @@ -51,12 +52,12 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { } #region Implementation of IExpressionILVisitor<Expression,Expression,Variable,bool,ProofOutcome> - private ProofOutcome Recurse(bool polarity, E expr) + private FlatDomain<bool> Recurse(bool polarity, E expr) { - return this.ContextProvider.ExpressionContext.Decode<bool, ProofOutcome, ExpressionAssertDischarger<E, V>> (expr, this, polarity); + return this.ContextProvider.ExpressionContext.Decode<bool, FlatDomain<bool>, ExpressionAssertDischarger<E, V>>(expr, this, polarity); } - public ProofOutcome Binary(E orig, BinaryOperator op, V dest, E operand1, E operand2, bool polarity) + public FlatDomain<bool> Binary(E orig, BinaryOperator op, V dest, E operand1, E operand2, bool polarity) { switch (op) { case BinaryOperator.Ceq: @@ -73,33 +74,33 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { } } - public ProofOutcome Isinst(E orig, TypeNode type, V dest, E obj, bool polarity) + public FlatDomain<bool> Isinst(E orig, TypeNode type, V dest, E obj, bool polarity) { if (!polarity) return this.analysis.IsNull (this.pc, dest); - ProofOutcome outcome = this.analysis.IsNonNull (this.pc, dest); + FlatDomain<bool> outcome = this.analysis.IsNonNull(this.pc, dest); - return outcome != ProofOutcome.True ? outcome : this.Recurse (true, obj); + return outcome.IsTrue() ? outcome : this.Recurse (true, obj); } - public ProofOutcome LoadNull(E orig, V dest, bool polarity) + public FlatDomain<bool> LoadNull(E orig, V dest, bool polarity) { return polarity ? ProofOutcome.False : ProofOutcome.True; } - public ProofOutcome LoadConst(E orig, TypeNode type, object constant, V dest, bool polarity) + public FlatDomain<bool> LoadConst(E orig, TypeNode type, object constant, V dest, bool polarity) { var isConstantEqualZero = constant is int && (int) constant == 0; return (isConstantEqualZero != polarity) ? ProofOutcome.True : ProofOutcome.False; } - public ProofOutcome Sizeof(E pc, TypeNode type, V dest, bool polarity) + public FlatDomain<bool> Sizeof(E pc, TypeNode type, V dest, bool polarity) { return polarity ? ProofOutcome.True : ProofOutcome.False; } - public ProofOutcome Unary(E orig, UnaryOperator op, bool unsigned, V dest, E source, bool polarity) + public FlatDomain<bool> Unary(E orig, UnaryOperator op, bool unsigned, V dest, E source, bool polarity) { switch (op) { case UnaryOperator.Conv_i: @@ -124,7 +125,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { #endregion #region Implementation of ISymbolicExpressionVisitor<Expression,Expression,Variable,bool,ProofOutcome> - public ProofOutcome SymbolicConstant(E pc, V variable, bool polarity) + public FlatDomain<bool> SymbolicConstant(E pc, V variable, bool polarity) { return polarity ? this.analysis.IsNonNull (this.pc, variable) : this.analysis.IsNull(this.pc, variable); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs index 0feed975fbd..a8caed7b5d7 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs @@ -33,7 +33,7 @@ using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Analysis.NonNull { struct ExpressionAssumeDecoder<E, V> - : ISymbolicExpressionVisitor<E, E, V, Pair<bool, Domain<E, V>>, Domain<E, V>> + : ISymbolicExpressionVisitor<E, E, V, Pair<bool, NonNullDomain<V>>, NonNullDomain<V>> where V : IEquatable<V> where E : IEquatable<E> { private readonly IExpressionContextProvider<E, V> context_provider; @@ -44,7 +44,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { } #region ISymbolicExpressionVisitor<E,E,V,Pair<bool,Domain<E,V>>,Domain<E,V>> Members - public Domain<E, V> Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, Pair<bool, NonNullDomain<V>> data) { IExpressionContext<E, V> exprCtx = this.context_provider.ExpressionContext; switch (op) { @@ -52,7 +52,7 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { case BinaryOperator.Cobjeq: if (data.Value.IsNull (exprCtx.Unrefine (operand2)) || exprCtx.IsZero (operand2) || data.Value.IsNull (exprCtx.Unrefine (operand1)) || exprCtx.IsZero (operand1)) - return Recurse (new Pair<bool, Domain<E, V>> (!data.Key, data.Value), operand1); + return Recurse (new Pair<bool, NonNullDomain<V>> (!data.Key, data.Value), operand1); if (data.Value.IsNonNull (exprCtx.Unrefine (operand1)) || data.Value.IsNonNull (exprCtx.Unrefine (operand2))) return Analysis<E, V>.AssumeNonNull (exprCtx.Unrefine (operand2), data.Value); return data.Value; @@ -67,21 +67,21 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { } } - public Domain<E, V> Isinst (E pc, TypeNode type, V dest, E obj, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> Isinst (E pc, TypeNode type, V dest, E obj, Pair<bool, NonNullDomain<V>> data) { if (data.Key) - return Recurse (new Pair<bool, Domain<E, V>> (true, Analysis<E, V>.AssumeNonNull (dest, data.Value)), obj); + return Recurse (new Pair<bool, NonNullDomain<V>> (true, Analysis<E, V>.AssumeNonNull (dest, data.Value)), obj); return data.Value; } - public Domain<E, V> LoadNull (E pc, V dest, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> LoadNull (E pc, V dest, Pair<bool, NonNullDomain<V>> data) { if (data.Key) - return Domain<E, V>.BottomValue; + return NonNullDomain<V>.BottomValue; return data.Value; } - public Domain<E, V> LoadConst (E pc, TypeNode type, object constant, V dest, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> LoadConst (E pc, TypeNode type, object constant, V dest, Pair<bool, NonNullDomain<V>> data) { if (constant is string) return data.Value; @@ -97,17 +97,17 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { } if (data.Key && isZero || !data.Key && !isZero) - return Domain<E, V>.BottomValue; + return NonNullDomain<V>.BottomValue; return data.Value; } - public Domain<E, V> Sizeof (E pc, TypeNode type, V dest, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> Sizeof (E pc, TypeNode type, V dest, Pair<bool, NonNullDomain<V>> data) { return data.Value; } - public Domain<E, V> Unary (E pc, UnaryOperator op, bool unsigned, V dest, E source, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> Unary (E pc, UnaryOperator op, bool unsigned, V dest, E source, Pair<bool, NonNullDomain<V>> data) { switch (op) { case UnaryOperator.Conv_i: @@ -124,30 +124,30 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { case UnaryOperator.Neg: return Recurse (data, source); case UnaryOperator.Not: - return Recurse (new Pair<bool, Domain<E, V>> (!data.Key, data.Value), source); + return Recurse (new Pair<bool, NonNullDomain<V>> (!data.Key, data.Value), source); default: return data.Value; } } - public Domain<E, V> SymbolicConstant (E orig, V variable, Pair<bool, Domain<E, V>> data) + public NonNullDomain<V> SymbolicConstant (E orig, V variable, Pair<bool, NonNullDomain<V>> data) { if (data.Key) { return !this.context_provider.ExpressionContext.IsZero (orig) - ? Domain<E, V>.BottomValue + ? NonNullDomain<V>.BottomValue : Analysis<E, V>.AssumeNonNull (variable, data.Value); } if (data.Value.NonNulls.Contains (variable)) - return Domain<E, V>.BottomValue; + return NonNullDomain<V>.BottomValue; return Analysis<E, V>.AssumeNull (variable, data.Value); } #endregion - private Domain<E, V> Recurse (Pair<bool, Domain<E, V>> pair, E expr) + private NonNullDomain<V> Recurse (Pair<bool, NonNullDomain<V>> pair, E expr) { - return this.context_provider.ExpressionContext.Decode<Pair<bool, Domain<E, V>>, Domain<E, V>, ExpressionAssumeDecoder<E, V>> (expr, this, pair); - } + return this.context_provider.ExpressionContext.Decode<Pair<bool, NonNullDomain<V>>, NonNullDomain<V>, ExpressionAssumeDecoder<E, V>> (expr, this, pair); } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs index ec5a22739e9..58a14705e8b 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs @@ -37,12 +37,11 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { get { return "Non-null"; } } - public IMethodResult<Variable> Analyze<Expression, Variable> - (string fullMethodName, IMethodDriver<Expression, Variable> methodDriver) - where Expression : IEquatable<Expression> - where Variable : IEquatable<Variable> + public IMethodResult<Var> Analyze<Expr, Var> (string fullMethodName, IMethodDriver<Expr, Var> methodDriver) + where Expr : IEquatable<Expr> + where Var : IEquatable<Var> { - var analysis = new Analysis<Expression, Variable> (methodDriver); + var analysis = new Analysis<Expr, Var> (methodDriver); methodDriver.HybridLayer.CreateForward (analysis) (analysis.InitialValue (methodDriver.KeyConverter)); analysis.MethodAnalysis = this; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Domain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullDomain.cs index 84f39569d03..c3c84dbe15f 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Domain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullDomain.cs @@ -27,19 +27,18 @@ // using System; +using System.IO; + using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Analysis.NonNull { - struct Domain<E, V> - where E : IEquatable<E> - where V : IEquatable<V> { - public static readonly Domain<E, V> BottomValue - = new Domain<E, V> (SetDomain<V>.BottomValue, SetDomain<V>.BottomValue); + struct NonNullDomain<V> where V : IEquatable<V> { + public static readonly NonNullDomain<V> BottomValue = new NonNullDomain<V> (SetDomain<V>.BottomValue, SetDomain<V>.BottomValue); public SetDomain<V> NonNulls; public SetDomain<V> Nulls; - public Domain(SetDomain<V> nonNulls, SetDomain<V> nulls) + public NonNullDomain(SetDomain<V> nonNulls, SetDomain<V> nulls) { this.NonNulls = nonNulls; this.Nulls = nulls; @@ -54,5 +53,22 @@ namespace Mono.CodeContracts.Static.Analysis.NonNull { { return this.Nulls.Contains (v); } + + public override string ToString() + { + var sw = new StringWriter(); + + sw.WriteLine("Nulls:"); + sw.WriteLine("<"); + this.Nulls.Dump (sw); + sw.WriteLine(">"); + + sw.WriteLine("Non-Nulls:"); + sw.WriteLine("<"); + this.NonNulls.Dump(sw); + sw.WriteLine(">"); + + return sw.ToString (); + } } }
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AbstractInterpretationException.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AbstractInterpretationException.cs new file mode 100644 index 00000000000..878ae4e8d1f --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AbstractInterpretationException.cs @@ -0,0 +1,38 @@ +// +// AbstractInterpretationException.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class AbstractInterpretationException : Exception { + public AbstractInterpretationException (string message) + : base (message) + { + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysers.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysers.cs new file mode 100644 index 00000000000..afe03b5b4fc --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysers.cs @@ -0,0 +1,52 @@ +// +// Analysers.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.Analysis.Drivers; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static class Analysers { + public enum ArithmeticEnvironmentKind { + Intervals, + DisIntervals + } + + public class Arithmetic : IMethodAnalysis { + public string Name { get { return "Arithmetic"; } } + + public IMethodResult<TVar> Analyze<TExpr, TVar> (string fullMethodName, + IMethodDriver<TExpr, TVar> methodDriver) + where TVar : IEquatable<TVar> + where TExpr : IEquatable<TExpr> + { + return AnalysisFacade.RunArithmeticAnalysis (fullMethodName, methodDriver); + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.ConstantEvaluator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.ConstantEvaluator.cs new file mode 100644 index 00000000000..a98b340eb68 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.ConstantEvaluator.cs @@ -0,0 +1,150 @@ +// +// Analysis.ConstantEvaluator.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; +using Mono.CodeContracts.Static.Providers; +using Mono.CodeContracts.Static.Proving; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static partial class AnalysisFacade { + static partial class Bind<TVar, TExpr> + where TExpr : IEquatable<TExpr> + where TVar : IEquatable<TVar> { + class ConstantEvaluator { + readonly IExpressionContextProvider<TExpr, TVar> context_provider; + readonly IMetaDataProvider meta_data_provider; + + public ConstantEvaluator (IExpressionContextProvider<TExpr, TVar> contextProvider, + IMetaDataProvider metaDataProvider) + { + context_provider = contextProvider; + meta_data_provider = metaDataProvider; + } + + public bool TryEvaluateToConstant (APC pc, TVar dest, BinaryOperator op, + BoxedExpression left, BoxedExpression right, + out long value) + { + var type = + context_provider.ValueContext.GetType ( + context_provider.MethodContext.CFG.Post (pc), dest); + long l; + long r; + + if (type.IsNormal () && TryEvaluateToConstant (pc, left, out l) && + TryEvaluateToConstant (pc, right, out r)) + return TryEvaluate (type.Value, op, l, r, out value); + + return false.Without (out value); + } + + bool TryEvaluate (TypeNode type, BinaryOperator op, long l, long r, out long value) + { + if (TryEvaluateIndependent (op, l, r, out value)) + return true; + + if (meta_data_provider.System_Int32.Equals (type)) + return TryEvaluateInt32 (op, (int) l, (int) r, out value); + + return false.Without (out value); + } + + static bool TryEvaluateInt32 (BinaryOperator op, int l, int r, out long value) + { + int result; + if (EvaluateArithmeticWithOverflow.TryBinary (op.ToExpressionOperator (), l, r, + out result)) + return true.With (result, out value); + + return false.Without (out value); + } + + bool TryEvaluateIndependent (BinaryOperator op, long l, long r, out long result) + { + switch (op) { + case BinaryOperator.And: + return true.With (l & r, out result); + case BinaryOperator.Ceq: + return true.With (ToInt (l == r), out result); + case BinaryOperator.Cne_Un: + return true.With (ToInt (l != r), out result); + case BinaryOperator.Cge: + return true.With (ToInt (l >= r), out result); + case BinaryOperator.Cgt: + return true.With (ToInt (l > r), out result); + case BinaryOperator.Cle: + return true.With (ToInt (l <= r), out result); + case BinaryOperator.Clt: + return true.With (ToInt (l < r), out result); + case BinaryOperator.LogicalAnd: + return true.With (ToInt (l != 0 && r != 0), out result); + case BinaryOperator.LogicalOr: + return true.With (ToInt (l != 0 || r != 0), out result); + case BinaryOperator.Or: + return true.With (l | r, out result); + case BinaryOperator.Xor: + return true.With (l ^ r, out result); + default: + return false.Without (out result); + } + } + + static long ToInt (bool value) + { + return value ? 1 : 0; + } + + static bool TryEvaluateToConstant (APC pc, BoxedExpression e, out long result) + { + int res; + if (e.IsConstantIntOrNull (out res)) + return true.With (res, out result); + + long argValue; + if (e.IsUnary && TryEvaluateToConstant (pc, e.UnaryArgument, out argValue)) { + switch (e.UnaryOperator) { + case UnaryOperator.Neg: + return true.With (-argValue, out result); + case UnaryOperator.Not: + return true.With (argValue != 0 ? 0L : 1L, out result); + default: + throw new ArgumentOutOfRangeException (); + } + } + + return false.Without (out result); + } + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericNumericalAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericNumericalAnalysis.cs new file mode 100644 index 00000000000..68e4bb6dc97 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericNumericalAnalysis.cs @@ -0,0 +1,113 @@ +// +// Analysis.GenericNumericalAnalysis.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.Analysis.Drivers; +using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.DataFlowAnalysis; +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; +using Mono.CodeContracts.Static.Proving; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static partial class AnalysisFacade { + static partial class Bind<TVar, TExpr> where TExpr : IEquatable<TExpr> where TVar : IEquatable<TVar> { + class GenericNumericalAnalysis : + GenericValueAnalysis<INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression>> { + readonly Analysers.ArithmeticEnvironmentKind env_kind; + + public GenericNumericalAnalysis (string methodName, + IMethodDriver<TExpr, TVar> methodDriver, + Analysers.ArithmeticEnvironmentKind envKind) + : base (methodName, methodDriver) + { + env_kind = envKind; + } + + public override INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> + TopValue () + { + switch (env_kind) { + case Analysers.ArithmeticEnvironmentKind.Intervals: + return + new IntervalEnvironment<BoxedVariable<TVar>, BoxedExpression> ( + ExpressionDecoder); + case Analysers.ArithmeticEnvironmentKind.DisIntervals: + return + new DisIntervalEnvironment<BoxedVariable<TVar>, BoxedExpression> + (ExpressionDecoder); + default: + throw new AbstractInterpretationException ( + "Unknown arithmetic environment kind."); + } + } + + public override IFactQuery<BoxedExpression, TVar> FactQuery + (IFixPointInfo + <APC, INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> + > fixpoint) + { + return new ConstantPropagationFactQuery<TVar> (); + } + + public override INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> Entry + (APC pc, Method method, + INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> data) + { + foreach (var param in MetaDataProvider.Parameters (method).AsEnumerable ()) { + TVar variable; + var readAt = ContextProvider.MethodContext.CFG.Post (pc); + if (!ContextProvider.ValueContext.TryParameterValue (readAt, param, out variable)) + continue; + + var abstractType = ContextProvider.ValueContext.GetType (readAt, + variable); + if (abstractType.IsNormal () && MetaDataProvider.IsPrimitive (abstractType.Value)) + data = SetInitialRange (variable, abstractType.Value, data); + } + + return data; + } + + INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> SetInitialRange + (TVar variable, TypeNode type, + INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> data) + { + var interval = Interval.Ranges.GetIntervalForType (type, + MetaDataProvider); + if (interval.IsNormal ()) + data = data.AssumeVariableIn (new BoxedVariable<TVar> (variable), + interval); + return data; + } + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericValueAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericValueAnalysis.cs new file mode 100644 index 00000000000..1d443afa133 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericValueAnalysis.cs @@ -0,0 +1,275 @@ +// +// Analysis.GenericValueAnalysis.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.AST.Visitors; +using Mono.CodeContracts.Static.Analysis.Drivers; +using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.DataFlowAnalysis; +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; +using Mono.CodeContracts.Static.Providers; +using Mono.CodeContracts.Static.Proving; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static partial class AnalysisFacade { + static partial class Bind<TVar, TExpr> where TExpr : IEquatable<TExpr> where TVar : IEquatable<TVar> { + abstract class GenericValueAnalysis<TDomain> : + ILVisitorBase<APC, TVar, TVar, TDomain, TDomain>, + IAbstractAnalysis<TDomain, TVar>, + IMethodResult<TVar> + where TDomain : IEnvironmentDomain<TDomain, BoxedVariable<TVar>, BoxedExpression> { + readonly IMethodDriver<TExpr, TVar> method_driver; + //readonly string method_name; + + protected ConstantEvaluator EvaluatorOfConstants; + + protected IFixPointInfo<APC, TDomain> FixPointInfo; + BoxedExpressionDecoder<TVar, TExpr> expression_decoder; + + protected GenericValueAnalysis (string methodName, + IMethodDriver<TExpr, TVar> methodDriver) + { + ThresholdDB.Reset (); + BoxedVariable<TVar>.ResetFreshVariableCounter (); + + // method_name = methodName; + method_driver = methodDriver; + + EvaluatorOfConstants = new ConstantEvaluator (ContextProvider, + MetaDataProvider); + } + + protected IExpressionContextProvider<TExpr, TVar> ContextProvider { get { return method_driver.ContextProvider; } } + protected IMetaDataProvider MetaDataProvider { get { return method_driver.MetaDataProvider; } } + + protected BoxedExpressionDecoder<TVar, TExpr> ExpressionDecoder + { + get + { + if (expression_decoder == null) + expression_decoder = + new BoxedExpressionDecoder<TVar, TExpr> ( + new ValueExpressionDecoder<TVar, TExpr> ( + MetaDataProvider, + ContextProvider)); + return expression_decoder; + } + } + + public IILVisitor<APC, TVar, TVar, TDomain, TDomain> GetVisitor () + { + return this; + } + + public TDomain Join (Pair<APC, APC> edge, TDomain newstate, TDomain prevstate, + out bool weaker, bool widen) + { + TDomain result; + if (!widen) { + result = Join (newstate, prevstate, edge); + weaker = true; + } + else { + result = Widen (newstate, prevstate, edge); + weaker = !result.LessEqual (prevstate); + } + + return result; + } + + public TDomain ImmutableVersion (TDomain arg) + { + return arg; + } + + public TDomain MutableVersion (TDomain arg) + { + return arg.Clone (); + } + + public virtual TDomain EdgeConversion (APC @from, APC to, bool isJoinPoint, + IImmutableMap<TVar, Sequence<TVar>> + sourceTargetMap, TDomain state) + { + return state; + } + + public bool IsBottom (APC pc, TDomain state) + { + return state.IsBottom; + } + + public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, TDomain> fixPointInfo) + { + FixPointInfo = fixPointInfo; + return a => false; + } + + public void Dump (Pair<TDomain, TextWriter> pair) + { + pair.Value.WriteLine (pair.Key.ToString ()); + } + + public abstract TDomain TopValue (); + + public TDomain BottomValue () + { + return TopValue ().Bottom; + } + + public abstract IFactQuery<BoxedExpression, TVar> FactQuery ( + IFixPointInfo<APC, TDomain> fixpoint); + + IFactQuery<BoxedExpression, TVar> IMethodAnalysisFixPoint<TVar>.FactQuery { get { return FactQuery (FixPointInfo); } } + + public FlatDomain<bool> ValidateExplicitAssertion (APC pc, TVar value) + { + return FlatDomain<bool>.TopValue; + } + + public IMethodAnalysis MethodAnalysis { get; set; } + + public void ValidateImplicitAssertions (IFactQuery<BoxedExpression, TVar> facts, + List<string> proofResults) + { + } + + protected virtual TDomain Widen (TDomain newState, TDomain prevState, + Pair<APC, APC> edge) + { + return newState.Widen (prevState); + } + + protected virtual TDomain Join (TDomain newState, TDomain prevState, Pair<APC, APC> edge) + { + return newState.Join (prevState); + } + + public override TDomain Assume (APC pc, EdgeTag tag, TVar condition, TDomain data) + { + var boxed = ToBoxedExpression (pc, condition); + if (tag != EdgeTag.False) { + bool value; + if (boxed.IsTrivialCondition (out value)) + return !value ? data.Bottom : data; + } + + List<int> thresholds; + if (ThresholdDB.TryGetAThreshold (boxed, expression_decoder, out thresholds)) + ThresholdDB.Add (thresholds); + + TDomain result; + switch (tag) { + case EdgeTag.True: + case EdgeTag.Requires: + case EdgeTag.Assume: + case EdgeTag.Invariant: + result = data.AssumeTrue (boxed); + break; + case EdgeTag.False: + result = data.AssumeFalse (boxed); + break; + default: + result = data; + break; + } + + if (tag != EdgeTag.False) { + var abstractType = + ContextProvider.ValueContext.GetType ( + ContextProvider.MethodContext.CFG.Post (pc), condition); + if (abstractType.IsNormal () && + MetaDataProvider.Equal (abstractType.Value, + MetaDataProvider.System_Boolean)) { + var guard = + BoxedExpression.Binary (BinaryOperator.Ceq, boxed, + BoxedExpression.Const (1, + MetaDataProvider + . + System_Int32)); + + result = result.AssumeTrue (guard); + } + } + + return result; + } + + public override TDomain Assert (APC pc, EdgeTag tag, TVar condition, TDomain data) + { + var boxed = ToBoxedExpression (pc, condition); + + bool result; + if (boxed.IsTrivialCondition (out result)) + return result ? data : data.Bottom; + + data = data.AssumeTrue (boxed); + + var type = + ContextProvider.ValueContext.GetType ( + ContextProvider.MethodContext.CFG.Post (pc), condition); + if (type.IsNormal () && + MetaDataProvider.Equal (type.Value, MetaDataProvider.System_Boolean)) { + var guard = + BoxedExpression.Binary (BinaryOperator.Ceq, boxed, + BoxedExpression.Const (1, + MetaDataProvider. + System_Int32)); + + data = data.AssumeTrue (guard); + } + + return data; + } + + public override TDomain DefaultVisit (APC pc, TDomain data) + { + return data; + } + + protected BoxedExpression ToBoxedExpression (APC pc, TVar condition) + { + return + BoxedExpression.For ( + ContextProvider.ExpressionContext.Refine (pc, condition), + ExpressionDecoder.ExternalDecoder); + } + + public IFactQuery<BoxedExpression, TVar> FactQuery () + { + return FactQuery (FixPointInfo); + } + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.cs new file mode 100644 index 00000000000..5df5d37c685 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Analysis.cs @@ -0,0 +1,66 @@ +// +// Analysis.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.Analysis.Drivers; +using Mono.CodeContracts.Static.DataFlowAnalysis; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static partial class AnalysisFacade { + public static IMethodResult<TVar> RunArithmeticAnalysis<TVar, TExpr> (string methodName, + IMethodDriver<TExpr, TVar> + methodDriver) + where TVar : IEquatable<TVar> + where TExpr : IEquatable<TExpr> + { + return Bind<TVar, TExpr>.RunArithmeticAnalysis (methodName, methodDriver); + } + + static partial class Bind<TVar, TExpr> where TExpr : IEquatable<TExpr> where TVar : IEquatable<TVar> { + public static IMethodResult<TVar> RunArithmeticAnalysis (string methodName, + IMethodDriver<TExpr, TVar> methodDriver) + { + var analysis = new GenericNumericalAnalysis (methodName, methodDriver, + Analysers.ArithmeticEnvironmentKind. + DisIntervals); + return RunAnalysis (methodName, methodDriver, analysis); + } + + public static IMethodResult<TVar> RunAnalysis<TDomain> (string methodName, + IMethodDriver<TExpr, TVar> methodDriver, + IAbstractAnalysis<TDomain, TVar> + analysis) + { + methodDriver.HybridLayer.CreateForward (analysis).Invoke (analysis.TopValue ()); + + return analysis as IMethodResult<TVar>; + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AssumeFalseVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AssumeFalseVisitor.cs new file mode 100644 index 00000000000..b3b9613f26e --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AssumeFalseVisitor.cs @@ -0,0 +1,85 @@ +// +// AssumeFalseVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class AssumeFalseVisitor<TDomain, TVar, TExpr> : + GenericExpressionVisitor<TDomain, TDomain, TVar, TExpr> + where TDomain : IEnvironmentDomain<TDomain, TVar, TExpr> { + protected AssumeFalseVisitor (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + public AssumeTrueVisitor<TDomain, TVar, TExpr> TrueVisitor { get; set; } + + protected override TDomain Default (TDomain data) + { + return data; + } + + public override TDomain VisitConstant (TExpr left, TDomain data) + { + bool boolValue; + if (Decoder.TryValueOf (left, ExpressionType.Bool, out boolValue)) + return boolValue ? data : data.Bottom; + + int intValue; + if (Decoder.TryValueOf (left, ExpressionType.Int32, out intValue)) + return intValue != 0 ? data : data.Bottom; + + return data; + } + + public override TDomain VisitNot (TExpr expr, TDomain data) + { + return TrueVisitor.Visit (expr, data); + } + + public override TDomain VisitEqual (TExpr left, TExpr right, TExpr original, TDomain data) + { + int value; + if (Decoder.TryValueOf (right, ExpressionType.Int32, out value) && value == 0) + // test (left :neq: 0) ==> test (left) + return TrueVisitor.Visit (left, data); + + return TrueVisitor.VisitNotEqual (left, right, original, data); + } + + public override TDomain VisitLessThan (TExpr left, TExpr right, TExpr original, TDomain data) + { + // !(left < right) ==> right <= left + return TrueVisitor.VisitLessEqualThan (right, left, original, data); + } + + public override TDomain VisitLessEqualThan (TExpr left, TExpr right, TExpr original, TDomain data) + { + // !(left <= right) ==> right < left + return TrueVisitor.VisitLessThan (right, left, original, data); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AssumeTrueVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AssumeTrueVisitor.cs new file mode 100644 index 00000000000..e01ad11911c --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/AssumeTrueVisitor.cs @@ -0,0 +1,108 @@ +// +// AssumeTrueVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class AssumeTrueVisitor<TDomain, TVar, TExpr> : GenericExpressionVisitor<TDomain, TDomain, TVar, TExpr> + where TDomain : IEnvironmentDomain<TDomain, TVar, TExpr> { + protected AssumeTrueVisitor (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + public AssumeFalseVisitor<TDomain, TVar, TExpr> FalseVisitor { get; set; } + + protected override TDomain Default (TDomain data) + { + return data; + } + + public override TDomain VisitConstant (TExpr left, TDomain data) + { + bool boolValue; + if (Decoder.TryValueOf (left, ExpressionType.Bool, out boolValue)) + return boolValue ? data : data.Bottom; + + int intValue; + if (Decoder.TryValueOf (left, ExpressionType.Int32, out intValue)) + return intValue != 0 ? data : data.Bottom; + + return data; + } + + public override TDomain VisitLogicalAnd (TExpr left, TExpr right, TExpr original, TDomain data) + { + var leftIsVariable = Decoder.IsVariable (left); + var rightIsVariable = Decoder.IsVariable (right); + + var leftIsConstant = Decoder.IsConstant (left); + var rightIsConstant = Decoder.IsConstant (right); + + if (leftIsVariable && rightIsConstant || leftIsConstant && rightIsVariable) + return data; + + return data.AssumeTrue (left).AssumeTrue (right); + } + + public override TDomain VisitLogicalOr (TExpr left, TExpr right, TExpr original, TDomain data) + { + var leftIsVariable = Decoder.IsVariable (left); + var rightIsVariable = Decoder.IsVariable (right); + + var leftIsConstant = Decoder.IsConstant (left); + var rightIsConstant = Decoder.IsConstant (right); + + if (leftIsVariable && rightIsConstant || leftIsConstant && rightIsVariable) + return data; + + var leftBranch = data.AssumeTrue (left); + var rightBranch = data.AssumeTrue (right); + + return leftBranch.Join (rightBranch); + } + + public override TDomain VisitNot (TExpr expr, TDomain data) + { + return FalseVisitor.Visit (expr, data); + } + + protected override bool TryPolarity (TExpr expr, TDomain data, out bool shouldNegate) + { + if (base.TryPolarity (expr, data, out shouldNegate)) + return true; + + var holds = data.CheckIfHolds (expr); + if (!holds.IsNormal ()) + return false.Without (out shouldNegate); + + return true.With (!holds.Value, out shouldNegate); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionDecoder.cs new file mode 100644 index 00000000000..417905d2a20 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionDecoder.cs @@ -0,0 +1,291 @@ +// +// BoxedExpressionDecoder.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding; +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Proving; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class BoxedExpressionDecoder<TVar, TExpr> : IExpressionDecoder<BoxedVariable<TVar>, BoxedExpression> { + public IFullExpressionDecoder<TVar, TExpr> ExternalDecoder { get; private set; } + + public BoxedExpressionDecoder (IFullExpressionDecoder<TVar, TExpr> externalDecoder) + { + ExternalDecoder = externalDecoder; + } + + public ExpressionOperator OperatorFor (BoxedExpression expr) + { + if (expr.IsVariable) + return ExpressionOperator.Variable; + if (expr.IsConstant) + return ExpressionOperator.Constant; + if (expr.IsSizeof) + return ExpressionOperator.SizeOf; + if (expr.IsUnary) + switch (expr.UnaryOperator) { + case UnaryOperator.Conv_i: + case UnaryOperator.Conv_i4: + case UnaryOperator.Conv_i8: + return ExpressionOperator.ConvertToInt32; + case UnaryOperator.Neg: + return ExpressionOperator.UnaryMinus; + case UnaryOperator.Not: + return ExpressionOperator.Not; + default: + return ExpressionOperator.Unknown; + } + + if (!expr.IsBinary) + return ExpressionOperator.Unknown; + + switch (expr.BinaryOperator) { + case BinaryOperator.Add: + return ExpressionOperator.Add; + case BinaryOperator.And: + return ExpressionOperator.And; + case BinaryOperator.Ceq: + return ExpressionOperator.Equal; + case BinaryOperator.Cobjeq: + return ExpressionOperator.Equal_Obj; + case BinaryOperator.Cne_Un: + return ExpressionOperator.NotEqual; + case BinaryOperator.Cge: + return ExpressionOperator.GreaterEqualThan; + case BinaryOperator.Cgt: + return ExpressionOperator.GreaterThan; + case BinaryOperator.Cle: + return ExpressionOperator.LessEqualThan; + case BinaryOperator.Clt: + return ExpressionOperator.LessThan; + case BinaryOperator.Div: + return ExpressionOperator.Div; + case BinaryOperator.LogicalAnd: + return ExpressionOperator.LogicalAnd; + case BinaryOperator.LogicalOr: + return ExpressionOperator.LogicalOr; + case BinaryOperator.Mul: + return ExpressionOperator.Mult; + case BinaryOperator.Or: + return ExpressionOperator.Or; + case BinaryOperator.Rem: + return ExpressionOperator.Mod; + case BinaryOperator.Sub: + return ExpressionOperator.Sub; + case BinaryOperator.Xor: + return ExpressionOperator.Xor; + default: + return ExpressionOperator.Unknown; + } + } + + public BoxedExpression LeftExpressionFor (BoxedExpression expr) + { + if (expr.IsBinary) + return expr.BinaryLeftArgument; + if (expr.IsUnary) + return expr.UnaryArgument; + + throw new InvalidOperationException (); + } + + public BoxedExpression RightExpressionFor (BoxedExpression expr) + { + if (expr.IsBinary) + return expr.BinaryRightArgument; + + throw new InvalidOperationException (); + } + + public ExpressionType TypeOf (BoxedExpression expr) + { + if (expr.IsConstant) { + var constant = expr.Constant; + if (constant == null) + return ExpressionType.Unknown; + + var convertible = constant as IConvertible; + if (convertible != null) + switch (convertible.GetTypeCode ()) { + case TypeCode.Boolean: + return ExpressionType.Bool; + case TypeCode.Int32: + return ExpressionType.Int32; + case TypeCode.Single: + return ExpressionType.Float32; + case TypeCode.Double: + return ExpressionType.Float64; + } + + return ExpressionType.Unknown; + } + + if (expr.IsUnary) { + switch (expr.UnaryOperator) { + case UnaryOperator.Conv_i4: + return ExpressionType.Int32; + case UnaryOperator.Conv_r4: + return ExpressionType.Float32; + case UnaryOperator.Conv_r8: + case UnaryOperator.Conv_r_un: + return ExpressionType.Float64; + case UnaryOperator.Not: + return ExpressionType.Bool; + default: + return ExpressionType.Int32; + } + } + + if (expr.IsBinary) + switch (expr.BinaryOperator) { + case BinaryOperator.Add: + case BinaryOperator.Add_Ovf: + case BinaryOperator.Add_Ovf_Un: + case BinaryOperator.Div: + case BinaryOperator.Div_Un: + case BinaryOperator.Mul: + case BinaryOperator.Mul_Ovf: + case BinaryOperator.Mul_Ovf_Un: + case BinaryOperator.Rem: + case BinaryOperator.Rem_Un: + case BinaryOperator.Sub: + case BinaryOperator.Sub_Ovf: + case BinaryOperator.Sub_Ovf_Un: + return Join (TypeOf (expr.BinaryLeftArgument), + TypeOf (expr.BinaryRightArgument)); + case BinaryOperator.Ceq: + case BinaryOperator.Cobjeq: + case BinaryOperator.Cne_Un: + case BinaryOperator.Cge: + case BinaryOperator.Cge_Un: + case BinaryOperator.Cgt: + case BinaryOperator.Cgt_Un: + case BinaryOperator.Cle: + case BinaryOperator.Cle_Un: + case BinaryOperator.Clt: + case BinaryOperator.Clt_Un: + return ExpressionType.Bool; + default: + return ExpressionType.Int32; + } + + return ExpressionType.Unknown; + } + + public BoxedVariable<TVar> UnderlyingVariable (BoxedExpression expr) + { + var uv = expr.UnderlyingVariable; + if (uv is TVar) + return new BoxedVariable<TVar> ((TVar) expr.UnderlyingVariable); + + var boxed = uv as BoxedVariable<TVar>; + return boxed ?? BoxedVariable<TVar>.SlackVariable (); + } + + public bool IsConstant (BoxedExpression expr) + { + return expr.IsConstant; + } + + public bool IsVariable (BoxedExpression expr) + { + return expr.IsVariable; + } + + public bool TryValueOf<T> (BoxedExpression expr, ExpressionType type, out T result) + { + if (!expr.IsConstant) + return false.Without (out result); + + var constant = expr.Constant; + if (constant == null) + return false.Without (out result); + + if (constant is T) + return true.With ((T) constant, out result); + + if (constant is string) + return false.Without (out result); + + var convertible = constant as IConvertible; + if (convertible != null) + try { + return true.With ((T) convertible.ToType (typeof (T), null), out result); + } + catch { + } + + return false.Without (out result); + } + + public bool TrySizeOf (BoxedExpression expr, out int size) + { + return expr.Sizeof (out size); + } + + public bool IsNull (BoxedExpression expr) + { + return expr.IsConstant && expr.IsNull; + } + + public bool IsConstantInt (BoxedExpression expr, out int value) + { + return expr.IsConstantIntOrNull (out value); + } + + public string NameOf (BoxedVariable<TVar> variable) + { + return variable.ToString (); + } + + public bool IsBinaryExpression (BoxedExpression expr) + { + return expr.IsBinary; + } + + ExpressionType Join (ExpressionType left, ExpressionType right) + { + if (left == right) + return left; + if (left == ExpressionType.Unknown) + return right; + if (right == ExpressionType.Unknown) + return left; + + if (left == ExpressionType.Float32 || right == ExpressionType.Float32) + return ExpressionType.Float32; + if (left == ExpressionType.Float64 || right == ExpressionType.Float64) + return ExpressionType.Float64; + + return left; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionEncoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionEncoder.cs new file mode 100644 index 00000000000..6ba3c5314f0 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionEncoder.cs @@ -0,0 +1,149 @@ +// +// BoxedExpressionEncoder.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.Providers; +using Mono.CodeContracts.Static.Proving; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class BoxedExpressionEncoder<TVar> : IExpressionEncoder<BoxedVariable<TVar>, BoxedExpression> { + readonly IMetaDataProvider metadata; + + public BoxedExpressionEncoder (IMetaDataProvider metadata) + { + this.metadata = metadata; + } + + public void ResetFreshVariableCounter () + { + BoxedVariable<TVar>.ResetFreshVariableCounter (); + } + + public BoxedVariable<TVar> FreshVariable () + { + return BoxedVariable<TVar>.SlackVariable (); + } + + public BoxedExpression VariableFor (BoxedVariable<TVar> var) + { + return BoxedExpression.Var (var); + } + + public BoxedExpression ConstantFor (object value) + { + if (value is int) + return BoxedExpression.Const (value, metadata.System_Int32); + + if (value is long) { + var val = (long) value; + return val < int.MaxValue && val > int.MinValue + ? BoxedExpression.Const (val, metadata.System_Int32) + : BoxedExpression.Const (val, metadata.System_Int64); + } + + if (value is short) + return BoxedExpression.Const (value, metadata.System_Int16); + if (value is sbyte) + return BoxedExpression.Const (value, metadata.System_Int8); + if (value is bool) + return BoxedExpression.Const (value, metadata.System_Boolean); + + throw new NotSupportedException (); + } + + public BoxedExpression CompoundFor (ExpressionType type, ExpressionOperator op, BoxedExpression arg) + { + return BoxedExpression.Unary (ToUnaryOperator (op), arg); + } + + public BoxedExpression CompoundFor (ExpressionType type, ExpressionOperator op, BoxedExpression left, + BoxedExpression right) + { + return BoxedExpression.Binary (ToBinaryOperator (op), left, right); + } + + public static IExpressionEncoder<BoxedVariable<TVar>, BoxedExpression> Encoder ( + IMetaDataProvider provider) + { + return new BoxedExpressionEncoder<TVar> (provider); + } + + BinaryOperator ToBinaryOperator (ExpressionOperator op) + { + switch (op) { + case ExpressionOperator.And: + return BinaryOperator.And; + case ExpressionOperator.Or: + return BinaryOperator.Or; + case ExpressionOperator.Xor: + return BinaryOperator.Xor; + case ExpressionOperator.Equal: + return BinaryOperator.Ceq; + case ExpressionOperator.Equal_Obj: + return BinaryOperator.Cobjeq; + case ExpressionOperator.NotEqual: + return BinaryOperator.Cne_Un; + case ExpressionOperator.LessThan: + return BinaryOperator.Clt; + case ExpressionOperator.LessEqualThan: + return BinaryOperator.Cle_Un; + case ExpressionOperator.GreaterThan: + return BinaryOperator.Cgt; + case ExpressionOperator.GreaterEqualThan: + return BinaryOperator.Cge; + case ExpressionOperator.Add: + return BinaryOperator.Add; + case ExpressionOperator.Sub: + return BinaryOperator.Sub; + case ExpressionOperator.Mult: + return BinaryOperator.Mul; + case ExpressionOperator.Div: + return BinaryOperator.Div; + case ExpressionOperator.Mod: + return BinaryOperator.Rem; + + default: + throw new ArgumentOutOfRangeException ("op"); + } + } + + UnaryOperator ToUnaryOperator (ExpressionOperator op) + { + switch (op) { + case ExpressionOperator.Not: + return UnaryOperator.Not; + case ExpressionOperator.UnaryMinus: + return UnaryOperator.Neg; + default: + throw new ArgumentOutOfRangeException ("op"); + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedVariable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedVariable.cs new file mode 100644 index 00000000000..40623c6f0bf --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/BoxedVariable.cs @@ -0,0 +1,181 @@ +// +// BoxedVariable.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class BoxedVariable<TVar> : IEquatable<BoxedVariable<TVar>> { + readonly InnerVariable inner_variable; + readonly VariableKind kind; + readonly TVar variable; + + public BoxedVariable (TVar variable) + { + if (variable != null) { + this.variable = variable; + inner_variable = null; + kind = VariableKind.Normal; + } + else { + this.variable = default(TVar); + inner_variable = new InnerVariable (); + kind = VariableKind.Slack; + } + } + + BoxedVariable () + { + variable = default (TVar); + inner_variable = new InnerVariable (); + kind = VariableKind.Slack; + } + + public bool Equals (BoxedVariable<TVar> that) + { + if (ReferenceEquals (this, that)) + return true; + + if (ReferenceEquals (that, null)) + return false; + + if (inner_variable != null) + return inner_variable.Equals (that.inner_variable); + + return variable != null && variable.Equals (that.variable); + } + + public override bool Equals (object obj) + { + if (ReferenceEquals (this, obj)) + return true; + + if (obj is TVar && inner_variable == null) + return variable.Equals (obj); + + var that = obj as BoxedVariable<TVar>; + if (that != null) { + if (inner_variable != null) + return inner_variable.Equals (that.inner_variable); + + if (variable != null) + return variable.Equals (that.variable); + } + + return false; + } + + public override int GetHashCode () + { + return inner_variable != null + ? inner_variable.GetHashCode () + : variable.GetHashCode (); + } + + public override string ToString () + { + if (kind == VariableKind.Slack) + return "s" + inner_variable; + + if (inner_variable != null) + return inner_variable.ToString (); + + return variable.ToString (); + } + + public bool TryUnpackVariable (out TVar value) + { + if (inner_variable != null) + return false.Without (out value); + + return true.With (variable, out value); + } + + public static BoxedVariable<TVar> SlackVariable () + { + return new BoxedVariable<TVar> (); + } + + public static void ResetFreshVariableCounter () + { + InnerVariable.ResetFreshVariableCounter (); + } + + #region Nested type: InnerVariable + + class InnerVariable { + static int count; + static int start_count; + + readonly int id; + readonly int start_id; + + public InnerVariable () + { + id = count++; + start_id = start_count++; + } + + public override bool Equals (object obj) + { + if (ReferenceEquals (this, obj)) + return true; + + var innerVariable = obj as InnerVariable; + return innerVariable != null && innerVariable.id == id; + } + + public override int GetHashCode () + { + return id; + } + + public override string ToString () + { + return string.Format ("iv{0}", id - start_id); + } + + public static void ResetFreshVariableCounter () + { + start_count = count; + } + } + + #endregion + + #region Nested type: VariableKind + + enum VariableKind { + Normal, + Slack + } + + #endregion + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ConstToIntervalEvaluator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ConstToIntervalEvaluator.cs new file mode 100644 index 00000000000..d4e19ce47bb --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ConstToIntervalEvaluator.cs @@ -0,0 +1,73 @@ +// +// ConstToIntervalEvaluator.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class ConstToIntervalEvaluator<TContext, TVar, TExpr, TInterval, TNumeric> : + GenericTypeExpressionVisitor<TVar, TExpr, TContext, TInterval> + where TContext : IntervalContextBase<TInterval, TNumeric> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, TNumeric> { + public ConstToIntervalEvaluator (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + public override TInterval Visit (TExpr e, TContext ctx) + { + if (!ReferenceEquals (e, null) && Decoder.IsConstant (e)) + return base.Visit (e, ctx); + + return Default (e, ctx); + } + + protected override TInterval VisitBool (TExpr expr, TContext ctx) + { + bool value; + if (Decoder.TryValueOf (expr, ExpressionType.Bool, out value)) + return ctx.For (value ? 1L : 0L); + + return Default (expr, ctx); + } + + protected override TInterval VisitInt32 (TExpr expr, TContext ctx) + { + int value; + if (Decoder.TryValueOf (expr, ExpressionType.Int32, out value)) + return ctx.For (value); + + return Default (expr, ctx); + } + + protected override TInterval Default (TExpr expr, TContext ctx) + { + return ctx.TopValue; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ConstantEvaluatorVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ConstantEvaluatorVisitor.cs new file mode 100644 index 00000000000..97ced323ea1 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ConstantEvaluatorVisitor.cs @@ -0,0 +1,172 @@ +// +// ConstantEvaluatorVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class ConstantEvaluatorVisitor<In, Out> { + protected virtual bool Default (out Out result) + { + return false.Without (out result); + } + + protected bool VisitBinary (ExpressionOperator o, In left, In right, out Out result) + { + try { + switch (o) { + case ExpressionOperator.And: + return VisitAnd (left, right, out result); + case ExpressionOperator.Or: + return VisitOr (left, right, out result); + case ExpressionOperator.Xor: + return VisitXor (left, right, out result); + case ExpressionOperator.LogicalAnd: + return VisitLogicalAnd (left, right, out result); + case ExpressionOperator.LogicalOr: + return VisitLogicalOr (left, right, out result); + case ExpressionOperator.Equal: + case ExpressionOperator.Equal_Obj: + return VisitEqual (left, right, out result); + case ExpressionOperator.NotEqual: + return VisitNotEqual (left, right, out result); + case ExpressionOperator.LessThan: + return VisitLessThan (left, right, out result); + case ExpressionOperator.LessEqualThan: + return VisitLessEqualThan (left, right, out result); + case ExpressionOperator.GreaterThan: + return VisitGreaterThan (left, right, out result); + case ExpressionOperator.GreaterEqualThan: + return VisitGreaterEqualThan (left, right, out result); + case ExpressionOperator.Add: + return VisitAdd (left, right, out result); + case ExpressionOperator.Sub: + return VisitSub (left, right, out result); + case ExpressionOperator.Mult: + return VisitMult (left, right, out result); + case ExpressionOperator.Div: + return VisitDiv (left, right, out result); + case ExpressionOperator.Mod: + return VisitMod (left, right, out result); + case ExpressionOperator.Unknown: + return VisitUnknown (left, out result); + } + throw new ArgumentOutOfRangeException ("not implemented"); + } + catch (ArithmeticException) { + return false.Without (out result); + } + } + + protected virtual bool VisitMod (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitDiv (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitMult (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitSub (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitGreaterEqualThan (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitGreaterThan (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitLessEqualThan (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitLessThan (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitNotEqual (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitEqual (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitLogicalOr (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitLogicalAnd (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitXor (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitOr (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitAnd (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitAdd (In left, In right, out Out result) + { + return Default (out result); + } + + protected virtual bool VisitUnknown (In left, out Out result) + { + return Default (out result); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Counter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Counter.cs new file mode 100644 index 00000000000..4022a104796 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Counter.cs @@ -0,0 +1,55 @@ +// +// Counter.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + struct Counter<T> { + public readonly int Count; + public readonly T Env; + + public Counter (T env) + : this (env, 0) + { + } + + Counter (T env, int count) + { + Env = env; + Count = count; + } + + public Counter<T> Incremented () + { + return new Counter<T> (Env, Count + 1); + } + + public override string ToString () + { + return string.Format ("{0} ({1})", Env, Count); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisInterval.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisInterval.cs new file mode 100644 index 00000000000..38d421017ee --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisInterval.cs @@ -0,0 +1,594 @@ +// +// DisInterval.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class DisInterval : IntervalBase<DisInterval, Rational> { + public static readonly DisInterval NotZero = + For (Sequence<Interval>.From (Interval.For (Rational.MinusInfinity, -1L), + Interval.For (1L, Rational.PlusInfinity))); + + static DisInterval cached_bottom; + static DisInterval cached_top; + + readonly Sequence<Interval> intervals; + readonly Interval join_interval; + readonly State state; + + DisInterval (Interval interval) + : base (interval.LowerBound, interval.UpperBound) + { + var list = Sequence<Interval>.Empty; + if (interval.IsTop) + state = State.Top; + else if (interval.IsBottom) + state = State.Bottom; + else { + state = State.Normal; + list = list.Cons (interval); + } + + intervals = list; + join_interval = interval; + } + + DisInterval (Sequence<Interval> intervals) + : base (Rational.MinusInfinity, Rational.PlusInfinity) + { + bool isBottom; + this.intervals = Normalize (intervals, out isBottom); + + if (isBottom) { + join_interval = Interval.BottomValue; + state = State.Bottom; + + return; + } + + join_interval = JoinAll (intervals); + if (join_interval.IsBottom) + state = State.Bottom; + else if (join_interval.IsTop) + state = intervals.Length () <= 1 ? State.Top : State.Normal; + else { + LowerBound = join_interval.LowerBound; + UpperBound = join_interval.UpperBound; + state = State.Normal; + } + } + + DisInterval (State state) + : base (Rational.MinusInfinity, Rational.PlusInfinity) + { + this.state = state; + join_interval = state == State.Bottom ? Interval.BottomValue : Interval.TopValue; + intervals = Sequence<Interval>.Empty; + } + + public static DisInterval BottomValue { get { return cached_bottom ?? (cached_bottom = new DisInterval (State.Bottom)); } } + + public static DisInterval TopValue { get { return cached_top ?? (cached_top = new DisInterval (State.Top)); } } + + public Interval AsInterval { get { return join_interval; } } + + public override DisInterval Top { get { return TopValue; } } + + public override DisInterval Bottom { get { return BottomValue; } } + + public override bool IsTop { get { return state == State.Top; } } + + public override bool IsBottom { get { return state == State.Bottom; } } + + public bool IsNotZero + { + get + { + if (!this.IsNormal ()) + return false; + + return intervals.All (intv => !intv.Includes (0)); + } + } + + public bool IsPositiveOrZero { get { return this.IsNormal () && LowerBound >= 0L; } } + + public override bool Equals (object other) + { + if (ReferenceEquals (this, other)) + return true; + var that = other as DisInterval; + + if (that == null) { + var intv = other as Interval; + if (intv == null) + return false; + + return Equals (For (intv)); + } + + if (state == that.state && join_interval.Equals (that.join_interval)) + return HaveSameIntervals (intervals, that.intervals); + + return false; + } + + static bool HaveSameIntervals (Sequence<Interval> left, Sequence<Interval> right) + { + if (left.Length () != right.Length ()) + return false; + + var curLeft = left; + var curRight = right; + + while (!curLeft.IsEmpty ()) { + if (!curLeft.Head.Equals (curRight.Head)) + return false; + curLeft = curLeft.Tail; + curRight = curRight.Tail; + } + + return true; + } + + public override int GetHashCode () + { + unchecked { + return (state.GetHashCode () * 397) ^ + (join_interval != null ? join_interval.GetHashCode () : 0); + } + } + + public static Sequence<Interval> Normalize (Sequence<Interval> intervals, out bool isBottom) + { + if (intervals.Length () == 0) { + isBottom = false; + return intervals; + } + + Comparison<Interval> comparison = + (a, b) => a.Equals (b) ? 0 : a.UpperBound <= b.UpperBound ? -1 : 1; + + var intervalList = new List<Interval> (intervals.AsEnumerable ()); + intervalList.Sort (comparison); + + var list = Sequence<Interval>.Empty; + + var bottomCnt = 0; + Interval last = null; + + foreach (var t in intervalList) { + var cur = t; + + if (cur.IsBottom) + bottomCnt++; + else if (cur.IsTop) { + isBottom = false; + return Sequence<Interval>.Empty; + } + else if (!cur.Equals (last)) { + if (last != null) { + while (list != null) { + last = list.Head; + if (Interval.AreConsecutiveIntegers (last, cur)) { + list = list.Tail; + cur = last.Join (cur); + } + else if (last.LessEqual (cur)) + list = list.Tail; + else if (last.OverlapsWith (cur)) { + list = list.Tail; + cur = cur.Join (last); + } + else + break; + } + } + + last = cur; + list = list.Cons (cur); + } + } + + isBottom = bottomCnt == intervals.Length (); + return list.Reverse (); + } + + public static Interval JoinAll (Sequence<Interval> list) + { + if (list == null) + return Interval.TopValue; + + var res = list.Head; + + var cur = list.Tail; + while (cur != null) { + res = res.Join (cur.Head); + cur = cur.Tail; + } + + return res; + } + + protected override bool IsFiniteBound (Rational n) + { + return !n.IsInfinity; + } + + public static DisInterval operator + (DisInterval left, DisInterval right) + { + return OperatorLifting (left, right, (a, b) => a + b, true); + } + + public static DisInterval operator * (DisInterval left, DisInterval right) + { + return OperatorLifting (left, right, (a, b) => a * b, true); + } + + public static DisInterval operator / (DisInterval left, DisInterval right) + { + return OperatorLifting (left, right, (a, b) => a / b, true); + } + + public static DisInterval operator - (DisInterval left, DisInterval right) + { + return OperatorLifting (left, right, (a, b) => a - b, true); + } + + public static DisInterval operator - (DisInterval left) + { + if (left.IsBottom || left.IsTop) + return left; + + return For (left.intervals.Select (i => -i).Reverse ()); + } + + static DisInterval OperatorLifting (DisInterval left, DisInterval right, + Func<Interval, Interval, Interval> binop, bool propagateTop) + { + if (left.IsBottom || right.IsBottom) + return BottomValue; + + if ((propagateTop && (left.IsTop || right.IsTop)) || (left.IsTop && right.IsTop)) + return TopValue; + + var intervals = Sequence<Interval>.Empty; + + var hasNoNormals = true; + + if (propagateTop || (left.IsNormal () && right.IsNormal ())) + foreach (var leftIntv in left.intervals.AsEnumerable ()) + foreach (var rightIntv in right.intervals.AsEnumerable ()) { + var res = binop (leftIntv, rightIntv); + if (res.IsTop) + return TopValue; + if (res.IsBottom) + continue; + + hasNoNormals = false; + intervals = intervals.Cons (res); + } + else { + var notTop = left.IsTop ? right : left; + var rightIsTop = !left.IsTop; + + foreach (var intv in notTop.intervals.AsEnumerable ()) { + var res = rightIsTop + ? binop (intv, Interval.TopValue) + : binop (Interval.TopValue, intv); + + if (res.IsTop) + return TopValue; + if (res.IsBottom) + continue; + + hasNoNormals = false; + intervals = intervals.Cons (res); + } + } + + return hasNoNormals ? BottomValue : For (intervals.Reverse ()); + } + + public override DisInterval Widen (DisInterval that) + { + if (IsTop || that.IsTop) + return TopValue; + + return new DisInterval (Widen (intervals, that.intervals)); + } + + static Sequence<Interval> Widen (Sequence<Interval> left, Sequence<Interval> right) + { + if (left.IsEmpty () || right.IsEmpty ()) + return right; + if (left.Length () == 1 && right.Length () == 1) + return Sequence<Interval>.Singleton (left.Head.Widen (right.Head)); + + if (left.Length () == 1) { + if (left.Head.LessEqual (right.Head)) + return right; + return Sequence<Interval>.Singleton (left.Head.Widen (right.Head.Join (right.Last ()))); + } + + if (right.Length () == 1) + return Sequence<Interval>.Singleton (left.Head.Join (left.Last ()).Widen (right.Head)); + + var l = left.Head.Widen (right.Head); + var r = left.Last ().Widen (right.Last ()); + + var list = Sequence<Interval>.Singleton (l); + + var curRight = right.Tail; + while (curRight != null && curRight.Tail != null) { + var curLeft = left.Tail; + while (curLeft != null && curRight.Tail != null) + if (curLeft.Head.LessEqual (curRight.Head)) { + list = list.Cons (curRight.Head); + break; + } + } + list = list.Cons (r); + + return list.Reverse (); + } + + public override DisInterval Meet (DisInterval that) + { + DisInterval result; + if (this.TryTrivialMeet (that, out result)) + return result; + + bool isBottom; + var meetIntervals = Meet (intervals, that.intervals, out isBottom); + + if (isBottom) + return BottomValue; + if (meetIntervals.Length () == 0) + return TopValue; + + return For (meetIntervals); + } + + static Sequence<Interval> Meet (Sequence<Interval> left, Sequence<Interval> right, out bool isBottom) + { + isBottom = true; + var list = Sequence<Interval>.Empty; + foreach (var leftIntv in left.AsEnumerable ()) { + foreach (var rightIntv in right.AsEnumerable ()) { + var res = leftIntv.Meet (rightIntv); + if (res.IsNormal ()) { + isBottom = false; + list = list.Cons (res); + } + } + } + + return list.Reverse (); + } + + public override DisInterval ImmutableVersion () + { + return this; + } + + public override DisInterval Clone () + { + return this; + } + + public override void Dump (TextWriter tw) + { + } + + public override bool LessEqual (DisInterval that) + { + bool result; + if (this.TryTrivialLessEqual (that, out result)) + return result; + + if (!join_interval.LessEqual (that.join_interval)) + return false; + + return intervals.AsEnumerable ().All (inv => that.intervals.Any (inv.LessEqual)); + } + + public override DisInterval Join (DisInterval that, bool widening, out bool weaker) + { + weaker = false; + return Join (that); + } + + public override DisInterval Join (DisInterval that) + { + DisInterval result; + if (this.TryTrivialJoin (that, out result)) + return result; + + var join = Join (intervals, that.intervals); + if (join.IsEmpty ()) + return TopValue; + + return For (join); + } + + static Sequence<Interval> Join (Sequence<Interval> left, Sequence<Interval> right) + { + var list = Sequence<Interval>.Empty; + + var curLeft = left; + var curRight = right; + + while (!curLeft.IsEmpty () && !curRight.IsEmpty ()) { + var l = curLeft.Head; + var r = curRight.Head; + + if (l.IsTop || r.IsTop) + return Sequence<Interval>.Empty; + + if (l.IsBottom) + curLeft = curLeft.Tail; + else if (r.IsBottom) + curRight = curRight.Tail; + else if (l.LessEqual (r)) { + list = list.Cons (r); + curLeft = curLeft.Tail; + curRight = curRight.Tail; + } + else if (r.LessEqual (l)) { + list = list.Cons (l); + curLeft = curLeft.Tail; + curRight = curRight.Tail; + } + else if (r.OverlapsWith (l)) { + list = list.Cons (l.Join (r)); + curLeft = curLeft.Tail; + curRight = curRight.Tail; + } + else if (l.OnTheLeftOf (r)) { + list = list.Cons (l); + curLeft = curLeft.Tail; + } + else if (r.OnTheLeftOf (l)) { + list = list.Cons (r); + curRight = curRight.Tail; + } + } + + while (!curLeft.IsEmpty ()) { + list = list.Cons (curLeft.Head); + curLeft = curLeft.Tail; + } + + while (!curRight.IsEmpty ()) { + list = list.Cons (curRight.Head); + curRight = curRight.Tail; + } + + return list.Reverse (); + } + + public static DisInterval For (Interval interval) + { + return new DisInterval (interval); + } + + public static DisInterval For (Sequence<Interval> intervals) + { + return new DisInterval (intervals); + } + + public override string ToString () + { + if (IsTop) + return "Top"; + if (IsBottom) + return this.BottomSymbolIfAny (); + if (intervals != null && intervals.Length () == 1) + return intervals.Head.ToString (); + + return string.Format ("({0})", ToString (intervals)); + } + + string ToString (Sequence<Interval> list) + { + if (list == null) + return "null"; + + var sb = new StringBuilder (); + var first = true; + + foreach (var intv in list.AsEnumerable ()) { + if (first) + first = false; + else + sb.Append (" "); + + sb.Append (intv); + } + + return sb.ToString (); + } + + public DisInterval Select (Func<Interval, Interval> selector) + { + if (IsBottom) + return this; + if (IsTop) + return new DisInterval (selector (Interval.TopValue)); + + var list = Sequence<Interval>.Empty; + + for (var cur = intervals; cur != null; cur = cur.Tail) { + var intv = selector (cur.Head); + if (intv.IsBottom) + return Bottom; + if (intv.IsTop) + return Top; + + list = list.Cons (intv); + } + + return new DisInterval (list.Reverse ()); + } + + public static DisInterval EverythingExcept (DisInterval interval) + { + var left = Interval.For (Rational.MinusInfinity, interval.LowerBound - 1L); + var right = Interval.For (interval.UpperBound + 1L, Rational.PlusInfinity); + + if (left.IsNormal () && right.IsNormal ()) + return new DisInterval (Sequence<Interval>.From (left, right)); + + if (left.IsNormal ()) + return new DisInterval (left); + + if (right.IsNormal ()) + return new DisInterval (right); + + return TopValue; + } + + #region Nested type: State + + enum State { + Normal = 0, + Top, + Bottom + } + + #endregion + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalAssumer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalAssumer.cs new file mode 100644 index 00000000000..1264c29a5d2 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalAssumer.cs @@ -0,0 +1,69 @@ +// +// DisIntervalAssumer.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class DisIntervalAssumer<Var, Expr> : IntervalRationalAssumerBase<Var, Expr, DisInterval> + where Var : IEquatable<Var> { + public override IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> AssumeNotEqualToZero + (Var var, IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> env) + { + return AssumeEqualToDisInterval (var, DisInterval.NotZero, env); + } + + static IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> AssumeEqualToDisInterval + (Var var, DisInterval intv, IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> env) + { + return env.RefineVariable (var, intv); + } + + public override IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> AssumeNotEqual + (Expr left, Expr right, IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> env) + { + var result = env; + + var rightIntv = env.Eval (right); + if (rightIntv.IsSinglePoint) { + var everythingExcept = DisInterval.EverythingExcept (rightIntv); + result = result.RefineVariable (env.Decoder.UnderlyingVariable (left), everythingExcept); + } + + IntervalInference.InferenceResult<Var, DisInterval> resultLeft; + IntervalInference.InferenceResult<Var, DisInterval> resultRight; + IntervalInference.ConstraintsFor.NotEqual (left, right, env.Decoder, result, out resultLeft, + out resultRight); + + var join = resultLeft.Join (resultRight); + if (join.IsBottom) + return env.Bottom as IntervalEnvironmentBase<Var, Expr, DisInterval, Rational>; + + return AssumeConstraints (join.Constraints, env); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalContext.cs new file mode 100644 index 00000000000..f0714614634 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalContext.cs @@ -0,0 +1,139 @@ +// +// DisIntervalContext.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class DisIntervalContext : IntervalRationalContextBase<DisInterval> { + public static readonly DisIntervalContext Instance = new DisIntervalContext (); + + DisIntervalContext () + { + } + + public override DisInterval TopValue { get { return DisInterval.TopValue; } } + public override DisInterval BottomValue { get { return DisInterval.BottomValue; } } + + public override DisInterval Zero { get { return DisInterval.For (Interval.For (Rational.Zero)); } } + public override DisInterval One { get { return DisInterval.For (Interval.For (Rational.One)); } } + + public override DisInterval Positive { get { return DisInterval.For (Interval.For (Rational.Zero, Rational.PlusInfinity)); } } + public override DisInterval Negative { get { return DisInterval.For (Interval.For (Rational.MinusInfinity, Rational.Zero)); } } + + public override DisInterval GreaterEqualThanMinusOne { get { return DisInterval.For (Interval.For (Rational.MinusOne, Rational.PlusInfinity)); } } + + public override DisInterval For (long value) + { + return DisInterval.For (Interval.For (value)); + } + + public override DisInterval For (long lower, long upper) + { + return DisInterval.For (Interval.For (lower, upper)); + } + + public override DisInterval For (long lower, Rational upper) + { + return DisInterval.For (Interval.For (lower, upper)); + } + + public override DisInterval For (Rational lower, long upper) + { + return DisInterval.For (Interval.For (lower, upper)); + } + + public override DisInterval For (Rational value) + { + return DisInterval.For (Interval.For (value)); + } + + public override DisInterval For (Rational lower, Rational upper) + { + return DisInterval.For (Interval.For (lower, upper)); + } + + public override DisInterval Add (DisInterval a, DisInterval b) + { + return a + b; + } + + public override DisInterval Sub (DisInterval a, DisInterval b) + { + return a - b; + } + + public override DisInterval Div (DisInterval a, DisInterval b) + { + return a / b; + } + + public override DisInterval Rem (DisInterval a, DisInterval b) + { + return TopValue; + } + + public override DisInterval Mul (DisInterval a, DisInterval b) + { + return a * b; + } + + public override DisInterval Not (DisInterval value) + { + if (!value.IsNormal ()) + return value; + + if (value.IsNotZero) + return Zero; + + if (value.IsPositiveOrZero) + return Negative; + + return TopValue; + } + + public override DisInterval UnaryMinus (DisInterval value) + { + return -value; + } + + public override DisInterval ApplyConversion (ExpressionOperator conv, DisInterval intv) + { + return intv.Select ((i) => Interval.ApplyConversion (conv, i)); + } + + public override DisInterval RightOpen (Rational lowerBound) + { + return DisInterval.For (Interval.For (lowerBound, Rational.PlusInfinity)); + } + + public override DisInterval LeftOpen (Rational lowerBound) + { + return DisInterval.For (Interval.For (Rational.MinusInfinity, lowerBound)); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalEnvironment.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalEnvironment.cs new file mode 100644 index 00000000000..075b59fc31f --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalEnvironment.cs @@ -0,0 +1,73 @@ +// +// DisIntervalEnvironment.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class DisIntervalEnvironment<TVar, TExpr> : + IntervalEnvironmentBase<TVar, TExpr, DisInterval, Rational> where TVar : IEquatable<TVar> { + static DisIntervalAssumer<TVar, TExpr> cached_assumer; + + DisIntervalEnvironment (IExpressionDecoder<TVar, TExpr> decoder, + EnvironmentDomain<TVar, DisInterval> varsToInterval) + : base (decoder, varsToInterval) + { + } + + public DisIntervalEnvironment (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + public override IntervalAssumerBase<TVar, TExpr, DisInterval, Rational> Assumer + { + get + { + return cached_assumer ?? + (cached_assumer = new DisIntervalAssumer<TVar, TExpr> ()); + } + } + + public override IntervalContextBase<DisInterval, Rational> Context { get { return DisIntervalContext.Instance; } } + + protected override IntervalEnvironmentBase<TVar, TExpr, DisInterval, Rational> NewInstance ( + EnvironmentDomain<TVar, DisInterval> varsToIntervals) + { + return new DisIntervalEnvironment<TVar, TExpr> (Decoder, varsToIntervals); + } + + public override IntervalEnvironmentBase<TVar, TExpr, DisInterval, Rational> AssumeVariableIn (TVar var, + Interval + interval) + { + return RefineVariable (var, DisInterval.For (interval)); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/EvaluateArithmeticWithOverflow.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/EvaluateArithmeticWithOverflow.cs new file mode 100644 index 00000000000..0a99ef2359a --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/EvaluateArithmeticWithOverflow.cs @@ -0,0 +1,66 @@ +// +// EvaluateArithmeticWithOverflow.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static class EvaluateArithmeticWithOverflow { + public static bool TryBinary (ExpressionOperator op, long left, long right, out int res) + { + return LongToIntegerConstantEvaluator.Evaluate (op, left, right, out res); + } + + public static bool TryBinary (ExpressionOperator op, long left, long right, out uint res) + { + return false.Without (out res); + } + + public static bool TryBinary<In> (ExpressionType targetType, ExpressionOperator op, In left, In right, + out object res) + where In : struct + { + switch (targetType) { + case ExpressionType.Unknown: + case ExpressionType.Bool: + return false.Without (out res); + + case ExpressionType.Int32: + var l = left.ConvertToLong (); + var r = right.ConvertToLong (); + + int intValue; + if (l.HasValue && r.HasValue && TryBinary (op, l.Value, r.Value, out intValue)) + return true.With (intValue, out res); + + break; + } + + return false.Without (out res); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/EvaluateExpressionVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/EvaluateExpressionVisitor.cs new file mode 100644 index 00000000000..f63e5aa3c9c --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/EvaluateExpressionVisitor.cs @@ -0,0 +1,219 @@ +// +// EvaluateExpressionVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class EvaluateExpressionVisitor<TEnv, TVar, TExpr, TInterval, TNumeric> : + GenericExpressionVisitor<Counter<TEnv>, TInterval, TVar, TExpr> + where TEnv : IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, TNumeric> { + readonly + ConstToIntervalEvaluator + <IntervalContextBase<TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> constToIntv; + + readonly VariableOccurences occurences; + + public Sequence<TVar> DuplicatedOccurences { get { return occurences.Duplicated; } } + + public EvaluateExpressionVisitor (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + occurences = new VariableOccurences (decoder); + constToIntv = + new ConstToIntervalEvaluator + <IntervalContextBase<TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> ( + decoder); + } + + public override TInterval Visit (TExpr expr, Counter<TEnv> data) + { + if (data.Count >= 10) // to avoid recursion if any + return Default (data); + + var intv = base.Visit (expr, data.Incremented ()); + if (intv == null) + return Default (data); + + intv = RefineWithTypeRanges (intv, expr, data.Env); + + var var = Decoder.UnderlyingVariable (expr); + + TInterval current; + if (data.Env.TryGetValue (var, out current)) + intv = intv.Meet (current); + + return intv; + } + + public override TInterval VisitConstant (TExpr expr, Counter<TEnv> data) + { + return constToIntv.Visit (expr, data.Env.Context); + } + + public override TInterval VisitAddition (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Add (l, r)); + } + + public override TInterval VisitDivision (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Div (l, r)); + } + + public override TInterval VisitMultiply (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Mul (l, r)); + } + + public override TInterval VisitSubtraction (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Sub (l, r)); + } + + public override TInterval VisitEqual (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultComparisons (left, right, data); + } + + public override TInterval VisitLessThan (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultComparisons (left, right, data); + } + + public override TInterval VisitGreaterEqualThan (TExpr left, TExpr right, TExpr original, + Counter<TEnv> data) + { + return DefaultComparisons (left, right, data); + } + + public override TInterval VisitLessEqualThan (TExpr left, TExpr right, TExpr original, + Counter<TEnv> data) + { + return DefaultComparisons (left, right, data); + } + + public override TInterval VisitGreaterThan (TExpr left, TExpr right, TExpr original, Counter<TEnv> data) + { + return DefaultComparisons (left, right, data); + } + + public override TInterval VisitUnknown (TExpr expr, Counter<TEnv> data) + { + occurences.Add (expr); + + return Default (data); + } + + protected override TInterval Default (Counter<TEnv> data) + { + return data.Env.Context.TopValue; + } + + delegate TInterval BinaryEvaluator (Counter<TEnv> env, TInterval left, TInterval right); + + TInterval DefaultBinary (TExpr left, TExpr right, Counter<TEnv> data, BinaryEvaluator binop) + { + occurences.Add (left, right); + + var incremented = data.Incremented (); + var leftIntv = Visit (left, incremented); + var rightIntv = Visit (right, incremented); + + return binop (data, leftIntv, rightIntv); + } + + TInterval DefaultComparisons (TExpr left, TExpr right, Counter<TEnv> data) + { + occurences.Add (left, right); + + return Default (data); + } + + TInterval RefineWithTypeRanges (TInterval intv, TExpr expr, TEnv env) + { + switch (Decoder.TypeOf (expr)) { + case ExpressionType.Int32: + return env.Context.ApplyConversion (ExpressionOperator.ConvertToInt32, intv); + case ExpressionType.Bool: + return env.Context.ApplyConversion (ExpressionOperator.ConvertToInt32, intv); + default: + return intv; + } + } + + class VariableOccurences { + readonly Dictionary<TVar, int> occurences; + + readonly IExpressionDecoder<TVar, TExpr> decoder; + + Sequence<TVar> duplicated; + + public VariableOccurences (IExpressionDecoder<TVar, TExpr> decoder) + { + this.decoder = decoder; + occurences = new Dictionary<TVar, int> (); + duplicated = Sequence<TVar>.Empty; + } + + public Sequence<TVar> Duplicated { get { return duplicated; } } + + void Add (TVar var) + { + int cnt; + if (!occurences.TryGetValue (var, out cnt)) + cnt = 0; + + occurences[var] = cnt + 1; + + if (cnt == 1) // if already was occurence + duplicated = duplicated.Cons (var); + } + + public void Add (TExpr e) + { + Add (decoder.UnderlyingVariable (e)); + } + + public void Add (params TExpr[] exprs) + { + foreach (var expr in exprs) + Add (expr); + } + + public override string ToString () + { + return occurences.ToString (); + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionOperator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionOperator.cs new file mode 100644 index 00000000000..076b431cef9 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionOperator.cs @@ -0,0 +1,115 @@ +// +// ExpressionOperator.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + enum ExpressionOperator { + Constant, + Variable, + Not, + And, + Or, + Xor, + LogicalAnd, + LogicalOr, + LogicalNot, + Equal, + Equal_Obj, + NotEqual, + LessThan, + LessEqualThan, + GreaterThan, + GreaterEqualThan, + Add, + Sub, + Mult, + Div, + Mod, + UnaryMinus, + SizeOf, + Unknown, + + ConvertToInt32 + } + + static class ExpressionOperatorExtensions { + static readonly HashSet<ExpressionOperator> relationalOperators = new HashSet<ExpressionOperator> (); + + static ExpressionOperatorExtensions () + { + relationalOperators.Add (ExpressionOperator.LessThan); + relationalOperators.Add (ExpressionOperator.LessEqualThan); + relationalOperators.Add (ExpressionOperator.GreaterThan); + relationalOperators.Add (ExpressionOperator.GreaterEqualThan); + relationalOperators.Add (ExpressionOperator.Equal); + relationalOperators.Add (ExpressionOperator.Equal_Obj); + relationalOperators.Add (ExpressionOperator.NotEqual); + } + + public static bool IsUnary (this ExpressionOperator op) + { + return op == ExpressionOperator.UnaryMinus || op == ExpressionOperator.Not; + } + + public static bool IsZerary (this ExpressionOperator op) + { + return op == ExpressionOperator.Constant || op == ExpressionOperator.Variable; + } + + public static bool IsBinary (this ExpressionOperator op) + { + return !op.IsUnary () && !op.IsZerary (); + } + + public static bool IsGreaterThan (this ExpressionOperator op) + { + return op == ExpressionOperator.GreaterThan; + } + + public static bool IsGreaterEqualThan (this ExpressionOperator op) + { + return op == ExpressionOperator.GreaterEqualThan; + } + + public static bool IsLessThan (this ExpressionOperator op) + { + return op == ExpressionOperator.LessThan; + } + + public static bool IsLessEqualThan (this ExpressionOperator op) + { + return op == ExpressionOperator.LessEqualThan; + } + + public static bool IsRelational (this ExpressionOperator op) + { + return relationalOperators.Contains (op); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionType.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionType.cs new file mode 100644 index 00000000000..7bfcdb4271a --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionType.cs @@ -0,0 +1,37 @@ +// +// ExpressionType.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + enum ExpressionType { + Unknown, + Int32, + Float32, + Float64, + Bool + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionViaStringComparer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionViaStringComparer.cs new file mode 100644 index 00000000000..3c0ca4563d4 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ExpressionViaStringComparer.cs @@ -0,0 +1,38 @@ +// +// ExpressionViaStringComparer.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class ExpressionViaStringComparer<TVar> : IComparer<TVar> { + public int Compare (TVar x, TVar y) + { + return System.String.CompareOrdinal(x.ToString (), y.ToString ()); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GenericExpressionVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GenericExpressionVisitor.cs new file mode 100644 index 00000000000..884fe98e384 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GenericExpressionVisitor.cs @@ -0,0 +1,338 @@ +// +// GenericExpressionVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.DataStructures; + +using Op = Mono.CodeContracts.Static.Analysis.Numerical.ExpressionOperator; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class GenericExpressionVisitor<In, Out, Var, Expr> { + protected readonly IExpressionDecoder<Var, Expr> Decoder; + + protected GenericExpressionVisitor (IExpressionDecoder<Var, Expr> decoder) + { + Decoder = decoder; + } + + public virtual Out Visit (Expr expr, In data) + { + var op = Decoder.OperatorFor (expr); + switch (op) { + case Op.Constant: + return VisitConstant (expr, data); + case Op.Variable: + return VisitVariable (Decoder.UnderlyingVariable (expr), expr, data); + case Op.Not: + return DispatchVisitNot (Decoder.LeftExpressionFor (expr), data); + case Op.And: + return VisitAnd (Decoder.LeftExpressionFor (expr), Decoder.RightExpressionFor (expr), + expr, data); + case Op.Or: + return VisitOr (Decoder.LeftExpressionFor (expr), Decoder.RightExpressionFor (expr), + expr, data); + case Op.Xor: + return VisitXor (Decoder.LeftExpressionFor (expr), Decoder.RightExpressionFor (expr), + expr, data); + case Op.LogicalAnd: + return VisitLogicalAnd (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.LogicalOr: + return VisitLogicalOr (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.NotEqual: + return VisitNotEqual (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + + case Op.Equal: + case Op.Equal_Obj: + return DispatchVisitEqual (op, Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + + case Op.LessThan: + return DispatchCompare (VisitLessThan, Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.LessEqualThan: + return DispatchCompare (VisitLessEqualThan, Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.GreaterThan: + return DispatchCompare (VisitGreaterThan, Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.GreaterEqualThan: + return DispatchCompare (VisitGreaterEqualThan, Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + + case Op.Add: + return VisitAddition (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.Div: + return VisitDivision (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.Sub: + return VisitSubtraction (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case Op.Mod: + return VisitModulus (Decoder.LeftExpressionFor (expr), Decoder.RightExpressionFor (expr), + expr, data); + case Op.Mult: + return VisitMultiply (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + + case Op.SizeOf: + return VisitSizeOf (Decoder.LeftExpressionFor (expr), data); + case Op.UnaryMinus: + return VisitUnaryMinus (Decoder.LeftExpressionFor (expr), expr, data); + case Op.LogicalNot: + return VisitLogicalNot (Decoder.LeftExpressionFor (expr), expr, data); + case Op.Unknown: + return VisitUnknown (expr, data); + default: + throw new ArgumentOutOfRangeException (); + } + } + + public virtual Out VisitVariable (Var var, Expr expr, In data) + { + return Default (data); + } + + public virtual Out VisitConstant (Expr expr, In data) + { + return Default (data); + } + + public virtual Out VisitLogicalNot (Expr left, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitUnaryMinus (Expr left, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitNot (Expr expr, In data) + { + return Default (data); + } + + public virtual Out VisitSizeOf (Expr expr, In data) + { + return Default (data); + } + + public virtual Out VisitUnknown (Expr expr, In data) + { + return Default (data); + } + + public virtual Out VisitLessThan (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitLessEqualThan (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitGreaterThan (Expr left, Expr right, Expr original, In data) + { + return DispatchCompare (VisitLessEqualThan, right, left, original, data); + } + + public virtual Out VisitGreaterEqualThan (Expr left, Expr right, Expr original, In data) + { + return DispatchCompare (VisitLessThan, right, left, original, data); + } + + public virtual Out VisitNotEqual (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitAddition (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitSubtraction (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitMultiply (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitModulus (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitDivision (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitEqual (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitLogicalOr (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitLogicalAnd (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitXor (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitOr (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + public virtual Out VisitAnd (Expr left, Expr right, Expr original, In data) + { + return Default (data); + } + + protected virtual bool TryPolarity (Expr expr, In data, out bool shouldNegate) + { + if (Decoder.IsConstant (expr)) { + int intValue; + if (Decoder.TryValueOf (expr, ExpressionType.Int32, out intValue)) + return true.With (intValue == 0, out shouldNegate); + + bool boolValue; + if (Decoder.TryValueOf (expr, ExpressionType.Bool, out boolValue)) + return true.With (boolValue, out shouldNegate); + } + + return false.Without (out shouldNegate); + } + + protected delegate Out CompareVisitor (Expr left, Expr right, Expr original, In data); + + protected virtual Out DispatchCompare (CompareVisitor cmp, Expr left, Expr right, Expr original, In data) + { + if (Decoder.IsConstant (left) && Decoder.OperatorFor (right) == ExpressionOperator.Sub) + // const OP (a - b) + { + int num; + if (Decoder.TryValueOf (left, ExpressionType.Int32, out num) && num == 0) + // 0 OP (a-b) ==> b OP a + return cmp (Decoder.RightExpressionFor (right), + Decoder.LeftExpressionFor (right), right, data); + } + else if (Decoder.IsConstant (right) && Decoder.OperatorFor (left) == ExpressionOperator.Sub) + // (a-b) OP const + { + int num; + if (Decoder.TryValueOf (right, ExpressionType.Int32, out num) && num == 0) + // (a-b) OP 0 ==> a OP b + return cmp (Decoder.LeftExpressionFor (left), + Decoder.RightExpressionFor (left), left, data); + } + + return cmp (left, right, original, data); + } + + protected abstract Out Default (In data); + + Out DispatchVisitNot (Expr expr, In data) + { + switch (Decoder.OperatorFor (expr)) { + case ExpressionOperator.Equal: + case ExpressionOperator.Equal_Obj: + return VisitNotEqual (Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case ExpressionOperator.LessThan: // a < b ==> b <= a + return DispatchCompare (VisitLessEqualThan, Decoder.RightExpressionFor (expr), + Decoder.LeftExpressionFor (expr), expr, data); + case ExpressionOperator.LessEqualThan: // a <= b ==> b < a + return DispatchCompare (VisitLessThan, Decoder.LeftExpressionFor (expr), + Decoder.RightExpressionFor (expr), expr, data); + case ExpressionOperator.GreaterThan: // a > b ==> b < a + return DispatchCompare (VisitLessThan, Decoder.RightExpressionFor (expr), + Decoder.LeftExpressionFor (expr), expr, data); + case ExpressionOperator.GreaterEqualThan: // a >= b ==> b <= a + return DispatchCompare (VisitLessEqualThan, Decoder.RightExpressionFor (expr), + Decoder.LeftExpressionFor (expr), expr, data); + default: + return VisitNot (expr, data); + } + } + + Out DispatchVisitEqual (ExpressionOperator eqKind, Expr left, Expr right, Expr original, In data) + { + // { left :eq: right } + switch (Decoder.OperatorFor (left)) { + case Op.GreaterEqualThan: + case Op.GreaterThan: + case Op.LessThan: + case Op.LessEqualThan: + case Op.Equal: + case Op.Equal_Obj: + // { ( a ?= b ) :eq: right } + bool shouldNegate; + if (TryPolarity (right, data, out shouldNegate)) + // { (a ?= b) :eq: true => (a ?= b) }; (a ?= b) :eq: false => !(a ?= b) } + return shouldNegate ? DispatchVisitNot (left, data) : Visit (left, data); + break; + } + + switch (Decoder.OperatorFor (right)) { + case Op.GreaterEqualThan: + case Op.GreaterThan: + case Op.LessThan: + case Op.LessEqualThan: + case Op.Equal: + case Op.Equal_Obj: + // { left :eq: (a ?= b) } + bool shouldNegate; + if (TryPolarity (left, data, out shouldNegate)) + // { true :eq: (a ?= b) => (a ?= b) }; false :eq: (a ?= b) => !(a ?= b) } + return shouldNegate ? DispatchVisitNot (right, data) : Visit (right, data); + break; + } + + return VisitEqual (left, right, original, data); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GenericTypeExpressionVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GenericTypeExpressionVisitor.cs new file mode 100644 index 00000000000..3d6fcdd347f --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GenericTypeExpressionVisitor.cs @@ -0,0 +1,65 @@ +// +// GenericTypeExpressionVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class GenericTypeExpressionVisitor<TVariable, TExpression, TIn, TOut> { + protected readonly IExpressionDecoder<TVariable, TExpression> Decoder; + + protected GenericTypeExpressionVisitor (IExpressionDecoder<TVariable, TExpression> decoder) + { + Decoder = decoder; + } + + public virtual TOut Visit (TExpression e, TIn input) + { + switch (Decoder.TypeOf (e)) { + case ExpressionType.Unknown: + return Default (e, input); + case ExpressionType.Int32: + return VisitInt32 (e, input); + case ExpressionType.Bool: + return VisitBool (e, input); + default: + throw new AbstractInterpretationException ("Unknown type for expressions " + + Decoder.TypeOf (e)); + } + } + + protected virtual TOut VisitBool (TExpression expr, TIn input) + { + return Default (expr, input); + } + + protected virtual TOut VisitInt32 (TExpression expr, TIn input) + { + return Default (expr, input); + } + + protected abstract TOut Default (TExpression expr, TIn input); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GetThresholdVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GetThresholdVisitor.cs new file mode 100644 index 00000000000..36f7f15896c --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/GetThresholdVisitor.cs @@ -0,0 +1,95 @@ +// +// GetThresholdVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class GetThresholdVisitor<TVar, TExpr> : GenericExpressionVisitor<Dummy, bool, TVar, TExpr> { + public List<int> Thresholds { get; private set; } + + public GetThresholdVisitor (IExpressionDecoder<TVar, TExpr> decoder) : base (decoder) + { + Thresholds = new List<int> (); + } + + protected override bool Default (Dummy data) + { + return false; + } + + public override bool VisitConstant (TExpr expr, Dummy data) + { + int value; + if (Decoder.IsConstantInt (expr, out value)) + return false; + + Thresholds.Add (value); + return true; + } + + public override bool VisitLessThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return VisitBinary (left, right, data); + } + + public override bool VisitLessEqualThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return VisitBinary (left, right, data); + } + + public override bool VisitGreaterThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return VisitBinary (left, right, data); + } + + public override bool VisitGreaterEqualThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return VisitBinary (left, right, data); + } + + public override bool VisitNotEqual (TExpr left, TExpr right, TExpr original, Dummy data) + { + return VisitBinary (left, right, data); + } + + public override bool VisitEqual (TExpr left, TExpr right, TExpr original, Dummy data) + { + return VisitBinary (left, right, data); + } + + bool VisitBinary (TExpr left, TExpr right, Dummy data) + { + var gatheredFromLeft = Visit (left, data); + var gatheredFromRight = Visit (right, data); + + return gatheredFromLeft || gatheredFromRight; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IEnvironmentDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IEnvironmentDomain.cs new file mode 100644 index 00000000000..94a396f9012 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IEnvironmentDomain.cs @@ -0,0 +1,39 @@ +// +// IEnvironmentDomain.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + interface IEnvironmentDomain<TDomain, TVar, TExpr> : IAbstractDomain<TDomain> { + TDomain AssumeTrue (TExpr guard); + TDomain AssumeFalse (TExpr guard); + + FlatDomain<bool> CheckIfHolds (TExpr expr); + string ToString (TExpr expr); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IExpressionDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IExpressionDecoder.cs new file mode 100644 index 00000000000..129f5d8feb0 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IExpressionDecoder.cs @@ -0,0 +1,53 @@ +// +// IExpressionDecoder.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + interface IExpressionDecoder<TVariable, TExpression> { + ExpressionOperator OperatorFor (TExpression expr); + TExpression LeftExpressionFor (TExpression expr); + TExpression RightExpressionFor (TExpression expr); + + TVariable UnderlyingVariable (TExpression expr); + + bool IsConstant (TExpression expr); + bool IsVariable (TExpression expr); + + bool TryValueOf<T> (TExpression left, ExpressionType type, out T result); + + bool TrySizeOf (TExpression expr, out int size); + + ExpressionType TypeOf (TExpression expr); + + bool IsNull (TExpression expr); + + bool IsConstantInt (TExpression expr, out int value); + string NameOf (TVariable variable); + + bool IsBinaryExpression (TExpression expr); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IExpressionEncoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IExpressionEncoder.cs new file mode 100644 index 00000000000..98c3ef62866 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IExpressionEncoder.cs @@ -0,0 +1,38 @@ +// +// IExpressionEncoder.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + interface IExpressionEncoder<TVar, TExpr> { + void ResetFreshVariableCounter (); + TVar FreshVariable (); + TExpr VariableFor (TVar var); + TExpr ConstantFor (object value); + TExpr CompoundFor (ExpressionType type, ExpressionOperator op, TExpr arg); + TExpr CompoundFor (ExpressionType type, ExpressionOperator op, TExpr left, TExpr right); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IIntervalEnvironment.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IIntervalEnvironment.cs new file mode 100644 index 00000000000..c1a15cc3757 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IIntervalEnvironment.cs @@ -0,0 +1,68 @@ +// +// IIntervalEnvironment.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + interface INumericalEnvironmentDomain<TVar, TExpr> : + IEnvironmentDomain<INumericalEnvironmentDomain<TVar, TExpr>, TVar, TExpr> { + INumericalEnvironmentDomain<TVar, TExpr> AssumeVariableIn (TVar var, Interval interval); + INumericalEnvironmentDomain<TVar, TExpr> AssumeLessEqualThan (TExpr left, TExpr right); + } + + interface IIntervalEnvironment<TVar, TExpr, TInterval, TNumeric> : INumericalEnvironmentDomain<TVar, TExpr> + where TInterval : IntervalBase<TInterval, TNumeric> { + IntervalContextBase<TInterval, TNumeric> Context { get; } + + TInterval Eval (TExpr expr); + TInterval Eval (TVar expr); + + bool TryGetValue (TVar rightVar, out TInterval intv); + } + + static class NumericalEnvironmentDomainExtensions { + public static INumericalEnvironmentDomain<TVar, TExpr> AssumeInInterval<TVar, TExpr> ( + this INumericalEnvironmentDomain<TVar, TExpr> domain, TExpr expr, Interval intv, + IExpressionEncoder<TVar, TExpr> encoder) + { + if (!domain.IsNormal ()) + return domain; + + if (intv.IsBottom) + return domain.Bottom; + + if (!intv.LowerBound.IsInfinity) + domain = domain.AssumeLessEqualThan (intv.LowerBound.ToExpression (encoder), expr); + + if (!intv.UpperBound.IsInfinity) + domain = domain.AssumeLessEqualThan (expr, intv.LowerBound.ToExpression (encoder)); + + return domain; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Interval.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Interval.cs new file mode 100644 index 00000000000..d473ca6b400 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Interval.cs @@ -0,0 +1,404 @@ +// +// Interval.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; +using Mono.CodeContracts.Static.Providers; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + /// <summary> + /// Represents a closed interval of <see cref="Rational"/> values. + /// </summary> + class Interval : IntervalBase<Interval, Rational>, IEquatable<Interval> { + static Interval cached_top_value; + static Interval cached_bottom_value; + + readonly bool is_bottom; + readonly bool is_top; + + Interval (Rational lowerBound, Rational upperBound) + : base (lowerBound, upperBound) + { + if (lowerBound.IsMinusInfinity && upperBound.IsPlusInfinity || + lowerBound.IsMinusInfinity && upperBound.IsMinusInfinity || + lowerBound.IsPlusInfinity && upperBound.IsPlusInfinity) { + LowerBound = Rational.MinusInfinity; + UpperBound = Rational.PlusInfinity; + is_top = true; + } + + is_bottom = LowerBound > UpperBound; + } + + public static Interval TopValue + { + get + { + if (ReferenceEquals (cached_top_value, null)) + cached_top_value = new Interval (Rational.MinusInfinity, Rational.PlusInfinity); + return cached_top_value; + } + } + + public static Interval BottomValue + { + get + { + if (ReferenceEquals (cached_bottom_value, null)) + cached_bottom_value = new Interval (Rational.PlusInfinity, + Rational.MinusInfinity); + return cached_bottom_value; + } + } + + public override Interval Top { get { return TopValue; } } + public override Interval Bottom { get { return BottomValue; } } + + public override bool IsTop { get { return is_top; } } + public override bool IsBottom { get { return is_bottom; } } + + public override bool LessEqual (Interval that) + { + bool result; + if (this.TryTrivialLessEqual (that, out result)) + return result; + + //less equal <==> is included in + return LowerBound >= that.LowerBound && UpperBound <= that.UpperBound; + } + + public bool LessEqual (IEnumerable<Interval> right) + { + return right.Any (LessEqual); + } + + public override Interval Join (Interval that, bool widening, out bool weaker) + { + weaker = false; + + return widening ? Widen (that) : Join (that); + } + + public override Interval Join (Interval that) + { + Interval result; + if (this.TryTrivialJoin (that, out result)) + return result; + + return For (Rational.Min (LowerBound, that.LowerBound), + Rational.Max (UpperBound, that.UpperBound)); + } + + public override Interval Widen (Interval that) + { + Interval result; + if (this.TryTrivialJoin (that, out result)) + return result; + + return For (LowerBound < that.LowerBound + ? ThresholdDB.GetPrevious (LowerBound) + : that.LowerBound, + UpperBound > that.UpperBound + ? ThresholdDB.GetNext (UpperBound) + : that.UpperBound); + } + + public override Interval Meet (Interval that) + { + Interval result; + if (this.TryTrivialMeet (that, out result)) + return result; + + return For ( + Rational.Max (LowerBound, that.LowerBound), + Rational.Min (UpperBound, that.UpperBound)); + } + + public static Interval For (Rational lowerBound, Rational upperBound) + { + return new Interval (lowerBound, upperBound); + } + + public static Interval For (Rational lowerBound, long upperBound) + { + return For (lowerBound, Rational.For (upperBound)); + } + + public static Interval For (long lowerBound, long upperBound) + { + return For (Rational.For (lowerBound), Rational.For (upperBound)); + } + + public static Interval For (long lower, Rational upperBound) + { + return For (Rational.For (lower), upperBound); + } + + public static Interval For (Rational value) + { + return For (value, value); + } + + public static Interval For (long value) + { + return For (Rational.For (value)); + } + + public static Interval operator + (Interval l, Interval r) + { + if (l.IsBottom || r.IsBottom) + return BottomValue; + + Rational lower, upper; + if (l.IsTop || r.IsTop + || !Rational.TryAdd (l.LowerBound, r.LowerBound, out lower) + || !Rational.TryAdd (l.UpperBound, r.UpperBound, out upper)) + return TopValue; + + return For (lower, upper); + } + + public static Interval operator - (Interval l, Interval r) + { + if (l.IsBottom || r.IsBottom) + return BottomValue; + + Rational lower, upper; + if (l.IsTop || r.IsTop + || !Rational.TrySubtract (l.LowerBound, r.UpperBound, out lower) + || !Rational.TrySubtract (l.UpperBound, r.LowerBound, out upper)) + return TopValue; + + return For (lower, upper); + } + + public static Interval operator / (Interval l, Interval r) + { + if (l.IsBottom || r.IsBottom) + return BottomValue; + + Rational a, b, c, d; + if (l.IsTop || r.IsTop || r.Includes (0) + || !Rational.TryDivide (l.LowerBound, r.UpperBound, out a) + || !Rational.TryDivide (l.LowerBound, r.LowerBound, out b) + || !Rational.TryDivide (l.UpperBound, r.UpperBound, out c) + || !Rational.TryDivide (l.UpperBound, r.LowerBound, out d)) + + return TopValue; + + var lower = Rational.Min (Rational.Min (a, b), Rational.Min (c, d)); + var upper = Rational.Max (Rational.Max (a, b), Rational.Max (c, d)); + + return For (lower, upper); + } + + public static Interval operator * (Interval l, Interval r) + { + if (l.IsBottom || r.IsBottom) + return BottomValue; + + Rational lower, upper; + if (l.IsTop || r.IsTop + || !Rational.TryMultiply (l.LowerBound, r.LowerBound, out lower) + || !Rational.TryMultiply (l.UpperBound, r.UpperBound, out upper)) + return TopValue; + + return For (lower, upper); + } + + public static Interval operator - (Interval l) + { + if (!l.IsNormal ()) + return l; + + Rational lower; + Rational upper; + if (!Rational.TryUnaryMinus (l.UpperBound, out lower) || + !Rational.TryUnaryMinus (l.LowerBound, out upper)) + return TopValue; + + return For (lower, upper); + } + + public static bool AreConsecutiveIntegers (Interval prev, Interval next) + { + if (!prev.IsNormal () || !next.IsNormal () || + !prev.UpperBound.IsInteger || !next.LowerBound.IsInteger) + return false; + + return prev.UpperBound + Rational.One == next.LowerBound; + } + + public static Interval ApplyConversion (ExpressionOperator conv, Interval intv) + { + if (intv.is_bottom) + return intv; + + switch (conv) { + case ExpressionOperator.ConvertToInt32: + return intv.RefineWithTypeRanges (int.MinValue, int.MaxValue); + default: + return intv; + } + } + + public bool TryGetSingletonFiniteInt32 (out int value) + { + int lower; + int upper; + if (IsFiniteAndInt32 (out lower, out upper) && lower == upper) + return true.With (lower, out value); + + return false.Without (out value); + } + + public bool Includes (long x) + { + return this.IsNormal () && LowerBound <= x && x <= UpperBound; + } + + public bool Includes (int x) + { + return this.IsNormal () && LowerBound <= x && x <= UpperBound; + } + + public bool OverlapsWith (Interval that) + { + return !Meet (that).IsBottom; + } + + public bool OnTheLeftOf (Interval that) + { + if (!this.IsNormal () || !that.IsNormal ()) + return false; + + return UpperBound <= that.LowerBound; + } + + public override Interval ImmutableVersion () + { + return this; + } + + public override Interval Clone () + { + return this; + } + + public override bool Equals (object obj) + { + if (ReferenceEquals (null, obj)) + return false; + if (ReferenceEquals (this, obj)) + return true; + return Equals ((Interval) obj); + } + + public bool Equals (Interval that) + { + if (ReferenceEquals (this, that)) + return true; + if (ReferenceEquals (that, null)) + return false; + + return LowerBound == that.LowerBound && UpperBound == that.UpperBound; + } + + public override int GetHashCode () + { + return (LowerBound.GetHashCode () * 397) ^ UpperBound.GetHashCode (); + } + + public override void Dump (TextWriter tw) + { + tw.WriteLine (ToString ()); + } + + protected override bool IsFiniteBound (Rational n) + { + return n.IsInteger; + } + + bool IsFiniteAndInt32 (out int lower, out int upper) + { + if (IsFinite && LowerBound.IsInt32 && UpperBound.IsInt32) { + try { + lower = (int) LowerBound; + upper = (int) UpperBound; + return true; + } + catch (ArithmeticException) { + } + } + + return false.With (0, out lower). + With (0, out upper); + } + + Interval RefineWithTypeRanges (int min, int max) + { + var lower = LowerBound.IsInfinity || !LowerBound.IsInRange (min, max) + ? Rational.MinusInfinity + : LowerBound.PreviousInt32; + + var upper = UpperBound.IsInfinity || !UpperBound.IsInRange (min, max) + ? Rational.PlusInfinity + : UpperBound.NextInt32; + + return For (lower, upper); + } + + public static class Ranges { + static Interval int8Range; + static Interval int32Range; + static Interval int64Range; + + public static Interval Int8Range { get { return int8Range ?? (int8Range = For (sbyte.MinValue, sbyte.MaxValue)); } } + public static Interval Int32Range { get { return int32Range ?? (int32Range = For (int.MinValue, int.MaxValue)); } } + public static Interval Int64Range { get { return int64Range ?? (int64Range = For (int.MinValue, int.MaxValue)); } } + + public static Interval GetIntervalForType (TypeNode type, IMetaDataProvider provider) + { + if (provider.Equal (provider.System_Int8, type)) + return Int8Range; + if (provider.Equal (provider.System_Int32, type)) + return Int32Range; + if (provider.Equal (provider.System_Int64, type)) + return Int64Range; + + return TopValue; + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeFalseVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeFalseVisitor.cs new file mode 100644 index 00000000000..e4ca73ce123 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeFalseVisitor.cs @@ -0,0 +1,83 @@ +// +// IntervalAssumeFalseVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class IntervalAssumeFalseVisitor<TVar, TExpr, TInterval, TNumeric> : + AssumeFalseVisitor<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>, TVar, TExpr> + where TInterval : IntervalBase<TInterval, TNumeric> + where TVar : IEquatable<TVar> { + public IntervalAssumeFalseVisitor (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Visit (TExpr expr, + IntervalEnvironmentBase + <TVar, TExpr, + TInterval, + TNumeric> data) + { + var res = base.Visit (expr, data); + + if (!Decoder.IsBinaryExpression (expr)) + return res; + + var left = Decoder.LeftExpressionFor (expr); + var right = Decoder.RightExpressionFor (expr); + + var intv = data.Eval (right); + if (intv.IsBottom) + return data.Bottom; + if (!intv.IsSinglePoint) + return res; + + switch (Decoder.OperatorFor (expr)) { + case ExpressionOperator.LessThan: { + var leftVar = Decoder.UnderlyingVariable (left); + return res.Assumer.AssumeLessEqualThan (intv, leftVar, res); + } + case ExpressionOperator.LessEqualThan: { + var leftVar = Decoder.UnderlyingVariable (left); + return res.Assumer.AssumeLessThan (intv, leftVar, res); + } + } + + return data; + } + + protected override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> DispatchCompare ( + CompareVisitor cmp, TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> data) + { + data = cmp (left, right, original, data); + return base.DispatchCompare (cmp, left, right, original, data); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeTrueVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeTrueVisitor.cs new file mode 100644 index 00000000000..bf80c4875cf --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeTrueVisitor.cs @@ -0,0 +1,128 @@ +// +// IntervalAssumeTrueVisitor.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class IntervalAssumeTrueVisitor<TVar, TExpr, TInterval, TNumeric> : + AssumeTrueVisitor<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>, TVar, TExpr> + where TInterval : IntervalBase<TInterval, TNumeric> + where TVar : IEquatable<TVar> { + public IntervalAssumeTrueVisitor (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + protected override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> DispatchCompare + (CompareVisitor cmp, TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + env = cmp (left, right, original, env); + return base.DispatchCompare (cmp, left, right, original, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitEqual + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + return env.Assumer.AssumeEqual (left, right, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitLessThan + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + return env.Assumer.AssumeLessThan (left, right, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitLessEqualThan + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + return env.Assumer.AssumeLessEqualThan (left, right, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitAddition + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + env = base.VisitAddition (left, right, original, env); + return env.Assumer.AssumeNotEqualToZero (original, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitDivision + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + env = base.VisitDivision (left, right, original, env); + return env.Assumer.AssumeNotEqualToZero (original, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitMultiply + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + env = base.VisitMultiply (left, right, original, env); + return env.Assumer.AssumeNotEqualToZero (original, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitUnknown + (TExpr expr, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + env = base.VisitUnknown (expr, env); + return env.Assumer.AssumeNotEqualToZero (expr, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitNot + (TExpr expr, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + return FalseVisitor.Visit (expr, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitNotEqual + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + return env.Assumer.AssumeNotEqual (left, right, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitVariable + (TVar var, TExpr expr, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + return env.Assumer.AssumeNotEqualToZero (expr, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitSubtraction + (TExpr left, TExpr right, TExpr original, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + env = base.VisitSubtraction (left, right, original, env); + return env.Assumer.AssumeNotEqualToZero (original, env); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumer.cs new file mode 100644 index 00000000000..7d192e700d8 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumer.cs @@ -0,0 +1,56 @@ +// +// IntervalAssumer.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class IntervalAssumer<TVar, TExpr> : IntervalRationalAssumerBase<TVar, TExpr, Interval> + where TVar : IEquatable<TVar> { + public override IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> AssumeNotEqual + (TExpr left, TExpr right, IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> env) + { + IntervalInference.InferenceResult<TVar, Interval> resultLeft; + IntervalInference.InferenceResult<TVar, Interval> resultRight; + IntervalInference.ConstraintsFor.NotEqual (left, right, env.Decoder, env, out resultLeft, + out resultRight); + + IntervalInference.InferenceResult<TVar, Interval> join = resultLeft.Join (resultRight); + if (join.IsBottom) + return env.Bottom; + + return this.AssumeConstraints (join.Constraints, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> AssumeNotEqualToZero + (TVar v, IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> env) + { + //do nothing, we can't exclude one point + return env; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumerBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumerBase.cs new file mode 100644 index 00000000000..6d96f09f81a --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumerBase.cs @@ -0,0 +1,163 @@ +// +// IntervalAssumerBase.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class IntervalAssumerBase<TVar, TExpr, TInterval, TNumeric> + where TInterval : IntervalBase<TInterval, TNumeric> + where TVar : IEquatable<TVar> { + public virtual IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeEqual + (TExpr left, + TExpr right, + IntervalEnvironmentBase + <TVar, + TExpr, + TInterval, + TNumeric> + env) + { + var leftVar = env.Decoder.UnderlyingVariable (left); + var rightVar = env.Decoder.UnderlyingVariable (right); + + if (env.Contains (leftVar)) { + var res = env; + var interval = env.Eval (left).Meet (env.Eval (right)); + + res = res.With (leftVar, interval); + res = res.With (rightVar, interval); + + return res; + } + + if (env.Decoder.IsConstant (left) && env.Decoder.IsConstant (right) && + env.Eval (left).Meet (env.Eval (right)).IsBottom) + return env.Bottom; + + return env; + } + + public virtual IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeEqualToZero + (TVar var, + IntervalEnvironmentBase + < + TVar + , + TExpr + , + TInterval + , + TNumeric + > + env) + { + return env.RefineVariable (var, env.Context.Zero); + } + + public virtual IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeNotEqual + (TExpr left, + TExpr right, + IntervalEnvironmentBase + <TVar, + TExpr, + TInterval + , + TNumeric + > env) + { + int value; + if (env.Decoder.OperatorFor (left).IsRelational () && env.Decoder.IsConstantInt (right, out value)) + return value == 0 ? env.AssumeTrue (left) : env.AssumeFalse (left); + + var assumer = env.Assumer; + return assumer.AssumeLessThan (left, right, env).Join (assumer.AssumeLessThan (right, left, env)); + } + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeLessThan + (TExpr left, + TExpr right, + IntervalEnvironmentBase + <TVar, + TExpr, + TInterval + , + TNumeric + > env); + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeLessEqualThan + ( + TExpr left, TExpr right, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env); + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeNotEqualToZero + (TVar v, IntervalEnvironmentBase<TVar,TExpr,TInterval,TNumeric> env); + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeNotEqualToZero + (TExpr e, IntervalEnvironmentBase<TVar,TExpr,TInterval,TNumeric> env); + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeLessEqualThan + (TInterval intv, TVar right, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env); + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeLessThan + (TInterval intv, TVar right, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env); + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeGreaterEqualThanZero + (TExpr expr, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env); + + protected IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeConstraints + (IImmutableMap<TVar, Sequence<TInterval>> constraints, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + var res = env; + foreach (var v in constraints.Keys) { + var seq = constraints[v]; + foreach (var intv in seq.AsEnumerable ()) + res = res.RefineVariable (v, intv); + } + + return res; + } + + protected IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeConstraints + ( + IDictionary<TVar, Sequence<TInterval>> constraints, + IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> env) + { + var res = env; + foreach (var v in constraints.Keys) { + var seq = constraints[v]; + foreach (var intv in seq.AsEnumerable ()) + res = res.RefineVariable (v, intv); + } + + return res; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalBase.cs new file mode 100644 index 00000000000..78d4c88f99b --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalBase.cs @@ -0,0 +1,77 @@ +// +// IntervalBase.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.IO; + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + /// <summary> + /// Represents a generic class for intervals on numeric values. + /// </summary> + abstract class IntervalBase<TInterval, TNumeric> : IAbstractDomain<TInterval> + where TInterval : IntervalBase<TInterval, TNumeric> { + protected IntervalBase (TNumeric lowerBound, TNumeric upperBound) + { + LowerBound = lowerBound; + UpperBound = upperBound; + } + + public TNumeric UpperBound { get; protected set; } + public TNumeric LowerBound { get; protected set; } + + public abstract TInterval Top { get; } + public abstract TInterval Bottom { get; } + + public abstract bool IsTop { get; } + public abstract bool IsBottom { get; } + + public bool IsSinglePoint { get { return this.IsNormal () && LowerBound.Equals (UpperBound); } } + public bool IsFinite { get { return this.IsNormal () && IsFiniteBound (LowerBound) && IsFiniteBound (UpperBound); } } + + public abstract bool LessEqual (TInterval that); + + public abstract TInterval Join (TInterval that, bool widening, out bool weaker); + public abstract TInterval Join (TInterval that); + + public abstract TInterval Widen (TInterval that); + public abstract TInterval Meet (TInterval that); + + public abstract TInterval ImmutableVersion (); + public abstract TInterval Clone (); + + public abstract void Dump (TextWriter tw); + + public override string ToString () + { + return string.Format ("[{0}, {1}]{2}", LowerBound, UpperBound, this.BottomSymbolIfAny ()); + } + + protected abstract bool IsFiniteBound (TNumeric n); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalContext.cs new file mode 100644 index 00000000000..4e96ad16ccd --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalContext.cs @@ -0,0 +1,137 @@ +// +// IntervalContext.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class IntervalContext : IntervalRationalContextBase<Interval> { + public static readonly IntervalContext Instance = new IntervalContext (); + + IntervalContext () + { + } + + public override Interval TopValue { get { return Interval.TopValue; } } + public override Interval BottomValue { get { return Interval.BottomValue; } } + + public override Interval Zero { get { return Interval.For (Rational.Zero); } } + public override Interval One { get { return Interval.For (Rational.One); } } + + public override Interval Positive { get { return Interval.For (0, Rational.PlusInfinity); } } + public override Interval Negative { get { return Interval.For (Rational.MinusInfinity, 0); } } + + public override Interval GreaterEqualThanMinusOne { get { return Interval.For (Rational.MinusOne, Rational.PlusInfinity); } } + + public override Interval For (long value) + { + return Interval.For (value); + } + + public override Interval For (long lower, long upper) + { + return Interval.For (lower, upper); + } + + public override Interval For (long lower, Rational upper) + { + return Interval.For (lower, upper); + } + + public override Interval For (Rational lower, long upper) + { + return Interval.For (lower, upper); + } + + public override Interval For (Rational value) + { + return Interval.For (value); + } + + public override Interval For (Rational lower, Rational upper) + { + return Interval.For (lower, upper); + } + + public override Interval LeftOpen (Rational upperBound) + { + return Interval.For (Rational.MinusInfinity, upperBound); + } + + public override Interval RightOpen (Rational lowerBound) + { + return Interval.For (lowerBound, Rational.PlusInfinity); + } + + public override Interval Add (Interval a, Interval b) + { + return a + b; + } + + public override Interval Sub (Interval a, Interval b) + { + return a - b; + } + + public override Interval Div (Interval a, Interval b) + { + return a / b; + } + + public override Interval Mul (Interval a, Interval b) + { + return a * b; + } + + public override Interval Not (Interval value) + { + if (!value.IsNormal ()) + return value; + + int intValue; + if (value.TryGetSingletonFiniteInt32 (out intValue)) + return Interval.For (intValue != 0 ? 0 : 1); + + return Interval.TopValue; + } + + public override Interval Rem (Interval a, Interval b) + { + return TopValue; + } + + public override Interval UnaryMinus (Interval value) + { + return -value; + } + + public override Interval ApplyConversion (ExpressionOperator conv, Interval intv) + { + return Interval.ApplyConversion (conv, intv); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalContextBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalContextBase.cs new file mode 100644 index 00000000000..880c5fa41d1 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalContextBase.cs @@ -0,0 +1,146 @@ +// +// IntervalContextBase.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class IntervalContextBase<TInterval, TNumeric> + where TInterval : IntervalBase<TInterval, TNumeric> { + /// <summary> + /// (-oo, +oo) + /// </summary> + public abstract TInterval TopValue { get; } + + /// <summary> + /// Empty set of values + /// </summary> + public abstract TInterval BottomValue { get; } + + /// <summary> + /// [0, 0] + /// </summary> + public abstract TInterval Zero { get; } + + /// <summary> + /// [1, 1] + /// </summary> + public abstract TInterval One { get; } + + /// <summary> + /// [0, +oo) + /// </summary> + public abstract TInterval Positive { get; } + + /// <summary> + /// (-oo, 0] + /// </summary> + public abstract TInterval Negative { get; } + + /// <summary> + /// [-1, +oo) + /// </summary> + public abstract TInterval GreaterEqualThanMinusOne { get; } + + public abstract TInterval For (long value); + public abstract TInterval For (long lower, long upper); + public abstract TInterval For (long lower, TNumeric upper); + public abstract TInterval For (TNumeric lower, long upper); + public abstract TInterval For (TNumeric value); + public abstract TInterval For (TNumeric lower, TNumeric upper); + + public abstract bool IsGreaterThanZero (TNumeric value); + public abstract bool IsGreaterEqualThanZero (TNumeric value); + + public abstract bool IsLessThanZero (TNumeric value); + public abstract bool IsLessEqualThanZero (TNumeric value); + + public abstract bool IsLessEqualThanZero (TInterval value); + + public abstract bool IsLessThan (TNumeric a, TNumeric b); + public abstract bool IsLessEqualThan (TNumeric a, TNumeric b); + + public abstract bool IsZero (TNumeric value); + + public abstract bool IsNotZero (TNumeric value); + + public abstract bool IsPlusInfinity (TNumeric value); + + public abstract bool IsMinusInfinity (TNumeric value); + + public abstract bool AreEqual (TNumeric a, TNumeric b); + + public abstract TInterval Add (TInterval a, TInterval b); + public abstract TInterval Sub (TInterval a, TInterval b); + public abstract TInterval Div (TInterval a, TInterval b); + public abstract TInterval Rem (TInterval a, TInterval b); + public abstract TInterval Mul (TInterval a, TInterval b); + public abstract TInterval Not (TInterval value); + + public abstract TInterval UnaryMinus (TInterval value); + + public abstract TInterval ApplyConversion (ExpressionOperator conv, TInterval intv); + + public virtual FlatDomain<bool> IsLessThan (TInterval a, TInterval b) + { + if (a.IsNormal () || b.IsNormal ()) + return ProofOutcome.Top; + + if (IsLessThan (a.UpperBound, b.LowerBound)) + return true; + if (IsLessEqualThan (b.UpperBound, a.LowerBound)) + return false; + + return ProofOutcome.Top; + } + + public virtual FlatDomain<bool> IsLessEqualThan (TInterval a, TInterval b) + { + if (a.IsNormal () || b.IsNormal ()) + return ProofOutcome.Top; + + if (IsLessEqualThan (a.UpperBound, b.LowerBound)) + return true; + if (IsLessThan (b.UpperBound, a.LowerBound)) + return false; + + return ProofOutcome.Top; + } + + public virtual FlatDomain<bool> IsEqualThan (TInterval a, TInterval b) + { + throw new NotImplementedException (); + } + + public abstract bool IsMaxInt32 (TInterval value); + + public abstract TInterval RightOpen (TNumeric lowerBound); + public abstract TInterval LeftOpen (TNumeric lowerBound); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironment.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironment.cs new file mode 100644 index 00000000000..9826af9632d --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironment.cs @@ -0,0 +1,68 @@ +// +// IntervalEnvironment.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class IntervalEnvironment<TVar, TExpr> : + IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> + where TVar : IEquatable<TVar> { + static IntervalAssumer<TVar, TExpr> cachedAssumer; + + public IntervalEnvironment (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + IntervalEnvironment + (IExpressionDecoder<TVar, TExpr> decoder, + EnvironmentDomain<TVar, Interval> varsToInterval) + : base (decoder, varsToInterval) + { + } + + public override IntervalAssumerBase<TVar, TExpr, Interval, Rational> + Assumer { get { return cachedAssumer ?? (cachedAssumer = new IntervalAssumer<TVar, TExpr> ()); } } + + public override IntervalContextBase<Interval, Rational> Context { get { return IntervalContext.Instance; } } + + protected override IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> NewInstance + (EnvironmentDomain<TVar, Interval> varsToIntervals) + { + return new IntervalEnvironment<TVar, TExpr> (Decoder, varsToIntervals); + } + + public override IntervalEnvironmentBase<TVar, TExpr, Interval, Rational> AssumeVariableIn + (TVar var, Interval interval) + { + return RefineVariable (var, interval); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironmentBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironmentBase.cs new file mode 100644 index 00000000000..8a69bba6b8b --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironmentBase.cs @@ -0,0 +1,338 @@ +// +// IntervalEnvironmentBase.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> : IIntervalEnvironment<TVar, TExpr, TInterval, TNumeric>, + IEnvironmentDomain<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>, TVar, TExpr> + where TInterval : IntervalBase<TInterval, TNumeric> + where TVar : IEquatable<TVar> { + public abstract IntervalAssumerBase<TVar, TExpr, TInterval, TNumeric> Assumer { get; } + public abstract IntervalContextBase<TInterval, TNumeric> Context { get; } + + public readonly IExpressionDecoder<TVar, TExpr> Decoder; + readonly EnvironmentDomain<TVar, TInterval> vars_to_intervals; + + public IEnumerable<TVar> Variables { get { return vars_to_intervals.Keys; } } + + protected IntervalEnvironmentBase + (IExpressionDecoder<TVar, TExpr> decoder, + EnvironmentDomain<TVar, TInterval> varsToInterval) + { + Decoder = decoder; + vars_to_intervals = varsToInterval; + } + + protected IntervalEnvironmentBase (IExpressionDecoder<TVar, TExpr> decoder) + : this (decoder, EnvironmentDomain<TVar, TInterval>.TopValue (null)) + { + } + + public TInterval Eval (TExpr expr) + { + int intValue; + if (Decoder.IsConstantInt (expr, out intValue)) + return Context.For (intValue); + + var evaluator = new EvaluateExpressionVisitor<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> (Decoder); + var interval = evaluator.Visit (expr, new Counter<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>> (this)); + + if (evaluator.DuplicatedOccurences.Length () >= 1) { + var noDuplicates = true; + TInterval result = null; + foreach (var var in evaluator.DuplicatedOccurences.AsEnumerable ()) { + TInterval intv; + if (TryGetValue (var, out intv) && intv.IsFinite && + Context.IsGreaterEqualThanZero (intv.LowerBound)) { + var extreme = EvalWithExtremes (expr, var, intv); + if (noDuplicates) { + noDuplicates = false; + result = extreme; + } + else + result = result.Join (extreme); + } + } + + if (!noDuplicates) + interval = result; + } + + return interval; + } + + public TInterval Eval (TVar var) + { + TInterval intv; + if (TryGetValue (var, out intv)) + return intv; + + return Context.TopValue; + } + + /// <summary> + /// Evaluates expression with variable equal to var's lowerbound or upperbound. + /// </summary> + /// <param name="expr"></param> + /// <param name="var"></param> + /// <param name="intv"></param> + /// <returns></returns> + TInterval EvalWithExtremes (TExpr expr, TVar var, TInterval intv) + { + var evaluator = new EvaluateExpressionVisitor<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> (Decoder); + + var envLowerBound = With (var, Context.For (intv.LowerBound)); + // replace current intv with it's only lowerbound + var withLowerBound = evaluator.Visit (expr, new Counter<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>> (envLowerBound)); + + var envUpperBound = With (var, Context.For (intv.UpperBound)); + // replace current intv with it's only upperBound + var withUpperBound = evaluator.Visit (expr, new Counter<IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>> (envUpperBound)); + + return withLowerBound.Join (withUpperBound); + } + + public string ToString (TExpr expr) + { + if (IsBottom) + return "_|_"; + if (IsTop) + return "Top"; + + var list = new List<string> (); + foreach (var variable in Variables) { + var intv = vars_to_intervals[variable]; + if (!intv.IsTop) { + var name = Decoder != null + ? Decoder.NameOf (variable) + : variable.ToString (); + list.Add (name + ": " + intv); + } + } + list.Sort (); + return string.Join (", ", list); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeTrue (TExpr guard) + { + Assumer.AssumeNotEqualToZero (Decoder.UnderlyingVariable (guard), this); + return new IntervalTestVisitor (Decoder).VisitTrue (guard, this); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeFalse (TExpr guard) + { + return Assumer.AssumeEqualToZero (Decoder.UnderlyingVariable (guard), this); + } + + public FlatDomain<bool> CheckIfHolds (TExpr expr) + { + return FlatDomain<bool>.TopValue; + } + + public bool Contains (TVar v) + { + return vars_to_intervals.Contains (v); + } + + public bool TryGetValue (TVar v, out TInterval interval) + { + return vars_to_intervals.TryGetValue (v, out interval); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> With (TVar var, TInterval interval) + { + return NewInstance (vars_to_intervals.With (var, interval)); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> RefineVariable (TVar var, TInterval interval) + { + TInterval current; + if (TryGetValue (var, out current)) + interval = interval.Meet (current); + + if (interval.IsBottom) + return Bottom; + + return With (var, interval); + } + + #region Implementation of IAbstractDomain<T> + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Top { get { return NewInstance (EnvironmentDomain<TVar, TInterval>.TopValue (null)); } } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Bottom { get { return NewInstance (EnvironmentDomain<TVar, TInterval>.BottomValue ()); } } + + public bool IsTop { get { return vars_to_intervals.IsTop; } } + + public bool IsBottom { get { return vars_to_intervals.IsBottom; } } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Join (IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> that) + { + return NewInstance (vars_to_intervals.Join (that.vars_to_intervals)); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Join (IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> that, bool widen, out bool weaker) + { + return NewInstance (vars_to_intervals.Join (that.vars_to_intervals, widen, out weaker)); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Widen (IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> that) + { + return NewInstance (vars_to_intervals.Widen (that.vars_to_intervals)); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Meet (IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> that) + { + return NewInstance (vars_to_intervals.Meet (that.vars_to_intervals)); + } + + public bool LessEqual (IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> that) + { + return vars_to_intervals.LessEqual (that.vars_to_intervals); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> ImmutableVersion () + { + return this; + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> Clone () + { + return this; + } + + public void Dump (TextWriter tw) + { + vars_to_intervals.Dump (tw); + } + + #endregion + + protected abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> NewInstance (EnvironmentDomain<TVar, TInterval> varsToIntervals); + + class IntervalTestVisitor { + readonly IntervalAssumeTrueVisitor<TVar, TExpr, TInterval, TNumeric> true_visitor; + readonly IntervalAssumeFalseVisitor<TVar, TExpr, TInterval, TNumeric> false_visitor; + + public IntervalTestVisitor (IExpressionDecoder<TVar, TExpr> decoder) + { + true_visitor = + new IntervalAssumeTrueVisitor<TVar, TExpr, TInterval, TNumeric> (decoder); + false_visitor = + new IntervalAssumeFalseVisitor<TVar, TExpr, TInterval, TNumeric> (decoder); + + true_visitor.FalseVisitor = false_visitor; + false_visitor.TrueVisitor = true_visitor; + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitTrue (TExpr guard, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> data) + { + return true_visitor.Visit (guard, data); + } + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> VisitFalse (TExpr guard, IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> data) + { + return false_visitor.Visit (guard, data); + } + } + + public abstract IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeVariableIn (TVar var, Interval interval); + + public IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric> AssumeLessEqualThan (TExpr left, TExpr right) + { + return Assumer.AssumeLessEqualThan (left, right, this); + } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Top { get { return Top; } } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Bottom { get { return Bottom; } } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Join (INumericalEnvironmentDomain<TVar, TExpr> that) + { + return Join (that as IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>); + } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Join + (INumericalEnvironmentDomain<TVar, TExpr> that, bool widen, out bool weaker) + { + return Join (that as IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>, widen, + out weaker); + } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Widen (INumericalEnvironmentDomain<TVar, TExpr> that) + { + return Widen (that as IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>); + } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Meet (INumericalEnvironmentDomain<TVar, TExpr> that) + { + return Meet (that as IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>); + } + + bool IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.LessEqual (INumericalEnvironmentDomain<TVar, TExpr> that) + { + return LessEqual (that as IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>); + } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.ImmutableVersion () + { + return ImmutableVersion (); + } + + INumericalEnvironmentDomain<TVar, TExpr> IAbstractDomain<INumericalEnvironmentDomain<TVar, TExpr>>.Clone () + { + return Clone (); + } + + INumericalEnvironmentDomain<TVar, TExpr> IEnvironmentDomain<INumericalEnvironmentDomain<TVar, TExpr>, TVar, TExpr>.AssumeTrue (TExpr guard) + { + return AssumeTrue (guard); + } + + INumericalEnvironmentDomain<TVar, TExpr> IEnvironmentDomain<INumericalEnvironmentDomain<TVar, TExpr>, TVar, TExpr>.AssumeFalse (TExpr guard) + { + return AssumeFalse (guard); + } + + INumericalEnvironmentDomain<TVar, TExpr> INumericalEnvironmentDomain<TVar, TExpr>.AssumeVariableIn (TVar var, Interval interval) + { + return AssumeVariableIn (var, interval); + } + + INumericalEnvironmentDomain<TVar, TExpr> INumericalEnvironmentDomain<TVar, TExpr>.AssumeLessEqualThan (TExpr left, TExpr right) + { + return AssumeLessEqualThan (left, right); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalInference.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalInference.cs new file mode 100644 index 00000000000..c24d8430e2a --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalInference.cs @@ -0,0 +1,546 @@ +// +// IntervalInference.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static class IntervalInference { + public static class ConstraintsFor { + public static IDictionary<TVar, Sequence<TInterval>> GreaterEqualThanZero<TEnv, TVar, TExpr, TInterval> + (TExpr expr, IExpressionDecoder<TVar, TExpr> decoder, TEnv env) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + var result = new Dictionary<TVar, Sequence<TInterval>> (); + var variable = decoder.UnderlyingVariable (expr); + + AddToResult (result, variable, env.Eval (expr).Meet (env.Context.Positive)); + + if (!decoder.IsVariable (expr)) { + Polynomial<TVar, TExpr> zeroPoly; // poly(0) + if (!Polynomial<TVar, TExpr>.TryToPolynomial (new[] {Monomial<TVar>.From (Rational.Zero)}, out zeroPoly)) + throw new AbstractInterpretationException ( + "It can never be the case that the conversion of a list of monomials into a polynomial fails."); + + Polynomial<TVar, TExpr> exprPoly; // poly(expr) + Polynomial<TVar, TExpr> fullPoly; // '0 <= poly(expr)' polynome + if (Polynomial<TVar, TExpr>.TryBuildFrom (expr, decoder, out exprPoly) && + Polynomial<TVar, TExpr>.TryToPolynomial (ExpressionOperator.LessEqualThan, zeroPoly, exprPoly, out fullPoly) && + fullPoly.IsIntervalForm) { + var k = fullPoly.Left[0].Coeff; // k != 0 + TVar x; + fullPoly.Left[0].IsSingleVariable (out x); + + Rational constraint; + if (Rational.TryDivide (fullPoly.Right[0].Coeff, k, out constraint)) { + TInterval interval; + if (k > 0L) // +x <= constraint + interval = env.Eval (x).Meet (env.Context.For (Rational.MinusInfinity, constraint)); + else // -x <= -constraint ==> x >= constraint + interval = env.Eval (x).Meet (env.Context.For (constraint, Rational.PlusInfinity)); + + AddToResult (result, x, interval); + } + } + } + return result; + } + + public static IDictionary<TVar, Sequence<TInterval>> LessEqualThan<TEnv, TVar, TExpr, TInterval> + (TExpr left, TExpr right, IExpressionDecoder<TVar, TExpr> decoder, TEnv env, out bool isBottom) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + isBottom = false; + var result = new Dictionary<TVar, Sequence<TInterval>> (); + + if (IsFloat (left, decoder) || IsFloat (right, decoder)) + return result; + + var leftIntv = env.Eval (left); + var rightIntv = env.Eval (right); + + var leftVar = decoder.UnderlyingVariable (left); + var rightVar = decoder.UnderlyingVariable (right); + + TInterval refinedIntv; + if (TryRefineLessEqualThan<TEnv, TVar, TExpr, TInterval> (leftIntv, rightVar, env, out refinedIntv)) + AddToResult (result, rightVar, refinedIntv); + + if (TryRefineLeftLessEqualThanK<TEnv, TVar, TExpr, TInterval> (leftVar, rightIntv, env, out refinedIntv)) + AddToResult (result, leftVar, refinedIntv); + + Polynomial<TVar, TExpr> poly; + Polynomial<TVar, TExpr> leftPoly; + Polynomial<TVar, TExpr> rightPoly; + + if (Polynomial<TVar, TExpr>.TryBuildFrom (left, decoder, out leftPoly) && + Polynomial<TVar, TExpr>.TryBuildFrom (right, decoder, out rightPoly) && + Polynomial<TVar, TExpr>.TryToPolynomial (ExpressionOperator.LessEqualThan, leftPoly, rightPoly, out poly) && + poly.IsLinear) { + if (poly.Left.Length == 1) + return TestTrueLessEqualThan_AxLeqK (poly, env, result, out isBottom); + if (poly.Left.Length == 2) + return TestTrueLessEqualThan_AxByLeqK (poly, env, result, out isBottom); + } + + return result; + } + + public static IDictionary<TVar, Sequence<TInterval>> LessThan<TEnv, TVar, TExpr, TInterval> + (TExpr left, TExpr right, IExpressionDecoder<TVar, TExpr> decoder, TEnv env, out bool isBottom) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + isBottom = false; + var result = new Dictionary<TVar, Sequence<TInterval>> (); + + var leftIntv = env.Eval (left); + var rightIntv = env.Eval (right); + + var rightVar = decoder.UnderlyingVariable (right); + var successor = IsFloat (left, decoder) || IsFloat (right, decoder) ? Rational.Zero : Rational.One; + + TInterval refinedIntv; + if (TryRefineKLessThanRight<TEnv, TVar, TExpr, TInterval> (leftIntv, rightVar, successor, env, out refinedIntv) && !refinedIntv.IsSinglePoint) + AddToResult (result, rightVar, refinedIntv); + + if (successor.IsZero) + return result; + + var leftVar = decoder.UnderlyingVariable (left); + if (TryRefineLessThan<TEnv, TVar, TExpr, TInterval> (leftVar, rightIntv, env, out refinedIntv) && !refinedIntv.IsSinglePoint) + AddToResult (result, leftVar, refinedIntv); + + Polynomial<TVar, TExpr> poly; + Polynomial<TVar, TExpr> leftPoly; + Polynomial<TVar, TExpr> rightPoly; + + if (Polynomial<TVar, TExpr>.TryBuildFrom (left, decoder, out leftPoly) && + Polynomial<TVar, TExpr>.TryBuildFrom (right, decoder, out rightPoly) && + Polynomial<TVar, TExpr>.TryToPolynomial (ExpressionOperator.LessThan, leftPoly, rightPoly, out poly) && + poly.IsLinear) { + if (poly.Left.Length == 1) + return TestTrueLessEqualThan_AxLtK (poly, env, result, out isBottom); + if (poly.Left.Length == 2) + return TestTrueLessEqualThan_AxByLtK (poly, env, result, out isBottom); + } + + return result; + } + + /// <summary> + /// Get interval for 'left' in inequation 'left <= k'. + /// </summary> + public static bool TryRefineLeftLessEqualThanK<TEnv, TVar, TExpr, TInterval> (TVar left, TInterval k, TEnv env, out TInterval refined) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> + { + if (!k.IsNormal ()) + return false.Without (out refined); + + var interval = env.Context.For (Rational.MinusInfinity, k.UpperBound); + + TInterval leftIntv; + if (env.TryGetValue (left, out leftIntv)) + interval = interval.Meet (leftIntv); + + return true.With (interval, out refined); + } + + /// <summary> + /// Get interval for 'left' in inequation 'left < k'. + /// </summary> + public static bool TryRefineLessThan<TEnv, TVar, TExpr, TInterval> (TVar left, TInterval k, TEnv env, out TInterval refined) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> + { + if (!k.IsNormal ()) + return false.Without (out refined); + + var interval = env.Context.For (Rational.MinusInfinity, k.UpperBound.IsInteger ? k.UpperBound - 1L : k.UpperBound); + + TInterval leftIntv; + if (env.TryGetValue (left, out leftIntv)) + interval = interval.Meet (leftIntv); + + return true.With (interval, out refined); + } + + /// <summary> + /// Get interval for 'right' in inequation 'k <= right'. + /// </summary> + public static bool TryRefineLessEqualThan<TEnv, TVar, TExpr, TInterval> (TInterval k, TVar right, TEnv env, out TInterval refined) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> + { + if (!k.IsNormal ()) + return false.Without (out refined); + + var interval = env.Context.RightOpen (k.LowerBound); + + TInterval rightIntv; + if (env.TryGetValue (right, out rightIntv)) + interval = interval.Meet (rightIntv); + + return true.With (interval, out refined); + } + + /// <summary> + /// Get interval for 'right' in inequation 'k < right'. + /// </summary> + public static bool TryRefineKLessThanRight<TEnv, TVar, TExpr, TInterval> (TInterval k, TVar right, Rational successor, TEnv env, out TInterval refined) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> + { + if (!k.IsNormal ()) + return false.Without (out refined); + + // [k, +oo] or (k, +oo] + var interval = env.Context.For (k.LowerBound.IsInteger ? k.LowerBound + successor : k.LowerBound, Rational.PlusInfinity); + + TInterval rightIntv; + if (env.TryGetValue (right, out rightIntv)) + interval = interval.Meet (rightIntv); + + return true.With (interval, out refined); + } + + public static void NotEqual<TEnv, TVar, TExpr, TInterval> + (TExpr left, TExpr right, IExpressionDecoder<TVar, TExpr> decoder, TEnv env, out InferenceResult<TVar, TInterval> resultLeft, + out InferenceResult<TVar, TInterval> resultRight) where TInterval : IntervalBase<TInterval, Rational> + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + { + resultLeft = InferenceResult<TVar, TInterval>.Empty; + resultRight = InferenceResult<TVar, TInterval>.Empty; + + var leftIntv = env.Eval (left); + var rightIntv = env.Eval (right); + + var leftVar = decoder.UnderlyingVariable (left); + var rightVar = decoder.UnderlyingVariable (right); + + var successor = IsFloat (left, decoder) || IsFloat (right, decoder) ? Rational.Zero : Rational.One; + + // l != r <==> l < r && r < l + LessThanRefinement<TEnv, TVar, TExpr, TInterval> (successor, env, leftIntv, rightIntv, leftVar, rightVar, ref resultLeft); + LessThanRefinement<TEnv, TVar, TExpr, TInterval> (successor, env, rightIntv, leftIntv, rightVar, leftVar, ref resultRight); + } + + static void LessThanRefinement<TEnv, TVar, TExpr, TInterval> + (Rational successor, TEnv env, + TInterval leftIntv, TInterval rightIntv, + TVar leftVar, TVar rightVar, + ref InferenceResult<TVar, TInterval> result) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> + where TVar : IEquatable<TVar> + { + TInterval refined; + if (TryRefineKLessThanRight<TEnv, TVar, TExpr, TInterval> (leftIntv, rightVar, successor, env, out refined)) + result = result.AddConstraintFor (rightVar, refined); + if (TryRefineLessThan<TEnv, TVar, TExpr, TInterval> (leftVar, rightIntv, env, out refined)) + result = result.AddConstraintFor (leftVar, refined); + } + + static IDictionary<TVar, Sequence<TInterval>> TestTrueLessEqualThan_AxByLeqK<TEnv, TVar, TExpr, TInterval> + (Polynomial<TVar, TExpr> poly, TEnv env, IDictionary<TVar, Sequence<TInterval>> result, out bool isBottom) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + // ax + by <= k + var ax = poly.Left[0]; + var by = poly.Left[1]; + + TVar x, y; + ax.IsSingleVariable (out x); + by.IsSingleVariable (out y); + + var k = poly.Right[0].Coeff; + var a = ax.Coeff; + var b = by.Coeff; + + var aInterval = env.Context.For (a); + var bInterval = env.Context.For (b); + var kInterval = env.Context.For (k); + + var xInterval = env.Eval (x); + var yInterval = env.Eval (y); + + IntervalContextBase<TInterval, Rational> ctx = env.Context; + + // x <= (k - (b * y)) / a; + var boundingInterval = ctx.Div (ctx.Sub (kInterval, ctx.Mul (bInterval, yInterval)), aInterval); + Func<Rational, TInterval> upperBounded = (i) => ctx.For (Rational.MinusInfinity, i); + Func<Rational, TInterval> lowerBounded = (i) => ctx.For (i, Rational.PlusInfinity); + + if (BoundVariable (ctx, a, xInterval, boundingInterval, x, result, out isBottom, upperBounded, lowerBounded)) + return result; + + // y <= (k - (a * x)) / b; + boundingInterval = ctx.Div (ctx.Sub (kInterval, ctx.Mul (aInterval, xInterval)), bInterval); + if (BoundVariable (ctx, b, yInterval, boundingInterval, y, result, out isBottom, upperBounded, lowerBounded)) + return result; + + return result; + } + + static IDictionary<TVar, Sequence<TInterval>> TestTrueLessEqualThan_AxByLtK<TEnv, TVar, TExpr, TInterval> + (Polynomial<TVar, TExpr> poly, TEnv env, IDictionary<TVar, Sequence<TInterval>> result, out bool isBottom) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + // ax + by <= k + var ax = poly.Left[0]; + var by = poly.Left[1]; + + TVar x, y; + ax.IsSingleVariable (out x); + by.IsSingleVariable (out y); + + var k = poly.Right[0].Coeff; + var a = ax.Coeff; + var b = by.Coeff; + + var aInterval = env.Context.For (a); + var bInterval = env.Context.For (b); + var kInterval = env.Context.For (k); + + var xInterval = env.Eval (x); + var yInterval = env.Eval (y); + + IntervalContextBase<TInterval, Rational> ctx = env.Context; + Func<Rational, TInterval> upperBounded = + (i) => ctx.For (Rational.MinusInfinity, !i.IsInteger ? i.PreviousInt32 : i - 1L); + Func<Rational, TInterval> lowerBounded = + (i) => ctx.For (!i.IsInteger ? i.NextInt32 : i + 1L, Rational.PlusInfinity); + + // x <= (k - (b * y)) / a; + var boundingInterval = ctx.Div (ctx.Sub (kInterval, ctx.Mul (bInterval, yInterval)), aInterval); + if (BoundVariable (ctx, a, xInterval, boundingInterval, x, result, out isBottom, upperBounded, lowerBounded)) + return result; + + // y <= (k - (a * x)) / b; + boundingInterval = ctx.Div (ctx.Sub (kInterval, ctx.Mul (aInterval, xInterval)), bInterval); + if (BoundVariable (ctx, b, yInterval, boundingInterval, y, result, out isBottom, upperBounded, lowerBounded)) + return result; + + return result; + } + + /// <summary> + /// Get constraints for variables from polynome in form 'a*x <= k' + /// </summary> + /// <param name="poly">Polynome in canonical form. Two monomes involved. </param> + static IDictionary<TVar, Sequence<TInterval>> TestTrueLessEqualThan_AxLeqK<TEnv, TVar, TExpr, TInterval> + (Polynomial<TVar, TExpr> poly, TEnv env, IDictionary<TVar, Sequence<TInterval>> result, out bool isBottom) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + isBottom = false; + + var ax = poly.Left[0]; + var k = poly.Right[1]; + if (ax.IsConstant) { + if (ax.Coeff > k.Coeff) { + isBottom = true; + return result; + } + } + else { + TVar x; + ax.IsSingleVariable (out x); + Rational div; + if (Rational.TryDivide (k.Coeff, ax.Coeff, out div)) { + var intv = env.Eval (x); + + var refined = ax.Coeff.Sign < 1 + ? intv.Meet (env.Context.For (div, Rational.PlusInfinity)) + : intv.Meet (env.Context.For (Rational.MinusInfinity, div)); + + AddToResult (result, x, refined); + } + } + + return result; + } + + /// <summary> + /// Get constraints for variables from polynome in form 'a*x <= k' + /// </summary> + /// <param name="poly">Polynome in canonical form. Two monomes involved. </param> + static IDictionary<TVar, Sequence<TInterval>> TestTrueLessEqualThan_AxLtK<TEnv, TVar, TExpr, TInterval> + (Polynomial<TVar, TExpr> poly, TEnv env, IDictionary<TVar, Sequence<TInterval>> result, out bool isBottom) + where TEnv : IIntervalEnvironment<TVar, TExpr, TInterval, Rational> + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + isBottom = false; + + var ax = poly.Left[0]; + var k = poly.Right[1]; + if (ax.IsConstant) { + if (ax.Coeff >= k.Coeff) { + isBottom = true; + return result; + } + } + else { + TVar x; + ax.IsSingleVariable (out x); + Rational div; + if (Rational.TryDivide (k.Coeff, ax.Coeff, out div)) { + var intv = env.Eval (x); + + var boundByDivPlus = !div.IsInteger + ? env.Context.For (div.NextInt32, Rational.PlusInfinity) + : env.Context.For (div + 1L, Rational.PlusInfinity); + var boundByDivMinus = !div.IsInteger + ? env.Context.For (Rational.MinusInfinity, div.NextInt32 - 1L) + : env.Context.For (Rational.MinusInfinity, div - 1L); + var refined = intv.Meet (ax.Coeff.Sign < 1 ? boundByDivPlus : boundByDivMinus); + + if (refined.IsBottom) { + isBottom = true; + return result; + } + + AddToResult (result, x, refined); + } + } + return result; + } + + static bool BoundVariable<TVar, TInterval> + (IntervalContextBase<TInterval, Rational> ctx, Rational a, TInterval xIntervalOld, TInterval boundingInterval, TVar x, + IDictionary<TVar, Sequence<TInterval>> result, out bool isBottom, + Func<Rational, TInterval> upperBounded, Func<Rational, TInterval> lowerBounded) + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + isBottom = false; + if (a.IsZero) { + TInterval boundingForVariable; + if (a.Sign > 0L) + boundingForVariable = upperBounded (boundingInterval.UpperBound); + else + boundingForVariable = lowerBounded (boundingInterval.LowerBound); + + var refined = xIntervalOld.Meet (boundingForVariable); + if (refined.IsBottom) { + isBottom = true; + return true; + } + + AddToResult (result, x, refined); + } + return false; + } + + static bool IsFloat<TVar, TExpr> (TExpr expr, IExpressionDecoder<TVar, TExpr> decoder) + { + if (decoder == null) + return false; + + var type = decoder.TypeOf (expr); + return type == ExpressionType.Float32 || type == ExpressionType.Float64; + } + + static void AddToResult<TVar, TInterval> (IDictionary<TVar, Sequence<TInterval>> result, TVar variable, TInterval intv) + where TVar : IEquatable<TVar> + where TInterval : IntervalBase<TInterval, Rational> + { + Sequence<TInterval> value; + result.TryGetValue (variable, out value); + + result[variable] = value.Cons (intv); + } + } + + public struct InferenceResult<TVar, TInterval> + where TInterval : IAbstractDomain<TInterval> + where TVar : IEquatable<TVar> { + public static readonly InferenceResult<TVar, TInterval> Empty = + new InferenceResult<TVar, TInterval> (false, ImmutableMap<TVar, Sequence<TInterval>>.Empty); + + public readonly bool IsBottom; + + public readonly IImmutableMap<TVar, Sequence<TInterval>> Constraints; + + InferenceResult (bool isbottom, IImmutableMap<TVar, Sequence<TInterval>> map) + { + Constraints = map; + IsBottom = isbottom; + } + + public InferenceResult<TVar, TInterval> AddConstraintFor (TVar rightVar, TInterval refined) + { + Sequence<TInterval> seq; + Constraints.TryGetValue (rightVar, out seq); + + return new InferenceResult<TVar, TInterval> (IsBottom, Constraints.Add (rightVar, seq.Cons (refined))); + } + + public InferenceResult<TVar, TInterval> Join (InferenceResult<TVar, TInterval> that) + { + if (IsBottom) + return that; + if (that.IsBottom) + return this; + + var result = Empty; + foreach (var var in Constraints.Keys) { + var leftContraints = Constraints[var]; + if (leftContraints == null) + continue; + + // tops are not included + Sequence<TInterval> rightConstraints; + if (that.Constraints.TryGetValue (var, out rightConstraints) && rightConstraints != null) { + var intv = leftContraints.Head.Join (rightConstraints.Head); + if (!intv.IsTop) + result.AddConstraintFor (var, intv); + } + } + + return result; + } + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalAssumerBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalAssumerBase.cs new file mode 100644 index 00000000000..d9c377be938 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalAssumerBase.cs @@ -0,0 +1,148 @@ +// +// IntervalRationalAssumerBase.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class IntervalRationalAssumerBase<TVar, TExpr, TInterval> : + IntervalAssumerBase<TVar, TExpr, TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> + where TVar : IEquatable<TVar> { + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> AssumeLessThan + (TExpr left, TExpr right, IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> env) + { + bool isBottom; + var constraints = + IntervalInference.ConstraintsFor.LessThan<IIntervalEnvironment<TVar, TExpr, TInterval, Rational>, TVar, TExpr, TInterval> + (left, right, env.Decoder, env, out isBottom); + if (isBottom) + return env.Bottom; + + var res = env; + foreach (var v in constraints.Keys) { + var intervals = constraints[v].AsEnumerable (); + foreach (var intv in intervals) + res = res.RefineVariable (v, intv); + } + + return res; + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> AssumeLessEqualThan + (TExpr left, TExpr right, IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> env) + { + bool isBottom; + var constraints = + IntervalInference.ConstraintsFor.LessEqualThan + <IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational>, TVar, TExpr, TInterval> + (left, right, env.Decoder, env, + out isBottom); + if (isBottom) + return env.Bottom; + + return AssumeConstraints (constraints, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> AssumeGreaterEqualThanZero + (TExpr expr, + IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> env) + { + var constraints = + IntervalInference.ConstraintsFor.GreaterEqualThanZero + <IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational>, TVar, TExpr, TInterval> + (expr, env.Decoder, env); + return AssumeConstraints (constraints, env); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> AssumeLessThan + (TInterval intv, + TVar right, + IntervalEnvironmentBase + <TVar, + TExpr, + TInterval + , + Rational + > env) + { + TInterval refined; + if ( + !IntervalInference.ConstraintsFor.TryRefineLessEqualThan + <IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational>, TVar, TExpr, TInterval> + (intv, right, env, out refined)) + return env; + + return env.With (right, refined); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> AssumeLessEqualThan + ( + TInterval intv, TVar right, IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> env) + { + TInterval refined; + if ( + !IntervalInference.ConstraintsFor.TryRefineLessEqualThan + <IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational>, TVar, TExpr, TInterval> + (intv, right, env, out refined)) + return env; + + return env.With (right, refined); + } + + public override IntervalEnvironmentBase<TVar, TExpr, TInterval, Rational> AssumeNotEqualToZero + (TExpr e, + IntervalEnvironmentBase + < + TVar + , + TExpr + , + TInterval + , + Rational + > + env) + { + var variable = env.Decoder.UnderlyingVariable (e); + + var intv = env.Eval (e); + + TInterval refinement; + if (intv.LowerBound.IsZero) + refinement = env.Context.For (1L, intv.UpperBound); + else if (intv.UpperBound.IsZero) + refinement = env.Context.For (intv.LowerBound, -1L); + else + refinement = env.Context.TopValue; + + return env.With (variable, intv.Meet (refinement)); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalContextBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalContextBase.cs new file mode 100644 index 00000000000..08f880da9af --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalContextBase.cs @@ -0,0 +1,102 @@ +// +// IntervalRationalContextBase.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class IntervalRationalContextBase<TInterval> : IntervalContextBase<TInterval, Rational> + where TInterval : IntervalBase<TInterval, Rational> { + public override bool IsGreaterThanZero (Rational value) + { + return value > Rational.Zero; + } + + public override bool IsGreaterEqualThanZero (Rational value) + { + return value >= Rational.Zero; + } + + public override bool IsLessThanZero (Rational value) + { + return value < Rational.Zero; + } + + public override bool IsLessEqualThanZero (Rational value) + { + return value <= Rational.Zero; + } + + public override bool IsLessEqualThanZero (TInterval value) + { + if (value.IsNormal ()) + return IsLessEqualThanZero (value.UpperBound); + + return false; + } + + public override bool IsLessThan (Rational a, Rational b) + { + return a < b; + } + + public override bool IsLessEqualThan (Rational a, Rational b) + { + return a <= b; + } + + public override bool IsZero (Rational value) + { + return value.IsZero; + } + + public override bool IsNotZero (Rational value) + { + return !value.IsZero; + } + + public override bool IsPlusInfinity (Rational value) + { + return value.IsPlusInfinity; + } + + public override bool IsMinusInfinity (Rational value) + { + return value.IsMinusInfinity; + } + + public override bool AreEqual (Rational a, Rational b) + { + return a == b; + } + + public override bool IsMaxInt32 (TInterval value) + { + return value.IsSinglePoint && value.LowerBound.IsInteger && (int) value.LowerBound.NextInt32 == int.MaxValue; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/LongToIntegerConstantEvaluator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/LongToIntegerConstantEvaluator.cs new file mode 100644 index 00000000000..c464331f3f8 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/LongToIntegerConstantEvaluator.cs @@ -0,0 +1,114 @@ +// +// LongToIntegerConstantEvaluator.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class LongToIntegerConstantEvaluator : ConstantEvaluatorVisitor<long, int> { + protected override bool VisitAdd (long left, long right, out int result) + { + return true.With ((int) left + (int) right, out result); + } + + protected override bool VisitAnd (long left, long right, out int result) + { + return true.With ((int) left & (int) right, out result); + } + + protected override bool VisitOr (long left, long right, out int result) + { + return true.With ((int) left | (int) right, out result); + } + + protected override bool VisitXor (long left, long right, out int result) + { + return true.With ((int) left ^ (int) right, out result); + } + + protected override bool VisitEqual (long left, long right, out int result) + { + return true.With ((int) left == (int) right ? 1 : 0, out result); + } + + protected override bool VisitNotEqual (long left, long right, out int result) + { + return true.With ((int) left != (int) right ? 1 : 0, out result); + } + + protected override bool VisitLessThan (long left, long right, out int result) + { + return true.With ((int) left < (int) right ? 1 : 0, out result); + } + + protected override bool VisitLessEqualThan (long left, long right, out int result) + { + return true.With ((int) left <= (int) right ? 1 : 0, out result); + } + + protected override bool VisitGreaterThan (long left, long right, out int result) + { + return true.With ((int) left > (int) right ? 1 : 0, out result); + } + + protected override bool VisitGreaterEqualThan (long left, long right, out int result) + { + return true.With ((int) left >= (int) right ? 1 : 0, out result); + } + + protected override bool VisitSub (long left, long right, out int result) + { + return true.With ((int) left - (int) right, out result); + } + + protected override bool VisitMult (long left, long right, out int result) + { + return true.With ((int) left * (int) right, out result); + } + + protected override bool VisitDiv (long left, long right, out int result) + { + if (right == 0) + return false.Without (out result); + + return true.With ((int) left / (int) right, out result); + } + + protected override bool VisitMod (long left, long right, out int result) + { + if (right == 0) + return false.Without (out result); + + return true.With ((int) left % (int) right, out result); + } + + public static bool Evaluate (ExpressionOperator op, long left, long right, out int res) + { + return new LongToIntegerConstantEvaluator ().VisitBinary (op, left, right, out res); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Monomial.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Monomial.cs new file mode 100644 index 00000000000..1ccaf78edd0 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Monomial.cs @@ -0,0 +1,210 @@ +// +// Monomial.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + struct Monomial<TVar> { + static readonly IComparer<TVar> Comparer = new ExpressionViaStringComparer<TVar> (); + + readonly Rational coefficient; + + readonly Sequence<TVar> variables; + + public Rational Coeff { get { return coefficient; } } + + public IEnumerable<TVar> Variables { get { return variables.AsEnumerable (); } } + + public int Degree { get; private set; } + + public bool IsLinear { get { return Degree <= 1; } } + + public bool IsConstant { get { return Degree == 0; } } + + Monomial (Rational coeff) + : this () + { + coefficient = coeff; + variables = Sequence<TVar>.Empty; + Degree = 0; + } + + private Monomial (TVar x) + : this () + { + coefficient = Rational.One; + variables = Sequence<TVar>.Singleton (x); + Degree = 1; + } + + private Monomial (Rational k, TVar x) + : this () + { + coefficient = k; + variables = k == Rational.Zero ? Sequence<TVar>.Empty : Sequence<TVar>.Singleton (x); + Degree = variables.Length (); + } + + Monomial (Rational k, Sequence<TVar> vars) + : this () + { + coefficient = k; + variables = k == Rational.Zero ? Sequence<TVar>.Empty : vars; + Degree = variables.Length (); + } + + public bool Contains (TVar var) + { + return variables.Any (v => v.Equals (var)); + } + + public bool IsSingleVariable (out TVar var) + { + if (Degree == 1) + return true.With (variables.Head, out var); + + return false.Without (out var); + } + + public Monomial<TVar> Rename (TVar x, TVar rename) + { + if (!Contains (x)) + return this; + + Func<TVar, TVar> renamer = v => v.Equals (x) ? rename : v; + + return From (Coeff, variables.Select (renamer)); + } + + public Monomial<TVar> With (Rational coeff) + { + return new Monomial<TVar> (coeff, variables); + } + + public Monomial<TVar> With (Func<Rational, Rational> func) + { + return new Monomial<TVar> (func (coefficient), variables); + } + + public static Monomial<TVar> operator - (Monomial<TVar> m) + { + return m.With (-m.coefficient); + } + + public static Monomial<TVar> From (Rational coeff) + { + return new Monomial<TVar> (coeff); + } + + public static Monomial<TVar> From (Rational coeff, Sequence<TVar> vars) + { + return From (coeff, vars, seq => seq.AsEnumerable ()); + } + + public static Monomial<TVar> From (Rational coeff, IEnumerable<TVar> vars) + { + return From (coeff, vars, seq => seq); + } + + static Monomial<TVar> From<T> (Rational coeff, T vars, Func<T, IEnumerable<TVar>> toEnumerable) + { + if (coeff == Rational.Zero) + return new Monomial<TVar> (coeff); + + var list = toEnumerable (vars).ToList (); + list.Sort (Comparer); + + return new Monomial<TVar> (coeff, Sequence<TVar>.From (list)); + } + + public override string ToString () + { + return string.Format ("{0} * {1}", coefficient, VarsToString (variables)); + } + + static string VarsToString (Sequence<TVar> seq) + { + var len = seq.Length (); + var sb = new StringBuilder (); + if (len == 0) + sb.Append ("1"); + else { + sb.Append (seq.Head); + seq.Tail.ForEach (v => sb.AppendFormat (" * {0}", v)); + } + + return sb.ToString (); + } + + public bool IsEquivalentTo (Monomial<TVar> that) + { + if (coefficient != that.coefficient || Degree != that.Degree) + return false; + + if (Degree == 1) + return variables.Head.Equals (that.variables.Head); + + foreach (var var in variables.AsEnumerable ()) { + if (!that.Contains (var)) + return false; + } + + return true; + } + + public override bool Equals (object obj) + { + if (ReferenceEquals (obj, null)) + return false; + + if (obj is Monomial<TVar>) + return IsEquivalentTo ((Monomial<TVar>) obj); + return false; + } + + public override int GetHashCode () + { + var res = 0; + variables.ForEach (v => res += v.GetHashCode ()); + return res + coefficient.GetHashCode (); + } + + public bool IsIntConstant (out long constant) + { + if (IsConstant && coefficient.IsInteger) + return true.With ((long) coefficient.NextInt64, out constant); + + return false.Without (out constant); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ObjectExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ObjectExtensions.cs new file mode 100644 index 00000000000..c6429285c0c --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ObjectExtensions.cs @@ -0,0 +1,47 @@ +// +// ObjectExtensions.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static class ObjectExtensions { + public static long? ConvertToLong (this object value) + { + var convertible = value as IConvertible; + if (convertible != null) { + try { + convertible.ToInt64 (null); + } + catch { + } + } + + return null; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Polynomial.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Polynomial.cs new file mode 100644 index 00000000000..66ed9826c0f --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Polynomial.cs @@ -0,0 +1,677 @@ +// +// Polynomial.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + struct Polynomial<TVar, TExpr> + where TVar : IEquatable<TVar> { + readonly Monomial<TVar>[] left; + readonly ExpressionOperator? relation; + readonly Monomial<TVar>[] right; + IImmutableSet<TVar> cached_variables; + + public Polynomial (Monomial<TVar> monome) + { + relation = null; + left = new[] {monome}; + right = null; + + cached_variables = null; + } + + public Polynomial (Monomial<TVar>[] monomes) + { + relation = null; + left = monomes; + right = null; + + cached_variables = null; + } + + public Polynomial (ExpressionOperator op, Monomial<TVar>[] left, Monomial<TVar>[] right) + { + relation = op; + this.left = left; + this.right = right; + + cached_variables = null; + } + + public Polynomial (ExpressionOperator op, Monomial<TVar>[] left, Monomial<TVar> right) + { + relation = op; + this.left = left; + this.right = new[] {right}; + + cached_variables = null; + } + + public Polynomial (ExpressionOperator op, Polynomial<TVar, TExpr> left, Polynomial<TVar, TExpr> right) + { + relation = op; + this.left = left.left; + this.right = right.left; + + cached_variables = null; + } + + public Polynomial (Polynomial<TVar, TExpr> that) + { + relation = that.relation; + left = DuplicateFrom (that.left); + right = that.right != null ? DuplicateFrom (that.right) : null; + + cached_variables = null; + } + + public ExpressionOperator? Relation { get { return relation; } } + + public IImmutableSet<TVar> Variables + { + get + { + if (cached_variables == null) { + cached_variables = ImmutableSet<TVar>.Empty (); + foreach (var monome in left) + cached_variables = cached_variables.AddRange (monome.Variables); + if (relation.HasValue) + foreach (var monome in right) + cached_variables = cached_variables.AddRange (monome.Variables); + } + + return cached_variables; + } + } + + public Monomial<TVar>[] Left { get { return left; } } + public Monomial<TVar>[] Right { get { return right; } } + + public Polynomial<TVar, TExpr> LeftAsPolynomial + { + get + { + Polynomial<TVar, TExpr> polynome; + TryToPolynomial (left, out polynome); + return polynome; + } + } + + /// <summary> + /// Returns true if poly is in form: 'k*x < c' + /// </summary> + public bool IsIntervalForm + { + get + { + var op = Relation; + + if (!op.HasValue) + return false; + if (left.Length != 1 || right.Length != 1 || left[0].Degree != 1 || !right[0].IsConstant) + return false; + + return op.Value == ExpressionOperator.LessEqualThan; + } + } + + public bool IsLinear + { + get + { + if (left.Any (m => !m.IsLinear)) + return false; + if (Relation.HasValue && right.Any (m => !m.IsLinear)) + return false; + return true; + } + } + + static Monomial<TVar>[] DuplicateFrom (Monomial<TVar>[] original) + { + var res = new Monomial<TVar>[original.Length]; + Array.Copy (original, res, original.Length); + return res; + } + + public static bool TryToPolynomial (Monomial<TVar>[] monomials, out Polynomial<TVar, TExpr> polynome) + { + if (monomials.Length > 1) { + polynome = new Polynomial<TVar, TExpr> (monomials); + return polynome.TryToCanonicalForm (out polynome); + } + + return true.With (new Polynomial<TVar, TExpr> (monomials), out polynome); + } + + public bool TryToCanonicalForm (out Polynomial<TVar, TExpr> polynome) + { + var poly = this; + if (poly.relation.HasValue) { + switch (poly.relation.Value) { + case ExpressionOperator.GreaterThan: + poly = poly.SwapOperands (ExpressionOperator.LessThan); + break; + case ExpressionOperator.GreaterEqualThan: + poly = poly.SwapOperands (ExpressionOperator.LessEqualThan); + break; + } + + poly = poly.MoveConstantsAndMonomes (); + Debug.Assert (poly.relation.HasValue); + + Monomial<TVar>[] left; + Monomial<TVar>[] right; + if (TrySimplifyMonomes (poly.left, out left) && TrySimplifyMonomes (poly.right, out right)) + return true.With (new Polynomial<TVar, TExpr> (poly.relation.Value, left, right), out polynome); + } + else { + Monomial<TVar>[] monome; + if (TrySimplifyMonomes (left, out monome)) + return true.With (new Polynomial<TVar, TExpr> (monome), out polynome); + } + + return false.Without (out polynome); + } + + static bool TrySimplifyMonomes (Monomial<TVar>[] monomes, out Monomial<TVar>[] result) + { + if (monomes.Length <= 1) + return true.With (monomes, out result); + + var dict = new Dictionary<ListEqual<TVar>, Monomial<TVar>> (); + foreach (var monomial in monomes) { + var key = new ListEqual<TVar> (monomial.Degree, monomial.Variables); + Monomial<TVar> monome; + if (dict.TryGetValue (key, out monome)) { + Rational coeff; + if (!Rational.TryAdd (monome.Coeff, monomial.Coeff, out coeff)) + return false.With (monomes, out result); + + var sum = monome.With (coeff); + dict[key] = sum; + } + else + dict.Add (key, monomial); + } + + var left = new List<Monomial<TVar>> (dict.Count); + var right = new List<Monomial<TVar>> (dict.Count); + + Monomial<TVar>? resMonome = null; + foreach (var pair in dict) { + var monome = pair.Value; + if (!monome.Coeff.IsZero) { + if (monome.IsConstant) + resMonome = monome; + else if (monome.Coeff > 0L) + left.Add (monome); + else + right.Add (monome); + } + } + + var list = new List<Monomial<TVar>> (dict.Count); + list.AddRange (left); + list.AddRange (right); + + if (resMonome.HasValue) + list.Add (resMonome.Value); + if (list.Count == 0) + list.Add (Monomial<TVar>.From (Rational.Zero)); + + return true.With (list.ToArray (), out result); + } + + Polynomial<TVar, TExpr> MoveConstantsAndMonomes () + { + if (!relation.HasValue) + return this; + + var left = new List<Monomial<TVar>> (); + var right = new List<Monomial<TVar>> (); + + foreach (var monomial in this.left) + if (!monomial.IsConstant) + left.Add (monomial); + else + right.Add (-monomial); + + foreach (var monomial in this.right) + if (!monomial.IsConstant) + left.Add (-monomial); + else + right.Add (monomial); + + if (left.Count == 0) + left.Add (Monomial<TVar>.From (0L)); + if (right.Count == 0) + right.Add (Monomial<TVar>.From (0)); + + return new Polynomial<TVar, TExpr> (relation.Value, left.ToArray (), right.ToArray ()); + } + + Polynomial<TVar, TExpr> SwapOperands (ExpressionOperator newOp) + { + return new Polynomial<TVar, TExpr> (newOp, right, left); + } + + public override string ToString () + { + if (!relation.HasValue) + return ListToString (left); + + return string.Format ("{0} {1} {2}", ListToString (left), relation, ListToString (right)); + } + + static string ListToString (Monomial<TVar>[] list) + { + if (list == null) + return string.Empty; + if (list.Length == 0) + return "()"; + + var sb = new StringBuilder (); + + var stringsOrdered = list.Select (x => x.ToString ()).OrderBy (x => x); + var first = true; + sb.Append ("("); + foreach (var str in stringsOrdered) { + if (first) + first = false; + else + sb.Append (", "); + sb.Append (str); + } + sb.Append (")"); + + return sb.ToString (); + } + + public static bool TryReduceCoefficients (Monomial<TVar>[] simplifiedLeft, Monomial<TVar>[] simplifiedRight) + { + if (simplifiedRight[0].Coeff.IsMinValue) + return false; + + var abs = Rational.Abs (simplifiedRight[0].Coeff); + if (abs.IsZero) + return true; + + if (simplifiedLeft.Any (monome => !(monome.Coeff / abs).IsInteger)) + return true; + + simplifiedRight[0] = simplifiedRight[0].With ((c) => c / abs); + for (var i = 0; i < simplifiedLeft.Length; i++) + simplifiedLeft[i] = simplifiedLeft[i].With (c => c / abs); + + return true; + } + + public static bool TryBuildFrom (TExpr expr, IExpressionDecoder<TVar, TExpr> decoder, out Polynomial<TVar, TExpr> result) + { + return new PolynomialBuilder (decoder).Build (expr, out result); + } + + static bool TryMinus (Polynomial<TVar, TExpr> p, out Polynomial<TVar, TExpr> result) + { + if (p.Relation.HasValue) + return false.Without (out result); + + var monomes = new Monomial<TVar>[p.left.Length]; + var cnt = 0; + foreach (var m in p.left) { + var k = -m.Coeff; + if (k.IsInfinity) + return false.Without (out result); + + var mm = m.With (k); + monomes[cnt++] = mm; + } + + return true.With (new Polynomial<TVar, TExpr> (monomes), out result); + } + + bool IsIntConstant (out long constant) + { + if (Relation.HasValue || left.Length != 1) + return false.Without (out constant); + + return left[0].IsIntConstant (out constant); + } + + static Polynomial<TVar, TExpr> Concatenate (Polynomial<TVar, TExpr> left, Polynomial<TVar, TExpr> right) + { + if (left.Relation.HasValue || right.Relation.HasValue) + throw new InvalidOperationException (); + + var monomes = new Monomial<TVar>[left.left.Length + right.left.Length]; + + Array.Copy (left.left, monomes, left.left.Length); + Array.Copy (right.left, 0, monomes, left.left.Length, right.left.Length); + + return new Polynomial<TVar, TExpr> (left.left); + } + + public static bool TryToPolynomial (ExpressionOperator op, Polynomial<TVar, TExpr> left, Polynomial<TVar, TExpr> right, out Polynomial<TVar, TExpr> result) + { + if (op.IsBinary () && !left.Relation.HasValue) { + try { + var poly = new Polynomial<TVar, TExpr> (op, left, right); + if (poly.TryToCanonicalForm (out result)) + return true; + } + catch (Exception) { + } + } + + return false.Without (out result); + } + + #region Nested type: ConstantGatherer + + class ConstantGatherer : GenericTypeExpressionVisitor<TVar, TExpr, Dummy, Pair<Rational, bool>> { + static readonly Pair<Rational, bool> Failure = new Pair<Rational, bool> (Rational.PlusInfinity, false); + + public ConstantGatherer (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + protected override Pair<Rational, bool> Default (TExpr expr, Dummy input) + { + if (Decoder.IsNull (expr)) + return Success (Rational.Zero); + + return Failure; + } + + protected override Pair<Rational, bool> VisitBool (TExpr expr, Dummy input) + { + return Failure; + } + + protected override Pair<Rational, bool> VisitInt32 (TExpr expr, Dummy input) + { + int value; + if (Decoder.TryValueOf (expr, ExpressionType.Int32, out value)) + return Success (Rational.For (value)); + + return Failure; + } + + static Pair<Rational, bool> Success (Rational value) + { + return new Pair<Rational, bool> (value, true); + } + } + + #endregion + + #region Nested type: ListEqual + + class ListEqual<T> { + readonly Lazy<int> cached_hash_code; + readonly T[] elements; + + public ListEqual (int len, IEnumerable<T> seq) + { + elements = seq.Take (len).ToArray (); + cached_hash_code = new Lazy<int> (() => elements.Sum (elem => elem.GetHashCode ()), LazyThreadSafetyMode.None); + } + + public override int GetHashCode () + { + return cached_hash_code.Value; + } + + public override bool Equals (object obj) + { + var leq = obj as ListEqual<T>; + if (leq == null || elements.Length != leq.elements.Length) + return false; + + if (elements.Length == 1) + return elements[0].Equals (leq.elements[0]); + + return elements.Intersect (leq.elements).Count () == elements.Count (); + } + } + + #endregion + + #region Nested type: PolynomialBuilder + + class PolynomialBuilder : GenericExpressionVisitor<Dummy, bool, TVar, TExpr> { + Polynomial<TVar, TExpr> poly; + + public PolynomialBuilder (IExpressionDecoder<TVar, TExpr> decoder) + : base (decoder) + { + } + + public bool Build (TExpr expr, out Polynomial<TVar, TExpr> result) + { + if (base.Visit (expr, Dummy.Value)) + return true.With (poly, out result); + + return false.Without (out result); + } + + protected override bool Default (Dummy data) + { + return false; + } + + public override bool VisitSizeOf (TExpr expr, Dummy data) + { + int sizeOf; + if (!Decoder.TrySizeOf (expr, out sizeOf)) + return false; + + return true.With (new Polynomial<TVar, TExpr> (Monomial<TVar>.From (Rational.For (sizeOf))), out poly); + } + + public override bool VisitConstant (TExpr expr, Dummy data) + { + var pair = new ConstantGatherer (Decoder).Visit (expr, Dummy.Value); + if (!pair.Value || pair.Key.IsInfinity) + return false; + + poly = new Polynomial<TVar, TExpr> (Monomial<TVar>.From (pair.Key)); + return true; + } + + public override bool VisitAddition (TExpr left, TExpr right, TExpr original, Dummy data) + { + Polynomial<TVar, TExpr> polyLeft, polyRight; + if (!Build (left, out polyLeft) || !Build (right, out polyRight)) + return false; + + long kLeft, kRight; + object addition; + if (polyLeft.IsIntConstant (out kLeft) && polyRight.IsIntConstant (out kRight) && + EvaluateArithmeticWithOverflow.TryBinary (Decoder.TypeOf (original), ExpressionOperator.Add, kLeft, kRight, out addition)) { + var longValue = addition.ConvertToLong (); + if (longValue.HasValue) + return true.With (new Polynomial<TVar, TExpr> (Monomial<TVar>.From (Rational.For (longValue.Value))), out poly); + } + return true.With (Concatenate (polyLeft, polyRight), out poly); + } + + public override bool VisitSubtraction (TExpr left, TExpr right, TExpr original, Dummy data) + { + Polynomial<TVar, TExpr> polyLeft, polyRight; + if (!Build (left, out polyLeft) || !Build (right, out polyRight)) + return false; + + long kLeft, kRight; + object subtraction; + if (polyLeft.IsIntConstant (out kLeft) && polyRight.IsIntConstant (out kRight) && + EvaluateArithmeticWithOverflow.TryBinary (Decoder.TypeOf (original), ExpressionOperator.Sub, kLeft, kRight, out subtraction)) { + var longValue = subtraction.ConvertToLong (); + if (longValue.HasValue) + return true.With (new Polynomial<TVar, TExpr> (Monomial<TVar>.From (Rational.For (longValue.Value))), out poly); + } + return TryToPolynomialHelperForSubtraction (polyLeft, polyRight, out poly); + } + + public override bool VisitMultiply (TExpr left, TExpr right, TExpr original, Dummy data) + { + Polynomial<TVar, TExpr> l, r; + var lBuilt = Build (left, out l); + var rBuilt = Build (right, out r); + + if (lBuilt && rBuilt) { + long kLeft, kRight; + object mult; + if (l.IsIntConstant (out kLeft) && r.IsIntConstant (out kRight) && + EvaluateArithmeticWithOverflow.TryBinary ( + Decoder.TypeOf (original), ExpressionOperator.Mult, kLeft, kRight, out mult)) { + var longValue = mult.ConvertToLong (); + if (longValue.HasValue) { + var monomial = Monomial<TVar>.From (Rational.For (longValue.Value)); + return true.With (new Polynomial<TVar, TExpr> (monomial), out poly); + } + } + return TryToPolynomialHelperForMultiplication (l, r, out poly); + } + return false; + } + + static bool TryToPolynomialHelperForMultiplication (Polynomial<TVar, TExpr> left, Polynomial<TVar, TExpr> right, out Polynomial<TVar, TExpr> result) + { + var list = new List<Monomial<TVar>> (left.left.Length + right.left.Length); + foreach (var m in left.left) + foreach (var n in right.left) { + Rational mul; + if (!Rational.TryMultiply (m.Coeff, n.Coeff, out mul)) + return false.Without (out result); + + list.Add (Monomial<TVar>.From (mul, m.Variables.Concat (n.Variables))); + } + + return true.With (new Polynomial<TVar, TExpr> (list.ToArray ()), out result); + } + + static bool TryToPolynomialHelperForSubtraction (Polynomial<TVar, TExpr> left, Polynomial<TVar, TExpr> right, out Polynomial<TVar, TExpr> result) + { + Polynomial<TVar, TExpr> minusRight; + if (TryMinus (right, out minusRight)) + return true.With (Concatenate (left, right), out result); + + return false.Without (out result); + } + + public override bool VisitVariable (TVar var, TExpr expr, Dummy data) + { + var monome = Monomial<TVar>.From (Rational.One, Sequence<TVar>.Singleton (Decoder.UnderlyingVariable (expr))); + + return true.With (new Polynomial<TVar, TExpr> (monome), out poly); + } + + public override bool VisitNotEqual (TExpr left, TExpr right, TExpr original, Dummy data) + { + return DefaultRelation (left, right, original); + } + + public override bool VisitLessThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return DefaultRelation (left, right, original); + } + + public override bool VisitLessEqualThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return DefaultRelation (left, right, original); + } + + public override bool VisitGreaterThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return DefaultRelation (left, right, original); + } + + public override bool VisitGreaterEqualThan (TExpr left, TExpr right, TExpr original, Dummy data) + { + return DefaultRelation (left, right, original); + } + + public override bool VisitDivision (TExpr left, TExpr right, TExpr original, Dummy data) + { + Polynomial<TVar, TExpr> l, r; + if (!Build (left, out l) || !Build (right, out r)) + return false; + + return HelperForDivision (l, r, out poly); + } + + bool HelperForDivision (Polynomial<TVar, TExpr> left, Polynomial<TVar, TExpr> right, out Polynomial<TVar, TExpr> result) + { + if (right.left.Length == 1) { + var div = right.left[0]; + + if (div.IsConstant && !div.Coeff.IsZero) { + var monomes = new Monomial<TVar>[left.left.Length]; + var cnt = 0; + foreach (var m in left.left) { + Rational k; + try { + k = m.Coeff / div.Coeff; + } + catch (ArithmeticException) { + return false.Without (out result); + } + + monomes[cnt++] = m.With (k); + } + + return true.With (new Polynomial<TVar, TExpr> (monomes), out result); + } + } + + return false.Without (out result); + } + + bool DefaultRelation (TExpr left, TExpr right, TExpr original) + { + Polynomial<TVar, TExpr> l, r; + if (!Build (left, out l) || !Build (right, out r) || l.Relation.HasValue || r.Relation.HasValue) + return false; + + return true.With (new Polynomial<TVar, TExpr> (Decoder.OperatorFor (original), l.left, r.left), out poly); + } + } + + #endregion + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Rational.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Rational.cs new file mode 100644 index 00000000000..b70ea968dfe --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Rational.cs @@ -0,0 +1,814 @@ +// +// Rational.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + /// <summary> + /// Represents a rational number. + /// </summary> + struct Rational : IEquatable<Rational> { + public static readonly Rational Zero = new Rational (0L); + public static readonly Rational One = new Rational (1L); + public static readonly Rational MinusOne = new Rational (-1L); + + public static Rational PlusInfinity = new Rational (Kind.PlusInfinity); + public static Rational MinusInfinity = new Rational (Kind.MinusInfinity); + + public static Rational MaxValue = new Rational (long.MaxValue); + public static Rational MinValue = new Rational (long.MinValue); + + readonly long down; + readonly Kind kind; + readonly long up; + + Rational (Kind kind) + { + if (kind == Kind.Normal) + throw new ArgumentException ( + "Kind should be equal to Kind.PlusInfinity or Kind.MinusInfinity", "kind"); + + this.kind = kind; + this.up = 0L; + this.down = 0L; + } + + Rational (long number) + : this (number, 1L) + { + } + + Rational (long nominator, long denominator) + { + if (denominator == 0L) + throw new ArgumentException ("Denominator should not be equal to 0"); + + if (nominator == 0L) { + this.kind = Kind.Normal; + this.up = 0L; + this.down = 1L; + + return; + } + + this.kind = Kind.Normal; + + int sign = System.Math.Sign (nominator) * System.Math.Sign (denominator); + + if (nominator == long.MinValue) + nominator = sign >= 0 ? long.MaxValue : long.MinValue; + else + nominator = sign * System.Math.Abs (nominator); + + if (denominator == long.MinValue) + denominator = long.MaxValue; + else + denominator = System.Math.Abs (denominator); + + if (nominator % denominator == 0) { + this.up = nominator / denominator; + this.down = 1L; + + return; + } + + long gcd = (nominator == 0L || nominator == long.MaxValue || + denominator == 0L || denominator == long.MaxValue) + ? 1L + : GCD (System.Math.Abs (nominator), System.Math.Abs (denominator)); + + this.up = nominator / gcd; + this.down = denominator / gcd; + } + + public bool IsInteger { get { return !this.IsInfinity && (this.up % this.down == 0L); } } + + public bool IsInt32 { get { return this.IsInteger && this.up >= int.MinValue && this.up <= int.MaxValue; } } + + public bool IsInfinity { get { return this.kind == Kind.PlusInfinity || this.kind == Kind.MinusInfinity; } } + public bool IsPlusInfinity { get { return this.kind == Kind.PlusInfinity; } } + public bool IsMinusInfinity { get { return this.kind == Kind.MinusInfinity; } } + + public bool IsZero { get { return this.kind == Kind.Normal && this.up == 0L; } } + + public bool IsMaxValue { get { return this.kind == Kind.Normal && this.up == long.MaxValue && this.down == 1L; } } + public bool IsMinValue { get { return this.kind == Kind.Normal && this.up == -long.MaxValue && this.down == 1L; } } + + public int Sign { get { return GetSign (this); } } + + public Rational NextInt32 + { + get + { + if (this.IsInfinity) + return this; + var next = (long) System.Math.Ceiling ((double) this); + + return For (next >= int.MaxValue ? int.MaxValue : next); + } + } + + public Rational PreviousInt32 + { + get + { + if (this.IsInfinity) + return this; + + var prev = (long) System.Math.Floor ((double) this); + + return For (prev <= int.MinValue ? int.MinValue : prev); + } + } + + public Rational NextInt64 + { + get + { + if (this.IsInfinity) + return this; + double next = System.Math.Ceiling ((double) this); + + return For (next >= (double) long.MaxValue ? long.MaxValue : (long) System.Math.Truncate (next)); + } + } + + public long Up { get { return up; } } + public long Down { get { return down; } } + + public bool IsInRange (long min, long max) + { + return min <= this && this <= max; + } + + public static Rational For (long number) + { + return new Rational (number); + } + + public static Rational For (long nominator, long denominator) + { + switch (denominator) { + case 0L: + return new Rational (nominator >= 0 ? Kind.PlusInfinity : Kind.MinusInfinity); + default: + return new Rational (nominator, denominator); + } + } + + public static bool operator == (Rational l, Rational r) + { + if (l.kind != r.kind) + return false; + + if (l.kind != Kind.Normal) + return true; + + return l.up == r.up && l.down == r.down; + } + + public static bool operator != (Rational l, Rational r) + { + return !(l == r); + } + + public static bool operator < (Rational l, Rational r) + { + if (l.IsMinusInfinity && !r.IsMinusInfinity + || r.IsPlusInfinity && !l.IsPlusInfinity) + return true; + if (l.IsPlusInfinity || r.IsMinusInfinity) + return false; + if (l.down == r.down) + return l.up < r.up; + if (l.up <= 0L && r.up > 0L) + return true; + if (l.up < 0L && r.up == 0L) + return true; + + try { + return checked(l.up * r.down) < checked(r.up * l.down); + } + catch (ArithmeticException) { + return (decimal) l.up / l.down < (decimal) r.up / r.down; + } + } + + public static bool operator <= (Rational l, Rational r) + { + if (l.IsMinusInfinity || r.IsPlusInfinity) + return true; + if (l.IsPlusInfinity || r.IsMinusInfinity) + return false; + + if (l.down == r.down) + return l.up <= r.up; + + try { + return checked(l.up * r.down) <= checked(r.up * l.down); + } + catch (ArithmeticException) { + return (decimal) l.up / l.down <= (decimal) r.up / r.down; + } + } + + public static bool operator >= (Rational l, Rational r) + { + return r <= l; + } + + public static bool operator <= (Rational l, long r) + { + switch (l.kind) { + case Kind.PlusInfinity: + return false; + case Kind.MinusInfinity: + return true; + default: + try { + return l.up <= checked(l.down * r); + } + catch (ArithmeticException) { + return (decimal) l.up / l.down <= r; + } + } + } + + public static bool operator <= (long l, Rational r) + { + switch (r.kind) { + case Kind.PlusInfinity: + return true; + case Kind.MinusInfinity: + return false; + default: + try { + return r.up >= checked(r.down * l); + } + catch (ArithmeticException) { + return (decimal) r.up / r.down >= l; + } + } + } + + public static bool operator >= (long l, Rational r) + { + return r <= l; + } + + public static bool operator >= (Rational l, long r) + { + return r <= l; + } + + public static bool operator > (Rational l, Rational r) + { + return r < l; + } + + public static bool operator < (Rational l, long r) + { + switch (l.kind) { + case Kind.PlusInfinity: + return false; + case Kind.MinusInfinity: + return true; + default: + try { + return l.up < checked(r * l.down); + } + catch { + return (decimal) l.up / l.down < r; + } + } + } + + public static bool operator > (Rational l, long r) + { + return r < l; + } + + public static bool operator < (long l, Rational r) + { + switch (r.kind) { + case Kind.PlusInfinity: + return true; + case Kind.MinusInfinity: + return false; + default: + try { + return checked(l * r.down) < r.up; + } + catch { + return l < (decimal) r.up / r.down; + } + } + } + + public static bool operator > (long l, Rational r) + { + return r < l; + } + + public static Rational operator + (Rational l, Rational r) + { + Rational result; + if (TryAdd (l, r, out result)) + return result; + + throw new ArithmeticException (); + } + + public static Rational operator - (Rational l, Rational r) + { + Rational result; + if (TrySubtract (l, r, out result)) + return result; + + throw new ArithmeticException (); + } + + public static Rational operator * (Rational l, Rational r) + { + Rational result; + if (TryMultiply (l, r, out result)) + return result; + + throw new ArithmeticException (); + } + + public static Rational operator / (Rational l, Rational r) + { + Rational result; + if (TryDivide (l, r, out result)) + return result; + + throw new ArithmeticException (); + } + + public static Rational operator - (Rational l, long i) + { + if (l.kind == Kind.Normal && l.down == 1L) + try { + return For (checked(l.up - i)); + } + catch (ArithmeticException) { + } + + return l - For (i); + } + + public static Rational operator + (Rational l, long i) + { + if (l.kind == Kind.Normal && l.down == 1L) + try { + return For (checked(l.up + i)); + } + catch (ArithmeticException) { + } + + return l + For (i); + } + + public static Rational operator - (Rational value) + { + Rational result; + if (TryUnaryMinus (value, out result)) + return result; + + throw new ArithmeticException (); + } + + public static explicit operator double (Rational r) + { + switch (r.kind) { + case Kind.PlusInfinity: + return double.PositiveInfinity; + case Kind.MinusInfinity: + return double.NegativeInfinity; + default: + return (double) r.up / r.down; + } + } + + public static explicit operator long (Rational r) + { + if (r.down == 0L) + return r.up >= 0L ? long.MaxValue : long.MinValue; + + if (!r.IsInteger) + return (long) System.Math.Round ((double) r.up / r.down); + + return r.up; + } + + public static explicit operator int (Rational r) + { + if (r.down != 0L) + return (int) System.Math.Round ((double) r.up / r.down); + + return r.up >= 0L ? int.MaxValue : int.MinValue; + } + + public static implicit operator Rational (long l) + { + return For (l); + } + + public static Rational Abs (Rational a) + { + switch (a.kind) { + case Kind.PlusInfinity: + case Kind.MinusInfinity: + return PlusInfinity; + default: + return a.IsZero || a > 0L ? a : -a; + } + } + + public static Rational Max (Rational a, Rational b) + { + return a < b ? b : a; + } + + public static Rational Min (Rational a, Rational b) + { + return a < b ? a : b; + } + + public static bool TryAdd (Rational l, Rational r, out Rational result) + { + if (l.IsZero) + return true.With (r, out result); + + if (r.IsZero || l.IsInfinity) + return true.With (l, out result); + + if (r.IsInfinity) + return true.With (r, out result); + + if (l.IsMaxValue && r > 0L || r.IsMaxValue && l > 0L) + return true.With (PlusInfinity, out result); + + long nom; + long denom; + try { + if (l.down == r.down) { + if (l.up == r.up && (r.down & 1L) == 0L) { + nom = l.up; + denom = l.down >> 1; + } + else { + nom = checked (l.up + r.up); + denom = l.down; + } + } + else { + nom = checked (l.up * r.down + r.up * l.down); + denom = checked (l.down * r.down); + } + } + catch (ArithmeticException) { + try { + long gcd = GCD (l.down, r.down); + nom = + checked ( + l.up * unchecked (r.down / gcd) + + r.up * unchecked (l.down / gcd)); + denom = checked ((l.down / gcd) * r.down); + } + catch (ArithmeticException) { + return false.Without (out result); + } + } + + return true.With (denom == 1L ? For (nom) : For (nom, denom), out result); + } + + public static bool TrySubtract (Rational l, Rational r, out Rational result) + { + if (r.IsZero) + return true.With (l, out result); + + if (l.IsZero) + return true.With (-r, out result); + + if (l == r) + return true.With (Zero, out result); + + if (r < 0L && !r.IsMinValue) + return TryAdd (l, Abs (r), out result); + + if (l.IsInfinity) + return true.With (l, out result); + + if (r.IsInfinity) + return true.With (-r, out result); + + if (l.IsMinValue && r > 0L) + return true.With (MinusInfinity, out result); + + long nom; + long denom; + try { + if (l.down == r.down) { + nom = checked (l.up - r.up); + denom = l.down; + } + else { + nom = checked (l.up * r.down - r.up * l.down); + denom = checked (l.down * r.down); + } + } + catch (ArithmeticException) { + return false.Without (out result); + } + + return true.With (For (nom, denom), out result); + } + + public static bool TryDivide (Rational l, Rational r, out Rational result) + { + if (r == One) + return true.With (l, out result); + + if (r.IsZero) + return false.Without (out result); + + if (l.IsZero || r.IsInfinity) + return true.With (Zero, out result); + + if (l.IsPlusInfinity) + return true.With (r.Sign > 0 ? PlusInfinity : MinusInfinity, out result); + + if (l.IsMinusInfinity) + return true.With (r.Sign > 0 ? MinusInfinity : PlusInfinity, out result); + + long nom; + long denom; + + if (l.up == r.up) { + // (a/b)/(a/c) = (c/b) + + nom = r.down; + denom = l.down; + } + else if (l.down == r.down) { + // (a/c)/(b/c) = (a/b) + + nom = l.up; + denom = r.up; + } + else { + // (x/y) / (e/f) == (x/e) * (f/y) + + Rational a = For (l.up, r.up); + Rational b = For (r.down, l.down); + + try { + return TryMultiply (a, b, out result); + } + catch (ArithmeticException) { + return false.Without (out result); + } + } + + return true.With (For (nom, denom), out result); + } + + public static bool TryMultiply (Rational l, Rational r, out Rational result) + { + if (l.IsZero || r.IsZero) + return true.With (Zero, out result); + + if (l == One) + return true.With (r, out result); + if (r == One) + return true.With (l, out result); + + if (l.IsPlusInfinity) { + if (r.IsPlusInfinity) + result = PlusInfinity; + else if (r.IsMinusInfinity) + result = MinusInfinity; + else if (r.IsZero) + result = Zero; + else + result = r.Sign > 0 ? PlusInfinity : MinusInfinity; + + return true; + } + + if (l.IsMinusInfinity) { + if (r.IsPlusInfinity) + result = MinusInfinity; + else if (r.IsMinusInfinity) + result = PlusInfinity; + else if (r.IsZero) + result = Zero; + else + result = r.Sign > 0 ? MinusInfinity : PlusInfinity; + + return true; + } + + if (r.IsPlusInfinity) { + if (l.IsZero) + result = Zero; + else + result = l.Sign > 0 ? PlusInfinity : MinusInfinity; + + return true; + } + + if (r.IsMinusInfinity) { + if (l.IsZero) + result = Zero; + else + result = l.Sign > 0 ? MinusInfinity : PlusInfinity; + + return true; + } + + long nom; + long denom; + + try { + Rational a = For (l.up, r.down); + Rational b = For (r.up, l.down); + + nom = checked(a.up * b.up); + denom = checked(a.down * b.down); + } + catch (ArithmeticException) { + return false.Without (out result); + } + + return true.With (For (nom, denom), out result); + } + + public static bool TryUnaryMinus (Rational value, out Rational result) + { + if (value.IsZero) + return true.With (value, out result); + + switch (value.kind) { + case Kind.PlusInfinity: + return true.With (MinusInfinity, out result); + case Kind.MinusInfinity: + return true.With (PlusInfinity, out result); + } + + if (value.IsMinValue) + return true.With (MaxValue, out result); + if (value.IsMaxValue) + return true.With (MinValue, out result); + + return true.With (For (-value.up, value.down), out result); + } + + static int GetSign (Rational r) + { + switch (r.kind) { + case Kind.PlusInfinity: + return 1; + case Kind.MinusInfinity: + return -1; + default: + return System.Math.Sign (r.up) * System.Math.Sign (r.down); + } + } + + static long GCD (long a, long b) + { + var aa = (ulong) a; + var bb = (ulong) b; + + int pow = 0; + + while (((aa | bb) & 1L) == 0L) //while both divide by 2 + { + aa >>= 1; + bb >>= 1; + ++pow; + } + + while ((aa & 1L) == 0L) //get rid of other 2's factors + aa >>= 1; + + do { + while ((bb & 1L) == 0L) + bb >>= 1; + + ulong cc; + if (aa < bb) + cc = bb - aa; + else { + ulong tmp = aa - bb; + aa = bb; + cc = tmp; + } + + bb = cc >> 1; + } while (bb != 0L); + + return (long) aa << pow; + } + + public override bool Equals (object obj) + { + if (ReferenceEquals (null, obj)) + return false; + if (ReferenceEquals (this, obj)) + return true; + return obj is Rational && this.Equals ((Rational) obj); + } + + public bool Equals (Rational other) + { + return this == other; + } + + public override int GetHashCode () + { + unchecked { + int hashCode = this.kind.GetHashCode (); + hashCode = (hashCode * 397) ^ this.up.GetHashCode (); + hashCode = (hashCode * 1001) ^ this.down.GetHashCode (); + return hashCode; + } + } + + public override string ToString () + { + switch (this.kind) { + case Kind.MinusInfinity: + return "-oo" + + (this.up == -1L || this.down == 0L + ? "" + : string.Format ("({0} / {1})", this.up, this.down)); + case Kind.PlusInfinity: + return "+oo" + + (this.up == 1L || this.down == 0L + ? "" + : string.Format ("({0} / {1})", this.up, this.down)); + default: + return this.IsInteger + ? this.up.ToString () + : string.Format ("({0} / {1})", this.up, this.down); + } + } + + enum Kind { + Normal, + PlusInfinity, + MinusInfinity, + } + } + + static class RationalExtensions { + public static TExpr ToExpression<TVar, TExpr>(this Rational value, IExpressionEncoder<TVar, TExpr> encoder ) + { + if (value.IsInteger) + return encoder.ConstantFor ((long) value); + if (value.IsPlusInfinity) + return encoder.CompoundFor (ExpressionType.Int32, ExpressionOperator.Div, + encoder.ConstantFor (1L), encoder.ConstantFor (0L)); + if (value.IsMinusInfinity) + return encoder.CompoundFor (ExpressionType.Int32, ExpressionOperator.Div, + encoder.ConstantFor (-1L), encoder.ConstantFor (0L)); + + TExpr l = encoder.ConstantFor (value.Up); + TExpr r = encoder.ConstantFor (value.Down); + + return encoder.CompoundFor (ExpressionType.Int32, ExpressionOperator.Div, l, r); + } + } +} diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/RationalThreshold.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/RationalThreshold.cs new file mode 100644 index 00000000000..9050db0d581 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/RationalThreshold.cs @@ -0,0 +1,46 @@ +// +// RationalThreshold.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class RationalThreshold : Threshold<Rational> { + public RationalThreshold (int size) : base (size) + { + } + + protected override Rational MinusInfinity { get { return Rational.MinusInfinity; } } + + protected override Rational PlusInfinity { get { return Rational.PlusInfinity; } } + + protected override Rational Zero { get { return Rational.Zero; } } + + protected override bool LessThan (Rational a, Rational b) + { + return a < b; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Threshold.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Threshold.cs new file mode 100644 index 00000000000..37f817ba22c --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/Threshold.cs @@ -0,0 +1,104 @@ +// +// Threshold.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + abstract class Threshold<T> { + protected int NextFree; + protected readonly List<T> Values; + + protected abstract T MinusInfinity { get; } + protected abstract T PlusInfinity { get; } + protected abstract T Zero { get; } + + public int Count { get { return Values.Count; } } + + protected Threshold (int size) + { + Values = new List<T> (size) {MinusInfinity, Zero, PlusInfinity}; + NextFree = 3; + } + + public bool Add (T value) + { + if (NextFree == Values.Count) + return false; + + var idx = 0; + while (idx < NextFree && LessThan (Values[idx], value)) + idx++; + + if (Values[idx].Equals (value)) + return false; + + Values.Insert (idx, value); + NextFree++; + return true; + } + + protected abstract bool LessThan (T a, T b); + + public T GetNext (T value) + { + var index = BinarySearch (value, 0, NextFree - 1); + + if (index >= 0) + return Values[index]; + + var nextIndex = ~index; //because binary search returns position of next item if not found + return Values[nextIndex]; + } + + public T GetPrevious (T value) + { + var index = BinarySearch (value, 0, NextFree - 1); + + if (index >= 0) + return Values[index]; + + var nextIndex = ~index; + return Values[nextIndex - 1]; + } + + public int BinarySearch (T value, int low, int hi) + { + while (low <= hi) { + var median = low + ((hi - low) >> 1); + if (Values[median].Equals (value)) + return median; + if (LessThan (Values[median], value)) + low = median + 1; + else + hi = median - 1; + } + + return ~low; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/TresholdDB.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/TresholdDB.cs new file mode 100644 index 00000000000..1914a8c09ad --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/TresholdDB.cs @@ -0,0 +1,75 @@ +// +// TresholdDB.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + static class ThresholdDB { + static RationalThreshold rational = new RationalThreshold (10); + + public static void Reset () + { + rational = new RationalThreshold (10); + } + + public static void Add (IEnumerable<int> values) + { + foreach (var value in values) { + rational.Add (Rational.For (value)); + } + } + + public static Rational GetNext (Rational value) + { + return rational.GetNext (value); + } + + public static Rational GetPrevious (Rational value) + { + return rational.GetPrevious (value); + } + + public static bool TryGetAThreshold<TVar, TExpr> (TExpr e, IExpressionDecoder<TVar, TExpr> decoder, out List<int> thresholds) + { + var visitor = new GetThresholdVisitor<TVar, TExpr> (decoder); + if (visitor.Visit (e, Dummy.Value)) { + thresholds = new List<int> (); + foreach (var threshold in visitor.Thresholds) { + thresholds.Add (threshold - 1); + thresholds.Add (threshold); + thresholds.Add (threshold + 1); + } + return true; + } + + return false.Without (out thresholds); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ValueExpressionDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ValueExpressionDecoder.cs new file mode 100644 index 00000000000..83a4a93484b --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Numerical/ValueExpressionDecoder.cs @@ -0,0 +1,333 @@ +// +// ValueExpressionDecoder.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.AST.Visitors; +using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding; +using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; +using Mono.CodeContracts.Static.Providers; + +namespace Mono.CodeContracts.Static.Analysis.Numerical { + class ValueExpressionDecoder<TVar, TExpr> : FullExpressionDecoder<TVar, TExpr>, IExpressionDecoder<TVar, TExpr> + where TVar : IEquatable<TVar> + where TExpr : IEquatable<TExpr> { + readonly VisitorForOperatorFor operator_for; + readonly VisitorForTypeOf type_of; + + public ValueExpressionDecoder (IMetaDataProvider metaDataProvider, IExpressionContextProvider<TExpr, TVar> contextProvider) + : base (metaDataProvider, contextProvider) + { + operator_for = new VisitorForOperatorFor (); + type_of = new VisitorForTypeOf (); + } + + IExpressionContext<TExpr, TVar> ExpressionContext { get { return ContextProvider.ExpressionContext; } } + + #region IExpressionDecoder<TVar,TExpr> Members + + public ExpressionOperator OperatorFor (TExpr expr) + { + return ExpressionContext.Decode<TExpr, ExpressionOperator, VisitorForOperatorFor> (expr, operator_for, expr); + } + + public TExpr LeftExpressionFor (TExpr expr) + { + UnaryOperator op; + BinaryOperator bop; + TExpr left; + TExpr right; + + if (IsUnaryExpression (expr, out op, out left) || IsBinaryExpression (expr, out bop, out left, out right)) + return left; + + throw new InvalidOperationException (); + } + + public TExpr RightExpressionFor (TExpr expr) + { + BinaryOperator bop; + TExpr left; + TExpr right; + if (IsBinaryExpression (expr, out bop, out left, out right)) + return right; + + throw new InvalidOperationException (); + } + + public bool IsConstant (TExpr expr) + { + return OperatorFor (expr) == ExpressionOperator.Constant; + } + + public bool IsVariable (TExpr expr) + { + object variable; + return base.IsVariable (expr, out variable); + } + + public bool TryValueOf<T> (TExpr e, ExpressionType expectedType, out T result) + { + object value; + TypeNode actualType; + if (base.IsConstant (e, out value, out actualType)) { + if (value is T) + return true.With ((T) value, out result); + if (value is int && expectedType == ExpressionType.Bool) { + result = (T) (object) ((int) value != 0); + return true; + } + } + return false.Without (out result); + } + + public bool TrySizeOf (TExpr expr, out int size) + { + TypeNode type; + if (VisitorForSizeOf<TVar, TExpr>.IsSizeOf (expr, out type, this)) { + size = MetaDataProvider.TypeSize (type); + return size != -1; + } + + return false.Without (out size); + } + + public ExpressionType TypeOf (TExpr expr) + { + if (IsConstant (expr)) + return ExpressionContext.Decode<Dummy, ExpressionType, VisitorForTypeOf> (expr, type_of, Dummy.Value); + + var abstractType = ExpressionContext.GetType (expr); + + if (abstractType.IsNormal ()) { + var type = abstractType.Value; + + if (MetaDataProvider.IsPrimitive (type)) { + if (MetaDataProvider.Equal (type, MetaDataProvider.System_Int32)) + return ExpressionType.Int32; + if (MetaDataProvider.Equal (type, MetaDataProvider.System_Single)) + return ExpressionType.Float32; + if (MetaDataProvider.Equal (type, MetaDataProvider.System_Double)) + return ExpressionType.Float64; + if (MetaDataProvider.Equal (type, MetaDataProvider.System_Boolean)) + return ExpressionType.Bool; + } + } + + return ExpressionType.Unknown; + } + + public bool IsConstantInt (TExpr expr, out int value) + { + TypeNode type; + object objValue; + if (IsConstant (expr, out objValue, out type)) + return true.With ((int) objValue, out value); + + return false.Without (out value); + } + + public string NameOf (TVar variable) + { + return variable.ToString (); + } + + public bool IsBinaryExpression (TExpr expr) + { + BinaryOperator op; + TExpr left; + TExpr right; + return IsBinaryExpression (expr, out op, out left, out right); + } + + #endregion + + #region Nested type: VisitorForOperatorFor + + class VisitorForOperatorFor : ISymbolicExpressionVisitor<TExpr, TExpr, TVar, TExpr, ExpressionOperator> { + #region ISymbolicExpressionVisitor<TExpr,TExpr,TVar,TExpr,ExpressionOperator> Members + + public ExpressionOperator Binary (TExpr pc, BinaryOperator bop, TVar dest, TExpr src1, TExpr src2, TExpr data) + { + switch (bop) { + case BinaryOperator.Add: + case BinaryOperator.Add_Ovf: + case BinaryOperator.Add_Ovf_Un: + return ExpressionOperator.Add; + case BinaryOperator.And: + return ExpressionOperator.And; + case BinaryOperator.Ceq: + return ExpressionOperator.Equal; + case BinaryOperator.Cobjeq: + return ExpressionOperator.Equal_Obj; + case BinaryOperator.Cne_Un: + return ExpressionOperator.NotEqual; + case BinaryOperator.Cge: + case BinaryOperator.Cge_Un: + return ExpressionOperator.GreaterEqualThan; + case BinaryOperator.Cgt: + case BinaryOperator.Cgt_Un: + return ExpressionOperator.GreaterThan; + case BinaryOperator.Cle: + case BinaryOperator.Cle_Un: + return ExpressionOperator.LessEqualThan; + case BinaryOperator.Clt: + case BinaryOperator.Clt_Un: + return ExpressionOperator.LessThan; + case BinaryOperator.Div: + case BinaryOperator.Div_Un: + return ExpressionOperator.Div; + case BinaryOperator.LogicalAnd: + return ExpressionOperator.LogicalAnd; + case BinaryOperator.LogicalOr: + return ExpressionOperator.LogicalOr; + case BinaryOperator.Mul: + case BinaryOperator.Mul_Ovf: + case BinaryOperator.Mul_Ovf_Un: + return ExpressionOperator.Mult; + case BinaryOperator.Or: + return ExpressionOperator.Or; + case BinaryOperator.Rem: + case BinaryOperator.Rem_Un: + return ExpressionOperator.Mod; + case BinaryOperator.Sub: + case BinaryOperator.Sub_Ovf: + case BinaryOperator.Sub_Ovf_Un: + return ExpressionOperator.Sub; + case BinaryOperator.Xor: + return ExpressionOperator.Xor; + default: + return ExpressionOperator.Unknown; + } + } + + public ExpressionOperator Unary (TExpr pc, UnaryOperator uop, bool unsigned, TVar dest, TExpr source, TExpr data) + { + switch (uop) { + case UnaryOperator.Conv_i: + case UnaryOperator.Conv_i1: + case UnaryOperator.Conv_i2: + case UnaryOperator.Conv_i4: + case UnaryOperator.Conv_i8: + return ExpressionOperator.ConvertToInt32; + case UnaryOperator.Neg: + return ExpressionOperator.Not; + case UnaryOperator.Not: + return ExpressionOperator.Not; + default: + return ExpressionOperator.Unknown; + } + } + + public ExpressionOperator LoadNull (TExpr pc, TVar dest, TExpr polarity) + { + return ExpressionOperator.Constant; + } + + public ExpressionOperator LoadConst (TExpr pc, TypeNode type, object constant, TVar dest, TExpr data) + { + return ExpressionOperator.Constant; + } + + public ExpressionOperator Sizeof (TExpr pc, TypeNode type, TVar dest, TExpr data) + { + return ExpressionOperator.SizeOf; + } + + public ExpressionOperator Isinst (TExpr pc, TypeNode type, TVar dest, TExpr obj, TExpr data) + { + return ExpressionOperator.Unknown; + } + + public ExpressionOperator SymbolicConstant (TExpr pc, TVar variable, TExpr data) + { + return ExpressionOperator.Variable; + } + + #endregion + } + + #endregion + + #region Nested type: VisitorForTypeOf + + class VisitorForTypeOf : ISymbolicExpressionVisitor<TExpr, TExpr, TVar, Dummy, ExpressionType> { + #region ISymbolicExpressionVisitor<TExpr,TExpr,TVar,Dummy,ExpressionType> Members + + public ExpressionType Binary (TExpr pc, BinaryOperator bop, TVar dest, TExpr src1, TExpr src2, Dummy data) + { + return ExpressionType.Unknown; + } + + public ExpressionType Unary (TExpr pc, UnaryOperator uop, bool unsigned, TVar dest, TExpr source, Dummy data) + { + return ExpressionType.Unknown; + } + + public ExpressionType LoadNull (TExpr pc, TVar dest, Dummy polarity) + { + return ExpressionType.Unknown; + } + + public ExpressionType LoadConst (TExpr pc, TypeNode type, object constant, TVar dest, Dummy data) + { + if (constant is int) + return ExpressionType.Int32; + if (constant is float) + return ExpressionType.Float32; + if (constant is double) + return ExpressionType.Float64; + if (constant is bool) + return ExpressionType.Bool; + + return ExpressionType.Unknown; + } + + public ExpressionType Sizeof (TExpr pc, TypeNode type, TVar dest, Dummy data) + { + return ExpressionType.Int32; + } + + public ExpressionType Isinst (TExpr pc, TypeNode type, TVar dest, TExpr obj, Dummy data) + { + return ExpressionType.Unknown; + } + + public ExpressionType SymbolicConstant (TExpr pc, TVar variable, Dummy data) + { + return ExpressionType.Unknown; + } + + #endregion + } + + #endregion + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs index 2f21c67939d..30d87a4f49e 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs @@ -38,7 +38,7 @@ namespace Mono.CodeContracts.Static.Analysis.StackAnalysis { public APCMap (Subroutine parent) { this.block_map = new Dictionary<int, T>[parent.BlockCount]; - this.call_on_this_map = ImmutableIntMap<bool>.Empty (); + this.call_on_this_map = ImmutableIntMap<bool>.Empty; } public T this [APC key] diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs index 5d0853f3a63..f7427ddea2a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs @@ -93,7 +93,7 @@ namespace Mono.CodeContracts.Static.Analysis.StackAnalysis { isLoadResult = false; isOld = false; lookupPC = pc; - for (LispList<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) { + for (Sequence<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) { EdgeTag edgeTag = list.Head.Tag; if (edgeTag == EdgeTag.Entry) { param = RemapParameter (param, list.Head.From, pc.Block); @@ -111,7 +111,7 @@ namespace Mono.CodeContracts.Static.Analysis.StackAnalysis { if (pc.Block.Subroutine.IsEnsuresOrOldValue) { isOld = true; - for (LispList<Edge<CFGBlock, EdgeTag>> ctx = pc.SubroutineContext; ctx != null; ctx = ctx.Tail) { + for (Sequence<Edge<CFGBlock, EdgeTag>> ctx = pc.SubroutineContext; ctx != null; ctx = ctx.Tail) { EdgeTag tag = ctx.Head.Tag; if (tag == EdgeTag.Exit) { param = RemapParameter (param, ctx.Head.From, pc.Block); @@ -155,7 +155,7 @@ namespace Mono.CodeContracts.Static.Analysis.StackAnalysis { } if (pc.Block.Subroutine.IsInvariant) { - for (LispList<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) { + for (Sequence<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) { EdgeTag tag = list.Head.Tag; if (tag == EdgeTag.Entry || tag == EdgeTag.Exit) { Method method; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthProvider.cs index 0ffc4616cda..1d87cf51669 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthProvider.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthProvider.cs @@ -295,8 +295,8 @@ namespace Mono.CodeContracts.Static.Analysis.StackAnalysis { return UnderlyingCFG.GetDecoder (metaDataProvider); } - void ICFG.Print (TextWriter tw, ILPrinter<APC> printer, Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context) + void ICFG.Print (TextWriter tw, ILPrinter<APC> printer, Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context) { DecoratorHelper.Push (this); try { @@ -305,7 +305,18 @@ namespace Mono.CodeContracts.Static.Analysis.StackAnalysis { DecoratorHelper.Pop (); } } - #endregion + + public bool IsForwardBackEdge (APC @from, APC to) + { + return this.UnderlyingCFG.IsForwardBackEdge (from, to); + } + + public APC Post (APC pc) + { + return UnderlyingCFG.Post (pc); + } + + #endregion #region Implementation of IStackInfo bool IStackInfo.IsCallOnThis (APC pc) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs index 12de0dafe96..449879a7736 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs @@ -27,8 +27,7 @@ // namespace Mono.CodeContracts.Static.Analysis { - interface IExpressionContextProvider<Expression, Variable> - : IValueContextProvider<Variable> { - IExpressionContext<Expression, Variable> ExpressionContext { get; } - } + interface IExpressionContextProvider<Expression, Variable> : IValueContextProvider<Variable> { + IExpressionContext<Expression, Variable> ExpressionContext { get; } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ILPrinter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ILPrinter.cs index 3f1bc695c62..15a1ac8d8fc 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ILPrinter.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ILPrinter.cs @@ -29,5 +29,5 @@ using System.IO; namespace Mono.CodeContracts.Static.Analysis { - delegate void ILPrinter<Label> (Label label, string prefix, TextWriter tw); + delegate void ILPrinter<TLabel> (TLabel label, string prefix, TextWriter tw); }
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs index 9da3d712fef..8b89680e119 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs @@ -39,6 +39,6 @@ namespace Mono.CodeContracts.Static.Analysis { bool TryParameterValue (APC at, Parameter p, out SymbolicValue sv); bool IsConstant (APC readAt, SymbolicValue symbol, out TypeNode type, out object constant); FlatDomain<TypeNode> GetType (APC readAt, SymbolicValue symbol); - LispList<PathElement> AccessPathList (APC at, SymbolicValue value, bool allowLocal, bool preferLocal); + Sequence<PathElement> AccessPathList (APC at, SymbolicValue value, bool allowLocal, bool preferLocal); } }
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockBuilder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockBuilder.cs index 23f0ccec38a..fcacab49c1a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockBuilder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockBuilder.cs @@ -32,23 +32,23 @@ using Mono.CodeContracts.Static.ControlFlow.Blocks; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { - class BlockBuilder<Label> : ILVisitorBase<Label, Dummy, Dummy, BlockWithLabels<Label>, bool>, - IAggregateVisitor<Label, BlockWithLabels<Label>, bool> { - private readonly SubroutineBuilder<Label> builder; - private BlockWithLabels<Label> current_block; + class BlockBuilder<TLabel> : ILVisitorBase<TLabel, Dummy, Dummy, BlockWithLabels<TLabel>, bool>, + IAggregateVisitor<TLabel, BlockWithLabels<TLabel>, bool> { + private readonly SubroutineBuilder<TLabel> builder; + private BlockWithLabels<TLabel> current_block; - private BlockBuilder (SubroutineBuilder<Label> builder) + private BlockBuilder (SubroutineBuilder<TLabel> builder) { this.builder = builder; } - private SubroutineBase<Label> CurrentSubroutine + private SubroutineBase<TLabel> CurrentSubroutine { get { return this.builder.CurrentSubroutine; } } #region IAggregateVisitor<Label,BlockWithLabels<Label>,bool> Members - public override bool Branch (Label pc, Label target, bool leavesExceptionBlock, BlockWithLabels<Label> currentBlock) + public override bool Branch (TLabel pc, TLabel target, bool leavesExceptionBlock, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.Branch, CurrentSubroutine.GetTargetBlock (target)); @@ -56,41 +56,41 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { return true; } - public override bool BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, BlockWithLabels<Label> currentBlock) + public override bool BranchCond (TLabel pc, TLabel target, BranchOperator bop, Dummy value1, Dummy value2, BlockWithLabels<TLabel> currentBlock) { return HandleConditionalBranch (pc, target, true, currentBlock); } - public override bool BranchFalse (Label pc, Label target, Dummy cond, BlockWithLabels<Label> currentBlock) + public override bool BranchFalse (TLabel pc, TLabel target, Dummy cond, BlockWithLabels<TLabel> currentBlock) { return HandleConditionalBranch (pc, target, false, currentBlock); } - public override bool BranchTrue (Label pc, Label target, Dummy cond, BlockWithLabels<Label> currentBlock) + public override bool BranchTrue (TLabel pc, TLabel target, Dummy cond, BlockWithLabels<TLabel> currentBlock) { return HandleConditionalBranch (pc, target, true, currentBlock); } - public override bool Throw (Label pc, Dummy exception, BlockWithLabels<Label> currentBlock) + public override bool Throw (TLabel pc, Dummy exception, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); return true; } - public override bool Rethrow (Label pc, BlockWithLabels<Label> currentBlock) + public override bool Rethrow (TLabel pc, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); return true; } - public override bool EndFinally (Label pc, BlockWithLabels<Label> currentBlock) + public override bool EndFinally (TLabel pc, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.EndSubroutine, CurrentSubroutine.Exit); return true; } - public override bool Return (Label pc, Dummy source, BlockWithLabels<Label> currentBlock) + public override bool Return (TLabel pc, Dummy source, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.Return, CurrentSubroutine.Exit); @@ -99,12 +99,12 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { return true; } - public override bool Nop (Label pc, BlockWithLabels<Label> currentBlock) + public override bool Nop (TLabel pc, BlockWithLabels<TLabel> currentBlock) { return false; } - public override bool LoadField (Label pc, Field field, Dummy dest, Dummy obj, BlockWithLabels<Label> data) + public override bool LoadField (TLabel pc, Field field, Dummy dest, Dummy obj, BlockWithLabels<TLabel> data) { if (CurrentSubroutine.IsMethod) { var methodInfo = (IMethodInfo) CurrentSubroutine; @@ -116,7 +116,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { return false; } - public override bool StoreField (Label pc, Field field, Dummy obj, Dummy value, BlockWithLabels<Label> data) + public override bool StoreField (TLabel pc, Field field, Dummy obj, Dummy value, BlockWithLabels<TLabel> data) { if (CurrentSubroutine.IsMethod) { var methodInfo = (IMethodInfo) CurrentSubroutine; @@ -128,28 +128,28 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { return false; } - public override bool EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, BlockWithLabels<Label> data) + public override bool EndOld (TLabel pc, TLabel matchingBegin, TypeNode type, Dummy dest, Dummy source, BlockWithLabels<TLabel> data) { this.current_block.AddLabel (pc); CurrentSubroutine.AddSuccessor (this.current_block, EdgeTag.EndOld, CurrentSubroutine.Exit); return false; } - public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, BlockWithLabels<Label> data) + public bool Aggregate (TLabel pc, TLabel aggregateStart, bool canBeTargetOfBranch, BlockWithLabels<TLabel> data) { TraceAggregateSequentally (aggregateStart); return false; } #endregion - public static BlockWithLabels<Label> BuildBlocks (Label entry, SubroutineBuilder<Label> subroutineBuilder) + public static BlockWithLabels<TLabel> BuildBlocks (TLabel entry, SubroutineBuilder<TLabel> subroutineBuilder) { - var blockBuilder = new BlockBuilder<Label> (subroutineBuilder); + var blockBuilder = new BlockBuilder<TLabel> (subroutineBuilder); blockBuilder.TraceAggregateSequentally (entry); if (blockBuilder.current_block == null) return null; - SubroutineBase<Label> subroutine = blockBuilder.CurrentSubroutine; + SubroutineBase<TLabel> subroutine = blockBuilder.CurrentSubroutine; subroutine.AddSuccessor (blockBuilder.current_block, EdgeTag.FallThroughReturn, subroutine.Exit); subroutine.AddReturnBlock (blockBuilder.current_block); @@ -157,34 +157,34 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { return blockBuilder.current_block; } - private void TraceAggregateSequentally (Label currentLabel) + private void TraceAggregateSequentally (TLabel currentLabel) { do { if (this.builder.IsBlockStart (currentLabel)) this.current_block = this.builder.RecordInformationForNewBlock (currentLabel, this.current_block); - if (this.builder.CodeProvider.Decode<BlockBuilder<Label>, BlockWithLabels<Label>, bool> (currentLabel, this, this.current_block)) + if (this.builder.CodeProvider.Decode<BlockBuilder<TLabel>, BlockWithLabels<TLabel>, bool> (currentLabel, this, this.current_block)) this.current_block = null; } while (this.builder.CodeProvider.Next (currentLabel, out currentLabel)); } - public override bool DefaultVisit (Label pc, BlockWithLabels<Label> currentBlock) + public override bool DefaultVisit (TLabel pc, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); return false; } - private bool HandleConditionalBranch (Label pc, Label target, bool isTrueBranch, BlockWithLabels<Label> currentBlock) + private bool HandleConditionalBranch (TLabel pc, TLabel target, bool isTrueBranch, BlockWithLabels<TLabel> currentBlock) { currentBlock.AddLabel (pc); EdgeTag trueTag = isTrueBranch ? EdgeTag.True : EdgeTag.False; EdgeTag falseTag = isTrueBranch ? EdgeTag.False : EdgeTag.True; - AssumeBlock<Label> trueBlock = CurrentSubroutine.NewAssumeBlock (pc, trueTag); + AssumeBlock<TLabel> trueBlock = CurrentSubroutine.NewAssumeBlock (pc, trueTag); this.builder.RecordInformationSameAsOtherBlock (trueBlock, this.current_block); CurrentSubroutine.AddSuccessor (currentBlock, trueTag, trueBlock); CurrentSubroutine.AddSuccessor (trueBlock, EdgeTag.FallThrough, CurrentSubroutine.GetTargetBlock (target)); - AssumeBlock<Label> falseBlock = CurrentSubroutine.NewAssumeBlock (pc, falseTag); + AssumeBlock<TLabel> falseBlock = CurrentSubroutine.NewAssumeBlock (pc, falseTag); this.builder.RecordInformationSameAsOtherBlock (falseBlock, this.current_block); CurrentSubroutine.AddSuccessor (currentBlock, falseTag, falseBlock); this.current_block = falseBlock; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SimpleSubroutineBuilder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SimpleSubroutineBuilder.cs index 9a31945f0a7..84ef300f4e3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SimpleSubroutineBuilder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SimpleSubroutineBuilder.cs @@ -31,23 +31,23 @@ using Mono.CodeContracts.Static.ControlFlow.Blocks; using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { - class SimpleSubroutineBuilder<Label> : SubroutineBuilder<Label> { - private readonly HashSet<Label> beginOldStart = new HashSet<Label> (); - private readonly HashSet<Label> endOldStart = new HashSet<Label> (); + class SimpleSubroutineBuilder<TLabel> : SubroutineBuilder<TLabel> { + private readonly HashSet<TLabel> begin_old_start = new HashSet<TLabel> (); + private readonly HashSet<TLabel> end_old_start = new HashSet<TLabel> (); - private BlockWithLabels<Label> block_prior_to_old; - private OldValueSubroutine<Label> current_old_subroutine; - private SubroutineBase<Label> current_subroutine; + private BlockWithLabels<TLabel> block_prior_to_old; + private OldValueSubroutine<TLabel> current_old_subroutine; + private SubroutineBase<TLabel> current_subroutine; - public SimpleSubroutineBuilder (ICodeProvider<Label> codeProvider, + public SimpleSubroutineBuilder (ICodeProvider<TLabel> codeProvider, SubroutineFacade subroutineFacade, - Label entry) + TLabel entry) : base (codeProvider, subroutineFacade, entry) { Initialize (entry); } - public override SubroutineBase<Label> CurrentSubroutine + public override SubroutineBase<TLabel> CurrentSubroutine { get { @@ -57,44 +57,44 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { } } - public BlockWithLabels<Label> BuildBlocks (Label entry, SubroutineBase<Label> subroutine) + public BlockWithLabels<TLabel> BuildBlocks (TLabel entry, SubroutineBase<TLabel> subroutine) { this.current_subroutine = subroutine; return base.BuildBlocks (entry); } - public override BlockWithLabels<Label> RecordInformationForNewBlock (Label currentLabel, BlockWithLabels<Label> previousBlock) + public override BlockWithLabels<TLabel> RecordInformationForNewBlock (TLabel currentLabel, BlockWithLabels<TLabel> previousBlock) { - Label label; - if (previousBlock != null && previousBlock.TryGetLastLabel (out label) && this.endOldStart.Contains (label)) { - OldValueSubroutine<Label> oldValueSubroutine = this.current_old_subroutine; + TLabel label; + if (previousBlock != null && previousBlock.TryGetLastLabel (out label) && this.end_old_start.Contains (label)) { + OldValueSubroutine<TLabel> oldValueSubroutine = this.current_old_subroutine; oldValueSubroutine.Commit (previousBlock); this.current_old_subroutine = null; - BlockWithLabels<Label> result = base.RecordInformationForNewBlock (currentLabel, this.block_prior_to_old); + BlockWithLabels<TLabel> result = base.RecordInformationForNewBlock (currentLabel, this.block_prior_to_old); CurrentSubroutine.AddEdgeSubroutine (this.block_prior_to_old, result, oldValueSubroutine, EdgeTag.Old); return result; } - if (!this.beginOldStart.Contains (currentLabel)) + if (!this.begin_old_start.Contains (currentLabel)) return base.RecordInformationForNewBlock (currentLabel, previousBlock); - this.current_old_subroutine = new OldValueSubroutine<Label> (this.SubroutineFacade, - ((MethodContractSubroutine<Label>) this.current_subroutine).Method, + this.current_old_subroutine = new OldValueSubroutine<TLabel> (this.SubroutineFacade, + ((MethodContractSubroutine<TLabel>) this.current_subroutine).Method, this, currentLabel); this.block_prior_to_old = previousBlock; - BlockWithLabels<Label> newBlock = base.RecordInformationForNewBlock (currentLabel, null); + BlockWithLabels<TLabel> newBlock = base.RecordInformationForNewBlock (currentLabel, null); this.current_old_subroutine.RegisterBeginBlock (newBlock); return newBlock; } - public override void BeginOldHook (Label label) + public override void BeginOldHook (TLabel label) { - this.beginOldStart.Add (label); + this.begin_old_start.Add (label); } - public override void EndOldHook (Label label) + public override void EndOldHook (TLabel label) { - this.endOldStart.Add (label); + this.end_old_start.Add (label); } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineFactory.cs index a9539d96052..cff129fbcee 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineFactory.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineFactory.cs @@ -65,7 +65,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { Subroutine sub = BuildNewSubroutine (key); this.cache.Add (key, sub); if (sub != null) - sub.Initialize (); + sub.Initialize (); + return sub; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineWithHandlersBuilder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineWithHandlersBuilder.cs index 33d0882f5d2..af64fe30d48 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineWithHandlersBuilder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineWithHandlersBuilder.cs @@ -40,7 +40,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { private readonly Dictionary<Label, Queue<Handler>> subroutine_handler_end_list = new Dictionary<Label, Queue<Handler>> (); private readonly Dictionary<Label, Queue<Handler>> try_end_list = new Dictionary<Label, Queue<Handler>> (); private readonly Dictionary<Label, Stack<Handler>> try_start_list = new Dictionary<Label, Stack<Handler>> (); - private LispList<SubroutineWithHandlers<Label, Handler>> subroutine_stack; + private Sequence<SubroutineWithHandlers<Label, Handler>> subroutine_stack; public SubroutineWithHandlersBuilder (IMethodCodeProvider<Label, Handler> codeProvider, SubroutineFacade subroutineFacade, @@ -63,7 +63,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { get { return this.subroutine_stack.Head; } } - private LispList<Handler> CurrentProtectingHanlders + private Sequence<Handler> CurrentProtectingHanlders { get { return CurrentSubroutineWithHandlers.CurrentProtectingHandlers; } set { CurrentSubroutineWithHandlers.CurrentProtectingHandlers = value; } @@ -132,13 +132,13 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { public CFGBlock BuildBlocks (Label entry, SubroutineWithHandlers<Label, Handler> subroutine) { - this.subroutine_stack = LispList<SubroutineWithHandlers<Label, Handler>>.Cons (subroutine, null); + this.subroutine_stack = Sequence<SubroutineWithHandlers<Label, Handler>>.Cons (subroutine, null); return base.BuildBlocks (entry); } public override void RecordInformationSameAsOtherBlock (BlockWithLabels<Label> newBlock, BlockWithLabels<Label> currentBlock) { - LispList<Handler> list; + Sequence<Handler> list; if (!CurrentSubroutineWithHandlers.ProtectingHandlers.TryGetValue (currentBlock, out list)) return; CurrentSubroutineWithHandlers.ProtectingHandlers.Add (newBlock, list); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodContractSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodContractSubroutine.cs index 1509dd5caf8..b66473ae74b 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodContractSubroutine.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodContractSubroutine.cs @@ -30,7 +30,7 @@ using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders; namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { - abstract class MethodContractSubroutine<Label> : SubroutineBase<Label>, IMethodInfo { + abstract class MethodContractSubroutine<TLabel> : SubroutineBase<TLabel>, IMethodInfo { private readonly Method method; protected MethodContractSubroutine (SubroutineFacade subroutineFacade, @@ -41,15 +41,15 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { protected MethodContractSubroutine (SubroutineFacade subroutineFacade, Method method, - SimpleSubroutineBuilder<Label> builder, - Label startLabel) : base (subroutineFacade, startLabel, builder) + SimpleSubroutineBuilder<TLabel> builder, + TLabel startLabel) : base (subroutineFacade, startLabel, builder) { this.method = method; } - protected new SimpleSubroutineBuilder<Label> Builder + protected new SimpleSubroutineBuilder<TLabel> Builder { - get { return (SimpleSubroutineBuilder<Label>) base.Builder; } + get { return (SimpleSubroutineBuilder<TLabel>) base.Builder; } set { base.Builder = value; } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldValueSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldValueSubroutine.cs index 1bb0c410568..ff083ab0e17 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldValueSubroutine.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldValueSubroutine.cs @@ -32,12 +32,12 @@ using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { - class OldValueSubroutine<Label> : MethodContractSubroutine<Label> { - private BlockWithLabels<Label> begin_old_block; - private BlockWithLabels<Label> end_old_block; + class OldValueSubroutine<TLabel> : MethodContractSubroutine<TLabel> { + private BlockWithLabels<TLabel> begin_old_block; + private BlockWithLabels<TLabel> end_old_block; public OldValueSubroutine (SubroutineFacade subroutineFacade, Method method, - SimpleSubroutineBuilder<Label> builder, Label startLabel) + SimpleSubroutineBuilder<TLabel> builder, TLabel startLabel) : base (subroutineFacade, method, builder, startLabel) { } @@ -61,23 +61,23 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { { } - public void Commit (BlockWithLabels<Label> endOldBlock) + public void Commit (BlockWithLabels<TLabel> endOldBlock) { this.end_old_block = endOldBlock; base.Commit (); } - public void RegisterBeginBlock (BlockWithLabels<Label> beginOldBlock) + public void RegisterBeginBlock (BlockWithLabels<TLabel> beginOldBlock) { this.begin_old_block = beginOldBlock; } - public APC BeginOldAPC (LispList<Edge<CFGBlock, EdgeTag>> context) + public APC BeginOldAPC (Sequence<Edge<CFGBlock, EdgeTag>> context) { return new APC (this.begin_old_block, 0, context); } - public APC EndOldAPC (LispList<Edge<CFGBlock, EdgeTag>> context) + public APC EndOldAPC (Sequence<Edge<CFGBlock, EdgeTag>> context) { return new APC (this.end_old_block, this.end_old_block.Count - 1, context); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/RequiresSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/RequiresSubroutine.cs index 18b3e6208b4..77f81350ebb 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/RequiresSubroutine.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/RequiresSubroutine.cs @@ -32,12 +32,11 @@ using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { - sealed class RequiresSubroutine<Label> : MethodContractSubroutine<Label>, IEquatable<RequiresSubroutine<Label>> + sealed class RequiresSubroutine<TLabel> : MethodContractSubroutine<TLabel>, IEquatable<RequiresSubroutine<TLabel>> { public override SubroutineKind Kind { get { return SubroutineKind.Requires; } } public override bool IsContract { get { return true; } } - public override bool IsRequires { get { return true; } } public RequiresSubroutine(SubroutineFacade subroutineFacade, @@ -52,8 +51,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { public RequiresSubroutine(SubroutineFacade subroutineFacade, Method method, - SimpleSubroutineBuilder<Label> builder, - Label entryLabel, + SimpleSubroutineBuilder<TLabel> builder, + TLabel entryLabel, IImmutableSet<Subroutine> inheritedRequires) : base(subroutineFacade, method, builder, entryLabel) { @@ -77,7 +76,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { this.AddEdgeSubroutine(this.Entry, targetOfEntry, subroutine, EdgeTag.Inherited); } - public bool Equals(RequiresSubroutine<Label> that) + public bool Equals(RequiresSubroutine<TLabel> that) { return this.Id == that.Id; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineBase.cs index c7ad984bd45..4718ecd1dc9 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineBase.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineBase.cs @@ -43,8 +43,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { protected readonly Label StartLabel; public readonly SubroutineFacade SubroutineFacade; - private readonly Dictionary<Pair<CFGBlock, CFGBlock>, LispList<Pair<EdgeTag, Subroutine>>> edge_subroutines - = new Dictionary<Pair<CFGBlock, CFGBlock>, LispList<Pair<EdgeTag, Subroutine>>> (); + private readonly Dictionary<Pair<CFGBlock, CFGBlock>, Sequence<Pair<EdgeTag, Subroutine>>> edge_subroutines + = new Dictionary<Pair<CFGBlock, CFGBlock>, Sequence<Pair<EdgeTag, Subroutine>>> (); private readonly BlockWithLabels<Label> entry; private readonly BlockWithLabels<Label> entry_after_requires; @@ -68,9 +68,9 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { this.exception_exit = new CatchFilterEntryBlock<Label> (this, ref this.BlockIdGenerator); } - protected SubroutineBase (SubroutineFacade SubroutineFacade, + protected SubroutineBase (SubroutineFacade facade, Label startLabel, SubroutineBuilder<Label> builder) - : this (SubroutineFacade) + : this (facade) { this.StartLabel = startLabel; Builder = builder; @@ -162,9 +162,9 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { #endregion #region IEdgeSubroutineAdaptor Members - public LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock from, CFGBlock to, LispList<Edge<CFGBlock, EdgeTag>> context) + public Sequence<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock from, CFGBlock to, Sequence<Edge<CFGBlock, EdgeTag>> context) { - LispList<Pair<EdgeTag, Subroutine>> list; + Sequence<Pair<EdgeTag, Subroutine>> list; this.edge_subroutines.TryGetValue (new Pair<CFGBlock, CFGBlock> (from, to), out list); if (list != null && context != null) list = list.Where (FilterRecursiveContracts (to, context)); @@ -268,7 +268,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return false; } - LispList<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (onlyOne, point.Block, point.SubroutineContext); + Sequence<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (onlyOne, point.Block, point.SubroutineContext); if (list.IsEmpty ()) { ifFound = APC.ForEnd (onlyOne, point.SubroutineContext); return true; @@ -284,8 +284,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { { Edge<CFGBlock, EdgeTag> head = point.SubroutineContext.Head; bool isExceptionHandlerEdge; - LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail; - LispList<Pair<EdgeTag, Subroutine>> flist = EdgeSubroutinesOuterToInner (head.From, head.To, out isExceptionHandlerEdge, tail); + Sequence<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail; + Sequence<Pair<EdgeTag, Subroutine>> flist = EdgeSubroutinesOuterToInner (head.From, head.To, out isExceptionHandlerEdge, tail); while (flist.Head.Value != this) flist = flist.Tail; if (flist.Tail.IsEmpty ()) { @@ -307,8 +307,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { private APC ComputeSubroutineContinuation (APC point) { Edge<CFGBlock, EdgeTag> head = point.SubroutineContext.Head; - LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail; - LispList<Pair<EdgeTag, Subroutine>> outerToInner = EdgeSubroutinesOuterToInner (head.From, head.To, tail); + Sequence<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail; + Sequence<Pair<EdgeTag, Subroutine>> outerToInner = EdgeSubroutinesOuterToInner (head.From, head.To, tail); if (outerToInner.Head.Value == this) return new APC (head.To, 0, tail); @@ -415,12 +415,11 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { if (subroutine == null) return; - var key = new Pair<CFGBlock, CFGBlock> (from, to); - LispList<Pair<EdgeTag, Subroutine>> list; - var item = new Pair<EdgeTag, Subroutine> (tag, subroutine); + var key = Pair.From (from, to); + Sequence<Pair<EdgeTag, Subroutine>> list; this.edge_subroutines.TryGetValue (key, out list); - this.edge_subroutines [key] = list.Cons (item); + this.edge_subroutines[key] = list.Cons (Pair.From (tag, subroutine)); } public override IEnumerable<APC> Successors (APC pc) @@ -446,7 +445,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { } } else { foreach (CFGBlock block in pc.Block.Subroutine.PredecessorBlocks (pc.Block)) { - LispList<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (block, pc.Block, pc.SubroutineContext); + Sequence<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (block, pc.Block, pc.SubroutineContext); if (diffs.IsEmpty ()) yield return APC.ForEnd (block, pc.SubroutineContext); else { @@ -461,10 +460,10 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { private IEnumerable<APC> ComputeSubroutinePreContinuation (APC point) { Edge<CFGBlock, EdgeTag> edge = point.SubroutineContext.Head; - LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail; + Sequence<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail; bool isHandlerEdge; - LispList<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (edge.From, edge.To, out isHandlerEdge, tail); + Sequence<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (edge.From, edge.To, out isHandlerEdge, tail); while (diffs.Head.Value != this) diffs = diffs.Tail; @@ -483,7 +482,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { public override APC ComputeTargetFinallyContext (APC pc, CFGBlock succ) { - LispList<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (pc.Block, succ, pc.SubroutineContext); + Sequence<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (pc.Block, succ, pc.SubroutineContext); if (list.IsEmpty ()) return new APC (succ, 0, pc.SubroutineContext); @@ -491,13 +490,13 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return new APC (last.Value.Entry, 0, pc.SubroutineContext.Cons (new Edge<CFGBlock, EdgeTag> (pc.Block, succ, last.Key))); } - private LispList<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock from, CFGBlock succ, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext) + private Sequence<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock from, CFGBlock succ, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext) { bool isExceptionHandlerEdge; return EdgeSubroutinesOuterToInner (from, succ, out isExceptionHandlerEdge, subroutineContext); } - public override LispList<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock from, CFGBlock succ, out bool isExceptionHandlerEdge, LispList<Edge<CFGBlock, EdgeTag>> context) + public override Sequence<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock from, CFGBlock succ, out bool isExceptionHandlerEdge, Sequence<Edge<CFGBlock, EdgeTag>> context) { if (from.Subroutine != this) return from.Subroutine.EdgeSubroutinesOuterToInner (from, succ, out isExceptionHandlerEdge, context); @@ -506,14 +505,14 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return GetOrdinaryEdgeSubroutines (from, succ, context); } - public override LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock from, CFGBlock to, LispList<Edge<CFGBlock, EdgeTag>> context) + public override Sequence<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock from, CFGBlock to, Sequence<Edge<CFGBlock, EdgeTag>> context) { IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider; var apc = new APC (to, 0, context); DecoratorHelper.Push (this); try { - LispList<Pair<EdgeTag, Subroutine>> list = DecoratorHelper.Dispatch<IEdgeSubroutineAdaptor> (this).GetOrdinaryEdgeSubroutinesInternal (from, to, context); + Sequence<Pair<EdgeTag, Subroutine>> list = DecoratorHelper.Dispatch<IEdgeSubroutineAdaptor> (this).GetOrdinaryEdgeSubroutinesInternal (from, to, context); if (apc.InsideContract) { if (context != null && !list.IsEmpty ()) { Method calledMethod; @@ -591,9 +590,9 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { } } - private LispList<Pair<EdgeTag, Subroutine>> InsertInvariant (CFGBlock from, LispList<Pair<EdgeTag, Subroutine>> list, + private Sequence<Pair<EdgeTag, Subroutine>> InsertInvariant (CFGBlock from, Sequence<Pair<EdgeTag, Subroutine>> list, Method calledMethod, ref TypeNode type, - LispList<Edge<CFGBlock, EdgeTag>> context) + Sequence<Edge<CFGBlock, EdgeTag>> context) { IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider; @@ -617,18 +616,18 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return list; } - private bool WithinConstructor (CFGBlock current, LispList<Edge<CFGBlock, EdgeTag>> context) + private bool WithinConstructor (CFGBlock current, Sequence<Edge<CFGBlock, EdgeTag>> context) { return new APC (current, 0, context).InsideConstructor; } - private LispList<Pair<EdgeTag, Subroutine>> SpecializedEnsures (LispList<Pair<EdgeTag, Subroutine>> subroutines, + private Sequence<Pair<EdgeTag, Subroutine>> SpecializedEnsures (Sequence<Pair<EdgeTag, Subroutine>> subroutines, Subroutine toReplace, Subroutine specializedEnsures) { return subroutines.Select (pair => new Pair<EdgeTag, Subroutine> (pair.Key, pair.Value == toReplace ? specializedEnsures : pair.Value)); } - private static Predicate<Pair<EdgeTag, Subroutine>> FilterRecursiveContracts (CFGBlock from, LispList<Edge<CFGBlock, EdgeTag>> context) + private static Predicate<Pair<EdgeTag, Subroutine>> FilterRecursiveContracts (CFGBlock from, Sequence<Edge<CFGBlock, EdgeTag>> context) { return (candidate) => { Subroutine sub = candidate.Value; @@ -701,11 +700,11 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { public override void Print (TextWriter tw, ILPrinter<APC> printer, Func<CFGBlock, - IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context, - HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> printed) + IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context, + HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> printed) { - var element = new Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>> (this, context); + var element = new Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>> (this, context); if (printed.Contains (element)) return; printed.Add (element); @@ -740,7 +739,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { if (this.edge_info.IsBackEdge (block, Dummy.Value, edge.Value)) tw.Write (" BE"); - for (LispList<Pair<EdgeTag, Subroutine>> list = GetOrdinaryEdgeSubroutines (block, edge.Value, context); list != null; list = list.Tail) { + for (Sequence<Pair<EdgeTag, Subroutine>> list = GetOrdinaryEdgeSubroutines (block, edge.Value, context); list != null; list = list.Tail) { subs.Add (list.Head.Value); tw.Write (" SR{0}({1})", list.Head.Value.Id, list.Head.Key); } @@ -752,9 +751,9 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { } protected virtual void PrintReferencedSubroutines (TextWriter tw, HashSet<Subroutine> subs, ILPrinter<APC> printer, - Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context, - HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> printed) + Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context, + HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> printed) { foreach (Subroutine subroutine in subs) { if (contextLookup == null) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineFacade.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineFacade.cs index 364a305841e..2a958a6b584 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineFacade.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineFacade.cs @@ -28,6 +28,8 @@ using System; using System.Collections.Generic; +using System.Linq; + using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.ControlFlow.Blocks; @@ -65,12 +67,12 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { } #endregion - public Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data) - where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result> + public TResult ForwardDecode<TData, TResult, TVisitor> (APC pc, TVisitor visitor, TData data) + where TVisitor : IILVisitor<APC, Dummy, Dummy, TData, TResult> { var block = pc.Block as BlockBase; if (block != null) - return block.ForwardDecode<Data, Result, Visitor> (pc, visitor, data); + return block.ForwardDecode<TData, TResult, TVisitor> (pc, visitor, data); return visitor.Nop (pc, data); } @@ -107,13 +109,11 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return new ControlFlowGraph (this.MetaDataProvider.AccessMethodBody (method, this, Dummy.Value), this); } - public void AddReads (Method method, Field field) { throw new NotImplementedException (); } - public IEnumerable<Method> GetAffectedGetters (Field field) { //todo: implement this @@ -123,8 +123,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { public IEnumerable<Field> GetModifies (Method method) { - //todo: implement this - return new Field[0]; + //todo: implement this + return Enumerable.Empty<Field> (); } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineWithHandlers.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineWithHandlers.cs index d41bd349693..ca1f9aa18f7 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineWithHandlers.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineWithHandlers.cs @@ -42,8 +42,8 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { public readonly Dictionary<Handler, Subroutine> FaultFinallySubroutines = new Dictionary<Handler, Subroutine> (); protected readonly Dictionary<Handler, BlockWithLabels<Label>> FilterCodeBlocks = new Dictionary<Handler, BlockWithLabels<Label>> (); - public readonly Dictionary<CFGBlock, LispList<Handler>> ProtectingHandlers = new Dictionary<CFGBlock, LispList<Handler>> (); - public LispList<Handler> CurrentProtectingHandlers = LispList<Handler>.Empty; + public readonly Dictionary<CFGBlock, Sequence<Handler>> ProtectingHandlers = new Dictionary<CFGBlock, Sequence<Handler>> (); + public Sequence<Handler> CurrentProtectingHandlers = Sequence<Handler>.Empty; protected SubroutineWithHandlers (SubroutineFacade subroutineFacade) : base (subroutineFacade) @@ -67,9 +67,9 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return CodeProvider.IsFaultHandler (handler); } - private LispList<Handler> ProtectingHandlerList (CFGBlock block) + private Sequence<Handler> ProtectingHandlerList (CFGBlock block) { - LispList<Handler> list; + Sequence<Handler> list; this.ProtectingHandlers.TryGetValue (block, out list); return list; } @@ -95,17 +95,17 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { return this.FaultFinallySubroutines.Values.Concat (base.UsedSubroutines (alreadySeen)); } - public override LispList<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock current, CFGBlock succ, - out bool isExceptionHandlerEdge, LispList<Edge<CFGBlock, EdgeTag>> context) + public override Sequence<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock current, CFGBlock succ, + out bool isExceptionHandlerEdge, Sequence<Edge<CFGBlock, EdgeTag>> context) { if (current.Subroutine != this) return current.Subroutine.EdgeSubroutinesOuterToInner (current, succ, out isExceptionHandlerEdge, context); - LispList<Handler> l1 = ProtectingHandlerList (current); - LispList<Handler> l2 = ProtectingHandlerList (succ); + Sequence<Handler> l1 = ProtectingHandlerList (current); + Sequence<Handler> l2 = ProtectingHandlerList (succ); isExceptionHandlerEdge = IsCatchFilterHeader (succ); - LispList<Pair<EdgeTag, Subroutine>> result = GetOrdinaryEdgeSubroutines (current, succ, context); + Sequence<Pair<EdgeTag, Subroutine>> result = GetOrdinaryEdgeSubroutines (current, succ, context); while (l1 != l2) { if (l1.Length () >= l2.Length ()) { @@ -142,7 +142,7 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { Data data, IHandlerFilter<Data> handlerPredicate) { IHandlerFilter<Data> handleFilter = handlerPredicate; - LispList<Handler> protectingHandlers = ProtectingHandlerList (block); + Sequence<Handler> protectingHandlers = ProtectingHandlerList (block); if (innerSubroutine != null && innerSubroutine.IsFaultFinally) { for (; protectingHandlers != null; protectingHandlers = protectingHandlers.Tail) { if (IsFaultOrFinally (protectingHandlers.Head) && this.FaultFinallySubroutines [protectingHandlers.Head] == innerSubroutine) { @@ -175,9 +175,9 @@ namespace Mono.CodeContracts.Static.ControlFlow.Subroutines { } protected override void PrintReferencedSubroutines (TextWriter tw, HashSet<Subroutine> subs, ILPrinter<APC> printer, - Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context, - HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> printed) + Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context, + HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> printed) { foreach (Subroutine sub in this.FaultFinallySubroutines.Values) { if (contextLookup == null) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs index c3233569f45..76b58999e4a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs @@ -38,9 +38,9 @@ namespace Mono.CodeContracts.Static.ControlFlow { public readonly CFGBlock Block; public readonly int Index; - public readonly LispList<Edge<CFGBlock, EdgeTag>> SubroutineContext; + public readonly Sequence<Edge<CFGBlock, EdgeTag>> SubroutineContext; - public APC (CFGBlock block, int index, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext) + public APC (CFGBlock block, int index, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext) { this.Block = block; this.Index = index; @@ -65,7 +65,7 @@ namespace Mono.CodeContracts.Static.ControlFlow { { get { - LispList<Edge<CFGBlock, EdgeTag>> ctx = this.SubroutineContext; + Sequence<Edge<CFGBlock, EdgeTag>> ctx = this.SubroutineContext; CFGBlock block = this.Block; while (block != null) { Subroutine subroutine = block.Subroutine; @@ -195,7 +195,7 @@ namespace Mono.CodeContracts.Static.ControlFlow { { if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null) return false; - for (LispList<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext; list != null; list = list.Tail) { + for (Sequence<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext; list != null; list = list.Tail) { if (list.Head.Tag == EdgeTag.Entry) return false; if (list.Head.Tag.Is (EdgeTag.BeforeMask)) { @@ -222,12 +222,12 @@ namespace Mono.CodeContracts.Static.ControlFlow { return this; } - public static APC ForEnd (CFGBlock block, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext) + public static APC ForEnd (CFGBlock block, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext) { return new APC (block, block.Count, subroutineContext); } - public static APC ForStart (CFGBlock block, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext) + public static APC ForStart (CFGBlock block, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext) { return new APC (block, 0, subroutineContext); } @@ -239,7 +239,7 @@ namespace Mono.CodeContracts.Static.ControlFlow { public bool TryGetContainingMethod (out Method method) { - LispList<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext; + Sequence<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext; CFGBlock block = this.Block; while (block != null) { var mi = block.Subroutine as IMethodInfo; @@ -258,7 +258,7 @@ namespace Mono.CodeContracts.Static.ControlFlow { return false; } - public static void ToString (StringBuilder sb, LispList<Edge<CFGBlock, EdgeTag>> context) + static void ToString (StringBuilder sb, Sequence<Edge<CFGBlock, EdgeTag>> context) { bool wasFirst = false; for (; context != null; context = context.Tail) { diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs index bfe4611fc74..adc421f34c4 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs @@ -55,32 +55,29 @@ namespace Mono.CodeContracts.Static.ControlFlow { get { return this; } } - public Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data) - where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result> + public TResult ForwardDecode<TData, TResult, TVisitor> (APC pc, TVisitor visitor, TData data) + where TVisitor : IILVisitor<APC, Dummy, Dummy, TData, TResult> { - return this.subroutine_facade.ForwardDecode<Data, Result, RemoveBranchDelegator<Data, Result, Visitor>> - (pc, new RemoveBranchDelegator<Data, Result, Visitor> (visitor, this.meta_data_provider), data); + return this.subroutine_facade.ForwardDecode<TData, TResult, RemoveBranchDelegator<TData, TResult, TVisitor>> + (pc, new RemoveBranchDelegator<TData, TResult, TVisitor> (visitor, this.meta_data_provider), data); } - public bool IsUnreachable (APC pc) + public bool IsUnreachable (APC pc) { return false; } - public Dummy EdgeData (APC @from, APC to) + public Dummy EdgeData (APC from, APC to) { return Dummy.Value; } #endregion - #region IMethodContextProvider Members public IMethodContext MethodContext { get { return this; } } - #endregion - #region IMethodContext Members public Method CurrentMethod { get { return this.cfg.CFGMethod; } @@ -100,6 +97,5 @@ namespace Mono.CodeContracts.Static.ControlFlow { { return this.subroutine_facade.GetAffectedGetters (field); } - #endregion } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/CFGBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/CFGBlock.cs index 73d06bad9ac..bbab18424f7 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/CFGBlock.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/CFGBlock.cs @@ -74,7 +74,7 @@ namespace Mono.CodeContracts.Static.ControlFlow { return APCs (null); } - private IEnumerable<APC> APCs (LispList<Edge<CFGBlock, EdgeTag>> context) + private IEnumerable<APC> APCs (Sequence<Edge<CFGBlock, EdgeTag>> context) { for (int i = 0; i < Count; i++) yield return new APC (this, i, context); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ContractFilteredCFG.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ContractFilteredCFG.cs index 2f3d130699e..5d90de432e3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ContractFilteredCFG.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ContractFilteredCFG.cs @@ -34,130 +34,137 @@ using Mono.CodeContracts.Static.DataStructures; using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.ControlFlow { - class ContractFilteredCFG : ICFG, IEdgeSubroutineAdaptor { - private readonly ICFG underlying; - - public ContractFilteredCFG (ICFG cfg) - { - this.underlying = cfg; - } - - #region ICFG Members - public APC Entry - { - get { return this.underlying.Entry; } - } - - public APC EntryAfterRequires - { - get { return this.underlying.EntryAfterRequires; } - } - - public APC NormalExit - { - get { return this.underlying.NormalExit; } - } - - public APC ExceptionExit - { - get { return this.underlying.ExceptionExit; } - } - - public Subroutine Subroutine - { - get { return this.underlying.Subroutine; } - } - - public APC Next (APC pc) - { - return this.underlying.Next (pc); - } - - public bool HasSingleSuccessor (APC pc, out APC ifFound) - { - DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); - try { - return this.underlying.HasSingleSuccessor (pc, out ifFound); - } finally { - DecoratorHelper.Pop (); - } - } - - public IEnumerable<APC> Successors (APC pc) - { - DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); - try { - return this.underlying.Successors (pc); - } finally { - DecoratorHelper.Pop (); - } - } - - public bool HasSinglePredecessor (APC pc, out APC ifFound) - { - DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); - try { - return this.underlying.HasSinglePredecessor (pc, out ifFound); - } finally { - DecoratorHelper.Pop (); - } - } - - public IEnumerable<APC> Predecessors (APC pc) - { - DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); - try { - return this.underlying.Predecessors (pc); - } finally { - DecoratorHelper.Pop (); - } - } - - public bool IsJoinPoint (APC pc) - { - return this.underlying.IsJoinPoint (pc); - } - - public bool IsSplitPoint (APC pc) - { - return this.underlying.IsSplitPoint (pc); - } - - public bool IsBlockStart (APC pc) - { - return this.underlying.IsBlockStart (pc); - } - - public bool IsBlockEnd (APC pc) - { - return this.underlying.IsBlockEnd (pc); - } - - public IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder (IMetaDataProvider metaDataProvider) - { - return this.underlying.GetDecoder (metaDataProvider); - } - - public void Print (TextWriter tw, ILPrinter<APC> printer, - Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context) - { - DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); - try { - this.underlying.Print (tw, printer, contextLookup, context); - } finally { - DecoratorHelper.Pop (); - } - } - #endregion - - #region Implementation of IEdgeSubroutineAdaptor - LispList<Pair<EdgeTag, Subroutine>> IEdgeSubroutineAdaptor.GetOrdinaryEdgeSubroutinesInternal (CFGBlock @from, CFGBlock to, - LispList<Edge<CFGBlock, EdgeTag>> context) - { - return DecoratorHelper.Inner<IEdgeSubroutineAdaptor> (this) - .GetOrdinaryEdgeSubroutinesInternal (from, to, context).Where ((pair) => !pair.Value.IsContract && !pair.Value.IsOldValue); - } - #endregion - } + class ContractFilteredCFG : ICFG, IEdgeSubroutineAdaptor { + readonly ICFG underlying; + + public ContractFilteredCFG (ICFG cfg) + { + this.underlying = cfg; + } + + #region ICFG Members + + public APC Entry { get { return this.underlying.Entry; } } + + public APC EntryAfterRequires { get { return this.underlying.EntryAfterRequires; } } + + public APC NormalExit { get { return this.underlying.NormalExit; } } + + public APC ExceptionExit { get { return this.underlying.ExceptionExit; } } + + public Subroutine Subroutine { get { return this.underlying.Subroutine; } } + + public APC Next (APC pc) + { + return this.underlying.Next (pc); + } + + public bool HasSingleSuccessor (APC pc, out APC ifFound) + { + DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); + try { + return this.underlying.HasSingleSuccessor (pc, out ifFound); + } + finally { + DecoratorHelper.Pop (); + } + } + + public IEnumerable<APC> Successors (APC pc) + { + DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); + try { + return this.underlying.Successors (pc); + } + finally { + DecoratorHelper.Pop (); + } + } + + public bool HasSinglePredecessor (APC pc, out APC ifFound) + { + DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); + try { + return this.underlying.HasSinglePredecessor (pc, out ifFound); + } + finally { + DecoratorHelper.Pop (); + } + } + + public IEnumerable<APC> Predecessors (APC pc) + { + DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); + try { + return this.underlying.Predecessors (pc); + } + finally { + DecoratorHelper.Pop (); + } + } + + public bool IsJoinPoint (APC pc) + { + return this.underlying.IsJoinPoint (pc); + } + + public bool IsSplitPoint (APC pc) + { + return this.underlying.IsSplitPoint (pc); + } + + public bool IsBlockStart (APC pc) + { + return this.underlying.IsBlockStart (pc); + } + + public bool IsBlockEnd (APC pc) + { + return this.underlying.IsBlockEnd (pc); + } + + public APC Post (APC pc) + { + return this.underlying.Post (pc); + } + + public IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder ( + IMetaDataProvider metaDataProvider) + { + return this.underlying.GetDecoder (metaDataProvider); + } + + public void Print (TextWriter tw, ILPrinter<APC> printer, + Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context) + { + DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this); + try { + this.underlying.Print (tw, printer, contextLookup, context); + } + finally { + DecoratorHelper.Pop (); + } + } + + public bool IsForwardBackEdge (APC @from, APC to) + { + return underlying.IsForwardBackEdge (from, to); + } + + #endregion + + #region Implementation of IEdgeSubroutineAdaptor + + Sequence<Pair<EdgeTag, Subroutine>> IEdgeSubroutineAdaptor.GetOrdinaryEdgeSubroutinesInternal ( + CFGBlock @from, CFGBlock to, + Sequence<Edge<CFGBlock, EdgeTag>> context) + { + return DecoratorHelper.Inner<IEdgeSubroutineAdaptor> (this) + .GetOrdinaryEdgeSubroutinesInternal (from, to, context).Where ( + (pair) => !pair.Value.IsContract && !pair.Value.IsOldValue); + } + + #endregion + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs index 19dda217820..7dd3c7f40b1 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.IO; + using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.Analysis; using Mono.CodeContracts.Static.ControlFlow.Subroutines; @@ -36,159 +37,163 @@ using Mono.CodeContracts.Static.DataStructures; using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.ControlFlow { - class ControlFlowGraph : ICFG { - private readonly object method_repository; - private readonly Subroutine method_subroutine; - - public ControlFlowGraph (Subroutine subroutine, object methodRepository) - { - this.method_subroutine = subroutine; - this.method_repository = methodRepository; - } - - private CFGBlock EntryBlock - { - get { return this.method_subroutine.Entry; } - } - - private CFGBlock ExitBlock - { - get { return this.method_subroutine.Exit; } - } - - private CFGBlock ExceptionExitBlock - { - get { return this.method_subroutine.ExceptionExit; } - } - - public Method CFGMethod - { - get - { - var methodInfo = this.method_subroutine as IMethodInfo; - if (methodInfo != null) - return methodInfo.Method; - throw new InvalidOperationException ("CFG has bad subroutine that is not a method"); - } - } - - #region ICFG Members - public APC Entry - { - get { return new APC (EntryBlock, 0, null); } - } - - public APC EntryAfterRequires - { - get { return new APC (this.method_subroutine.EntryAfterRequires, 0, null); } - } - - public APC NormalExit - { - get { return new APC (ExitBlock, 0, null); } - } - - public APC ExceptionExit - { - get { return new APC (ExceptionExitBlock, 0, null); } - } - - public Subroutine Subroutine - { - get { return this.method_subroutine; } - } - - public APC Next (APC pc) - { - APC next; - - if (HasSingleSuccessor (pc, out next)) - return next; - - return pc; - } - - public bool HasSingleSuccessor (APC pc, out APC ifFound) - { - return pc.Block.Subroutine.HasSingleSuccessor (pc, out ifFound); - } - - public IEnumerable<APC> Successors (APC pc) - { - return pc.Block.Subroutine.Successors (pc); - } - - public bool HasSinglePredecessor (APC pc, out APC ifFound) - { - return pc.Block.Subroutine.HasSinglePredecessor (pc, out ifFound); - } - - public IEnumerable<APC> Predecessors (APC pc) - { - return pc.Block.Subroutine.Predecessors (pc); - } - - public bool IsJoinPoint (APC pc) - { - if (pc.Index != 0) - return false; - - return IsJoinPoint (pc.Block); - } - - public bool IsSplitPoint (APC pc) - { - if (pc.Index != pc.Block.Count) - return false; - - return IsSplitPoint (pc.Block); - } - - public bool IsBlockStart (APC pc) - { - return pc.Index == 0; - } - - public bool IsBlockEnd (APC pc) - { - return pc.Index == pc.Block.Count; - } - - public IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder (IMetaDataProvider metaDataProvider) - { - var methodRepository = this.method_repository as SubroutineFacade; - return new APCDecoder (this, metaDataProvider, methodRepository); - } - - public void Print (TextWriter tw, ILPrinter<APC> printer, - Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context) - { - var set = new HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> (); - this.method_subroutine.Print (tw, printer, contextLookup, context, set); - } - #endregion - - private bool IsJoinPoint (CFGBlock block) - { - return block.Subroutine.IsJoinPoint (block); - } - - private bool IsSplitPoint (CFGBlock block) - { - return block.Subroutine.IsSplitPoint (block); - } - - public IGraph<APC, Dummy> AsForwardGraph () - { - return new GraphWrapper<APC, Dummy> (new APC[0], (pc) => SuccessorsEdges (pc)); - } - - private IEnumerable<Pair<Dummy, APC>> SuccessorsEdges (APC pc) - { - APC last = pc.LastInBlock (); - foreach (APC succ in Successors (last)) - yield return new Pair<Dummy, APC> (Dummy.Value, succ); - } - } -} + class ControlFlowGraph : ICFG { + readonly SubroutineFacade method_repository; + readonly Subroutine method_subroutine; + + public ControlFlowGraph (Subroutine subroutine, SubroutineFacade methodRepository) + { + this.method_subroutine = subroutine; + this.method_repository = methodRepository; + } + + CFGBlock EntryBlock { get { return this.method_subroutine.Entry; } } + + CFGBlock ExitBlock { get { return this.method_subroutine.Exit; } } + + CFGBlock ExceptionExitBlock { get { return this.method_subroutine.ExceptionExit; } } + + public Method CFGMethod + { + get + { + var methodInfo = this.method_subroutine as IMethodInfo; + if (methodInfo != null) + return methodInfo.Method; + throw new InvalidOperationException ("CFG has bad subroutine that is not a method"); + } + } + + #region ICFG Members + + public APC Entry { get { return new APC (this.EntryBlock, 0, null); } } + + public APC EntryAfterRequires { get { return new APC (this.method_subroutine.EntryAfterRequires, 0, null); } } + + public APC NormalExit { get { return new APC (this.ExitBlock, 0, null); } } + + public APC ExceptionExit { get { return new APC (this.ExceptionExitBlock, 0, null); } } + + public Subroutine Subroutine { get { return this.method_subroutine; } } + + public APC Next (APC pc) + { + APC next; + + if (this.HasSingleSuccessor (pc, out next)) + return next; + + return pc; + } + + public bool HasSingleSuccessor (APC pc, out APC ifFound) + { + return pc.Block.Subroutine.HasSingleSuccessor (pc, out ifFound); + } + + public IEnumerable<APC> Successors (APC pc) + { + return pc.Block.Subroutine.Successors (pc); + } + + public bool HasSinglePredecessor (APC pc, out APC ifFound) + { + return pc.Block.Subroutine.HasSinglePredecessor (pc, out ifFound); + } + + public IEnumerable<APC> Predecessors (APC pc) + { + return pc.Block.Subroutine.Predecessors (pc); + } + + public bool IsJoinPoint (APC pc) + { + if (pc.Index != 0) + return false; + + return IsJoinPoint (pc.Block); + } + + public bool IsSplitPoint (APC pc) + { + if (pc.Index != pc.Block.Count) + return false; + + return IsSplitPoint (pc.Block); + } + + public bool IsBlockStart (APC pc) + { + return pc.Index == 0; + } + + public bool IsBlockEnd (APC pc) + { + return pc.Index == pc.Block.Count; + } + + public IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder ( + IMetaDataProvider metaDataProvider) + { + return new APCDecoder (this, metaDataProvider, this.method_repository); + } + + public void Print (TextWriter tw, ILPrinter<APC> printer, + Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context) + { + var set = new HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> (); + this.method_subroutine.Print (tw, printer, contextLookup, context, set); + } + + public bool IsForwardBackEdge (APC @from, APC to) + { + if (to.Index != 0) + return false; + + return this.IsForwardBackEdgeHelper (from, to); + } + + public APC Post (APC pc) + { + APC next; + return this.HasSingleSuccessor (pc, out next) ? next : pc; + } + + #endregion + + bool IsForwardBackEdgeHelper (APC @from, APC to) + { + if (to.Block.Subroutine.EdgeInfo.IsBackEdge (from.Block, Dummy.Value, to.Block)) + return true; + + if (from.SubroutineContext.IsEmpty () || from.SubroutineContext.Tail != to.SubroutineContext) + return false; + + Edge<CFGBlock, EdgeTag> edge = @from.SubroutineContext.Head; + return edge.To.Subroutine.EdgeInfo.IsBackEdge (edge.From, Dummy.Value, edge.To); + } + + bool IsJoinPoint (CFGBlock block) + { + return block.Subroutine.IsJoinPoint (block); + } + + bool IsSplitPoint (CFGBlock block) + { + return block.Subroutine.IsSplitPoint (block); + } + + public IGraph<APC, Dummy> AsForwardGraph () + { + return new GraphWrapper<APC, Dummy> (new APC[0], (pc) => this.SuccessorsEdges (pc)); + } + + IEnumerable<Pair<Dummy, APC>> SuccessorsEdges (APC pc) + { + APC last = pc.LastInBlock (); + foreach (APC succ in this.Successors (last)) + yield return new Pair<Dummy, APC> (Dummy.Value, succ); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs index 62e10488c03..14b7adb9c99 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs @@ -31,34 +31,34 @@ using System; namespace Mono.CodeContracts.Static.ControlFlow { [Flags] enum EdgeTag : uint { - None = 0, + None = 0, FallThroughReturn = 1, - Branch = 1 << 1, - Return = 1 << 2, - EndSubroutine = 1 << 3, - True = 1 << 4, - False = 1 << 5, - FallThrough = 1 << 6, - Entry = 1 << 7, - AfterNewObj = 1 << 8 | AfterMask, - AfterCall = 1 << 9 | AfterMask, - Exit = 1 << 10, - Finally = 1 << 11, - Inherited = 1 << 12 | InheritedMask, - BeforeCall = 1 << 13 | BeforeMask, - BeforeNewObj = 1 << 14 | BeforeMask, - Requires = 1 << 15, - Assume = 1 << 16, - Assert = 1 << 17, - Invariant = 1 << 18, - OldManifest = 1 << 19 | OldMask, - Old = 1 << 20 | OldMask, - EndOld = 1 << 21, + Branch = 1 << 1, + Return = 1 << 2, + EndSubroutine = 1 << 3, + True = 1 << 4, + False = 1 << 5, + FallThrough = 1 << 6, + Entry = 1 << 7, + AfterNewObj = 1 << 8 | AfterMask, + AfterCall = 1 << 9 | AfterMask, + Exit = 1 << 10, + Finally = 1 << 11, + Inherited = 1 << 12 | InheritedMask, + BeforeCall = 1 << 13 | BeforeMask, + BeforeNewObj = 1 << 14 | BeforeMask, + Requires = 1 << 15, + Assume = 1 << 16, + Assert = 1 << 17, + Invariant = 1 << 18, + OldManifest = 1 << 19 | OldMask, + Old = 1 << 20 | OldMask, + EndOld = 1 << 21, - BeforeMask = 1 << 22, - AfterMask = 1 << 23, - InheritedMask = 1 << 24, - ExtraMask = 1 << 25, - OldMask = 1 << 26, + BeforeMask = 1 << 22, + AfterMask = 1 << 23, + InheritedMask = 1 << 24, + ExtraMask = 1 << 25, + OldMask = 1 << 26, } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs index 89869ce9bc9..e3e648d9189 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs @@ -58,7 +58,10 @@ namespace Mono.CodeContracts.Static.ControlFlow { IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder (IMetaDataProvider metaDataProvider); void Print (TextWriter tw, ILPrinter<APC> printer, - Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context); + Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context); + + bool IsForwardBackEdge (APC @from, APC to); + APC Post (APC pc); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs index 1b333ecac29..6eeb7817125 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs @@ -30,6 +30,6 @@ using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.ControlFlow { interface IEdgeSubroutineAdaptor { - LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock @from, CFGBlock to, LispList<Edge<CFGBlock, EdgeTag>> context); + Sequence<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock @from, CFGBlock to, Sequence<Edge<CFGBlock, EdgeTag>> context); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs index b4351223491..98e537c92a0 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs @@ -33,9 +33,9 @@ using Mono.CodeContracts.Static.Analysis; using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.ControlFlow { - abstract class Subroutine : ITypedProperties, IEquatable<Subroutine> { + abstract class Subroutine : IPropertyCollection, IEquatable<Subroutine> { private static int _subroutineIdGenerator; - private readonly TypedProperties properties = new TypedProperties (); + private readonly PropertyCollection properties = new PropertyCollection (); private readonly int subroutine_id = _subroutineIdGenerator++; public virtual SubroutineKind Kind @@ -110,14 +110,14 @@ namespace Mono.CodeContracts.Static.ControlFlow { public abstract int StackDelta { get; } - #region ITypedProperties Members + #region IPropertyCollection Members public bool TryGetValue<T> (TypedKey key, out T value) { return this.properties.TryGetValue (key, out value); } #endregion - #region Implementation of ITypedProperties + #region Implementation of IPropertyCollection public bool Contains (TypedKey key) { return this.properties.Contains (key); @@ -158,8 +158,8 @@ namespace Mono.CodeContracts.Static.ControlFlow { public abstract bool IsCatchFilterHeader (CFGBlock block); public abstract APC ComputeTargetFinallyContext (APC pc, CFGBlock succ); - public abstract LispList<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock current, CFGBlock succ, out bool isExceptionHandlerEdge, LispList<Edge<CFGBlock, EdgeTag>> context); - public abstract LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock current, CFGBlock succ, LispList<Edge<CFGBlock, EdgeTag>> context); + public abstract Sequence<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock current, CFGBlock succ, out bool isExceptionHandlerEdge, Sequence<Edge<CFGBlock, EdgeTag>> context); + public abstract Sequence<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock current, CFGBlock succ, Sequence<Edge<CFGBlock, EdgeTag>> context); public abstract void Initialize (); public abstract IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen); @@ -172,9 +172,9 @@ namespace Mono.CodeContracts.Static.ControlFlow { Data data, IHandlerFilter<Data> handlerPredicate); public abstract void Print (TextWriter tw, ILPrinter<APC> printer, - Func<CFGBlock, IEnumerable<LispList<Edge<CFGBlock, EdgeTag>>>> contextLookup, - LispList<Edge<CFGBlock, EdgeTag>> context, - HashSet<Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>>> set); + Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup, + Sequence<Edge<CFGBlock, EdgeTag>> context, + HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> set); #region Implementation of IEquatable<Subroutine> public bool Equals (Subroutine other) diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs index ec6c23d4544..a6fdfc53ae9 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs @@ -35,27 +35,27 @@ using Mono.CodeContracts.Static.DataStructures; using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.DataFlowAnalysis { - class ForwardAnalysis<AState, EdgeData> : - ForwardDataFlowAnalysisBase<AState>, - IFixPointInfo<APC, AState> { - private readonly Action<Pair<AState, TextWriter>> dumper; - private readonly EdgeConverter<APC, AState, EdgeData> edge_converter; + class ForwardAnalysis<AbstractState, EdgeData> : + ForwardDataFlowAnalysisBase<AbstractState>, + IFixPointInfo<APC, AbstractState> { + private readonly Action<Pair<AbstractState, TextWriter>> dumper; + private readonly EdgeConverter<APC, AbstractState, EdgeData> edge_converter; private readonly Func<APC, APC, EdgeData> edge_data_getter; - private readonly Func<AState, AState> immutable_version; - private readonly Func<APC, AState, bool> is_bottom; - private readonly Joiner<APC, AState> joiner; - private readonly Func<AState, AState> mutable_version; - private readonly Func<APC, AState, AState> transfer; + private readonly Func<AbstractState, AbstractState> immutable_version; + private readonly Func<APC, AbstractState, bool> is_bottom; + private readonly Joiner<APC, AbstractState> joiner; + private readonly Func<AbstractState, AbstractState> mutable_version; + private readonly Func<APC, AbstractState, AbstractState> transfer; public ForwardAnalysis (ICFG cfg, - Func<APC, AState, AState> transfer, - Joiner<APC, AState> joiner, - Func<AState, AState> immutableVersion, - Func<AState, AState> mutableVersion, - EdgeConverter<APC, AState, EdgeData> edgeConverter, + Func<APC, AbstractState, AbstractState> transfer, + Joiner<APC, AbstractState> joiner, + Func<AbstractState, AbstractState> immutableVersion, + Func<AbstractState, AbstractState> mutableVersion, + EdgeConverter<APC, AbstractState, EdgeData> edgeConverter, Func<APC, APC, EdgeData> edgeDataGetter, - Func<APC, AState, bool> isBottom, - Action<Pair<AState, TextWriter>> dumper) : base (cfg) + Func<APC, AbstractState, bool> isBottom, + Action<Pair<AbstractState, TextWriter>> dumper) : base (cfg) { this.transfer = transfer; this.joiner = joiner; @@ -68,26 +68,26 @@ namespace Mono.CodeContracts.Static.DataFlowAnalysis { } #region IFixPointInfo<APC,AbstractState> Members - public bool PreStateLookup (APC pc, out AState state) + public bool PreStateLookup (APC pc, out AbstractState state) { return GetPreState (pc, out state); } - public bool PostStateLookup (APC pc, out AState state) + public bool PostStateLookup (APC pc, out AbstractState state) { return GetPostState (pc, out state); } #endregion - public static ForwardAnalysis<AState, EdgeData> Make<Source, Dest, Context> ( + public static ForwardAnalysis<AbstractState, EdgeData> Make<Source, Dest, Context> ( IILDecoder<APC, Source, Dest, Context, EdgeData> decoder, - IAnalysis<APC, AState, IILVisitor<APC, Source, Dest, AState, AState>, EdgeData> analysis) + IAnalysis<APC, AbstractState, IILVisitor<APC, Source, Dest, AbstractState, AbstractState>, EdgeData> analysis) where Context : IMethodContextProvider { - IILVisitor<APC, Source, Dest, AState, AState> visitor = analysis.GetVisitor (); - var forwardAnalysisSolver = new ForwardAnalysis<AState, EdgeData> ( + IILVisitor<APC, Source, Dest, AbstractState, AbstractState> visitor = analysis.GetVisitor (); + var forwardAnalysisSolver = new ForwardAnalysis<AbstractState, EdgeData> ( decoder.ContextProvider.MethodContext.CFG, - (pc, state) => decoder.ForwardDecode<AState, AState, IILVisitor<APC, Source, Dest, AState, AState>> (pc, visitor, state), + (pc, state) => decoder.ForwardDecode<AbstractState, AbstractState, IILVisitor<APC, Source, Dest, AbstractState, AbstractState>> (pc, visitor, state), analysis.Join, analysis.ImmutableVersion, analysis.MutableVersion, @@ -106,19 +106,19 @@ namespace Mono.CodeContracts.Static.DataFlowAnalysis { return forwardAnalysisSolver; } - protected override void Dump (AState state) + protected override void Dump (AbstractState state) { - this.dumper (new Pair<AState, TextWriter> (state, Console.Out)); + this.dumper (new Pair<AbstractState, TextWriter> (state, Console.Out)); } - protected override void PushState (APC from, APC next, AState state) + protected override void PushState (APC from, APC next, AbstractState state) { EdgeData data = this.edge_data_getter (from, next); - AState pushState = this.edge_converter (from, next, RequiresJoining (next), data, state); + AbstractState pushState = this.edge_converter (from, next, RequiresJoining (next), data, state); base.PushState (from, next, pushState); } - protected override bool Join (Pair<APC, APC> edge, AState newState, AState existingState, out AState joinedState, bool widen) + protected override bool Join (Pair<APC, APC> edge, AbstractState newState, AbstractState existingState, out AbstractState joinedState, bool widen) { bool weaker; joinedState = this.joiner (edge, newState, existingState, out weaker, widen); @@ -126,24 +126,24 @@ namespace Mono.CodeContracts.Static.DataFlowAnalysis { return weaker; } - protected override bool IsBottom (APC pc, AState state) + protected override bool IsBottom (APC pc, AbstractState state) { return this.is_bottom (pc, state); } - protected override AState Transfer (APC pc, AState state) + protected override AbstractState Transfer (APC pc, AbstractState state) { - AState resultState = this.transfer (pc, state); + AbstractState resultState = this.transfer (pc, state); return resultState; } - protected override AState MutableVersion (AState state, APC at) + protected override AbstractState MutableVersion (AbstractState state, APC at) { return this.mutable_version (state); } - protected override AState ImmutableVersion (AState state, APC at) + protected override AbstractState ImmutableVersion (AbstractState state, APC at) { return this.immutable_version (state); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardDataFlowAnalysisBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardDataFlowAnalysisBase.cs index b82f8f182df..a96721b0bd0 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardDataFlowAnalysisBase.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardDataFlowAnalysisBase.cs @@ -54,7 +54,7 @@ namespace Mono.CodeContracts.Static.DataFlowAnalysis { private AState GetPreState (APC apc, AState ifMissing, out bool noInfo) { - LispList<APC> rest = null; + Sequence<APC> rest = null; APC tmp = apc; APC singlePredecessor; AState state; @@ -147,9 +147,7 @@ namespace Mono.CodeContracts.Static.DataFlowAnalysis { protected override bool IsBackEdge (APC from, APC to) { - //todo: implement this - //can't be false, because back edges means having cycles, so we definitely have to widen - return true; + return CFG.IsForwardBackEdge (from, to); } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs index b3027b86408..8786f946135 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs @@ -28,8 +28,11 @@ using System; using System.IO; + +using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Proving; namespace Mono.CodeContracts.Static.DataFlowAnalysis { interface IAnalysis<Label, AbstractState, Visitor, EdgeData> { @@ -42,4 +45,10 @@ namespace Mono.CodeContracts.Static.DataFlowAnalysis { Predicate<Label> SaveFixPointInfo (IFixPointInfo<Label, AbstractState> fixPointInfo); void Dump (Pair<AbstractState, TextWriter> pair); } + + interface IAbstractAnalysis<TDomain, TVar> : IAnalysis<APC, TDomain, IILVisitor<APC, TVar, TVar, TDomain, TDomain>, IImmutableMap<TVar, Sequence<TVar>>> { + TDomain TopValue (); + TDomain BottomValue (); + IFactQuery<BoxedExpression, TVar> FactQuery (IFixPointInfo<APC, TDomain> fixpoint); + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/BranchNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/BranchNode.cs new file mode 100644 index 00000000000..5c63d97722b --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/BranchNode.cs @@ -0,0 +1,152 @@ +// +// BranchNode.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Mono.CodeContracts.Static.DataStructures.Patricia +{ + internal class BranchNode<T> : PatriciaTrieNode<T> + { + private readonly int count; + + public readonly int Prefix; + public readonly int BranchingBit; + public readonly PatriciaTrieNode<T> Left; + public readonly PatriciaTrieNode<T> Right; + + public override int Key { get { return Prefix; } } + public override int Count { get { return count; } } + + public BranchNode(int prefix, int branchingBit, PatriciaTrieNode<T> left, PatriciaTrieNode<T> right) + { + Prefix = prefix; + BranchingBit = branchingBit; + Left = left; + Right = right; + + count = left.Count + right.Count; + } + + public override bool Contains(int key) + { + if (!MatchPrefix(key, Prefix, BranchingBit)) + return false; + + var child = IsZeroBitAt(key, BranchingBit) ? Left : Right; + + return child.Contains(key); + } + + public override IImmutableIntMap<T> Add(int key, T value) + { + if (!MatchPrefix(key, Prefix, BranchingBit)) + return Join(new LeafNode<T>(key, value), this); + + if (IsZeroBitAt(key, BranchingBit)) + return new BranchNode<T>(Prefix, BranchingBit, (PatriciaTrieNode<T>)Left.Add(key, value), Right); + + return new BranchNode<T>(Prefix, BranchingBit, Left, (PatriciaTrieNode<T>)Right.Add(key, value)); + } + + public override IImmutableIntMap<T> Remove(int key) + { + var left = Left; + var right = Right; + if (IsZeroBitAt(key, BranchingBit)) + { + left = (PatriciaTrieNode<T>)left.Remove(key); + if (left.Count == 0) + return right; + } + else + { + right = (PatriciaTrieNode<T>)right.Remove(key); + if (right.Count == 0) + return left; + } + + return Join(left, right); + } + + public override void Visit(Action<T> action) + { + Left.Visit(action); + Right.Visit(action); + } + + public override void Visit(Action<int, T> action) + { + Left.Visit(action); + Right.Visit(action); + } + + public override T Lookup(int key) + { + BranchNode<T> current = this; + + PatriciaTrieNode<T> child; + do + { + child = IsZeroBitAt(key, current.BranchingBit) ? current.Left : current.Right; + current = child as BranchNode<T>; + } + while (current != null); + + return child.Lookup(key); + } + + protected internal override void FillKeysTo(List<int> list) + { + Left.FillKeysTo(list); + Right.FillKeysTo(list); + } + + protected internal override void FillValuesTo(List<T> list) + { + Left.FillValuesTo(list); + Right.FillValuesTo(list); + } + + protected internal override void AppendToBuilder(StringBuilder sb) + { + Left.AppendToBuilder(sb); + Right.AppendToBuilder(sb); + } + + protected internal override void Dump(TextWriter tw, string prefix) + { + tw.WriteLine(prefix + "<Branch Prefix={0} BranchingBit={1}>", Prefix, BranchingBit); + Left.Dump(tw, prefix + " "); + Right.Dump(tw, prefix + " "); + tw.WriteLine(prefix + "</Branch>"); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/EmptyNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/EmptyNode.cs new file mode 100644 index 00000000000..cdde993afcb --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/EmptyNode.cs @@ -0,0 +1,93 @@ +// +// EmptyNode.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Mono.CodeContracts.Static.DataStructures.Patricia +{ + class EmptyNode<T> : PatriciaTrieNode<T> + { + public static readonly EmptyNode<T> Instance = new EmptyNode<T>(); + + public override bool Contains(int key) + { + return false; + } + + public override int Key { get { throw new NotSupportedException("No key for empty node");} } + + public override int Count + { + get { return 0; } + } + + public override IImmutableIntMap<T> Add(int key, T value) + { + return new LeafNode<T>(key, value); + } + + public override IImmutableIntMap<T> Remove(int key) + { + return this; + } + + public override void Visit(Action<T> action) + { + } + + public override void Visit(Action<int, T> action) + { + } + + protected internal override void FillKeysTo(List<int> list) + { + } + + protected internal override void FillValuesTo(List<T> list) + { + } + + protected internal override void AppendToBuilder(StringBuilder sb) + { + sb.Append("*"); + } + + protected internal override void Dump(TextWriter tw, string prefix) + { + tw.WriteLine(prefix + "<empty/>"); + } + + public override T Lookup(int key) + { + return default(T); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/LeafNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/LeafNode.cs new file mode 100644 index 00000000000..c8b4b5b62e3 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/LeafNode.cs @@ -0,0 +1,106 @@ +// +// LeafNode.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Mono.CodeContracts.Static.DataStructures.Patricia +{ + internal class LeafNode<T> : PatriciaTrieNode<T> + { + private readonly int _key; + + public override bool Contains(int key) + { + return key == _key; + } + + public override int Key { get { return _key; } } + public override int Count { get { return 1; } } + public T Value { get; private set; } + + public LeafNode(int key, T value) + { + _key = key; + Value = value; + } + + public override IImmutableIntMap<T> Add(int key, T value) + { + if (key == Key) + return new LeafNode<T>(key, value); + + return Join(new LeafNode<T>(key, value), this); + } + + public override IImmutableIntMap<T> Remove(int key) + { + if (key == this.Key) + return EmptyNode<T>.Instance; + + return this; + } + + public override void Visit(Action<T> action) + { + action(Value); + } + + public override void Visit(Action<int, T> action) + { + action(Key, Value); + } + + protected internal override void FillKeysTo(List<int> list) + { + list.Add(_key); + } + + protected internal override void FillValuesTo(List<T> list) + { + list.Add(Value); + } + + protected internal override void AppendToBuilder(StringBuilder sb) + { + sb.AppendFormat("{0}->'{1}' ", _key, Value); + } + + protected internal override void Dump(TextWriter tw, string prefix) + { + tw.WriteLine(prefix + "<Leaf Key={0} Value='{1}' />", _key, Value); + } + + public override T Lookup(int key) + { + return key == _key ? Value : default(T); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/PatriciaTrieNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/PatriciaTrieNode.cs new file mode 100644 index 00000000000..f0e99e5ffce --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures.Patricia/PatriciaTrieNode.cs @@ -0,0 +1,133 @@ +// +// PatriciaTrieNode.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Mono.CodeContracts.Static.DataStructures.Patricia +{ + abstract class PatriciaTrieNode<T> : IImmutableIntMap<T> + { + public T this[int key] + { + get { return this.Lookup(key); } + } + + public T Any { get; private set; } + + public abstract bool Contains(int key); + + public abstract int Key { get; } + public abstract int Count { get; } + public abstract IImmutableIntMap<T> Add(int key, T value); + public abstract IImmutableIntMap<T> Remove(int key); + + public abstract void Visit(Action<T> action); + public abstract void Visit(Action<int, T> action); + + public abstract T Lookup(int key); + + public IEnumerable<int> Keys + { + get + { + var list = new List<int>(this.Count); + FillKeysTo(list); + return list; + } + } + + public IEnumerable<T> Values + { + get + { + var list = new List<T>(this.Count); + FillValuesTo(list); + return list; + } + } + + public void Dump(TextWriter tw) + { + Dump(tw, string.Empty); + } + + protected internal abstract void FillKeysTo(List<int> list); + protected internal abstract void FillValuesTo(List<T> list); + protected internal abstract void AppendToBuilder(StringBuilder sb); + protected internal abstract void Dump(TextWriter tw, string prefix); + + public override string ToString() + { + var sb = new StringBuilder(); + AppendToBuilder(sb); + return sb.ToString(); + } + + protected static IImmutableIntMap<T> Join(PatriciaTrieNode<T> left, PatriciaTrieNode<T> right) + { + int keyLeft = left.Key; + int keyRight = right.Key; + + int branchingBit = BranchingBit(keyLeft, keyRight); + var prefix = MaskWithBit(keyLeft, branchingBit); + + if (IsZeroBitAt(keyLeft, branchingBit)) + return new BranchNode<T>(prefix, branchingBit, left, right); + + return new BranchNode<T>(prefix, branchingBit, right, left); + } + + protected static bool IsZeroBitAt(int key, int branchingBit) + { + return (key & branchingBit) == 0; + } + + private static int BranchingBit(int left, int right) + { + return LowestBit(left ^ right); + } + + private static int LowestBit(int x) + { + return x & -x; + } + + private static int MaskWithBit(int key, int mask) + { + return key & (mask - 1); + } + + protected static bool MatchPrefix(int key, int prefix, int maskBit) + { + return MaskWithBit(key, maskBit) == prefix; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/BooleanExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/BooleanExtensions.cs new file mode 100644 index 00000000000..337cdc0b808 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/BooleanExtensions.cs @@ -0,0 +1,63 @@ +// +// BooleanExtensions.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.Lattices; + +namespace Mono.CodeContracts.Static.DataStructures +{ + static class BooleanExtensions + { + /// <summary> + /// Returns value and sets result to a resultValue. + /// </summary> + public static bool With<T>(this bool value, T resultValue, out T result) + { + result = resultValue; + return value; + } + + /// <summary> + /// Returns value and sets result to a default(T). + /// </summary> + public static bool Without<T>(this bool value, out T result) + { + result = default(T); + return value; + } + + /// <summary> + /// Returns ProofOutcome value based on input. + /// </summary> + /// <param name="condition">Condition to check.</param> + /// <returns><see cref="ProofOutcome.True"/> if condition holds, otherwise <see cref="ProofOutcome.Top"/></returns> + public static FlatDomain<bool> ToTrueOrTop(this bool condition) + { + return condition ? ProofOutcome.True : ProofOutcome.Top; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs index be7a11ae8ce..35d2573a5cc 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs @@ -1,3 +1,31 @@ +// +// DecoratorHelper.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using System.Collections.Generic; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs index 16ee3b900bd..a4bc992d0ac 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs @@ -96,7 +96,7 @@ namespace Mono.CodeContracts.Static.DataStructures { public virtual void VisitAll () { foreach (Node node in this.graph.Nodes) - VisitSubGraphNonRecursive (node); + this.VisitSubGraphNonRecursive (node); } public void VisitSubGraphNonRecursive (Node node) @@ -121,41 +121,40 @@ namespace Mono.CodeContracts.Static.DataStructures { } } - private void VisitEdgeNonRecursive (Info<Node> sourceInfo, Node source, Edge info, Node target) - { - if (this.edge_visitor != null) - this.edge_visitor (source, info, target); - - Info<Node> targetInfo; - if (this.history.TryGetValue (target, out targetInfo)) { - if (targetInfo.FinishTime != 0) - return; - - targetInfo.TargetOfBackEdge = true; - sourceInfo.SourceOfBackEdge = true; - this.back_edges.Add (new Tuple<Node, Edge, Node> (source, info, target)); - } else - ScheduleNode (target, source); - } + private void VisitEdgeNonRecursive(Info<Node> sourceInfo, Node source, Edge info, Node target) + { + if (!VisitEdgeCommon (sourceInfo, source, info, target)) + ScheduleNode (target, source); + } - private void VisitEdge (Info<Node> sourceInfo, Node source, Edge info, Node target) - { - if (this.edge_visitor != null) - this.edge_visitor (source, info, target); - - Info<Node> targetInfo; - if (this.history.TryGetValue (target, out targetInfo)) { - if (targetInfo.FinishTime != 0) - return; - - targetInfo.TargetOfBackEdge = true; - sourceInfo.SourceOfBackEdge = true; - this.back_edges.Add (new Tuple<Node, Edge, Node> (source, info, target)); - } else - VisitSubGraph (target, source); - } + private void VisitEdge (Info<Node> sourceInfo, Node source, Edge info, Node target) + { + if (!VisitEdgeCommon (sourceInfo, source, info, target)) + VisitSubGraph (target, source); + } + + private bool VisitEdgeCommon(Info<Node> sourceInfo, Node source, Edge info, Node target ) + { + if (this.edge_visitor != null) + this.edge_visitor(source, info, target); + + Info<Node> targetInfo; + if (this.history.TryGetValue(target, out targetInfo)) + { + if (targetInfo.FinishTime != 0) + return true; + + targetInfo.TargetOfBackEdge = true; + sourceInfo.SourceOfBackEdge = true; + this.back_edges.Add(new Tuple<Node, Edge, Node>(source, info, target)); + + return true; + } + + return false; + } - public void VisitSubGraph (Node node, Node parent) + public void VisitSubGraph (Node node, Node parent) { if (this.history.ContainsKey (node)) return; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs index 2be8d32ad0d..0bb4a723de3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs @@ -44,5 +44,13 @@ namespace Mono.CodeContracts.Static.DataStructures { bool ContainsKey (K key); void Visit (Func<K, V, VisitStatus> func); + + bool TryGetValue (K key, out V value); + + IImmutableMapFactory<K, V> Factory(); } + + internal interface IImmutableMapFactory<K, V> { + IImmutableMap<K, V> Empty { get; } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs index 21873b8bcb7..77808560ffe 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs @@ -31,12 +31,12 @@ using System.Collections.Generic; using System.IO; namespace Mono.CodeContracts.Static.DataStructures { - interface IImmutableSet<T> - where T : IEquatable<T> { + interface IImmutableSet<T> { T Any { get; } int Count { get; } IEnumerable<T> Elements { get; } IImmutableSet<T> Add (T item); + IImmutableSet<T> AddRange (IEnumerable<T> item); IImmutableSet<T> Remove (T item); bool Contains (T item); bool IsContainedIn (IImmutableSet<T> that); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs index 344344fb446..1a8528fc7b8 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs @@ -26,9 +26,20 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.Collections.Generic; + namespace Mono.CodeContracts.Static.DataStructures { - interface IIndexable<T> { + interface IIndexable<out T> { int Count { get; } T this [int index] { get; } } + + static class IndexableExtensions { + public static IEnumerable<T> AsEnumerable<T>(this IIndexable<T> indexable) + { + for (int i = 0; i < indexable.Count; i++) { + yield return indexable[i]; + } + } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ITypedProperties.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IPropertyCollection.cs index a4533d0422b..337e6b08b26 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ITypedProperties.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IPropertyCollection.cs @@ -1,5 +1,5 @@ // -// ITypedProperties.cs +// IPropertyCollection.cs // // Authors: // Alexander Chebaturkin (chebaturkin@gmail.com) @@ -27,7 +27,7 @@ // namespace Mono.CodeContracts.Static.DataStructures { - internal interface ITypedProperties { + internal interface IPropertyCollection { bool Contains (TypedKey key); void Add<T> (TypedKey key, T value); bool TryGetValue<T> (TypedKey key, out T value); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs index 6cbf5961e34..10f69397b30 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs @@ -46,14 +46,13 @@ namespace Mono.CodeContracts.Static.DataStructures { { get { - Pair<K, V> pair = this.immutable_int_map [this.keyConverter (key)]; - if (pair != null) - return pair.Value; - return default(V); + V value; + TryGetValue (key, out value); + return value; } } - public K AnyKey + public K AnyKey { get { return Keys.First (); } } @@ -93,11 +92,20 @@ namespace Mono.CodeContracts.Static.DataStructures { return this.immutable_int_map.Contains (this.keyConverter (key)); } - public void Visit (Func<K, V, VisitStatus> func) + public bool TryGetValue(K key, out V value) + { + Pair<K, V> pair = this.immutable_int_map[this.keyConverter(key)]; + if (pair != null) + return true.With(pair.Value, out value); + return false.Without(out value); + } + + public void Visit (Func<K, V, VisitStatus> func) { this.immutable_int_map.Visit (data => func (data.Key, data.Value)); } - #endregion + + #endregion #region Implementation of IEquatable<IImmutableMap<K,V>> public bool Equals (IImmutableMap<K, V> other) @@ -108,7 +116,23 @@ namespace Mono.CodeContracts.Static.DataStructures { public static IImmutableMap<K, V> Empty (Func<K, int> keyConverter) { - return new ImmutableIntKeyMap<K, V> (ImmutableIntMap<Pair<K, V>>.Empty (), keyConverter); + return new ImmutableIntKeyMap<K, V> (ImmutableIntMap<Pair<K, V>>.Empty, keyConverter); } + + public IImmutableMapFactory<K, V> Factory () + { + return new MapFactory (this.keyConverter); + } + + private class MapFactory : IImmutableMapFactory<K,V> { + private readonly Func<K, int> keyConverter; + + public MapFactory (Func<K, int> keyConverter) + { + this.keyConverter = keyConverter; + } + + public IImmutableMap<K, V> Empty { get { return ImmutableIntKeyMap<K, V>.Empty (keyConverter);}} + } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntMap.cs index 39bb01ce9c2..8d2bc096683 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntMap.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntMap.cs @@ -26,121 +26,11 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System; -using System.Collections.Generic; -using System.Linq; +using Mono.CodeContracts.Static.DataStructures.Patricia; namespace Mono.CodeContracts.Static.DataStructures { - class ImmutableIntMap<T> : IImmutableIntMap<T> { - private readonly Dictionary<int, T> map = new Dictionary<int, T> (); - - private ImmutableIntMap (Dictionary<int, T> map) - { - this.map = map; - } - - #region Implementation of IImm utableIntMap<T> - public T this [int key] - { - get - { - if (this.map == null || !this.map.ContainsKey (key)) - return default(T); - - return this.map [key]; - } - } - - public T Any - { - get - { - if (this.map == null) - return default(T); - return this.map.Values.First (); - } - } - - public IEnumerable<T> Values - { - get - { - if (this.map == null) - return Enumerable.Empty<T> (); - return this.map.Values; - } - } - - public IEnumerable<int> Keys - { - get - { - if (this.map == null) - return Enumerable.Empty<int> (); - return this.map.Keys; - } - } - - public int Count - { - get - { - if (this.map == null) - return 0; - return this.map.Count; - } - } - - public T Lookup (int key) - { - if (this.map == null) - return default(T); - return this.map [key]; - } - - public bool Contains (int key) - { - if (this.map == null) - return false; - return this.map.ContainsKey (key); - } - - public IImmutableIntMap<T> Add (int key, T value) - { - if (this.map == null) - return new ImmutableIntMap<T> (new Dictionary<int, T> {{key, value}}); - - var newDict = new Dictionary<int, T> (this.map); - newDict [key] = value; - return new ImmutableIntMap<T> (newDict); - } - - public IImmutableIntMap<T> Remove (int key) - { - if (this.map == null || !this.map.ContainsKey (key)) - return this; - - var newDict = new Dictionary<int, T> (this.map); - newDict.Remove (key); - return new ImmutableIntMap<T> (newDict); - } - - public void Visit (Action<T> action) - { - foreach (T value in Values) - action (value); - } - - public void Visit (Action<int, T> action) - { - foreach (int key in Keys) - action (key, this [key]); - } - #endregion - - public static IImmutableIntMap<T> Empty () - { - return new ImmutableIntMap<T> (null); - } + static class ImmutableIntMap<T> + { + public static readonly IImmutableIntMap<T> Empty = EmptyNode<T>.Instance; } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs index 7b62009cc59..529b0be7076 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs @@ -33,12 +33,13 @@ using System.Linq; namespace Mono.CodeContracts.Static.DataStructures { class ImmutableMap<K, V> : IImmutableMap<K, V> where K : IEquatable<K> { - public static ImmutableMap<K, V> Empty = new ImmutableMap<K, V> (ImmutableIntMap<LispList<Pair<K, V>>>.Empty (), 0, null); + public static readonly ImmutableMap<K, V> Empty = new ImmutableMap<K, V> (ImmutableIntMap<Sequence<Pair<K, V>>>.Empty, 0, null); + private readonly int count; - private readonly IImmutableIntMap<LispList<Pair<K, V>>> immutable_int_map; - private readonly LispList<K> keys; + private readonly IImmutableIntMap<Sequence<Pair<K, V>>> immutable_int_map; + private readonly Sequence<K> keys; - private ImmutableMap (IImmutableIntMap<LispList<Pair<K, V>>> map, int count, LispList<K> keys) + private ImmutableMap (IImmutableIntMap<Sequence<Pair<K, V>>> map, int count, Sequence<K> keys) { this.keys = keys; this.count = count; @@ -50,16 +51,23 @@ namespace Mono.CodeContracts.Static.DataStructures { { get { - for (LispList<Pair<K, V>> list = this.immutable_int_map [key.GetHashCode ()]; list != null; list = list.Tail) { - K k = list.Head.Key; - if (key.Equals (k)) - return list.Head.Value; - } - return default(V); + V value; + return TryGetValue (key, out value) ? value : default(V); } } - public K AnyKey + public bool TryGetValue (K key, out V value) + { + for (Sequence<Pair<K, V>> list = this.immutable_int_map[key.GetHashCode ()]; list != null; list = list.Tail) + { + K k = list.Head.Key; + if (key.Equals (k)) + return true.With (list.Head.Value, out value); + } + return false.Without (out value); + } + + public K AnyKey { get { return this.keys.Head; } } @@ -82,10 +90,10 @@ namespace Mono.CodeContracts.Static.DataStructures { public IImmutableMap<K, V> Add (K key, V value) { int hashCode = key.GetHashCode (); - LispList<Pair<K, V>> list1 = this.immutable_int_map [hashCode]; - LispList<Pair<K, V>> newList = Remove (list1, key).Cons (new Pair<K, V> (key, value)); - int diff = newList.Length () - list1.Length (); - LispList<K> newKeys = diff == 0 ? this.keys : this.keys.Cons (key); + Sequence<Pair<K, V>> cur = this.immutable_int_map [hashCode]; + Sequence<Pair<K, V>> newList = Remove (cur, key).Cons (new Pair<K, V> (key, value)); + int diff = newList.Length () - cur.Length (); + Sequence<K> newKeys = diff == 0 ? this.keys : this.keys.Cons (key); return new ImmutableMap<K, V> (this.immutable_int_map.Add (hashCode, newList), this.count + diff, newKeys); } @@ -93,13 +101,14 @@ namespace Mono.CodeContracts.Static.DataStructures { public IImmutableMap<K, V> Remove (K key) { int hashCode = key.GetHashCode (); - LispList<Pair<K, V>> from = this.immutable_int_map [hashCode]; + Sequence<Pair<K, V>> from = this.immutable_int_map [hashCode]; if (from == null) return this; - LispList<Pair<K, V>> newList = Remove (from, key); + Sequence<Pair<K, V>> newList = Remove (from, key); if (newList == from) return this; - LispList<K> newKeys = RemoveKey (key, this.keys); + + Sequence<K> newKeys = RemoveKey (key, this.keys); if (newList == null) return new ImmutableMap<K, V> (this.immutable_int_map.Remove (hashCode), this.count - 1, newKeys); return new ImmutableMap<K, V> (this.immutable_int_map.Add (hashCode, newList), this.count - 1, newKeys); @@ -118,17 +127,17 @@ namespace Mono.CodeContracts.Static.DataStructures { }); } - private LispList<Pair<K, V>> Remove (LispList<Pair<K, V>> from, K key) + private Sequence<Pair<K, V>> Remove (Sequence<Pair<K, V>> from, K key) { if (from == null) return null; if (key.Equals (from.Head.Key)) return from.Tail; - LispList<Pair<K, V>> tail = Remove (from.Tail, key); + Sequence<Pair<K, V>> tail = Remove (from.Tail, key); return tail == from.Tail ? from : tail.Cons (from.Head); } - private static LispList<K> RemoveKey (K key, LispList<K> keys) + private static Sequence<K> RemoveKey (K key, Sequence<K> keys) { if (keys == null) throw new InvalidOperationException (); @@ -139,5 +148,15 @@ namespace Mono.CodeContracts.Static.DataStructures { return RemoveKey (key, keys.Tail).Cons (keys.Head); } #endregion + + public IImmutableMapFactory<K, V> Factory () + { + return new MapFactory (); + } + + private class MapFactory : IImmutableMapFactory<K, V> + { + public IImmutableMap<K, V> Empty { get { return ImmutableMap<K,V>.Empty;}} + } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs index cc385da6406..38ee77d3a5a 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs @@ -35,7 +35,7 @@ namespace Mono.CodeContracts.Static.DataStructures { where T : IEquatable<T> { private readonly IImmutableMap<T, Dummy> underlying; - public ImmutableSet (IImmutableMap<T, Dummy> immutableMap) + private ImmutableSet (IImmutableMap<T, Dummy> immutableMap) { this.underlying = immutableMap; } @@ -61,7 +61,16 @@ namespace Mono.CodeContracts.Static.DataStructures { return new ImmutableSet<T> (this.underlying.Add (item, Dummy.Value)); } - public IImmutableSet<T> Remove (T item) + public IImmutableSet<T> AddRange(IEnumerable<T> seq) + { + var map = this.underlying; + foreach (var item in seq) + map = map.Add(item, Dummy.Value); + + return new ImmutableSet<T>(map); + } + + public IImmutableSet<T> Remove (T item) { return new ImmutableSet<T> (this.underlying.Remove (item)); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispList.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispList.cs deleted file mode 100644 index 9e5d2282100..00000000000 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispList.cs +++ /dev/null @@ -1,131 +0,0 @@ -// -// LispList.cs -// -// Authors: -// Alexander Chebaturkin (chebaturkin@gmail.com) -// -// Copyright (C) 2011 Alexander Chebaturkin -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Mono.CodeContracts.Static.DataStructures { - class LispList<T> { - public static readonly LispList<T> Empty = null; - private readonly int count; - private readonly T element; - private readonly LispList<T> tail; - - private LispList (T elem, LispList<T> tail) - { - this.element = elem; - this.tail = tail; - this.count = LengthOf (tail) + 1; - } - - public T Head - { - get { return this.element; } - } - - public LispList<T> Tail - { - get { return this.tail; } - } - - public static LispList<T> Cons (T elem, LispList<T> tail) - { - return new LispList<T> (elem, tail); - } - - public static LispList<T> Reverse (LispList<T> list) - { - LispList<T> rest = null; - for (; list != null; list = list.tail) - rest = rest.Cons (list.element); - return rest; - } - - public static bool Contains (LispList<T> l, T o) - { - if (l == null) - return false; - var equatable = o as IEquatable<T>; - if (equatable != null) { - if (equatable.Equals (l.element)) - return true; - } else if (o.Equals (l.element)) - return true; - - return Contains (l.tail, o); - } - - public static int LengthOf (LispList<T> list) - { - if (list == null) - return 0; - return list.count; - } - - public static void Apply (LispList<T> list, Action<T> action) - { - for (; list != null; list = list.tail) - action (list.Head); - } - - public static IEnumerable<T> PrivateGetEnumerable (LispList<T> list) - { - LispList<T> current = list; - while (current != null) { - T next = current.Head; - current = current.tail; - yield return next; - } - } - - public static LispList<S> Select<S> (LispList<T> list, Func<T, S> selector) - { - if (list == null) - return null; - return list.tail.Select (selector).Cons (selector (list.Head)); - } - - public override string ToString () - { - var sb = new StringBuilder (); - BuildString (sb); - - return sb.ToString (); - } - - private void BuildString (StringBuilder sb) - { - sb.Append (this.element == null ? "<null>" : this.element.ToString ()); - if (this.tail != null) { - sb.Append (","); - this.tail.BuildString (sb); - } - } - } -} diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispListExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispListExtensions.cs deleted file mode 100644 index 52c5f0c0582..00000000000 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispListExtensions.cs +++ /dev/null @@ -1,116 +0,0 @@ -// -// LispListExtensions.cs -// -// Authors: -// Alexander Chebaturkin (chebaturkin@gmail.com) -// -// Copyright (C) 2011 Alexander Chebaturkin -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; - -namespace Mono.CodeContracts.Static.DataStructures { - static class LispListExtensions { - public static LispList<T> Cons<T> (this LispList<T> rest, T elem) - { - return LispList<T>.Cons (elem, rest); - } - - public static LispList<T> Append<T> (this LispList<T> list, LispList<T> append) - { - if (list == null) - return append; - if (append == null) - return list; - - return Cons (list.Tail.Append (append), list.Head); - } - - public static LispList<T> Where<T> (this LispList<T> list, Predicate<T> keep) - { - if (list == null) - return null; - LispList<T> rest = list.Tail.Where (keep); - if (!keep (list.Head)) - return rest; - - if (rest == list.Tail) - return list; - - return Cons (rest, list.Head); - } - - public static void Apply<T> (this LispList<T> list, Action<T> action) - { - LispList<T>.Apply (list, action); - } - - public static IEnumerable<T> AsEnumerable<T> (this LispList<T> list) - { - return LispList<T>.PrivateGetEnumerable (list); - } - - public static bool Any<T> (this LispList<T> list, Predicate<T> predicate) - { - if (list == null) - return false; - - if (predicate (list.Head)) - return true; - - return list.Tail.Any (predicate); - } - - public static int Length<T> (this LispList<T> list) - { - return LispList<T>.LengthOf (list); - } - - public static bool IsEmpty<T> (this LispList<T> list) - { - return list == null; - } - - public static LispList<S> Select<T, S> (this LispList<T> list, Func<T, S> selector) - { - return LispList<T>.Select (list, selector); - } - - public static T Last<T> (this LispList<T> list) - { - if (list == null) - return default(T); - - while (LispList<T>.LengthOf (list) > 1) - list = list.Tail; - - return list.Head; - } - - public static LispList<T> Coerce<S, T> (this LispList<S> list) - where S : T - { - return list.Select (l => (T) l); - } - } -} diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs index 52a8b3472cb..277a8067926 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs @@ -68,4 +68,11 @@ namespace Mono.CodeContracts.Static.DataStructures { (!ValueIsReferenceType || ((object) this.Value) != null) ? this.Value.ToString () : "<null>"); } } + + static class Pair { + public static Pair<K,V> From<K,V>(K key, V value) + { + return new Pair<K, V> (key, value); + } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedProperties.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/PropertyCollection.cs index 7e4f2daa1c0..ec66fb56b16 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedProperties.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/PropertyCollection.cs @@ -1,5 +1,5 @@ // -// TypedProperties.cs +// PropertyCollection.cs // // Authors: // Alexander Chebaturkin (chebaturkin@gmail.com) @@ -28,33 +28,39 @@ using System.Collections.Generic; +using Mono.CodeContracts.Static.Analysis.Numerical; + namespace Mono.CodeContracts.Static.DataStructures { - class TypedProperties : ITypedProperties { + class PropertyCollection : IPropertyCollection { private readonly Dictionary<object, object> dictionary = new Dictionary<object, object> (); - #region Implementation of ITypedProperties + #region Implementation of IPropertyCollection public bool Contains (TypedKey key) { return this.dictionary.ContainsKey (key); } - public void Add<T> (TypedKey key, T value) + public void Add<T> (TypedKey key, T value) { this.dictionary.Add (key, value); } - public bool TryGetValue<T> (TypedKey key, out T value) - { - object result; + public bool TryGetValue<T> (TypedKey key, out T value) + { + object result; - if (!this.dictionary.TryGetValue (key, out result)) { - value = default(T); - return false; - } + if (!this.dictionary.TryGetValue (key, out result)) + return false.Without (out value); - value = (T) result; - return true; - } - #endregion + value = (T) result; + return true; + } + + public void Remove(TypedKey key) + { + this.dictionary.Remove (key); + } + + #endregion } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Sequence.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Sequence.cs new file mode 100644 index 00000000000..6899b4bea00 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Sequence.cs @@ -0,0 +1,164 @@ +// +// Sequence.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2011 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Mono.CodeContracts.Static.DataStructures { + class Sequence<T> : IEquatable<Sequence<T>> { + public static readonly Sequence<T> Empty = null; + readonly int count; + readonly T element; + readonly Sequence<T> tail; + + Sequence (T elem, Sequence<T> tail) + { + this.element = elem; + this.tail = tail; + this.count = LengthOf (tail) + 1; + } + + public T Head { get { return this.element; } } + + public Sequence<T> Tail { get { return this.tail; } } + + public static Sequence<T> Cons (T elem, Sequence<T> tail) + { + return new Sequence<T> (elem, tail); + } + + public static bool Contains (Sequence<T> l, T o) + { + if (l == null) + return false; + var equatable = o as IEquatable<T>; + if (equatable != null) { + if (equatable.Equals (l.element)) + return true; + } + else if (o.Equals (l.element)) + return true; + + return Contains (l.tail, o); + } + + public static int LengthOf (Sequence<T> list) + { + if (list == null) + return 0; + return list.count; + } + + public static void Apply (Sequence<T> list, Action<T> action) + { + for (; list != null; list = list.tail) + action (list.Head); + } + + public static IEnumerable<T> PrivateGetEnumerable (Sequence<T> list) + { + Sequence<T> current = list; + while (current != null) { + T next = current.Head; + current = current.tail; + yield return next; + } + } + + public static Sequence<S> Select<S> (Sequence<T> list, Func<T, S> selector) + { + if (list == null) + return null; + return list.tail.Select (selector).Cons (selector (list.Head)); + } + + public static Sequence<T> From (params T[] elems) + { + Sequence<T> result = null; + foreach (T elem in elems) + result = result.Cons (elem); + + return result.Reverse (); + } + + public static Sequence<T> From (IEnumerable<T> elems) + { + Sequence<T> result = null; + foreach (T elem in elems) + result = result.Cons (elem); + + return result.Reverse (); + } + + public bool Equals (Sequence<T> other) + { + if (ReferenceEquals (null, other)) return false; + if (ReferenceEquals (this, other)) return true; + return Equals (this.tail, other.tail) && EqualityComparer<T>.Default.Equals (this.element, other.element); + } + + public override bool Equals (object obj) + { + if (ReferenceEquals (null, obj)) return false; + if (ReferenceEquals (this, obj)) return true; + if (obj.GetType () != this.GetType ()) return false; + return Equals ((Sequence<T>) obj); + } + + public override int GetHashCode () + { + unchecked { + return ((this.tail != null ? this.tail.GetHashCode () : 0) * 397) ^ + EqualityComparer<T>.Default.GetHashCode (this.element); + } + } + + public override string ToString () + { + var sb = new StringBuilder (); + this.BuildString (sb); + + return sb.ToString (); + } + + void BuildString (StringBuilder sb) + { + sb.Append (this.element == null ? "<null>" : this.element.ToString ()); + if (this.tail != null) { + sb.Append (","); + this.tail.BuildString (sb); + } + } + + public static Sequence<T> Singleton (T value) + { + return new Sequence<T> (value, null); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/SequenceExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/SequenceExtensions.cs new file mode 100644 index 00000000000..5fa7f4b86c3 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/SequenceExtensions.cs @@ -0,0 +1,146 @@ +// +// SequenceExtensions.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2011 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; + +namespace Mono.CodeContracts.Static.DataStructures { + static class SequenceExtensions { + public static Sequence<T> Cons<T> (this Sequence<T> rest, T elem) + { + return Sequence<T>.Cons (elem, rest); + } + + public static Sequence<T> Append<T> (this Sequence<T> list, Sequence<T> append) + { + if (list == null) + return append; + if (append == null) + return list; + + return Cons (list.Tail.Append (append), list.Head); + } + + public static Sequence<T> Where<T> (this Sequence<T> list, Predicate<T> keep) + { + if (list == null) + return null; + Sequence<T> rest = list.Tail.Where (keep); + if (!keep (list.Head)) + return rest; + + if (rest == list.Tail) + return list; + + return Cons (rest, list.Head); + } + + public static void Apply<T> (this Sequence<T> list, Action<T> action) + { + Sequence<T>.Apply (list, action); + } + + public static IEnumerable<T> AsEnumerable<T> (this Sequence<T> list) + { + return Sequence<T>.PrivateGetEnumerable (list); + } + + public static bool Any<T> (this Sequence<T> list, Predicate<T> predicate) + { + if (list == null) + return false; + + if (predicate (list.Head)) + return true; + + return list.Tail.Any (predicate); + } + + public static bool All<T> (this Sequence<T> list, Predicate<T> predicate) + { + if (list == null) + return true; + + if (!predicate (list.Head)) + return false; + + return list.Tail.All (predicate); + } + + public static int Length<T> (this Sequence<T> list) + { + return Sequence<T>.LengthOf (list); + } + + public static bool IsEmpty<T> (this Sequence<T> list) + { + return list == null; + } + + public static Sequence<S> Select<T, S> (this Sequence<T> list, Func<T, S> selector) + { + return Sequence<T>.Select (list, selector); + } + + public static T Last<T> (this Sequence<T> list) + { + if (list == null) + return default(T); + + while (Sequence<T>.LengthOf (list) > 1) + list = list.Tail; + + return list.Head; + } + + public static Sequence<T> Coerce<S, T> (this Sequence<S> list) + where S : T + { + return list.Select (l => (T) l); + } + + public static Sequence<T> Reverse<T> (this Sequence<T> list) + { + Sequence<T> rest = null; + + for (Sequence<T> cur = list; cur != null; cur = cur.Tail) + rest = rest.Cons (cur.Head); + + return rest; + } + + public static void ForEach<T> (this Sequence<T> seq, Action<T> action) + { + if (seq == null) + return; + + action (seq.Head); + seq.Tail.ForEach (action); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs index 90da17f06e5..ce3d3eaa662 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs @@ -1,3 +1,31 @@ +// +// Extensions.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System.Collections.Generic; using System.Linq; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/AbstractDomainExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/AbstractDomainExtensions.cs new file mode 100644 index 00000000000..5c0ff40fc89 --- /dev/null +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/AbstractDomainExtensions.cs @@ -0,0 +1,106 @@ +// +// AbstractDomainExtensions.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Mono.CodeContracts.Static.DataStructures; + +namespace Mono.CodeContracts.Static.Lattices { + static class AbstractDomainExtensions { + public static bool IsNormal<T> (this IAbstractDomain<T> domain) + { + return !domain.IsTop && !domain.IsBottom; + } + + public static string BottomSymbolIfAny<T> (this IAbstractDomain<T> domain) + { + return domain.IsBottom ? "_|_" : string.Empty; + } + + public static bool TryTrivialLessEqual<T> (this T left, T right, out bool result) + where T : IAbstractDomain<T> + { + if (ReferenceEquals (left, right)) + return true.With (true, out result); + + if (left.IsBottom) + return true.With (true, out result); + + if (left.IsTop) + return true.With (right.IsTop, out result); + + if (right.IsBottom) + return true.With (false, out result); + + if (right.IsTop) + return true.With (true, out result); + + return false.Without (out result); + } + + public static bool TryTrivialJoin<T> (this T left, T right, out T result) + where T : IAbstractDomain<T> + { + if (ReferenceEquals (left, right)) + return true.With (left, out result); + + if (left.IsBottom) + return true.With (right, out result); + + if (left.IsTop) + return true.With (left, out result); + + if (right.IsBottom) + return true.With (left, out result); + + if (right.IsTop) + return true.With (right, out result); + + return false.Without (out result); + } + + public static bool TryTrivialMeet<T> (this T left, T right, out T result) + where T : IAbstractDomain<T> + { + if (ReferenceEquals (left, right)) + return true.With (left, out result); + + if (left.IsBottom) + return true.With (left, out result); + + if (left.IsTop) + return true.With (right, out result); + + if (right.IsBottom) + return true.With (right, out result); + + if (right.IsTop) + return true.With (left, out result); + + return false.Without (out result); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs index 555753bd0a6..f91eedd5862 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs @@ -30,192 +30,268 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; + using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Lattices { - class EnvironmentDomain<K, V> : IAbstractDomain<EnvironmentDomain<K, V>> - where V : IAbstractDomain<V> - where K : IEquatable<K> { - public static readonly EnvironmentDomain<K, V> BottomValue = new EnvironmentDomain<K, V> (null); - private static Func<K, int> KeyConverter; - private readonly IImmutableMap<K, V> map; - - private EnvironmentDomain (IImmutableMap<K, V> map) - { - this.map = map; - } - - public V this [K key] - { - get { return this.map == null ? default(V) : this.map [key]; } - } - - public IEnumerable<K> Keys - { - get { return this.map.Keys; } - } - - #region IAbstractDomain<EnvironmentDomain<K,V>> Members - public EnvironmentDomain<K, V> Top - { - get { return TopValue (KeyConverter); } - } - - public EnvironmentDomain<K, V> Bottom - { - get { return BottomValue; } - } - - public bool IsTop - { - get { return this.map != null && this.map.Count == 0; } - } - - public bool IsBottom - { - get { return this.map == null; } - } - - public EnvironmentDomain<K, V> Join (EnvironmentDomain<K, V> that, bool widening, out bool weaker) - { - weaker = false; - if (this.map == that.map || IsTop) - return this; - if (that.IsTop) { - weaker = !IsTop; - return that; - } - if (IsBottom) { - weaker = !that.IsBottom; - return that; - } - if (that.IsBottom) - return this; - - IImmutableMap<K, V> min; - IImmutableMap<K, V> max; - GetMinAndMaxByCount (this.map, that.map, out min, out max); - - IImmutableMap<K, V> intersect = min; - foreach (K key in min.Keys) { - if (!max.ContainsKey (key)) - intersect = intersect.Remove (key); - else { - bool keyWeaker; - V join = min [key].Join (max [key], widening, out keyWeaker); - if (keyWeaker) { - weaker = true; - intersect = join.IsTop ? intersect.Remove (key) : intersect.Add (key, join); - } - } - } - - weaker |= intersect.Count < this.map.Count; - return new EnvironmentDomain<K, V> (intersect); - } - - public EnvironmentDomain<K, V> Meet (EnvironmentDomain<K, V> that) - { - if (this.map == that.map) - return this; - if (IsTop) - return that; - if (that.IsTop || IsBottom) - return this; - if (that.IsBottom) - return that; - - IImmutableMap<K, V> min; - IImmutableMap<K, V> max; - GetMinAndMaxByCount (this.map, that.map, out min, out max); - - IImmutableMap<K, V> union = max; - foreach (K key in min.Keys) { - if (!max.ContainsKey (key)) - union = union.Add (key, min [key]); - else { - V meet = min [key].Meet (max [key]); - union = union.Add (key, meet); - } - } - - return new EnvironmentDomain<K, V> (union); - } - - public bool LessEqual (EnvironmentDomain<K, V> that) - { - if (that.IsTop || IsBottom) - return true; - if (IsTop || that.IsBottom || this.map.Count < that.map.Count) - return false; - - return that.map.Keys.All (key => this.map.ContainsKey (key) && this.map [key].LessEqual (that.map [key])); - } - - public EnvironmentDomain<K, V> ImmutableVersion () - { - return this; - } - - public EnvironmentDomain<K, V> Clone () - { - return this; - } - - public void Dump (TextWriter tw) - { - if (IsTop) - tw.WriteLine ("Top"); - else if (IsBottom) - tw.WriteLine ("Bot"); - else { - this.map.Visit ((k, v) => { - tw.WriteLine ("{0} -> {1}", k, v); - return VisitStatus.ContinueVisit; - }); - } - } - #endregion - - private static bool GetMinAndMaxByCount (IImmutableMap<K, V> a, IImmutableMap<K, V> b, - out IImmutableMap<K, V> min, out IImmutableMap<K, V> max) - { - if (a.Count < b.Count) { - min = a; - max = b; - return true; - } - max = a; - min = b; - return false; - } - - public static EnvironmentDomain<K, V> TopValue (Func<K, int> keyConverter) - { - if (KeyConverter == null) - KeyConverter = keyConverter; - - return new EnvironmentDomain<K, V> (ImmutableIntKeyMap<K, V>.Empty (KeyConverter)); - } - - public EnvironmentDomain<K, V> Add (K key, V value) - { - return new EnvironmentDomain<K, V> (this.map.Add (key, value)); - } - - public EnvironmentDomain<K, V> Remove (K key) - { - return new EnvironmentDomain<K, V> (this.map.Remove (key)); - } - - public bool Contains (K key) - { - return this.map.ContainsKey (key); - } - - public EnvironmentDomain<K, V> Empty () - { - return new EnvironmentDomain<K, V> (this.map.EmptyMap); - } - } -} + class EnvironmentDomain<K, V> : IAbstractDomain<EnvironmentDomain<K, V>> + where V : IAbstractDomain<V> + where K : IEquatable<K> { + readonly IImmutableMapFactory<K, V> factory; + readonly IImmutableMap<K, V> map; + + EnvironmentDomain (IImmutableMapFactory<K, V> factory) + : this (factory, factory.Empty) + { + } + + EnvironmentDomain (IImmutableMap<K, V> map) + : this (map.Factory (), map) + { + } + + EnvironmentDomain (IImmutableMapFactory<K, V> factory, IImmutableMap<K, V> map) + { + this.factory = factory; + this.map = map; + } + + public V this [K key] { get { return map == null ? default(V) : map[key]; } } + + public IEnumerable<K> Keys { get { return map.Keys; } } + + #region IAbstractDomain<EnvironmentDomain<K,V>> Members + + public EnvironmentDomain<K, V> Top { get { return new EnvironmentDomain<K, V> (factory.Empty); } } + + public EnvironmentDomain<K, V> Bottom { get { return new EnvironmentDomain<K, V> (factory, null); } } + + public bool IsTop { get { return map != null && map.Count == 0; } } + + public bool IsBottom { get { return map == null; } } + + public EnvironmentDomain<K, V> Join (EnvironmentDomain<K, V> that) + { + return JoinOrWiden (that, (a, b) => a.Join (b)); + } + + public EnvironmentDomain<K, V> Widen (EnvironmentDomain<K, V> that) + { + return JoinOrWiden (that, (a, b) => a.Widen (b)); + } + + EnvironmentDomain<K, V> JoinOrWiden (EnvironmentDomain<K, V> that, Func<V, V, V> op) + { + if (ReferenceEquals (map, that.map) || IsBottom) + return that; + if (that.IsBottom) + return this; + + IImmutableMap<K, V> min; + IImmutableMap<K, V> max; + GetMinAndMaxByCount (map, that.map, out min, out max); + + var result = min; // intersection of keys + foreach (var key in min.Keys) { + V thatValue; + if (max.TryGetValue (key, out thatValue)) { + var join = op (min[key], thatValue); + if (join.IsBottom) + return Bottom; + + result = join.IsTop ? result.Remove (key) : result.Add (key, join); + } + else + result = result.Remove (key); + } + + return new EnvironmentDomain<K, V> (result); + } + + public EnvironmentDomain<K, V> Join (EnvironmentDomain<K, V> that, bool widening, out bool weaker) + { + //todo: remove it + + weaker = false; + if (map == that.map || IsTop) + return this; + if (that.IsTop) { + weaker = !IsTop; + return that; + } + if (IsBottom) { + weaker = !that.IsBottom; + return that; + } + if (that.IsBottom) + return this; + + IImmutableMap<K, V> min; + IImmutableMap<K, V> max; + GetMinAndMaxByCount (map, that.map, out min, out max); + + var intersect = min; + foreach (var key in min.Keys) { + if (!max.ContainsKey (key)) + intersect = intersect.Remove (key); + else { + bool keyWeaker; + var join = min[key].Join (max[key], widening, out keyWeaker); + if (keyWeaker) { + weaker = true; + intersect = join.IsTop ? intersect.Remove (key) : intersect.Add (key, join); + } + } + } + + weaker |= intersect.Count < map.Count; + return new EnvironmentDomain<K, V> (intersect); + } + + public EnvironmentDomain<K, V> Meet (EnvironmentDomain<K, V> that) + { + if (ReferenceEquals (map, that.map)) + return this; + if (IsTop) + return that; + if (that.IsTop || IsBottom) + return this; + if (that.IsBottom) + return that; + + IImmutableMap<K, V> min; + IImmutableMap<K, V> max; + GetMinAndMaxByCount (map, that.map, out min, out max); + + var union = max; + foreach (var key in min.Keys) { + if (!max.ContainsKey (key)) + union = union.Add (key, min[key]); + else { + var meet = min[key].Meet (max[key]); + union = union.Add (key, meet); + } + } + + return new EnvironmentDomain<K, V> (union); + } + + public bool LessEqual (EnvironmentDomain<K, V> that) + { + bool result; + if (this.TryTrivialLessEqual (that, out result)) + return result; + + if (map.Count < that.map.Count) + return false; + + return that.map.Keys.All (key => map.ContainsKey (key) && map[key].LessEqual (that.map[key])); + } + + public EnvironmentDomain<K, V> ImmutableVersion () + { + return this; + } + + public EnvironmentDomain<K, V> Clone () + { + return this; + } + + public void Dump (TextWriter tw) + { + if (IsTop) + tw.WriteLine ("Top"); + else if (IsBottom) + tw.WriteLine (this.BottomSymbolIfAny ()); + else { + map.Visit ((k, v) => { + tw.WriteLine ("{0} -> {1}", k, v); + return VisitStatus.ContinueVisit; + }); + } + } + + #endregion + + public static EnvironmentDomain<K, V> TopValue (Func<K, int> keyConverter) + { + if (keyConverter == null) + throw new ArgumentNullException ("keyConverter"); + + return new EnvironmentDomain<K, V> (ImmutableIntKeyMap<K, V>.Empty (keyConverter)); + } + + public static EnvironmentDomain<K, V> TopValue () + { + return new EnvironmentDomain<K, V> (ImmutableMap<K, V>.Empty); + } + + public static EnvironmentDomain<K, V> BottomValue (Func<K, int> keyConverter) + { + if (keyConverter == null) + throw new ArgumentNullException ("keyConverter"); + + return new EnvironmentDomain<K, V> (ImmutableIntKeyMap<K, V>.Empty (keyConverter).Factory (), null); + } + + public static EnvironmentDomain<K, V> BottomValue () + { + return new EnvironmentDomain<K, V> (ImmutableMap<K, V>.Empty.Factory (), null); + } + + public EnvironmentDomain<K, V> With (K key, V value) + { + if (value.IsTop) + return Without (key); + + return new EnvironmentDomain<K, V> (map.Add (key, value)); + } + + public EnvironmentDomain<K, V> RefineWith (K key, V value) + { + V old; + if (map.TryGetValue (key, out old)) + value = value.Meet (old); + + return With (key, value); + } + + public EnvironmentDomain<K, V> Without (K key) + { + return new EnvironmentDomain<K, V> (map.Remove (key)); + } + + public bool Contains (K key) + { + return map != null && map.ContainsKey (key); + } + + public bool TryGetValue (K key, out V value) + { + if (map == null) + return false.Without (out value); + + return map.TryGetValue (key, out value); + } + + public EnvironmentDomain<K, V> Empty () + { + return new EnvironmentDomain<K, V> (factory.Empty); + } + + static bool GetMinAndMaxByCount + (IImmutableMap<K, V> a, IImmutableMap<K, V> b, + out IImmutableMap<K, V> min, out IImmutableMap<K, V> max) + { + if (a.Count < b.Count) { + min = a; + max = b; + return true; + } + max = a; + min = b; + return false; + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs index 6e7417cdcf1..8d77aba5c3b 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs @@ -30,167 +30,154 @@ using System; using System.IO; namespace Mono.CodeContracts.Static.Lattices { - /// <summary> - /// Represents domain, where abstract values are disjunct, and their join/meet turns into Top/Bottom respectively - /// </summary> - /// <example> - /// Top - /// / | \ - /// v1 v2 v3 - /// \ | / - /// Bot - /// </example> - /// <typeparam name="T"></typeparam> - struct FlatDomain<T> : IAbstractDomain<FlatDomain<T>>, IEquatable<FlatDomain<T>> - where T : IEquatable<T> { - public static readonly FlatDomain<T> BottomValue = new FlatDomain<T> (Kind.Bottom); - public static readonly FlatDomain<T> TopValue = new FlatDomain<T> (Kind.Top); - - public readonly T Concrete; - private readonly Kind _kind; - - private FlatDomain (Kind kind) - { - this._kind = kind; - this.Concrete = default(T); - } - - public FlatDomain (T value) - { - this._kind = Kind.Concrete; - this.Concrete = value; - } - - public static implicit operator FlatDomain<T> (T value) - { - return new FlatDomain<T> (value); - } - - #region Implementation of IAbstractDomain<FlatDomain<T>> - public bool IsNormal - { - get { return this._kind == Kind.Concrete; } - } - - public FlatDomain<T> Top - { - get { return TopValue; } - } - - public FlatDomain<T> Bottom - { - get { return BottomValue; } - } - - public bool IsTop - { - get { return this._kind == Kind.Top; } - } - - public bool IsBottom - { - get { return this._kind == Kind.Bottom; } - } - - public FlatDomain<T> Join (FlatDomain<T> that, bool widening, out bool weaker) - { - if (IsTop || that.IsBottom) { - weaker = false; - return this; - } - if (that.IsTop) { - weaker = !IsTop; - return that; - } - if (IsBottom) { - weaker = !that.IsBottom; - return that; - } - if (this.Concrete.Equals (that.Concrete)) { - weaker = false; - return that; - } - - weaker = true; - return TopValue; - } - - public FlatDomain<T> Meet (FlatDomain<T> that) - { - if (IsTop || that.IsBottom) - return that; - if (that.IsTop || IsBottom) - return this; - if (this.Concrete.Equals (that.Concrete)) - return that; - - return BottomValue; - } - - public bool LessEqual (FlatDomain<T> that) - { - if (that.IsTop || IsBottom) - return true; - if (IsTop || that.IsBottom) - return false; - - //less equal means equality of values - return this.Concrete.Equals (that.Concrete); - } - - public FlatDomain<T> ImmutableVersion () - { - return this; - } - - public FlatDomain<T> Clone () - { - return this; - } - - public void Dump (TextWriter tw) - { - if (IsTop) - tw.WriteLine ("Top"); - else if (IsBottom) - tw.WriteLine ("Bot"); - else - tw.WriteLine ("<{0}>", this.Concrete); - } - - public override string ToString () - { - if (IsTop) - return "Top"; - if (IsBottom) - return "Bot"; - - return string.Format ("<{0}>", this.Concrete); - } - #endregion - - #region Implementation of IEquatable<FlatDomain<T>> - public bool Equals (FlatDomain<T> that) - { - if (!this.IsNormal) - return this._kind == that._kind; - - if (!that.IsNormal) - return false; - - if (this.Concrete.Equals (that.Concrete)) - return true; - - return false; - } - #endregion - - #region Nested type: Kind - private enum Kind : byte { - Top = 0, - Bottom, - Concrete - } - #endregion - } -} + /// <summary> + /// Represents domain, where abstract values are disjunct, and their join/meet turns into Top/Bottom respectively + /// </summary> + /// <example> + /// Top + /// / | \ + /// v1 v2 v3 + /// \ | / + /// Bot + /// </example> + /// <typeparam name="T"></typeparam> + struct FlatDomain<T> : IAbstractDomain<FlatDomain<T>>, IEquatable<FlatDomain<T>> + where T : IEquatable<T> { + public static readonly FlatDomain<T> BottomValue = new FlatDomain<T> (DomainKind.Bottom); + public static readonly FlatDomain<T> TopValue = new FlatDomain<T> (DomainKind.Top); + + public readonly T Value; + readonly DomainKind state; + + FlatDomain (DomainKind state) + { + this.state = state; + Value = default(T); + } + + public FlatDomain (T value) + { + state = DomainKind.Normal; + Value = value; + } + + public static implicit operator FlatDomain<T> (T value) + { + return new FlatDomain<T> (value); + } + + #region Implementation of IAbstractDomain<FlatDomain<T>> + + public FlatDomain<T> Top { get { return TopValue; } } + + public FlatDomain<T> Bottom { get { return BottomValue; } } + + public bool IsTop { get { return state == DomainKind.Top; } } + + public bool IsBottom { get { return state == DomainKind.Bottom; } } + + public FlatDomain<T> Join (FlatDomain<T> that, bool widening, out bool weaker) + { + if (IsTop || that.IsBottom) { + weaker = false; + return this; + } + if (that.IsTop) { + weaker = !IsTop; + return that; + } + if (IsBottom) { + weaker = !that.IsBottom; + return that; + } + if (Value.Equals (that.Value)) { + weaker = false; + return that; + } + + weaker = true; + return TopValue; + } + + public FlatDomain<T> Widen (FlatDomain<T> that) + { + // no widening - it's finite lattice + + return Join (that); + } + + public FlatDomain<T> Join (FlatDomain<T> that) + { + FlatDomain<T> result; + if (this.TryTrivialJoin (that, out result)) + return result; + + // this and that must be normal here + return Value.Equals (that.Value) ? this : TopValue; + } + + public FlatDomain<T> Meet (FlatDomain<T> that) + { + FlatDomain<T> result; + if (this.TryTrivialMeet (that, out result)) + return result; + + return Value.Equals (that.Value) ? this : BottomValue; + } + + public bool LessEqual (FlatDomain<T> that) + { + bool result; + if (this.TryTrivialLessEqual (that, out result)) + return result; + + return Value.Equals (that.Value); + } + + public FlatDomain<T> ImmutableVersion () + { + return this; + } + + public FlatDomain<T> Clone () + { + return this; + } + + public void Dump (TextWriter tw) + { + if (IsTop) + tw.WriteLine ("Top"); + else if (IsBottom) + tw.WriteLine (this.BottomSymbolIfAny ()); + else + tw.WriteLine ("<{0}>", Value); + } + + public override string ToString () + { + if (IsTop) + return "Top"; + if (IsBottom) + return this.BottomSymbolIfAny (); + + return string.Format ("<{0}>", Value); + } + + #endregion + + public bool Equals (FlatDomain<T> that) + { + if (!this.IsNormal ()) + return state == that.state; + + return that.IsNormal () && Value.Equals (that.Value); + } + } + + enum DomainKind { + Normal = 0, + Top, + Bottom + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs index 9825cb610e7..c63319ac013 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs @@ -29,52 +29,54 @@ using System.IO; namespace Mono.CodeContracts.Static.Lattices { - /// <summary> - /// Represents abstraction of concrete value - /// </summary> - /// <typeparam name="T"></typeparam> - interface IAbstractDomain<T> { - /// <summary> - /// Represents universe set (which holds every value) - /// </summary> - T Top { get; } + /// <summary> + /// Represents abstraction of concrete value + /// </summary> + /// <typeparam name="T"></typeparam> + interface IAbstractDomain<T> { + /// <summary> + /// Represents universe set (which holds every value) + /// </summary> + T Top { get; } - /// <summary> - /// Represents empty set (which holds nothing) - /// </summary> - T Bottom { get; } + /// <summary> + /// Represents empty set (which holds nothing) + /// </summary> + T Bottom { get; } - /// <summary> - /// Is this value a universe set - /// </summary> - bool IsTop { get; } + /// <summary> + /// Is this value a universe set + /// </summary> + bool IsTop { get; } - /// <summary> - /// Is this value an empty set - /// </summary> - bool IsBottom { get; } + /// <summary> + /// Is this value an empty set + /// </summary> + bool IsBottom { get; } - /// <summary> - /// Returns a union of this and that - /// </summary> - /// <param name="that"></param> - /// <param name="widening">Specifies that widening-join operator must be used</param> - /// <param name="weaker">Returns that result domain is weaker than this</param> - /// <returns></returns> - T Join (T that, bool widening, out bool weaker); + /// <summary> + /// Returns a union of this and that + /// </summary> + /// <param name="that"></param> + /// <returns></returns> + T Join (T that); - /// <summary> - /// Returns an intersection of this and that - /// </summary> - /// <param name="that"></param> - /// <returns></returns> - T Meet (T that); + T Join (T that, bool widen, out bool weaker); - bool LessEqual (T that); + T Widen (T that); - T ImmutableVersion (); - T Clone (); + /// <summary> + /// Returns an intersection of this and that + /// </summary> + /// <param name="that"></param> + /// <returns></returns> + T Meet (T that); - void Dump (TextWriter tw); - } -} + bool LessEqual (T that); + + T ImmutableVersion (); + T Clone (); + + void Dump (TextWriter tw); + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs index 95c389a110a..fbb8db2c7d3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs @@ -28,130 +28,128 @@ using System; using System.IO; + using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Lattices { - struct SetDomain<T> : IAbstractDomain<SetDomain<T>> - where T : IEquatable<T> { - public static readonly SetDomain<T> TopValue = new SetDomain<T> (ImmutableSet<T>.Empty ()); - public static readonly SetDomain<T> BottomValue = new SetDomain<T> ((IImmutableSet<T>) null); - - private readonly IImmutableSet<T> set; - - private SetDomain (IImmutableSet<T> set) - { - this.set = set; - } - - public SetDomain (Func<T, int> keyConverter) - { - this.set = ImmutableSet<T>.Empty (keyConverter); - } - - public SetDomain<T> Top - { - get { return TopValue; } - } - - public SetDomain<T> Bottom - { - get { return BottomValue; } - } - - public bool IsTop - { - get - { - if (this.set != null) - return this.set.Count == 0; - - return false; - } - } - - public bool IsBottom - { - get { return this.set == null; } - } - - public SetDomain<T> Join (SetDomain<T> that, bool widening, out bool weaker) - { - if (this.set == that.set) { - weaker = false; - return this; - } - if (IsBottom) { - weaker = !that.IsBottom; - return that; - } - if (that.IsBottom || IsTop) { - weaker = false; - return this; - } - if (that.IsTop) { - weaker = !IsTop; - return that; - } - - IImmutableSet<T> join = this.set.Intersect (that.set); - - weaker = join.Count < this.set.Count; - return new SetDomain<T> (join); - } - - public SetDomain<T> Meet (SetDomain<T> that) - { - if (this.set == that.set || IsBottom || that.IsTop) - return this; - if (that.IsBottom || IsTop) - return that; - - return new SetDomain<T> (this.set.Union (that.set)); - } - - public bool LessEqual (SetDomain<T> that) - { - if (IsBottom) - return true; - if (that.IsBottom) - return false; - - return that.set.IsContainedIn (this.set); - } - - public SetDomain<T> ImmutableVersion () - { - return this; - } - - public SetDomain<T> Clone () - { - return this; - } - - public SetDomain<T> Add (T elem) - { - return new SetDomain<T> (this.set.Add (elem)); - } - - public SetDomain<T> Remove (T elem) - { - return new SetDomain<T> (this.set.Remove (elem)); - } - - public bool Contains (T item) - { - return this.set.Contains (item); - } - - public void Dump (TextWriter tw) - { - if (IsBottom) - tw.WriteLine ("Bot"); - else if (IsTop) - tw.WriteLine ("Top"); - else - this.set.Dump (tw); - } - } -} + struct SetDomain<T> : IAbstractDomain<SetDomain<T>> + where T : IEquatable<T> { + public static readonly SetDomain<T> TopValue = new SetDomain<T> (ImmutableSet<T>.Empty ()); + public static readonly SetDomain<T> BottomValue = new SetDomain<T> ((IImmutableSet<T>) null); + + readonly IImmutableSet<T> set; + + SetDomain (IImmutableSet<T> set) + { + this.set = set; + } + + public SetDomain (Func<T, int> keyConverter) + { + set = ImmutableSet<T>.Empty (keyConverter); + } + + public SetDomain<T> Top { get { return TopValue; } } + + public SetDomain<T> Bottom { get { return BottomValue; } } + + public bool IsTop { get { return set != null && set.Count == 0; } } + + public bool IsBottom { get { return set == null; } } + + public SetDomain<T> Join (SetDomain<T> that) + { + SetDomain<T> result; + if (this.TryTrivialJoin (that, out result)) + return result; + + return new SetDomain<T> (set.Intersect (that.set)); + } + + public SetDomain<T> Join (SetDomain<T> that, bool widening, out bool weaker) + { + if (set == that.set) { + weaker = false; + return this; + } + if (IsBottom) { + weaker = !that.IsBottom; + return that; + } + if (that.IsBottom || IsTop) { + weaker = false; + return this; + } + if (that.IsTop) { + weaker = !IsTop; + return that; + } + + var join = set.Intersect (that.set); + + weaker = join.Count < set.Count; + return new SetDomain<T> (join); + } + + public SetDomain<T> Widen (SetDomain<T> that) + { + //no widening - finite lattice + + return Join (that); + } + + public SetDomain<T> Meet (SetDomain<T> that) + { + SetDomain<T> result; + if (this.TryTrivialMeet (that, out result)) + return result; + + return new SetDomain<T> (set.Union (that.set)); + } + + public bool LessEqual (SetDomain<T> that) + { + if (IsBottom) + return true; + if (that.IsBottom) + return false; + + return that.set.IsContainedIn (set); + } + + public SetDomain<T> ImmutableVersion () + { + return this; + } + + public SetDomain<T> Clone () + { + return this; + } + + public SetDomain<T> With (T elem) + { + return new SetDomain<T> (set.Add (elem)); + } + + public SetDomain<T> Without (T elem) + { + return new SetDomain<T> (set.Remove (elem)); + } + + public bool Contains (T item) + { + return set.Contains (item); + } + + public void Dump (TextWriter tw) + { + if (IsBottom) + tw.WriteLine ("Bot"); + else if (IsTop) + tw.WriteLine ("Top"); + else + set.Dump (tw); + } + } +}
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs index cce8d55541b..d549f607b5e 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs @@ -399,11 +399,11 @@ namespace Mono.CodeContracts.Static.Providers { var binary = node as BinaryExpression; if (binary != null) { if (index == 0) { - nested = binary.Operand1; + nested = binary.Left; return null; } if (index == 1) { - nested = binary.Operand2; + nested = binary.Right; return null; } nested = null; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs index 186f85fb1ce..47f4ece314f 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs @@ -1,11 +1,39 @@ +// +// ICodeProvider.cs +// +// Authors: +// Alexander Chebaturkin (chebaturkin@gmail.com) +// +// Copyright (C) 2012 Alexander Chebaturkin +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using Mono.CodeContracts.Static.AST.Visitors; namespace Mono.CodeContracts.Static.Providers { - interface ICodeProvider<Label> { - Result Decode<CodeVisitor, Data, Result> (Label pc, CodeVisitor visitor, Data data) - where CodeVisitor : IAggregateVisitor<Label, Data, Result>; + interface ICodeProvider<TLabel> { + TResult Decode<TVisitor, TData, TResult> (TLabel pc, TVisitor visitor, TData data) + where TVisitor : IAggregateVisitor<TLabel, TData, TResult>; - bool Next (Label current, out Label nextLabel); - int GetILOffset (Label current); + bool Next (TLabel current, out TLabel nextLabel); + int GetILOffset (TLabel current); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs index 263f5d6d990..a65a97b202d 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs @@ -33,6 +33,8 @@ using Mono.CodeContracts.Static.DataStructures; namespace Mono.CodeContracts.Static.Providers { interface IMetaDataProvider { + TypeNode System_Single { get; } + TypeNode System_Double { get; } TypeNode System_Int32 { get; } TypeNode System_String { get; } TypeNode System_Boolean { get; } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs index a78dfbec344..cca82427192 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs @@ -280,24 +280,25 @@ namespace Mono.CodeContracts.Static.Providers { if (method.Parameters == null || method.Parameters.Count == 0) return true; if (method.Parameters.Count == 1) - return method.Parameters [0].Type == CoreSystemTypes.Instance.TypeBoolean; + return Equal(method.Parameters [0].Type, CoreSystemTypes.Instance.TypeBoolean); return false; } #endregion #region Implementation of IMetaDataProvider<Local,Parameter,Method,FieldReference,PropertyReference,EventReference,TypeNode,Attribute,AssemblyNode> - public TypeNode System_Double - { - get { return CoreSystemTypes.Instance.TypeDouble; } - } - public TypeNode System_Single + public TypeNode System_Single + { + get { return CoreSystemTypes.Instance.TypeSingle; } + } + + public TypeNode System_Double { - get { return CoreSystemTypes.Instance.TypeSingle; } + get { return CoreSystemTypes.Instance.TypeDouble; } } - public TypeNode System_Type + public TypeNode System_Type { get { return CoreSystemTypes.Instance.TypeSystemType; } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs index 0b40151df5d..7fb05e93c21 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.Analysis.Drivers; using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { static class AssertionFinder { @@ -55,23 +56,16 @@ namespace Mono.CodeContracts.Static.Proving { object assertStats; foreach (AssertionObligation obl in GetAssertions (driver, out assertStats)) { - ProofOutcome outcome = facts.IsTrue (obl.Apc, BoxedExpression.For (driver.ContextProvider.ExpressionContext.Refine (obl.Apc, obl.Condition), driver.ExpressionDecoder)); + FlatDomain<bool> outcome = facts.IsTrue (obl.Apc, BoxedExpression.For (driver.ContextProvider.ExpressionContext.Refine (obl.Apc, obl.Condition), driver.ExpressionDecoder)); string pc = obl.Apc.ToString (); - switch (outcome) { - case ProofOutcome.Top: - proofResults.Add ("Assertion at point " + pc + " is unproven"); - break; - case ProofOutcome.True: - proofResults.Add ("Assertion at point " + pc + " is true"); - break; - case ProofOutcome.False: - proofResults.Add ("Assertion at point " + pc + " is false"); - break; - case ProofOutcome.Bottom: - proofResults.Add ("Assertion at point " + pc + " is unreachable"); - break; - } + + if (outcome.IsNormal ()) + proofResults.Add (string.Format ("Assertion at point {0} is {1}", pc, outcome.IsTrue () ? "true" : "false")); + else if (outcome.IsTop) + proofResults.Add ("Assertion at point " + pc + " is unproven"); + else + proofResults.Add("Assertion at point " + pc + " is unreachable"); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs index 4ce37d4f819..68e943d0888 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs @@ -30,6 +30,7 @@ using System; using Mono.CodeContracts.Static.Analysis; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { class BasicFacts<Expression, Variable> : IFactQuery<BoxedExpression, Variable> { @@ -45,12 +46,12 @@ namespace Mono.CodeContracts.Static.Proving { } #region Implementation of IFactBase<Variable> - public ProofOutcome IsNull (APC pc, Variable variable) + public FlatDomain<bool> IsNull(APC pc, Variable variable) { return this.FactBase.IsNull (pc, variable); } - public ProofOutcome IsNonNull (APC pc, Variable variable) + public FlatDomain<bool> IsNonNull(APC pc, Variable variable) { return this.FactBase.IsNonNull (pc, variable); } @@ -77,56 +78,53 @@ namespace Mono.CodeContracts.Static.Proving { #endregion #region Implementation of IFactQuery<BoxedExpression,Variable> - public virtual ProofOutcome IsNull (APC pc, BoxedExpression expr) + public virtual FlatDomain<bool> IsNull(APC pc, BoxedExpression expr) { Variable v; if (TryVariable (expr, out v)) { - ProofOutcome outcome = this.FactBase.IsNull (pc, v); - if (outcome != ProofOutcome.Top) + FlatDomain<bool> outcome = this.FactBase.IsNull(pc, v); + if (!outcome.IsTop) return outcome; } return ProofOutcome.Top; } - public virtual ProofOutcome IsNonNull (APC pc, BoxedExpression expr) + public virtual FlatDomain<bool> IsNonNull(APC pc, BoxedExpression expr) { Variable v; if (TryVariable (expr, out v)) { - ProofOutcome outcome = this.FactBase.IsNonNull (pc, v); - if (outcome != ProofOutcome.Top) + FlatDomain<bool> outcome = this.FactBase.IsNonNull(pc, v); + if (!outcome.IsTop) return outcome; } return ProofOutcome.Top; } - public ProofOutcome IsTrue (APC pc, BoxedExpression expr) + public FlatDomain<bool> IsTrue(APC pc, BoxedExpression expr) { return IsNonZero (pc, expr); } - public ProofOutcome IsTrueImply (APC pc, LispList<BoxedExpression> positiveAssumptions, LispList<BoxedExpression> negativeAssumptions, BoxedExpression goal) + public FlatDomain<bool> IsTrueImply(APC pc, Sequence<BoxedExpression> positiveAssumptions, Sequence<BoxedExpression> negativeAssumptions, BoxedExpression goal) { - ProofOutcome outcome = IsTrue (pc, goal); - switch (outcome) { - case ProofOutcome.True: - case ProofOutcome.Bottom: - return outcome; - default: - return ProofOutcome.Top; - } + FlatDomain<bool> outcome = IsTrue(pc, goal); + if (outcome.IsTrue() || outcome.IsBottom) + return outcome; + + return ProofOutcome.Top; } - public ProofOutcome IsGreaterEqualToZero (APC pc, BoxedExpression expr) + public FlatDomain<bool> IsGreaterEqualToZero(APC pc, BoxedExpression expr) { return ProofOutcome.Top; } - public ProofOutcome IsLessThan (APC pc, BoxedExpression expr, BoxedExpression right) + public FlatDomain<bool> IsLessThan(APC pc, BoxedExpression expr, BoxedExpression right) { return ProofOutcome.Top; } - public ProofOutcome IsNonZero (APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNonZero(APC pc, BoxedExpression expr) { return IsNonNull (pc, expr); } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs index a391b6f38f2..003be5f46ba 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs @@ -37,6 +37,7 @@ using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding; using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Providers; namespace Mono.CodeContracts.Static.Proving { internal abstract class BoxedExpression { @@ -75,7 +76,7 @@ namespace Mono.CodeContracts.Static.Proving { get { throw new InvalidOperationException (); } } - public virtual bool IsSizeof + public virtual bool IsSizeof { get { return false; } } @@ -156,6 +157,11 @@ namespace Mono.CodeContracts.Static.Proving { return false; } + public virtual bool Sizeof (out int size) + { + return false.Without (out size); + } + public virtual bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type) { expr = null; @@ -188,6 +194,11 @@ namespace Mono.CodeContracts.Static.Proving { return new VariableExpression (var); } + public static BoxedExpression Const (object value, TypeNode type) + { + return new ConstantExpression (value, type); + } + public static BoxedExpression For<Variable, Expression> (Expression external, IFullExpressionDecoder<Variable, Expression> decoder) where Expression : IEquatable<Expression> { @@ -210,7 +221,7 @@ namespace Mono.CodeContracts.Static.Proving { object variable; if (decoder.IsVariable (expr, out variable)) { - LispList<PathElement> variableAccessPath = decoder.GetVariableAccessPath (expr); + Sequence<PathElement> variableAccessPath = decoder.GetVariableAccessPath (expr); return new VariableExpression (variable, variableAccessPath); } @@ -236,6 +247,16 @@ namespace Mono.CodeContracts.Static.Proving { return new BinaryExpression (bop, Convert (left, decoder), Convert (right, decoder)); } + public static BoxedExpression Binary (BinaryOperator bop, BoxedExpression left, BoxedExpression right) + { + return new BinaryExpression (bop, left, right); + } + + public static BoxedExpression Unary (UnaryOperator op, BoxedExpression arg) + { + return new UnaryExpression (op, arg); + } + #region Nested type: AssertExpression public class AssertExpression : ContractExpression { public AssertExpression (BoxedExpression condition, EdgeTag tag, APC pc) : base (condition, tag, pc) @@ -1347,7 +1368,13 @@ namespace Mono.CodeContracts.Static.Proving { public override bool IsSizeof { get { return true; } - } + } + + public override bool Sizeof (out int size) + { + size = SizeAsConstant; + return size >= 0; + } public override void AddFreeVariables (HashSet<BoxedExpression> set) { @@ -1586,17 +1613,17 @@ namespace Mono.CodeContracts.Static.Proving { public readonly object VarType; public VariableExpression (object var) - : this (var, (LispList<PathElement>) null) + : this (var, (Sequence<PathElement>) null) { } - public VariableExpression (object var, LispList<PathElement> path) + public VariableExpression (object var, Sequence<PathElement> path) { this.UnderlyingVar = var; this.Path = path != null ? path.AsEnumerable ().ToArray () : null; } - public VariableExpression (object var, LispList<PathElement> path, object type) + public VariableExpression (object var, Sequence<PathElement> path, object type) : this (var, path) { this.VarType = type; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs index 5c82f79b1dc..3c579d036b7 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs @@ -28,6 +28,9 @@ using System; +using Mono.CodeContracts.Static.AST; +using Mono.CodeContracts.Static.DataStructures; + namespace Mono.CodeContracts.Static.Proving { static class BoxedExpressionExtensions @@ -52,5 +55,113 @@ namespace Mono.CodeContracts.Static.Proving } return false; } + + public static bool IsConstantBool(this BoxedExpression e, out bool result) + { + if (e.IsConstant && e.Constant is bool) + return true.With ((bool) e.Constant, out result); + + return false.Without (out result); + } + + public static bool IsTrivialCondition(this BoxedExpression e, out bool result) + { + int value; + if (e.IsConstantIntOrNull (out value)) + return true.With (value != 0, out result); + if (e.IsConstantBool (out result)) + return true; + + BinaryOperator bop; + BoxedExpression left; + BoxedExpression right; + if (e.IsBinaryExpression (out bop, out left, out right)) { + int l, r; + var isLeftInt = left.IsConstantIntOrNull (out l); + var isRightInt = right.IsConstantIntOrNull (out r); + if (bop == BinaryOperator.Ceq) { + if (isLeftInt && isRightInt) + return true.With (l == r, out result); + bool leftResult; + if (isRightInt && r == 0 && left.IsTrivialCondition (out leftResult)) + return true.With (!leftResult, out result); + + bool rightResult; + if (isLeftInt && l == 0 && right.IsTrivialCondition (out rightResult)) + return true.With (!rightResult, out result); + + return false.Without (out result); + } + + switch (bop) { + case BinaryOperator.Add: + case BinaryOperator.Add_Ovf: + case BinaryOperator.Add_Ovf_Un: + return true.With (l + r != 0, out result); + case BinaryOperator.And: + return true.With ((l & r) != 0, out result); + case BinaryOperator.Cne_Un: + return true.With (l != r, out result); + case BinaryOperator.Cge: + return true.With (l >= r, out result); + case BinaryOperator.Cge_Un: + return true.With ((uint) l >= (uint) r, out result); + case BinaryOperator.Cgt: + return true.With (l > r, out result); + case BinaryOperator.Cgt_Un: + return true.With ((uint) l > (uint) r, out result); + case BinaryOperator.Cle: + return true.With (l <= r, out result); + case BinaryOperator.Cle_Un: + return true.With ((uint) l <= (uint) r, out result); + case BinaryOperator.Clt: + return true.With (l < r, out result); + case BinaryOperator.Clt_Un: + return true.With ((uint) l < (uint) r, out result); + case BinaryOperator.Div: + if (r == 0) + return false.Without (out result); + return true.With (l / r != 0, out result); + case BinaryOperator.Div_Un: + if (r == 0) + return false.Without (out result); + return true.With ((uint) l / (uint) r != 0, out result); + case BinaryOperator.LogicalAnd: + return true.With (l != 0 && r != 0, out result); + case BinaryOperator.LogicalOr: + return true.With (l != 0 || r != 0, out result); + case BinaryOperator.Mul: + case BinaryOperator.Mul_Ovf: + case BinaryOperator.Mul_Ovf_Un: + return true.With (l * r != 0, out result); + case BinaryOperator.Or: + return true.With ((l | r) != 0, out result); + case BinaryOperator.Rem: + if (r == 0) + return false.Without (out result); + return true.With (l % r != 0, out result); + case BinaryOperator.Rem_Un: + if (r == 0) + return false.Without (out result); + return true.With (((uint) l) % ((uint) r) != 0, out result); + case BinaryOperator.Shl: + return true.With (l << r != 0, out result); + case BinaryOperator.Shr: + return true.With (l >> r != 0, out result); + case BinaryOperator.Shr_Un: + return true.With (((uint) l) >> r != 0, out result); + case BinaryOperator.Sub: + case BinaryOperator.Sub_Ovf: + case BinaryOperator.Sub_Ovf_Un: + return true.With (l - r != 0, out result); + case BinaryOperator.Xor: + return true.With ((l ^ r) != 0, out result); + default: + return false.Without (out result); + } + } + + return false.Without (out result); + } } }
\ No newline at end of file diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ComposedFactQuery.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ComposedFactQuery.cs index ff5668b7519..a31947941bd 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ComposedFactQuery.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ComposedFactQuery.cs @@ -32,6 +32,7 @@ using System.Linq; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { @@ -45,7 +46,7 @@ namespace Mono.CodeContracts.Static.Proving this.isUnreachable = isUnreachable; } - public void Add(IFactQuery<BoxedExpression, Variable> item ) + public void Add(IFactQuery<BoxedExpression, Variable> item) { if (item == null) return; @@ -53,14 +54,14 @@ namespace Mono.CodeContracts.Static.Proving } #region Implementation of IFactBase<Variable> - public ProofOutcome IsNull(APC pc, Variable variable) + public FlatDomain<bool> IsNull(APC pc, Variable variable) { - return elements.Select(fact => fact.IsNull(pc, variable)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsNull(pc, variable)).FirstOrDefault(factResult => !factResult.IsTop); } - public ProofOutcome IsNonNull(APC pc, Variable variable) + public FlatDomain<bool> IsNonNull(APC pc, Variable variable) { - return elements.Select(fact => fact.IsNonNull(pc, variable)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsNonNull(pc, variable)).FirstOrDefault(factResult => !factResult.IsTop); } public bool IsUnreachable(APC pc) @@ -72,49 +73,37 @@ namespace Mono.CodeContracts.Static.Proving #endregion #region Implementation of IFactQuery<BoxedExpression,Variable> - public ProofOutcome IsNull(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNull(APC pc, BoxedExpression expr) { - return elements.Select (fact => fact.IsNull (pc, expr)).FirstOrDefault (factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsNull(pc, expr)).FirstOrDefault(factResult => !factResult.IsTop); } - public ProofOutcome IsNonNull(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNonNull(APC pc, BoxedExpression expr) { - return elements.Select(fact => fact.IsNonNull(pc, expr)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsNonNull(pc, expr)).FirstOrDefault(factResult => !factResult.IsTop); } - public ProofOutcome IsTrue(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsTrue(APC pc, BoxedExpression expr) { - ProofOutcome res = ProofOutcome.Top; + FlatDomain<bool> res = ProofOutcome.Top; foreach (var factQuery in elements) { var outcome = factQuery.IsTrue (pc, expr); - switch (outcome) { - case ProofOutcome.True: - case ProofOutcome.Bottom: - return outcome; - case ProofOutcome.False: - res = outcome; - continue; - default: - continue; - } + + if (outcome.IsTrue() || outcome.IsBottom) + return outcome; + if (outcome.IsFalse ()) + res = outcome; } - if (res != ProofOutcome.Top) + if (!res.IsTop) return res; BinaryOperator op; BoxedExpression left; BoxedExpression right; if (expr.IsBinaryExpression (out op, out left, out right)) { - if ((op == BinaryOperator.Ceq || op == BinaryOperator.Cobjeq) && this.IsRelational (left) && this.IsNull (pc, right) == ProofOutcome.True) { + if ((op == BinaryOperator.Ceq || op == BinaryOperator.Cobjeq) && this.IsRelational (left) && this.IsNull (pc, right).IsTrue ()) { var outcome = this.IsTrue (pc, left); - switch (outcome) { - case ProofOutcome.False: - return ProofOutcome.True; - case ProofOutcome.True: - return ProofOutcome.False; - default: - return outcome; - } + return outcome.Negate (); } int leftInt; int rightInt; @@ -124,14 +113,7 @@ namespace Mono.CodeContracts.Static.Proving if (expr.IsUnary && expr.UnaryOperator == UnaryOperator.Not) { var outcome = this.IsTrue (pc, expr.UnaryArgument); - switch (outcome) { - case ProofOutcome.False: - return ProofOutcome.True; - case ProofOutcome.True: - return ProofOutcome.False; - default: - return outcome; - } + return outcome.Negate (); } return ProofOutcome.Top; @@ -160,24 +142,24 @@ namespace Mono.CodeContracts.Static.Proving return false; } - public ProofOutcome IsTrueImply(APC pc, LispList<BoxedExpression> positiveAssumptions, LispList<BoxedExpression> negativeAssumptions, BoxedExpression goal) + public FlatDomain<bool> IsTrueImply(APC pc, Sequence<BoxedExpression> positiveAssumptions, Sequence<BoxedExpression> negativeAssumptions, BoxedExpression goal) { - return elements.Select(fact => fact.IsTrueImply(pc, positiveAssumptions, negativeAssumptions, goal)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsTrueImply(pc, positiveAssumptions, negativeAssumptions, goal)).FirstOrDefault(factResult => !factResult.IsTop); } - public ProofOutcome IsGreaterEqualToZero(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsGreaterEqualToZero(APC pc, BoxedExpression expr) { - return elements.Select(fact => fact.IsGreaterEqualToZero(pc, expr)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsGreaterEqualToZero(pc, expr)).FirstOrDefault(factResult => !factResult.IsTop); } - public ProofOutcome IsLessThan(APC pc, BoxedExpression expr, BoxedExpression right) + public FlatDomain<bool> IsLessThan(APC pc, BoxedExpression expr, BoxedExpression right) { - return elements.Select(fact => fact.IsLessThan(pc, expr, right)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsLessThan(pc, expr, right)).FirstOrDefault(factResult => !factResult.IsTop); } - public ProofOutcome IsNonZero(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNonZero(APC pc, BoxedExpression expr) { - return elements.Select(fact => fact.IsNonZero(pc, expr)).FirstOrDefault(factResult => factResult != ProofOutcome.Top); + return elements.Select(fact => fact.IsNonZero(pc, expr)).FirstOrDefault(factResult => !factResult.IsTop); } #endregion } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs index 2d2a99a540d..5379a131955 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs @@ -26,108 +26,101 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -using System.Linq; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { - class ConstantPropagationFactQuery<Variable> : IFactQuery<BoxedExpression, Variable> - { + class ConstantPropagationFactQuery<Variable> : IFactQuery<BoxedExpression, Variable> { #region Implementation of IFactBase<Variable> - public ProofOutcome IsNull(APC pc, Variable variable) - { - return ProofOutcome.Top; - } + public bool IsUnreachable(APC pc) + { + return false; + } - public ProofOutcome IsNonNull(APC pc, Variable variable) + public FlatDomain<bool> IsNull(APC pc, Variable variable) { return ProofOutcome.Top; } - public bool IsUnreachable(APC pc) + public FlatDomain<bool> IsNonNull(APC pc, Variable variable) { - return false; + return ProofOutcome.Top; } #endregion #region Implementation of IFactQuery<BoxedExpression,Variable> - public ProofOutcome IsNull(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNull(APC pc, BoxedExpression expr) { int num; if (expr.IsConstantIntOrNull (out num)) - return IsTrueOrTop (num == 0); + return (num == 0).ToTrueOrTop (); return ProofOutcome.Top; } - public ProofOutcome IsNonNull(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNonNull(APC pc, BoxedExpression expr) { int num; if (expr.IsConstantIntOrNull (out num)) - return IsTrueOrTop (num != 0); + return (num != 0).ToTrueOrTop (); return ProofOutcome.Top; } - public ProofOutcome IsTrue(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsTrue(APC pc, BoxedExpression expr) { int num; if (expr.IsConstantIntOrNull (out num)) - return IsTrueOrTop (num != 0); + return (num != 0).ToTrueOrTop (); return ConstantFact (expr); } - - public ProofOutcome IsTrueImply(APC pc, LispList<BoxedExpression> positiveAssumptions, LispList<BoxedExpression> negativeAssumptions, BoxedExpression goal) + public FlatDomain<bool> IsTrueImply(APC pc, Sequence<BoxedExpression> positiveAssumptions, Sequence<BoxedExpression> negativeAssumptions, BoxedExpression goal) { UnaryOperator op; BoxedExpression arg; while (goal.IsUnaryExpression (out op, out arg) && op.IsConversionOperator ()) goal = arg; - if (positiveAssumptions.AsEnumerable ().Any (positiveAssumption => positiveAssumptions.Equals (goal))) + if (positiveAssumptions.Any(assumption => assumption.Equals (goal))) return ProofOutcome.True; return ProofOutcome.Top; } - public ProofOutcome IsGreaterEqualToZero(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsGreaterEqualToZero(APC pc, BoxedExpression expr) { int num; if (expr.IsConstantIntOrNull(out num)) - return IsTrueOrTop(num >= 0); + return (num >= 0).ToTrueOrTop (); return ProofOutcome.Top; } - public ProofOutcome IsLessThan(APC pc, BoxedExpression left, BoxedExpression right) + public FlatDomain<bool> IsLessThan(APC pc, BoxedExpression left, BoxedExpression right) { int l; int r; if (left.IsConstantIntOrNull(out l) && right.IsConstantIntOrNull(out r)) - return IsTrueOrTop (l < r); + return (l < r).ToTrueOrTop (); return ProofOutcome.Top; } - public ProofOutcome IsNonZero(APC pc, BoxedExpression expr) + public FlatDomain<bool> IsNonZero(APC pc, BoxedExpression expr) { int num; if (expr.IsConstantIntOrNull(out num)) - return IsTrueOrTop (num != 0); + return (num != 0).ToTrueOrTop (); return ProofOutcome.Top; } - private static ProofOutcome IsTrueOrTop(bool condition) - { - return condition ? ProofOutcome.True : ProofOutcome.Top; - } - - private ProofOutcome ConstantFact(BoxedExpression expr) + private static FlatDomain<bool> ConstantFact(BoxedExpression expr) { BinaryOperator op; BoxedExpression left; @@ -142,65 +135,42 @@ namespace Mono.CodeContracts.Static.Proving if (leftIsInt || rightIsInt) { if (leftIsInt && rightIsInt) { switch (op) { - case BinaryOperator.Add: - return IsTrueOrTop ((l + r) != 0); - case BinaryOperator.And: - return IsTrueOrTop((l & r) != 0); - case BinaryOperator.Ceq: - return IsTrueOrTop(l == r); - case BinaryOperator.Cobjeq: - return ProofOutcome.Top; - case BinaryOperator.Cne_Un: - return IsTrueOrTop(l != r); - case BinaryOperator.Cge: - return IsTrueOrTop(l >= r); - case BinaryOperator.Cge_Un: - return IsTrueOrTop((uint)l >= (uint)r); - case BinaryOperator.Cgt: - return IsTrueOrTop(l > r); - case BinaryOperator.Cgt_Un: - return IsTrueOrTop((uint)l > (uint)r); - case BinaryOperator.Cle: - return IsTrueOrTop(l <= r); - case BinaryOperator.Cle_Un: - return IsTrueOrTop((uint)l <= (uint)r); - case BinaryOperator.Clt: - return IsTrueOrTop(l < r); - case BinaryOperator.Clt_Un: - return IsTrueOrTop((uint)l < (uint)r); - case BinaryOperator.Div: - return IsTrueOrTop(r != 0 && ((l / r) != 0)); - case BinaryOperator.LogicalAnd: - return IsTrueOrTop(l != 0 && r != 0); - case BinaryOperator.LogicalOr: - return IsTrueOrTop(l != 0 || r != 0); - case BinaryOperator.Mul: - return IsTrueOrTop(l * r != 0); - case BinaryOperator.Or: - return IsTrueOrTop((l | r) != 0); - case BinaryOperator.Rem: - return IsTrueOrTop(r != 0 && (l % r != 0)); - case BinaryOperator.Shl: - return IsTrueOrTop(l << r != 0); - case BinaryOperator.Shr: - return IsTrueOrTop(l >> r != 0); - case BinaryOperator.Sub: - return IsTrueOrTop(l - r != 0); - case BinaryOperator.Xor: - return IsTrueOrTop((l ^ r) != 0); + case BinaryOperator.Add: return ((l + r) != 0).ToTrueOrTop (); + case BinaryOperator.And: return ((l & r) != 0).ToTrueOrTop (); + case BinaryOperator.Ceq: return (l == r).ToTrueOrTop (); + case BinaryOperator.Cobjeq: return ProofOutcome.Top; + case BinaryOperator.Cne_Un: return (l != r).ToTrueOrTop (); + case BinaryOperator.Cge: return (l >= r).ToTrueOrTop (); + case BinaryOperator.Cge_Un: return ((uint)l >= (uint)r).ToTrueOrTop (); + case BinaryOperator.Cgt: return (l > r).ToTrueOrTop (); + case BinaryOperator.Cgt_Un: return ((uint)l > (uint)r).ToTrueOrTop (); + case BinaryOperator.Cle: return (l <= r).ToTrueOrTop (); + case BinaryOperator.Cle_Un: return ((uint)l <= (uint)r).ToTrueOrTop (); + case BinaryOperator.Clt: return (l < r).ToTrueOrTop (); + case BinaryOperator.Clt_Un: return ((uint)l < (uint)r).ToTrueOrTop (); + case BinaryOperator.Div: return (r != 0 && ((l / r) != 0)).ToTrueOrTop (); + case BinaryOperator.LogicalAnd: return (l != 0 && r != 0).ToTrueOrTop (); + case BinaryOperator.LogicalOr: return (l != 0 || r != 0).ToTrueOrTop (); + case BinaryOperator.Mul: return (l * r != 0).ToTrueOrTop (); + case BinaryOperator.Or: return ((l | r) != 0).ToTrueOrTop (); + case BinaryOperator.Rem: return (r != 0 && (l % r != 0)).ToTrueOrTop (); + case BinaryOperator.Shl: return (l << r != 0).ToTrueOrTop (); + case BinaryOperator.Shr: return (l >> r != 0).ToTrueOrTop (); + case BinaryOperator.Sub: return (l - r != 0).ToTrueOrTop (); + case BinaryOperator.Xor: return ((l ^ r) != 0).ToTrueOrTop (); } } if (op == BinaryOperator.Ceq && (leftIsInt && l == 0 || rightIsInt && r == 0)) - return this.ConstantFact (left).Negate (); + return ConstantFact (left).Negate (); } else if (left.IsConstant && right.IsConstant) { var lConst = left.Constant; var rConst = right.Constant; switch (op) { case BinaryOperator.Cobjeq: - return lConst == null ? IsTrueOrTop (rConst == null) : IsTrueOrTop (lConst.Equals (rConst)); + return lConst == null ? (rConst == null).ToTrueOrTop () : lConst.Equals (rConst).ToTrueOrTop (); case BinaryOperator.Cne_Un: - return lConst == null ? IsTrueOrTop (rConst != null) : IsTrueOrTop (!lConst.Equals (rConst)); + return lConst == null ? (rConst != null).ToTrueOrTop () : (!lConst.Equals (rConst)).ToTrueOrTop (); } } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs index e626d6795af..1b5958e7385 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs @@ -27,11 +27,13 @@ // using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { - interface IFactBase<Variable> { - ProofOutcome IsNull (APC pc, Variable variable); - ProofOutcome IsNonNull (APC pc, Variable variable); - bool IsUnreachable (APC pc); + interface IFactBase<in Variable> { + bool IsUnreachable(APC pc); + + FlatDomain<bool> IsNull (APC pc, Variable variable); + FlatDomain<bool> IsNonNull(APC pc, Variable variable); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs index ad641e7b6cc..136ce3cfe93 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs @@ -28,15 +28,16 @@ using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataStructures; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { interface IFactQuery<Expression, Variable> : IFactBase<Variable> { - ProofOutcome IsNull (APC pc, Expression expr); - ProofOutcome IsNonNull (APC pc, Expression expr); - ProofOutcome IsTrue (APC pc, Expression expr); - ProofOutcome IsTrueImply (APC pc, LispList<Expression> positiveAssumptions, LispList<Expression> negativeAssumptions, Expression goal); - ProofOutcome IsGreaterEqualToZero (APC pc, Expression expr); - ProofOutcome IsLessThan (APC pc, Expression expr, Expression right); - ProofOutcome IsNonZero (APC pc, Expression expr); + FlatDomain<bool> IsNull(APC pc, Expression expr); + FlatDomain<bool> IsNonNull(APC pc, Expression expr); + FlatDomain<bool> IsTrue(APC pc, Expression expr); + FlatDomain<bool> IsTrueImply(APC pc, Sequence<Expression> positiveAssumptions, Sequence<Expression> negativeAssumptions, Expression goal); + FlatDomain<bool> IsGreaterEqualToZero(APC pc, Expression expr); + FlatDomain<bool> IsLessThan(APC pc, Expression expr, Expression right); + FlatDomain<bool> IsNonZero(APC pc, Expression expr); } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs index 0f1037e7cc9..709a85a5cf3 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs @@ -29,7 +29,9 @@ using System; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.Analysis; +using Mono.CodeContracts.Static.Analysis.Numerical; using Mono.CodeContracts.Static.ControlFlow; +using Mono.CodeContracts.Static.Lattices; namespace Mono.CodeContracts.Static.Proving { class SimpleLogicInference<Expression, Variable> : BasicFacts<Expression, Variable> { @@ -38,12 +40,12 @@ namespace Mono.CodeContracts.Static.Proving { { } - public override ProofOutcome IsNull (APC pc, BoxedExpression expr) + public override FlatDomain<bool> IsNull(APC pc, BoxedExpression expr) { Variable v; if (TryVariable (expr, out v)) { - ProofOutcome proofOutcome = this.FactBase.IsNull (pc, v); - if (proofOutcome != ProofOutcome.Top) + FlatDomain<bool> proofOutcome = this.FactBase.IsNull(pc, v); + if (!proofOutcome.IsTop) return proofOutcome; } @@ -53,34 +55,32 @@ namespace Mono.CodeContracts.Static.Proving { return ProofOutcome.True; if (constant is string) return ProofOutcome.False; - var convertible = constant as IConvertible; - if (convertible != null) { - try { - return (convertible.ToInt64 (null) == 0) ? ProofOutcome.True : ProofOutcome.False; - } catch { - return ProofOutcome.Top; - } - } + + long? longValue = constant.ConvertToLong (); + if (longValue.HasValue) + return longValue == 0 ? ProofOutcome.True : ProofOutcome.False; + + return ProofOutcome.Top; } BinaryOperator op; BoxedExpression left; BoxedExpression right; if (expr.IsBinaryExpression (out op, out left, out right)) { - if ((op == BinaryOperator.Ceq || op == BinaryOperator.Cobjeq) && IsNull (pc, right) == ProofOutcome.True) + if ((op == BinaryOperator.Ceq || op == BinaryOperator.Cobjeq) && IsNull (pc, right).IsTrue ()) return IsNonNull (pc, left); - if (op == BinaryOperator.Cne_Un && IsNull (pc, right) == ProofOutcome.True) + if (op == BinaryOperator.Cne_Un && IsNull (pc, right).IsTrue ()) return IsNull (pc, left); } return ProofOutcome.Top; } - public override ProofOutcome IsNonNull (APC pc, BoxedExpression expr) + public override FlatDomain<bool> IsNonNull(APC pc, BoxedExpression expr) { Variable v; if (TryVariable (expr, out v)) { - ProofOutcome proofOutcome = this.FactBase.IsNonNull (pc, v); - if (proofOutcome != ProofOutcome.Top) + FlatDomain<bool> proofOutcome = this.FactBase.IsNonNull(pc, v); + if (!proofOutcome.IsTop) return proofOutcome; } @@ -90,23 +90,21 @@ namespace Mono.CodeContracts.Static.Proving { return ProofOutcome.False; if (constant is string) return ProofOutcome.True; - var convertible = constant as IConvertible; - if (convertible != null) { - try { - return (convertible.ToInt64 (null) == 0) ? ProofOutcome.False : ProofOutcome.True; - } catch { - return ProofOutcome.Top; - } - } + + long? longValue = constant.ConvertToLong(); + if (longValue.HasValue) + return longValue != 0 ? ProofOutcome.True : ProofOutcome.False; + + return ProofOutcome.Top; } BinaryOperator op; BoxedExpression left; BoxedExpression right; if (expr.IsBinaryExpression (out op, out left, out right)) { - if ((op == BinaryOperator.Ceq || op == BinaryOperator.Cobjeq) && IsNull (pc, right) == ProofOutcome.True) + if ((op == BinaryOperator.Ceq || op == BinaryOperator.Cobjeq) && IsNull (pc, right).IsTrue ()) return IsNull (pc, left); - if (op == BinaryOperator.Cne_Un && IsNull (pc, right) == ProofOutcome.True) + if (op == BinaryOperator.Cne_Un && IsNull (pc, right).IsTrue ()) return IsNonNull (pc, left); } return ProofOutcome.Top; diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs index 22bf9877c13..1e664f502fc 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs @@ -32,6 +32,7 @@ using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.Analysis.Drivers; using Mono.CodeContracts.Static.Analysis.HeapAnalysis; using Mono.CodeContracts.Static.Analysis.NonNull; +using Mono.CodeContracts.Static.Analysis.Numerical; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.Providers; using Mono.CodeContracts.Static.Proving; @@ -60,7 +61,11 @@ namespace Mono.CodeContracts.Static { DebugOptions.Debug = this.options.ShowDebug; - this.analyzers = new Dictionary<string, IMethodAnalysis> {{"non-null", new NonNullAnalysisFacade ()}}; + this.analyzers = new Dictionary<string, IMethodAnalysis> { + {"non-null", new NonNullAnalysisFacade ()}, + {"arithmetic", new Analysers.Arithmetic ()} + }; + this.analysis_driver = new CodeContractsAnalysisDriver<IMethodResult<SymbolicValue>> ( new BasicAnalysisDriver (MetaDataProvider.Instance, CodeContractDecoder.Instance)); diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs index 2d4122573c5..d14ad82e38d 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs @@ -26,11 +26,46 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.ComponentModel; + +using Mono.CodeContracts.Static.Lattices; + namespace Mono.CodeContracts.Static { - public enum ProofOutcome { - Top, - True, - False, - Bottom - } + static class ProofOutcome { + /// <summary> + /// Can be true or false. + /// </summary> + public static readonly FlatDomain<bool> Top = FlatDomain<bool>.TopValue; + /// <summary> + /// Unreachable. + /// </summary> + public static readonly FlatDomain<bool> Bottom = FlatDomain<bool>.BottomValue; + /// <summary> + /// Definitely true. + /// </summary> + public static readonly FlatDomain<bool> True = true; + /// <summary> + /// Definitely false. + /// </summary> + public static readonly FlatDomain<bool> False = false; + + public static FlatDomain<bool> Negate(this FlatDomain<bool> o) + { + if (o.IsNormal()) + return !o.IsTrue(); + + return o; + } + + public static bool IsTrue(this FlatDomain<bool> o) + { + return o.IsNormal () && o.Value; + } + + public static bool IsFalse(this FlatDomain<bool> o) + { + return o.IsNormal () && !o.Value; + } + } } diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcomeExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcomeExtensions.cs deleted file mode 100644 index c4b1e04f687..00000000000 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcomeExtensions.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// ProofOutcomeExtensions.cs -// -// Authors: -// Alexander Chebaturkin (chebaturkin@gmail.com) -// -// Copyright (C) 2011 Alexander Chebaturkin -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -namespace Mono.CodeContracts.Static { - static class ProofOutcomeExtensions { - public static ProofOutcome Negate (this ProofOutcome o) - { - switch (o) { - case ProofOutcome.Top: - case ProofOutcome.Bottom: - return o; - case ProofOutcome.True: - return ProofOutcome.False; - case ProofOutcome.False: - return ProofOutcome.True; - default: - return ProofOutcome.Top; - } - } - - public static ProofOutcome Meet (this ProofOutcome a, ProofOutcome b) - { - if (a == b) - return a; - if (a == ProofOutcome.Top || b == ProofOutcome.Bottom) - return b; - if (b == ProofOutcome.Top || a == ProofOutcome.Bottom) - return a; - - return ProofOutcome.Bottom; - } - - public static ProofOutcome Join (this ProofOutcome a, ProofOutcome b) - { - if (a == b || a == ProofOutcome.Top || b == ProofOutcome.Bottom) - return a; - if (b == ProofOutcome.Top || a == ProofOutcome.Bottom) - return b; - - return ProofOutcome.Top; - } - - public static bool IsNormal (this ProofOutcome o) - { - return o == ProofOutcome.False || o == ProofOutcome.True; - } - } -} diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.dll.sources b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.dll.sources index c0cfb9d8030..b26cf76b660 100644 --- a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.dll.sources +++ b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.dll.sources @@ -115,10 +115,62 @@ Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueContextProvider.cs Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueDecoder.cs Mono.CodeContracts.Static.Analysis.HeapAnalysis/Wrapper.cs Mono.CodeContracts.Static.Analysis.NonNull/Analysis.cs -Mono.CodeContracts.Static.Analysis.NonNull/Domain.cs +Mono.CodeContracts.Static.Analysis.NonNull/NonNullDomain.cs Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssertDischarger.cs Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs +Mono.CodeContracts.Static.Analysis.Numerical/AbstractInterpretationException.cs +Mono.CodeContracts.Static.Analysis.Numerical/Analysers.cs +Mono.CodeContracts.Static.Analysis.Numerical/Analysis.cs +Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericValueAnalysis.cs +Mono.CodeContracts.Static.Analysis.Numerical/Analysis.ConstantEvaluator.cs +Mono.CodeContracts.Static.Analysis.Numerical/Analysis.GenericNumericalAnalysis.cs +Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionDecoder.cs +Mono.CodeContracts.Static.Analysis.Numerical/BoxedExpressionEncoder.cs +Mono.CodeContracts.Static.Analysis.Numerical/BoxedVariable.cs +Mono.CodeContracts.Static.Analysis.Numerical/Counter.cs +Mono.CodeContracts.Static.Analysis.Numerical/DisInterval.cs +Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalAssumer.cs +Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalContext.cs +Mono.CodeContracts.Static.Analysis.Numerical/ConstToIntervalEvaluator.cs +Mono.CodeContracts.Static.Analysis.Numerical/DisIntervalEnvironment.cs +Mono.CodeContracts.Static.Analysis.Numerical/EvaluateExpressionVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/ExpressionType.cs +Mono.CodeContracts.Static.Analysis.Numerical/GetThresholdVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/IExpressionDecoder.cs +Mono.CodeContracts.Static.Analysis.Numerical/IExpressionEncoder.cs +Mono.CodeContracts.Static.Analysis.Numerical/IIntervalEnvironment.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumer.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalContext.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalContextBase.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironment.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalInference.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalAssumerBase.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalRationalContextBase.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeFalseVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumeTrueVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalAssumerBase.cs +Mono.CodeContracts.Static.Analysis.Numerical/LongToIntegerConstantEvaluator.cs +Mono.CodeContracts.Static.Analysis.Numerical/EvaluateArithmeticWithOverflow.cs +Mono.CodeContracts.Static.Analysis.Numerical/ExpressionOperator.cs +Mono.CodeContracts.Static.Analysis.Numerical/ExpressionViaStringComparer.cs +Mono.CodeContracts.Static.Analysis.Numerical/ConstantEvaluatorVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/GenericExpressionVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/GenericTypeExpressionVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/IEnvironmentDomain.cs +Mono.CodeContracts.Static.Analysis.Numerical/Interval.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalBase.cs +Mono.CodeContracts.Static.Analysis.Numerical/IntervalEnvironmentBase.cs +Mono.CodeContracts.Static.Analysis.Numerical/Monomial.cs +Mono.CodeContracts.Static.Analysis.Numerical/ObjectExtensions.cs +Mono.CodeContracts.Static.Analysis.Numerical/Polynomial.cs +Mono.CodeContracts.Static.Analysis.Numerical/Rational.cs +Mono.CodeContracts.Static.Analysis.Numerical/AssumeFalseVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/AssumeTrueVisitor.cs +Mono.CodeContracts.Static.Analysis.Numerical/RationalThreshold.cs +Mono.CodeContracts.Static.Analysis.Numerical/Threshold.cs +Mono.CodeContracts.Static.Analysis.Numerical/TresholdDB.cs +Mono.CodeContracts.Static.Analysis.Numerical/ValueExpressionDecoder.cs Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs Mono.CodeContracts.Static.Analysis.StackAnalysis/SequenceGenerator.cs Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs @@ -260,7 +312,12 @@ Mono.CodeContracts.Static.DataFlowAnalysis/IFixPointInfo.cs Mono.CodeContracts.Static.DataFlowAnalysis/IWidenStrategy.cs Mono.CodeContracts.Static.DataFlowAnalysis/Joiner.cs Mono.CodeContracts.Static.DataFlowAnalysis/StepWidening.cs +Mono.CodeContracts.Static.DataStructures.Patricia/BranchNode.cs +Mono.CodeContracts.Static.DataStructures.Patricia/EmptyNode.cs +Mono.CodeContracts.Static.DataStructures.Patricia/LeafNode.cs +Mono.CodeContracts.Static.DataStructures.Patricia/PatriciaTrieNode.cs Mono.CodeContracts.Static.DataStructures/AbstractWorkList.cs +Mono.CodeContracts.Static.DataStructures/BooleanExtensions.cs Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs Mono.CodeContracts.Static.DataStructures/DepthFirst.cs Mono.CodeContracts.Static.DataStructures/DoubleDictionary.cs @@ -279,18 +336,19 @@ Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs Mono.CodeContracts.Static.DataStructures/ImmutableSetExtensions.cs Mono.CodeContracts.Static.DataStructures/Indexable.cs -Mono.CodeContracts.Static.DataStructures/ITypedProperties.cs +Mono.CodeContracts.Static.DataStructures/IPropertyCollection.cs Mono.CodeContracts.Static.DataStructures/IWorkList.cs -Mono.CodeContracts.Static.DataStructures/LispList.cs -Mono.CodeContracts.Static.DataStructures/LispListExtensions.cs +Mono.CodeContracts.Static.DataStructures/Sequence.cs +Mono.CodeContracts.Static.DataStructures/SequenceExtensions.cs Mono.CodeContracts.Static.DataStructures/Optional.cs Mono.CodeContracts.Static.DataStructures/Pair.cs Mono.CodeContracts.Static.DataStructures/PriorityQueue.cs Mono.CodeContracts.Static.DataStructures/TypedKey.cs -Mono.CodeContracts.Static.DataStructures/TypedProperties.cs +Mono.CodeContracts.Static.DataStructures/PropertyCollection.cs Mono.CodeContracts.Static.DataStructures/VisitStatus.cs Mono.CodeContracts.Static.DataStructures/WorkList.cs Mono.CodeContracts.Static.Extensions/Extensions.cs +Mono.CodeContracts.Static.Lattices/AbstractDomainExtensions.cs Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs Mono.CodeContracts.Static.Lattices/FlatDomain.cs Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs @@ -317,4 +375,3 @@ Mono.CodeContracts.Static/CheckOptions.cs Mono.CodeContracts.Static/Checker.cs Mono.CodeContracts.Static/DebugOptions.cs Mono.CodeContracts.Static/ProofOutcome.cs -Mono.CodeContracts.Static/ProofOutcomeExtensions.cs |