The base architecture for code-contracts analysis
authorAlexander Chebaturkin <chebaturkin@gmail.com>
Wed, 13 Jul 2011 22:47:34 +0000 (02:47 +0400)
committerMarek Safar <marek.safar@gmail.com>
Wed, 24 Aug 2011 20:35:02 +0000 (21:35 +0100)
290 files changed:
man/cccheck.1 [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts-net_4_0.csproj
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/CodeVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/DefaultNodeVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IAggregateVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ICodeConsumer.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IExpressionILVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IILVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ILVisitorBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IMethodCodeConsumer.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ISymbolicExpressionVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ISyntheticILVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeInspector.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ValueCodeVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ArrayTypeNode.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/AssemblyNode.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/AssignmentStatement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Block.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BlockExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BodyParser.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Branch.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/CatchFilter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Class.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Construct.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/CoreSystemTypes.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/EndFinally.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Ensures.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ExceptionHandler.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Expression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ExpressionStatement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/FaultHandler.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Field.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Local.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Member.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MemberBinding.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Method.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodCall.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodContract.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodContractElement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Module.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/NaryExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Node.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/NodeType.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/OperatorExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Parameter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Property.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Reference.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Requires.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Return.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Statement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/This.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/UnaryExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/UnaryOperator.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Variable.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/AnalysisDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/BasicAnalysisDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/BasicMethodDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/CodeContractsAnalysisDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IBasicAnalysisDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IBasicMethodDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysis.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysisFixPoint.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodDriver.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodResult.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/FullExpressionDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/IFullExpressionDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/QueryVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsBinaryExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsInst.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsNull.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsUnaryExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForSizeOf.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForUnderlyingVariable.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForValueOf.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariable.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariablesIn.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/BinaryExpr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/ConstExpr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/Expr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/IsInstExpr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/NullExpr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/SizeOfExpr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/UnaryExpr.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AnalysisDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AssumeDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExprDomain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionAnalysisFacade.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoderAdapter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionPrinterFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ILDecoderAdapter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ValueAnalysis.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/AccessPathFilter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/IVisibilityCheck.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/MethodCallPathElement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/ParameterPathElement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElementBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement`1.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElement.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElementKind.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/AbstractDomainUpdate.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EdgeUpdate.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EliminateEdgeUpdate.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityPair.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityUpdate.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/IMergeInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MergeInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdge.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdgeUpdate.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraph.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraphTerm.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/Update.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AbstractType.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/AnalysisDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Domain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/FunctionsTable.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/HeapAnalysis.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/IAbstractDomainForEGraph.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/IConstantInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ISymGraph.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/LabeledSymbol.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/MethodWrapper.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ParameterWrapper.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/StackToSymbolicAdapter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymFunction.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymValue.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymbolicValue.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/TypeCache.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueContextProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ValueDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Wrapper.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Analysis.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Domain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssertDischarger.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/SequenceGenerator.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo`1.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/CodeLayer.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/CodeLayerFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ICodeLayer.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContext.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ILPrinter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IMethodContext.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IMethodContextProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IStackContext.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IStackContextProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContextProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/PrinterFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/ContractExtractor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/ContractNodes.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/GatherLocals.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/HelperMethods.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/RepresentationForAttribute.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/AssumeBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/BlockBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/BlockWithLabels.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/CatchFilterEntryBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EnsuresBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EntryBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EntryExitBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/LabelAdapter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/MethodCallBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/NewObjCallBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockBuilder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockStartGatherer.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/EnsuresFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/RequiresFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SimpleSubroutineBuilder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineBuilder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineFactory.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineWithHandlersBuilder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/EnsuresSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultFinallySubroutineBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FinallySubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodContractSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldScanStateMachine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldValueSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/RequiresSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SimpleSubroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineFacade.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineWithHandlers.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/CFGBlock.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ContractFilteredCFG.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Edge.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTagExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IHandlerFilter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IMethodInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IStackInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/RemoveBranchDelegator.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/SubroutineKind.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/DataFlowAnalysisBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/EdgeBasedWidening.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/EdgeConverter.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardDataFlowAnalysisBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IFixPointInfo.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IWidenStrategy.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/Joiner.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/StepWidening.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/AbstractWorkList.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DoubleDictionary.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DoubleImmutableMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Dummy.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/EdgeVisitor.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/GraphWrapper.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IGraph.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableIntMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ITypedProperties.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IWorkList.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSetExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Indexable.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispList.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispListExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Optional.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/PriorityQueue.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedKey.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedProperties.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/VisitStatus.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/WorkList.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeContractDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IContractProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IILDecoder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMethodCodeProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ComposedFactQuery.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/CheckOptions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/CheckResults.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/DebugOptions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcomeExtensions.cs [new file with mode: 0644]
mcs/class/Mono.CodeContracts/Mono.CodeContracts.dll.sources
mcs/tools/Makefile
mcs/tools/cccheck/Makefile [new file with mode: 0644]
mcs/tools/cccheck/Program.cs [new file with mode: 0644]
mcs/tools/cccheck/cccheck.exe.sources [new file with mode: 0644]

diff --git a/man/cccheck.1 b/man/cccheck.1
new file mode 100644 (file)
index 0000000..aead19a
--- /dev/null
@@ -0,0 +1,67 @@
+.\" 
+.\" cccheck manual page.
+.\" Copyright (C) 2011 Alexander Chebaturkin
+.\" Author:
+.\"   Alexander Chebaturkin (chebaturkin@gmail.com)
+.\"
+.TH Mono "cccheck"
+.SH NAME
+cccheck \- Perform static code contracts verification for CLR assemblies.
+.SH SYNOPSIS
+.PP
+.B cccheck --assembly=<assembly> [options]
+.SH DESCRIPTION
+Perform static code contracts verification to find bugs and inconsistences
+between code and specification. This includes non-null, integer analyses. 
+.PP
+The assembly must have been built with the symbol CONTRACTS_FULL defined,
+otherwise the calls to the contract methods will have been removed
+by the compiler.
+.PP
+Currently only Contract.Assume() and Contract.Assert() methods are 
+supported. Only non-null analysis is supported, the consecutive analyses are
+in development. An error message will be shown if cccheck is unable to process
+all or some of the methods of specified assembly.
+.SH CONFIGURATION OPTIONS
+.TP
+.I "--assembly <assembly-name>"
+The assembly to perform static verification.
+.TP
+.I "--debug"
+Shows debug information about process of proving the assertions. It shows
+four layers of abstraction, raw layer, stack layer, heap layer, 
+and substituted expression level.
+.TP
+.I "--method=<method-name-substring>"
+String for finding method. It filters all methods in assembly where method
+name has this parameter as a substring.
+.TP
+.I "--help"
+Show help for cccheck, listing configuration options.
+
+.SH EXAMPLES
+.TP
+Suppose you have a method:
+  void Method() {
+    object x = null;
+    int y = 1;
+    if (y % 2 == 1)
+      x = new object();
+    else
+      x = new string();
+
+   Contract.Assert(x != null);
+}
+
+After the verification the tool will have results in following format:
+"Assertion at : [Subroutine: <id> Block <blockId> PC <id>] : 
+ is (true|false|unproven|unreachable)".
+(PC is a program counter)
+
+.SH AUTHOR
+Written by Alexander Chebaturkin
+.SH COPYRIGHT
+Copyright 2011 Alexander Chebaturkin.
+Released under MIT license.
+.SH WEB SITE
+Visit http://www.mono-project.com for details
index dfc6f8230365a40bfd1b761780f2803bf88e4a49..f7bccdc7c69cc2e6aa31ce32313a5529b76be439 100644 (file)
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
   <PropertyGroup>\r
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
     <OutputPath>./../../class/lib/net_4_0</OutputPath>\r
     <DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0</DefineConstants>\r
     <NoStdLib>true</NoStdLib>\r
-    \r
     <AppDesignerFolder>Properties</AppDesignerFolder>\r
     <RootNamespace>mscorlib</RootNamespace>\r
     <AssemblyName>Mono.CodeContracts</AssemblyName>\r
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>\r
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>\r
     <FileAlignment>512</FileAlignment>\r
     <StartupObject>\r
     </StartupObject>\r
   </PropertyGroup>\r
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
   <ItemGroup>\r
-   <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" />
-\r
+    <Compile Include="..\..\build\common\Consts.cs" />\r
+    <Compile Include="Assembly\AssemblyInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\AssemblyRef.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\ConditionTextExtractor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\ContractRequiresInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\ContractsRuntime.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\Decompile.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\ExprGen.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\MethodInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\PerformRewrite.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\Rewriter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\RewriterOptions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\RewriterResults.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite\TransformContractsVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprAdd.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpArithmetic.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOpComparison.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBinaryOp.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprBox.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCall.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareEqual.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareGreaterThan.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprCompareLessThan.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprConv.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\Expr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadArg.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprLoadConstant.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprNop.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprReturn.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprSub.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\ExprType.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.Ast\Sn.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\CompileVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\ExprVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\InstructionExtentVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Rewrite.AstVisitors\SourcePositionVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\AnalysisDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicAnalysisDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\BasicMethodDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\CodeContractsAnalysisDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicAnalysisDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IBasicMethodDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysis.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodAnalysisFixPoint.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodDriver.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.Drivers\IMethodResult.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\FullExpressionDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\IFullExpressionDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\QueryVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsBinaryExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsInst.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsNull.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForIsUnaryExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForSizeOf.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForUnderlyingVariable.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForValueOf.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariable.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding\VisitorForVariablesIn.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\BinaryExpr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\ConstExpr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\Expr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\IsInstExpr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\NullExpr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\SizeOfExpr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions\UnaryExpr.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AnalysisDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\AssumeDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExprDomain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionAnalysisFacade.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionDecoderAdapter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ExpressionPrinterFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ILDecoderAdapter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.ExpressionAnalysis\ValueAnalysis.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\AccessPathFilter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\IVisibilityCheck.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\MethodCallPathElement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\ParameterPathElement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElementBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathElement`1.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\PathExtensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths\SpecialPathElementKind.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\AbstractDomainUpdate.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EdgeUpdate.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EliminateEdgeUpdate.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityPair.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\EqualityUpdate.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\IMergeInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MergeInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdge.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\MultiEdgeUpdate.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraph.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\SymGraphTerm.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph\Update.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AbstractType.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\AnalysisDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Domain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\FunctionsTable.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\HeapAnalysis.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IAbstractDomainForEGraph.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\IConstantInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ISymGraph.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\LabeledSymbol.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\MethodWrapper.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ParameterWrapper.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\StackToSymbolicAdapter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymbolicValue.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymFunction.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\SymValue.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\TypeCache.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueContextProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\ValueDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.HeapAnalysis\Wrapper.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Analysis.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\Domain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssertDischarger.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\ExpressionAssumeDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.NonNull\NonNullAnalysisFacade.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\APCMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\SequenceGenerator.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackDepthProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis.StackAnalysis\StackInfo`1.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayer.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\CodeLayerFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\ICodeLayer.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContext.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IExpressionContextProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\ILPrinter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContext.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IMethodContextProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContext.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IStackContextProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContext.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\IValueContextProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Analysis\PrinterFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\CodeVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\DefaultNodeVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IAggregateVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ICodeConsumer.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IExpressionILVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IILVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ILVisitorBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\IMethodCodeConsumer.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISymbolicExpressionVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ISyntheticILVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeInspector.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\NodeVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST.Visitors\ValueCodeVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\ArrayTypeNode.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\AssemblyNode.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\AssignmentStatement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\BinaryExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\BinaryOperator.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Block.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\BlockExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\BodyParser.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Branch.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\CatchFilter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Class.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Construct.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\CoreSystemTypes.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\EndFinally.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Ensures.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\ExceptionHandler.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Expression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\ExpressionStatement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\FaultHandler.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Field.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Literal.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Local.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Member.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\MemberBinding.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Method.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\MethodCall.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\MethodContract.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\MethodContractElement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Module.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\NaryExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Node.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\NodeType.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\OperatorExtensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Parameter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Property.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Reference.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Requires.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Return.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Statement.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\This.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\TypeNode.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\UnaryExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\UnaryOperator.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.AST\Variable.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractExtractor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ContractExtraction\ContractNodes.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ContractExtraction\GatherLocals.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ContractExtraction\HelperMethods.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ContractExtraction\RepresentationForAttribute.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\AssumeBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\BlockWithLabels.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\CatchFilterEntryBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EnsuresBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\EntryExitBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\LabelAdapter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\MethodCallBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Blocks\NewObjCallBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockBuilder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\BlockStartGatherer.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\EnsuresFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\RequiresFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SimpleSubroutineBuilder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineBuilder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineFactory.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders\SubroutineWithHandlersBuilder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\EnsuresSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultFinallySubroutineBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FaultSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\FinallySubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodContractSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\MethodSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldScanStateMachine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\OldValueSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\RequiresSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SimpleSubroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineFacade.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow.Subroutines\SubroutineWithHandlers.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\APC.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\APCDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\CFGBlock.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\ContractFilteredCFG.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\ControlFlowGraph.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\Edge.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTag.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeTagExtensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\EdgeVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\ICFG.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\IConstantInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\IHandlerFilter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\IMethodInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\IStackInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\RemoveBranchDelegator.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\Subroutine.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.ControlFlow\SubroutineKind.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\DataFlowAnalysisBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeBasedWidening.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\EdgeConverter.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardAnalysis.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\ForwardDataFlowAnalysisBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IAnalysis.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IFixPointInfo.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\IWidenStrategy.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\Joiner.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataFlowAnalysis\StepWidening.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\AbstractWorkList.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\DecoratorHelper.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\DepthFirst.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleDictionary.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\DoubleImmutableMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\Dummy.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\EdgeVisitor.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\GraphWrapper.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\IGraph.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableIntMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\IImmutableSet.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\IIndexable.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntKeyMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableIntMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableMap.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSet.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\ImmutableSetExtensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\Indexable.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\ITypedProperties.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\IWorkList.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\LispList.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\LispListExtensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\Optional.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\Pair.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\PriorityQueue.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedKey.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\TypedProperties.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\VisitStatus.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.DataStructures\WorkList.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Extensions\Extensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Lattices\EnvironmentDomain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Lattices\FlatDomain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Lattices\IAbstractDomain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Lattices\SetDomain.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\CodeContractDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\CodeProviderImpl.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\ICodeProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\IContractProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\IILDecoder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\IMetaDataProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\IMethodCodeProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Providers\MetaDataProvider.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\AssertionFinder.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\BasicFacts.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpression.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\BoxedExpressionExtensions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\ComposedFactQuery.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\ConstantPropagationFactQuery.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\IFactBase.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\IFactQuery.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static.Proving\SimpleLogicInference.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static\CheckResults.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static\CheckOptions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static\Checker.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static\DebugOptions.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static\ProofOutcome.cs" />\r
+    <Compile Include="Mono.CodeContracts.Static\ProofOutcomeExtensions.cs" />\r
   </ItemGroup>\r
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
        Other similar extension points exist, see Microsoft.Common.targets.\r
   <PropertyGroup>\r
     <PreBuildEvent></PreBuildEvent>\r
   </PropertyGroup>\r
-  <ItemGroup>
-    <Reference Include="mscorlib.dll">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\\lib\build\mscorlib.dll</HintPath>
-    </Reference>
-    <Reference Include="System">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\\lib\build\System</HintPath>
-    </Reference>
-    <Reference Include="System.Core">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\\lib\build\System.Core</HintPath>
-    </Reference>
-    <Reference Include="Mono.Cecil.dll">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\\lib\build\Mono.Cecil.dll</HintPath>
-    </Reference>
-    <Reference Include="Mono.Cecil.Mdb.dll">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\\lib\build\Mono.Cecil.Mdb.dll</HintPath>
-    </Reference>
-  </ItemGroup>
-\r
+  <ItemGroup>\r
+    <Reference Include="mscorlib.dll">\r
+      <SpecificVersion>False</SpecificVersion>\r
+      <HintPath>..\\lib\build\mscorlib.dll</HintPath>\r
+    </Reference>\r
+    <Reference Include="System">\r
+      <SpecificVersion>False</SpecificVersion>\r
+      <HintPath>..\\lib\build\System</HintPath>\r
+    </Reference>\r
+    <Reference Include="System.Core">\r
+      <SpecificVersion>False</SpecificVersion>\r
+      <HintPath>..\\lib\build\System.Core</HintPath>\r
+    </Reference>\r
+    <Reference Include="Mono.Cecil.dll">\r
+      <SpecificVersion>False</SpecificVersion>\r
+      <HintPath>..\\lib\build\Mono.Cecil.dll</HintPath>\r
+    </Reference>\r
+    <Reference Include="Mono.Cecil.Mdb.dll">\r
+      <SpecificVersion>False</SpecificVersion>\r
+      <HintPath>..\\lib\build\Mono.Cecil.Mdb.dll</HintPath>\r
+    </Reference>\r
+  </ItemGroup>\r
   <ItemGroup>\r
     <Folder Include="Properties\" />\r
   </ItemGroup>\r
-  \r
-</Project>\r
-
+\r
+</Project>
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..efd7c4c
--- /dev/null
@@ -0,0 +1,81 @@
+using System;
+using System.IO;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataFlowAnalysis;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       class CodeVisitor<Variable, Expression, ContextData, EdgeData>
+               : ILVisitorBase<APC, Expression, Variable, bool, bool>,
+                 IAnalysis<APC, bool, IILVisitor<APC, Expression, Variable, bool, bool>, EdgeData>
+               where ContextData : IMethodContextProvider {
+               private ICodeLayer<Expression, Variable, ContextData, EdgeData> codeLayer;
+
+               public ContextData Context
+               {
+                       get { return this.codeLayer.ILDecoder.ContextProvider; }
+               }
+
+               protected IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.codeLayer.MetaDataProvider; }
+               }
+
+               public void Run (ICodeLayer<Expression, Variable, ContextData, EdgeData> codeLayer)
+               {
+                       this.codeLayer = codeLayer;
+                       codeLayer.CreateForward (this) (true);
+               }
+
+               #region Overrides of ILVisitorBase<APC,Expression,Variable,bool,bool>
+               public override bool DefaultVisit (APC pc, bool data)
+               {
+                       return data;
+               }
+               #endregion
+
+               #region Implementation of IAnalysis<APC,bool,IILVisitor<APC,Expression,Variable,bool,bool>,EdgeData>
+               public IILVisitor<APC, Expression, Variable, bool, bool> GetVisitor ()
+               {
+                       return this;
+               }
+
+               public virtual bool Join (Pair<APC, APC> edge, bool newstate, bool prevstate, out bool weaker, bool widen)
+               {
+                       weaker = false;
+                       return true;
+               }
+
+               public bool ImmutableVersion (bool arg)
+               {
+                       return arg;
+               }
+
+               public bool MutableVersion (bool arg)
+               {
+                       return arg;
+               }
+
+               public bool EdgeConversion (APC @from, APC to, bool isJoinPoint, EdgeData data, bool state)
+               {
+                       return state;
+               }
+
+               public bool IsBottom (APC pc, bool state)
+               {
+                       return !state;
+               }
+
+               public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, bool> fixPointInfo)
+               {
+                       return null;
+               }
+
+               public void Dump (Pair<bool, TextWriter> pair)
+               {
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..133fb57
--- /dev/null
@@ -0,0 +1,467 @@
+// 
+// DefaultNodeVisitor.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       class DefaultNodeVisitor : NodeVisitor {
+               #region Overrides of NodeVisitor
+               public override Node Visit (Node node)
+               {
+                       if (node == null)
+                               return null;
+                       switch (node.NodeType) {
+                       case NodeType.Nop:
+                               return node;
+
+                               #region Binary
+                       case NodeType.Add:
+                       case NodeType.Sub:
+                       case NodeType.Rem:
+                       case NodeType.Clt:
+                       case NodeType.Cgt:
+                       case NodeType.Ceq:
+                       case NodeType.Box:
+                       case NodeType.Le:
+                       case NodeType.Mul:
+                       case NodeType.Div:
+                       case NodeType.Div_Un:
+                       case NodeType.Rem_Un:
+                       case NodeType.And:
+                       case NodeType.Or:
+                       case NodeType.Shr:
+                       case NodeType.Xor:
+                       case NodeType.Shl:
+                       case NodeType.Shr_Un:
+                       case NodeType.Ne:
+                       case NodeType.Ge:
+                       case NodeType.Gt:
+                       case NodeType.Lt:
+                       case NodeType.Eq:
+                               return VisitBinaryExpression ((BinaryExpression) node);
+                               #endregion
+
+                       case NodeType.Call:
+                       case NodeType.Jmp:
+                       case NodeType.MethodCall:
+                               return VisitMethodCall ((MethodCall) node);
+
+                       case NodeType.Conv:
+                       case NodeType.Conv_I1:
+                       case NodeType.Conv_I2:
+                       case NodeType.Conv_I8:
+                       case NodeType.Conv_I4:
+                       case NodeType.Conv_R4:
+                       case NodeType.Conv_R8:
+                       case NodeType.Neg:
+                       case NodeType.Not:
+                       case NodeType.LogicalNot:
+                               return VisitUnaryExpression ((UnaryExpression) node);
+
+                       case NodeType.Literal:
+                               return VisitLiteral ((Literal) node);
+                       case NodeType.This:
+                               return VisitThis ((This) node);
+
+                       case NodeType.Block:
+                               return VisitBlock ((Block) node);
+                       case NodeType.Branch:
+                               return VisitBranch ((Branch) node);
+                       case NodeType.Return:
+                               return VisitReturn ((Return) node);
+                       case NodeType.AssignmentStatement:
+                               return VisitAssignmentStatement ((AssignmentStatement) node);
+                       case NodeType.Local:
+                               return VisitLocal ((Local) node);
+                       case NodeType.Parameter:
+                               return VisitParameter ((Parameter) node);
+                       case NodeType.ExpressionStatement:
+                               return VisitExpressionStatement ((ExpressionStatement) node);
+                       case NodeType.Method:
+                               return VisitMethod ((Method) node);
+                       case NodeType.MethodContract:
+                               return VisitMethodContract ((MethodContract) node);
+                       case NodeType.Requires:
+                               return VisitRequires ((Requires) node);
+                       case NodeType.Ensures:
+                               return VisitEnsures ((Ensures) node);
+                       case NodeType.TypeNode:
+                               return VisitTypeNode ((TypeNode) node);
+                       case NodeType.Assembly:
+                               return VisitAssembly ((AssemblyNode) node);
+                       case NodeType.Module:
+                               return VisitModule ((Module) node);
+                       case NodeType.MemberBinding:
+                               return VisitMemberBinding ((MemberBinding) node);
+                       case NodeType.Construct:
+                               return VisitConstruct ((Construct) node);
+                       }
+
+                       return VisitUnknownNodeType (node);
+               }
+
+               public virtual AssemblyNode VisitAssembly (AssemblyNode node)
+               {
+                       if (node == null)
+                               return null;
+
+                       VisitModuleList (node.Modules);
+
+
+                       return node;
+               }
+
+               public virtual void VisitModuleList (IEnumerable<Module> node)
+               {
+                       if (node == null)
+                               return;
+
+                       foreach (Module module in node)
+                               VisitModule (module);
+               }
+
+               private Module VisitModule (Module node)
+               {
+                       if (node == null)
+                               return null;
+
+                       VisitTypeNodeList (node.Types);
+
+                       return node;
+               }
+
+               public virtual Statement VisitAssignmentStatement (AssignmentStatement node)
+               {
+                       if (node == null)
+                               return node;
+                       node.Target = VisitTargetExpression (node.Target);
+                       node.Source = VisitExpression (node.Source);
+
+                       return node;
+               }
+
+               public virtual Expression VisitBinaryExpression (BinaryExpression node)
+               {
+                       if (node == null)
+                               return node;
+
+                       node.Operand1 = VisitExpression (node.Operand1);
+                       node.Operand2 = VisitExpression (node.Operand2);
+
+                       return node;
+               }
+
+               public virtual Block VisitBlock (Block node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Statements = VisitStatementList (node.Statements);
+
+                       return node;
+               }
+
+               public virtual List<Statement> VisitStatementList (List<Statement> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++)
+                               node [i] = (Statement) Visit (node [i]);
+
+                       return node;
+               }
+
+               public virtual Statement VisitBranch (Branch node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Condition = VisitExpression (node.Condition);
+
+                       return node;
+               }
+
+               public virtual Expression VisitConstruct (Construct node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Constructor = VisitExpression (node.Constructor);
+                       node.Arguments = VisitExpressionList (node.Arguments);
+
+                       return node;
+               }
+
+               public virtual Ensures VisitEnsures (Ensures node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Assertion = VisitExpression (node.Assertion);
+                       node.UserMessage = VisitExpression (node.UserMessage);
+
+                       return node;
+               }
+
+               public virtual Expression VisitExpression (Expression node)
+               {
+                       if (node == null)
+                               return null;
+
+                       return node;
+               }
+
+               public virtual Statement VisitExpressionStatement (ExpressionStatement node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Expression = VisitExpression (node.Expression);
+
+                       return node;
+               }
+
+               public virtual Expression VisitLiteral (Literal node)
+               {
+                       return node;
+               }
+
+               public virtual Expression VisitLocal (Local node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Type = VisitTypeNode (node.Type);
+
+                       //todo: maybe there should be something else
+
+                       return node;
+               }
+
+               public virtual Expression VisitMemberBinding (MemberBinding node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.TargetObject = VisitExpression (node.TargetObject);
+
+                       return node;
+               }
+
+               public virtual Method VisitMethod (Method node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.ReturnType = VisitTypeNode (node.ReturnType);
+                       node.Parameters = VisitParameterList (node.Parameters);
+                       node.MethodContract = VisitMethodContract (node.MethodContract);
+                       node.Body = VisitBlock (node.Body);
+
+                       return node;
+               }
+
+               public virtual List<Parameter> VisitParameterList (List<Parameter> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++)
+                               node [i] = VisitParameter (node [i]);
+
+                       return node;
+               }
+
+               public virtual Expression VisitMethodCall (MethodCall node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Callee = VisitExpression (node.Callee);
+                       node.Arguments = VisitExpressionList (node.Arguments);
+
+                       return node;
+               }
+
+               public virtual MethodContract VisitMethodContract (MethodContract node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Requires = VisitRequiresList (node.Requires);
+                       node.Ensures = VisitEnsuresList (node.Ensures);
+
+                       return node;
+               }
+
+               public virtual List<Ensures> VisitEnsuresList (List<Ensures> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++)
+                               node [i] = (Ensures) Visit (node [i]);
+
+                       return node;
+               }
+
+               public virtual List<Requires> VisitRequiresList (List<Requires> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++)
+                               node [i] = (Requires) Visit (node [i]);
+
+                       return node;
+               }
+
+               public virtual Parameter VisitParameter (Parameter node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Type = VisitTypeNode (node.Type);
+
+                       //todo: there may be something else
+
+                       return node;
+               }
+
+               public virtual Requires VisitRequires (Requires node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Assertion = VisitExpression (node.Assertion);
+                       node.UserMessage = VisitExpression (node.UserMessage);
+
+                       return node;
+               }
+
+               public virtual Return VisitReturn (Return node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Expression = VisitExpression (node.Expression);
+
+                       return node;
+               }
+
+               public virtual Expression VisitTargetExpression (Expression node)
+               {
+                       return VisitExpression (node);
+               }
+
+               public virtual Expression VisitThis (This node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Type = VisitTypeNode (node.Type);
+
+                       return node;
+               }
+
+               public virtual TypeNode VisitTypeNode (TypeNode node)
+               {
+                       if (node == null)
+                               return null;
+
+                       var clazz = node as Class;
+                       if (clazz != null)
+                               clazz.BaseType = VisitTypeNode (clazz.BaseType);
+
+                       VisitPropertiesList (node.Properties);
+                       VisitMethodsList (node.Methods);
+                       VisitTypeNodeList (node.NestedTypes);
+
+                       return node;
+               }
+
+               public virtual List<Property> VisitPropertiesList (List<Property> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++) {
+                               Property property = node [i];
+                               if (property != null)
+                                       node [i] = (Property) Visit (node [i]);
+                       }
+
+                       return node;
+               }
+
+               public virtual List<Method> VisitMethodsList (List<Method> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++) {
+                               Method method = node [i];
+                               if (method != null)
+                                       node [i] = (Method) Visit (node [i]);
+                       }
+
+                       return node;
+               }
+
+               public virtual List<TypeNode> VisitTypeNodeList (List<TypeNode> node)
+               {
+                       if (node == null)
+                               return null;
+
+                       for (int i = 0; i < node.Count; i++) {
+                               TypeNode method = node [i];
+                               if (method != null)
+                                       node [i] = (TypeNode) Visit (node [i]);
+                       }
+
+                       return node;
+               }
+
+               public virtual Expression VisitUnaryExpression (UnaryExpression node)
+               {
+                       if (node == null)
+                               return null;
+
+                       node.Operand = VisitExpression (node.Operand);
+
+                       return node;
+               }
+
+               public virtual Node VisitUnknownNodeType (Node node)
+               {
+                       return node;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IAggregateVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IAggregateVisitor.cs
new file mode 100644 (file)
index 0000000..8778f8d
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IAggregateVisitor.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 Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       interface IAggregateVisitor<Label, Data, Result> : IILVisitor<Label, Dummy, Dummy, Data, Result> {
+               Result Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Data data);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ICodeConsumer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ICodeConsumer.cs
new file mode 100644 (file)
index 0000000..44f8973
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// ICodeConsumer.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 Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       interface ICodeConsumer<Data, Result> {
+               Result Accept<Label> (ICodeProvider<Label> codeProvider, Label entryPoint, Data data);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IExpressionILVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IExpressionILVisitor.cs
new file mode 100644 (file)
index 0000000..3c0e7a9
--- /dev/null
@@ -0,0 +1,38 @@
+// 
+// IExpressionILVisitor.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.AST.Visitors {
+       interface IExpressionILVisitor<Label, Source, Dest, Data, Result> {
+               Result Binary (Label pc, BinaryOperator bop, Dest dest, Source src1, Source src2, Data data);
+               Result Unary (Label pc, UnaryOperator uop, bool unsigned, Dest dest, Source source, Data data);
+               Result LoadNull (Label pc, Dest dest, Data polarity);
+               Result LoadConst (Label pc, TypeNode type, object constant, Dest dest, Data data);
+               Result Sizeof (Label pc, TypeNode type, Dest dest, Data data);
+               Result Isinst (Label pc, TypeNode type, Dest dest, Source obj, Data data);
+       }
+}
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
new file mode 100644 (file)
index 0000000..dfbbc0c
--- /dev/null
@@ -0,0 +1,102 @@
+// 
+// IILVisitor.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.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);
+
+               Result Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dest dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Source>;
+
+               Result Calli<TypeList, ArgList> (Label pc, TypeNode returnType, TypeList argTypes, bool instance, Dest dest, Source functionPointer, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Source>;
+
+               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);
+
+               Result ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dest dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Source>;
+
+               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);
+
+               Result NewArray<ArgList> (Label pc, TypeNode type, Dest dest, ArgList lengths, Data data)
+                       where ArgList : IIndexable<Source>;
+
+               Result NewObj<ArgList> (Label pc, Method ctor, Dest dest, ArgList args, Data data)
+                       where ArgList : IIndexable<Source>;
+
+               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);
+               }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ILVisitorBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ILVisitorBase.cs
new file mode 100644 (file)
index 0000000..37822b1
--- /dev/null
@@ -0,0 +1,371 @@
+// 
+// ILVisitorBase.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.Collections.Generic;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.AST.Visitors
+{
+       /// <summary>
+       /// Abstract base implementation of ILVisitor
+       /// </summary>
+       /// <remarks> Each (non-overriden) operation returns DefaultVisit(pc, data) </remarks>
+       abstract class ILVisitorBase<Label, Source, Dest, Data, Result>
+               : IILVisitor<Label, Source, Dest, Data, Result>
+       {
+               public abstract Result DefaultVisit(Label pc, Data data);
+
+               #region Implementation of IExpressionILVisitor<Label,Type,Source,Dest,Data,Result>
+               public virtual Result Binary(Label pc, BinaryOperator bop, Dest dest, Source operand1, Source operand2, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Isinst(Label pc, TypeNode type, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadNull(Label pc, Dest dest, Data polarity)
+               {
+                       return DefaultVisit (pc, polarity);
+               }
+
+               public virtual Result LoadConst(Label pc, TypeNode type, object constant, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Sizeof(Label pc, TypeNode type, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Unary(Label pc, UnaryOperator uop, bool unsigned, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+               #endregion
+
+               #region Implementation of IILVisitor<Label,Local,Parameter,Method,Field,Type,Source,Dest,Data,Result>
+               public virtual Result Arglist(Label pc, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Branch(Label pc, Label target, bool leavesExceptionBlock, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result BranchCond(Label pc, Label target, BranchOperator bop, Source value1, Source value2, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result BranchTrue(Label pc, Label target, Source cond, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result BranchFalse(Label pc, Label target, Source cond, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Break(Label pc, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Call<TypeList, ArgList>(Label pc, Method method, bool virt, TypeList extraVarargs, Dest dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<Source>
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Calli<TypeList, ArgList>(Label pc, TypeNode returnType, TypeList argTypes, bool instance, Dest dest, Source functionPointer, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<Source>
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result CheckFinite(Label pc, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result CopyBlock(Label pc, Source destAddress, Source srcAddress, Source len, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result EndFilter(Label pc, Source decision, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result EndFinally(Label pc, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Jmp(Label pc, Method method, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadArg(Label pc, Parameter param, bool isOld, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadArgAddress(Label pc, Parameter param, bool isOld, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadLocal(Label pc, Local local, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadLocalAddress(Label pc, Local local, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Nop(Label pc, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Pop(Label pc, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Return(Label pc, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result StoreArg(Label pc, Parameter param, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result StoreLocal(Label pc, Local local, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Switch(Label pc, TypeNode type, IEnumerable<Pair<object, Label>> cases, Source value, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Box(Label pc, TypeNode type, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result ConstrainedCallvirt<TypeList, ArgList>(Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dest dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Source>
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result CastClass(Label pc, TypeNode type, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result CopyObj(Label pc, TypeNode type, Source destPtr, Source sourcePtr, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Initobj(Label pc, TypeNode type, Source ptr, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadElement(Label pc, TypeNode type, Dest dest, Source array, Source index, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadField(Label pc, Field field, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadFieldAddress(Label pc, Field field, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadLength(Label pc, Dest dest, Source array, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadStaticField(Label pc, Field field, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadStaticFieldAddress(Label pc, Field field, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadTypeToken(Label pc, TypeNode type, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadFieldToken(Label pc, Field field, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadMethodToken(Label pc, Method method, Dest dest, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result NewArray<ArgList>(Label pc, TypeNode type, Dest dest, ArgList lengths, Data data) 
+                       where ArgList : IIndexable<Source>
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result NewObj<ArgList>(Label pc, Method ctor, Dest dest, ArgList args, Data data) 
+                       where ArgList : IIndexable<Source>
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result MkRefAny(Label pc, TypeNode type, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result RefAnyType(Label pc, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result RefAnyVal(Label pc, TypeNode type, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Rethrow(Label pc, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result StoreElement(Label pc, TypeNode type, Source array, Source index, Source value, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result StoreField(Label pc, Field field, Source obj, Source value, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result StoreStaticField(Label pc, Field field, Source value, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Throw(Label pc, Source exception, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Unbox(Label pc, TypeNode type, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result UnboxAny(Label pc, TypeNode type, Dest dest, Source obj, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+               #endregion
+
+               #region Implementation of ISyntheticILVisitor<Label,Method,Field,Type,Source,Dest,Data,Result>
+               public virtual Result Entry(Label pc, Method method, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Assume(Label pc, EdgeTag tag, Source condition, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result Assert(Label pc, EdgeTag tag, Source condition, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result BeginOld(Label pc, Label matchingEnd, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result EndOld(Label pc, Label matchingBegin, TypeNode type, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadStack(Label pc, int offset, Dest dest, Source source, bool isOld, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadStackAddress(Label pc, int offset, Dest dest, Source source, TypeNode type, bool isOld, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+
+               public virtual Result LoadResult(Label pc, TypeNode type, Dest dest, Source source, Data data)
+               {
+                       return DefaultVisit (pc, data);
+               }
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IMethodCodeConsumer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/IMethodCodeConsumer.cs
new file mode 100644 (file)
index 0000000..97b5ec6
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IMethodCodeConsumer.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 Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       interface IMethodCodeConsumer<Data, Result> {
+               Result Accept<Label, Handler> (IMethodCodeProvider<Label, Handler> codeProvider, Label entry, Method method, Data data);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ISymbolicExpressionVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ISymbolicExpressionVisitor.cs
new file mode 100644 (file)
index 0000000..7e4ac73
--- /dev/null
@@ -0,0 +1,34 @@
+// 
+// ISymbolicExpressionVisitor.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.AST.Visitors {
+       interface ISymbolicExpressionVisitor<Label, Source, Dest, Data, Result>
+               : IExpressionILVisitor<Label, Source, Dest, Data, Result> {
+               Result SymbolicConstant (Label pc, Dest variable, Data data);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ISyntheticILVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/ISyntheticILVisitor.cs
new file mode 100644 (file)
index 0000000..e337aa3
--- /dev/null
@@ -0,0 +1,42 @@
+// 
+// ISyntheticILVisitor.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 Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       interface ISyntheticILVisitor<Label, Source, Dest, Data, Result> {
+               Result Entry (Label pc, Method method, Data data);
+               Result Assume (Label pc, EdgeTag tag, Source condition, Data data);
+               Result Assert (Label pc, EdgeTag tag, Source condition, Data data);
+               Result LoadStack (Label pc, int offset, Dest dest, Source source, bool isOld, Data data);
+               Result LoadStackAddress (Label pc, int offset, Dest dest, Source source, TypeNode type, bool isOld, Data data);
+               Result LoadResult (Label pc, TypeNode type, Dest dest, Source source, Data data);
+               Result BeginOld (Label pc, Label matchingEnd, Data data);
+               Result EndOld (Label pc, Label matchingBegin, TypeNode type, Dest dest, Source source, Data 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
new file mode 100644 (file)
index 0000000..b1f1ae2
--- /dev/null
@@ -0,0 +1,436 @@
+// 
+// NodeInspector.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       class NodeInspector {
+               public virtual void Visit (Node node)
+               {
+                       if (node == null)
+                               return;
+                       switch (node.NodeType) {
+                       case NodeType.Nop:
+                               break;
+
+                               #region Binary
+                       case NodeType.Add:
+                       case NodeType.Sub:
+                       case NodeType.Rem:
+                       case NodeType.Clt:
+                       case NodeType.Cgt:
+                       case NodeType.Ceq:
+                       case NodeType.Box:
+                       case NodeType.Le:
+                       case NodeType.Mul:
+                       case NodeType.Div:
+                       case NodeType.Div_Un:
+                       case NodeType.Rem_Un:
+                       case NodeType.And:
+                       case NodeType.Or:
+                       case NodeType.Shr:
+                       case NodeType.Xor:
+                       case NodeType.Shl:
+                       case NodeType.Shr_Un:
+                       case NodeType.Ne:
+                       case NodeType.Ge:
+                       case NodeType.Gt:
+                       case NodeType.Lt:
+                       case NodeType.Eq:
+                               VisitBinaryExpression ((BinaryExpression) node);
+                               break;
+                               #endregion
+
+                       case NodeType.Call:
+                       case NodeType.Jmp:
+                       case NodeType.MethodCall:
+                               VisitMethodCall ((MethodCall) node);
+                               break;
+                       case NodeType.Conv:
+                       case NodeType.Conv_I1:
+                       case NodeType.Conv_I2:
+                       case NodeType.Conv_I8:
+                       case NodeType.Conv_I4:
+                       case NodeType.Conv_R4:
+                       case NodeType.Conv_R8:
+                       case NodeType.Neg:
+                       case NodeType.Not:
+                       case NodeType.LogicalNot:
+                               VisitUnaryExpression ((UnaryExpression) node);
+                               break;
+                       case NodeType.Literal:
+                               VisitLiteral ((Literal) node);
+                               break;
+                       case NodeType.This:
+                               VisitThis ((This) node);
+                               break;
+                       case NodeType.Block:
+                               VisitBlock ((Block) node);
+                               break;
+                       case NodeType.Branch:
+                               VisitBranch ((Branch) node);
+                               break;
+                       case NodeType.Return:
+                               VisitReturn ((Return) node);
+                               break;
+                       case NodeType.AssignmentStatement:
+                               VisitAssignmentStatement ((AssignmentStatement) node);
+                               break;
+                       case NodeType.Local:
+                               VisitLocal ((Local) node);
+                               break;
+                       case NodeType.Parameter:
+                               VisitParameter ((Parameter) node);
+                               break;
+                       case NodeType.ExpressionStatement:
+                               VisitExpressionStatement ((ExpressionStatement) node);
+                               break;
+                       case NodeType.Method:
+                               VisitMethod ((Method) node);
+                               break;
+                       case NodeType.MethodContract:
+                               VisitMethodContract ((MethodContract) node);
+                               break;
+                       case NodeType.Requires:
+                               VisitRequires ((Requires) node);
+                               break;
+                       case NodeType.Ensures:
+                               VisitEnsures ((Ensures) node);
+                               break;
+                       case NodeType.TypeNode:
+                               VisitTypeNode ((TypeNode) node);
+                               break;
+                       case NodeType.Assembly:
+                               VisitAssembly ((AssemblyNode) node);
+                               break;
+                       case NodeType.Module:
+                               VisitModule ((Module) node);
+                               break;
+                       case NodeType.MemberBinding:
+                               VisitMemberBinding ((MemberBinding) node);
+                               break;
+                       case NodeType.Construct:
+                               VisitConstruct ((Construct) node);
+                               break;
+                       default:
+                               VisitUnknownNodeType (node);
+                               break;
+                       }
+               }
+
+               public virtual void VisitAssembly (AssemblyNode node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitModuleList (node.Modules);
+               }
+
+               public virtual void VisitModuleList (IEnumerable<Module> node)
+               {
+                       if (node == null)
+                               return;
+
+                       foreach (Module module in node)
+                               VisitModule (module);
+               }
+
+               public virtual void VisitModule (Module node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitTypeNodeList (node.Types);
+               }
+
+               public virtual void VisitAssignmentStatement (AssignmentStatement node)
+               {
+                       if (node == null)
+                               return;
+                       VisitTargetExpression (node.Target);
+                       VisitExpression (node.Source);
+               }
+
+               public virtual void VisitBinaryExpression (BinaryExpression node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Operand1);
+                       VisitExpression (node.Operand2);
+               }
+
+               public virtual void VisitBlock (Block node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitStatementList (node.Statements);
+               }
+
+               public virtual void VisitStatementList (List<Statement> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++)
+                               Visit (node [i]);
+               }
+
+               public virtual void VisitBranch (Branch node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Condition);
+               }
+
+               public virtual void VisitConstruct (Construct node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Constructor);
+                       VisitExpressionList (node.Arguments);
+               }
+
+               public virtual void VisitExpressionList (List<Expression> list)
+               {
+                       if (list == null)
+                               return;
+
+                       for (int i = 0; i < list.Count; ++i)
+                               Visit (list [i]);
+               }
+
+               public virtual void VisitEnsures (Ensures node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Assertion);
+                       VisitExpression (node.UserMessage);
+               }
+
+               public virtual void VisitExpression (Expression node)
+               {
+                       if (node == null)
+                               return;
+
+                       //todo: maybe there will be something
+               }
+
+               public virtual void VisitExpressionStatement (ExpressionStatement node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Expression);
+               }
+
+               public virtual void VisitLiteral (Literal node)
+               {
+               }
+
+               public virtual void VisitLocal (Local node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitTypeNode (node.Type);
+
+                       //todo: maybe there should be something else
+               }
+
+               public virtual void VisitMemberBinding (MemberBinding node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.TargetObject);
+               }
+
+               public virtual void VisitMethod (Method node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitTypeNode (node.ReturnType);
+                       VisitParameterList (node.Parameters);
+                       VisitMethodContract (node.MethodContract);
+                       VisitBlock (node.Body);
+               }
+
+               public virtual void VisitParameterList (List<Parameter> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++)
+                               VisitParameter (node [i]);
+               }
+
+               public virtual void VisitMethodCall (MethodCall node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Callee);
+                       VisitExpressionList (node.Arguments);
+               }
+
+               public virtual void VisitMethodContract (MethodContract node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitRequiresList (node.Requires);
+                       VisitEnsuresList (node.Ensures);
+               }
+
+               public virtual void VisitEnsuresList (List<Ensures> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++)
+                               Visit (node [i]);
+               }
+
+               public virtual void VisitRequiresList (List<Requires> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++)
+                               Visit (node [i]);
+               }
+
+               public virtual void VisitParameter (Parameter node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitTypeNode (node.Type);
+
+                       //todo: there may be something else
+               }
+
+               public virtual void VisitRequires (Requires node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Assertion);
+                       VisitExpression (node.UserMessage);
+               }
+
+               public virtual void VisitReturn (Return node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Expression);
+               }
+
+               public virtual void VisitTargetExpression (Expression node)
+               {
+                       VisitExpression (node);
+               }
+
+               public virtual void VisitThis (This node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitTypeNode (node.Type);
+               }
+
+               public virtual void VisitTypeNode (TypeNode node)
+               {
+                       if (node == null)
+                               return;
+
+                       var clazz = node as Class;
+                       if (clazz != null)
+                               VisitTypeNode (clazz.BaseType);
+
+                       VisitPropertiesList (node.Properties);
+                       VisitMethodsList (node.Methods);
+                       VisitTypeNodeList (node.NestedTypes);
+               }
+
+               public virtual void VisitPropertiesList (List<Property> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++) {
+                               Property property = node [i];
+                               if (property != null)
+                                       Visit (node [i]);
+                       }
+               }
+
+               public virtual void VisitMethodsList (List<Method> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++) {
+                               Method method = node [i];
+                               if (method != null)
+                                       Visit (node [i]);
+                       }
+               }
+
+               public virtual void VisitTypeNodeList (List<TypeNode> node)
+               {
+                       if (node == null)
+                               return;
+
+                       for (int i = 0; i < node.Count; i++) {
+                               TypeNode typeNode = node [i];
+                               if (typeNode != null)
+                                       Visit (typeNode);
+                       }
+               }
+
+               public virtual void VisitUnaryExpression (UnaryExpression node)
+               {
+                       if (node == null)
+                               return;
+
+                       VisitExpression (node.Operand);
+               }
+
+               public virtual void VisitUnknownNodeType (Node node)
+               {
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST.Visitors/NodeVisitor.cs
new file mode 100644 (file)
index 0000000..adfed09
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// NodeVisitor.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       abstract class NodeVisitor {
+               public abstract Node Visit (Node node);
+
+               public virtual List<Expression> VisitExpressionList (List<Expression> list)
+               {
+                       if (list == null)
+                               return null;
+
+                       for (int i = 0; i < list.Count; ++i)
+                               list [i] = (Expression) Visit (list [i]);
+
+                       return list;
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..00d366f
--- /dev/null
@@ -0,0 +1,36 @@
+// 
+// ValueCodeVisitor.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 Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.AST.Visitors {
+       class ValueCodeVisitor<Variable> : 
+               CodeVisitor<Variable, Variable, IValueContextProvider<Variable>, IImmutableMap<Variable, LispList<Variable>>> {
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ArrayTypeNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ArrayTypeNode.cs
new file mode 100644 (file)
index 0000000..c6ca2be
--- /dev/null
@@ -0,0 +1,38 @@
+// 
+// ArrayTypeNode.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 Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class ArrayTypeNode : TypeNode {
+               public ArrayTypeNode (TypeNode type, int lowerBound, int rank) :
+                       base (new ArrayType (type.TypeDefinition, rank))
+               {
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/AssemblyNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/AssemblyNode.cs
new file mode 100644 (file)
index 0000000..04c7c6e
--- /dev/null
@@ -0,0 +1,86 @@
+// 
+// AssemblyNode.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.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class AssemblyNode : Node {
+               private readonly AssemblyDefinition definition;
+               private IEnumerable<Module> modules;
+
+               public AssemblyNode (AssemblyDefinition definition) : base (NodeType.Assembly)
+               {
+                       this.definition = definition;
+               }
+
+               public string FullName
+               {
+                       get { return this.definition.FullName; }
+               }
+
+               public IEnumerable<Module> Modules
+               {
+                       get
+                       {
+                               if (this.modules == null)
+                                       this.modules = this.definition.Modules.Select (it => new Module (it)).ToList ();
+                               return this.modules;
+                       }
+               }
+
+               public TypeNode GetType (string ns, string className)
+               {
+                       foreach (Module module in Modules) {
+                               TypeNode type = module.GetType (ns, className);
+                               if (type != null)
+                                       return type;
+                       }
+                       IEnumerable<TypeDefinition> enumerable = this.definition.Modules.SelectMany (m => m.Types);
+                       TypeDefinition firstOrDefault = enumerable.FirstOrDefault (t => t.Namespace == ns && t.Name == className);
+                       if (firstOrDefault == null)
+                               return null;
+
+                       return TypeNode.Create (firstOrDefault);
+               }
+
+               public static AssemblyNode ReadAssembly (string filename)
+               {
+                       var readerParameters = new ReaderParameters ();
+                       AssemblyDefinition definition = AssemblyDefinition.ReadAssembly (filename, readerParameters);
+
+                       return new AssemblyNode (definition);
+               }
+
+               public static AssemblyNode GetSystemAssembly ()
+               {
+                       return ReadAssembly (typeof (object).Module.Assembly.Location);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/AssignmentStatement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/AssignmentStatement.cs
new file mode 100644 (file)
index 0000000..abf51f4
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// AssignmentStatement.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.AST {
+       class AssignmentStatement : Statement {
+               public AssignmentStatement (Expression source, Expression target)
+                       : base (NodeType.AssignmentStatement)
+               {
+                       Source = source;
+                       Target = target;
+               }
+
+               public Expression Source { get; set; }
+               public Expression Target { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("{0} := {1};", Target, Source);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryExpression.cs
new file mode 100644 (file)
index 0000000..5d6cf08
--- /dev/null
@@ -0,0 +1,56 @@
+// 
+// BinaryExpression.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.AST {
+       class BinaryExpression : Expression {
+               public BinaryExpression (NodeType nodeType) : base (nodeType)
+               {
+               }
+
+               public BinaryExpression (NodeType nodeType, Expression operand1, Expression operand2) : base (nodeType)
+               {
+                       Operand1 = operand1;
+                       Operand2 = operand2;
+               }
+
+               public BinaryExpression (NodeType nodeType, Expression operand1, Expression operand2, TypeNode type)
+                       : base (nodeType, type)
+               {
+                       Operand1 = operand1;
+                       Operand2 = operand2;
+               }
+
+               public Expression Operand1 { get; set; }
+               public Expression Operand2 { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("({1} :{0}: {2})", NodeType, Operand1, Operand2);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BinaryOperator.cs
new file mode 100644 (file)
index 0000000..1b3a9f0
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// BinaryOperator.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.AST {
+       enum BinaryOperator {
+               Add,
+               Add_Ovf,
+               Add_Ovf_Un,
+               And,
+               Ceq,
+               Cobjeq,
+               Cne_Un,
+               Cge,
+               Cge_Un,
+               Cgt,
+               Cgt_Un,
+               Cle,
+               Cle_Un,
+               Clt,
+               Clt_Un,
+               Div,
+               Div_Un,
+               LogicalAnd,
+               LogicalOr,
+               Mul,
+               Mul_Ovf,
+               Mul_Ovf_Un,
+               Or,
+               Rem,
+               Rem_Un,
+               Shl,
+               Shr,
+               Shr_Un,
+               Sub,
+               Sub_Ovf,
+               Sub_Ovf_Un,
+               Xor
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Block.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Block.cs
new file mode 100644 (file)
index 0000000..f67107e
--- /dev/null
@@ -0,0 +1,50 @@
+// 
+// Block.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Block : Statement {
+               public Block (List<Statement> statements) : base (NodeType.Block)
+               {
+                       Statements = statements;
+               }
+
+               public Block () : base (NodeType.Block)
+               {
+               }
+
+               public int ILOffset { get; set; }
+               public List<Statement> Statements { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Block(Off:{0}, Stmts:{1})", ILOffset, Statements.Count);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BlockExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BlockExpression.cs
new file mode 100644 (file)
index 0000000..b96c029
--- /dev/null
@@ -0,0 +1,50 @@
+// 
+// BlockExpression.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.AST {
+       class BlockExpression : Expression {
+               public Block Block;
+
+               public BlockExpression (Block block, TypeNode type)
+                       : this ()
+               {
+                       this.Block = block;
+                       Type = type;
+               }
+
+               public BlockExpression (Block block) : this ()
+               {
+                       this.Block = block;
+               }
+
+               public BlockExpression ()
+                       : base (NodeType.BlockExpression)
+               {
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BodyParser.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/BodyParser.cs
new file mode 100644 (file)
index 0000000..df6a6f2
--- /dev/null
@@ -0,0 +1,856 @@
+// 
+// BodyParser.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 Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST {
+       class BodyParser {
+               private readonly MethodDefinition method;
+               private readonly Dictionary<int, Block> block_map = new Dictionary<int, Block> ();
+               private readonly Stack<Expression> evaluation_stack;
+
+               public BodyParser (MethodDefinition method)
+               {
+                       this.method = method;
+                       this.evaluation_stack = new Stack<Expression> (2);
+
+                       CoreSystemTypes.ModuleDefinition = this.method.Module;
+               }
+
+               public List<Statement> ParseBlocks ()
+               {
+                       CreateBlockMap ();
+                       var statements = new List<Statement> ();
+                       Block block = null;
+
+                       int counter = 0;
+                       Collection<Instruction> instructions = this.method.Body.Instructions;
+                       int size = instructions.Count;
+                       while (counter < size) {
+                               if (block == null) {
+                                       int offset = instructions [counter].Offset;
+                                       block = GetOrCreateBlock (offset);
+                                       statements.Add (block);
+                               }
+
+                               bool isNewBlock;
+                               counter = ParseStatement (instructions, counter, block.Statements, out isNewBlock);
+                               if (isNewBlock)
+                                       block = null;
+                       }
+
+                       statements.Add (GetOrCreateBlock (instructions [size - 1].Offset + 1));
+
+                       return statements;
+               }
+
+               private int ParseStatement (Collection<Instruction> instructions, int index, List<Statement> result, out bool isNewBlock)
+               {
+                       Expression expression = null;
+                       Statement statement = null;
+                       isNewBlock = false;
+
+                       bool needToRepeat = true;
+                       while (index < instructions.Count) {
+                               Instruction inst = instructions [index++];
+                               Code opcode = inst.OpCode.Code;
+                               bool isStatement = false;
+                               switch (opcode) {
+                               case Code.Nop:
+                                       statement = new Statement (NodeType.Nop);
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Ldarg_0:
+                               case Code.Ldarg_1:
+                               case Code.Ldarg_2:
+                               case Code.Ldarg_3:
+                                       expression = GetParameterExpression (opcode - Code.Ldarg_0);
+                                       break;
+                               case Code.Ldarg_S:
+                                       expression = GetParameterExpression ((int) inst.Operand);
+                                       break;
+                               case Code.Ldloc_0:
+                               case Code.Ldloc_1:
+                               case Code.Ldloc_2:
+                               case Code.Ldloc_3:
+                                       expression = GetLocalExpression (opcode - Code.Ldloc_0);
+                                       break;
+                               case Code.Ldloc_S:
+                                       expression = GetLocalExpression ((int) (inst.Operand));
+                                       break;
+                               case Code.Stloc_0:
+                               case Code.Stloc_1:
+                               case Code.Stloc_2:
+                               case Code.Stloc_3:
+                                       statement = new AssignmentStatement (PopOperand (), GetLocalExpression ((opcode - Code.Stloc_0)));
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Stloc_S:
+                                       statement = new AssignmentStatement (PopOperand (), GetLocalExpression ((VariableDefinition) (inst.Operand)));
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Starg_S:
+                                       statement = new AssignmentStatement (PopOperand (), GetParameterExpression ((int) (inst.Operand)));
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Ldarga_S:
+                                       throw new NotImplementedException ();
+                               case Code.Ldloca_S:
+                                       throw new NotImplementedException ();
+                               case Code.Ldnull:
+                                       expression = Literal.Null;
+                                       break;
+                               case Code.Ldc_I4_M1:
+                               case Code.Ldc_I4_0:
+                               case Code.Ldc_I4_1:
+                               case Code.Ldc_I4_2:
+                               case Code.Ldc_I4_3:
+                               case Code.Ldc_I4_4:
+                               case Code.Ldc_I4_5:
+                               case Code.Ldc_I4_6:
+                               case Code.Ldc_I4_7:
+                               case Code.Ldc_I4_8:
+                                       expression = GetLiteral ((opcode - Code.Ldc_I4_0), CoreSystemTypes.Instance.TypeInt32);
+                                       break;
+                               case Code.Ldc_I8:
+                                       expression = GetLiteral ((Int64) inst.Operand, CoreSystemTypes.Instance.TypeInt64);
+                                       break;
+                               case Code.Ldc_I4_S:
+                                       expression = GetLiteral ((int) (sbyte) inst.Operand, CoreSystemTypes.Instance.TypeInt32);
+                                       break;
+                               case Code.Ldc_I4:
+                                       expression = GetLiteral ((int) inst.Operand, CoreSystemTypes.Instance.TypeInt32);
+                                       break;
+                               case Code.Ldc_R4:
+                                       expression = GetLiteral ((float) inst.Operand, CoreSystemTypes.Instance.TypeSingle);
+                                       break;
+                               case Code.Ldc_R8:
+                                       expression = GetLiteral ((double) inst.Operand, CoreSystemTypes.Instance.TypeDouble);
+                                       break;
+                               case Code.Ret:
+                                       statement = new Return (TypeIsVoid (this.method.ReturnType) ? null : PopOperand ());
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Br_S:
+                                       statement = ParseBranch (inst, NodeType.Nop, 0, true, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Brfalse_S:
+                                       statement = ParseBranch (inst, NodeType.LogicalNot, 1, true, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Brtrue_S:
+                                       statement = ParseBranch (inst, NodeType.Nop, 1, true, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bne_Un_S:
+                                       statement = ParseBranch (inst, NodeType.Ne, 2, true, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bge_Un_S:
+                                       statement = ParseBranch (inst, NodeType.Ge, 2, true, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bgt_Un_S:
+                                       statement = ParseBranch (inst, NodeType.Gt, 2, true, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Ble_S:
+                                       statement = ParseBranch (inst, NodeType.Le, 2, true, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Blt_Un_S:
+                                       statement = ParseBranch (inst, NodeType.Lt, 2, true, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Br:
+                                       statement = ParseBranch (inst, NodeType.Nop, 0, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Brfalse:
+                                       statement = ParseBranch (inst, NodeType.LogicalNot, 0, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Brtrue:
+                                       statement = ParseBranch (inst, NodeType.Nop, 1, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Beq:
+                                       statement = ParseBranch (inst, NodeType.Eq, 2, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bge:
+                                       statement = ParseBranch (inst, NodeType.Ge, 2, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bgt:
+                                       statement = ParseBranch (inst, NodeType.Gt, 2, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Ble:
+                                       statement = ParseBranch (inst, NodeType.Le, 2, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Blt:
+                                       statement = ParseBranch (inst, NodeType.Lt, 2, false, false);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bne_Un:
+                                       statement = ParseBranch (inst, NodeType.LogicalNot, 2, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bge_Un:
+                                       statement = ParseBranch (inst, NodeType.Ge, 2, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Bgt_Un:
+                                       statement = ParseBranch (inst, NodeType.Gt, 2, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Ble_Un:
+                                       statement = ParseBranch (inst, NodeType.Le, 2, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Blt_Un:
+                                       statement = ParseBranch (inst, NodeType.Lt, 2, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Leave:
+                                       statement = ParseBranch (inst, NodeType.Nop, 0, false, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Leave_S:
+                                       statement = ParseBranch (inst, NodeType.Nop, 0, true, false, true);
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Endfinally:
+                                       statement = new EndFinally ();
+                                       isNewBlock = true;
+                                       needToRepeat = false;
+                                       break;
+                               case Code.Switch:
+                                       break;
+                               case Code.Ldind_I1:
+                                       break;
+                               case Code.Ldind_U1:
+                                       break;
+                               case Code.Ldind_I2:
+                                       break;
+                               case Code.Ldind_U2:
+                                       break;
+                               case Code.Ldind_I4:
+                                       break;
+                               case Code.Ldind_U4:
+                                       break;
+                               case Code.Ldind_I8:
+                                       break;
+                               case Code.Ldind_I:
+                                       break;
+                               case Code.Ldind_R4:
+                                       break;
+                               case Code.Ldind_R8:
+                                       break;
+                               case Code.Ldind_Ref:
+                                       break;
+                               case Code.Stind_Ref:
+                                       break;
+                               case Code.Stind_I1:
+                                       break;
+                               case Code.Stind_I2:
+                                       break;
+                               case Code.Stind_I4:
+                                       break;
+                               case Code.Stind_I8:
+                                       break;
+                               case Code.Stind_R4:
+                                       break;
+                               case Code.Stind_R8:
+                                       break;
+                               case Code.Add:
+                                       expression = ParseBinaryOperation (NodeType.Add);
+                                       break;
+                               case Code.Sub:
+                                       expression = ParseBinaryOperation (NodeType.Sub);
+                                       break;
+                               case Code.Mul:
+                                       expression = ParseBinaryOperation (NodeType.Mul);
+                                       break;
+                               case Code.Div:
+                                       expression = ParseBinaryOperation (NodeType.Div);
+                                       break;
+                               case Code.Div_Un:
+                                       expression = ParseBinaryOperation (NodeType.Div_Un);
+                                       break;
+                               case Code.Rem:
+                                       expression = ParseBinaryOperation (NodeType.Rem);
+                                       break;
+                               case Code.Rem_Un:
+                                       expression = ParseBinaryOperation (NodeType.Rem_Un);
+                                       break;
+                               case Code.And:
+                                       expression = ParseBinaryOperation (NodeType.And);
+                                       break;
+                               case Code.Or:
+                                       expression = ParseBinaryOperation (NodeType.Or);
+                                       break;
+                               case Code.Xor:
+                                       expression = ParseBinaryOperation (NodeType.Xor);
+                                       break;
+                               case Code.Shl:
+                                       expression = ParseBinaryOperation (NodeType.Shl);
+                                       break;
+                               case Code.Shr:
+                                       expression = ParseBinaryOperation (NodeType.Shr);
+                                       break;
+                               case Code.Shr_Un:
+                                       expression = ParseBinaryOperation (NodeType.Shr_Un);
+                                       break;
+                               case Code.Neg:
+                                       expression = ParseUnaryOperation (NodeType.Neg);
+                                       break;
+                               case Code.Not:
+                                       expression = ParseUnaryOperation (NodeType.Not);
+                                       break;
+                               case Code.Conv_I1:
+                                       expression = new UnaryExpression (NodeType.Conv_I1, PopOperand (), CoreSystemTypes.Instance.TypeSByte);
+                                       break;
+                               case Code.Conv_I2:
+                                       expression = new UnaryExpression (NodeType.Conv_I2, PopOperand (), CoreSystemTypes.Instance.TypeInt16);
+                                       break;
+                               case Code.Conv_I4:
+                                       expression = new UnaryExpression (NodeType.Conv_I4, PopOperand (), CoreSystemTypes.Instance.TypeInt32);
+                                       break;
+                               case Code.Conv_I8:
+                                       expression = new UnaryExpression (NodeType.Conv_I8, PopOperand (), CoreSystemTypes.Instance.TypeInt64);
+                                       break;
+                               case Code.Conv_R4:
+                                       expression = new UnaryExpression (NodeType.Conv_R4, PopOperand (), CoreSystemTypes.Instance.TypeSingle);
+                                       break;
+                               case Code.Conv_R8:
+                                       expression = new UnaryExpression (NodeType.Conv_R8, PopOperand (), CoreSystemTypes.Instance.TypeDouble);
+                                       break;
+                               case Code.Conv_U4:
+                                       expression = new UnaryExpression (NodeType.Conv_R8, PopOperand (), CoreSystemTypes.Instance.TypeUInt32);
+                                       break;
+                               case Code.Conv_U8:
+                                       expression = new UnaryExpression (NodeType.Conv_R8, PopOperand (), CoreSystemTypes.Instance.TypeUInt64);
+                                       break;
+                               case Code.Call:
+                                       expression = ParseCall (inst, NodeType.Call, out isStatement);
+                                       if (isStatement)
+                                               needToRepeat = false;
+                                       break;
+                               case Code.Callvirt:
+                                       expression = ParseCall (inst, NodeType.CallVirt, out isStatement);
+                                       if (isStatement)
+                                               needToRepeat = false;
+                                       break;
+                               case Code.Cpobj:
+                                       break;
+                               case Code.Ldobj:
+                                       break;
+                               case Code.Ldstr:
+                                       expression = GetLiteral (inst.Operand, CoreSystemTypes.Instance.TypeString);
+                                       break;
+                               case Code.Newobj:
+                                       expression = ParseNewObjectCreation (inst);
+                                       break;
+                               case Code.Castclass:
+                                       break;
+                               case Code.Isinst:
+                                       break;
+                               case Code.Conv_R_Un:
+                                       break;
+                               case Code.Unbox:
+                                       break;
+                               case Code.Throw:
+                                       isNewBlock = true;
+                                       break;
+                               case Code.Ldfld:
+                                       break;
+                               case Code.Ldflda:
+                                       break;
+                               case Code.Stfld:
+                                       break;
+                               case Code.Ldsfld:
+                                       break;
+                               case Code.Ldsflda:
+                                       break;
+                               case Code.Stsfld:
+                                       break;
+                               case Code.Stobj:
+                                       break;
+                               case Code.Conv_Ovf_I1_Un:
+                                       break;
+                               case Code.Conv_Ovf_I2_Un:
+                                       break;
+                               case Code.Conv_Ovf_I4_Un:
+                                       break;
+                               case Code.Conv_Ovf_I8_Un:
+                                       break;
+                               case Code.Conv_Ovf_U1_Un:
+                                       break;
+                               case Code.Conv_Ovf_U2_Un:
+                                       break;
+                               case Code.Conv_Ovf_U4_Un:
+                                       break;
+                               case Code.Conv_Ovf_U8_Un:
+                                       break;
+                               case Code.Conv_Ovf_I_Un:
+                                       break;
+                               case Code.Conv_Ovf_U_Un:
+                                       break;
+                               case Code.Box:
+                                       break;
+                               case Code.Newarr:
+                                       break;
+                               case Code.Ldlen:
+                                       break;
+                               case Code.Ldelema:
+                                       break;
+                               case Code.Ldelem_I1:
+                                       break;
+                               case Code.Ldelem_U1:
+                                       break;
+                               case Code.Ldelem_I2:
+                                       break;
+                               case Code.Ldelem_U2:
+                                       break;
+                               case Code.Ldelem_I4:
+                                       break;
+                               case Code.Ldelem_U4:
+                                       break;
+                               case Code.Ldelem_I8:
+                                       break;
+                               case Code.Ldelem_I:
+                                       break;
+                               case Code.Ldelem_R4:
+                                       break;
+                               case Code.Ldelem_R8:
+                                       break;
+                               case Code.Ldelem_Ref:
+                                       break;
+                               case Code.Stelem_I:
+                                       break;
+                               case Code.Stelem_I1:
+                                       break;
+                               case Code.Stelem_I2:
+                                       break;
+                               case Code.Stelem_I4:
+                                       break;
+                               case Code.Stelem_I8:
+                                       break;
+                               case Code.Stelem_R4:
+                                       break;
+                               case Code.Stelem_R8:
+                                       break;
+                               case Code.Stelem_Ref:
+                                       break;
+                               case Code.Ldelem_Any:
+                                       break;
+                               case Code.Stelem_Any:
+                                       break;
+                               case Code.Unbox_Any:
+                                       break;
+                               case Code.Conv_Ovf_I1:
+                                       break;
+                               case Code.Conv_Ovf_U1:
+                                       break;
+                               case Code.Conv_Ovf_I2:
+                                       break;
+                               case Code.Conv_Ovf_U2:
+                                       break;
+                               case Code.Conv_Ovf_I4:
+                                       break;
+                               case Code.Conv_Ovf_U4:
+                                       break;
+                               case Code.Conv_Ovf_I8:
+                                       break;
+                               case Code.Conv_Ovf_U8:
+                                       break;
+                               case Code.Refanyval:
+                                       break;
+                               case Code.Ckfinite:
+                                       break;
+                               case Code.Mkrefany:
+                                       break;
+                               case Code.Ldtoken:
+                                       break;
+                               case Code.Conv_U2:
+                                       break;
+                               case Code.Conv_U1:
+                                       break;
+                               case Code.Conv_I:
+                                       break;
+                               case Code.Conv_Ovf_I:
+                                       break;
+                               case Code.Conv_Ovf_U:
+                                       break;
+                               case Code.Add_Ovf:
+                                       break;
+                               case Code.Add_Ovf_Un:
+                                       break;
+                               case Code.Mul_Ovf:
+                                       break;
+                               case Code.Mul_Ovf_Un:
+                                       break;
+                               case Code.Sub_Ovf:
+                                       break;
+                               case Code.Sub_Ovf_Un:
+                                       break;
+
+                               case Code.Stind_I:
+                                       break;
+                               case Code.Conv_U:
+                                       break;
+                               case Code.Arglist:
+                                       break;
+                               case Code.Ceq:
+                                       expression = ParseBinaryComparison (NodeType.Ceq);
+                                       break;
+                               case Code.Cgt:
+                                       expression = ParseBinaryComparison (NodeType.Cgt);
+                                       break;
+                               case Code.Cgt_Un:
+                                       break;
+                               case Code.Clt:
+                                       expression = ParseBinaryComparison (NodeType.Clt);
+                                       break;
+                               case Code.Clt_Un:
+                                       break;
+                               case Code.Ldftn:
+                                       break;
+                               case Code.Ldvirtftn:
+                                       break;
+                               case Code.Ldarg:
+                                       break;
+                               case Code.Ldarga:
+                                       break;
+                               case Code.Starg:
+                                       break;
+                               case Code.Ldloc:
+                                       break;
+                               case Code.Ldloca:
+                                       break;
+                               case Code.Stloc:
+                                       break;
+                               case Code.Localloc:
+                                       break;
+                               case Code.Endfilter:
+                                       isNewBlock = true;
+                                       break;
+                               case Code.Unaligned:
+                                       break;
+                               case Code.Volatile:
+                                       break;
+                               case Code.Tail:
+                                       break;
+                               case Code.Initobj:
+                                       break;
+                               case Code.Constrained:
+                                       break;
+                               case Code.Cpblk:
+                                       break;
+                               case Code.Initblk:
+                                       break;
+                               case Code.No:
+                                       break;
+                               case Code.Rethrow:
+                                       isNewBlock = true;
+                                       break;
+                               case Code.Sizeof:
+                                       break;
+                               case Code.Refanytype:
+                                       break;
+                               case Code.Readonly:
+                                       break;
+                               default:
+                                       needToRepeat = false;
+                                       break;
+                               }
+                               if (!needToRepeat)
+                                       break;
+
+                               int offset = inst.Next == null ? inst.Offset + 1 : inst.Next.Offset;
+                               if (!this.block_map.ContainsKey (offset))
+                                       this.evaluation_stack.Push (expression);
+                               else {
+                                       isNewBlock = true;
+                                       break;
+                               }
+                       }
+
+
+                       while (this.evaluation_stack.Count > 0) {
+                               Statement stmt = new ExpressionStatement (this.evaluation_stack.Pop ());
+                               result.Add (stmt);
+                       }
+
+                       if (statement == null)
+                               statement = new ExpressionStatement (expression);
+
+                       result.Add (statement);
+                       if (!isNewBlock)
+                               isNewBlock = this.block_map.ContainsKey (instructions [index].Offset);
+
+                       return index;
+               }
+
+
+               private Expression ParseNewObjectCreation (Instruction inst)
+               {
+                       Method method = GetMethodFromMethodCallInstruction (inst);
+                       int count = method.Parameters.Count;
+                       List<Expression> arguments;
+                       {
+                               var expressions = new Expression[count];
+                               for (int index = count - 1; index >= 0; index--)
+                                       expressions [index] = PopOperand ();
+
+                               arguments = new List<Expression> (expressions);
+                       }
+
+                       var construct = new Construct (new MemberBinding (null, method), arguments) {Type = method.DeclaringType};
+
+                       return construct;
+               }
+
+               private Expression ParseUnaryOperation (NodeType operatorType)
+               {
+                       Expression operand = PopOperand ();
+                       return new UnaryExpression (operatorType, operand, operand.Type);
+               }
+
+               private Expression ParseBinaryComparison (NodeType comparisonType)
+               {
+                       Expression op1;
+                       Expression op2;
+                       Expression binaryExpression = ParseBinaryExpressionWithoutType (comparisonType, out op1, out op2);
+
+                       binaryExpression.Type = CoreSystemTypes.Instance.TypeByte;
+
+                       return binaryExpression;
+               }
+
+               private Expression ParseBinaryOperation (NodeType operatorType)
+               {
+                       Expression op1;
+                       Expression op2;
+                       Expression binaryExpression = ParseBinaryExpressionWithoutType (operatorType, out op1, out op2);
+
+                       binaryExpression.Type = op1.Type ?? op2.Type;
+
+                       return binaryExpression;
+               }
+
+               private Expression ParseBinaryExpressionWithoutType (NodeType operatorType, out Expression op1, out Expression op2)
+               {
+                       op2 = PopOperand ();
+                       op1 = PopOperand ();
+
+                       return new BinaryExpression (operatorType, op1, op2);
+               }
+
+               private Statement ParseBranch (Instruction inst, NodeType operatorType, int operandCount, bool isShortOffset, bool unsigned)
+               {
+                       return ParseBranch (inst, operatorType, operandCount, isShortOffset, unsigned, false);
+               }
+
+               private Statement ParseBranch (Instruction inst, NodeType operatorType, int operandCount, bool isShortOffset, bool unsigned, bool leavesExceptionBlock)
+               {
+                       Expression operand = operandCount > 1 ? PopOperand () : null;
+                       Expression expression = operandCount > 0 ? PopOperand () : null;
+                       Expression condition = operandCount > 1
+                                               ? new BinaryExpression (operatorType, expression, operand)
+                                               : (operandCount > 0
+                                                       ? (operatorType == NodeType.Nop
+                                                               ? expression
+                                                               : new UnaryExpression (operatorType, expression)
+                                                         )
+                                                       : null);
+
+                       int offset = ((Instruction) inst.Operand).Offset;
+                       Block target = this.block_map [offset];
+
+                       return new Branch (condition, target, isShortOffset, unsigned, leavesExceptionBlock);
+               }
+
+               private MethodCall ParseCall (Instruction instruction, NodeType typeOfCall, out bool isStatement)
+               {
+                       Method method = GetMethodFromMethodCallInstruction (instruction);
+                       isStatement = TypeIsVoid (method.ReturnType);
+                       int parametersCount = method.Parameters == null ? 0 : method.Parameters.Count;
+                       int n = typeOfCall != NodeType.Jmp ? parametersCount : 0;
+                       List<Expression> arguments;
+                       {
+                               var expressions = new Expression[n];
+
+                               for (int index = n - 1; index >= 0; --index)
+                                       expressions [index] = PopOperand ();
+                               arguments = new List<Expression> (expressions);
+                       }
+
+                       var methodCall = new MethodCall (new MemberBinding (method.IsStatic ? null : PopOperand (), method), arguments, typeOfCall) {Type = method.ReturnType};
+                       return methodCall;
+               }
+
+               private Method GetMethodFromMethodCallInstruction (Instruction instruction)
+               {
+                       var methodReference = instruction.Operand as MethodReference;
+
+                       var method = new Method (methodReference.Resolve ());
+                       return method;
+               }
+
+               private Expression GetParameterExpression (int index)
+               {
+                       if (this.method.IsStatic)
+                               return new Parameter (this.method.Parameters [index]);
+                       if (index == 0)
+                               return new Parameter (this.method.Body.ThisParameter);
+
+                       return new Parameter (this.method.Parameters [index - 1]);
+               }
+
+               private static bool TypeIsVoid (TypeNode type)
+               {
+                       return type.FullName.Equals ("System.Void");
+               }
+
+               private static bool TypeIsVoid (TypeReference type)
+               {
+                       return type.FullName.Equals ("System.Void");
+               }
+
+               private Expression GetLocalExpression (int index)
+               {
+                       return new Local (this.method.Body.Variables [index]);
+               }
+
+               private Expression GetLocalExpression (VariableDefinition variable)
+               {
+                       return new Local (variable);
+               }
+
+               private Expression PopOperand ()
+               {
+                       return this.evaluation_stack.Pop ();
+               }
+
+               private Literal GetLiteral (object constant, TypeNode type)
+               {
+                       return new Literal (constant, type);
+               }
+
+               #region Block map creation
+               private void CreateBlockMap ()
+               {
+                       foreach (Instruction inst in this.method.Body.Instructions)
+                               ProcessInstructionForBlockMap (inst);
+               }
+
+               private void ProcessInstructionForBlockMap (Instruction inst)
+               {
+                       switch (inst.OpCode.Code) {
+                       case Code.Leave:
+                       case Code.Br:
+                       case Code.Brfalse:
+                       case Code.Brtrue:
+                       case Code.Beq:
+                       case Code.Bge:
+                       case Code.Bgt:
+                       case Code.Ble:
+                       case Code.Blt:
+                       case Code.Bne_Un:
+                       case Code.Bge_Un:
+                       case Code.Bgt_Un:
+                       case Code.Ble_Un:
+                       case Code.Blt_Un:
+                               GetOrCreateBlock (((Instruction) inst.Operand).Offset);
+                               break;
+                       case Code.Leave_S:
+                       case Code.Br_S:
+                       case Code.Brfalse_S:
+                       case Code.Brtrue_S:
+                       case Code.Beq_S:
+                       case Code.Bge_S:
+                       case Code.Bgt_S:
+                       case Code.Ble_S:
+                       case Code.Blt_S:
+                       case Code.Bne_Un_S:
+                       case Code.Bge_Un_S:
+                       case Code.Bgt_Un_S:
+                       case Code.Ble_Un_S:
+                       case Code.Blt_Un_S:
+                               GetOrCreateBlock (((Instruction) inst.Operand).Offset);
+                               break;
+                       case Code.Switch:
+                               break;
+                       }
+               }
+
+               private Block GetOrCreateBlock (int address)
+               {
+                       Block block;
+                       if (!this.block_map.TryGetValue (address, out block)) {
+                               this.block_map [address] = (block = new Block (new List<Statement> ()));
+                               block.ILOffset = address;
+                       }
+                       return block;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Branch.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Branch.cs
new file mode 100644 (file)
index 0000000..b17dede
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// Branch.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.AST {
+       class Branch : Statement {
+               public readonly bool LeavesExceptionBlock;
+               public Expression Condition;
+               public Block Target;
+               public bool IsShortOffset;
+               public bool Unsigned;
+
+               public Branch (Expression condition, Block target, bool isShortOffset, bool unsigned, bool leavesExceptionBlock) : base (NodeType.Branch)
+               {
+                       this.Condition = condition;
+                       this.Target = target;
+                       this.IsShortOffset = isShortOffset;
+                       this.Unsigned = unsigned;
+                       this.LeavesExceptionBlock = leavesExceptionBlock;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Branch({0}, {1})", this.Condition == null ? "<no cond>" : this.Condition.ToString (), this.Target == null ? "<no target>" : this.Target.ToString ());
+               }
+       }
+
+       enum BranchOperator {
+               Beq,
+               Bge,
+               Bge_Un,
+               Bgt,
+               Bgt_Un,
+               Ble,
+               Ble_Un,
+               Blt,
+               Blt_Un,
+               Bne_un
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/CatchFilter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/CatchFilter.cs
new file mode 100644 (file)
index 0000000..681c64c
--- /dev/null
@@ -0,0 +1,45 @@
+// 
+// CatchFilter.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.AST {
+       class CatchFilter : Statement {
+               public CatchFilter () : base (NodeType.Filter)
+               {
+               }
+
+               public CatchFilter (Block block, Expression expression)
+                       : base (NodeType.Filter)
+               {
+                       Block = block;
+                       Expression = expression;
+               }
+
+               public Block Block { get; set; }
+               public Expression Expression { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Class.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Class.cs
new file mode 100644 (file)
index 0000000..128d3ac
--- /dev/null
@@ -0,0 +1,66 @@
+// 
+// Class.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.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Class : TypeNode {
+               public Class (TypeDefinition firstOrDefault) : base (firstOrDefault)
+               {
+                       NodeType = NodeType.Class;
+               }
+
+               public IEnumerable<Method> GetMethods (string name, params TypeNode[] args)
+               {
+                       IEnumerable<Method> enumerable = Methods.Where (m => m.Name == name);
+                       foreach (Method method in enumerable) {
+                               List<Parameter> parameters = method.Parameters;
+                               bool ok = true;
+                               if (args.Length != parameters.Count)
+                                       continue;
+
+                               for (int i = 0; i < args.Length; i++) {
+                                       if (!parameters [i].Type.Equals (args [i])) {
+                                               ok = false;
+                                               break;
+                                       }
+                               }
+
+                               if (ok)
+                                       yield return method;
+                       }
+               }
+
+               public Method GetMethod (string name, params TypeNode[] args)
+               {
+                       return GetMethods (name, args).FirstOrDefault ();
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Construct.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Construct.cs
new file mode 100644 (file)
index 0000000..11a5efe
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// Construct.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Construct : NaryExpression {
+               public Construct ()
+                       : base (null, NodeType.Construct)
+               {
+               }
+
+               public Construct (Expression constructor, List<Expression> arguments)
+                       : base (arguments, NodeType.Construct)
+               {
+                       Constructor = constructor;
+               }
+
+               public Expression Constructor { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/CoreSystemTypes.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/CoreSystemTypes.cs
new file mode 100644 (file)
index 0000000..0fb0a3d
--- /dev/null
@@ -0,0 +1,206 @@
+// 
+// CoreSystemTypes.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 Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       sealed class CoreSystemTypes {
+               private static CoreSystemTypes _instance;
+
+               private readonly ModuleDefinition Module;
+               private Lazy<AssemblyNode> systemAssembly;
+               private Lazy<TypeNode> typeArray;
+               private Lazy<TypeNode> typeBoolean;
+               private Lazy<TypeNode> typeByte;
+               private Lazy<TypeNode> typeChar;
+               private Lazy<TypeNode> typeDouble;
+               private Lazy<TypeNode> typeInt16;
+               private Lazy<TypeNode> typeInt32;
+               private Lazy<TypeNode> typeInt64;
+               private Lazy<TypeNode> typeIntPtr;
+               private Lazy<TypeNode> typeObject;
+               private Lazy<TypeNode> typeSByte;
+               private Lazy<TypeNode> typeSingle;
+               private Lazy<TypeNode> typeString;
+               private Lazy<TypeNode> typeSystemType;
+               private Lazy<TypeNode> typeUInt16;
+               private Lazy<TypeNode> typeUInt32;
+               private Lazy<TypeNode> typeUInt64;
+
+               private Lazy<TypeNode> typeUIntPtr;
+               private Lazy<TypeNode> typeVoid;
+
+               public CoreSystemTypes (ModuleDefinition module)
+               {
+                       this.Module = module;
+
+                       InitializeLazyTypes ();
+               }
+
+               public static ModuleDefinition ModuleDefinition { get; set; }
+
+               public static CoreSystemTypes Instance
+               {
+                       get { return GetOrCreateInstance (ModuleDefinition); }
+               }
+
+               public TypeNode TypeObject
+               {
+                       get { return this.typeObject.Value; }
+               }
+
+               public TypeNode TypeString
+               {
+                       get { return this.typeString.Value; }
+               }
+
+               public TypeNode TypeBoolean
+               {
+                       get { return this.typeBoolean.Value; }
+               }
+
+               public TypeNode TypeVoid
+               {
+                       get { return this.typeVoid.Value; }
+               }
+
+               public TypeNode TypeSByte
+               {
+                       get { return this.typeSByte.Value; }
+               }
+
+               public TypeNode TypeByte
+               {
+                       get { return this.typeByte.Value; }
+               }
+
+               public TypeNode TypeInt16
+               {
+                       get { return this.typeInt16.Value; }
+               }
+
+               public TypeNode TypeInt32
+               {
+                       get { return this.typeInt32.Value; }
+               }
+
+               public TypeNode TypeInt64
+               {
+                       get { return this.typeInt64.Value; }
+               }
+
+               public TypeNode TypeSingle
+               {
+                       get { return this.typeSingle.Value; }
+               }
+
+               public TypeNode TypeDouble
+               {
+                       get { return this.typeDouble.Value; }
+               }
+
+               public TypeNode TypeUInt16
+               {
+                       get { return this.typeUInt16.Value; }
+               }
+
+               public TypeNode TypeUInt32
+               {
+                       get { return this.typeUInt32.Value; }
+               }
+
+               public TypeNode TypeUInt64
+               {
+                       get { return this.typeUInt64.Value; }
+               }
+
+               public AssemblyNode SystemAssembly
+               {
+                       get { return this.systemAssembly.Value; }
+               }
+
+               public TypeNode TypeIntPtr
+               {
+                       get { return this.typeIntPtr.Value; }
+               }
+
+               public TypeNode TypeArray
+               {
+                       get { return this.typeArray.Value; }
+               }
+
+               public TypeNode TypeUIntPtr
+               {
+                       get { return this.typeUIntPtr.Value; }
+               }
+
+               public TypeNode TypeChar
+               {
+                       get { return this.typeChar.Value; }
+               }
+
+               public TypeNode TypeSystemType
+               {
+                       get { return this.typeSystemType.Value; }
+               }
+
+               private static CoreSystemTypes GetOrCreateInstance (ModuleDefinition module)
+               {
+                       if (_instance == null)
+                               _instance = new CoreSystemTypes (module);
+
+                       return _instance;
+               }
+
+               private void InitializeLazyTypes ()
+               {
+                       this.typeVoid = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (void))));
+                       this.typeSByte = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (SByte))));
+                       this.typeByte = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Byte))));
+                       this.typeInt16 = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Int16))));
+                       this.typeInt32 = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Int32))));
+                       this.typeInt64 = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Int64))));
+                       this.typeUInt16 = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (UInt16))));
+                       this.typeUInt32 = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (UInt32))));
+                       this.typeUInt64 = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (UInt64))));
+                       this.typeSingle = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Single))));
+                       this.typeDouble = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Double))));
+                       this.typeBoolean = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Boolean))));
+                       this.typeObject = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (object))));
+                       this.typeString = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (string))));
+                       this.typeArray = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Array))));
+                       this.typeIntPtr = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (IntPtr))));
+                       this.typeUIntPtr = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (UIntPtr))));
+                       this.typeChar = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (char))));
+                       this.typeSystemType = new Lazy<TypeNode> (() => TypeNode.Create (this.Module.Import (typeof (Type))));
+
+                       this.systemAssembly = new Lazy<AssemblyNode> (() => AssemblyNode.GetSystemAssembly ());
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/EndFinally.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/EndFinally.cs
new file mode 100644 (file)
index 0000000..029234b
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// EndFinally.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.AST {
+       class EndFinally : Statement {
+               public EndFinally () : base (NodeType.EndFinally)
+               {
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Ensures.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Ensures.cs
new file mode 100644 (file)
index 0000000..1f2cebd
--- /dev/null
@@ -0,0 +1,47 @@
+// 
+// Ensures.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.AST {
+       class Ensures : MethodContractElement {
+               public Ensures ()
+                       : base (NodeType.Ensures)
+               {
+               }
+
+               public Ensures (NodeType nodeType)
+                       : base (nodeType)
+               {
+               }
+
+               public Ensures (Expression condition)
+                       : this ()
+               {
+                       Assertion = condition;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ExceptionHandler.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ExceptionHandler.cs
new file mode 100644 (file)
index 0000000..d4ac7ff
--- /dev/null
@@ -0,0 +1,43 @@
+// 
+// ExceptionHandler.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.AST {
+       class ExceptionHandler : Node {
+               public ExceptionHandler () : base (NodeType.ExceptionHandler)
+               {
+               }
+
+               public NodeType HandlerType { get; set; }
+               public Block TryStartBlock { get; set; }
+               public Block BlockAfterTryEnd { get; set; }
+               public Block HandlerStartBlock { get; set; }
+               public Block BlockAfterHandlerEnd { get; set; }
+               public Block FilterExpression { get; set; }
+               public TypeNode FilterType { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Expression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Expression.cs
new file mode 100644 (file)
index 0000000..8b6c1c8
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+// Expression.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.AST {
+       class Expression : Node {
+               protected TypeNode type;
+
+               public Expression (NodeType nodeType) : base (nodeType)
+               {
+               }
+
+               public Expression (NodeType nodeType, TypeNode type) : base (nodeType)
+               {
+                       this.type = type;
+               }
+
+               public virtual TypeNode Type
+               {
+                       get { return this.type; }
+                       set { this.type = value; }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ExpressionStatement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/ExpressionStatement.cs
new file mode 100644 (file)
index 0000000..73ae3ae
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+// ExpressionStatement.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.AST {
+       class ExpressionStatement : Statement {
+               public ExpressionStatement () : base (NodeType.ExpressionStatement)
+               {
+               }
+
+               public ExpressionStatement (Expression expression)
+                       : base (NodeType.ExpressionStatement)
+               {
+                       Expression = expression;
+               }
+
+               public Expression Expression { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("ExpressionStatement({0})", Expression);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/FaultHandler.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/FaultHandler.cs
new file mode 100644 (file)
index 0000000..0c8a7ad
--- /dev/null
@@ -0,0 +1,42 @@
+// 
+// FaultHandler.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.AST {
+       class FaultHandler : Statement {
+               public FaultHandler () : base (NodeType.FaultHandler)
+               {
+               }
+
+               public FaultHandler (Block block) : this ()
+               {
+                       Block = block;
+               }
+
+               public Block Block { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Field.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Field.cs
new file mode 100644 (file)
index 0000000..122fe53
--- /dev/null
@@ -0,0 +1,107 @@
+// 
+// Field.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 Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Field : Member {
+               private readonly FieldDefinition definition;
+
+               public Field (FieldDefinition definition) : base (NodeType.Field)
+               {
+                       this.definition = definition;
+               }
+
+               #region Overrides of Member
+               public override bool IsStatic
+               {
+                       get { return this.definition.IsStatic; }
+               }
+
+               public TypeNode FieldType
+               {
+                       get { return TypeNode.Create (this.definition.FieldType); }
+               }
+
+               public string Name
+               {
+                       get { return this.definition.Name; }
+               }
+
+               public override TypeNode DeclaringType
+               {
+                       get { return TypeNode.Create (this.definition.DeclaringType); }
+               }
+
+               public override Module Module
+               {
+                       get { return new Module (this.definition.Module); }
+               }
+
+               public override bool IsPublic
+               {
+                       get { return this.definition.IsPublic; }
+               }
+
+               public override bool IsPrivate
+               {
+                       get { return this.definition.IsPrivate; }
+               }
+
+               public override bool IsAssembly
+               {
+                       get { return this.definition.IsAssembly; }
+               }
+
+               public override bool IsFamily
+               {
+                       get { return this.definition.IsFamily; }
+               }
+
+               public override bool IsFamilyOrAssembly
+               {
+                       get { return this.definition.IsFamilyOrAssembly; }
+               }
+
+               public override bool IsFamilyAndAssembly
+               {
+                       get { return this.definition.IsFamilyAndAssembly; }
+               }
+
+               public bool IsReadonly
+               {
+                       get { return this.definition.IsInitOnly; }
+               }
+
+               public bool IsCompilerGenerated
+               {
+                       get { return this.definition.IsCompilerControlled; }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Literal.cs
new file mode 100644 (file)
index 0000000..e9e8103
--- /dev/null
@@ -0,0 +1,55 @@
+// 
+// Literal.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.AST {
+       sealed class Literal : Expression {
+               public static Literal Null = new Literal (null);
+               public object Value;
+
+               public Literal () : base (NodeType.Literal)
+               {
+               }
+
+               public Literal (object value)
+                       : base (NodeType.Literal)
+               {
+                       this.Value = value;
+               }
+
+               public Literal (object value, TypeNode type) : base (NodeType.Literal)
+               {
+                       this.Value = value;
+                       this.type = type;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Literal({0})", this.Value ?? "<null>");
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Local.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Local.cs
new file mode 100644 (file)
index 0000000..c941394
--- /dev/null
@@ -0,0 +1,65 @@
+// 
+// Local.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 Mono.Cecil.Cil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Local : Variable {
+               public Local (VariableDefinition definition)
+                       : base (NodeType.Local)
+               {
+                       Definition = definition;
+                       this.type = TypeNode.Create (definition.VariableType);
+               }
+
+               public VariableDefinition Definition { get; private set; }
+
+               public string Name
+               {
+                       get { return ToString (); }
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Local({0})", Definition);
+               }
+
+               public override bool Equals (object obj)
+               {
+                       var other = obj as Local;
+                       if (other != null)
+                               return other.Definition == Definition;
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return Definition.GetHashCode ();
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Member.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Member.cs
new file mode 100644 (file)
index 0000000..7d8f6f2
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// Member.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.AST {
+       abstract class Member : Node {
+               public Member (NodeType nodeType) : base (nodeType)
+               {
+               }
+
+               public abstract TypeNode DeclaringType { get; }
+               public abstract Module Module { get; }
+
+               public abstract bool IsStatic { get; }
+               public abstract bool IsPublic { get; }
+               public abstract bool IsPrivate { get; }
+               public abstract bool IsAssembly { get; }
+               public abstract bool IsFamily { get; }
+               public abstract bool IsFamilyOrAssembly { get; }
+               public abstract bool IsFamilyAndAssembly { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MemberBinding.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MemberBinding.cs
new file mode 100644 (file)
index 0000000..3b4e073
--- /dev/null
@@ -0,0 +1,58 @@
+// 
+// MemberBinding.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.AST {
+       class MemberBinding : Expression {
+               public MemberBinding ()
+                       : base (NodeType.MemberBinding)
+               {
+               }
+
+               public MemberBinding (Expression targetObject, Member boundMember) : base (NodeType.MemberBinding)
+               {
+                       BoundMember = boundMember;
+                       TargetObject = targetObject;
+                       switch (boundMember.NodeType) {
+                       case NodeType.Method:
+                               Type = ((Method) boundMember).ReturnType;
+                               break;
+                       default:
+                               Type = boundMember as TypeNode;
+                               break;
+                       }
+               }
+
+               public Member BoundMember { get; set; }
+               public Expression TargetObject { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("MemberBinding({0}.{1})", TargetObject == null ? "<no target>" : TargetObject.ToString (), BoundMember);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Method.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Method.cs
new file mode 100644 (file)
index 0000000..48344cf
--- /dev/null
@@ -0,0 +1,345 @@
+// 
+// Method.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.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Method : Member, IEquatable<Method> {
+               #region Delegates
+               public delegate void MethodContractProvider (Method method);
+               #endregion
+
+               private readonly MethodDefinition definition;
+               private Block block;
+               private MethodContract contract;
+               private MethodContractProvider method_contract_provider;
+               private List<Parameter> parameters;
+               private TypeNode returnType;
+               private This thisParameter;
+
+               public Method (MethodDefinition definition)
+                       : base (NodeType.Method)
+               {
+                       this.definition = definition;
+               }
+
+               private Method (MethodDefinition definition, Block block) : base (NodeType.Method)
+               {
+                       this.definition = definition;
+                       this.block = block;
+               }
+
+               public bool HasGenericParameters
+               {
+                       get { return this.definition.HasGenericParameters; }
+               }
+
+               public MethodDefinition Definition
+               {
+                       get { return this.definition; }
+               }
+
+               public override TypeNode DeclaringType
+               {
+                       get { return TypeNode.Create (this.definition.DeclaringType); }
+               }
+
+               public override Module Module
+               {
+                       get { return new Module (this.definition.Module); }
+               }
+
+               public Method OverriddenMethod
+               {
+                       get
+                       {
+                               if (!this.definition.HasOverrides)
+                                       return null;
+                               return ParseMethodDefinition (this.definition.Overrides [0].Resolve ());
+                       }
+               }
+
+               public Block Body
+               {
+                       get
+                       {
+                               if (this.block == null)
+                                       this.block = ParseMethodBlock (this.definition);
+                               return this.block;
+                       }
+                       set { this.block = value; }
+               }
+
+               public MethodContract MethodContract
+               {
+                       get
+                       {
+                               if (this.contract == null && ContractProvider != null) {
+                                       MethodContractProvider provider = ContractProvider;
+                                       ContractProvider = null;
+                                       provider (this);
+                               }
+                               return this.contract;
+                       }
+                       set
+                       {
+                               this.contract = value;
+                               if (value != null)
+                                       this.contract.DeclaringMethod = this;
+                               ContractProvider = null;
+                       }
+               }
+
+               public MethodContractProvider ContractProvider
+               {
+                       get { return this.method_contract_provider; }
+                       set
+                       {
+                               if (value == null) {
+                                       this.method_contract_provider = null;
+                                       return;
+                               }
+
+                               if (this.method_contract_provider != null)
+                                       this.method_contract_provider += value;
+                               else
+                                       this.method_contract_provider = value;
+
+                               this.contract = null;
+                       }
+               }
+
+
+               public bool IsFinal
+               {
+                       get { return this.definition.IsFinal; }
+               }
+
+               public bool HasBody
+               {
+                       get { return this.definition.HasBody; }
+               }
+
+               public override bool IsPrivate
+               {
+                       get { return this.definition.IsPrivate; }
+               }
+
+               public override bool IsAssembly
+               {
+                       get { return this.definition.IsAssembly; }
+               }
+
+               public override bool IsFamily
+               {
+                       get { return this.definition.IsFamily; }
+               }
+
+               public override bool IsFamilyOrAssembly
+               {
+                       get { return this.definition.IsFamilyOrAssembly; }
+               }
+
+               public override bool IsFamilyAndAssembly
+               {
+                       get { return this.definition.IsFamilyAndAssembly; }
+               }
+
+               public override bool IsPublic
+               {
+                       get { return this.definition.IsPublic; }
+               }
+
+               public bool IsProtected
+               {
+                       get { return this.definition.IsFamily; }
+               }
+
+               public bool IsProtectedOrInternal
+               {
+                       get { return this.definition.IsFamilyOrAssembly; }
+               }
+
+               public bool IsProtectedAndInternal
+               {
+                       get { return this.definition.IsFamilyAndAssembly; }
+               }
+
+               public string Name
+               {
+                       get { return this.definition.Name; }
+               }
+
+               public string FullName
+               {
+                       get { return this.definition.FullName; }
+               }
+
+               public bool HasOverrides
+               {
+                       get { return this.definition.HasOverrides; }
+               }
+
+               public bool IsVirtual
+               {
+                       get { return this.definition.IsVirtual; }
+               }
+
+               public override bool IsStatic
+               {
+                       get { return this.definition.IsStatic; }
+               }
+
+               public bool IsNewSlot
+               {
+                       get { return this.definition.IsNewSlot; }
+               }
+
+               public bool IsAbstract
+               {
+                       get { return this.definition.IsAbstract; }
+               }
+
+               public bool IsConstructor
+               {
+                       get { return this.definition.IsConstructor; }
+               }
+
+               public List<Parameter> Parameters
+               {
+                       get
+                       {
+                               if (this.parameters == null)
+                                       this.parameters = this.definition.Parameters.Select (i => new Parameter (i)).ToList ();
+                               return this.parameters;
+                       }
+                       set { this.parameters = value; }
+               }
+
+               public bool HasParameters
+               {
+                       get { return Parameters != null && Parameters.Count > 0; }
+               }
+
+               public TypeNode ReturnType
+               {
+                       get
+                       {
+                               if (this.returnType == null)
+                                       this.returnType = TypeNode.Create (this.definition.ReturnType);
+                               return this.returnType;
+                       }
+                       set { this.returnType = value; }
+               }
+
+               public bool IsSetter
+               {
+                       get { return this.definition.IsSetter; }
+               }
+
+               public bool IsGetter
+               {
+                       get { return this.definition.IsGetter; }
+               }
+
+               public This ThisParameter
+               {
+                       get
+                       {
+                               if (this.thisParameter == null && !IsStatic && DeclaringType != null)
+                                       ThisParameter = !DeclaringType.IsValueType ? new This (DeclaringType.SelfInstantiation ()) : new This (DeclaringType.SelfInstantiation ().GetReferenceType ());
+                               return this.thisParameter;
+                       }
+                       private set
+                       {
+                               this.thisParameter = value;
+                               if (value != null)
+                                       this.thisParameter.DeclaringMethod = this;
+                       }
+               }
+
+               public Method DeclaringMethod { get; private set; }
+
+               public List<TypeNode> GenericParameters
+               {
+                       get
+                       {
+                               Collection<GenericParameter> genericParameters = this.definition.GenericParameters;
+                               if (genericParameters == null)
+                                       return null;
+                               return genericParameters.Select (it => TypeNode.Create (it)).ToList ();
+                       }
+               }
+
+               public IList<Local> Locals
+               {
+                       get
+                       {
+                               Collection<VariableDefinition> variables = this.definition.Body.Variables;
+                               if (variables == null)
+                                       return null;
+                               return variables.Select (it => new Local (it)).ToList ();
+                       }
+               }
+
+               public bool IsCompilerGenerated
+               {
+                       get { return this.definition.IsCompilerControlled; }
+               }
+
+               #region IEquatable<Method> Members
+               public bool Equals (Method other)
+               {
+                       return this.definition == other.definition;
+               }
+               #endregion
+
+               public static Method ParseMethodDefinition (MethodDefinition methodDefinition)
+               {
+                       Block methodBlock = ParseMethodBlock (methodDefinition);
+
+                       return new Method (methodDefinition, methodBlock);
+               }
+
+               private static Block ParseMethodBlock (MethodDefinition methodDefinition)
+               {
+                       var bp = new BodyParser (methodDefinition);
+                       return new Block (bp.ParseBlocks ());
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Method(Name: {0})", FullName);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodCall.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodCall.cs
new file mode 100644 (file)
index 0000000..a54deb5
--- /dev/null
@@ -0,0 +1,57 @@
+// 
+// MethodCall.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.Collections.Generic;
+using System.Linq;
+
+namespace Mono.CodeContracts.Static.AST {
+       class MethodCall : NaryExpression {
+               public MethodCall () : base (null, NodeType.MethodCall)
+               {
+               }
+
+               public MethodCall (Expression callee, List<Expression> arguments)
+                       : base (arguments, NodeType.MethodCall)
+               {
+                       Callee = callee;
+               }
+
+               public MethodCall (Expression callee, List<Expression> arguments, NodeType typeOfCall)
+                       : base (arguments, typeOfCall)
+               {
+                       Callee = callee;
+               }
+
+               public Expression Callee { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("MethodCall({0}, args:{{{1}}})", Callee, string.Join (", ", Arguments.Select (it => it.ToString ())));
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodContract.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodContract.cs
new file mode 100644 (file)
index 0000000..9daae52
--- /dev/null
@@ -0,0 +1,66 @@
+// 
+// MethodContract.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST {
+       class MethodContract : Node {
+               public Method DeclaringMethod;
+
+               public MethodContract (Method method) : base (NodeType.MethodContract)
+               {
+                       this.DeclaringMethod = method;
+               }
+
+               public List<Requires> Requires { get; set; }
+
+               public List<Ensures> Ensures { get; set; }
+
+               public int RequiresCount
+               {
+                       get
+                       {
+                               List<Requires> list = Requires;
+                               if (list == null)
+                                       return 0;
+                               return list.Count;
+                       }
+               }
+
+               public int EnsuresCount
+               {
+                       get
+                       {
+                               List<Ensures> list = Ensures;
+                               if (list == null)
+                                       return 0;
+                               return list.Count;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodContractElement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/MethodContractElement.cs
new file mode 100644 (file)
index 0000000..7ff57ac
--- /dev/null
@@ -0,0 +1,39 @@
+// 
+// MethodContractElement.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.AST {
+       abstract class MethodContractElement : Node {
+               public Expression UserMessage;
+
+               protected MethodContractElement (NodeType nodeType) : base (nodeType)
+               {
+               }
+
+               public Expression Assertion { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Module.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Module.cs
new file mode 100644 (file)
index 0000000..2e1e16c
--- /dev/null
@@ -0,0 +1,69 @@
+// 
+// Module.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.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Module : Node {
+               private readonly ModuleDefinition definition;
+               private List<TypeNode> types;
+
+               public Module (ModuleDefinition module) : base (NodeType.Module)
+               {
+                       this.definition = module;
+               }
+
+               public ModuleDefinition Definition
+               {
+                       get { return this.definition; }
+               }
+
+
+               public List<TypeNode> Types
+               {
+                       get
+                       {
+                               if (this.types == null)
+                                       this.types = this.definition.Types.Select (it => TypeNode.Create (it)).ToList ();
+
+                               return this.types;
+                       }
+               }
+
+               public TypeNode GetType (string ns, string className)
+               {
+                       TypeReference firstOrDefault = this.definition.Types.FirstOrDefault (t => t.Namespace == ns && t.Name == className);
+                       if (firstOrDefault == null)
+                               return null;
+
+                       return TypeNode.Create (firstOrDefault);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/NaryExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/NaryExpression.cs
new file mode 100644 (file)
index 0000000..6f26ff3
--- /dev/null
@@ -0,0 +1,45 @@
+// 
+// NaryExpression.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.AST {
+       abstract class NaryExpression : Expression {
+               public NaryExpression () : base (NodeType.Nop)
+               {
+               }
+
+               public NaryExpression (List<Expression> arguments, NodeType nodeType)
+                       : base (nodeType)
+               {
+                       Arguments = arguments;
+               }
+
+               public List<Expression> Arguments { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Node.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Node.cs
new file mode 100644 (file)
index 0000000..9f68e41
--- /dev/null
@@ -0,0 +1,38 @@
+// 
+// Node.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.AST {
+       abstract class Node {
+               protected Node (NodeType nodeType)
+               {
+                       NodeType = nodeType;
+               }
+
+               public NodeType NodeType { get; set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/NodeType.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/NodeType.cs
new file mode 100644 (file)
index 0000000..187f54e
--- /dev/null
@@ -0,0 +1,105 @@
+// 
+// NodeType.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.AST {
+       enum NodeType {
+               Unknown,
+               Block,
+               Nop,
+               LoadArg,
+               LoadConstant,
+               Clt,
+               Cgt,
+               Ceq,
+               Return,
+               Box,
+               Conv,
+               Add,
+               Sub,
+               Rem,
+               Expression,
+               Literal,
+               Instruction,
+               AssignmentStatement,
+               Local,
+               Parameter,
+               Branch,
+               ExpressionStatement,
+               Le,
+               Mul,
+               Div,
+               Div_Un,
+               Rem_Un,
+               And,
+               Or,
+               Shr,
+               Xor,
+               Shl,
+               Shr_Un,
+               Neg,
+               Not,
+               Conv_I1,
+               Conv_I2,
+               Conv_I8,
+               Conv_I4,
+               Conv_R4,
+               Conv_R8,
+               LogicalNot,
+               Ne,
+               Ge,
+               Gt,
+               Lt,
+               Eq,
+               This,
+               Method,
+               MethodContract,
+               Requires,
+               Ensures,
+               ExceptionHandler,
+               Filter,
+               Catch,
+               Finally,
+               FaultHandler,
+               TypeNode,
+               EndFinally,
+               Call,
+               Calli,
+               Jmp,
+               MethodCall,
+               MemberBinding,
+               Construct,
+               Class,
+               Property,
+               Assembly,
+               Module,
+               BlockExpression,
+               CallVirt,
+               Field,
+               Reference
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/OperatorExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/OperatorExtensions.cs
new file mode 100644 (file)
index 0000000..5e92d4c
--- /dev/null
@@ -0,0 +1,58 @@
+// 
+// OperatorExtensions.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.AST {
+       static class OperatorExtensions {
+               public static bool IsConversionOperator (this UnaryOperator op)
+               {
+                       switch (op) {
+                       case UnaryOperator.Conv_i:
+                       case UnaryOperator.Conv_i1:
+                       case UnaryOperator.Conv_i2:
+                       case UnaryOperator.Conv_i4:
+                       case UnaryOperator.Conv_i8:
+                       case UnaryOperator.Conv_r4:
+                       case UnaryOperator.Conv_r8:
+                       case UnaryOperator.Conv_u:
+                       case UnaryOperator.Conv_u1:
+                       case UnaryOperator.Conv_u2:
+                       case UnaryOperator.Conv_u4:
+                       case UnaryOperator.Conv_u8:
+                       case UnaryOperator.Conv_r_un:
+                               return true;
+                       default:
+                               return false;
+                       }
+               }
+
+               public static bool IsEqualityOperator (this BinaryOperator bop)
+               {
+                       return bop == BinaryOperator.Ceq || bop == BinaryOperator.Cobjeq;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Parameter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Parameter.cs
new file mode 100644 (file)
index 0000000..b1c7a77
--- /dev/null
@@ -0,0 +1,85 @@
+// 
+// Parameter.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 Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Parameter : Variable {
+               private readonly ParameterDefinition definition;
+               private Method declaringMethod;
+               private bool declaringMethodSpecified;
+
+               public Parameter () : base (NodeType.Parameter)
+               {
+               }
+
+               public Parameter (ParameterDefinition definition) : base (NodeType.Parameter)
+               {
+                       this.definition = definition;
+                       this.type = TypeNode.Create (definition.ParameterType);
+               }
+
+               public string Name { get; protected set; }
+
+               public Method DeclaringMethod
+               {
+                       get
+                       {
+                               if (!this.declaringMethodSpecified && this.declaringMethod == null) {
+                                       var methodReference = this.definition.Method as MethodReference;
+                                       if (methodReference == null)
+                                               throw new NotImplementedException ("Function pointers are not implemented");
+
+                                       this.declaringMethod = new Method (methodReference.Resolve ());
+                               }
+                               return this.declaringMethod;
+                       }
+                       set
+                       {
+                               this.declaringMethod = value;
+                               this.declaringMethodSpecified = true;
+                       }
+               }
+
+               public virtual int Index
+               {
+                       get { return this.definition.Index; }
+               }
+
+               public virtual bool IsOut
+               {
+                       get { return this.definition.IsOut; }
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Parameter({0})", this.definition);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Property.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Property.cs
new file mode 100644 (file)
index 0000000..8898153
--- /dev/null
@@ -0,0 +1,143 @@
+// 
+// Property.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 Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class Property : Member {
+               private readonly PropertyDefinition definition;
+
+               public Property (PropertyDefinition definition) : base (NodeType.Property)
+               {
+                       this.definition = definition;
+               }
+
+               #region Overrides of Member
+               public override TypeNode DeclaringType
+               {
+                       get { return TypeNode.Create (this.definition.DeclaringType); }
+               }
+
+               public override Module Module
+               {
+                       get { return new Module (this.definition.Module); }
+               }
+
+               public override bool IsStatic
+               {
+                       get { return (Getter == null || Getter.IsStatic) && (Setter == null || Setter.IsStatic); }
+               }
+
+               public override bool IsPublic
+               {
+                       get
+                       {
+                               //todo: implement this 
+                               return true;
+                       }
+               }
+
+               public override bool IsPrivate
+               {
+                       get
+                       {
+                               //todo: implement this 
+                               return false;
+                       }
+               }
+
+               public override bool IsAssembly
+               {
+                       get
+                       {
+                               //todo: implement this 
+                               return false;
+                       }
+               }
+
+               public override bool IsFamily
+               {
+                       get
+                       {
+                               //todo: implement this 
+                               return false;
+                       }
+               }
+
+               public override bool IsFamilyOrAssembly
+               {
+                       get
+                       {
+                               //todo: implement this 
+                               return false;
+                       }
+               }
+
+               public override bool IsFamilyAndAssembly
+               {
+                       get
+                       {
+                               //todo: implement this 
+                               return false;
+                       }
+               }
+
+               public Method Getter
+               {
+                       get
+                       {
+                               MethodDefinition methodDefinition = this.definition.GetMethod;
+                               if (methodDefinition == null)
+                                       return null;
+                               return new Method (methodDefinition);
+                       }
+               }
+
+               public Method Setter
+               {
+                       get
+                       {
+                               MethodDefinition methodDefinition = this.definition.SetMethod;
+                               if (methodDefinition == null)
+                                       return null;
+                               return new Method (methodDefinition);
+                       }
+               }
+
+               public bool HasGetter
+               {
+                       get { return (Getter != null); }
+               }
+
+               public bool HasSetter
+               {
+                       get { return (Setter != null); }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Reference.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Reference.cs
new file mode 100644 (file)
index 0000000..34452e6
--- /dev/null
@@ -0,0 +1,56 @@
+// 
+// Reference.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.AST {
+       class Reference : TypeNode {
+               private readonly TypeNode element_type;
+               private readonly string name;
+
+               public Reference (TypeNode elementType) : base (NodeType.Reference)
+               {
+                       TypeDefinition = null;
+                       this.element_type = elementType;
+                       this.name = elementType.Name + "^";
+               }
+
+               public override string Name
+               {
+                       get { return this.name; }
+               }
+
+               public override string FullName
+               {
+                       get { return this.element_type.FullName + "^"; }
+               }
+
+               public TypeNode ElementType
+               {
+                       get { return this.element_type; }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Requires.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Requires.cs
new file mode 100644 (file)
index 0000000..6f4780b
--- /dev/null
@@ -0,0 +1,47 @@
+// 
+// Requires.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.AST {
+       class Requires : MethodContractElement {
+               public Requires ()
+                       : base (NodeType.Requires)
+               {
+               }
+
+               public Requires (NodeType nodeType)
+                       : base (nodeType)
+               {
+               }
+
+               public Requires (Expression condition)
+                       : this ()
+               {
+                       Assertion = condition;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Return.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Return.cs
new file mode 100644 (file)
index 0000000..3837d4b
--- /dev/null
@@ -0,0 +1,47 @@
+// 
+// Return.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.AST {
+       class Return : ExpressionStatement {
+               public Return ()
+               {
+                       NodeType = NodeType.Return;
+               }
+
+               public Return (Expression expression)
+                       : base (expression)
+               {
+                       NodeType = NodeType.Return;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("return {0};", Expression);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Statement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Statement.cs
new file mode 100644 (file)
index 0000000..533d23f
--- /dev/null
@@ -0,0 +1,40 @@
+// 
+// Statement.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.AST {
+       class Statement : Node {
+               public Statement (NodeType nodeType) : base (nodeType)
+               {
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Statement({0})", NodeType);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/This.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/This.cs
new file mode 100644 (file)
index 0000000..8092009
--- /dev/null
@@ -0,0 +1,58 @@
+// 
+// This.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.AST {
+       class This : Parameter {
+               public This ()
+               {
+                       base.NodeType = NodeType.This;
+                       base.Name = "this";
+               }
+
+               public This (TypeNode type) : this ()
+               {
+                       this.type = type;
+                       DeclaringMethod = null;
+               }
+
+               public override int Index
+               {
+                       get { return 0; }
+               }
+
+               public override bool IsOut
+               {
+                       get { return false; }
+               }
+
+               public override string ToString ()
+               {
+                       return "<this>";
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/TypeNode.cs
new file mode 100644 (file)
index 0000000..70af314
--- /dev/null
@@ -0,0 +1,335 @@
+// 
+// TypeNode.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.Linq;
+using Mono.Cecil;
+
+namespace Mono.CodeContracts.Static.AST {
+       class TypeNode : Member, IEquatable<TypeNode> {
+               private TypeNode base_type;
+               private List<Method> methods;
+               private List<TypeNode> nestedTypes;
+               private List<Property> properties;
+
+               protected TypeNode () : base (NodeType.TypeNode)
+               {
+               }
+
+               protected TypeNode (NodeType nodeType)
+                       : base (nodeType)
+               {
+               }
+
+               protected TypeNode (TypeReference typeReference) : this ()
+               {
+                       TypeDefinition = typeReference as TypeDefinition ?? typeReference.Resolve ();
+               }
+
+               public TypeDefinition TypeDefinition { get; set; }
+
+               public IEnumerable<TypeNode> Interfaces
+               {
+                       get
+                       {
+                               if (TypeDefinition == null)
+                                       return null;
+                               return TypeDefinition.Interfaces.Select (i => new TypeNode (i));
+                       }
+               }
+
+               public TypeNode BaseType
+               {
+                       get
+                       {
+                               if (this.base_type == null && TypeDefinition != null)
+                                       this.base_type = new TypeNode (TypeDefinition.BaseType);
+                               return this.base_type;
+                       }
+                       set { this.base_type = value; }
+               }
+
+               public virtual string FullName
+               {
+                       get { return TypeDefinition == null ? "<null>" : TypeDefinition.FullName; }
+               }
+
+               public List<Property> Properties
+               {
+                       get
+                       {
+                               if (this.properties == null)
+                                       this.properties = TypeDefinition.Properties.Select (it => new Property (it)).ToList ();
+                               return this.properties;
+                       }
+                       set { this.properties = value; }
+               }
+
+               public List<Method> Methods
+               {
+                       get
+                       {
+                               if (this.methods == null)
+                                       this.methods = TypeDefinition.Methods.Select (it => new Method (it)).ToList ();
+                               return this.methods;
+                       }
+                       set { this.methods = value; }
+               }
+
+               public List<TypeNode> NestedTypes
+               {
+                       get
+                       {
+                               if (this.nestedTypes == null)
+                                       this.nestedTypes = TypeDefinition.NestedTypes.Select (it => new TypeNode (it)).ToList ();
+                               return this.nestedTypes;
+                       }
+                       set { this.nestedTypes = value; }
+               }
+
+               public virtual string Name
+               {
+                       get { return TypeDefinition.Name; }
+               }
+
+               public static TypeNode Create (TypeReference typeReference)
+               {
+                       TypeDefinition typeDefinition = typeReference.Resolve ();
+                       if (typeDefinition == null)
+                               return null;
+                       if (typeDefinition.IsClass)
+                               return new Class (typeDefinition);
+
+                       return new TypeNode (typeDefinition);
+               }
+
+               public bool IsAssignableTo (TypeNode targetType)
+               {
+                       if (this == CoreSystemTypes.Instance.TypeVoid)
+                               return false;
+                       if (targetType == this)
+                               return true;
+                       if (this == CoreSystemTypes.Instance.TypeObject)
+                               return false;
+                       if (targetType == CoreSystemTypes.Instance.TypeObject || BaseType.IsAssignableTo (targetType))
+                               return true;
+                       IEnumerable<TypeNode> interfaces = Interfaces;
+                       if (interfaces == null || !interfaces.Any ())
+                               return false;
+                       foreach (TypeNode iface in interfaces) {
+                               if (iface != null && iface.IsAssignableTo (targetType))
+                                       return true;
+                       }
+                       return false;
+               }
+
+               public TypeNode GetReferenceType ()
+               {
+                       return new Reference (this);
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Type({0})", FullName);
+               }
+
+               public TypeNode SelfInstantiation ()
+               {
+                       //todo: implement this for generic
+                       return this;
+               }
+
+               public TypeNode GetArrayType (int rank)
+               {
+                       return new ArrayTypeNode (this, 0, rank);
+               }
+
+               #region Implementation of IEquatable<TypeNode>
+               public bool Equals (TypeNode other)
+               {
+                       return TypeDefinition == other.TypeDefinition;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return TypeDefinition.GetHashCode ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       return Equals (obj as TypeNode);
+               }
+               #endregion
+
+               #region Overrides of Member
+               private int classSize;
+               private bool classSizeSpecified;
+
+               public override bool IsStatic
+               {
+                       get { return false; }
+               }
+
+               public override TypeNode DeclaringType
+               {
+                       get { return Create (TypeDefinition.DeclaringType); }
+               }
+
+               public override Module Module
+               {
+                       get
+                       {
+                               if (TypeDefinition == null)
+                                       return null;
+                               return new Module (TypeDefinition.Module);
+                       }
+               }
+
+               public override bool IsPublic
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsPublic; }
+               }
+
+               public override bool IsAssembly
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsNotPublic; }
+               }
+
+               public override bool IsPrivate
+               {
+                       get { return false; }
+               }
+
+               public override bool IsFamily
+               {
+                       get { return false; }
+               }
+
+               public override bool IsFamilyOrAssembly
+               {
+                       get { return IsFamily || IsAssembly; }
+               }
+
+               public override bool IsFamilyAndAssembly
+               {
+                       get { return IsFamily && IsAssembly; }
+               }
+
+               public virtual bool IsValueType
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsValueType; }
+               }
+
+               public virtual bool IsStruct
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsValueType; }
+               }
+
+               public virtual bool IsArray
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsArray; }
+               }
+
+               public virtual bool IsInterface
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsInterface; }
+               }
+
+               public virtual bool HasGenericParameters
+               {
+                       get { return TypeDefinition != null && TypeDefinition.HasGenericParameters; }
+               }
+
+               public virtual bool IsNestedFamily
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsNestedFamily; }
+               }
+
+               public virtual bool IsNestedPublic
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsNestedPublic; }
+               }
+
+               public virtual bool IsNestedInternal
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsNestedAssembly; }
+               }
+
+               public virtual bool IsNestedFamilyAndAssembly
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsNestedFamilyAndAssembly; }
+               }
+
+               public virtual bool IsNestedAssembly
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsNestedAssembly; }
+               }
+
+               public virtual bool IsPrimitive
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsPrimitive; }
+               }
+
+               public virtual bool IsEnum
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsEnum; }
+               }
+
+               public virtual bool IsClass
+               {
+                       get { return TypeDefinition != null && TypeDefinition.IsClass; }
+               }
+
+               public virtual IEnumerable<Field> Fields
+               {
+                       get
+                       {
+                               if (TypeDefinition == null)
+                                       return null;
+                               return TypeDefinition.Fields.Select (it => new Field (it));
+                       }
+               }
+
+               public int ClassSize
+               {
+                       get
+                       {
+                               if (!this.classSizeSpecified && TypeDefinition != null)
+                                       ClassSize = TypeDefinition.ClassSize;
+                               return this.classSize;
+                       }
+                       set
+                       {
+                               this.classSize = value;
+                               this.classSizeSpecified = true;
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/UnaryExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/UnaryExpression.cs
new file mode 100644 (file)
index 0000000..6046d10
--- /dev/null
@@ -0,0 +1,55 @@
+// 
+// UnaryExpression.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.AST {
+       class UnaryExpression : Expression {
+               public UnaryExpression (NodeType nodeType)
+                       : base (nodeType)
+               {
+               }
+
+               public UnaryExpression (NodeType nodeType, Expression operand)
+                       : base (nodeType)
+               {
+                       Operand = operand;
+               }
+
+               public UnaryExpression (NodeType nodeType, Expression operand, TypeNode type)
+                       : base (nodeType, type)
+               {
+                       Operand = operand;
+               }
+
+               public Expression Operand { get; set; }
+
+               public override string ToString ()
+               {
+                       return string.Format ("Unary({0}: {1})", NodeType, Operand);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/UnaryOperator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/UnaryOperator.cs
new file mode 100644 (file)
index 0000000..2223b01
--- /dev/null
@@ -0,0 +1,47 @@
+// 
+// UnaryOperator.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.AST {
+       enum UnaryOperator {
+               Conv_i,
+               Conv_i1,
+               Conv_i2,
+               Conv_i4,
+               Conv_i8,
+               Conv_r4,
+               Conv_r8,
+               Conv_u,
+               Conv_u1,
+               Conv_u2,
+               Conv_u4,
+               Conv_u8,
+               Conv_r_un,
+               Neg,
+               Not,
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Variable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.AST/Variable.cs
new file mode 100644 (file)
index 0000000..f7cc709
--- /dev/null
@@ -0,0 +1,36 @@
+// 
+// Variable.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.AST {
+       abstract class Variable : Expression {
+               protected Variable (NodeType type)
+                       : base (type)
+               {
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/AnalysisDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/AnalysisDriver.cs
new file mode 100644 (file)
index 0000000..42cdcd7
--- /dev/null
@@ -0,0 +1,62 @@
+// 
+// AnalysisDriver.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       abstract class AnalysisDriver<Expression, Variable>
+               : IBasicAnalysisDriver {
+               private readonly IBasicAnalysisDriver basic_driver;
+
+               protected AnalysisDriver (IBasicAnalysisDriver basicDriver)
+               {
+                       this.basic_driver = basicDriver;
+               }
+
+               #region IBasicAnalysisDriver Members
+               public SubroutineFacade SubroutineFacade
+               {
+                       get { return this.basic_driver.SubroutineFacade; }
+               }
+
+               public IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.basic_driver.MetaDataProvider; }
+               }
+
+               public IContractProvider ContractProvider
+               {
+                       get { return this.basic_driver.ContractProvider; }
+               }
+               #endregion
+
+               public abstract IMethodDriver<Expression, Variable> CreateMethodDriver (Method method);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/BasicAnalysisDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/BasicAnalysisDriver.cs
new file mode 100644 (file)
index 0000000..503a7c2
--- /dev/null
@@ -0,0 +1,66 @@
+// 
+// BasicAnalysisDriver.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       class BasicAnalysisDriver : IBasicAnalysisDriver {
+               private readonly IContractProvider contract_provider;
+               private readonly IMetaDataProvider meta_data_provider;
+
+               #region Implementation of IBasicAnalysisDriver<Local,Parameter,Method,Field,Property,Event,Type,Attribute,Assembly>
+               public IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.meta_data_provider; }
+               }
+
+
+               public IContractProvider ContractProvider
+               {
+                       get { return this.contract_provider; }
+               }
+
+               public SubroutineFacade SubroutineFacade { get; private set; }
+               #endregion
+
+               public BasicAnalysisDriver (IMetaDataProvider metaDataProvider,
+                                           IContractProvider contractProvider)
+               {
+                       SubroutineFacade = new SubroutineFacade (metaDataProvider, contractProvider);
+                       this.meta_data_provider = metaDataProvider;
+                       this.contract_provider = contractProvider;
+               }
+
+               public BasicMethodDriver CreateMethodDriver (Method method)
+               {
+                       return new BasicMethodDriver (method, this);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/BasicMethodDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/BasicMethodDriver.cs
new file mode 100644 (file)
index 0000000..657213a
--- /dev/null
@@ -0,0 +1,137 @@
+// 
+// BasicMethodDriver.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.StackAnalysis;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       class BasicMethodDriver {
+               private readonly Method method;
+               private readonly IBasicAnalysisDriver parent;
+               private ICFG contract_free_cfg;
+
+               private ICodeLayer<Dummy, Dummy, IMethodContextProvider, Dummy> contract_free_raw_layer;
+               private ICodeLayer<int, int, IStackContextProvider, Dummy> contract_free_stack_layer;
+
+               public BasicMethodDriver (Method method, IBasicAnalysisDriver parent)
+               {
+                       this.method = method;
+                       this.parent = parent;
+
+                       RawLayer = CodeLayerFactory.Create (
+                                                           this.parent.SubroutineFacade.GetControlFlowGraph (method).GetDecoder (parent.MetaDataProvider),
+                                                           parent.MetaDataProvider,
+                                                           parent.ContractProvider, dummy => "", dummy => "");
+
+                       if (DebugOptions.Debug) {
+                               Console.WriteLine ("-----APC based CFG-----");
+                               RawLayer.ILDecoder.ContextProvider.MethodContext.CFG.Print (Console.Out, RawLayer.Printer, null, null);
+                       }
+
+                       StackLayer = CodeLayerFactory.Create (
+                                                             StackDepthFactory.Create (RawLayer.ILDecoder, RawLayer.MetaDataProvider),
+                                                             RawLayer.MetaDataProvider,
+                                                             RawLayer.ContractProvider, (i => "s" + i.ToString ()), i => "s" + i.ToString ()
+                               );
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("-----Stack based CFG-----");
+                               StackLayer.ILDecoder.ContextProvider.MethodContext.CFG.Print (Console.Out, StackLayer.Printer, null, null);
+                       }
+               }
+
+               public Method CurrentMethod
+               {
+                       get { return this.method; }
+               }
+
+               public IBasicAnalysisDriver AnalysisDriver
+               {
+                       get { return this.parent; }
+               }
+
+               public ICodeLayer<Dummy, Dummy, IMethodContextProvider, Dummy> RawLayer { get; private set; }
+               public ICodeLayer<int, int, IStackContextProvider, Dummy> StackLayer { get; private set; }
+
+               public ICodeLayer<Dummy, Dummy, IMethodContextProvider, Dummy> ContractFreeRawLayer
+               {
+                       get
+                       {
+                               if (this.contract_free_raw_layer == null) {
+                                       this.contract_free_raw_layer =
+                                               CodeLayerFactory.Create (ContractFreeCFG.GetDecoder (this.parent.MetaDataProvider),
+                                                                        RawLayer.MetaDataProvider,
+                                                                        RawLayer.ContractProvider,
+                                                                        RawLayer.ExpressionToString, RawLayer.VariableToString, RawLayer.Printer);
+                               }
+                               return this.contract_free_raw_layer;
+                       }
+               }
+
+               public ICodeLayer<int, int, IStackContextProvider, Dummy> ContractFreeStackLayer
+               {
+                       get
+                       {
+                               if (this.contract_free_stack_layer == null) {
+                                       this.contract_free_stack_layer =
+                                               CodeLayerFactory.Create (StackDepthFactory.Create (ContractFreeRawLayer.ILDecoder, this.contract_free_raw_layer.MetaDataProvider),
+                                                                        ContractFreeRawLayer.MetaDataProvider,
+                                                                        ContractFreeRawLayer.ContractProvider,
+                                                                        StackLayer.ExpressionToString, StackLayer.VariableToString, StackLayer.Printer);
+                               }
+                               return this.contract_free_stack_layer;
+                       }
+               }
+
+               public ICFG ContractFreeCFG
+               {
+                       get
+                       {
+                               if (this.contract_free_cfg == null) {
+                                       this.contract_free_cfg = new ContractFilteredCFG (RawLayer.ILDecoder.ContextProvider.MethodContext.CFG);
+
+                                       if (DebugOptions.Debug)
+                                       {
+                                               Console.WriteLine ("------raw contract-free cfg -----------------");
+                                               this.contract_free_cfg.Print (Console.Out, RawLayer.Printer, null, null);
+                                       }
+                               }
+                               return this.contract_free_cfg;
+                       }
+               }
+
+               public ICFG CFG
+               {
+                       get { return StackLayer.ILDecoder.ContextProvider.MethodContext.CFG; }
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..275c301
--- /dev/null
@@ -0,0 +1,146 @@
+using System;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis;
+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.Providers;
+using Mono.CodeContracts.Static.Proving;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       class CodeContractsAnalysisDriver<MethodResult>
+               : AnalysisDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> {
+               public CodeContractsAnalysisDriver (IBasicAnalysisDriver basicDriver)
+                       : base (basicDriver)
+               {
+               }
+
+               public override IMethodDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> CreateMethodDriver (Method method)
+               {
+                       return new MethodDriver (method, this);
+               }
+
+               #region Nested type: MethodDriver
+               private class MethodDriver : BasicMethodDriver,
+                                            IMethodDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>,
+                                            IFactBase<SymbolicValue> {
+                       private Func<LabeledSymbol<APC, SymbolicValue>, string> expr2String;
+                       private IFullExpressionDecoder<SymbolicValue, LabeledSymbol<APC, SymbolicValue>> expression_decoder;
+                       private HeapAnalysis.HeapAnalysis heap_analysis;
+
+                       public MethodDriver (Method method,
+                                            CodeContractsAnalysisDriver<MethodResult> parent)
+                               : base (method, parent)
+                       {
+                       }
+
+                       private new AnalysisDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> AnalysisDriver
+                       {
+                               get { return (AnalysisDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>) base.AnalysisDriver; }
+                       }
+
+                       #region IFactBase<SymbolicValue> Members
+                       public ProofOutcome IsNull (APC pc, SymbolicValue variable)
+                       {
+                               return ProofOutcome.Top;
+                       }
+
+                       public ProofOutcome IsNonNull (APC pc, SymbolicValue variable)
+                       {
+                               return ProofOutcome.Top;
+                       }
+
+                       public bool IsUnreachable (APC pc)
+                       {
+                               return this.heap_analysis.IsUnreachable (pc);
+                       }
+                       #endregion
+
+                       #region IMethodDriver<LabeledSymbol<APC,SymbolicValue>,SymbolicValue> Members
+                       public ICodeLayer<SymbolicValue, SymbolicValue,
+                               IValueContextProvider<SymbolicValue>,
+                               IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> ValueLayer { get; private set; }
+
+                       public ICodeLayer<LabeledSymbol<APC, SymbolicValue>, SymbolicValue,
+                               IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>,
+                               IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> ExpressionLayer { get; private set; }
+
+                       public ICodeLayer<SymbolicValue, SymbolicValue,
+                               IValueContextProvider<SymbolicValue>,
+                               IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> HybridLayer { get; private set; }
+
+                       public IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> ContextProvider
+                       {
+                               get { return ExpressionLayer.ILDecoder.ContextProvider; }
+                       }
+
+                       public IMetaDataProvider MetaDataProvider
+                       {
+                               get { return RawLayer.MetaDataProvider; }
+                       }
+
+                       public IFactBase<SymbolicValue> BasicFacts
+                       {
+                               get { return this; }
+                       }
+
+                       public IFullExpressionDecoder<SymbolicValue, LabeledSymbol<APC, SymbolicValue>> ExpressionDecoder
+                       {
+                               get
+                               {
+                                       if (this.expression_decoder == null)
+                                               this.expression_decoder = 
+                                                       new FullExpressionDecoder<SymbolicValue, LabeledSymbol<APC, SymbolicValue>>(MetaDataProvider, ContextProvider);
+                                       return this.expression_decoder;
+                               }
+                       }
+
+                       public void RunHeapAndExpressionAnalyses ()
+                       {
+                               if (this.heap_analysis != null)
+                                       return;
+
+                               this.heap_analysis = new HeapAnalysis.HeapAnalysis (StackLayer);
+                               StackLayer.CreateForward (this.heap_analysis) (this.heap_analysis.InitialValue ());
+
+                               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>>>
+                                       (ValueLayer, this.heap_analysis.IsUnreachable);
+                               ValueLayer.CreateForward (expressionAnalysis.CreateExpressionAnalysis ()) (expressionAnalysis.InitialValue (SymbolicValue.GetUniqueKey));
+
+                               if (DebugOptions.Debug)
+                               {
+                                       Console.WriteLine ("------------Value based CFG-----------------");
+                                       ValueLayer.ILDecoder.ContextProvider.MethodContext.CFG.Print (Console.Out, ValueLayer.Printer, null, null);
+                               }
+
+                               IILDecoder
+                                       <APC, LabeledSymbol<APC, SymbolicValue>, SymbolicValue, IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>>
+                                       decoder = expressionAnalysis.GetDecoder (ValueLayer.ILDecoder);
+                               this.expr2String = ExpressionPrinterFactory.Printer (decoder.ContextProvider, this);
+                               ExpressionLayer = CodeLayerFactory.Create (decoder, ValueLayer.MetaDataProvider, ValueLayer.ContractProvider,
+                                                                          this.expr2String, ValueLayer.VariableToString);
+
+                               if (DebugOptions.Debug)
+                               {
+                                       Console.WriteLine ("------------Expression based CFG-------------");
+                                       ExpressionLayer.ILDecoder.ContextProvider.MethodContext.CFG.Print (Console.Out, ExpressionLayer.Printer, null, null);
+                               }
+
+                               HybridLayer = CodeLayerFactory.Create (ValueLayer.ILDecoder, ValueLayer.MetaDataProvider, ValueLayer.ContractProvider,
+                                                                      ValueLayer.ExpressionToString,
+                                                                      ValueLayer.VariableToString, ExpressionLayer.Printer);
+                       }
+
+                       public int KeyConverter (SymbolicValue var)
+                       {
+                               return SymbolicValue.GetUniqueKey (var);
+                       }
+                       #endregion
+                                            }
+               #endregion
+               }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IBasicAnalysisDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IBasicAnalysisDriver.cs
new file mode 100644 (file)
index 0000000..7e71c2d
--- /dev/null
@@ -0,0 +1,38 @@
+// 
+// IBasicAnalysisDriver.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 Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       interface IBasicAnalysisDriver {
+               SubroutineFacade SubroutineFacade { get; }
+               IMetaDataProvider MetaDataProvider { get; }
+               IContractProvider ContractProvider { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IBasicMethodDriver.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IBasicMethodDriver.cs
new file mode 100644 (file)
index 0000000..c3e6aac
--- /dev/null
@@ -0,0 +1,42 @@
+// 
+// IBasicMethodDriver.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 Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       interface IBasicMethodDriver {
+               ICodeLayer<Dummy, Dummy, IMethodContextProvider, Dummy> RawLayer { get; }
+               ICodeLayer<int, int, IStackContextProvider, Dummy> StackLayer { get; }
+               ICodeLayer<Dummy, Dummy, IMethodContextProvider, Dummy> ContractFreeRawLayer { get; }
+               ICodeLayer<int, int, IStackContextProvider, Dummy> ContractFreeStackLayer { get; }
+
+               ICFG ContractFreeCFG { get; }
+               IBasicAnalysisDriver AnalysisDriver { get; }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysis.cs
new file mode 100644 (file)
index 0000000..803bf7e
--- /dev/null
@@ -0,0 +1,40 @@
+// 
+// IMethodAnalysis.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;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       interface IMethodAnalysis {
+               string Name { get; }
+
+               IMethodResult<Variable> Analyze<Expression, Variable> (
+                       string fullMethodName, IMethodDriver<Expression, Variable> methodDriver)
+                       where Variable : IEquatable<Variable>
+                       where Expression : IEquatable<Expression>;
+       }
+}
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
new file mode 100644 (file)
index 0000000..7c9b520
--- /dev/null
@@ -0,0 +1,37 @@
+// 
+// IMethodAnalysisFixPoint.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 Mono.CodeContracts.Static.ControlFlow;
+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);
+       }
+}
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
new file mode 100644 (file)
index 0000000..7a09747
--- /dev/null
@@ -0,0 +1,53 @@
+// 
+// IMethodDriver.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+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; }
+
+               IExpressionContextProvider<Expression, Variable> ContextProvider { get; }
+               IMetaDataProvider MetaDataProvider { get; }
+
+               ICFG CFG { get; }
+               Method CurrentMethod { get; }
+               IFactBase<Variable> BasicFacts { get; }
+               IFullExpressionDecoder<Variable, Expression> ExpressionDecoder { get; }
+
+               void RunHeapAndExpressionAnalyses ();
+               int KeyConverter (Variable var);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodResult.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.Drivers/IMethodResult.cs
new file mode 100644 (file)
index 0000000..a09439c
--- /dev/null
@@ -0,0 +1,37 @@
+// 
+// IMethodResult.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.Collections.Generic;
+using Mono.CodeContracts.Static.Proving;
+
+namespace Mono.CodeContracts.Static.Analysis.Drivers {
+       interface IMethodResult<Variable> : IMethodAnalysisFixPoint<Variable> {
+               IMethodAnalysis MethodAnalysis { get; set; }
+               void ValidateImplicitAssertions (IFactQuery<BoxedExpression, Variable> facts, List<string> proofResults);
+       }
+}
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
new file mode 100644 (file)
index 0000000..4e3f4bc
--- /dev/null
@@ -0,0 +1,157 @@
+// 
+// FullExpressionDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class FullExpressionDecoder<V, E> : IFullExpressionDecoder<V, E>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               public readonly VisitorForIsBinaryExpression<V, E> BinaryExpressionVisitor;
+               public readonly VisitorForIsInst<V, E> IsInstVisitor;
+               public readonly VisitorForIsNull<V, E> IsNullVisitor;
+               public readonly VisitorForSizeOf<V, E> SizeOfVisitor;
+               public readonly VisitorForIsUnaryExpression<V, E> UnaryExpressionVisitor;
+               public readonly VisitorForUnderlyingVariable<V, E> UnderlyingVariableVisitor;
+               public readonly VisitorForValueOf<V, E> ValueOfVisitor;
+               public readonly VisitorForVariable<V, E> VariableVisitor;
+               public readonly VisitorForVariablesIn<V, E> VariablesInVisitor;
+               private readonly IMetaDataProvider meta_data_provider;
+
+               #region Implementation of IFullExpressionDecoder<V,E>
+               public bool IsVariable (E expr, out object variable)
+               {
+                       V var;
+                       bool res = VisitorForVariable<V, E>.IsVariable (expr, out var, this);
+
+                       variable = var;
+                       return res;
+               }
+
+               public V UnderlyingVariable (E expr)
+               {
+                       return VisitorForUnderlyingVariable<V, E>.IsUnderlyingVariable (expr, this);
+               }
+
+               public bool IsNull (E expr)
+               {
+                       return VisitorForIsNull<V, E>.IsNull (expr, this);
+               }
+
+               public bool IsConstant (E expr, out object value, out TypeNode type)
+               {
+                       return VisitorForValueOf<V, E>.IsConstant (expr, out value, out type, this);
+               }
+
+               public bool IsSizeof (E expr, out TypeNode type)
+               {
+                       return VisitorForSizeOf<V, E>.IsSizeOf (expr, out type, this);
+               }
+
+               public bool IsIsinst (E expr, out E arg, out TypeNode type)
+               {
+                       return VisitorForIsInst<V, E>.IsIsInst (expr, out type, out arg, this);
+               }
+
+               public bool IsUnaryExpression (E expr, out UnaryOperator op, out E arg)
+               {
+                       return VisitorForIsUnaryExpression<V, E>.IsUnary (expr, out op, out arg, this);
+               }
+
+               public bool IsBinaryExpression (E expr, out BinaryOperator op, out E left, out E right)
+               {
+                       return VisitorForIsBinaryExpression<V, E>.IsBinary (expr, out op, out left, out right, this);
+               }
+
+               public void AddFreeVariables (E expr, ISet<E> set)
+               {
+                       VisitorForVariablesIn<V, E>.AddFreeVariables (expr, set, this);
+               }
+
+               public LispList<PathElement> GetVariableAccessPath (E expr)
+               {
+                       return ContextProvider.ValueContext.AccessPathList (ContextProvider.ExpressionContext.GetPC (expr), ContextProvider.ExpressionContext.Unrefine (expr), true, false);
+               }
+
+               public bool TryGetType (E expr, out TypeNode type)
+               {
+                       FlatDomain<TypeNode> aType = ContextProvider.ExpressionContext.GetType (expr);
+                       if (aType.IsNormal) {
+                               type = aType.Concrete;
+                               return true;
+                       }
+
+                       type = null;
+                       return false;
+               }
+
+               public bool TrySizeOfAsConstant (E expr, out int sizeAsConstant)
+               {
+                       return TrySizeOf (expr, out 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);
+                               if (size != -1) {
+                                       sizeAsConstant = size;
+                                       return true;
+                               }
+                       }
+
+                       sizeAsConstant = -1;
+                       return false;
+               }
+               #endregion
+
+               public FullExpressionDecoder (IMetaDataProvider metaDataProvider, IExpressionContextProvider<E, V> contextProvider)
+               {
+                       ContextProvider = contextProvider;
+                       this.meta_data_provider = metaDataProvider;
+                       this.VariableVisitor = new VisitorForVariable<V, E> ();
+                       this.UnderlyingVariableVisitor = new VisitorForUnderlyingVariable<V, E> ();
+                       this.UnaryExpressionVisitor = new VisitorForIsUnaryExpression<V, E> ();
+                       this.BinaryExpressionVisitor = new VisitorForIsBinaryExpression<V, E> ();
+                       this.VariablesInVisitor = new VisitorForVariablesIn<V, E> (contextProvider);
+                       this.ValueOfVisitor = new VisitorForValueOf<V, E> ();
+                       this.SizeOfVisitor = new VisitorForSizeOf<V, E> ();
+                       this.IsInstVisitor = new VisitorForIsInst<V, E> ();
+                       this.IsNullVisitor = new VisitorForIsNull<V, E> ();
+               }
+
+               public IExpressionContextProvider<E, V> ContextProvider { get; private set; }
+       }
+}
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
new file mode 100644 (file)
index 0000000..b9dc54a
--- /dev/null
@@ -0,0 +1,49 @@
+// 
+// IFullExpressionDecoder.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       interface IFullExpressionDecoder<Variable, Expression> {
+               bool IsVariable (Expression expr, out object variable);
+               Variable UnderlyingVariable (Expression expr);
+               bool IsNull (Expression expr);
+               bool IsConstant (Expression expr, out object value, out TypeNode type);
+               bool IsSizeof (Expression expr, out TypeNode type);
+               bool IsIsinst (Expression expr, out Expression arg, out TypeNode type);
+               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);
+               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
new file mode 100644 (file)
index 0000000..99372a7
--- /dev/null
@@ -0,0 +1,79 @@
+// 
+// QueryVisitor.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 Mono.CodeContracts.Static.AST;
+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> {
+               #region ISymbolicExpressionVisitor<E,E,V,Dummy,bool> Members
+               public virtual bool Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, Dummy data)
+               {
+                       return false;
+               }
+
+               public virtual bool Isinst (E pc, TypeNode type, V dest, E obj, Dummy data)
+               {
+                       return false;
+               }
+
+               public virtual bool LoadNull (E pc, V dest, Dummy polarity)
+               {
+                       return false;
+               }
+
+               public virtual bool LoadConst (E pc, TypeNode type, object constant, V dest, Dummy data)
+               {
+                       return false;
+               }
+
+               public virtual bool Sizeof (E pc, TypeNode type, V dest, Dummy data)
+               {
+                       return false;
+               }
+
+               public virtual bool Unary (E pc, UnaryOperator op, bool unsigned, V dest, E source, Dummy data)
+               {
+                       return false;
+               }
+
+               public virtual bool SymbolicConstant (E pc, V variable, Dummy data)
+               {
+                       return false;
+               }
+               #endregion
+
+               protected static bool Decode<Visitor> (E expr, Visitor visitor, FullExpressionDecoder<V,E> decoder)
+                       where Visitor : QueryVisitor<V, E>
+               {
+                       return decoder.ContextProvider.ExpressionContext.Decode<Dummy, bool, Visitor> (expr, visitor, Dummy.Value);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsBinaryExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsBinaryExpression.cs
new file mode 100644 (file)
index 0000000..7512f5e
--- /dev/null
@@ -0,0 +1,61 @@
+// 
+// VisitorForIsBinaryExpression.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForIsBinaryExpression<V, E> : QueryVisitor<V, E> 
+               where V : IEquatable<V> where E : IEquatable<E> {
+               
+               private BinaryOperator op;
+               private E left;
+               private E right;
+
+               public static bool IsBinary (E expr, out BinaryOperator bop, out E left, out E right, FullExpressionDecoder<V,E> decoder)
+               {
+                       VisitorForIsBinaryExpression<V, E> v = decoder.BinaryExpressionVisitor;
+                       bool res = Decode (expr, v, decoder);
+
+                       bop = v.op;
+                       left = v.left;
+                       right = v.right;
+                       return res;
+               }
+
+               public override bool Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, Dummy data)
+               {
+                       this.op = op;
+                       this.left = operand1;
+                       this.right = operand2;
+
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsInst.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsInst.cs
new file mode 100644 (file)
index 0000000..b56d35f
--- /dev/null
@@ -0,0 +1,58 @@
+// 
+// VisitorForIsInst.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForIsInst<V, E> : QueryVisitor<V, E> 
+               where V : IEquatable<V> 
+               where E : IEquatable<E> {
+               
+               private E argument;
+               private TypeNode type;
+
+               public static bool IsIsInst (E expr, out TypeNode type, out E arg, FullExpressionDecoder<V,E> decoder)
+               {
+                       VisitorForIsInst<V, E> v = decoder.IsInstVisitor;
+                       bool res = Decode (expr, v, decoder);
+
+                       arg = v.argument;
+                       type = v.type;
+                       return res;
+               }
+
+               public override bool Isinst (E pc, TypeNode type, V dest, E obj, Dummy data)
+               {
+                       this.type = type;
+                       this.argument = obj;
+                       return true;
+               }
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..e694d4b
--- /dev/null
@@ -0,0 +1,49 @@
+// 
+// VisitorForIsNull.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 Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForIsNull<V, E> : QueryVisitor<V, E>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               public static bool IsNull (E expr, FullExpressionDecoder<V, E> decoder)
+               {
+                       VisitorForIsNull<V, E> v = decoder.IsNullVisitor;
+                       bool res = Decode (expr, v, decoder);
+
+                       return res;
+               }
+
+               public override bool LoadNull (E pc, V dest, Dummy polarity)
+               {
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsUnaryExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsUnaryExpression.cs
new file mode 100644 (file)
index 0000000..4640156
--- /dev/null
@@ -0,0 +1,56 @@
+// 
+// VisitorForIsUnaryExpression.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForIsUnaryExpression<V, E> : QueryVisitor<V, E>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               private E Argument;
+               private UnaryOperator Operator;
+
+               public static bool IsUnary (E expr, out UnaryOperator op, out E arg, FullExpressionDecoder<V, E> decoder)
+               {
+                       VisitorForIsUnaryExpression<V, E> v = decoder.UnaryExpressionVisitor;
+                       bool res = Decode (expr, v, decoder);
+                       op = v.Operator;
+                       arg = v.Argument;
+                       return res;
+               }
+
+               public override bool Unary (E pc, UnaryOperator op, bool unsigned, V dest, E source, Dummy data)
+               {
+                       this.Argument = source;
+                       this.Operator = op;
+                       return true;
+               }
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..ae19934
--- /dev/null
@@ -0,0 +1,54 @@
+// 
+// VisitorForSizeOf.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+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;
+
+               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;
+                       return res;
+               }
+
+               public override bool Sizeof (E pc, TypeNode type, V dest, Dummy data)
+               {
+                       this.Type = type;
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForUnderlyingVariable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForUnderlyingVariable.cs
new file mode 100644 (file)
index 0000000..96fabb3
--- /dev/null
@@ -0,0 +1,88 @@
+// 
+// VisitorForUnderlyingVariable.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForUnderlyingVariable<V,E> : QueryVisitor<V, E>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               private V Variable;
+
+               public static V IsUnderlyingVariable (E expr, FullExpressionDecoder<V, E> decoder)
+               {
+                       VisitorForUnderlyingVariable<V, E> visitor = decoder.UnderlyingVariableVisitor;
+                       Decode (expr, visitor, decoder);
+                       return visitor.Variable;
+               }
+
+               public override bool Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, Dummy data)
+               {
+                       this.Variable = dest;
+                       return true;
+               }
+
+               public override bool Isinst (E pc, TypeNode type, V dest, E obj, Dummy data)
+               {
+                       this.Variable = dest;
+                       return true;
+               }
+
+               public override bool LoadConst (E pc, TypeNode type, object constant, V dest, Dummy data)
+               {
+                       this.Variable = dest;
+                       return true;
+               }
+
+               public override bool LoadNull (E pc, V dest, Dummy polarity)
+               {
+                       this.Variable = dest;
+                       return true;
+               }
+
+               public override bool Sizeof (E pc, TypeNode type, V dest, Dummy data)
+               {
+                       this.Variable = dest;
+                       return true;
+               }
+
+               public override bool SymbolicConstant (E pc, V variable, Dummy data)
+               {
+                       this.Variable = variable;
+                       return true;
+               }
+
+               public override bool Unary (E pc, UnaryOperator op, bool unsigned, V dest, E source, Dummy data)
+               {
+                       this.Variable = dest;
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForValueOf.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForValueOf.cs
new file mode 100644 (file)
index 0000000..7592b7d
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// VisitorForValueOf.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForValueOf<V, E> : QueryVisitor<V, E>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               private TypeNode Type;
+               private object Value;
+
+               public static bool IsConstant (E expr, out object value, out TypeNode type, FullExpressionDecoder<V, E> decoder)
+               {
+                       VisitorForValueOf<V, E> v = decoder.ValueOfVisitor;
+                       bool res = Decode (expr, v, decoder);
+
+                       value = v.Value;
+                       type = v.Type;
+                       return res;
+               }
+
+               public override bool LoadNull (E pc, V dest, Dummy polarity)
+               {
+                       this.Type = null;
+                       this.Value = null;
+                       return true;
+               }
+
+               public override bool LoadConst (E pc, TypeNode type, object constant, V dest, Dummy data)
+               {
+                       this.Type = type;
+                       this.Value = constant;
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariable.cs
new file mode 100644 (file)
index 0000000..db72b6e
--- /dev/null
@@ -0,0 +1,52 @@
+// 
+// VisitorForVariable.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 Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForVariable<V,E> : QueryVisitor<V, E> 
+               where V : IEquatable<V> 
+               where E : IEquatable<E> {
+               private V variable;
+
+               public static bool IsVariable (E expr, out V var, FullExpressionDecoder<V, E> decoder)
+               {
+                       VisitorForVariable<V, E> visitor = decoder.VariableVisitor;
+                       bool res = Decode (expr, visitor, decoder);
+                       var = visitor.variable;
+                       return res;
+               }
+
+               public override bool SymbolicConstant (E pc, V variable, Dummy data)
+               {
+                       this.variable = variable;
+                       return true;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariablesIn.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariablesIn.cs
new file mode 100644 (file)
index 0000000..3d591e3
--- /dev/null
@@ -0,0 +1,100 @@
+// 
+// VisitorForVariablesIn.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding {
+       class VisitorForVariablesIn<V, E> : ISymbolicExpressionVisitor<E, E, V, ISet<E>, Dummy>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               private readonly IExpressionContextProvider<E, V> contextProvider;
+
+               public VisitorForVariablesIn (IExpressionContextProvider<E, V> contextProvider)
+               {
+                       this.contextProvider = contextProvider;
+               }
+
+               public static void AddFreeVariables (E expr, ISet<E> set, FullExpressionDecoder<V, E> decoder)
+               {
+                       decoder.VariablesInVisitor.Recurse (expr, set);
+               }
+
+               private void Recurse (E expr, ISet<E> set)
+               {
+                       this.contextProvider.ExpressionContext.Decode<ISet<E>, Dummy, VisitorForVariablesIn<V, E>> (expr, this, set);
+               }
+
+               #region Implementation of IExpressionILVisitor<E,E,V,ISet<E>,Dummy>
+               public Dummy Binary (E pc, BinaryOperator op, V dest, E operand1, E operand2, ISet<E> data)
+               {
+                       Recurse (operand1, data);
+                       Recurse (operand2, data);
+                       return Dummy.Value;
+               }
+
+               public Dummy Isinst (E pc, TypeNode type, V dest, E obj, ISet<E> data)
+               {
+                       data.Add (pc);
+                       return Dummy.Value;
+               }
+
+               public Dummy LoadNull (E pc, V dest, ISet<E> polarity)
+               {
+                       return Dummy.Value;
+               }
+
+               public Dummy LoadConst (E pc, TypeNode type, object constant, V dest, ISet<E> data)
+               {
+                       return Dummy.Value;
+               }
+
+               public Dummy Sizeof (E pc, TypeNode type, V dest, ISet<E> data)
+               {
+                       data.Add (pc);
+                       return Dummy.Value;
+               }
+
+               public Dummy Unary (E pc, UnaryOperator op, bool unsigned, V dest, E source, ISet<E> data)
+               {
+                       Recurse (source, data);
+                       return Dummy.Value;
+               }
+               #endregion
+
+               #region Implementation of ISymbolicExpressionVisitor<E,E,V,ISet<E>,Dummy>
+               public Dummy SymbolicConstant (E pc, V variable, ISet<E> data)
+               {
+                       return Dummy.Value;
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..8902d8b
--- /dev/null
@@ -0,0 +1,98 @@
+// 
+// BinaryExpr.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       class BinaryExpr<TSymbolicValue> : Expr<TSymbolicValue>
+               where TSymbolicValue : IEquatable<TSymbolicValue> {
+               
+               public readonly BinaryOperator Operator;
+               public readonly TSymbolicValue Left;
+               public readonly TSymbolicValue Right;
+
+               public BinaryExpr (TSymbolicValue left, TSymbolicValue right, BinaryOperator op)
+               {
+                       this.Left = left;
+                       this.Right = right;
+                       this.Operator = op;
+               }
+
+               #region Overrides of Expression
+               public override IEnumerable<TSymbolicValue> Variables
+               {
+                       get
+                       {
+                               yield return this.Left;
+                               yield return this.Right;
+                       }
+               }
+
+               public override Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data)
+               {
+                       return visitor.Binary (pc, this.Operator, dest, this.Left, this.Right, data);
+               }
+
+               public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<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);
+
+                       return null;
+               }
+
+               public override bool IsContained (IImmutableSet<TSymbolicValue> candidates)
+               {
+                       return candidates.Contains (this.Left) || candidates.Contains (this.Right);
+               }
+
+               public override bool Contains (TSymbolicValue symbol)
+               {
+                       return this.Left.Equals (symbol) || this.Right.Equals (symbol);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("Binary({0} {1} {2})", this.Left, this.Operator, this.Right);
+               }
+
+               public override bool Equals (Expr<TSymbolicValue> other)
+               {
+                       var binary = other as BinaryExpr<TSymbolicValue>;
+                       if (binary == null || binary.Operator != this.Operator)
+                               return false;
+
+                       return binary.Left.Equals (this.Left) && binary.Right.Equals (this.Right);
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..69cfccc
--- /dev/null
@@ -0,0 +1,85 @@
+// 
+// ConstExpr.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       class ConstExpr<TSymbolicValue> : Expr<TSymbolicValue> where TSymbolicValue : IEquatable<TSymbolicValue> {
+               public readonly TypeNode Type;
+               public readonly object value;
+
+               public ConstExpr (TypeNode type, object value)
+               {
+                       this.Type = type;
+                       this.value = value;
+               }
+
+               #region Overrides of Expression
+               public override IEnumerable<TSymbolicValue> Variables
+               {
+                       get { yield break; }
+               }
+
+               public override Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data)
+               {
+                       return visitor.LoadConst (pc, this.Type, this.value, dest, data);
+               }
+
+               public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions)
+               {
+                       return this;
+               }
+
+               public override bool IsContained (IImmutableSet<TSymbolicValue> candidates)
+               {
+                       return false;
+               }
+
+               public override bool Contains (TSymbolicValue symbol)
+               {
+                       return false;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("Const({0} {1})", this.Type, this.value);
+               }
+
+               public override bool Equals (Expr<TSymbolicValue> other)
+               {
+                       var constant = other as ConstExpr<TSymbolicValue>;
+
+                       return constant != null && constant.Type.Equals (this.Type) && constant.value.Equals (this.value);
+               }
+               #endregion
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..542094f
--- /dev/null
@@ -0,0 +1,57 @@
+// 
+// Expr.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 Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       abstract class Expr<TSymbolicValue> : IEquatable<Expr<TSymbolicValue>>
+               where TSymbolicValue : IEquatable<TSymbolicValue> {
+               
+               public abstract IEnumerable<TSymbolicValue> Variables { get; }
+
+               public abstract bool Equals (Expr<TSymbolicValue> other);
+
+               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);
+
+               /// <summary>
+               /// Specifies that current expression is partially contained in candidates
+               /// </summary>
+               public abstract bool IsContained (IImmutableSet<TSymbolicValue> candidates);
+
+               public abstract bool Contains (TSymbolicValue symbol);
+
+               public abstract override string ToString ();
+       }
+}
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
new file mode 100644 (file)
index 0000000..0822092
--- /dev/null
@@ -0,0 +1,87 @@
+// 
+// IsInstExpr.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       class IsInstExpr<TSymbolicValue> : Expr<TSymbolicValue> where TSymbolicValue : IEquatable<TSymbolicValue> {
+               public readonly TSymbolicValue Argument;
+               public readonly TypeNode Type;
+
+               public IsInstExpr (TSymbolicValue argument, TypeNode type)
+               {
+                       this.Argument = argument;
+                       this.Type = type;
+               }
+
+               #region Overrides of Expression
+               public override IEnumerable<TSymbolicValue> Variables
+               {
+                       get { yield return this.Argument; }
+               }
+
+               public override Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data)
+               {
+                       return visitor.Isinst (pc, this.Type, dest, this.Argument, data);
+               }
+
+               public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions)
+               {
+                       if (substitutions.ContainsKey (this.Argument))
+                               return new IsInstExpr<TSymbolicValue> (substitutions [this.Argument].Head, this.Type);
+                       return null;
+               }
+
+               public override bool IsContained (IImmutableSet<TSymbolicValue> candidates)
+               {
+                       return candidates.Contains (this.Argument);
+               }
+
+               public override bool Contains (TSymbolicValue symbol)
+               {
+                       return this.Argument.Equals (symbol);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ((string) "IsInst({0} {1})", (object) this.Type, (object) this.Argument);
+               }
+
+               public override bool Equals (Expr<TSymbolicValue> other)
+               {
+                       var inst = other as IsInstExpr<TSymbolicValue>;
+
+                       return (inst != null && inst.Type.Equals (this.Type) && inst.Argument.Equals (this.Argument));
+               }
+               #endregion
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..fc9e8de
--- /dev/null
@@ -0,0 +1,79 @@
+// 
+// NullExpr.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 Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       sealed class NullExpr<TSymbolicValue> : Expr<TSymbolicValue> where TSymbolicValue : IEquatable<TSymbolicValue> {
+               public static readonly Expr<TSymbolicValue> Instance = new NullExpr<TSymbolicValue> ();
+
+               private NullExpr ()
+               {
+               }
+
+               #region Overrides of Expression
+               public override IEnumerable<TSymbolicValue> Variables
+               {
+                       get { yield break; }
+               }
+
+               public override Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data)
+               {
+                       return visitor.LoadNull (pc, dest, data);
+               }
+
+               public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions)
+               {
+                       return this;
+               }
+
+               public override bool IsContained (IImmutableSet<TSymbolicValue> candidates)
+               {
+                       return false;
+               }
+
+               public override bool Contains (TSymbolicValue symbol)
+               {
+                       return false;
+               }
+
+               public override string ToString ()
+               {
+                       return "Null()";
+               }
+
+               public override bool Equals (Expr<TSymbolicValue> other)
+               {
+                       return other == this;
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..106880d
--- /dev/null
@@ -0,0 +1,85 @@
+// 
+// SizeoOfExpr.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.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       sealed class SizeOfExpr<TSymbolicValue> : Expr<TSymbolicValue> where TSymbolicValue : IEquatable<TSymbolicValue> {
+
+               public readonly TypeNode Type;
+
+               public SizeOfExpr (TypeNode type)
+               {
+                       this.Type = type;
+               }
+
+               #region Overrides of Expression
+               public override IEnumerable<TSymbolicValue> Variables
+               {
+                       get { return Enumerable.Empty<TSymbolicValue> (); }
+               }
+
+               public override Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data)
+               {
+                       return visitor.Sizeof (pc, this.Type, dest, data);
+               }
+
+               public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions)
+               {
+                       return this;
+               }
+
+               public override bool IsContained (IImmutableSet<TSymbolicValue> candidates)
+               {
+                       return false;
+               }
+
+               public override bool Contains (TSymbolicValue symbol)
+               {
+                       return false;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("Sizeof({0})", this.Type);
+               }
+
+               public override bool Equals (Expr<TSymbolicValue> other)
+               {
+                       var @sizeof = other as SizeOfExpr<TSymbolicValue>;
+
+                       return (@sizeof != null && @sizeof.Type.Equals (this.Type));
+               }
+               #endregion
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..8dd288a
--- /dev/null
@@ -0,0 +1,92 @@
+// 
+// UnaryExpr.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions {
+       class UnaryExpr<TSymbolicValue> : Expr<TSymbolicValue> where TSymbolicValue : IEquatable<TSymbolicValue> {
+               public readonly UnaryOperator Operator;
+               public readonly TSymbolicValue Source;
+               public readonly bool Unsigned;
+
+               public UnaryExpr (TSymbolicValue source, UnaryOperator op, bool unsigned)
+               {
+                       this.Source = source;
+                       this.Operator = op;
+                       this.Unsigned = unsigned;
+               }
+
+               #region Overrides of Expression
+               public override IEnumerable<TSymbolicValue> Variables
+               {
+                       get { yield return this.Source; }
+               }
+
+               public override Result Decode<Data, Result, Visitor> (APC pc, TSymbolicValue dest, Visitor visitor, Data data)
+               {
+                       return visitor.Unary (pc, this.Operator, this.Unsigned, dest, this.Source, data);
+               }
+
+               public override Expr<TSymbolicValue> Substitute (IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> substitutions)
+               {
+                       if (substitutions.ContainsKey (this.Source))
+                               return new UnaryExpr<TSymbolicValue> (substitutions [this.Source].Head, this.Operator, this.Unsigned);
+                       
+                       return null;
+               }
+
+               public override bool IsContained (IImmutableSet<TSymbolicValue> candidates)
+               {
+                       return candidates.Contains (this.Source);
+               }
+
+               public override bool Contains (TSymbolicValue symbol)
+               {
+                       return symbol.Equals (this.Source);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("Unary({0} {1})", this.Operator, this.Source);
+               }
+
+               public override bool Equals (Expr<TSymbolicValue> other)
+               {
+                       var unary = other as UnaryExpr<TSymbolicValue>;
+                       if (unary == null || unary.Operator != this.Operator || unary.Unsigned != this.Unsigned)
+                               return false;
+
+                       return unary.Source.Equals (this.Source);
+               }
+               #endregion
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..b87e83a
--- /dev/null
@@ -0,0 +1,98 @@
+// 
+// AnalysisDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       class AnalysisDecoder<TSymValue> : ILVisitorBase<APC, TSymValue, TSymValue, ExprDomain<TSymValue>, ExprDomain<TSymValue>>
+               where TSymValue : IEquatable<TSymValue> {
+               public override ExprDomain<TSymValue> DefaultVisit (APC pc, ExprDomain<TSymValue> data)
+               {
+                       return data;
+               }
+
+               public override ExprDomain<TSymValue> Assume (APC pc, EdgeTag tag, TSymValue condition, ExprDomain<TSymValue> data)
+               {
+                       FlatDomain<Expr<TSymValue>> aExpression = data [condition];
+
+                       if (aExpression.IsNormal) {
+                               bool truth = tag != EdgeTag.False;
+                               data = aExpression.Concrete.Decode<ExprDomain<TSymValue>, ExprDomain<TSymValue>, AssumeDecoder<TSymValue>>
+                                       (pc, condition, new AssumeDecoder<TSymValue> (truth), data);
+                       }
+
+                       return data;
+               }
+
+               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>>
+                                       (pc, condition, new AssumeDecoder<TSymValue> (true), data);
+                       }
+
+                       return data;
+               }
+
+               public override ExprDomain<TSymValue> Binary (APC pc, BinaryOperator op, TSymValue dest, TSymValue operand1, TSymValue operand2, ExprDomain<TSymValue> data)
+               {
+                       return data.Add (dest, new BinaryExpr<TSymValue> (operand1, operand2, op));
+               }
+
+               public override ExprDomain<TSymValue> Isinst (APC pc, TypeNode type, TSymValue dest, TSymValue obj, ExprDomain<TSymValue> data)
+               {
+                       return data.Add (dest, new IsInstExpr<TSymValue> (obj, type));
+               }
+
+               public override ExprDomain<TSymValue> LoadConst (APC pc, TypeNode type, object constant, TSymValue dest, ExprDomain<TSymValue> data)
+               {
+                       return data.Add (dest, new ConstExpr<TSymValue> (type, constant));
+               }
+
+               public override ExprDomain<TSymValue> LoadNull (APC pc, TSymValue dest, ExprDomain<TSymValue> polarity)
+               {
+                       return polarity.Add (dest, NullExpr<TSymValue>.Instance);
+               }
+
+               public override ExprDomain<TSymValue> Sizeof (APC pc, TypeNode type, TSymValue dest, ExprDomain<TSymValue> data)
+               {
+                       return data.Add (dest, new SizeOfExpr<TSymValue> (type));
+               }
+
+               public override ExprDomain<TSymValue> Unary (APC pc, UnaryOperator op, bool unsigned, TSymValue dest, TSymValue source, ExprDomain<TSymValue> data)
+               {
+                       return data.Add (dest, new UnaryExpr<TSymValue> (source, op, unsigned));
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..4780fbd
--- /dev/null
@@ -0,0 +1,100 @@
+// 
+// AssumeDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       struct AssumeDecoder<SymbolicValue> : IExpressionILVisitor<APC, SymbolicValue, SymbolicValue, ExprDomain<SymbolicValue>, ExprDomain<SymbolicValue>>
+               where SymbolicValue : IEquatable<SymbolicValue> {
+               private readonly bool truth;
+
+               public AssumeDecoder (bool truth)
+               {
+                       this.truth = truth;
+               }
+
+               #region IExpressionILVisitor<APC,SymbolicValue,SymbolicValue,ExprDomain<SymbolicValue>,ExprDomain<SymbolicValue>> Members
+               public ExprDomain<SymbolicValue> Binary (APC pc, BinaryOperator op, SymbolicValue dest, SymbolicValue s1, SymbolicValue s2, ExprDomain<SymbolicValue> data)
+               {
+                       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);
+                               } 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 (!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);
+                               } else if (!data.HasRefinement (s2)) {
+                                       FlatDomain<Expr<SymbolicValue>> expression1 = data [s1];
+                                       if (expression1.IsNormal && !data.IsReachableFrom (s1, s2))
+                                               return data.Add (s2, expression1.Concrete);
+                               }
+                       }
+                       return data;
+               }
+
+               public ExprDomain<SymbolicValue> Isinst (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, ExprDomain<SymbolicValue> data)
+               {
+                       return data;
+               }
+
+               public ExprDomain<SymbolicValue> LoadNull (APC pc, SymbolicValue dest, ExprDomain<SymbolicValue> polarity)
+               {
+                       return polarity;
+               }
+
+               public ExprDomain<SymbolicValue> LoadConst (APC pc, TypeNode type, object constant, SymbolicValue dest, ExprDomain<SymbolicValue> data)
+               {
+                       return data;
+               }
+
+               public ExprDomain<SymbolicValue> Sizeof (APC pc, TypeNode type, SymbolicValue dest, ExprDomain<SymbolicValue> data)
+               {
+                       return data;
+               }
+
+               public ExprDomain<SymbolicValue> Unary (APC pc, UnaryOperator op, bool unsigned, SymbolicValue dest, SymbolicValue source, ExprDomain<SymbolicValue> data)
+               {
+                       return data;
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..f596be9
--- /dev/null
@@ -0,0 +1,121 @@
+// 
+// ExprDomain.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.IO;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       class ExprDomain<TSymValue> : IGraph<TSymValue, Dummy> 
+               where TSymValue : IEquatable<TSymValue> {
+               private readonly EnvironmentDomain<TSymValue, FlatDomain<Expr<TSymValue>>> expressions;
+
+               private ExprDomain (EnvironmentDomain<TSymValue, FlatDomain<Expr<TSymValue>>> expressions)
+               {
+                       this.expressions = expressions;
+               }
+
+               #region Implementation of IGraph<SymbolicValue,Dummy>
+               public IEnumerable<TSymValue> Keys
+               {
+                       get { return this.expressions.Keys; }
+               }
+
+               public bool IsBottom
+               {
+                       get { return this.expressions.IsBottom; }
+               }
+
+               IEnumerable<TSymValue> IGraph<TSymValue, Dummy>.Nodes
+               {
+                       get { return this.expressions.Keys; }
+               }
+
+               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);
+               }
+               #endregion
+
+               public FlatDomain<Expr<TSymValue>> this[TSymValue sv]
+               {
+                       get { return this.expressions[sv]; }
+               }
+
+               public ExprDomain<TSymValue> Join(ExprDomain<TSymValue> that, bool widening, out bool weaker)
+               {
+                       return new ExprDomain<TSymValue> (this.expressions.Join (that.expressions, widening, out weaker));
+               }
+
+               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));
+               }
+
+               public ExprDomain<TSymValue> Remove(TSymValue sv)
+               {
+                       return new ExprDomain<TSymValue> (this.expressions.Remove (sv));
+               }
+
+               public ExprDomain<TSymValue> Empty()
+               {
+                       return new ExprDomain<TSymValue> (this.expressions.Empty ());
+               }
+
+               public bool HasRefinement(TSymValue sv)
+               {
+                       return this.expressions.Contains (sv);
+               }
+
+               public bool IsReachableFrom(TSymValue source, TSymValue target)
+               {
+                       bool reachable = false;
+                       DepthFirst.Visit (this, source, sv => {
+                                                               if (sv.Equals (target))
+                                                                       reachable = true;
+                                                               return true;
+                                                       }, null);
+                       return reachable;
+               }
+
+               public void Dump(TextWriter tw)
+               {
+                       this.expressions.Dump (tw);
+               }
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..026a460
--- /dev/null
@@ -0,0 +1,88 @@
+// 
+// ExpressionAnalysisFacade.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 Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataFlowAnalysis;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+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>> {
+               
+               public readonly Predicate<APC> IsUnreachable;
+
+               public readonly ICodeLayer<TSymValue, TSymValue, TContext, TEdgeData> ValueLayer;
+               private IFixPointInfo<APC, ExprDomain<TSymValue>> fix_point_info;
+
+               public ExpressionAnalysisFacade (ICodeLayer<TSymValue, TSymValue, TContext, TEdgeData> valueLayer,
+                                                Predicate<APC> isUnreachable)
+               {
+                       this.ValueLayer = valueLayer;
+                       this.IsUnreachable = isUnreachable;
+               }
+
+               public bool PreStateLookup (APC label, out ExprDomain<TSymValue> ifFound)
+               {
+                       return this.fix_point_info.PreStateLookup (label, out ifFound);
+               }
+
+               public bool PostStateLookup (APC label, out ExprDomain<TSymValue> ifFound)
+               {
+                       return this.fix_point_info.PostStateLookup (label, out ifFound);
+               }
+
+               public void SaveFixPointInfo (IFixPointInfo<APC, ExprDomain<TSymValue>> fixPointInfo)
+               {
+                       this.fix_point_info = fixPointInfo;
+               }
+
+               public ExprDomain<TSymValue> InitialValue (Func<TSymValue, int> keyConverter)
+               {
+                       return ExprDomain<TSymValue>.TopValue (keyConverter);
+               }
+
+               public IAnalysis<APC, ExprDomain<TSymValue>, IILVisitor<APC, TSymValue, TSymValue, ExprDomain<TSymValue>, ExprDomain<TSymValue>>, TEdgeData> 
+                       CreateExpressionAnalysis ()
+               {
+                       return new ValueAnalysis<TSymValue, TContext, TEdgeData> (this);
+               }
+
+               public IILDecoder<APC, LabeledSymbol<APC, TSymValue>, TSymValue, IExpressionContextProvider<LabeledSymbol<APC, TSymValue>, TSymValue>, TEdgeData> 
+                       GetDecoder (
+                       IILDecoder<APC, TSymValue, TSymValue, IValueContextProvider<TSymValue>, TEdgeData> ilDecoder)
+               {
+                       return new ExpressionDecoder<TSymValue, TContext, TEdgeData> (ilDecoder, this);
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..3fc0581
--- /dev/null
@@ -0,0 +1,165 @@
+// 
+// ExpressionDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
+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;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       class ExpressionDecoder<TSymbolicValue, TContext, TEdgeData> :
+               IILDecoder<APC, LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue, IExpressionContextProvider<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue>, TEdgeData>,
+               IExpressionContextProvider<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue>,
+               IExpressionContext<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue>
+               where TSymbolicValue : IEquatable<TSymbolicValue>
+               where TContext : IValueContextProvider<TSymbolicValue>
+               where TEdgeData : IImmutableMap<TSymbolicValue, LispList<TSymbolicValue>> {
+               private readonly IILDecoder<APC, TSymbolicValue, TSymbolicValue, IValueContextProvider<TSymbolicValue>, TEdgeData> value_decoder;
+               private readonly ExpressionAnalysisFacade<TSymbolicValue, TContext, TEdgeData> parent;
+               private readonly IValueContextProvider<TSymbolicValue> underlying;
+
+               public ExpressionDecoder (IILDecoder<APC, TSymbolicValue, TSymbolicValue, IValueContextProvider<TSymbolicValue>, TEdgeData> valueDecoder,
+                                         ExpressionAnalysisFacade<TSymbolicValue, TContext, TEdgeData> parent)
+               {
+                       this.value_decoder = valueDecoder;
+                       this.parent = parent;
+                       this.underlying = valueDecoder.ContextProvider;
+               }
+
+               #region IExpressionContext<LabeledSymbol<APC,SymbolicValue>,SymbolicValue> Members
+               public LabeledSymbol<APC, TSymbolicValue> Refine (APC pc, TSymbolicValue variable)
+               {
+                       return new LabeledSymbol<APC, TSymbolicValue> (pc, variable);
+               }
+
+               public TSymbolicValue Unrefine (LabeledSymbol<APC, TSymbolicValue> expression)
+               {
+                       return expression.Symbol;
+               }
+
+               public Result Decode<Data, Result, Visitor> (LabeledSymbol<APC, TSymbolicValue> expr, Visitor visitor, Data data)
+                       where Visitor : ISymbolicExpressionVisitor<LabeledSymbol<APC, TSymbolicValue>, LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue, Data, Result>
+               {
+                       ExprDomain<TSymbolicValue> ifFound;
+                       if (!this.parent.PreStateLookup (expr.ReadAt, out ifFound) || ifFound.IsBottom)
+                               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);
+                       }
+
+                       TypeNode type;
+                       object constant;
+                       if (this.parent.ValueLayer.ILDecoder.ContextProvider.ValueContext.IsConstant (expr.ReadAt, expr.Symbol, out type, out constant))
+                               return visitor.LoadConst (expr, type, constant, expr.Symbol, data);
+
+                       return visitor.SymbolicConstant (expr, expr.Symbol, data);
+               }
+
+               public FlatDomain<TypeNode> GetType (LabeledSymbol<APC, TSymbolicValue> expr)
+               {
+                       return this.underlying.ValueContext.GetType (expr.ReadAt, expr.Symbol);
+               }
+
+               public APC GetPC (LabeledSymbol<APC, TSymbolicValue> pc)
+               {
+                       return pc.ReadAt;
+               }
+
+               public LabeledSymbol<APC, TSymbolicValue> For (TSymbolicValue variable)
+               {
+                       return new LabeledSymbol<APC, TSymbolicValue> (MethodContext.CFG.Entry, variable);
+               }
+
+               public bool IsZero (LabeledSymbol<APC, TSymbolicValue> expression)
+               {
+                       return ValueContext.IsZero (expression.ReadAt, expression.Symbol);
+               }
+               #endregion
+
+               #region IILDecoder<APC,LabeledSymbol<APC,SymbolicValue>,SymbolicValue,IExpressionContextProvider<LabeledSymbol<APC,SymbolicValue>,SymbolicValue>,EdgeData> Members
+               public IExpressionContextProvider<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue> ContextProvider
+               {
+                       get { return this; }
+               }
+
+               public Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data state)
+                       where Visitor : IILVisitor<APC, LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue, Data, Result>
+               {
+                       return this.value_decoder.ForwardDecode<Data, Result, ILDecoderAdapter<TSymbolicValue, Data, Result, Visitor>>
+                               (pc, new ILDecoderAdapter<TSymbolicValue, Data, Result, Visitor> (visitor), state);
+               }
+
+               public bool IsUnreachable (APC pc)
+               {
+                       return this.parent.IsUnreachable (pc);
+               }
+
+               public TEdgeData EdgeData (APC from, APC to)
+               {
+                       return this.parent.ValueLayer.ILDecoder.EdgeData (from, to);
+               }
+               #endregion
+
+               #region Implementation of IMethodContextProvider<Field,Method>
+               public IMethodContext MethodContext
+               {
+                       get { return this.underlying.MethodContext; }
+               }
+               #endregion
+
+               #region Implementation of IStackContextProvider<Field,Method>
+               public IStackContext StackContext
+               {
+                       get { return this.underlying.StackContext; }
+               }
+               #endregion
+
+               #region Implementation of IValueContextProvider<Local,Parameter,Method,Field,Type,SymbolicValue>
+               public IValueContext<TSymbolicValue> ValueContext
+               {
+                       get { return this.underlying.ValueContext; }
+               }
+               #endregion
+
+               #region Implementation of IExpressionContextProvider<Local,Parameter,Method,Field,Type,ExternalExpression<APC,SymbolicValue>,SymbolicValue>
+               public IExpressionContext<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue> ExpressionContext
+               {
+                       get { return this; }
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..53a24a4
--- /dev/null
@@ -0,0 +1,57 @@
+using System;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis;
+using Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       struct ExpressionDecoderAdapter<SymbolicValue, Data, Result, Visitor> 
+               : IExpressionILVisitor<APC, SymbolicValue, SymbolicValue, Data, Result>
+               where SymbolicValue : IEquatable<SymbolicValue> 
+               where Visitor : ISymbolicExpressionVisitor<LabeledSymbol<APC, SymbolicValue>, LabeledSymbol<APC, SymbolicValue>, SymbolicValue, Data, Result> {
+
+               private readonly Visitor visitor;
+
+               public ExpressionDecoderAdapter (Visitor visitor)
+               {
+                       this.visitor = visitor;
+               }
+
+               #region Implementation of IExpressionILVisitor<APC,Type,SymbolicValue,SymbolicValue,Data,Result>
+               public Result Binary (APC pc, BinaryOperator op, SymbolicValue dest, SymbolicValue operand1, SymbolicValue operand2, Data data)
+               {
+                       return this.visitor.Binary (Unrefine (pc, dest), op, dest, Unrefine (pc, operand1), Unrefine (pc, operand2), data);
+               }
+
+               public Result Isinst (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.Isinst (Unrefine (pc, dest), type, dest, Unrefine (pc, obj), data);
+               }
+
+               public Result LoadNull (APC pc, SymbolicValue dest, Data polarity)
+               {
+                       return this.visitor.LoadNull (Unrefine (pc, dest), dest, polarity);
+               }
+
+               public Result LoadConst (APC pc, TypeNode type, object constant, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadConst (Unrefine (pc, dest), type, constant, dest, data);
+               }
+
+               public Result Sizeof (APC pc, TypeNode type, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.Sizeof (Unrefine (pc, dest), type, dest, data);
+               }
+
+               public Result Unary (APC pc, UnaryOperator op, bool unsigned, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.Unary (Unrefine (pc, dest), op, unsigned, dest, Unrefine (pc, source), data);
+               }
+
+               private LabeledSymbol<APC, SymbolicValue> Unrefine (APC pc, SymbolicValue dest)
+               {
+                       return new LabeledSymbol<APC, SymbolicValue> (pc, dest);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionPrinterFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionPrinterFactory.cs
new file mode 100644 (file)
index 0000000..e91cc2b
--- /dev/null
@@ -0,0 +1,132 @@
+// 
+// ExpressionPrinterFactory.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.Text;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.Drivers;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       static class ExpressionPrinterFactory {
+               public static Func<LabeledSymbol<APC, SymbolicValue>, string> Printer<SymbolicValue>
+                       (IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> contextProvider,
+                        IMethodDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> methodDriver)
+                       where SymbolicValue : IEquatable<SymbolicValue>
+               {
+                       return new PrinterImpl<SymbolicValue> (contextProvider, methodDriver).PrintAt;
+               }
+
+               #region Nested type: PrinterImpl
+               private class PrinterImpl<SymbolicValue> :
+                       ISymbolicExpressionVisitor<LabeledSymbol<APC, SymbolicValue>, LabeledSymbol<APC, SymbolicValue>, SymbolicValue, StringBuilder, Dummy>
+                       where SymbolicValue : IEquatable<SymbolicValue> {
+                       private readonly IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> context_provider;
+                       private readonly IMethodDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> method_driver;
+
+                       public PrinterImpl (IExpressionContextProvider<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> contextProvider,
+                                           IMethodDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> methodDriver)
+                       {
+                               this.context_provider = contextProvider;
+                               this.method_driver = methodDriver;
+                       }
+
+                       public string PrintAt (LabeledSymbol<APC, SymbolicValue> expr)
+                       {
+                               var sb = new StringBuilder ();
+                               Recurse (sb, expr);
+                               return sb.ToString ();
+                       }
+
+                       private void Recurse (StringBuilder sb, LabeledSymbol<APC, SymbolicValue> expr)
+                       {
+                               if (expr.Symbol.Equals (default(SymbolicValue)))
+                                       sb.Append ("<!null!>");
+                               else
+                                       this.context_provider.ExpressionContext.Decode<StringBuilder, Dummy, PrinterImpl<SymbolicValue>> (expr, this, sb);
+                       }
+
+                       #region Implementation of IExpressionILVisitor<ExternalExpression<APC,SymbolicValue>,ExternalExpression<APC,SymbolicValue>,SymbolicValue,StringBuilder,Dummy>
+                       public Dummy Binary (LabeledSymbol<APC, SymbolicValue> pc, BinaryOperator op, SymbolicValue dest, LabeledSymbol<APC, SymbolicValue> operand1, LabeledSymbol<APC, SymbolicValue> operand2,
+                                            StringBuilder data)
+                       {
+                               data.Append ('(');
+                               Recurse (data, operand1);
+                               data.AppendFormat (" {0} ", op);
+                               Recurse (data, operand2);
+                               data.Append (')');
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Isinst (LabeledSymbol<APC, SymbolicValue> pc, TypeNode type, SymbolicValue dest, LabeledSymbol<APC, SymbolicValue> obj, StringBuilder data)
+                       {
+                               data.AppendFormat ("IsInst({0}) ", this.method_driver.MetaDataProvider.FullName (type));
+                               Recurse (data, obj);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadNull (LabeledSymbol<APC, SymbolicValue> pc, SymbolicValue dest, StringBuilder polarity)
+                       {
+                               polarity.Append ("NULL");
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadConst (LabeledSymbol<APC, SymbolicValue> pc, TypeNode type, object constant, SymbolicValue dest, StringBuilder data)
+                       {
+                               data.Append (constant.ToString ());
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Sizeof (LabeledSymbol<APC, SymbolicValue> pc, TypeNode type, SymbolicValue dest, StringBuilder data)
+                       {
+                               data.AppendFormat ("sizeof({0})", this.method_driver.MetaDataProvider.FullName (type));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Unary (LabeledSymbol<APC, SymbolicValue> pc, UnaryOperator op, bool unsigned, SymbolicValue dest, LabeledSymbol<APC, SymbolicValue> source, StringBuilder data)
+                       {
+                               data.AppendFormat ("{0} ", op.ToString ());
+                               Recurse (data, source);
+                               return Dummy.Value;
+                       }
+                       #endregion
+
+                       #region Implementation of ISymbolicExpressionVisitor<ExternalExpression<APC,SymbolicValue>,ExternalExpression<APC,SymbolicValue>,SymbolicValue,StringBuilder,Dummy>
+                       public Dummy SymbolicConstant (LabeledSymbol<APC, SymbolicValue> pc, SymbolicValue variable, StringBuilder data)
+                       {
+                               data.Append (variable.ToString ());
+                               return Dummy.Value;
+                       }
+                       #endregion
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ILDecoderAdapter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ILDecoderAdapter.cs
new file mode 100644 (file)
index 0000000..0c00327
--- /dev/null
@@ -0,0 +1,411 @@
+// 
+// ILDecoderAdapter.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       /// <summary>
+       /// This class performs translation from (source) SymbolicValue to LabeledSymbol
+       /// </summary>
+       struct ILDecoderAdapter<SymbolicValue, Data, Result, Visitor>
+               : IILVisitor<APC, SymbolicValue, SymbolicValue, Data, Result>
+               where SymbolicValue : IEquatable<SymbolicValue>
+               where Visitor : IILVisitor<APC, LabeledSymbol<APC, SymbolicValue>, SymbolicValue, Data, Result> {
+               private readonly Visitor visitor;
+
+               public ILDecoderAdapter (Visitor visitor)
+               {
+                       this.visitor = visitor;
+               }
+
+               #region IILVisitor<APC,SymbolicValue,SymbolicValue,Data,Result> Members
+               public Result Binary (APC pc, BinaryOperator op, SymbolicValue dest, SymbolicValue operand1, SymbolicValue operand2, Data data)
+               {
+                       return this.visitor.Binary (pc, op, dest, Convert (pc, operand1), Convert (pc, operand2), data);
+               }
+
+               public Result Isinst (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.Isinst (pc, type, dest, Convert (pc, obj), data);
+               }
+
+               public Result LoadNull (APC pc, SymbolicValue dest, Data polarity)
+               {
+                       return this.visitor.LoadNull (pc, dest, polarity);
+               }
+
+               public Result LoadConst (APC pc, TypeNode type, object constant, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadConst (pc, type, constant, dest, data);
+               }
+
+               public Result Sizeof (APC pc, TypeNode type, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.Sizeof (pc, type, dest, data);
+               }
+
+               public Result Unary (APC pc, UnaryOperator op, bool unsigned, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.Unary (pc, op, unsigned, dest, Convert (pc, source), data);
+               }
+
+               public Result Entry (APC pc, Method method, Data data)
+               {
+                       return this.visitor.Entry (pc, method, data);
+               }
+
+               public Result Assume (APC pc, EdgeTag tag, SymbolicValue condition, Data data)
+               {
+                       return this.visitor.Assume (pc, tag, Convert (pc, condition), data);
+               }
+
+               public Result Assert (APC pc, EdgeTag tag, SymbolicValue condition, Data data)
+               {
+                       return this.visitor.Assert (pc, tag, Convert (pc, condition), data);
+               }
+
+               public Result BeginOld (APC pc, APC matchingEnd, Data data)
+               {
+                       return this.visitor.BeginOld (pc, matchingEnd, data);
+               }
+
+               public Result EndOld (APC pc, APC matchingBegin, TypeNode type, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.EndOld (pc, matchingBegin, type, dest, Convert (pc, source), data);
+               }
+
+               public Result LoadStack (APC pc, int offset, SymbolicValue dest, SymbolicValue source, bool isOld, Data data)
+               {
+                       return this.visitor.LoadStack (pc, offset, dest, Convert (pc, source), isOld, data);
+               }
+
+               public Result LoadStackAddress (APC pc, int offset, SymbolicValue dest, SymbolicValue source, TypeNode type, bool isOld, Data data)
+               {
+                       return this.visitor.LoadStackAddress (pc, offset, dest, Convert (pc, source), type, isOld, data);
+               }
+
+               public Result LoadResult (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.LoadResult (pc, type, dest, Convert (pc, source), data);
+               }
+
+               public Result Arglist (APC pc, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.Arglist (pc, dest, data);
+               }
+
+               public Result Branch (APC pc, APC target, bool leavesExceptionBlock, Data data)
+               {
+                       throw new Exception ("Should not get branches at this level of abstraction.");
+               }
+
+               public Result BranchCond (APC pc, APC target, BranchOperator bop, SymbolicValue value1, SymbolicValue value2, Data data)
+               {
+                       throw new Exception ("Should not get branches at this level of abstraction.");
+               }
+
+               public Result BranchTrue (APC pc, APC target, SymbolicValue cond, Data data)
+               {
+                       throw new Exception ("Should not get branches at this level of abstraction.");
+               }
+
+               public Result BranchFalse (APC pc, APC target, SymbolicValue cond, Data data)
+               {
+                       throw new Exception ("Should not get branches at this level of abstraction.");
+               }
+
+               public Result Break (APC pc, Data data)
+               {
+                       return this.visitor.Break (pc, data);
+               }
+
+               public Result Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, SymbolicValue dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<SymbolicValue>
+               {
+                       return this.visitor.Call (pc, method, virt, extraVarargs, dest, Convert (pc, args), data);
+               }
+
+               public Result Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, SymbolicValue dest, SymbolicValue functionPointer, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<SymbolicValue>
+               {
+                       return this.visitor.Calli (pc, returnType, argTypes, instance, dest, Convert (pc, functionPointer), Convert (pc, args), data);
+               }
+
+               public Result CheckFinite (APC pc, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.CheckFinite (pc, dest, Convert (pc, source), data);
+               }
+
+               public Result CopyBlock (APC pc, SymbolicValue destAddress, SymbolicValue srcAddress, SymbolicValue len, Data data)
+               {
+                       return this.visitor.CopyBlock (pc, Convert (pc, destAddress), Convert (pc, srcAddress), Convert (pc, len), data);
+               }
+
+               public Result EndFilter (APC pc, SymbolicValue decision, Data data)
+               {
+                       return this.visitor.EndFilter (pc, Convert (pc, decision), data);
+               }
+
+               public Result EndFinally (APC pc, Data data)
+               {
+                       return this.visitor.EndFinally (pc, data);
+               }
+
+               public Result Jmp (APC pc, Method method, Data data)
+               {
+                       return this.visitor.Jmp (pc, method, data);
+               }
+
+               public Result LoadArg (APC pc, Parameter argument, bool isOld, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadArg (pc, argument, isOld, dest, data);
+               }
+
+               public Result LoadArgAddress (APC pc, Parameter argument, bool isOld, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadArgAddress (pc, argument, isOld, dest, data);
+               }
+
+               public Result LoadLocal (APC pc, Local local, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadLocal (pc, local, dest, data);
+               }
+
+               public Result LoadLocalAddress (APC pc, Local local, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadLocalAddress (pc, local, dest, data);
+               }
+
+               public Result Nop (APC pc, Data data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public Result Pop (APC pc, SymbolicValue source, Data data)
+               {
+                       return this.visitor.Pop (pc, Convert (pc, source), data);
+               }
+
+               public Result Return (APC pc, SymbolicValue source, Data data)
+               {
+                       return this.visitor.Return (pc, Convert (pc, source), data);
+               }
+
+               public Result StoreArg (APC pc, Parameter argument, SymbolicValue source, Data data)
+               {
+                       return this.visitor.StoreArg (pc, argument, Convert (pc, source), data);
+               }
+
+               public Result StoreLocal (APC pc, Local local, SymbolicValue source, Data data)
+               {
+                       return this.visitor.StoreLocal (pc, local, Convert (pc, source), data);
+               }
+
+               public Result Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, SymbolicValue value, Data data)
+               {
+                       throw new Exception ("Should not get branches at this level of abstraction.");
+               }
+
+               public Result Box (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.Box (pc, type, dest, Convert (pc, source), data);
+               }
+
+               public Result ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint, TypeList extraVarargs, SymbolicValue dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<SymbolicValue>
+               {
+                       return this.visitor.ConstrainedCallvirt (pc, method, constraint, extraVarargs, dest, Convert (pc, args), data);
+               }
+
+               public Result CastClass (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.CastClass (pc, type, dest, Convert (pc, obj), data);
+               }
+
+               public Result CopyObj (APC pc, TypeNode type, SymbolicValue destPtr, SymbolicValue sourcePtr, Data data)
+               {
+                       return this.visitor.CopyObj (pc, type, Convert (pc, destPtr), Convert (pc, sourcePtr), data);
+               }
+
+               public Result Initobj (APC pc, TypeNode type, SymbolicValue ptr, Data data)
+               {
+                       return this.visitor.Initobj (pc, type, Convert (pc, ptr), data);
+               }
+
+               public Result LoadElement (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue array, SymbolicValue index, Data data)
+               {
+                       return this.visitor.LoadElement (pc, type, dest, Convert (pc, array), Convert (pc, index), data);
+               }
+
+               public Result LoadField (APC pc, Field field, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.LoadField (pc, field, dest, Convert (pc, obj), data);
+               }
+
+               public Result LoadFieldAddress (APC pc, Field field, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.LoadFieldAddress (pc, field, dest, Convert (pc, obj), data);
+               }
+
+               public Result LoadLength (APC pc, SymbolicValue dest, SymbolicValue array, Data data)
+               {
+                       return this.visitor.LoadLength (pc, dest, Convert (pc, array), data);
+               }
+
+               public Result LoadStaticField (APC pc, Field field, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadStaticField (pc, field, dest, data);
+               }
+
+               public Result LoadStaticFieldAddress (APC pc, Field field, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadStaticFieldAddress (pc, field, dest, data);
+               }
+
+               public Result LoadTypeToken (APC pc, TypeNode type, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadTypeToken (pc, type, dest, data);
+               }
+
+               public Result LoadFieldToken (APC pc, Field type, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadFieldToken (pc, type, dest, data);
+               }
+
+               public Result LoadMethodToken (APC pc, Method type, SymbolicValue dest, Data data)
+               {
+                       return this.visitor.LoadMethodToken (pc, type, dest, data);
+               }
+
+               public Result NewArray<ArgList> (APC pc, TypeNode type, SymbolicValue dest, ArgList lengths, Data data) where ArgList : IIndexable<SymbolicValue>
+               {
+                       return this.visitor.NewArray (pc, type, dest, Convert (pc, lengths), data);
+               }
+
+               public Result NewObj<ArgList> (APC pc, Method ctor, SymbolicValue dest, ArgList args, Data data) where ArgList : IIndexable<SymbolicValue>
+               {
+                       return this.visitor.NewObj (pc, ctor, dest, Convert (pc, args), data);
+               }
+
+               public Result MkRefAny (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.MkRefAny (pc, type, dest, Convert (pc, obj), data);
+               }
+
+               public Result RefAnyType (APC pc, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.RefAnyType (pc, dest, Convert (pc, source), data);
+               }
+
+               public Result RefAnyVal (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue source, Data data)
+               {
+                       return this.visitor.RefAnyVal (pc, type, dest, Convert (pc, source), data);
+               }
+
+               public Result Rethrow (APC pc, Data data)
+               {
+                       return this.visitor.Rethrow (pc, data);
+               }
+
+               public Result StoreElement (APC pc, TypeNode type, SymbolicValue array, SymbolicValue index, SymbolicValue value, Data data)
+               {
+                       return this.visitor.StoreElement (pc, type, Convert (pc, array), Convert (pc, index), Convert (pc, value), data);
+               }
+
+               public Result StoreField (APC pc, Field field, SymbolicValue obj, SymbolicValue value, Data data)
+               {
+                       return this.visitor.StoreField (pc, field, Convert (pc, obj), Convert (pc, value), data);
+               }
+
+               public Result StoreStaticField (APC pc, Field field, SymbolicValue value, Data data)
+               {
+                       return this.visitor.StoreStaticField (pc, field, Convert (pc, value), data);
+               }
+
+               public Result Throw (APC pc, SymbolicValue exception, Data data)
+               {
+                       return this.visitor.Throw (pc, Convert (pc, exception), data);
+               }
+
+               public Result Unbox (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.Unbox (pc, type, dest, Convert (pc, obj), data);
+               }
+
+               public Result UnboxAny (APC pc, TypeNode type, SymbolicValue dest, SymbolicValue obj, Data data)
+               {
+                       return this.visitor.UnboxAny (pc, type, dest, Convert (pc, obj), data);
+               }
+               #endregion
+
+               private static LabeledSymbol<APC, SymbolicValue> Convert (APC pc, SymbolicValue value)
+               {
+                       return new LabeledSymbol<APC, SymbolicValue> (pc, value);
+               }
+
+               private static ArgumentWrapper<ArgList> Convert<ArgList> (APC pc, ArgList value)
+                       where ArgList : IIndexable<SymbolicValue>
+               {
+                       return new ArgumentWrapper<ArgList> (value, pc);
+               }
+
+               #region Nested type: ArgumentWrapper
+               private struct ArgumentWrapper<ArgList> : IIndexable<LabeledSymbol<APC, SymbolicValue>>
+                       where ArgList : IIndexable<SymbolicValue> {
+                       private readonly APC readAt;
+                       private readonly ArgList underlying;
+
+                       public ArgumentWrapper (ArgList underlying, APC readAt)
+                       {
+                               this.underlying = underlying;
+                               this.readAt = readAt;
+                       }
+
+                       #region Implementation of IIndexable<ExternalExpression<APC,SymbolicValue>>
+                       public int Count
+                       {
+                               get { return this.underlying.Count; }
+                       }
+
+                       public LabeledSymbol<APC, SymbolicValue> this [int index]
+                       {
+                               get { return new LabeledSymbol<APC, SymbolicValue> (this.readAt, this.underlying [index]); }
+                       }
+                       #endregion
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..47cd464
--- /dev/null
@@ -0,0 +1,122 @@
+using System;
+using System.IO;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataFlowAnalysis;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
+       class ValueAnalysis<SymbolicValue, Context, EdgeData> : IAnalysis<APC, ExprDomain<SymbolicValue>,
+                                                                        IILVisitor<APC, SymbolicValue, SymbolicValue, ExprDomain<SymbolicValue>, ExprDomain<SymbolicValue>>, EdgeData>
+                       where SymbolicValue : IEquatable<SymbolicValue> 
+                       where Context : IValueContextProvider<SymbolicValue> 
+                       where EdgeData : IImmutableMap<SymbolicValue, LispList<SymbolicValue>> {
+               private readonly ExpressionAnalysisFacade<SymbolicValue, Context, EdgeData> parent;
+
+               public ValueAnalysis (ExpressionAnalysisFacade<SymbolicValue, Context, EdgeData> parent)
+               {
+                       this.parent = parent;
+               }
+
+               #region Implementation of IAnalysis<APC,ExpressionAnalysis<Local,Parameter,Method,Field,Property,Event,Type,Attribute,Assembly,SymbolicValue,contextProvider,EdgeData>.Domain,IILVisitor<APC,Local,Parameter,Method,Field,Type,SymbolicValue,SymbolicValue,ExpressionAnalysis<Local,Parameter,Method,Field,Property,Event,Type,Attribute,Assembly,SymbolicValue,contextProvider,EdgeData>.Domain,ExpressionAnalysis<Local,Parameter,Method,Field,Property,Event,Type,Attribute,Assembly,SymbolicValue,contextProvider,EdgeData>.Domain>,EdgeData>
+               public ExprDomain<SymbolicValue> EdgeConversion (APC @from, APC to, bool isJoinPoint, EdgeData sourceTargetMap, ExprDomain<SymbolicValue> originalState)
+               {
+                       if (sourceTargetMap == null)
+                               return originalState;
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("====Expression analysis Parallel assign====");
+                               DumpMap (sourceTargetMap);
+                               DumpExpressions ("original expressions", originalState);
+                       }
+
+                       ExprDomain<SymbolicValue> result = originalState.Empty ();
+                       ExprDomain<SymbolicValue> domain = originalState.Empty ();
+
+                       foreach (SymbolicValue sv in originalState.Keys) {
+                               Expr<SymbolicValue> expression = originalState [sv].Concrete.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;
+                                       foreach (SymbolicValue sub in sourceTargetMap [sv].AsEnumerable ())
+                                               result = result.Add (sub, expression);
+                               }
+                       }
+
+                       if (DebugOptions.Debug)
+                       {
+                               DumpExpressions ("new expressions", result);
+                       }
+                       return result;
+               }
+
+               public IILVisitor<APC, SymbolicValue, SymbolicValue, ExprDomain<SymbolicValue>, ExprDomain<SymbolicValue>> GetVisitor ()
+               {
+                       return new AnalysisDecoder<SymbolicValue> ();
+               }
+
+               public ExprDomain<SymbolicValue> Join (Pair<APC, APC> edge, ExprDomain<SymbolicValue> newstate, ExprDomain<SymbolicValue> prevstate, out bool weaker, bool widen)
+               {
+                       return prevstate.Join (newstate, widen, out weaker);
+               }
+
+               public ExprDomain<SymbolicValue> ImmutableVersion (ExprDomain<SymbolicValue> arg)
+               {
+                       return arg;
+               }
+
+               public ExprDomain<SymbolicValue> MutableVersion (ExprDomain<SymbolicValue> arg)
+               {
+                       return arg;
+               }
+
+               public bool IsBottom (APC pc, ExprDomain<SymbolicValue> state)
+               {
+                       return state.IsBottom;
+               }
+
+               public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, ExprDomain<SymbolicValue>> fixPointInfo)
+               {
+                       this.parent.SaveFixPointInfo (fixPointInfo);
+                       return pc => true;
+               }
+
+               public void Dump (Pair<ExprDomain<SymbolicValue>, TextWriter> pair)
+               {
+                       pair.Key.Dump (pair.Value);
+               }
+
+               private void DumpMap (IImmutableMap<SymbolicValue, LispList<SymbolicValue>> sourceTargetMap)
+               {
+                       Console.WriteLine ("Source-Target assignment");
+                       foreach (SymbolicValue key in sourceTargetMap.Keys) {
+                               foreach (SymbolicValue value in sourceTargetMap [key].AsEnumerable ())
+                                       Console.Write ("{0} ", value);
+                               Console.WriteLine (" := {0}", key);
+                       }
+               }
+
+               private void DumpExpressions (string header, ExprDomain<SymbolicValue> state)
+               {
+                       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);
+                               else if (domain.IsTop)
+                                       Console.WriteLine ("{0} -> (Top)", index);
+                               else if (domain.IsBottom)
+                                       Console.WriteLine ("{0} -> (Bot)", index);
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/AccessPathFilter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/AccessPathFilter.cs
new file mode 100644 (file)
index 0000000..944bf2f
--- /dev/null
@@ -0,0 +1,112 @@
+// 
+// AccessPathFilter.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       class AccessPathFilter<TMember> {
+               public static AccessPathFilter<TMember> NoFilter = new AccessPathFilter<TMember> ();
+               private readonly Flags flags;
+               private readonly TMember member;
+               private readonly MemberFilter member_filter;
+
+               private AccessPathFilter ()
+               {
+                       this.flags = Flags.AllowLocals;
+                       this.member_filter = MemberFilter.NoFilter;
+               }
+
+               private AccessPathFilter (TMember member, MemberFilter memberFilter)
+               {
+                       this.member_filter = memberFilter;
+                       this.member = member;
+               }
+
+               public bool AllowLocal
+               {
+                       get { return (this.flags & Flags.AllowLocals) == Flags.AllowLocals; }
+               }
+
+               public bool HasVisibilityMember
+               {
+                       get { return this.member_filter != MemberFilter.NoFilter; }
+               }
+
+               public TMember VisibilityMember
+               {
+                       get { return this.member; }
+               }
+
+               public static AccessPathFilter<TMember> FromPrecondition (TMember member)
+               {
+                       return new AccessPathFilter<TMember> (member, MemberFilter.FromPrecondition);
+               }
+
+               public static AccessPathFilter<TMember> FromPostcondition (TMember member)
+               {
+                       return new AccessPathFilter<TMember> (member, MemberFilter.FromPostcondition);
+               }
+
+               public static AccessPathFilter<TMember> IsVisibleFrom (TMember member)
+               {
+                       return new AccessPathFilter<TMember> (member, MemberFilter.FromMethodBody);
+               }
+
+               public bool FilterOutPathElement<P> (P element)
+                       where P : IVisibilityCheck<TMember>
+               {
+                       switch (this.member_filter) {
+                       case MemberFilter.FromPrecondition:
+                               return !element.IsAsVisibleAs (this.member);
+                       case MemberFilter.FromPostcondition:
+                               return !element.IfRootIsParameter || !element.IsVisibleFrom (this.member);
+                       case MemberFilter.FromMethodBody:
+                               return !element.IsVisibleFrom (this.member);
+                       default:
+                               return false;
+                       }
+               }
+
+               #region Nested type: Flags
+               [Flags]
+               private enum Flags {
+                       AllowLocals = 1,
+                       RequireParameter = 2
+               }
+               #endregion
+
+               #region Nested type: MemberFilter
+               private enum MemberFilter {
+                       NoFilter = 0,
+                       FromPrecondition,
+                       FromPostcondition,
+                       FromMethodBody
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/IVisibilityCheck.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/IVisibilityCheck.cs
new file mode 100644 (file)
index 0000000..22da353
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IVisibilityCheck.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.Analysis.HeapAnalysis.Paths {
+       interface IVisibilityCheck<TMember> {
+               bool IfRootIsParameter { get; }
+               bool IsAsVisibleAs (TMember member);
+               bool IsVisibleFrom (TMember member);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/MethodCallPathElement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/MethodCallPathElement.cs
new file mode 100644 (file)
index 0000000..9244914
--- /dev/null
@@ -0,0 +1,69 @@
+// 
+// MethodCallPathElement.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 Mono.CodeContracts.Static.AST;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       class MethodCallPathElement : PathElement<Method> {
+               private readonly bool is_boolean_typed;
+               private readonly bool is_compressed;
+               private readonly bool is_getter;
+
+               public MethodCallPathElement (Method method,
+                                             bool isGetter, bool isBooleanTyped,
+                                             bool isStatic, string description,
+                                             SymFunction func, bool isCompressed)
+                       : base (method, description, func)
+               {
+                       this.is_boolean_typed = isBooleanTyped;
+                       this.is_getter = isGetter;
+                       this.is_compressed = isCompressed;
+                       this.isStatic = isStatic;
+               }
+
+               public override bool IsAddressOf
+               {
+                       get { return !this.is_compressed; }
+               }
+
+               public override bool IsMethodCall
+               {
+                       get { return true; }
+               }
+
+               public override bool IsGetter
+               {
+                       get { return this.is_getter; }
+               }
+
+               public override bool IsBooleanTyped
+               {
+                       get { return this.is_boolean_typed; }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/ParameterPathElement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/ParameterPathElement.cs
new file mode 100644 (file)
index 0000000..bd5f29a
--- /dev/null
@@ -0,0 +1,67 @@
+// 
+// ParameterPathElement.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       class ParameterPathElement : PathElement<Parameter> {
+               public ParameterPathElement (Parameter p, string description,
+                                            SymFunction c, IMetaDataProvider metaDataProvider)
+                       : base (p, description, c)
+               {
+                       TypeNode type = metaDataProvider.ParameterType (p);
+                       ResultType = metaDataProvider.ManagedPointer (type);
+
+                       if (metaDataProvider.IsManagedPointer (type))
+                               this.isManagedPointer = true;
+               }
+
+               public override bool IsParameter
+               {
+                       get { return true; }
+               }
+
+               public override bool IsAddressOf
+               {
+                       get { return false; }
+               }
+
+               public override Result Decode<Data, Result, Visitor, Label> (Label label, Visitor visitor, Data data)
+               {
+                       Parameter p = this.Element;
+                       return visitor.LoadArg (label, p, false, Dummy.Value, data);
+               }
+
+               public override bool IsCallerVisible ()
+               {
+                       return true;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement.cs
new file mode 100644 (file)
index 0000000..16c87df
--- /dev/null
@@ -0,0 +1,63 @@
+// 
+// PathElement.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths
+{
+  abstract class PathElement
+  {
+    public virtual bool IsBooleanTyped { get { return false; } }
+    public virtual bool IsDeref { get { return false; } }
+
+    public virtual bool IsMethodCall { get { return false; } }
+    public virtual bool IsGetter { get { return false; } }
+    public virtual bool IsStatic { get { return false; } }
+    public virtual bool IsUnmanagedPointer { get { return false; } }
+    public virtual bool IsManagedPointer { get { return false; } }
+    public virtual bool IsParameter { get { return false; } }
+    public virtual bool IsParameterRef { get { return false; } }
+    public virtual string CastTo  { get { return ""; } }
+    public abstract bool IsAddressOf { get; }
+
+    public virtual bool TryField(out Field f)
+    {
+      f = default(Field);
+      return false;
+    }
+
+    public abstract bool TryGetResultType(out TypeNode type);
+
+    public abstract TResult Decode<TData, TResult, TVisitor, TLabel>(TLabel label, TVisitor visitor, TData data)
+      where TVisitor : IAggregateVisitor<TLabel, TData, TResult>;
+
+    public abstract override string ToString();
+  }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElementBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElementBase.cs
new file mode 100644 (file)
index 0000000..4e9187f
--- /dev/null
@@ -0,0 +1,43 @@
+// 
+// PathElementBase.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       abstract class PathElementBase : PathElement {
+               public readonly SymFunction Func;
+
+               protected PathElementBase (SymFunction c)
+               {
+                       this.Func = c;
+               }
+
+               public abstract bool TrySetType (TypeNode expectedType, IMetaDataProvider metaDataProvider, out TypeNode type);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement`1.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement`1.cs
new file mode 100644 (file)
index 0000000..cdbb9fd
--- /dev/null
@@ -0,0 +1,205 @@
+// 
+// PathElement`1.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       class PathElement<T> : PathElementBase {
+               public readonly string Description;
+               public readonly T Element;
+               protected string castTo;
+               protected bool isManagedPointer;
+               protected bool isStatic;
+               protected bool isUnmanagedPointer;
+
+               #region Overrides of PathElement
+               public override bool IsStatic
+               {
+                       get { return this.isStatic; }
+               }
+
+               public override bool IsUnmanagedPointer
+               {
+                       get { return this.isUnmanagedPointer; }
+               }
+
+               public override bool IsManagedPointer
+               {
+                       get { return this.isManagedPointer; }
+               }
+
+               public override bool IsParameterRef
+               {
+                       get { return typeof (T) == typeof (Parameter); }
+               }
+
+               public override string CastTo
+               {
+                       get { return this.castTo; }
+               }
+
+               public override bool IsAddressOf
+               {
+                       get { return true; }
+               }
+
+               public override bool TryField (out Field f)
+               {
+                       if (typeof (T) == typeof (Field)) {
+                               f = (Field) (object) this.Element;
+                               return true;
+                       }
+
+                       f = default(Field);
+                       return false;
+               }
+
+               public override bool TryGetResultType (out TypeNode type)
+               {
+                       type = ResultType;
+                       return true;
+               }
+
+               public override TResult Decode<TData, TResult, TVisitor, TLabel> (TLabel label, TVisitor visitor, TData data)
+               {
+                       if (typeof (T) == typeof (Field)) {
+                               var field = (Field) (object) this.Element;
+                               if (this.isStatic)
+                                       return visitor.LoadStaticFieldAddress (label, field, Dummy.Value, data);
+                               return visitor.LoadFieldAddress (label, field, Dummy.Value, Dummy.Value, data);
+                       }
+
+                       if (typeof (T) == typeof (Local)) {
+                               var local = (Local) (object) this.Element;
+                               return visitor.LoadLocalAddress (label, local, Dummy.Value, data);
+                       }
+
+                       if (typeof (T) == typeof (Method)) {
+                               var method = (Method) (object) this.Element;
+                               bool isVirtualMethod = this.Func.IsVirtualMethod;
+                               return visitor.Call (label, method, isVirtualMethod, Indexable<TypeNode>.Empty, Dummy.Value, Indexable<Dummy>.Empty, data);
+                       }
+
+                       if (typeof (T) == typeof (Parameter)) {
+                               var parameter = (Parameter) (object) this.Element;
+                               return visitor.LoadArgAddress (label, parameter, false, Dummy.Value, data);
+                       }
+
+                       throw new InvalidOperationException ("Field, Local, Method or Parameter expected");
+               }
+
+               public override string ToString ()
+               {
+                       return this.Description;
+               }
+               #endregion
+
+               public PathElement (T element, string description, SymFunction c) : base (c)
+               {
+                       this.Element = element;
+                       this.Description = description;
+                       this.isStatic = false;
+                       this.isUnmanagedPointer = false;
+                       this.isManagedPointer = false;
+               }
+
+               public TypeNode ResultType { get; protected set; }
+
+               public virtual bool IsCallerVisible ()
+               {
+                       return (typeof (T) == typeof (Parameter));
+               }
+
+               #region Overrides of PathElementBase
+               public override bool TrySetType (TypeNode expectedType, IMetaDataProvider metaDataProvider, out TypeNode resultType)
+               {
+                       if (typeof (T) == typeof (Parameter)) {
+                               var p = (Parameter) (object) this.Element;
+                               TypeNode type = metaDataProvider.ParameterType (p);
+                               this.isManagedPointer = metaDataProvider.IsManagedPointer (type);
+                               ResultType = resultType = metaDataProvider.ManagedPointer (type);
+                               return true;
+                       }
+
+                       if (typeof (T) == typeof (Field)) {
+                               var f = (Field) (object) this.Element;
+                               TypeNode type = metaDataProvider.FieldType (f);
+                               this.isStatic = metaDataProvider.IsStatic (f);
+                               this.isManagedPointer = metaDataProvider.IsManagedPointer (type);
+                               ResultType = resultType = metaDataProvider.ManagedPointer (type);
+
+                               TypeNode declaringType = metaDataProvider.DeclaringType (f);
+                               if (metaDataProvider.IsManagedPointer (expectedType))
+                                       expectedType = metaDataProvider.ElementType (expectedType);
+                               expectedType = metaDataProvider.Unspecialized (expectedType);
+
+                               if (!metaDataProvider.IsStatic (f) && declaringType.Equals (expectedType) &&
+                                   (!metaDataProvider.DerivesFrom (expectedType, declaringType) ||
+                                    !metaDataProvider.IsProtected (f) && !metaDataProvider.IsPublic (f)))
+                                       this.castTo = metaDataProvider.FullName (declaringType);
+
+                               return true;
+                       }
+
+                       if (typeof (T) == typeof (Local)) {
+                               var local = (Local) (object) this.Element;
+                               TypeNode type = metaDataProvider.LocalType (local);
+                               this.isManagedPointer = metaDataProvider.IsManagedPointer (type);
+                               ResultType = resultType = metaDataProvider.ManagedPointer (type);
+
+                               return true;
+                       }
+
+                       if (typeof (T) == typeof (Method)) {
+                               var method = (Method) (object) this.Element;
+                               ResultType = resultType = !IsAddressOf
+                                                               ? metaDataProvider.ReturnType (method)
+                                                               : metaDataProvider.ManagedPointer (metaDataProvider.ReturnType (method));
+
+                               if (metaDataProvider.IsManagedPointer (expectedType))
+                                       expectedType = metaDataProvider.ElementType (expectedType);
+                               expectedType = metaDataProvider.Unspecialized (expectedType);
+
+                               TypeNode declaringType = metaDataProvider.DeclaringType (method);
+                               if (!metaDataProvider.IsStatic (method) && declaringType.Equals (expectedType) &&
+                                   (!metaDataProvider.DerivesFrom (expectedType, declaringType)
+                                    || !metaDataProvider.IsProtected (method) && !metaDataProvider.IsPublic (method)))
+                                       this.castTo = metaDataProvider.FullName (declaringType);
+
+                               return true;
+                       }
+
+                       ResultType = resultType = default(TypeNode);
+                       return false;
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..bd2ecc5
--- /dev/null
@@ -0,0 +1,110 @@
+// 
+// PathExtensions.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       static class PathExtensions {
+               public static HashSet<Field> FieldsIn (this LispList<PathElement> path)
+               {
+                       var result = new HashSet<Field> ();
+                       if (path != null) {
+                               foreach (PathElement element in path.AsEnumerable ()) {
+                                       Field f;
+                                       if (element.TryField (out f))
+                                               result.Add (f);
+                               }
+                       }
+                       return result;
+               }
+
+               public static string ToCodeString (this PathElement[] path)
+               {
+                       return PathToString (path);
+               }
+
+               public static string ToCodeString (this LispList<PathElement> path)
+               {
+                       return PathToString (path.AsEnumerable ());
+               }
+
+               private static string PathToString (IEnumerable<PathElement> path)
+               {
+                       bool first = true;
+                       bool isReference = false;
+                       bool isUnmanagedPointer = false;
+                       var sb = new StringBuilder ();
+
+                       List<PathElement> pathL = path.ToList ();
+
+                       for (int i = 0; i < pathL.Count; i++) {
+                               PathElement element = pathL [i];
+                               if (element.IsMethodCall && !element.IsGetter && element.IsStatic) {
+                                       string oldString = sb.ToString ();
+                                       sb = new StringBuilder ();
+                                       sb.AppendFormat ("{0}({1})", element, oldString);
+                               } else {
+                                       if (!string.IsNullOrEmpty (element.CastTo)) {
+                                               string oldString = sb.ToString ();
+                                               sb = new StringBuilder ();
+                                               sb.AppendFormat ("(({0}{1}){2})", element.CastTo, isUnmanagedPointer ? "*" : "", oldString);
+                                       }
+
+                                       sb.Append (isUnmanagedPointer ? "->" : ".");
+                                       sb.Append (element.ToString ());
+                                       if (element.IsMethodCall && !element.IsGetter)
+                                               sb.Append ("()");
+                               }
+                               if (first)
+                                       first = false;
+
+                               int num = (element.IsAddressOf ? 1 : 0) + (element.IsUnmanagedPointer ? 1 : 0) + (element.IsManagedPointer ? 1 : 0);
+                               isUnmanagedPointer = element.IsUnmanagedPointer;
+
+                               for (int j = 0; j < num; j++) {
+                                       if (j + 1 < pathL.Count) {
+                                               if (pathL [j + 1].IsDeref)
+                                                       ++j;
+                                       } else
+                                               isReference = true;
+                               }
+                       }
+
+                       if (isReference)
+                               return isUnmanagedPointer ? sb.ToString () : "&" + sb;
+                       if (isUnmanagedPointer)
+                               return "*" + sb;
+
+                       return sb.ToString ();
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElement.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElement.cs
new file mode 100644 (file)
index 0000000..0abee38
--- /dev/null
@@ -0,0 +1,103 @@
+// 
+// SpecialPathElement.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
+       class SpecialPathElement : PathElement<SpecialPathElementKind> {
+               private object type;
+
+               public SpecialPathElement (SpecialPathElementKind element, SymFunction c) : base (element, element.ToString (), c)
+               {
+                       this.castTo = "";
+               }
+
+               public override bool IsAddressOf
+               {
+                       get { return false; }
+               }
+
+               public override bool IsDeref
+               {
+                       get { return this.Element == SpecialPathElementKind.Deref; }
+               }
+
+
+               public override bool TryGetResultType (out TypeNode resultType)
+               {
+                       if (this.type is TypeNode) {
+                               resultType = (TypeNode) this.type;
+                               return true;
+                       }
+
+                       resultType = default (TypeNode);
+                       return false;
+               }
+
+               public override bool TrySetType (TypeNode expectedType, IMetaDataProvider metaDataProvider, out TypeNode resultType)
+               {
+                       switch (this.Element) {
+                       case SpecialPathElementKind.Length:
+                               this.castTo = metaDataProvider.IsArray (expectedType)
+                                             || metaDataProvider.System_String.Equals (expectedType)
+                                               ? ""
+                                               : "System.Array";
+                               resultType = metaDataProvider.System_Int32;
+                               return true;
+                       case SpecialPathElementKind.Deref:
+                               if (metaDataProvider.IsManagedPointer (expectedType)) {
+                                       TypeNode type = metaDataProvider.ElementType (expectedType);
+                                       this.type = type;
+                                       resultType = type;
+                                       return true;
+                               }
+                               resultType = default(TypeNode);
+                               return false;
+
+                       default:
+                               resultType = default(TypeNode);
+                               return false;
+                       }
+               }
+
+               public override Result Decode<Data, Result, Visitor, Label> (Label label, Visitor visitor, Data data)
+               {
+                       switch (this.Element) {
+                       case SpecialPathElementKind.Length:
+                               return visitor.LoadLength (label, Dummy.Value, Dummy.Value, data);
+                       case SpecialPathElementKind.Deref:
+                               throw new NotImplementedException ();
+                       default:
+                               throw new InvalidOperationException ();
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElementKind.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElementKind.cs
new file mode 100644 (file)
index 0000000..eb950df
--- /dev/null
@@ -0,0 +1,34 @@
+// 
+// SpecialPathElementKind.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.Analysis.HeapAnalysis.Paths {
+       enum SpecialPathElementKind {
+               Length,
+               Deref
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/AbstractDomainUpdate.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/AbstractDomainUpdate.cs
new file mode 100644 (file)
index 0000000..e3b7237
--- /dev/null
@@ -0,0 +1,87 @@
+// 
+// AbstractDomainUpdate.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class AbstractDomainUpdate<TFunc, TAbstractDomain> : Update<TFunc, TAbstractDomain>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               private readonly SymValue sv;
+
+               public AbstractDomainUpdate (SymValue sv)
+               {
+                       this.sv = sv;
+               }
+
+               #region Overrides of Update
+               public override void Replay (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       if (!merge.IsCommon (this.sv))
+                               return;
+
+                       TAbstractDomain val1 = merge.Graph1 [this.sv];
+                       TAbstractDomain val2 = merge.Graph2 [this.sv];
+                       bool weaker;
+                       TAbstractDomain join = val1.Join (val2, merge.Widen, out weaker);
+
+                       TAbstractDomain wasInResult = merge.Result [this.sv];
+                       if (weaker) {
+                               if (DebugOptions.Debug)
+                               {
+                                       Console.WriteLine ("----SymGraph changed during AbstractDomainUpdate of {3} " +
+                                                          "due to weaker abstractValue join (val1 = {0}, val2 = {1}, wasInResult = {2}",
+                                                          val1, val2, wasInResult, this.sv);
+                               }
+                               merge.Changed = true;
+                       }
+
+                       if (join.Equals (wasInResult))
+                               return;
+
+                       merge.Result [this.sv] = join;
+               }
+
+               public override void ReplayElimination (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       if (!merge.IsCommon (this.sv))
+                               return;
+
+                       TAbstractDomain val1 = merge.Graph1 [this.sv];
+
+                       if (val1.IsTop)
+                               merge.Result [this.sv] = val1;
+                       else {
+                               TAbstractDomain val2 = merge.Graph2 [this.sv];
+                               if (val2.IsTop)
+                                       merge.Result [this.sv] = val2;
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EdgeUpdate.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EdgeUpdate.cs
new file mode 100644 (file)
index 0000000..0b37aed
--- /dev/null
@@ -0,0 +1,97 @@
+// 
+// EdgeUpdate.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class EdgeUpdate<TFunc, TAbstractDomain> : Update<TFunc, TAbstractDomain>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               private readonly SymValue from;
+               private readonly TFunc function;
+
+               public EdgeUpdate (SymValue from, TFunc function)
+               {
+                       this.from = from;
+                       this.function = function;
+               }
+
+               #region Overrides of Update
+               public override void Replay (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       if (!merge.IsCommon (this.from))
+                               return;
+
+                       SymValue sv1 = merge.Graph1.LookupWithoutManifesting (this.from, this.function);
+                       SymValue sv2 = merge.Graph2.LookupWithoutManifesting (this.from, this.function);
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("Replay edge update: {0} -{1} -> [ {2}, {3} ]",
+                                                  this.from, this.function, sv1, sv2);
+                       }
+                       if (sv1 == null) {
+                               if (this.function.KeepAsBottomField && merge.Graph1.HasAllBottomFields (this.from))
+                                       sv1 = merge.Graph1.BottomPlaceHolder;
+                               else {
+                                       if (sv2 == null || merge.Widen || !this.function.ManifestField)
+                                               return;
+                                       if (DebugOptions.Debug)
+                                       {
+                                               Console.WriteLine ("---SymGraph changed due to manifestation of a top edge in Graph1");
+                                       }
+                                       merge.Changed = true;
+                               }
+                       }
+                       if (sv2 == null) {
+                               if (this.function.KeepAsBottomField && merge.Graph2.HasAllBottomFields (this.from))
+                                       sv2 = merge.Graph2.BottomPlaceHolder;
+                               else {
+                                       if (merge.Widen || !this.function.ManifestField)
+                                               return;
+                                       if (DebugOptions.Debug)
+                                       {
+                                               Console.WriteLine ("---SymGraph changed due to manifestation of due to missing target in Graph2");
+                                       }
+                                       merge.Changed = true;
+                                       return;
+                               }
+                       }
+
+                       SymValue r = merge.AddJointEdge (sv1, sv2, this.function, this.from);
+                       if (r == null || r.UniqueId <= merge.LastCommonVariable)
+                               return;
+
+                       merge.JoinSymbolicValue (sv1, sv2, r);
+               }
+
+               public override void ReplayElimination (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EliminateEdgeUpdate.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EliminateEdgeUpdate.cs
new file mode 100644 (file)
index 0000000..cd15e71
--- /dev/null
@@ -0,0 +1,79 @@
+// 
+// EliminateEdgeUpdate.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class EliminateEdgeUpdate<TFunc, TAbstractDomain> : Update<TFunc, TAbstractDomain>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               private readonly SymValue from;
+               private readonly TFunc function;
+
+               public EliminateEdgeUpdate (SymValue sv, TFunc function)
+               {
+                       this.from = sv;
+                       this.function = function;
+               }
+
+               #region Overrides of Update
+               public override void ReplayElimination (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       if (!merge.IsCommon (this.from))
+                               return;
+
+                       merge.Result.Eliminate (this.function, this.from);
+               }
+
+               public override void Replay (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       if (!merge.IsCommon (this.from))
+                               return;
+
+                       SymValue sv1 = merge.Graph1.LookupWithoutManifesting (this.from, this.function);
+                       SymValue sv2 = merge.Graph2.LookupWithoutManifesting (this.from, this.function);
+                       if (sv1 != null && sv2 != null)
+                               return;
+                       if (sv1 != null) {
+                               if (DebugOptions.Debug)
+                               {
+                                       Console.WriteLine ("---SymGraph changed due to EliminateEdgeUpdate {0}-{1} " +
+                                                          "-> that is only in G1", this.from, this.function);
+                               }
+                               merge.Changed = true;
+                       }
+
+                       bool noEdgeInResult = merge.Result.LookupWithoutManifesting (this.from, this.function) == null;
+                       if (noEdgeInResult)
+                               return;
+
+                       merge.Result.Eliminate (this.function, this.from);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityPair.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityPair.cs
new file mode 100644 (file)
index 0000000..60e3486
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// EqualityPair.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       struct EqualityPair<TFunc, TAbstractDomain> : IEquatable<EqualityPair<TFunc, TAbstractDomain>> 
+               where TFunc : IEquatable<TFunc>, IConstantInfo 
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+
+               public readonly SymValue Sv1;
+               public readonly SymValue Sv2;
+
+               public EqualityPair (SymValue v1, SymValue v2)
+               {
+                       this.Sv1 = v1;
+                       this.Sv2 = v2;
+               }
+
+               #region Implementation of IEquatable<SymGraph<Constant,AbstractValue>.EqualityPair>
+               public bool Equals (EqualityPair<TFunc, TAbstractDomain> other)
+               {
+                       return (this.Sv1 == other.Sv1 && this.Sv2 == other.Sv2);
+               }
+               #endregion
+
+               public override bool Equals (object obj)
+               {
+                       if (obj is EqualityPair<TFunc, TAbstractDomain>)
+                               return Equals ((EqualityPair<TFunc, TAbstractDomain>) obj);
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return (this.Sv1 == null ? 1 : this.Sv1.GlobalId) + this.Sv2.GlobalId;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityUpdate.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityUpdate.cs
new file mode 100644 (file)
index 0000000..5da762e
--- /dev/null
@@ -0,0 +1,60 @@
+// 
+// EqualityUpdate.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class EqualityUpdate<TFunc, TAbstractDomain> : Update<TFunc, TAbstractDomain> 
+               where TFunc : IEquatable<TFunc>, IConstantInfo 
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               private readonly SymValue sv1;
+               private readonly SymValue sv2;
+
+               public EqualityUpdate (SymValue sv1, SymValue sv2)
+               {
+                       this.sv1 = sv1;
+                       this.sv2 = sv2;
+               }
+
+               #region Overrides of Update
+               public override void Replay (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       if (!merge.IsCommon (this.sv1) || !merge.IsCommon (this.sv2) || (!merge.Graph1.IsEqual (this.sv1, this.sv2) || merge.Result.IsEqual (this.sv1, this.sv2)))
+                               return;
+                       if (merge.Graph2.IsEqual (this.sv1, this.sv2))
+                               merge.Result.AssumeEqual (this.sv1, this.sv2);
+                       else
+                               merge.Changed = true;
+               }
+
+               public override void ReplayElimination (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+               }
+               #endregion
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..bb0702b
--- /dev/null
@@ -0,0 +1,53 @@
+// 
+// IMergeInfo.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 Mono.CodeContracts.Static.DataStructures;
+
+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; }
+
+               bool IsResultGraph<TFunc, TAbstractDomain> (SymGraph<TFunc, TAbstractDomain> graph)
+                       where TFunc : IEquatable<TFunc>, IConstantInfo
+                       where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain>;
+
+               bool IsGraph1<TFunc, TAbstractDomain> (SymGraph<TFunc, TAbstractDomain> graph)
+                       where TFunc : IEquatable<TFunc>, IConstantInfo
+                       where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain>;
+
+               bool IsGraph2<TFunc, TAbstractDomain> (SymGraph<TFunc, TAbstractDomain> graph)
+                       where TFunc : IEquatable<TFunc>, IConstantInfo
+                       where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain>;
+       }
+}
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
new file mode 100644 (file)
index 0000000..dacf94b
--- /dev/null
@@ -0,0 +1,516 @@
+// 
+// MergeInfo.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.Linq;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Extensions;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class MergeInfo<TFunc, TADomain> : IMergeInfo
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TADomain : IAbstractDomainForEGraph<TADomain>, IEquatable<TADomain> {
+               
+               public readonly SymGraph<TFunc, TADomain> Result;
+               public readonly SymGraph<TFunc, TADomain> Graph1;
+               public readonly SymGraph<TFunc, TADomain> Graph2;
+
+               public readonly int LastCommonVariable;
+               public readonly bool Widen;
+
+               private readonly HashSet<SymValue> manifested;
+               private readonly DoubleDictionary<SymValue, SymValue, int> pending_counts;
+               private readonly HashSet<Tuple<SymValue, SymValue, MultiEdge<TFunc, TADomain>>> visited_multi_edges;
+
+               private DoubleImmutableMap<SymValue, SymValue, SymValue> mappings;
+               private IImmutableSet<SymValue> visited_key1;
+               private LispList<Tuple<SymValue, SymValue, SymValue>> merge_triples;
+
+               public MergeInfo (SymGraph<TFunc, TADomain> result,
+                                 SymGraph<TFunc, TADomain> g1,
+                                 SymGraph<TFunc, TADomain> g2, bool widen)
+               {
+                       this.mappings = DoubleImmutableMap<SymValue, SymValue, SymValue>.Empty (SymValue.GetUniqueKey);
+                       this.visited_key1 = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       this.visited_multi_edges = new HashSet<Tuple<SymValue, SymValue, MultiEdge<TFunc, TADomain>>> ();
+                       this.pending_counts = new DoubleDictionary<SymValue, SymValue, int> ();
+                       this.manifested = new HashSet<SymValue> ();
+                       
+                       this.LastCommonVariable = result.IdGenerator;
+                       this.Widen = widen;
+                       this.Result = result;
+                       this.Graph1 = g1;
+                       this.Graph2 = g2;
+
+                       this.Changed = false;
+               }
+
+               #region IMergeInfo Members
+               public bool Changed { get; set; }
+
+               public IEnumerable<Tuple<SymValue, SymValue, SymValue>> MergeTriples
+               {
+                       get { return this.merge_triples.AsEnumerable (); }
+               }
+
+               public IImmutableMap<SymValue, LispList<SymValue>> ForwardG1Map
+               {
+                       get { return GetForwardGraphMap ((t) => t.Item1); }
+               }
+
+               public IImmutableMap<SymValue, LispList<SymValue>> ForwardG2Map
+               {
+                       get { return GetForwardGraphMap ((t) => t.Item2); }
+               }
+
+               public bool IsResultGraph<TFunc1, TAbstractDomain> (SymGraph<TFunc1, TAbstractDomain> graph)
+                       where TFunc1 : IEquatable<TFunc1>, IConstantInfo
+                       where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain>
+               {
+                       return Equals (graph, this.Result);
+               }
+
+               public bool IsGraph1<TFunc1, TAbstractDomain> (SymGraph<TFunc1, TAbstractDomain> graph)
+                       where TFunc1 : IEquatable<TFunc1>, IConstantInfo
+                       where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain>
+               {
+                       return (Equals (this.Graph1, graph) || Equals (this.Graph1.Parent, graph) && Equals (this.Graph1.Updates, graph.Updates));
+               }
+
+               public bool IsGraph2<TFunc1, TAbstractDomain> (SymGraph<TFunc1, TAbstractDomain> graph)
+                       where TFunc1 : IEquatable<TFunc1>, IConstantInfo
+                       where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain>
+               {
+                       return (Equals (this.Graph2, graph) || Equals (this.Graph2.Parent, graph) && Equals (this.Graph2.Updates, graph.Updates));
+               }
+               #endregion
+
+               public void AddMapping (SymValue v1, SymValue v2, SymValue result)
+               {
+                       if (v1 != null && v2 != null)
+                               this.mappings = this.mappings.Add (v1, v2, result);
+                       else if (v2 == null)
+                               this.visited_key1 = this.visited_key1.Add (v1);
+                       else
+                               this.visited_key1 = this.visited_key1.Add (v2);
+
+                       AddMergeTriple (v1, v2, result);
+               }
+
+               public SymValue AddJointEdge (SymValue v1Target, SymValue v2Target, TFunc function, SymValue resultArg)
+               {
+                       SymValue result = LookupMapping (v1Target, v2Target);
+                       bool newEdge = false;
+                       if (result == null)
+                       {
+                               if (IsMappingAlreadyAdded (v1Target, v2Target))
+                               {
+                                       if (DebugOptions.Debug)
+                                               Console.WriteLine ("---SymGraph changed due to pre-existing mapping in G1 of {0}", v1Target);
+                                       Changed = true;
+                                       if (v1Target == null)
+                                       {
+                                               if (this.manifested.Contains (v2Target))
+                                                       return null;
+                                               this.manifested.Add (v2Target);
+                                       }
+                                       if (v2Target == null)
+                                       {
+                                               if (this.manifested.Contains (v1Target))
+                                                       return null;
+                                               this.manifested.Add (v1Target);
+                                       }
+                               }
+                               newEdge = true;
+                               result = v1Target == null || v1Target.UniqueId > this.LastCommonVariable || v1Target != v2Target ? this.Result.FreshSymbol () : v1Target;
+                               AddMapping (v1Target, v2Target, result);
+                       }
+                       else if (this.Result.LookupWithoutManifesting (resultArg, function) == result)
+                               return null;
+                       this.Result[function, resultArg] = result;
+                       TADomain val1 = Graph1ADomain (v1Target);
+                       TADomain val2 = Graph2ADomain (v2Target);
+
+                       bool weaker;
+                       TADomain join = val1.Join (val2, this.Widen, out weaker);
+                       this.Result[result] = join;
+
+                       if (weaker)
+                       {
+                               if (DebugOptions.Debug)
+                               {
+                                       Console.WriteLine ("----SymGraph changed due to join of abstract values of [{0}, {1}] " +
+                                                          "(prev {2}, new {3}, join {4}", v1Target, v2Target, val1, val2, join);
+                               }
+                               Changed = true;
+                       }
+
+                       return newEdge ? result : null;
+               }
+
+               public SymValue AddJointEdge (SymValue v1Target, SymValue v2Target, TFunc function, SymValue[] resultArgs)
+               {
+                       SymValue result = LookupMapping (v1Target, v2Target);
+                       bool newEdge = false;
+                       if (result == null)
+                       {
+                               if (IsMappingAlreadyAdded (v1Target, v2Target))
+                               {
+                                       if (DebugOptions.Debug)
+                                               Console.WriteLine ("---SymGraph changed due to pre-existing mapping in G1 of {0}", v1Target);
+                                       Changed = true;
+                                       if (v1Target == null || v2Target == null)
+                                               return null;
+                               }
+                               newEdge = true;
+                               result = v1Target == null || v1Target.UniqueId > this.LastCommonVariable || v1Target != v2Target ? this.Result.FreshSymbol () : v1Target;
+                               AddMapping (v1Target, v2Target, result);
+                       }
+                       else if (this.Result.LookupWithoutManifesting (resultArgs, function) == result)
+                               return null;
+                       this.Result[resultArgs, function] = result;
+                       TADomain val1 = Graph1ADomain (v1Target);
+                       TADomain val2 = Graph2ADomain (v2Target);
+
+                       bool weaker;
+                       TADomain joinValue = val1.Join (val2, this.Widen, out weaker);
+
+                       this.Result[result] = joinValue;
+                       if (weaker)
+                       {
+                               if (DebugOptions.Debug)
+                                       Console.WriteLine ("----SymGraph changed due to join of abstract values of [{0}, {1}] (prev {2}, new {3}, join {4}",
+                                                          v1Target, v2Target,
+                                                          val1, val2, joinValue);
+                               Changed = true;
+                       }
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("AddJointEdge: ({0}) -{1} -> [{2},{3},{4}]",
+                                                  resultArgs.ToString (", "), function,
+                                                  v1Target, v2Target, result);
+                       }
+                       return newEdge ? result : null;
+               }
+
+               public bool IsCommon (SymValue sv)
+               {
+                       return sv.UniqueId <= this.LastCommonVariable;
+               }
+
+               public bool AreCommon (SymValue[] svs)
+               {
+                       return svs.All (sv => IsCommon (sv));
+               }
+
+               public void JoinSymbolicValue (SymValue sv1, SymValue sv2, SymValue r)
+               {
+                       if (this.Graph2.HasAllBottomFields (sv2)) {
+                               if (sv1 != null) {
+                                       foreach (TFunc function in this.Graph1.TermMap.Keys2 (sv1)) {
+                                               SymValue v1 = this.Graph1.LookupWithoutManifesting (sv1, function);
+                                               bool isPlaceHolder;
+                                               SymValue v2 = this.Graph2.LookupOrBottomPlaceHolder (sv2, function, out isPlaceHolder);
+                                               if (!isPlaceHolder || function.KeepAsBottomField) {
+                                                       SymValue r1 = AddJointEdge (v1, v2, function, r);
+                                                       if (r1 != null)
+                                                               JoinSymbolicValue (v1, v2, r1);
+                                               }
+                                       }
+                               }
+                       } else if (!this.Widen && this.Graph1.HasAllBottomFields (sv1)) {
+                               if (DebugOptions.Debug)
+                                       Console.WriteLine ("---SymGraph changed due to an all bottom field value in G1 changing to non-bottom");
+                               Changed = true;
+                               if (sv2 != null) {
+                                       foreach (TFunc function in this.Graph2.TermMap.Keys2 (sv2)) {
+                                               bool isPlaceHolder;
+                                               SymValue v1 = this.Graph1.LookupOrBottomPlaceHolder (sv1, function, out isPlaceHolder);
+                                               SymValue v2 = this.Graph2.LookupWithoutManifesting (sv2, function);
+                                               if (!isPlaceHolder || function.KeepAsBottomField) {
+                                                       SymValue r1 = AddJointEdge (v1, v2, function, r);
+                                                       if (r1 != null)
+                                                               JoinSymbolicValue (v1, v2, r1);
+                                               }
+                                       }
+                               }
+                       } else {
+                               IEnumerable<TFunc> functions;
+                               if (this.Widen) {
+                                       if (this.Graph1.TermMap.Keys2Count (sv1) <= this.Graph2.TermMap.Keys2Count (sv2))
+                                               functions = this.Graph1.TermMap.Keys2 (sv1);
+                                       else {
+                                               functions = this.Graph2.TermMap.Keys2 (sv2);
+                                               if (DebugOptions.Debug)
+                                                       Console.WriteLine ("---SymGraph changed because G2 has fewer keys for {0} than {1} in G1", sv2, sv1);
+                                               Changed = true;
+                                       }
+                               } else {
+                                       if (this.Graph1.TermMap.Keys2Count (sv1) < this.Graph2.TermMap.Keys2Count (sv2)) {
+                                               functions = this.Graph2.TermMap.Keys2 (sv2);
+                                               if (DebugOptions.Debug)
+                                                       Console.WriteLine ("---SymGraph changed because G1 has fewer keys for {0} than {1} in G2", sv1, sv2);
+                                               Changed = true;
+                                       } else
+                                               functions = this.Graph1.TermMap.Keys2 (sv1);
+                               }
+
+                               foreach (TFunc function in functions) {
+                                       SymValue v1 = this.Graph1.LookupWithoutManifesting (sv1, function);
+                                       SymValue v2 = this.Graph2.LookupWithoutManifesting (sv2, function);
+
+                                       if (v1 == null) {
+                                               if (!this.Widen && function.ManifestField) {
+                                                       if (DebugOptions.Debug)
+                                                               Console.WriteLine ("---SymGraph changed due to manifestation of a top edge in G1");
+                                                       Changed = true;
+
+                                               } else
+                                                       continue;
+                                       }
+                                       if (v2 == null && (this.Widen || !function.ManifestField)) {
+                                               if (DebugOptions.Debug)
+                                                       Console.WriteLine ("---SymGraph changed due to absence of map {0}-{1} -> in G2", sv2, function);
+                                               Changed = true;
+                                       }
+
+                                       if (v1 != null && v2 != null)
+                                       {
+                                               //we have to joint ends of edges
+                                               SymValue r1 = AddJointEdge (v1, v2, function, r);
+                                               if (r1 != null)
+                                                       JoinSymbolicValue (v1, v2, r1);
+                                       }
+                               }
+                       }
+
+                       JoinMultiEdges (sv1, sv2);
+               }
+
+               public void JoinMultiEdge (SymValue sv1, SymValue sv2, MultiEdge<TFunc, TADomain> edge)
+               {
+                       var key = new Tuple<SymValue, SymValue, MultiEdge<TFunc, TADomain>> (sv1, sv2, edge);
+                       if (!this.visited_multi_edges.Add (key))
+                               return;
+
+                       LispList<SymValue> list1 = this.Graph1.MultiEdgeMap [sv1, edge];
+                       LispList<SymValue> list2 = this.Graph2.MultiEdgeMap [sv2, edge];
+                       if (list2.IsEmpty ())
+                               return;
+                       foreach (SymValue v1 in list1.AsEnumerable ()) {
+                               foreach (SymValue v2 in list2.AsEnumerable ()) {
+                                       if (UpdatePendingCount (v1, v2, edge.Arity)) {
+                                               SymGraphTerm<TFunc> term1 = this.Graph1.EqualMultiTermsMap [v1];
+                                               SymGraphTerm<TFunc> term2 = this.Graph2.EqualMultiTermsMap [v2];
+                                               if (term1.Args != null && term2.Args != null) {
+                                                       var resultRoots = new SymValue[term1.Args.Length];
+                                                       for (int i = 0; i < resultRoots.Length; i++)
+                                                               resultRoots [i] = this.mappings [term1.Args [i], term2.Args [i]];
+                                                       SymValue r = AddJointEdge (v1, v2, edge.Function, resultRoots);
+                                                       if (r != null)
+                                                               JoinSymbolicValue (sv1, sv2, r);
+                                               } else
+                                                       break;
+                                       }
+                               }
+                       }
+               }
+
+               public void Replay (SymGraph<TFunc, TADomain> common)
+               {
+                       PrimeMapWithCommon ();
+                       Replay (this.Graph1.Updates, common.Updates);
+                       Replay (this.Graph2.Updates, common.Updates);
+               }
+
+               public void ReplayEliminations (SymGraph<TFunc, TADomain> common)
+               {
+                       ReplayEliminations (this.Graph1.Updates, common.Updates);
+                       ReplayEliminations (this.Graph2.Updates, common.Updates);
+               }
+
+               public void Commit ()
+               {
+                       if (Changed)
+                               return;
+
+                       bool needContinue = false;
+                       foreach (var edge in this.Graph1.ValidMultiTerms)
+                       {
+                               SymGraphTerm<TFunc> term = edge.Value;
+                               var args = new SymValue[term.Args.Length];
+
+                               for (int i = 0; i < args.Length; ++i)
+                               {
+                                       SymValue sv = term.Args[i];
+                                       if (IsMappingAlreadyAdded (sv, null))
+                                       {
+                                               if (this.mappings.Keys2 (sv) != null && this.mappings.Keys2 (sv).Count () == 1)
+                                                       args[i] = this.mappings[sv, this.mappings.Keys2 (sv).First ()];
+                                       }
+                                       else
+                                       {
+                                               needContinue = true;
+                                               break;
+                                       }
+
+                                       if (args[i] == null)
+                                       {
+                                               Changed = true;
+                                               return;
+                                       }
+                               }
+
+                               if (needContinue)
+                                       continue;
+
+                               SymValue symbol = this.Result.LookupWithoutManifesting (args, term.Function);
+                               if (symbol != null)
+                               {
+                                       SymValue key = edge.Key;
+                                       if (this.mappings.Keys2 (key) != null && this.mappings.Keys2 (key).Count () == 1 && this.mappings[key, this.mappings.Keys2 (key).First ()] == symbol)
+                                               continue;
+                               }
+
+                               Changed = true;
+                               return;
+                       }
+               }
+
+               private IImmutableMap<SymValue, LispList<SymValue>> GetForwardGraphMap (Func<Tuple<SymValue, SymValue, SymValue>, SymValue> sourceSelector)
+               {
+                       IImmutableMap<SymValue, LispList<SymValue>> res = ImmutableIntKeyMap<SymValue, LispList<SymValue>>.Empty (SymValue.GetUniqueKey);
+                       foreach (var tuple in this.merge_triples.AsEnumerable ()) {
+                               SymValue sv = sourceSelector (tuple);
+                               if (sv != null)
+                                       res = res.Add (sv, res [sv].Cons (tuple.Item3));
+                       }
+                       return res;
+               }
+
+               private bool UpdatePendingCount (SymValue xi, SymValue yi, int arity)
+               {
+                       int result;
+                       this.pending_counts.TryGetValue (xi, yi, out result);
+                       result = result + 1;
+
+                       this.pending_counts [xi, yi] = result;
+                       if (result == arity)
+                               return true;
+
+                       return false;
+               }
+
+               private void JoinMultiEdges (SymValue sv1, SymValue sv2)
+               {
+                       if (sv1 == null || sv2 == null)
+                               return;
+
+                       IEnumerable<MultiEdge<TFunc, TADomain>> edges =
+                               this.Graph1.MultiEdgeMap.Keys2Count (sv1) > this.Graph2.MultiEdgeMap.Keys2Count (sv2)
+                                       ? this.Graph2.MultiEdgeMap.Keys2 (sv2)
+                                       : this.Graph1.MultiEdgeMap.Keys2 (sv1);
+                       foreach (var edge in edges)
+                               JoinMultiEdge (sv1, sv2, edge);
+               }
+
+               private TADomain Graph1ADomain (SymValue sv)
+               {
+                       if (sv != null)
+                               return this.Graph1 [sv];
+                       return this.Graph1.UnderlyingTopValue.ForManifestedField ();
+               }
+
+               private TADomain Graph2ADomain (SymValue sv)
+               {
+                       if (sv != null)
+                               return this.Graph2 [sv];
+                       return this.Graph2.UnderlyingTopValue.ForManifestedField ();
+               }
+
+               private void AddMergeTriple (SymValue v1, SymValue v2, SymValue result)
+               {
+                       this.merge_triples = this.merge_triples.Cons (new Tuple<SymValue, SymValue, SymValue> (v1, v2, result));
+               }
+
+               private bool IsMappingAlreadyAdded (SymValue v1, SymValue v2)
+               {
+                       if (v1 != null)
+                               return this.visited_key1.Contains (v1) || this.mappings.ContainsKey1 (v1);
+                       
+                       return this.visited_key1.Contains (v2);
+               }
+
+               private SymValue LookupMapping (SymValue v1, SymValue v2)
+               {
+                       if (v1 == null || v2 == null)
+                               return null;
+
+                       return this.mappings [v1, v2];
+               }
+
+               private void PrimeMapWithCommon ()
+               {
+                       LispList<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))
+                                               rest = rest.Cons (sv);
+                                       AddMapping (sv, sv, sv);
+                               }
+                       }
+                       foreach (SymValue sv in this.Graph1.EqualMultiTermsMap.Keys) {
+                               if (IsCommon (sv) && (this.Graph2.EqualTermsMap.ContainsKey (sv) || this.Graph2.EqualMultiTermsMap.ContainsKey (sv)) && this.mappings [sv, sv] == null) {
+                                       if (this.Graph1.MultiEdgeMap.ContainsKey1 (sv))
+                                               rest = rest.Cons (sv);
+                                       AddMapping (sv, sv, sv);
+                               }
+                       }
+                       while (rest != null) {
+                               SymValue sv = rest.Head;
+                               rest = rest.Tail;
+                               foreach (var edge in this.Graph1.MultiEdgeMap.Keys2 (sv))
+                                       JoinMultiEdge (sv, sv, edge);
+                       }
+               }
+
+               private void Replay (LispList<Update<TFunc, TADomain>> updates, LispList<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)
+               {
+                       for (Update<TFunc, TADomain> update = Update<TFunc, TADomain>.Reverse (updates, common); update != null; update = update.Next)
+                               update.ReplayElimination (this);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdge.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdge.cs
new file mode 100644 (file)
index 0000000..c8483d4
--- /dev/null
@@ -0,0 +1,71 @@
+// 
+// MultiEdge.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       struct MultiEdge<TFunc, TAbstractDomain> : IEquatable<MultiEdge<TFunc, TAbstractDomain>> 
+               where TFunc : IEquatable<TFunc>, IConstantInfo 
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               
+               public readonly int Arity;
+               public readonly int Index;
+               public readonly TFunc Function;
+
+               public MultiEdge (TFunc function, int index, int arity)
+               {
+                       this.Function = function;
+                       this.Index = index;
+                       this.Arity = arity;
+               }
+
+               #region Implementation of IEquatable<MultiEdge>
+               public bool Equals (MultiEdge<TFunc, TAbstractDomain> other)
+               {
+                       return (this.Index == other.Index && this.Arity == other.Arity && this.Function.Equals (other.Function));
+               }
+               #endregion
+
+               public override bool Equals (object obj)
+               {
+                       if (obj is MultiEdge<TFunc, TAbstractDomain>)
+                               return Equals ((MultiEdge<TFunc, TAbstractDomain>) obj);
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return this.Arity*13 + this.Index;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("[{0}:{1}]", this.Function, this.Index);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdgeUpdate.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdgeUpdate.cs
new file mode 100644 (file)
index 0000000..00c748b
--- /dev/null
@@ -0,0 +1,60 @@
+// 
+// MultiEdgeUpdate.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class MultiEdgeUpdate<TFunc, TAbstractDomain> : Update<TFunc, TAbstractDomain>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               private readonly SymValue[] from;
+               private readonly TFunc function;
+
+               public MultiEdgeUpdate (SymValue[] from, TFunc function)
+               {
+                       this.function = function;
+                       this.from = from;
+               }
+
+               #region Overrides of Update
+               public override void Replay (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+                       int len = this.from.Length;
+                       for (int i = 0; i < len; i++) {
+                               SymValue sv = this.from [i];
+                               if (merge.IsCommon (sv))
+                                       merge.JoinMultiEdge (sv, sv, new MultiEdge<TFunc, TAbstractDomain> (this.function, i, len));
+                       }
+               }
+
+               public override void ReplayElimination (MergeInfo<TFunc, TAbstractDomain> merge)
+               {
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..6f6bd38
--- /dev/null
@@ -0,0 +1,908 @@
+// 
+// SymGraph.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.IO;
+using System.Linq;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Extensions;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       class SymGraph<TFunc, TADomain> : ISymGraph<TFunc, TADomain, SymGraph<TFunc, TADomain>>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TADomain : IAbstractDomainForEGraph<TADomain>, IEquatable<TADomain> {
+               public const bool DoIncrementalJoin = false;
+               private static int egraphIdGenerator;
+               private static SymGraph<TFunc, TADomain> BottomValue;
+               public readonly SymValue BottomPlaceHolder;
+               public readonly SymGraph<TFunc, TADomain> Parent;
+               public readonly TADomain UnderlyingTopValue;
+
+               private readonly SymValue const_root;
+               private readonly int egraph_id;
+               private readonly int history_size;
+
+               private readonly SymGraph<TFunc, TADomain> root_graph;
+
+               private readonly TADomain underlying_bottom_value;
+               private IImmutableMap<SymValue, TADomain> abs_map;
+               private IImmutableMap<SymValue, SymValue> forw_map;
+               private bool is_immutable;
+
+               public SymGraph (TADomain topValue, TADomain bottomValue)
+                       : this (topValue, bottomValue, false)
+               {
+                       if (BottomValue != null)
+                               return;
+                       BottomValue = new SymGraph<TFunc, TADomain> (topValue, bottomValue, false);
+               }
+
+               private SymGraph (TADomain topValue, TADomain bottomValue, bool _)
+               {
+                       this.egraph_id = egraphIdGenerator++;
+                       this.const_root = FreshSymbol ();
+
+                       TermMap = DoubleImmutableMap<SymValue, TFunc, SymValue>.Empty (SymValue.GetUniqueKey);
+                       MultiEdgeMap = DoubleImmutableMap<SymValue, MultiEdge<TFunc, TADomain>, LispList<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);
+                       EqualMultiTermsMap = ImmutableIntKeyMap<SymValue, SymGraphTerm<TFunc>>.Empty (SymValue.GetUniqueKey);
+
+                       this.BottomPlaceHolder = FreshSymbol ();
+                       this.abs_map = this.abs_map.Add (this.BottomPlaceHolder, bottomValue);
+                       this.is_immutable = false;
+                       this.history_size = 1;
+                       this.Parent = null;
+                       this.root_graph = this;
+                       Updates = null;
+                       this.UnderlyingTopValue = topValue;
+                       this.underlying_bottom_value = bottomValue;
+               }
+
+               private SymGraph (SymGraph<TFunc, TADomain> from)
+               {
+                       this.egraph_id = egraphIdGenerator++;
+                       this.const_root = from.const_root;
+                       this.BottomPlaceHolder = from.BottomPlaceHolder;
+                       TermMap = from.TermMap;
+                       MultiEdgeMap = from.MultiEdgeMap;
+                       IdGenerator = from.IdGenerator;
+                       this.abs_map = from.abs_map;
+                       this.forw_map = from.forw_map;
+                       EqualTermsMap = from.EqualTermsMap;
+                       EqualMultiTermsMap = from.EqualMultiTermsMap;
+                       this.UnderlyingTopValue = from.UnderlyingTopValue;
+                       this.underlying_bottom_value = from.underlying_bottom_value;
+                       Updates = from.Updates;
+                       this.Parent = from;
+                       this.root_graph = from.root_graph;
+                       this.history_size = from.history_size + 1;
+
+                       from.MarkAsImmutable ();
+               }
+
+               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 DoubleImmutableMap<SymValue, TFunc, SymValue> TermMap { get; private set; }
+               public int IdGenerator { get; private set; }
+               public LispList<Update<TFunc, TADomain>> Updates { get; private set; }
+
+               public bool IsImmutable
+               {
+                       get { return this.is_immutable; }
+               }
+
+               private int LastSymbolId
+               {
+                       get { return IdGenerator; }
+               }
+
+               public SymValue this [SymValue[] args, TFunc function]
+               {
+                       get
+                       {
+                               int len = args.Length;
+                               for (int i = 0; i < len; i++)
+                                       args [i] = Find (args [i]);
+
+                               SymValue candidate = FindCandidate (args, function);
+                               if (candidate != null)
+                                       return candidate;
+                               candidate = FreshSymbol ();
+                               for (int i = 0; i < len; i++) {
+                                       var edge = new MultiEdge<TFunc, TADomain> (function, i, len);
+                                       MultiEdgeMap = MultiEdgeMap.Add (args [i], edge, MultiEdgeMap [args [i], edge].Cons (candidate));
+                               }
+                               EqualMultiTermsMap = EqualMultiTermsMap.Add (candidate, new SymGraphTerm<TFunc> (function, args));
+                               AddMultiEdgeUpdate (args, function);
+                               return candidate;
+                       }
+                       set
+                       {
+                               int len = args.Length;
+                               for (int i = 0; i < len; i++)
+                                       args [i] = Find (args [i]);
+
+                               bool isTermEqual = true;
+                               SymGraphTerm<TFunc> term = EqualMultiTermsMap [value];
+                               if (term.Args != null) {
+                                       for (int i = 0; i < len; i++) {
+                                               if (term.Args [i] != args [i]) {
+                                                       isTermEqual = false;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               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))
+                                               isTermEqual = false;
+                                       if (!isTermEqual)
+                                               MultiEdgeMap = MultiEdgeMap.Add (args [i], edge, list.Cons (value));
+                               }
+                               if (isTermEqual)
+                                       return;
+                               EqualMultiTermsMap = EqualMultiTermsMap.Add (value, new SymGraphTerm<TFunc> (function, args));
+                               AddMultiEdgeUpdate (args, function);
+                       }
+               }
+
+               public SymValue this [TFunc function, params SymValue[] args]
+               {
+                       get { return this [args, function]; }
+               }
+
+               private SymValue this [SymValue source, TFunc function]
+               {
+                       get
+                       {
+                               source = Find (source);
+                               SymValue sv = TermMap [source, function];
+                               SymValue key;
+                               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));
+                                       AddEdgeUpdate (source, function);
+                               } else
+                                       key = Find (sv);
+
+                               return key;
+                       }
+                       set
+                       {
+                               source = Find (source);
+                               value = Find (value);
+
+                               TermMap = TermMap.Add (source, function, value);
+                               LispList<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)));
+
+                               AddEdgeUpdate (source, function);
+                       }
+               }
+
+               public IEnumerable<Pair<SymValue, SymGraphTerm<TFunc>>> ValidMultiTerms {
+                       get
+                       {
+                               foreach (SymValue sv in EqualMultiTermsMap.Keys) {
+                                       SymGraphTerm<TFunc> term = EqualMultiTermsMap [sv];
+                                       if (IsValidMultiTerm (term))
+                                               yield return new Pair<SymValue, SymGraphTerm<TFunc>> (sv, term);
+                               }
+                       }
+               }
+
+               public SymValue ConstRoot
+               {
+                       get { return this.const_root; }
+               }
+
+               #region ISymGraph<TFunc,TADomain,SymGraph<TFunc,TADomain>> Members
+               public TADomain this [SymValue symbol]
+               {
+                       get
+                       {
+                               symbol = Find (symbol);
+                               if (this.abs_map.ContainsKey (symbol))
+                                       return this.abs_map [symbol];
+
+                               return this.UnderlyingTopValue;
+                       }
+                       set
+                       {
+                               SymValue newSym = Find (symbol);
+                               if (this [symbol].Equals (value))
+                                       return;
+                               AddAbstractValueUpdate (newSym);
+                               if (value.IsTop)
+                                       this.abs_map = this.abs_map.Remove (newSym);
+                               else
+                                       this.abs_map = this.abs_map.Add (newSym, value);
+                       }
+               }
+
+               public SymValue this [TFunc function]
+               {
+                       get { return this [this.const_root, function]; }
+                       set { this [this.const_root, function] = value; }
+               }
+
+               public SymValue this [TFunc function, SymValue arg]
+               {
+                       get { return this [arg, function]; }
+                       set { this [arg, function] = value; }
+               }
+
+               public IEnumerable<TFunc> Constants
+               {
+                       get { return TermMap.Keys2 (this.const_root); }
+               }
+
+               public IEnumerable<SymValue> Variables
+               {
+                       get { return TermMap.Keys1; }
+               }
+
+               public SymGraph<TFunc, TADomain> Top
+               {
+                       get { return new SymGraph<TFunc, TADomain> (this.UnderlyingTopValue, this.underlying_bottom_value); }
+               }
+
+               public SymGraph<TFunc, TADomain> Bottom
+               {
+                       get
+                       {
+                               if (BottomValue == null) {
+                                       BottomValue = new SymGraph<TFunc, TADomain> (this.UnderlyingTopValue, this.underlying_bottom_value);
+                                       BottomValue.MarkAsImmutable ();
+                               }
+                               return BottomValue;
+                       }
+               }
+
+               public bool IsTop
+               {
+                       get { return TermMap.Keys2Count (this.const_root) == 0; }
+               }
+
+               public bool IsBottom
+               {
+                       get { return this == BottomValue; }
+               }
+
+               public SymValue FreshSymbol ()
+               {
+                       return new SymValue (++IdGenerator);
+               }
+
+               public SymValue TryLookup (TFunc function)
+               {
+                       return LookupWithoutManifesting (this.const_root, function);
+               }
+
+               public SymValue TryLookup (TFunc function, SymValue arg)
+               {
+                       return LookupWithoutManifesting (arg, function);
+               }
+
+               public void Eliminate (TFunc function, SymValue arg)
+               {
+                       SymValue value = Find (arg);
+                       DoubleImmutableMap<SymValue, TFunc, SymValue> newTermMap = TermMap.Remove (value, function);
+                       if (newTermMap == TermMap)
+                               return;
+                       TermMap = newTermMap;
+                       AddEliminateEdgeUpdate (value, function);
+               }
+
+               public void Eliminate (TFunc function)
+               {
+                       TermMap = TermMap.Remove (this.const_root, function);
+                       AddEliminateEdgeUpdate (this.const_root, function);
+               }
+
+               public void EliminateAll (SymValue arg)
+               {
+                       SymValue value = Find (arg);
+                       AddEliminateAllUpdate (value);
+                       TermMap = TermMap.RemoveAll (value);
+                       this [arg] = this.UnderlyingTopValue;
+               }
+
+               public void AssumeEqual (SymValue v1, SymValue v2)
+               {
+                       var workList = new WorkList<EqualityPair<TFunc, TADomain>> ();
+                       SymValue sv1 = Find (v1);
+                       SymValue sv2 = Find (v2);
+
+                       if (TryPushEquality (workList, sv1, sv2))
+                               AddEqualityUpdate (sv1, sv2);
+
+                       DrainEqualityWorkList (workList);
+               }
+
+               public bool IsEqual (SymValue v1, SymValue v2)
+               {
+                       return Find (v1) == Find (v2);
+               }
+
+               public IEnumerable<TFunc> Functions (SymValue sv)
+               {
+                       return TermMap.Keys2 (Find (sv));
+               }
+
+               public IEnumerable<SymGraphTerm<TFunc>> EqTerms (SymValue sv)
+               {
+                       foreach (var term in EqualTermsMap [Find (sv)].AsEnumerable ()) {
+                               if (TryLookup (term.Function, term.Args) == sv)
+                                       yield return term;
+                       }
+               }
+
+               public SymGraph<TFunc, TADomain> Clone ()
+               {
+                       return new SymGraph<TFunc, TADomain> (this);
+               }
+
+               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);
+                       weaker = info.Changed;
+                       return join;
+               }
+
+               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 doingIncrementalJoin = hasCommonTail & commonTail != egraph.root_graph & !widen & DoIncrementalJoin;
+
+                       //debug
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("SymGraph {0}", widen ? "widen" : "join");
+                               if (commonTail != null)
+                                       Console.WriteLine ("Last common symbol: {0}", commonTail.LastSymbolId);
+
+                               Console.WriteLine ("  Doing {0}", doingIncrementalJoin ? "incremental join" : "full join");
+                       }
+
+                       SymGraph<TFunc, TADomain> result;
+                       MergeInfo<TFunc, TADomain> mergeState;
+                       if (doingIncrementalJoin) {
+                               result = new SymGraph<TFunc, TADomain> (commonTail);
+                               mergeState = new MergeInfo<TFunc, TADomain> (result, egraph, that, widen);
+                               mergeState.Replay (commonTail);
+                               mergeState.Commit ();
+                       } else {
+                               result = new SymGraph<TFunc, TADomain> (commonTail);
+                               mergeState = new MergeInfo<TFunc, TADomain> (result, egraph, that, widen);
+                               mergeState.ReplayEliminations (commonTail);
+                               mergeState.AddMapping (egraph.const_root, that.const_root, result.const_root);
+                               mergeState.JoinSymbolicValue (egraph.const_root, that.const_root, result.const_root);
+                               mergeState.Commit ();
+                       }
+                       mergeInfo = mergeState;
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("  Result update size {0}", result.Updates.Length ());
+                               Console.WriteLine ("Done with Egraph join: changed = {0}", mergeInfo.Changed ? 1 : 0);
+                       }
+
+                       return result;
+               }
+
+               public void Dump (TextWriter tw)
+               {
+                       var set = new HashSet<SymValue> ();
+                       var workList = new WorkList<SymValue> ();
+                       IImmutableMap<SymValue, int> triggers = ImmutableIntKeyMap<SymValue, int>.Empty (SymValue.GetUniqueKey);
+                       tw.WriteLine ("EGraphId: {0}", this.egraph_id);
+                       tw.WriteLine ("LastSymbolId: {0}", LastSymbolId);
+
+                       foreach (TFunc function in TermMap.Keys2 (this.const_root)) {
+                               SymValue sv = this [this.const_root, function];
+                               tw.WriteLine ("{0} = {1}", function, sv);
+                               workList.Add (sv);
+                       }
+
+                       while (!workList.IsEmpty ()) {
+                               SymValue sv = workList.Pull ();
+                               if (!set.Add (sv))
+                                       continue;
+
+                               foreach (TFunc function in TermMap.Keys2 (sv)) {
+                                       SymValue target = this [sv, function];
+
+                                       tw.WriteLine ("{0}({2}) = {1})", function, target, sv);
+                                       workList.Add (target);
+                               }
+                               foreach (var edge in MultiEdgeMap.Keys2 (sv)) {
+                                       foreach (SymValue target in MultiEdgeMap [sv, edge].AsEnumerable ()) {
+                                               if (!UpdateTrigger (target, edge, ref triggers))
+                                                       continue;
+                                               SymGraphTerm<TFunc> term = EqualMultiTermsMap [target];
+                                               if (term.Args != null) {
+                                                       tw.WriteLine ("{0}({1}) = {2}",
+                                                                     term.Function,
+                                                                     term.Args.ToString (", "), target);
+                                                       workList.Add (target);
+                                               }
+                                       }
+                               }
+                       }
+
+                       tw.WriteLine ("**Abstract value map");
+                       foreach (SymValue sv in set) {
+                               TADomain abstractValue = this [sv];
+                               if (!abstractValue.IsTop)
+                                       tw.WriteLine ("{0} -> {1}", sv, abstractValue);
+                       }
+               }
+               #endregion
+
+               #region Implementation of IAbstractDomain<SymGraph<Constant,AbstractValue>>
+               public SymGraph<TFunc, TADomain> Meet (SymGraph<TFunc, TADomain> that)
+               {
+                       if (this == that || IsBottom || that.IsTop)
+                               return this;
+                       if (that.IsBottom || IsTop)
+                               return that;
+
+                       return this;
+               }
+
+               public bool LessEqual (SymGraph<TFunc, TADomain> that)
+               {
+                       IImmutableMap<SymValue, LispList<SymValue>> forwardMap;
+                       IImmutableMap<SymValue, SymValue> backwardMap;
+
+                       return LessEqual (that, out forwardMap, out backwardMap);
+               }
+
+               public SymGraph<TFunc, TADomain> ImmutableVersion ()
+               {
+                       MarkAsImmutable ();
+                       return this;
+               }
+
+               public bool LessEqual (SymGraph<TFunc, TADomain> that, 
+                       out IImmutableMap<SymValue, LispList<SymValue>> forward, 
+                       out IImmutableMap<SymValue, SymValue> backward)
+               {
+                       if (!IsSameEGraph (that))
+                               return InternalLessEqual (this, that, out forward, out backward);
+
+                       forward = null;
+                       backward = null;
+                       return true;
+               }
+               #endregion
+
+               public bool HasAllBottomFields (SymValue sv)
+               {
+                       if (sv == null)
+                               return false;
+
+                       return this [sv].HasAllBottomFields;
+               }
+
+               public SymValue LookupOrManifest (TFunc function, SymValue arg, out bool fresh)
+               {
+                       int oldCnt = IdGenerator;
+                       SymValue result = this [function, arg];
+
+                       fresh = oldCnt < IdGenerator;
+                       return result;
+               }
+
+               public SymValue TryLookup (TFunc function, params SymValue[] args)
+               {
+                       if (args.Length == 0 || args.Length == 1)
+                               return LookupWithoutManifesting (this.const_root, function);
+                       return LookupWithoutManifesting (args, function);
+               }
+
+               public SymValue LookupWithoutManifesting (SymValue sv, TFunc function)
+               {
+                       if (sv == null)
+                               return null;
+                       sv = Find (sv);
+                       SymValue result = TermMap [sv, function];
+
+                       if (result == null)
+                               return null;
+                       return Find (result);
+               }
+
+               public SymValue LookupWithoutManifesting (SymValue[] args, TFunc function)
+               {
+                       int length = args.Length;
+                       for (int i = 0; i < length; i++)
+                               args [i] = Find (args [i]);
+                       return FindCandidate (args, function);
+               }
+
+               public SymValue LookupOrBottomPlaceHolder (SymValue arg, TFunc function, out bool isPlaceHolder)
+               {
+                       SymValue result = LookupWithoutManifesting (arg, function);
+
+                       isPlaceHolder = result == null;
+                       return isPlaceHolder ? this.BottomPlaceHolder : result;
+               }
+
+               private SymValue Find (SymValue v)
+               {
+                       SymValue forw = this.forw_map [v];
+                       if (forw == null)
+                               return v;
+
+                       return Find (forw);
+               }
+
+               private bool IsOldSymbol (SymValue sv)
+               {
+                       if (this.Parent == null)
+                               return false;
+                       return sv.UniqueId <= this.Parent.LastSymbolId;
+               }
+
+               private SymValue FindCandidate (SymValue[] args, TFunc function)
+               {
+                       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) {
+                               SymGraphTerm<TFunc> term = EqualMultiTermsMap [list.Head];
+                               if (term.Args.Length == length) {
+                                       bool found = true;
+
+                                       for (int i = 0; i < length; ++i) {
+                                               if (Find (term.Args [i]) != args [i]) {
+                                                       found = false;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (found)
+                                               return list.Head;
+                               }
+                       }
+                       return null;
+               }
+
+               private bool TryPushEquality (WorkList<EqualityPair<TFunc, TADomain>> workList, SymValue sv1, SymValue sv2)
+               {
+                       if (sv1 != sv2) {
+                               workList.Add (new EqualityPair<TFunc, TADomain> (sv1, sv2));
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               private void DrainEqualityWorkList (WorkList<EqualityPair<TFunc, TADomain>> workList)
+               {
+                       while (!workList.IsEmpty ()) {
+                               EqualityPair<TFunc, TADomain> equalityPair = workList.Pull ();
+                               SymValue sv1 = Find (equalityPair.Sv1);
+                               SymValue sv2 = Find (equalityPair.Sv2);
+                               if (sv1 != sv2) {
+                                       if (sv1.UniqueId < sv2.UniqueId) {
+                                               SymValue tmp = sv1;
+                                               sv1 = sv2;
+                                               sv2 = tmp;
+                                       }
+
+                                       foreach (TFunc function in Functions (sv1)) {
+                                               SymValue v2 = LookupWithoutManifesting (sv2, function);
+                                               if (v2 == null)
+                                                       this [sv2, function] = this [sv1, function];
+                                               else
+                                                       TryPushEquality (workList, this [sv1, function], v2);
+                                       }
+                                       TADomain thisValue = this [sv1];
+                                       TADomain thatValue = this [sv2];
+                                       foreach (var elem in EqualTermsMap [sv1].AsEnumerable ())
+                                               EqualTermsMap = EqualTermsMap.Add (sv2, EqualTermsMap [sv2].Cons (elem));
+
+                                       this.forw_map = this.forw_map.Add (sv1, sv2);
+                                       this [sv2] = thisValue.Meet (thatValue);
+                               }
+                       }
+               }
+
+               private IEnumerable<MultiEdge<TFunc, TADomain>> MultiEdges (SymValue sv)
+               {
+                       return MultiEdgeMap.Keys2 (Find (sv));
+               }
+
+               public IEnumerable<SymGraphTerm<TFunc>> EqMultiTerms (SymValue sv)
+               {
+                       SymGraphTerm<TFunc> term = EqualMultiTermsMap [sv];
+                       if (term.Args != null && IsValidMultiTerm (term))
+                               yield return term;
+               }
+
+               public bool IsValidSymbol (SymValue sv)
+               {
+                       return EqualTermsMap.ContainsKey (sv);
+               }
+
+               private bool IsValidMultiTerm (SymGraphTerm<TFunc> term)
+               {
+                       return LookupWithoutManifesting (term.Args, term.Function) != null;
+               }
+
+               private static SymGraph<TFunc, TADomain> ComputeCommonTail (SymGraph<TFunc, TADomain> g1, SymGraph<TFunc, TADomain> g2, out int updateSize)
+               {
+                       SymGraph<TFunc, TADomain> graph1 = g1;
+                       SymGraph<TFunc, TADomain> graph2 = g2;
+                       while (graph1 != graph2) {
+                               if (graph1 == null)
+                                       break;
+                               if (graph2 == null) {
+                                       graph1 = null;
+                                       break;
+                               }
+                               if (graph1.history_size > graph2.history_size)
+                                       graph1 = graph1.Parent;
+                               else if (graph2.history_size > graph1.history_size)
+                                       graph2 = graph2.Parent;
+                               else {
+                                       graph1 = graph1.Parent;
+                                       graph2 = graph2.Parent;
+                               }
+                       }
+                       SymGraph<TFunc, TADomain> tail = graph1;
+                       int historySize = tail != null ? tail.history_size : 0;
+                       updateSize = g1.history_size + g2.history_size - 2*historySize;
+                       return tail;
+               }
+
+               private static bool InternalLessEqual (SymGraph<TFunc, TADomain> thisG, SymGraph<TFunc, TADomain> thatG,
+                                                      out IImmutableMap<SymValue, LispList<SymValue>> forward,
+                                                      out IImmutableMap<SymValue, SymValue> backward)
+               {
+                       int updateSize;
+                       SymGraph<TFunc, TADomain> commonTail = ComputeCommonTail (thisG, thatG, out updateSize);
+                       if (thisG.IsImmutable)
+                               thisG = thisG.Clone ();
+
+                       var workList = new WorkList<EqualityPair<TFunc, TADomain>> ();
+                       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, int> triggers = ImmutableIntKeyMap<SymValue, int>.Empty (SymValue.GetUniqueKey);
+
+                       while (!workList.IsEmpty ()) {
+                               EqualityPair<TFunc, TADomain> equalityPair = workList.Pull ();
+                               SymValue sv1 = equalityPair.Sv1;
+                               SymValue sv2 = equalityPair.Sv2;
+
+                               SymValue s;
+                               if (VisitedBefore (sv2, backwardManifested, backwardMap, out s)) {
+                                       if (s != null && s == sv1)
+                                               continue;
+
+                                       if (DebugOptions.Debug)
+                                               Console.WriteLine ("---LessEqual fails due to pre-existing relation: {0} <- {1}", s, sv2);
+                                       forward = null;
+                                       backward = null;
+                                       return false;
+                               }
+
+                               TADomain val1 = sv1 == null ? thisG.UnderlyingTopValue.ForManifestedField () : thisG [sv1];
+                               TADomain val2 = thatG [sv2];
+                               if (!val1.LessEqual (val2)) {
+                                       if (DebugOptions.Debug)
+                                               Console.WriteLine ("---LessEqual fails due to abstract values: !({0} <= {1})", val1, val2);
+                                       forward = null;
+                                       backward = null;
+                                       return false;
+                               }
+                               if (sv1 != null) {
+                                       backwardMap = backwardMap.Add (sv2, sv1);
+                                       forwardMap = forwardMap.Add (sv1, forwardMap [sv1].Cons (sv2));
+                               } else
+                                       backwardManifested = backwardManifested.Add (sv2);
+                               if (thisG.HasAllBottomFields (sv1))
+                                       continue;
+                               if (thatG.HasAllBottomFields (sv2)) {
+                                       if (DebugOptions.Debug)
+                                       {
+                                               Console.WriteLine ("---LessEqual fails due to bottom field difference");
+                                       }
+                                       forward = null;
+                                       backward = null;
+                                       return false;
+                               }
+
+                               foreach (TFunc function in thatG.Functions (sv2)) {
+                                       SymValue v1 = thisG [function, sv1];
+                                       SymValue v2 = thatG [function, sv2];
+                                       if (DebugOptions.Debug)
+                                               Console.WriteLine ("    {0}-{1}->{2} <=? {3}-{4}->{5}", sv1, function, v1, sv2, function, v2);
+                                       workList.Add (new EqualityPair<TFunc, TADomain> (v1, v2));
+                               }
+
+                               foreach (var e in thatG.MultiEdges (sv2)) {
+                                       foreach (SymValue sv in thatG.MultiEdgeMap [sv2, e].AsEnumerable ()) {
+                                               if (!UpdateTrigger (sv, e, ref triggers))
+                                                       continue;
+
+                                               SymGraphTerm<TFunc> term = thatG.EqualMultiTermsMap [sv];
+                                               var args = new SymValue[term.Args.Length];
+                                               for (int i = 0; i < args.Length; i++)
+                                                       args [i] = backwardMap [term.Args [i]];
+
+                                               SymValue v1 = thisG.LookupWithoutManifesting (args, e.Function);
+                                               if (v1 == null) {
+                                                       if (DebugOptions.Debug)
+                                                               Console.WriteLine ("---LessEqual fails due to missing multi term {0}({1})",
+                                                                                  e.Function,
+                                                                                  string.Join (", ", term.Args.Select (it => it.ToString ())));
+                                                       forward = null;
+                                                       backward = null;
+                                                       return false;
+                                               }
+
+                                               workList.Add (new EqualityPair<TFunc, TADomain> (v1, sv));
+                                       }
+                               }
+                       }
+                       forward = forwardMap;
+                       backward = CompleteWithCommon (backwardMap, thisG, commonTail.IdGenerator);
+                       return true;
+               }
+
+               private static IImmutableMap<SymValue, SymValue> CompleteWithCommon (IImmutableMap<SymValue, SymValue> map,
+                                                                                    SymGraph<TFunc, TADomain> thisGraph, int lastCommonId)
+               {
+                       IEnumerable<SymValue> symValues = thisGraph.EqualTermsMap.Keys.Concat (thisGraph.EqualMultiTermsMap.Keys);
+                       foreach (SymValue sv in symValues) {
+                               if (IsCommon (sv, lastCommonId) && !map.ContainsKey (sv))
+                                       map = map.Add (sv, sv);
+                       }
+                       return map;
+               }
+
+               private static bool IsCommon (SymValue sv, int lastCommonId)
+               {
+                       return sv.UniqueId <= lastCommonId;
+               }
+
+               private static bool UpdateTrigger (SymValue sv, MultiEdge<TFunc, TADomain> edge, ref IImmutableMap<SymValue, int> triggers)
+               {
+                       int val = triggers [sv] + 1;
+                       triggers = triggers.Add (sv, val);
+                       return (val == edge.Arity);
+               }
+
+               private static bool VisitedBefore (SymValue sv2,
+                                                  IImmutableSet<SymValue> backwardManifested,
+                                                  IImmutableMap<SymValue, SymValue> backward,
+                                                  out SymValue sv1)
+               {
+                       sv1 = backward [sv2];
+                       return sv1 != null || backwardManifested.Contains (sv2);
+               }
+
+               private bool IsSameEGraph (SymGraph<TFunc, TADomain> that)
+               {
+                       if (this == that)
+                               return true;
+                       if (that.Parent == this)
+                               return that.Updates == Updates;
+
+                       return false;
+               }
+
+               private void MarkAsImmutable ()
+               {
+                       this.is_immutable = true;
+               }
+
+               #region Merge updates
+               private void AddUpdate (Update<TFunc, TADomain> update)
+               {
+                       Updates = Updates.Cons (update);
+               }
+
+               private void AddAbstractValueUpdate (SymValue sv)
+               {
+                       if (!IsOldSymbol (sv))
+                               return;
+                       AddUpdate (new AbstractDomainUpdate<TFunc, TADomain> (sv));
+               }
+
+               private void AddEqualityUpdate (SymValue sv1, SymValue sv2)
+               {
+                       if (!IsOldSymbol (sv1) || !IsOldSymbol (sv2))
+                               return;
+                       AddUpdate (new EqualityUpdate<TFunc, TADomain> (sv1, sv2));
+               }
+
+               private void AddEdgeUpdate (SymValue from, TFunc function)
+               {
+                       if (!IsOldSymbol (from))
+                               return;
+                       AddUpdate (new EdgeUpdate<TFunc, TADomain> (from, function));
+               }
+
+               private void AddEliminateAllUpdate (SymValue from)
+               {
+                       if (!IsOldSymbol (from))
+                               return;
+                       foreach (TFunc function in TermMap.Keys2 (from))
+                               AddUpdate (new EliminateEdgeUpdate<TFunc, TADomain> (from, function));
+               }
+
+               private void AddEliminateEdgeUpdate (SymValue from, TFunc function)
+               {
+                       if (!IsOldSymbol (from))
+                               return;
+                       AddUpdate (new EliminateEdgeUpdate<TFunc, TADomain> (from, function));
+               }
+
+               private void AddMultiEdgeUpdate (SymValue[] from, TFunc function)
+               {
+                       for (int i = 0; i < from.Length; i++) {
+                               if (!IsOldSymbol (from [i]))
+                                       return;
+                       }
+
+                       AddUpdate (new MultiEdgeUpdate<TFunc, TADomain> (from, function));
+               }
+               #endregion
+
+               public IImmutableMap<SymValue, LispList<SymValue>> GetForwardIdentityMap ()
+               {
+                       var res = ImmutableIntKeyMap<SymValue, LispList<SymValue>>.Empty (SymValue.GetUniqueKey);
+                       foreach (var sv in this.EqualTermsMap.Keys.Union (this.EqualMultiTermsMap.Keys)) {
+                               res = res.Add (sv, LispList<SymValue>.Cons (sv, null));
+                       }
+                       return res;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraphTerm.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraphTerm.cs
new file mode 100644 (file)
index 0000000..e122702
--- /dev/null
@@ -0,0 +1,62 @@
+// 
+// SymGraphTerm.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.Linq;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       struct SymGraphTerm<TFunc> : IEquatable<SymGraphTerm<TFunc>>
+               where TFunc : IEquatable<TFunc> {
+               public readonly SymValue[] Args;
+               public readonly TFunc Function;
+
+               public SymGraphTerm (TFunc function, params SymValue[] args)
+               {
+                       this.Function = function;
+                       this.Args = args;
+               }
+
+               public bool Equals (SymGraphTerm<TFunc> that)
+               {
+                       if (!this.Function.Equals (that.Function) || this.Args.Length != that.Args.Length)
+                               return false;
+
+                       for (int i = 0; i < this.Args.Length; i++) {
+                               if (!this.Args [i].Equals (that.Args [i]))
+                                       return false;
+                       }
+                       return true;
+               }
+
+               public override string ToString ()
+               {
+                       var args = this.Args == null ? "<no args>" : string.Join (", ", this.Args.Select (a => a.ToString ()));
+                       return string.Format ("Term({0}, {{{1}}})", this.Function, args);
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..ed63b15
--- /dev/null
@@ -0,0 +1,53 @@
+// 
+// Update.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 Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph {
+       abstract class Update<TFunc, TAbstractDomain>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TAbstractDomain : IAbstractDomainForEGraph<TAbstractDomain>, IEquatable<TAbstractDomain> {
+               public Update<TFunc, TAbstractDomain> Next { get; private set; }
+
+               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)
+               {
+                       Update<TFunc, TAbstractDomain> last = null;
+                       for (; updates != common; updates = updates.Tail) {
+                               Update<TFunc, TAbstractDomain> head = updates.Head;
+                               head.Next = last;
+                               last = head;
+                       }
+                       return last;
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..e9a4955
--- /dev/null
@@ -0,0 +1,174 @@
+// 
+// AbstractType.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.IO;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       struct AbstractType : IAbstractDomainForEGraph<AbstractType>, IEquatable<AbstractType> {
+               public static AbstractType TopValue = new AbstractType (FlatDomain<TypeNode>.TopValue, false);
+               public static AbstractType BottomValue = new AbstractType (FlatDomain<TypeNode>.BottomValue, true);
+
+               private FlatDomain<TypeNode> value;
+
+               public AbstractType (FlatDomain<TypeNode> value, bool isZero) : this ()
+               {
+                       IsZero = isZero;
+                       this.value = value;
+               }
+
+               public bool IsZero { get; private set; }
+
+               public FlatDomain<TypeNode> Type
+               {
+                       get { return this.value; }
+               }
+
+               public TypeNode ConcreteType
+               {
+                       get { return this.value.Concrete; }
+               }
+
+               public bool IsNormal
+               {
+                       get { return this.value.IsNormal; }
+               }
+
+               private static AbstractType ForManifestedFieldValue
+               {
+                       get { return TopValue; }
+               }
+
+               public AbstractType ButZero
+               {
+                       get { return new AbstractType (this.value, true); }
+               }
+               public AbstractType With (FlatDomain<TypeNode> type)
+               {
+                       return new AbstractType (type, this.IsZero);
+               }
+
+               #region IAbstractDomainForEGraph<AbstractType> Members
+               public AbstractType Top
+               {
+                       get { return new AbstractType (FlatDomain<TypeNode>.TopValue, false); }
+               }
+
+               public AbstractType Bottom
+               {
+                       get { return new AbstractType (FlatDomain<TypeNode>.BottomValue, true); }
+               }
+
+               public bool IsTop
+               {
+                       get { return !IsZero && this.value.IsTop; }
+               }
+
+               public bool IsBottom
+               {
+                       get { return IsZero && this.value.IsBottom; }
+               }
+
+               public AbstractType Join (AbstractType that, bool widening, out bool weaker)
+               {
+                       if (that.IsZero) {
+                               weaker = false;
+                               if (this.value.IsBottom)
+                                       return new AbstractType (that.value, IsZero);
+                               return this;
+                       }
+                       if (IsZero) {
+                               weaker = true;
+                               if (that.value.IsBottom)
+                                       return new AbstractType (this.value, that.IsZero);
+                               return that;
+                       }
+
+                       FlatDomain<TypeNode> resultType = this.value.Join (that.value, widening, out weaker);
+                       return new AbstractType (resultType, false);
+               }
+
+               public AbstractType Meet (AbstractType that)
+               {
+                       return new AbstractType (this.value.Meet (that.value), IsZero || that.IsZero);
+               }
+
+               public bool LessEqual (AbstractType that)
+               {
+                       if (IsZero)
+                               return true;
+                       if (that.IsZero)
+                               return false;
+
+                       return this.value.LessEqual (that.value);
+               }
+
+               public AbstractType ImmutableVersion ()
+               {
+                       return this;
+               }
+
+               public AbstractType Clone ()
+               {
+                       return this;
+               }
+
+               public void Dump (TextWriter tw)
+               {
+                       if (IsZero)
+                               tw.Write ("(Zero) ");
+
+                       this.value.Dump (tw);
+               }
+
+               public bool HasAllBottomFields
+               {
+                       get { return IsZero; }
+               }
+
+               public AbstractType ForManifestedField ()
+               {
+                       return ForManifestedFieldValue;
+               }
+               #endregion
+
+               #region IEquatable<AbstractType> Members
+               public bool Equals (AbstractType that)
+               {
+                       return this.IsZero == that.IsZero && this.value.Equals (that.value);
+               }
+               #endregion
+
+               public override string ToString ()
+               {
+                       return (IsZero ? "(Zero) " : "") + this.value;
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..2a2b2b6
--- /dev/null
@@ -0,0 +1,1262 @@
+// 
+// AnalysisDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       struct AnalysisDecoder : IILVisitor<APC, int, int, Domain, Domain> {
+               private readonly HeapAnalysis parent;
+
+               public AnalysisDecoder (HeapAnalysis parent)
+               {
+                       this.parent = parent;
+               }
+
+               public IContractProvider ContractProvider
+               {
+                       get { return this.parent.ContractProvider; }
+               }
+
+               public IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.parent.MetaDataProvider; }
+               }
+               #region Helper Methods
+               private void UnaryEffect (UnaryOperator op, int dest, int source, Domain data)
+               {
+                       switch (op)
+                       {
+                       case UnaryOperator.Conv_i:
+                               data.AssignValueAndNullnessAtConv_IU (dest, source, false);
+                               break;
+                       case UnaryOperator.Conv_u:
+                               data.AssignValueAndNullnessAtConv_IU (dest, source, true);
+                               break;
+                       case UnaryOperator.Not:
+                               data.AssignSpecialUnary (dest, data.Functions.UnaryNot, source, MetaDataProvider.System_Int32);
+                               break;
+                       default:
+                               data.AssignPureUnary (dest, op, data.UnaryResultType (op, data.CurrentType (source)), source);
+                               break;
+                       }
+               }
+
+               private Domain BinaryEffect (APC pc, BinaryOperator op, int dest, int op1, int op2, Domain data)
+               {
+                       FlatDomain<TypeNode> resultType = data.BinaryResultType (op, data.CurrentType (op1), data.CurrentType (op2));
+                       switch (op) {
+                       case BinaryOperator.Ceq:
+                       case BinaryOperator.Cobjeq:
+                               {
+                                       SymValue srcValue = data.Value (op1);
+                                       if (data.IsZero (srcValue)) {
+                                               data.AssignSpecialUnary (dest, data.Functions.UnaryNot, op2, resultType);
+                                               break;
+                                       }
+                                       SymValue val2 = data.Value (op2);
+                                       if (data.IsZero (val2)) {
+                                               data.AssignSpecialUnary (dest, data.Functions.UnaryNot, op1, resultType);
+                                               break;
+                                       }
+                                       goto default;
+                               }
+                       case BinaryOperator.Cne_Un:
+                               {
+                                       SymValue val1 = data.Value (op1);
+                                       if (data.IsZero (val1)) {
+                                               data.AssignSpecialUnary (dest, data.Functions.NeZero, op2, resultType);
+                                               break;
+                                       }
+                                       SymValue val2 = data.Value (op2);
+                                       if (data.IsZero (val2)) {
+                                               data.AssignSpecialUnary (dest, data.Functions.NeZero, op1, resultType);
+                                               break;
+                                       }
+                                       goto default;
+                               }
+                       default:
+                               data.AssignPureBinary (dest, op, resultType, op1, op2);
+                               break;
+                       }
+
+                       data.Havoc (2);
+                       return data;
+               }
+
+               private void LoadArgEffect (Parameter argument, bool isOld, int dest, Domain data)
+               {
+                       SymValue address = isOld ? data.OldValueAddress (argument) : data.Address (argument);
+                       IMetaDataProvider metadataDecoder = MetaDataProvider;
+                       data.CopyValue (data.Address (dest), address, metadataDecoder.ManagedPointer (metadataDecoder.ParameterType (argument)));
+               }
+
+               private void StoreLocalEffect (Local local, int source, Domain data)
+               {
+                       data.CopyValue (data.Address (local), data.Address (source), MetaDataProvider.ManagedPointer (MetaDataProvider.LocalType (local)));
+                       data.Havoc (source);
+               }
+
+               private void IsinstEffect (TypeNode type, int dest, Domain data)
+               {
+                       data.AssignValue (dest, type);
+               }
+
+               private void LoadLocalEffect (Local local, int dest, Domain data)
+               {
+                       data.CopyValue (data.Address (dest), data.Address (local), MetaDataProvider.ManagedPointer (MetaDataProvider.LocalType (local)));
+               }
+
+               private Domain AssumeEffect (APC pc, EdgeTag tag, int condition, Domain data)
+               {
+                       data = data.Assume (condition, tag != EdgeTag.False);
+                       if (!data.IsBottom)
+                               data.Havoc (condition);
+
+                       return data;
+               }
+
+               private Domain AssertEffect (APC pc, EdgeTag tag, int condition, Domain data)
+               {
+                       data = data.Assume (condition, true);
+                       if (!data.IsBottom)
+                               data.Havoc (condition);
+
+                       return data;
+               }
+
+               private static void LoadStackAddressEffect (APC pc, int offset, int dest, int source, Domain data)
+               {
+                       data.CopyStackAddress (data.Address (dest), source);
+               }
+
+               private Domain CallEffect<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, int dest, ArgList args, Domain data, TypeNode constraint, bool constrainedCall)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       TypeNode t = constraint;
+                       if (!pc.InsideContract)
+                               data.ResetModifiedAtCall ();
+
+                       IImmutableMap<TypeNode, TypeNode> instantiationMap = ComputeTypeInstantiationMap (pc, method);
+                       bool derefThis = false;
+                       if (virt)
+                       {
+                               if (MetaDataProvider.IsStruct (constraint))
+                                       DevirtualizeImplementingMethod (constraint, ref method);
+                               else
+                               {
+                                       if (constrainedCall && MetaDataProvider.IsReferenceType (Specialize (instantiationMap, constraint)))
+                                               derefThis = true;
+                                       SymValue loc = data.Value (args[0]);
+                                       if (derefThis)
+                                               loc = data.Value (loc);
+                                       AbstractType aType = data.GetType (loc);
+                                       if (aType.IsNormal)
+                                               DevirtualizeImplementingMethod (aType.ConcreteType, ref method);
+                               }
+                       }
+                       string name = MetaDataProvider.Name (method);
+                       if (args.Count > 0)
+                       {
+                               if ((MetaDataProvider.Equal (t, MetaDataProvider.System_String) || MetaDataProvider.Equal (t, MetaDataProvider.System_Array))
+                                   && (name == "get_Length" || name == "get_LongLength"))
+                               {
+                                       data.AssignArrayLength (data.Address (dest), data.Value (args[0]));
+                                       return data;
+                               }
+                               if (MetaDataProvider.Equal (t, MetaDataProvider.System_Object) && name == "MemberwiseClone")
+                               {
+                                       TypeNode t2 = data.GetType (data.Value (args[0])).ConcreteType;
+                                       SymValue obj = data.CreateObject (t2);
+                                       data.CopyStructValue (obj, data.Value (args[0]), t2);
+                                       data.CopyAddress (data.Address (dest), obj, t2);
+                                       return data;
+                               }
+                               if (args.Count > 1 && MetaDataProvider.IsReferenceType (t))
+                               {
+                                       if (name.EndsWith ("op_Inequality"))
+                                               return Binary (pc, BinaryOperator.Cne_Un, dest, args[0], args[1], data);
+                                       if (name.EndsWith ("op_Equality"))
+                                               return Binary (pc, BinaryOperator.Cobjeq, dest, args[0], args[1], data);
+                               }
+                               if (MetaDataProvider.Equal (t, MetaDataProvider.System_IntPtr) && name.StartsWith ("op_Explicit"))
+                               {
+                                       data.Copy (dest, args[0]);
+                                       return data;
+                               }
+                       }
+                       //todo:
+                       //                              if (extraVarargs.Count == 0 && !this.MetaDataProvider.IsVoidMethod(method) && this.ContractProvider.)
+
+                       {
+                               Property property;
+                               if (MetaDataProvider.IsPropertySetter (method, out property))
+                               {
+                                       if (args.Count <= 2)
+                                       {
+                                               Method getter;
+                                               if (MetaDataProvider.HasGetter (property, out getter))
+                                               {
+                                                       SymValue obj;
+                                                       SymValue srcAddr;
+                                                       if (args.Count == 1)
+                                                       {
+                                                               obj = data.Globals;
+                                                               srcAddr = data.Address (args[0]);
+                                                       }
+                                                       else
+                                                       {
+                                                               obj = data.Value (args[0]);
+                                                               if (derefThis)
+                                                                       obj = data.Value (obj);
+                                                               srcAddr = data.Address (args[1]);
+                                                       }
+                                                       if (MetaDataProvider.Equal (MetaDataProvider.DeclaringType (this.parent.CurrentMethod), MetaDataProvider.Unspecialized (MetaDataProvider.DeclaringType (method))))
+                                                       {
+                                                               data.HavocUp (obj, ref data.ModifiedAtCall, false);
+
+                                                               if (MetaDataProvider.IsAutoPropertyMember (method))
+                                                               {
+                                                                       foreach (Field f in this.parent.StackContextProvider.MethodContext.Modifies (method))
+                                                                       {
+                                                                               TypeNode fieldAddressType;
+                                                                               SymValue destAddr = data.FieldAddress (obj, f, out fieldAddressType);
+                                                                               data.CopyValue (destAddr, srcAddr, fieldAddressType);
+                                                                       }
+                                                               }
+                                                               else
+                                                                       data.HavocFields (obj, this.parent.StackContextProvider.MethodContext.Modifies (method), ref data.ModifiedAtCall);
+                                                       }
+                                                       TypeNode pseudoFieldAddressType;
+                                                       SymValue destAddr1 = data.PseudoFieldAddress (obj, getter, out pseudoFieldAddressType, true);
+                                                       data.CopyValue (destAddr1, srcAddr, pseudoFieldAddressType);
+                                                       data.AssignValue (dest, MetaDataProvider.System_Void);
+                                                       return data;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               Method getter;
+                                               if (MetaDataProvider.HasGetter (property, out getter))
+                                               {
+                                                       var args1 = new SymValue[GetNonOutArgs (method) - 1];
+                                                       int num = 0;
+                                                       for (int i = 0; i < args.Count - 1; i++)
+                                                       {
+                                                               bool isOut;
+                                                               SymValue sv = KeyForPureFunctionArgument (method, i, args[i], data, instantiationMap, out isOut);
+                                                               if (!isOut)
+                                                                       args1[num++] = sv;
+                                                       }
+                                                       SymValue thisSV = data.Value (args[0]);
+                                                       if (derefThis)
+                                                               thisSV = data.Value (thisSV);
+                                                       TypeNode pseudoFieldAddressType;
+                                                       SymValue pseudoField = data.PseudoFieldAddress (args1, getter, out pseudoFieldAddressType, false);
+                                                       AssignAllOutParameters (data, pseudoField, method, args);
+                                                       SymValue srcAddr = data.Address (args[args.Count - 1]);
+                                                       data.CopyValue (pseudoField, srcAddr, pseudoFieldAddressType);
+                                                       if (MetaDataProvider.Equal (MetaDataProvider.DeclaringType (this.parent.CurrentMethod), MetaDataProvider.Unspecialized (MetaDataProvider.DeclaringType (method))))
+                                                       {
+                                                               data.HavocUp (thisSV, ref data.ModifiedAtCall, false);
+                                                               data.HavocFields (thisSV, this.parent.StackContextProvider.MethodContext.Modifies (method), ref data.ModifiedAtCall);
+                                                       }
+                                               }
+                                               data.AssignValue (dest, MetaDataProvider.System_Void);
+                                               return data;
+                                       }
+                               }
+                               bool insideConstructor = MetaDataProvider.IsConstructor (method);
+                               HavocParameters (pc, method, extraVarargs, args, data, constraint, insideConstructor, false, derefThis);
+                               data.AssignReturnValue (dest, MetaDataProvider.ReturnType (method));
+                               return data;
+                       }
+               }
+
+               private static Domain DoWithBothDomains (Domain data, Func<Domain, Domain> action)
+               {
+                       data = action (data);
+                       if (data.OldDomain != null)
+                               data.OldDomain = action (data.OldDomain);
+                       return data;
+               }
+
+               private static Domain DoWithBothDomains (Domain data, Action<Domain> action)
+               {
+                       action (data);
+                       if (data.OldDomain != null)
+                               action (data.OldDomain);
+                       return data;
+               }
+               #endregion
+
+               #region IILVisitor<APC,int,int,Domain,Domain> Members
+               public Domain Binary (APC pc, BinaryOperator op, int dest, int operand1, int operand2, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.BinaryEffect (pc, op, dest, operand1, operand2, d));
+               }
+
+               public Domain Isinst (APC pc, TypeNode type, int dest, int obj, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.IsinstEffect (type, dest, d));
+               }
+
+               public Domain LoadNull (APC pc, int dest, Domain polarity)
+               {
+                       return DoWithBothDomains (polarity, d => d.AssignNull (dest));
+               }
+
+               public Domain LoadConst (APC pc, TypeNode type, object constant, int dest, Domain data)
+               {
+                       return DoWithBothDomains (data, d => d.AssignConst (dest, type, constant));
+               }
+
+               public Domain Sizeof (APC pc, TypeNode type, int dest, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => d.AssignValue (dest, it.MetaDataProvider.System_Int32));
+               }
+
+               public Domain Unary (APC pc, UnaryOperator op, bool unsigned, int dest, int source, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.UnaryEffect (op, dest, source, d));
+               }
+
+               public Domain Entry (APC pc, Method method, Domain data)
+               {
+                       IIndexable<Local> locals = MetaDataProvider.Locals (method);
+                       for (int i = 0; i < locals.Count; i++)
+                               MaterializeLocal (locals [i], method, data);
+
+                       TypeNode declaringType = MetaDataProvider.DeclaringType (method);
+                       IIndexable<Parameter> parameters = MetaDataProvider.Parameters (method);
+                       for (int i = 0; i < parameters.Count; i++)
+                               MaterializeParameter (parameters [i], declaringType, data, false);
+
+                       if (!MetaDataProvider.IsStatic (method))
+                               MaterializeParameter (MetaDataProvider.This (method), declaringType, data, true);
+
+                       if (MetaDataProvider.IsConstructor (method)) {
+                               Parameter p = MetaDataProvider.This (method);
+                               SymValue ptr = data.Value (p);
+
+                               foreach (Field field in MetaDataProvider.Fields (declaringType)) {
+                                       if (MetaDataProvider.IsStatic (field))
+                                               continue;
+
+                                       TypeNode fieldType = MetaDataProvider.FieldType (field);
+                                       if (MetaDataProvider.IsStruct (fieldType))
+                                               data.AssignConst (data.FieldAddress (ptr, field), fieldType, 0);
+                                       else
+                                               data.AssignNull (data.FieldAddress (ptr, field));
+                               }
+
+                               foreach (Property property in MetaDataProvider.Properties (declaringType)) {
+                                       Method getter;
+                                       if (!MetaDataProvider.IsStatic (property) && MetaDataProvider.HasGetter (property, out getter)
+                                           && MetaDataProvider.IsCompilerGenerated (getter) && MetaDataProvider.Parameters (getter).Count == 0) {
+                                               TypeNode propertyType = MetaDataProvider.ReturnType (getter);
+                                               if (MetaDataProvider.IsStruct (propertyType))
+                                                       data.AssignConst (data.PseudoFieldAddress (ptr, getter), propertyType, 0);
+                                               else
+                                                       data.AssignNull (data.PseudoFieldAddress (ptr, getter));
+                                       }
+                               }
+                       }
+
+                       return data;
+               }
+
+               public Domain Assume (APC pc, EdgeTag tag, int condition, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.AssumeEffect (pc, tag, condition, data));
+               }
+
+               public Domain Assert (APC pc, EdgeTag tag, int condition, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.AssertEffect (pc, tag, condition, data));
+               }
+
+               public Domain BeginOld (APC pc, APC matchingEnd, Domain data)
+               {
+                       if (data.InsideOld++ == 0) {
+                               Domain oldState = FindOldState (pc, data);
+                               if (oldState == null)
+                                       throw new InvalidOperationException ("begin_old in weird calling context");
+                               Domain domain = oldState.Clone ();
+                               domain.BeginOldPC = pc;
+                               data.OldDomain = domain;
+                       }
+
+                       return data;
+               }
+
+               public Domain EndOld (APC pc, APC matchingBegin, TypeNode type, int dest, int source, Domain data)
+               {
+                       if (--data.InsideOld == 0)
+                               data.OldDomain = null;
+
+                       data.Copy (dest, source);
+                       return data;
+               }
+
+               public Domain LoadStack (APC pc, int offset, int dest, int source, bool isOld, Domain data)
+               {
+                       if (isOld) {
+                               Domain oldState = FindOldState (pc, data);
+                               oldState.CopyOldValue (pc, dest, source, data, false);
+                               if (data.OldDomain != null)
+                                       oldState.CopyOldValue (pc, dest, source, data.OldDomain, false);
+                       } else {
+                               data.Copy (dest, source);
+                               if (data.OldDomain != null)
+                                       data.OldDomain.Copy (dest, source);
+                       }
+
+                       return data;
+               }
+
+               public Domain LoadStackAddress (APC pc, int offset, int dest, int source, TypeNode type, bool isOld, Domain data)
+               {
+                       if (isOld) {
+                               TypeNode ptrType = MetaDataProvider.ManagedPointer (type);
+                               Domain oldState = FindOldState (pc, data);
+                               SymValue srcOldAddr = oldState.Address (source);
+                               SymValue sv = data.CreateValue (type);
+
+                               oldState.CopyOldValue (pc, sv, srcOldAddr, data, true);
+                               data.CopyAddress (data.Address (dest), sv, ptrType);
+                               if (data.OldDomain != null) {
+                                       TypeNode ptrPtrType = MetaDataProvider.ManagedPointer (ptrType);
+                                       oldState.CopyOldValueToDest (pc, data.OldDomain.Address (dest), srcOldAddr, ptrPtrType, data.OldDomain);
+                               }
+                       } else {
+                               LoadStackAddressEffect (pc, offset, dest, source, data);
+                               if (data.OldDomain != null)
+                                       LoadStackAddressEffect (pc, offset, dest, source, data.OldDomain);
+                       }
+                       return data;
+               }
+
+               public Domain LoadResult (APC pc, TypeNode type, int dest, int source, Domain data)
+               {
+                       return DoWithBothDomains (data, d => d.Copy (dest, source));
+               }
+
+               public Domain Arglist (APC pc, int dest, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain Branch (APC pc, APC target, bool leavesExceptionBlock, Domain data)
+               {
+                       throw new InvalidOperationException ("Should not see branches, should see assumes. See APCDecoder");
+               }
+
+               public Domain BranchCond (APC pc, APC target, BranchOperator bop, int value1, int value2, Domain data)
+               {
+                       throw new InvalidOperationException ("Should not see branches, should see assumes. See APCDecoder");
+               }
+
+               public Domain BranchTrue (APC pc, APC target, int cond, Domain data)
+               {
+                       throw new InvalidOperationException ("Should not see branches, should see assumes. See APCDecoder");
+               }
+
+               public Domain BranchFalse (APC pc, APC target, int cond, Domain data)
+               {
+                       throw new InvalidOperationException ("Should not see branches, should see assumes. See APCDecoder");
+               }
+
+               public Domain Break (APC pc, Domain data)
+               {
+                       return data;
+               }
+
+               public Domain Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, int dest, ArgList args, Domain data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       TypeNode declaringType = MetaDataProvider.DeclaringType (method);
+                       if (data.OldDomain == null)
+                               return CallEffect (pc, method, virt, extraVarargs, dest, args, data, declaringType, false);
+                       data.OldDomain = CallEffect (pc, method, virt, extraVarargs, dest, args, data.OldDomain, declaringType, false);
+                       if (!MetaDataProvider.IsVoidMethod (method))
+                               data.OldDomain.CopyOldValue (data.OldDomain.BeginOldPC, dest, dest, data, true);
+                       return data;
+               }
+
+               public Domain Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, int dest, int functionPointer, ArgList args, Domain data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       if (data.OldDomain == null)
+                               return CalliEffect (pc, returnType, argTypes, instance, dest, functionPointer, args, data);
+                       data.OldDomain = CalliEffect (pc, returnType, argTypes, instance, dest, functionPointer, args, data.OldDomain);
+                       if (!MetaDataProvider.IsVoid (returnType))
+                               data.OldDomain.CopyOldValue (data.OldDomain.BeginOldPC, dest, dest, data, true);
+                       return data;
+               }
+
+               public Domain CheckFinite (APC pc, int dest, int source, Domain data)
+               {
+                       data.Copy (dest, source);
+                       if (data.OldDomain != null)
+                               data.OldDomain.Copy (dest, source);
+
+                       return data;
+               }
+
+               public Domain CopyBlock (APC pc, int destAddress, int srcAddress, int len, Domain data)
+               {
+                       data.Havoc (destAddress);
+                       data.Havoc (srcAddress);
+                       data.Havoc (len);
+
+                       return data;
+               }
+
+               public Domain EndFilter (APC pc, int decision, Domain data)
+               {
+                       data.Havoc (decision);
+
+                       return data;
+               }
+
+               public Domain EndFinally (APC pc, Domain data)
+               {
+                       return data;
+               }
+
+               public Domain Jmp (APC pc, Method method, Domain data)
+               {
+                       return data;
+               }
+
+               public Domain LoadArg (APC pc, Parameter argument, bool isOld, int dest, Domain data)
+               {
+                       LoadArgEffect (argument, isOld, dest, data);
+                       if (data.OldDomain != null)
+                               LoadArgEffect (argument, isOld, dest, data.OldDomain);
+
+                       return data;
+               }
+
+               public Domain LoadArgAddress (APC pc, Parameter argument, bool isOld, int dest, Domain data)
+               {
+                       LoadArgAddressEffect (argument, isOld, dest, data);
+                       if (data.OldDomain != null)
+                               LoadArgAddressEffect (argument, isOld, dest, data.OldDomain);
+                       return data;
+               }
+
+               public Domain LoadLocal (APC pc, Local local, int dest, Domain data)
+               {
+                       LoadLocalEffect (local, dest, data);
+                       if (data.OldDomain != null)
+                               data.CopyValueToOldState (data.OldDomain.BeginOldPC, MetaDataProvider.LocalType (local), dest, dest, data.OldDomain);
+
+                       return data;
+               }
+
+               public Domain LoadLocalAddress (APC pc, Local local, int dest, Domain data)
+               {
+                       LoadLocalAddressEffect (local, dest, data);
+                       if (data.OldDomain != null)
+                               LoadLocalAddressEffect (local, dest, data.OldDomain);
+
+                       return data;
+               }
+
+               public Domain Nop (APC pc, Domain data)
+               {
+                       return data;
+               }
+
+               public Domain Pop (APC pc, int source, Domain data)
+               {
+                       data.Havoc (source);
+                       if (data.OldDomain != null)
+                               data.OldDomain.Havoc (source);
+
+                       return data;
+               }
+
+               public Domain Return (APC pc, int source, Domain data)
+               {
+                       data.Havoc (source);
+
+                       return data;
+               }
+
+               public Domain StoreArg (APC pc, Parameter argument, int source, Domain data)
+               {
+                       data.CopyValue (data.Address (argument), data.Address (source), MetaDataProvider.ManagedPointer (MetaDataProvider.ParameterType (argument)));
+                       data.Havoc (source);
+
+                       return data;
+               }
+
+               public Domain StoreLocal (APC pc, Local local, int source, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.StoreLocalEffect (local, source, d));
+               }
+
+               public Domain Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, int value, Domain data)
+               {
+                       throw new InvalidOperationException ("Should only see assumes");
+               }
+
+               public Domain Box (APC pc, TypeNode type, int dest, int source, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, (d) => it.BoxEffect (type, dest, source, d));
+               }
+
+               public Domain ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint, TypeList extraVarargs, int dest, ArgList args, Domain data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       if (data.OldDomain == null)
+                               return CallEffect (pc, method, true, extraVarargs, dest, args, data, constraint, true);
+
+                       data.OldDomain = CallEffect (pc, method, true, extraVarargs, dest, args, data.OldDomain, constraint, true);
+                       if (!MetaDataProvider.IsVoidMethod (method))
+                               data.OldDomain.CopyOldValue (data.OldDomain.BeginOldPC, dest, dest, data, true);
+                       return data;
+               }
+
+               public Domain CastClass (APC pc, TypeNode type, int dest, int obj, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.CastClassEffect (type, dest, obj, d));
+               }
+
+               public Domain CopyObj (APC pc, TypeNode type, int destPtr, int sourcePtr, Domain data)
+               {
+                       data.CopyValue (data.Value (destPtr), data.Value (sourcePtr), MetaDataProvider.ManagedPointer (type));
+                       data.Havoc (destPtr);
+                       data.Havoc (sourcePtr);
+                       return data;
+               }
+
+               public Domain Initobj (APC pc, TypeNode type, int ptr, Domain data)
+               {
+                       SymValue obj = data.Value (ptr);
+                       data.Havoc (obj);
+                       foreach (Field field in MetaDataProvider.Fields (type)) {
+                               SymValue dest = data.FieldAddress (obj, field);
+                               data.AssignZeroEquivalent (dest, MetaDataProvider.FieldType (field));
+                       }
+                       data.Havoc (ptr);
+                       return data;
+               }
+
+               public Domain LoadElement (APC pc, TypeNode type, int dest, int array, int index, Domain data)
+               {
+                       if (data.OldDomain != null) {
+                               LoadElementEffect (type, dest, array, index, data.OldDomain);
+                               data.OldDomain.CopyOldValue (data.OldDomain.BeginOldPC, dest, dest, data, true);
+                       } else
+                               LoadElementEffect (type, dest, array, index, data);
+
+                       return data;
+               }
+
+               public Domain LoadField (APC pc, Field field, int dest, int obj, Domain data)
+               {
+                       if (data.OldDomain != null) {
+                               LoadFieldEffect (field, dest, obj, data.OldDomain);
+                               data.OldDomain.CopyOldValue (data.OldDomain.BeginOldPC, dest, dest, data, true);
+                       } else
+                               LoadFieldEffect (field, dest, obj, data);
+
+                       return data;
+               }
+
+               public Domain LoadFieldAddress (APC pc, Field field, int dest, int obj, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, domain => it.LoadFieldAddressEffect (pc, field, dest, obj, domain));
+               }
+
+               public Domain LoadLength (APC pc, int dest, int array, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, domain => it.LoadLengthEffect (dest, array, domain));
+               }
+
+               public Domain LoadStaticField (APC pc, Field field, int dest, Domain data)
+               {
+                       if (data.OldDomain != null) {
+                               LoadStaticFieldEffect (field, dest, data.OldDomain);
+                               data.OldDomain.CopyOldValue (data.OldDomain.BeginOldPC, dest, dest, data, true);
+                       } else
+                               LoadStaticFieldEffect (field, dest, data);
+                       return data;
+               }
+
+               public Domain LoadStaticFieldAddress (APC pc, Field field, int dest, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, domain => it.LoadStaticFieldAddressEffect (field, dest, domain));
+               }
+
+               public Domain LoadTypeToken (APC pc, TypeNode type, int dest, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain LoadFieldToken (APC pc, Field type, int dest, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain LoadMethodToken (APC pc, Method type, int dest, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain NewArray<ArgList> (APC pc, TypeNode type, int dest, ArgList lengths, Domain data) where ArgList : IIndexable<int>
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.NewArrayEffect<ArgList> (type, dest, lengths, d));
+               }
+
+               public Domain NewObj<ArgList> (APC pc, Method ctor, int dest, ArgList args, Domain data) where ArgList : IIndexable<int>
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.NewObjEffect (pc, ctor, dest, args, d));
+               }
+
+               public Domain MkRefAny (APC pc, TypeNode type, int dest, int obj, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain RefAnyType (APC pc, int dest, int source, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain RefAnyVal (APC pc, TypeNode type, int dest, int source, Domain data)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public Domain Rethrow (APC pc, Domain data)
+               {
+                       return data.Bottom;
+               }
+
+               public Domain StoreElement (APC pc, TypeNode type, int array, int index, int value, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => it.StoreElementEffect (type, array, index, value, d));
+               }
+
+               public Domain StoreField (APC pc, Field field, int obj, int value, Domain data)
+               {
+                       data.CopyValue (data.FieldAddress (data.Value (obj), field), data.Address (value));
+                       if (!MetaDataProvider.IsCompilerGenerated (field))
+                               data.HavocPseudoFields (data.Value (obj));
+                       data.Havoc (obj);
+                       data.Havoc (value);
+                       return data;
+               }
+
+               public Domain StoreStaticField (APC pc, Field field, int value, Domain data)
+               {
+                       data.CopyValue (data.FieldAddress (data.Globals, field), data.Address (value));
+                       data.Havoc (value);
+                       return data;
+               }
+
+               public Domain Throw (APC pc, int exception, Domain data)
+               {
+                       data.Havoc (exception);
+                       return data;
+               }
+
+               public Domain Unbox (APC pc, TypeNode type, int dest, int obj, Domain data)
+               {
+                       AnalysisDecoder it = this;
+                       return DoWithBothDomains (data, d => d.AssignValue (dest, it.MetaDataProvider.ManagedPointer (type)));
+               }
+
+               public Domain UnboxAny (APC pc, TypeNode type, int dest, int obj, Domain data)
+               {
+                       return DoWithBothDomains (data, d => d.AssignValue (dest, type));
+               }
+               #endregion
+
+               private void MaterializeParameter (Parameter parameter, TypeNode declaringType, Domain data, bool aggressiveMaterialization)
+               {
+                       TypeNode type = MetaDataProvider.ParameterType (parameter);
+                       data.Assign (parameter, type);
+                       MaterializeParameterInfo (data.Address (parameter), MetaDataProvider.ManagedPointer (type), 0, data, declaringType, aggressiveMaterialization);
+                       data.CopyParameterIntoShadow (parameter);
+               }
+
+               private void MaterializeParameterInfo (SymValue sv, TypeNode t, int depth, Domain data, TypeNode fromType, bool aggressiveMaterialization)
+               {
+                       data.MakeUnmodified (sv);
+                       data.SetType (sv, t);
+                       if (depth > 2 && !aggressiveMaterialization || depth > 5)
+                               return;
+                       if (MetaDataProvider.IsManagedPointer (t)) {
+                               TypeNode elemType = MetaDataProvider.ElementType (t);
+                               if (!MetaDataProvider.HasValueRepresentation (elemType)) {
+                                       data.ManifestStructId (sv);
+                                       foreach (Field field in MetaDataProvider.Fields (elemType)) {
+                                               if (!MetaDataProvider.IsStatic (field) && MetaDataProvider.IsVisibleFrom (field, fromType)) {
+                                                       TypeNode fieldAddressType;
+                                                       MaterializeParameterInfo (data.FieldAddress (sv, field, out fieldAddressType), fieldAddressType, depth + 1, data, fromType, aggressiveMaterialization);
+                                               }
+                                       }
+                                       ManifestProperties (sv, depth + 1, data, fromType, aggressiveMaterialization, elemType);
+                               } else
+                                       MaterializeParameterInfo (data.Value (sv), elemType, depth + 1, data, fromType, aggressiveMaterialization);
+                       } else {
+                               if (MetaDataProvider.IsClass (t)) {
+                                       foreach (Field field in MetaDataProvider.Fields (t)) {
+                                               if (!MetaDataProvider.IsStatic (field) && MetaDataProvider.IsVisibleFrom (field, fromType)) {
+                                                       TypeNode fieldAddressType;
+                                                       MaterializeParameterInfo (data.FieldAddress (sv, field, out fieldAddressType), fieldAddressType, depth + 1, data, fromType, aggressiveMaterialization);
+                                               }
+                                       }
+                               } else if (data.NeedsArrayLengthManifested (t))
+                                       data.ManifestArrayLength (sv);
+                       }
+               }
+
+               private void ManifestProperties (SymValue sv, int depth, Domain data, TypeNode fromType, bool aggressiveMaterialization, TypeNode type)
+               {
+                       foreach (Property property in MetaDataProvider.Properties (type)) {
+                               Method getter;
+                               if (MetaDataProvider.IsStatic (property) || !MetaDataProvider.HasGetter (property, out getter) || !MetaDataProvider.IsVisibleFrom (getter, fromType))
+                                       continue;
+
+                               TypeNode pseudoFieldAddressType;
+                               MaterializeParameterInfo (data.PseudoFieldAddress (sv, getter, out pseudoFieldAddressType, false), pseudoFieldAddressType, depth + 1, data, fromType, aggressiveMaterialization);
+                       }
+
+                       if (!MetaDataProvider.IsInterface (type))
+                               return;
+
+                       foreach (TypeNode iface in MetaDataProvider.Interfaces (type)) {
+                               if (MetaDataProvider.IsVisibleFrom (iface, fromType))
+                                       ManifestProperties (sv, depth, data, fromType, aggressiveMaterialization, iface);
+                       }
+               }
+
+               private void MaterializeLocal (Local local, Method method, Domain data)
+               {
+                       TypeNode t = MetaDataProvider.LocalType (local);
+                       data.AssignZeroEquivalent (data.Address (local), t);
+               }
+
+               private void HavocParameters (APC pc, Method method, IIndexable<TypeNode> extraVarargs, IIndexable<int> args, Domain data, TypeNode declaringType, bool insideConstructor, bool thisArgMissing,
+                                             bool derefThis)
+               {
+                       IIndexable<Parameter> parameters = MetaDataProvider.Parameters (method);
+                       IIndexable<Parameter> unspecializedParameters = null;
+                       if (MetaDataProvider.IsSpecialized (method))
+                               unspecializedParameters = MetaDataProvider.Parameters (MetaDataProvider.Unspecialized (method));
+                       int index2 = 0;
+                       int num1 = 0;
+                       for (int index1 = 0; index1 < args.Count; ++index1) {
+                               bool materialize = false;
+                               bool nonFirstThis = false;
+                               int num2 = args [index1];
+                               bool parameterHasGenericType = false;
+                               bool havocReadonlyFields = false;
+                               TypeNode ype;
+
+                               if (index1 == 0 && !thisArgMissing && !MetaDataProvider.IsStatic (method)) {
+                                       num1 = 1;
+                                       ype = MetaDataProvider.ParameterType (MetaDataProvider.This (method));
+                                       if (MetaDataProvider.IsPrimitive (declaringType) || MetaDataProvider.Equal (declaringType, MetaDataProvider.System_Object)) {
+                                               if (MetaDataProvider.IsStruct (declaringType))
+                                                       data.Value (data.Value (args [0]));
+                                               continue;
+                                       }
+                                       if (MetaDataProvider.IsConstructor (method)) {
+                                               if (insideConstructor && data.IsThis (this.parent.CurrentMethod, num2)) {
+                                                       if (TypesEqualModuloInstantiation (declaringType, MetaDataProvider.DeclaringType (this.parent.CurrentMethod)))
+                                                               havocReadonlyFields = true;
+                                                       else
+                                                               continue;
+                                               }
+                                               if (MetaDataProvider.IsStruct (declaringType))
+                                                       materialize = true;
+                                       }
+                               } else if (index2 < parameters.Count) {
+                                       if (data.IsThis (this.parent.CurrentMethod, num2))
+                                               nonFirstThis = true;
+                                       Parameter p = parameters [index2];
+                                       materialize = MetaDataProvider.IsOut (p);
+                                       ype = MetaDataProvider.ParameterType (p);
+                                       if (unspecializedParameters != null) {
+                                               TypeNode unspecType = MetaDataProvider.ParameterType (unspecializedParameters [index2]);
+                                               parameterHasGenericType = MetaDataProvider.IsFormalTypeParameter (unspecType) || MetaDataProvider.IsMethodFormalTypeParameter (unspecType);
+                                       }
+                                       ++index2;
+                               } else if (!data.IsThis (this.parent.CurrentMethod, num2))
+                                       ype = extraVarargs [index1 - index2 - num1];
+                               else
+                                       continue;
+                               if (!pc.InsideContract) {
+                                       bool havocFields = AggressiveUpHavocMethod (method);
+                                       if (havocFields || materialize || MustHavocParameter (method, declaringType, ype, parameterHasGenericType, nonFirstThis)) {
+                                               SymValue loc = data.Value (num2);
+                                               if (derefThis && index1 == 0 && num1 == 1)
+                                                       loc = data.Value (loc);
+                                               data.HavocObjectAtCall (loc, ref data.ModifiedAtCall, havocFields, havocReadonlyFields);
+                                               if (materialize)
+                                                       data.MaterializeAccordingToType (loc, ype, 0);
+                                       }
+                               }
+                               data.Havoc (num2);
+                       }
+               }
+
+               private bool MustHavocParameter (Method method, TypeNode declaringType, TypeNode pt, bool parameterHasGenericType, bool nonFirstThis)
+               {
+                       if (parameterHasGenericType || MetaDataProvider.IsStruct (pt) || MetaDataProvider.Equal (declaringType, MetaDataProvider.System_Object) ||
+                           IsImmutable (pt) || nonFirstThis || MetaDataProvider.Equal (pt, MetaDataProvider.System_Object))
+                               return false;
+
+                       return true;
+               }
+
+               private bool IsImmutable (TypeNode pt)
+               {
+                       return MetaDataProvider.Equal (pt, MetaDataProvider.System_String);
+               }
+
+               private bool AggressiveUpHavocMethod (Method method)
+               {
+                       if (MetaDataProvider.Name (MetaDataProvider.DeclaringType (method)) != "Monitor")
+                               return false;
+                       string name = MetaDataProvider.Name (method);
+
+                       return (name == "Exit" || name == "Wait");
+               }
+
+               private bool TypesEqualModuloInstantiation (TypeNode a, TypeNode b)
+               {
+                       a = MetaDataProvider.Unspecialized (a);
+                       b = MetaDataProvider.Unspecialized (b);
+                       return MetaDataProvider.Equal (a, b);
+               }
+
+               private SymValue KeyForPureFunctionArgument (Method method, int index, int arg, Domain data, IImmutableMap<TypeNode, TypeNode> specialization, out bool isOut)
+               {
+                       bool isByRef;
+                       TypeNode type;
+                       bool isPrimitive;
+                       if (!ParameterHasValueRepresentation (method, index, specialization, out isPrimitive, out isOut, out isByRef, out type))
+                               return data.StructId (isByRef ? data.Value (arg) : data.Address (arg));
+                       SymValue sv = data.Value (arg);
+                       if (isByRef)
+                               sv = data.Value (sv);
+                       return isPrimitive || IsImmutableType (type) ? sv : data.ObjectVersion (sv);
+               }
+
+               private bool ParameterHasValueRepresentation (Method method, int index, IImmutableMap<TypeNode, TypeNode> specialization, out bool isPrimitive, out bool isOut, out bool isByRef, out TypeNode type)
+               {
+                       if (index == 0 && !MetaDataProvider.IsStatic (method)) {
+                               isOut = false;
+                               type = MetaDataProvider.DeclaringType (method);
+                               isPrimitive = MetaDataProvider.IsPrimitive (type);
+                               bool hasValueRepresentation = MetaDataProvider.HasValueRepresentation (type);
+                               isByRef = (isPrimitive || !hasValueRepresentation);
+                               return hasValueRepresentation;
+                       }
+
+                       int paramIndex = MetaDataProvider.IsStatic (method) ? index : (index - 1);
+                       Parameter p = MetaDataProvider.Parameters (method) [paramIndex];
+                       type = MetaDataProvider.ParameterType (p);
+                       type = Specialize (specialization, type);
+                       isOut = MetaDataProvider.IsOut (p);
+                       if (isByRef = MetaDataProvider.IsManagedPointer (type))
+                               type = MetaDataProvider.ElementType (type);
+
+                       isPrimitive = MetaDataProvider.IsPrimitive (type);
+                       return MetaDataProvider.HasValueRepresentation (type);
+               }
+
+               private bool IsImmutableType (TypeNode type)
+               {
+                       //todo: implement
+                       return false;
+               }
+
+               private int GetNonOutArgs (Method method)
+               {
+                       int res = MetaDataProvider.IsStatic (method) ? 1 : 0;
+                       IIndexable<Parameter> parameters = MetaDataProvider.Parameters (method);
+                       for (int i = 0; i < parameters.Count; ++i) {
+                               if (!MetaDataProvider.IsOut (parameters [i]))
+                                       ++res;
+                       }
+
+                       return res;
+               }
+
+               private void AssignAllOutParameters<ArgList> (Domain data, SymValue fieldAddr, Method method, ArgList args)
+                       where ArgList : IIndexable<int>
+               {
+                       int index = 0;
+
+                       if (!MetaDataProvider.IsStatic (method))
+                               ++index;
+                       IIndexable<Parameter> parameters = MetaDataProvider.Parameters (method);
+                       for (; index < parameters.Count; index++) {
+                               Parameter p = parameters [index];
+                               if (MetaDataProvider.IsOut (p)) {
+                                       TypeNode pType = MetaDataProvider.ParameterType (p);
+                                       SymValue srcAddr = data.PseudoFieldAddressOfOutParameter (index, fieldAddr, pType);
+                                       SymValue destAddr = data.Value (args [index]);
+                                       data.CopyValue (destAddr, srcAddr, pType);
+                               }
+                       }
+               }
+
+               private TypeNode Specialize (IImmutableMap<TypeNode, TypeNode> instantiationMap, TypeNode declaringType)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               private void DevirtualizeImplementingMethod (TypeNode declaringType, ref Method method)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               private IImmutableMap<TypeNode, TypeNode> ComputeTypeInstantiationMap (APC pc, Method method)
+               {
+                       IImmutableMap<TypeNode, TypeNode> specialization = ImmutableMap<TypeNode, TypeNode>.Empty;
+                       foreach (var edge in pc.SubroutineContext.AsEnumerable ()) {
+                               Method calledMethod;
+                               bool isVirtual;
+                               bool isNewObj;
+                               if (edge.From.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual))
+                                       MetaDataProvider.IsSpecialized (calledMethod, ref specialization);
+                               else if (edge.To.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual))
+                                       MetaDataProvider.IsSpecialized (calledMethod, ref specialization);
+                       }
+                       return specialization;
+               }
+
+               private Domain CalliEffect<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool isInstance, int dest, int functionPointer, ArgList args, Domain data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       for (int i = 0; i < args.Count; i++) {
+                               int num = args [i];
+                               TypeNode type;
+                               if (isInstance) {
+                                       if (i > 0)
+                                               type = argTypes [i - 1];
+                                       else {
+                                               SymValue sv = data.Value (num);
+                                               AbstractType aType = data.GetType (sv);
+                                               type = aType.IsNormal ? aType.ConcreteType : MetaDataProvider.System_Object;
+                                       }
+                               } else
+                                       type = argTypes [i];
+                               if (!MetaDataProvider.IsStruct (type)) {
+                                       data.ResetModifiedAtCall ();
+                                       data.HavocObjectAtCall (data.Value (num), ref data.ModifiedAtCall, false, false);
+                               }
+                               data.Havoc (num);
+                       }
+                       data.AssignValue (dest, returnType);
+                       return data;
+               }
+
+               private void LoadArgAddressEffect (Parameter p, bool isOld, int dest, Domain data)
+               {
+                       SymValue srcAddr = isOld ? data.OldValueAddress (p) : data.Address (p);
+                       data.CopyAddress (data.Address (dest), srcAddr, MetaDataProvider.ManagedPointer (MetaDataProvider.ParameterType (p)));
+               }
+
+               private void LoadLocalAddressEffect (Local local, int dest, Domain data)
+               {
+                       data.CopyAddress (data.Address (dest), data.Address (local), MetaDataProvider.ManagedPointer (MetaDataProvider.LocalType (local)));
+               }
+
+               private void BoxEffect (TypeNode type, int dest, int source, Domain data)
+               {
+                       if (MetaDataProvider.IsReferenceType (type))
+                               data.Copy (dest, source);
+                       else {
+                               SymValue srcAddr = data.Address (source);
+                               TypeNode systemObject = MetaDataProvider.System_Object;
+                               SymValue specialUnary = data.GetSpecialUnary (data.Functions.BoxOperator, source, systemObject);
+                               data.SetValue (specialUnary, srcAddr, MetaDataProvider.ManagedPointer (type), false);
+                               data.AssignSpecialUnary (dest, specialUnary, systemObject);
+                       }
+               }
+
+               private void CastClassEffect (TypeNode type, int dest, int obj, Domain data)
+               {
+                       SymValue destAddr = data.Address (dest);
+                       TypeNode mp = MetaDataProvider.ManagedPointer (type);
+                       data.CopyValueAndCast (destAddr, data.Address (obj), mp);
+               }
+
+               private void LoadElementEffect (TypeNode type, int dest, int array, int index, Domain data)
+               {
+                       TypeNode t = type;
+                       if (!MetaDataProvider.IsStruct (type)) {
+                               SymValue sv = data.Value (array);
+                               AbstractType aType = data.GetType (sv);
+                               if (aType.IsNormal && MetaDataProvider.IsArray (aType.ConcreteType)) {
+                                       t = MetaDataProvider.ElementType (aType.ConcreteType);
+                                       if (t == null)
+                                               t = type;
+                               }
+                       }
+                       TypeNode elementAddressType = MetaDataProvider.ManagedPointer (t);
+                       data.CopyValue (data.Address (dest), data.ElementAddress (data.Value (array), data.Value (index), elementAddressType), elementAddressType);
+                       data.Havoc (index);
+               }
+
+               private void LoadFieldEffect (Field field, int dest, int obj, Domain data)
+               {
+                       SymValue ptr;
+                       if (MetaDataProvider.IsStruct (MetaDataProvider.DeclaringType (field))) {
+                               AbstractType abstractType = data.GetType (data.Address (obj));
+                               ptr = abstractType.IsNormal
+                                     && MetaDataProvider.IsManagedPointer (abstractType.ConcreteType)
+                                     && MetaDataProvider.IsStruct (MetaDataProvider.ElementType (abstractType.ConcreteType))
+                                       ? data.Address (obj)
+                                       : data.Value (obj);
+                       } else
+                               ptr = data.Value (obj);
+                       TypeNode fieldAddressType;
+                       SymValue srcAddr = data.FieldAddress (ptr, field, out fieldAddressType);
+                       data.CopyValue (data.Address (dest), srcAddr, fieldAddressType);
+               }
+
+               private void LoadFieldAddressEffect (APC pc, Field field, int dest, int obj, Domain data)
+               {
+                       SymValue sv = data.Value (obj);
+                       TypeNode fieldAddressType;
+                       SymValue srcAddr = data.FieldAddress (sv, field, out fieldAddressType);
+                       data.CopyAddress (data.Address (dest), srcAddr, fieldAddressType);
+                       if (!pc.InsideContract && MetaDataProvider.Equal (MetaDataProvider.DeclaringType (this.parent.CurrentMethod), MetaDataProvider.Unspecialized (MetaDataProvider.DeclaringType (field))))
+                               data.HavocPseudoFields (this.parent.StackContextProvider.MethodContext.AffectedGetters (field), sv);
+               }
+
+               private void LoadLengthEffect (int dest, int array, Domain data)
+               {
+                       data.AssignArrayLength (data.Address (dest), data.Value (array));
+               }
+
+               private void LoadStaticFieldEffect (Field field, int dest, Domain data)
+               {
+                       TypeNode fieldAddressType;
+                       SymValue srcAddr = data.FieldAddress (data.Globals, field, out fieldAddressType);
+                       data.CopyValue (data.Address (dest), srcAddr, fieldAddressType);
+               }
+
+               private void LoadStaticFieldAddressEffect (Field field, int dest, Domain data)
+               {
+                       TypeNode fieldAddressType;
+                       SymValue srcAddr = data.FieldAddress (data.Globals, field, out fieldAddressType);
+                       data.CopyAddress (data.Address (dest), srcAddr, fieldAddressType);
+               }
+
+               private void NewArrayEffect<T> (TypeNode type, int dest, IIndexable<int> list, Domain data)
+               {
+                       if (list.Count == 1) {
+                               SymValue array = data.CreateArray (type, data.Value (list [0]));
+                               data.CopyAddress (data.Address (dest), array, MetaDataProvider.ArrayType (type, 1));
+                       } else
+                               data.AssignValue (dest, type);
+               }
+
+               private void NewObjEffect<ArgList> (APC pc, Method ctor, int dest, ArgList args, Domain data)
+                       where ArgList : IIndexable<int>
+               {
+                       for (int i = 0; i < args.Count; ++i)
+                               data.Havoc (args [i]);
+
+                       TypeNode declaringType = MetaDataProvider.DeclaringType (ctor);
+                       if (MetaDataProvider.IsStruct (declaringType)) {
+                               SymValue srcAddr = data.CreateValue (declaringType);
+                               data.MaterializeAccordingToType (srcAddr, MetaDataProvider.ManagedPointer (declaringType), 0);
+                               HavocParameters (pc, ctor, Indexable<TypeNode>.Empty, args, data, declaringType, false, true, false);
+                               data.CopyValue (data.Address (dest), srcAddr, MetaDataProvider.ManagedPointer (declaringType));
+                               return;
+                       }
+
+                       SymValue sv = data.CreateObject (declaringType);
+                       HavocParameters (pc, ctor, Indexable<TypeNode>.Empty, args, data, declaringType, false, true, false);
+                       data.CopyAddress (data.Address (dest), sv, declaringType);
+               }
+
+               private void StoreElementEffect (TypeNode type, int array, int index, int value, Domain data)
+               {
+                       TypeNode elementAddressType = MetaDataProvider.ManagedPointer (type);
+                       SymValue arrayValue = data.Value (array);
+                       SymValue indexValue = data.Value (index);
+                       data.HavocArrayAtIndex (arrayValue, indexValue);
+                       data.CopyValue (data.ElementAddress (arrayValue, indexValue, elementAddressType), data.Address (value), elementAddressType);
+                       data.Havoc (array);
+                       data.Havoc (index);
+                       data.Havoc (value);
+               }
+
+               public static Domain FindOldState (APC pc, Domain data)
+               {
+                       for (LispList<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));
+                       }
+                       return null;
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..c288957
--- /dev/null
@@ -0,0 +1,1635 @@
+// 
+// Domain.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.IO;
+using System.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class Domain : IAbstractDomain<Domain> {
+               private static Domain BottomValue;
+               public readonly FunctionsTable Functions;
+               private readonly Dictionary<APC, Domain> begin_old_saved_states;
+               private readonly SymGraph<SymFunction, AbstractType> egraph;
+               private readonly HeapAnalysis parent;
+               private TypeCache IEnumerable1Type = new TypeCache (@"System.Collections.IEnumerable`1");
+               private TypeCache IEnumerableType = new TypeCache (@"System.Collections.IEnumerable");
+               public int InsideOld;
+               public IImmutableSet<SymValue> ModifiedAtCall;
+               private IImmutableMap<SymValue, SymFunction> constantLookup;
+               private IImmutableSet<SymValue> unmodifiedFieldsSinceEntry;
+               private IImmutableSet<SymValue> unmodifiedSinceEntry;
+
+               private Domain (SymGraph<SymFunction, AbstractType> newEgraph,
+                               IImmutableMap<SymValue, SymFunction> constantMap,
+                               IImmutableSet<SymValue> unmodifiedSinceEntry, IImmutableSet<SymValue> unmodifiedFieldsSinceEntry, IImmutableSet<SymValue> modifiedAtCall,
+                               Domain from, Domain oldDomain)
+               {
+                       this.egraph = newEgraph;
+                       this.Functions = from.Functions;
+                       this.parent = from.parent;
+                       this.begin_old_saved_states = from.begin_old_saved_states;
+                       this.constantLookup = constantMap;
+                       this.unmodifiedSinceEntry = unmodifiedSinceEntry;
+                       this.unmodifiedFieldsSinceEntry = unmodifiedFieldsSinceEntry;
+                       this.ModifiedAtCall = modifiedAtCall;
+                       this.InsideOld = from.InsideOld;
+                       OldDomain = oldDomain;
+                       BeginOldPC = from.BeginOldPC;
+               }
+
+               public Domain (HeapAnalysis parent)
+               {
+                       this.parent = parent;
+                       this.egraph = new SymGraph<SymFunction, AbstractType> (AbstractType.TopValue, AbstractType.BottomValue);
+                       this.constantLookup = ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey);
+                       this.unmodifiedSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       this.unmodifiedFieldsSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       this.ModifiedAtCall = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       this.Functions = new FunctionsTable (parent.MetaDataProvider);
+                       this.begin_old_saved_states = new Dictionary<APC, Domain> ();
+
+                       SymValue nullValue = this.egraph.FreshSymbol ();
+                       this.egraph [this.Functions.NullValue] = nullValue;
+                       this.egraph [nullValue] = AbstractType.BottomValue;
+                       this.egraph [ConstantValue (0, MetaDataProvider.System_Int32)] = new AbstractType (MetaDataProvider.System_Int32, true);
+               }
+
+               public Domain OldDomain { get; set; }
+               public APC BeginOldPC { get; set; }
+
+               public SymValue Globals
+               {
+                       get { return this.egraph.ConstRoot; }
+               }
+
+               private SymValue Null
+               {
+                       get { return this.egraph [this.Functions.NullValue]; }
+               }
+
+               private SymValue Zero
+               {
+                       get { return this.egraph [this.Functions.ZeroValue]; }
+               }
+
+               public SymValue VoidAddr
+               {
+                       get { return this.egraph [this.Functions.VoidAddr]; }
+               }
+
+               private IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.parent.MetaDataProvider; }
+               }
+
+               public IEnumerable<SymValue> Variables
+               {
+                       get { return this.egraph.Variables; }
+               }
+
+               #region IAbstractDomain<Domain> Members
+               public void Dump (TextWriter tw)
+               {
+                       this.egraph.Dump (tw);
+                       tw.WriteLine ("Unmodified locations:");
+                       foreach (SymValue sv in this.unmodifiedSinceEntry.Elements)
+                               tw.Write ("{0} ", sv);
+                       tw.WriteLine ();
+
+                       tw.WriteLine ("Unmodified locations for fields:");
+                       foreach (SymValue sv in this.unmodifiedFieldsSinceEntry.Elements)
+                               tw.Write ("{0} ", sv);
+                       tw.WriteLine ();
+
+                       if (this.ModifiedAtCall != null) {
+                               tw.WriteLine ("Modified locations at last call");
+                               foreach (SymValue sv in this.ModifiedAtCall.Elements)
+                                       tw.Write ("{0} ", sv);
+                               tw.WriteLine ();
+                       }
+                       if (OldDomain == null)
+                               return;
+
+                       tw.WriteLine ("## has old domain ##");
+                       OldDomain.egraph.Dump (tw);
+                       tw.WriteLine ("## end old domain ##");
+               }
+
+               public Domain Clone ()
+               {
+                       return new Domain (this.egraph.Clone (), this.constantLookup, this.unmodifiedSinceEntry, this.unmodifiedFieldsSinceEntry, this.ModifiedAtCall, this, OldDomain == null ? null : OldDomain.Clone ());
+               }
+               #endregion
+
+               public static bool IsRootedInParameter (LispList<PathElement> path)
+               {
+                       return path.Head is PathElement<Parameter>;
+               }
+
+               public SymValue Address (Local local)
+               {
+                       SymFunction function = this.Functions.For (local);
+                       SymValue sv = this.egraph.TryLookup (function);
+                       if (sv == null) {
+                               sv = this.egraph [function];
+                               SetType (sv, MetaDataProvider.ManagedPointer (MetaDataProvider.LocalType (local)));
+                       }
+                       return sv;
+               }
+
+               public SymValue Address (Parameter v)
+               {
+                       SymFunction function = this.Functions.For (v);
+                       SymValue sv = this.egraph.TryLookup (function);
+                       if (sv == null) {
+                               sv = this.egraph [function];
+                               SetType (sv, MetaDataProvider.ManagedPointer (MetaDataProvider.ParameterType (v)));
+                       }
+                       return sv;
+               }
+
+               public SymValue Address (SymFunction v)
+               {
+                       return this.egraph [v];
+               }
+
+               public SymValue Address (int v)
+               {
+                       return Address (this.Functions.For (v));
+               }
+
+               public void AssignConst (int dest, TypeNode type, object constant)
+               {
+                       AssignConst (Address (this.Functions.For (dest)), type, constant);
+               }
+
+               public void AssignConst (SymValue address, TypeNode type, object constant)
+               {
+                       SymValue value = ConstantValue (constant, type);
+                       SetType (address, MetaDataProvider.ManagedPointer (type));
+                       this.egraph [this.Functions.ValueOf, address] = value;
+
+                       var str = constant as string;
+                       if (str != null)
+                               this.egraph [this.Functions.Length, value] = ConstantValue (str.Length, MetaDataProvider.System_Int32);
+               }
+
+               public void AssignValue (int dest, FlatDomain<TypeNode> type)
+               {
+                       AssignValue (Address (this.Functions.For (dest)), type);
+               }
+
+               private void AssignValue (SymValue address, FlatDomain<TypeNode> type)
+               {
+                       Havoc (address);
+                       SetType (address, type.IsNormal ? MetaDataProvider.ManagedPointer (type.Concrete) : type);
+                       if (IsStructWithFields (type))
+                               return;
+
+                       SymValue fresh = this.egraph.FreshSymbol ();
+                       SetType (fresh, type);
+                       this.egraph [this.Functions.ValueOf, address] = fresh;
+
+                       if (!type.IsNormal)
+                               return;
+
+                       if (NeedsArrayLengthManifested (type.Concrete))
+                               ManifestArrayLength (fresh);
+               }
+
+               public void AssignNull (int addr)
+               {
+                       AssignNull (Address (this.Functions.For (addr)));
+               }
+
+               public void AssignNull (SymValue addr)
+               {
+                       Havoc (addr);
+                       this.egraph [this.Functions.ValueOf, addr] = Null;
+               }
+
+               private void AssignZero (SymValue addr)
+               {
+                       this.egraph [this.Functions.ValueOf, addr] = Zero;
+               }
+
+               public void AssignZeroEquivalent (SymValue addr, TypeNode t)
+               {
+                       if (MetaDataProvider.IsReferenceType (t))
+                               AssignNull (addr);
+                       else if (MetaDataProvider.HasValueRepresentation (t))
+                               AssignZero (addr);
+               }
+
+               public void AssignSpecialUnary (int dest, SymFunction op, int source, FlatDomain<TypeNode> typeOfValue)
+               {
+                       SymValue specialUnary = GetSpecialUnary (op, source, typeOfValue);
+                       AssignSpecialUnary (dest, specialUnary, typeOfValue);
+               }
+
+               public void AssignSpecialUnary (int dest, SymValue result, FlatDomain<TypeNode> typeOfValue)
+               {
+                       SymValue address = Address (dest);
+                       AssignValue (address, typeOfValue);
+                       this.egraph [this.Functions.ValueOf, address] = result;
+               }
+
+               public void AssignPureBinary (int dest, BinaryOperator op, FlatDomain<TypeNode> typeOpt, int op1, int op2)
+               {
+                       var args = new[] {Value (op1), Value (op2)};
+                       SymFunction c = this.Functions.For (op);
+                       TypeNode type = !typeOpt.IsNormal ? MetaDataProvider.System_Int32 : typeOpt.Concrete;
+
+                       bool fresh;
+
+                       SymValue pointerValue = LookupAddressAndManifestType (args, c, type, out fresh);
+                       SymValue destAddr = Address (dest);
+
+                       SetType (destAddr, MetaDataProvider.ManagedPointer (type));
+                       this.egraph [this.Functions.ValueOf, destAddr] = pointerValue;
+               }
+
+               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;
+
+                       SymValue unaryOperand = this.egraph [c, Value (operand)];
+                       SymValue sv = Address (dest);
+
+                       SetType (sv, MetaDataProvider.ManagedPointer (type));
+                       this.egraph [this.Functions.ValueOf, sv] = unaryOperand;
+               }
+
+               private SymValue ConstantValue (object constant, TypeNode type)
+               {
+                       SymFunction symFunction = this.Functions.ForConstant (constant, type);
+                       SymValue sv = this.egraph.TryLookup (symFunction);
+                       if (sv == null) {
+                               sv = this.egraph [symFunction];
+                               SetType (sv, type);
+                               this.constantLookup = this.constantLookup.Add (sv, symFunction);
+                       }
+                       return sv;
+               }
+
+               public void Havoc (int i)
+               {
+                       Havoc (Address (i));
+               }
+
+               public void Havoc (SymValue addr)
+               {
+                       this.egraph.EliminateAll (addr);
+               }
+
+               private void HavocIfStruct (SymValue address)
+               {
+                       AbstractType aType = this.egraph [address];
+                       if (aType.IsBottom || (aType.IsNormal && MetaDataProvider.IsStruct (aType.ConcreteType)))
+                               Havoc (address);
+               }
+
+               private void HavocMutableFields (SymFunction except, SymValue address, ref IImmutableSet<SymValue> havoced)
+               {
+                       HavocFields (except, address, ref havoced, false);
+               }
+
+               private void HavocFields (SymFunction except, SymValue address, ref IImmutableSet<SymValue> havoced, bool havocImmutable)
+               {
+                       if (havoced.Contains (address))
+                               return;
+
+                       havoced = havoced.Add (address);
+                       MakeTotallyModified (address);
+                       foreach (SymFunction c in this.egraph.Functions (address))
+                               HavocConstructor (except, address, c, ref havoced, havocImmutable);
+               }
+
+               private void HavocConstructor (SymFunction except, SymValue address, SymFunction c, ref IImmutableSet<SymValue> havoced, bool havocImmutable)
+               {
+                       if (c == this.Functions.ValueOf)
+                               this.egraph [this.Functions.OldValueOf, address] = this.egraph [c, address];
+                       if (c == this.Functions.ValueOf || c == this.Functions.ObjectVersion || c == this.Functions.StructId) {
+                               this.egraph.Eliminate (c, address);
+                               havoced = havoced.Add (address);
+                       } else {
+                               var fieldWrapper = c as Wrapper<Field>;
+                               if (fieldWrapper != null && fieldWrapper != except) {
+                                       if (havocImmutable || !MetaDataProvider.IsReadonly (fieldWrapper.Item))
+                                               HavocFields (except, this.egraph [c, address], ref havoced, havocImmutable);
+
+                                       return;
+                               }
+
+                               var methodWrapper = c as Wrapper<Method>;
+                               if (methodWrapper != null && methodWrapper != except)
+                                       HavocFields (except, this.egraph [c, address], ref havoced, havocImmutable);
+                       }
+               }
+
+               public void HavocPseudoFields (SymValue address)
+               {
+                       IImmutableSet<SymValue> havoced = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       HavocPseudoFields (null, address, ref havoced);
+               }
+
+               private void HavocPseudoFields (SymFunction except, SymValue address, ref IImmutableSet<SymValue> havoced)
+               {
+                       if (havoced.Contains (address))
+                               return;
+                       havoced = havoced.Add (address);
+                       if (IsUnmodified (address)) {
+                               MakeModified (address);
+                               MakeUnmodifiedField (address);
+                       }
+                       this.egraph.Eliminate (this.Functions.ObjectVersion, address);
+                       this.egraph.Eliminate (this.Functions.StructId, address);
+                       foreach (SymFunction c in this.egraph.Functions (address)) {
+                               if (c != except && c is Wrapper<Method>)
+                                       HavocMutableFields (except, this.egraph [c, address], ref havoced);
+                       }
+               }
+
+               private void HavocPseudoFields (SymFunction except, IEnumerable<Method> getters, SymValue address, ref IImmutableSet<SymValue> havoced)
+               {
+                       if (havoced.Contains (address))
+                               return;
+                       havoced = havoced.Add (address);
+                       if (IsUnmodified (address)) {
+                               MakeModified (address);
+                               MakeUnmodifiedField (address);
+                       }
+                       this.egraph.Eliminate (this.Functions.ObjectVersion, address);
+                       this.egraph.Eliminate (this.Functions.StructId, address);
+                       foreach (Method m in getters)
+                               HavocMutableFields (except, this.egraph [this.Functions.For (m), address], ref havoced);
+               }
+
+               public void HavocPseudoFields (IEnumerable<Method> getters, SymValue address)
+               {
+                       IImmutableSet<SymValue> havoced = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       HavocPseudoFields (null, getters, address, ref havoced);
+               }
+
+               private void MakeUnmodifiedField (SymValue address)
+               {
+                       this.unmodifiedFieldsSinceEntry = this.unmodifiedFieldsSinceEntry.Add (address);
+               }
+
+               private void MakeModified (SymValue address)
+               {
+                       this.unmodifiedSinceEntry = this.unmodifiedSinceEntry.Remove (address);
+               }
+
+               public void CopyValue (SymValue destAddr, SymValue sourceAddr)
+               {
+                       AbstractType type = this.egraph [sourceAddr];
+                       CopyValue (destAddr, sourceAddr, type.Type);
+               }
+
+               public void CopyValue (SymValue destAddr, SymValue sourceAddr, FlatDomain<TypeNode> addrType)
+               {
+                       CopyValue (destAddr, sourceAddr, addrType, true, false);
+               }
+
+               private void CopyValue (SymValue destAddr, SymValue sourceAddr, FlatDomain<TypeNode> addrType, bool setTargetAddrType, bool cast)
+               {
+                       MakeTotallyModified (destAddr);
+                       if (destAddr != sourceAddr)
+                               HavocIfStruct (destAddr);
+                       if (setTargetAddrType)
+                               SetType (destAddr, addrType);
+
+                       SetValue (destAddr, sourceAddr, addrType, cast);
+               }
+
+               public void CopyOldValue (APC pc, int dest, int source, Domain target, bool atEndOld)
+               {
+                       CopyOldValue (pc, target.Address (dest), Address (source), target, atEndOld);
+               }
+
+               public void CopyOldValue (APC pc, SymValue destAddr, SymValue srcAddr, Domain target, bool atEndOld)
+               {
+                       AbstractType abstractType = this.egraph [srcAddr];
+                       CopyOldValue (pc, destAddr, srcAddr, abstractType.Type, target, atEndOld);
+               }
+
+               private void CopyOldValue (APC pc, SymValue destAddr, SymValue srcAddr, FlatDomain<TypeNode> addrType, Domain target, bool atEndOld)
+               {
+                       CopyOldValue (pc, destAddr, srcAddr, addrType, true, atEndOld, target);
+               }
+
+               private void CopyOldValue (APC pc, SymValue destAddr, SymValue srcAddr, FlatDomain<TypeNode> addrType, bool setTargetAddrType, bool atEndOld, Domain target)
+               {
+                       target.MakeTotallyModified (destAddr);
+                       if (destAddr != srcAddr)
+                               target.HavocIfStruct (destAddr);
+                       if (setTargetAddrType)
+                               target.SetType (destAddr, addrType);
+
+                       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)) {
+                               srcAddr = TryValue (srcAddr);
+                               if (srcAddr == null)
+                                       return;
+                               destAddr = target.Value (destAddr);
+                               CopyOldValue (pc, destAddr, srcAddr, targetType, setTargetAddrType, atEndOld, target);
+                       } else {
+                               SymValue source = this.egraph.TryLookup (this.Functions.ValueOf, srcAddr);
+                               if (source == null) {
+                                       if (this.egraph.IsImmutable)
+                                               return;
+                                       source = this.egraph [this.Functions.ValueOf, srcAddr];
+                               }
+                               CopyOldValueToDest (pc, destAddr, source, addrType, target);
+                       }
+               }
+
+               public void CopyOldValueToDest (APC pc, SymValue destAddr, SymValue source, FlatDomain<TypeNode> addrType, Domain target)
+               {
+                       if (pc.InsideEnsuresAtCall) {
+                               TypeNode type;
+                               object constant;
+
+                               if (IsConstant (source, out type, out constant)) {
+                                       SymValue sv = target.ConstantValue (constant, type);
+                                       target.CopyNonStructWithFieldValue (destAddr, sv, addrType);
+                                       return;
+                               }
+
+                               foreach (var sv in GetAccessPathsRaw (source, AccessPathFilter<Method>.NoFilter, false))
+                                       throw new NotImplementedException ();
+                       }
+               }
+
+               private IEnumerable<LispList<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)
+               {
+                       if (sv == this.egraph.ConstRoot)
+                               yield return path;
+                       else if (!visited.Contains (sv)) {
+                               visited.Add (sv);
+                               foreach (var term in this.egraph.EqTerms (sv)) {
+                                       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;
+
+                                                       if (path == null || !compress || (!(next is PathElement<Method>)))
+                                                               newPath = path.Cons (next);
+                                                       else
+                                                               newPath = path.Tail.Cons (next);
+
+                                                       foreach (var item in GetAccessPathsRaw (term.Args [0], newPath, visited, filter, compress))
+                                                               yield return item;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               private LispList<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;
+
+                       foreach (var path in GetAccessPathsFiltered (sv, filter, compress)) {
+                               if (path != null) {
+                                       if (path.Head is PathElement<Parameter>) {
+                                               if (bestParameterPath == null || bestParameterPath.Length () > path.Length ())
+                                                       bestParameterPath = path;
+                                       } else if (filter.AllowLocal && allowLocal && path.Head is PathElement<Local>) {
+                                               if (!path.Head.ToString ().Contains ("$") && (bestLocalPath == null || bestLocalPath.Length () > path.Length ()))
+                                                       bestLocalPath = path;
+                                       } else if (path.Head is PathElement<Field> && path.Head.Func.IsStatic) {
+                                               if (bestFieldMethodPath == null || bestFieldMethodPath.Length () > path.Length ())
+                                                       bestFieldMethodPath = path;
+                                       } else if (path.Head is PathElement<Method> && path.Head.Func.IsStatic) {
+                                               if (bestFieldMethodPath == null || bestFieldMethodPath.Length () > path.Length ())
+                                                       bestFieldMethodPath = path;
+                                       }
+                               }
+                       }
+                       if (preferLocal && bestLocalPath != null)
+                               return bestLocalPath;
+                       if (bestParameterPath != null)
+                               return bestParameterPath;
+                       if (allowLocal && bestLocalPath != null)
+                               return bestLocalPath;
+
+                       return bestFieldMethodPath;
+               }
+
+               public IEnumerable<LispList<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)
+               {
+                       if (path.Length () == 0 || !filter.HasVisibilityMember)
+                               return true;
+
+                       Method visibilityMember = filter.VisibilityMember;
+                       TypeNode t = MetaDataProvider.DeclaringType (visibilityMember);
+                       TypeNode type = default(TypeNode);
+
+                       while (path != null) {
+                               PathElement pathElement = path.Head;
+                               if (!pathElement.TryGetResultType (out type))
+                                       return true;
+                               while (MetaDataProvider.IsManagedPointer (type))
+                                       type = MetaDataProvider.ElementType (type);
+                               if ("this" != pathElement.ToString ()) {
+                                       var peMethod = pathElement as PathElement<Method>;
+                                       if (peMethod != null) {
+                                               Method method = peMethod.Element;
+                                               if (!MetaDataProvider.IsVisibleFrom (method, t))
+                                                       return false;
+                                       }
+
+                                       var peProperty = pathElement as PathElement<Property>;
+                                       if (peProperty != null) {
+                                               Property property = peProperty.Element;
+                                               Method method;
+                                               if (!MetaDataProvider.HasGetter (property, out method))
+                                                       MetaDataProvider.HasSetter (property, out method);
+
+                                               if (!MetaDataProvider.IsVisibleFrom (method, t))
+                                                       return false;
+                                       }
+
+                                       var peField = pathElement as PathElement<Field>;
+                                       if (peField != null) {
+                                               Field field = peField.Element;
+                                               if (!MetaDataProvider.IsVisibleFrom (field, t))
+                                                       return false;
+                                       }
+                               }
+                               path = path.Tail;
+                       }
+                       return true;
+               }
+
+               private bool TryPropagateTypeInfo (LispList<PathElementBase> path, out LispList<PathElementBase> result)
+               {
+                       if (path == null) {
+                               result = null;
+                               return true;
+                       }
+                       PathElementBase head = path.Head;
+                       TypeNode prevType;
+                       if (!head.TrySetType (MetaDataProvider.System_IntPtr, MetaDataProvider, out prevType)) {
+                               result = null;
+                               return false;
+                       }
+
+                       LispList<PathElementBase> result1;
+                       if (!TryPropagateTypeInfoRecurse (path.Tail, prevType, out result1)) {
+                               result = null;
+                               return false;
+                       }
+                       if (head.IsAddressOf && head is PathElement<Parameter> && result1 != null && result1.Head.IsDeref) {
+                               var pathElement = (PathElement<Parameter>) head;
+                               result = result1.Tail.Cons (new ParameterPathElement (pathElement.Element, pathElement.Description, pathElement.Func, MetaDataProvider));
+                               return true;
+                       }
+
+                       result = result1.Cons (head);
+                       return true;
+               }
+
+               private bool TryPropagateTypeInfoRecurse (LispList<PathElementBase> path, TypeNode prevType, out LispList<PathElementBase> result)
+               {
+                       if (path == null) {
+                               result = null;
+                               return true;
+                       }
+                       PathElementBase head = path.Head;
+                       if (head.TrySetType (prevType, MetaDataProvider, out prevType)) {
+                               LispList<PathElementBase> updatedPath;
+                               if (TryPropagateTypeInfoRecurse (path.Tail, prevType, out updatedPath)) {
+                                       result = updatedPath.Cons (head);
+                                       return true;
+                               }
+                       }
+
+                       result = null;
+                       return false;
+               }
+
+               private IEnumerable<LispList<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;
+                               if (TryPropagateTypeInfo (path, out result))
+                                       yield return result;
+                       }
+               }
+
+               private void CopyNonStructWithFieldValue (SymValue destAddr, SymValue sv, FlatDomain<TypeNode> addrType)
+               {
+                       this.egraph [this.Functions.ValueOf, destAddr] = sv;
+                       SetType (destAddr, addrType);
+               }
+
+               public bool IsConstant (SymValue source, out TypeNode type, out object constant)
+               {
+                       SymFunction c = this.constantLookup [source];
+                       if (c != null)
+                               return this.Functions.IsConstant (c, out type, out constant);
+
+                       type = default(TypeNode);
+                       constant = null;
+                       return false;
+               }
+
+               private void CopyOldStructValue (APC pc, SymValue destAddr, SymValue srcAddr, TypeNode type, Domain target, bool atEndOld)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public void SetValue (SymValue destAddr, SymValue sourceAddr, FlatDomain<TypeNode> addrType, bool cast)
+               {
+                       FlatDomain<TypeNode> type = TargetType (addrType);
+                       if (IsStructWithFields (type))
+                               CopyStructValue (destAddr, sourceAddr, type.Concrete);
+
+                       CopyPrimValue (destAddr, sourceAddr, cast, type);
+               }
+
+               private void CopyPrimValue (SymValue destAddr, SymValue sourceAddr, bool cast, FlatDomain<TypeNode> elementType)
+               {
+                       SymValue value = this.egraph [this.Functions.ValueOf, sourceAddr];
+                       if (cast)
+                               SetType (value, elementType);
+                       else
+                               SetTypeIfUnknown (value, elementType);
+
+                       if (elementType.IsNormal) {
+                               if (NeedsArrayLengthManifested (elementType.Concrete))
+                                       ManifestArrayLength (value);
+                       }
+
+                       this.egraph [this.Functions.ValueOf, destAddr] = value;
+               }
+
+               public void CopyValueToOldState (APC pc, TypeNode type, int dest, int source, Domain target)
+               {
+                       SymValue destAddress = target.Address (dest);
+                       SymValue srcAddress = Address (source);
+
+                       AbstractType aType = GetType (srcAddress);
+                       TypeNode addrType = aType.IsNormal ? aType.ConcreteType : MetaDataProvider.ManagedPointer (type);
+                       CopyValueToOldState (pc, addrType, destAddress, srcAddress, target);
+               }
+
+               private void CopyValueToOldState (APC pc, TypeNode addrType, SymValue destAddress, SymValue srcAddress, Domain target)
+               {
+                       target.MakeTotallyModified (destAddress);
+                       if (destAddress != srcAddress)
+                               target.HavocIfStruct (destAddress);
+                       target.SetType (destAddress, addrType);
+                       FlatDomain<TypeNode> targetType = TargetType (addrType);
+                       if (IsStructWithFields (targetType))
+                               CopyStructValueToOldState (pc, destAddress, srcAddress, targetType, target);
+                       else {
+                               SymValue sv = this.egraph.TryLookup (this.Functions.ValueOf, srcAddress);
+                               if (sv == null) {
+                                       if (this.egraph.IsImmutable)
+                                               return;
+                                       sv = this.egraph [this.Functions.ValueOf, srcAddress];
+                               }
+                               CopyPrimitiveValueToOldState (pc, addrType, destAddress, sv, target);
+                       }
+               }
+
+               private void CopyPrimitiveValueToOldState (APC pc, TypeNode addrType, SymValue destAddress, SymValue sv, Domain target)
+               {
+                       if (target.IsValidSymbol (sv))
+                               target.CopyNonStructWithFieldValue (destAddress, sv, addrType);
+                       else
+                               target.Assign (destAddress, addrType);
+               }
+
+               private bool IsValidSymbol (SymValue sv)
+               {
+                       return this.egraph.IsValidSymbol (sv);
+               }
+
+               private void Assign (SymValue destAddress, TypeNode addrType)
+               {
+                       Havoc (destAddress);
+                       SetType (destAddress, addrType);
+                       FlatDomain<TypeNode> targetType = TargetType (addrType);
+                       if (IsStructWithFields (targetType))
+                               return;
+
+                       SymValue fresh = this.egraph.FreshSymbol ();
+                       SetType (fresh, targetType);
+                       this.egraph [this.Functions.ValueOf, destAddress] = fresh;
+                       if (!targetType.IsNormal)
+                               return;
+
+                       if (NeedsArrayLengthManifested (targetType.Concrete))
+                               ManifestArrayLength (fresh);
+               }
+
+               private void CopyStructValueToOldState (APC pc, SymValue destAddress, SymValue srcAddress, FlatDomain<TypeNode> targetType, Domain target)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public void ManifestArrayLength (SymValue arrayValue)
+               {
+                       SetType (this.egraph [this.Functions.Length, arrayValue], MetaDataProvider.System_Int32);
+               }
+
+               public bool NeedsArrayLengthManifested (TypeNode type)
+               {
+                       return MetaDataProvider.IsArray (type) || MetaDataProvider.System_String.Equals (type);
+               }
+
+               public void CopyStructValue (SymValue destAddr, SymValue sourceAddr, TypeNode type)
+               {
+                       if (destAddr == null)
+                               return;
+                       this.egraph [this.Functions.StructId, destAddr] = this.egraph [this.Functions.StructId, sourceAddr];
+                       foreach (SymFunction function in this.egraph.Functions (sourceAddr)) {
+                               if (function.ActsAsField) {
+                                       TypeNode functionType = function.FieldAddressType ();
+                                       CopyValue (this.egraph [function, destAddr], this.egraph [function, sourceAddr], functionType);
+                               }
+                       }
+               }
+
+               public SymValue OldValueAddress (Parameter p)
+               {
+                       return Address (OldValueParameterConstructor (p));
+               }
+
+               private SymFunction OldValueParameterConstructor (Parameter argument)
+               {
+                       return this.Functions.For ("$OldParameter_" + MetaDataProvider.Name (argument));
+               }
+
+               public void CopyParameterIntoShadow (Parameter p)
+               {
+                       CopyValue (Address (OldValueParameterConstructor (p)), Address (this.Functions.For (p)));
+               }
+
+               public void Copy (int dest, int source)
+               {
+                       CopyValue (Address (this.Functions.For (dest)), Address (this.Functions.For (source)));
+               }
+
+               private bool IsIEnumerable (TypeNode type)
+               {
+                       TypeNode ienumerableType;
+                       return (this.IEnumerable1Type.TryGet (MetaDataProvider, out ienumerableType) && MetaDataProvider.DerivesFrom (type, ienumerableType)
+                               || this.IEnumerableType.TryGet (MetaDataProvider, out ienumerableType) && MetaDataProvider.DerivesFrom (type, ienumerableType));
+               }
+
+               public SymValue GetSpecialUnary (SymFunction op, int source, FlatDomain<TypeNode> type)
+               {
+                       SymValue value = Value (source);
+                       SymValue sv = this.egraph [op, value];
+                       SetType (sv, type);
+                       return sv;
+               }
+
+               private SymValue LookupAddressAndManifestType (SymValue[] args, SymFunction op, TypeNode type, out bool fresh)
+               {
+                       SymValue sv = this.egraph.TryLookup (op, args);
+                       if (sv != null) {
+                               fresh = false;
+                               return sv;
+                       }
+                       fresh = true;
+                       sv = this.egraph [op, args];
+                       SetType (sv, type);
+                       return sv;
+               }
+
+               public bool IsZero (SymValue symValue)
+               {
+                       return this.egraph [symValue].IsZero;
+               }
+
+               public SymValue Value (int v)
+               {
+                       return Value (Address (this.Functions.For (v)));
+               }
+
+               public SymValue Value (SymValue address)
+               {
+                       bool fresh;
+                       SymValue symbol = this.egraph.LookupOrManifest (this.Functions.ValueOf, address, out fresh);
+
+                       if (fresh && IsUnmodified (address))
+                               MakeUnmodified (symbol);
+
+                       return symbol;
+               }
+
+               public SymValue Value (Parameter p)
+               {
+                       return Value (Address (this.Functions.For (p)));
+               }
+
+               public void MakeUnmodified (SymValue value)
+               {
+                       this.unmodifiedSinceEntry = this.unmodifiedSinceEntry.Add (value);
+               }
+
+               private bool IsUnmodified (SymValue value)
+               {
+                       return this.unmodifiedSinceEntry.Contains (value);
+               }
+
+               public AbstractType CurrentType (int stackPos)
+               {
+                       return CurrentType (Value (Address (this.Functions.For (stackPos))));
+               }
+
+               private AbstractType CurrentType (SymValue address)
+               {
+                       return this.egraph [address];
+               }
+
+               public Domain Assume (int t, bool truth)
+               {
+                       return Assume (Value (t), truth);
+               }
+
+               private Domain Assume (SymValue sv, bool truth)
+               {
+                       if (!truth) {
+                               if (IsNonZero (sv))
+                                       return Bottom;
+                               this.egraph [sv] = this.egraph [sv].ButZero;
+                               foreach (var term in this.egraph.EqTerms (sv)) {
+                                       if (term.Function == this.Functions.UnaryNot || term.Function == this.Functions.NeZero)
+                                               return Assume (term.Args [0], true);
+                               }
+                       } else {
+                               if (this.egraph [sv].IsZero)
+                                       return Bottom;
+                               foreach (var term in this.egraph.EqTerms (sv)) {
+                                       if (term.Function == this.Functions.UnaryNot || term.Function == this.Functions.NeZero)
+                                               return Assume (term.Args [0], false);
+                               }
+                       }
+
+                       return this;
+               }
+
+               private bool IsNonZero (SymValue sv)
+               {
+                       foreach (var term in this.egraph.EqTerms (sv)) {
+                               var wrapper = term.Function as Wrapper<object>;
+                               if (wrapper != null && wrapper.Item is int && (int) wrapper.Item != 0)
+                                       return true;
+                       }
+                       return false;
+               }
+
+               public FlatDomain<TypeNode> BinaryResultType (BinaryOperator op, AbstractType t1, AbstractType t2)
+               {
+                       switch (op) {
+                       case BinaryOperator.Add:
+                       case BinaryOperator.Add_Ovf:
+                       case BinaryOperator.Add_Ovf_Un:
+                               if (t1.IsZero)
+                                       return t2.Type;
+                               return t1.Type;
+                       case BinaryOperator.Sub:
+                       case BinaryOperator.Sub_Ovf:
+                       case BinaryOperator.Sub_Ovf_Un:
+                               return t1.Type;
+                       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 MetaDataProvider.System_Boolean;
+                       default:
+                               return t1.Type;
+                       }
+               }
+
+               private bool IsStructWithFields (FlatDomain<TypeNode> type)
+               {
+                       if (!type.IsNormal)
+                               return false;
+
+                       return !MetaDataProvider.HasValueRepresentation (type.Concrete);
+               }
+
+               private FlatDomain<TypeNode> TargetType (FlatDomain<TypeNode> type)
+               {
+                       if (!type.IsNormal)
+                               return type;
+
+                       TypeNode normalType = type.Concrete;
+                       if (MetaDataProvider.IsManagedPointer (normalType))
+                               return MetaDataProvider.ElementType (normalType);
+
+                       return FlatDomain<TypeNode>.TopValue;
+               }
+
+               public void SetType (SymValue sv, FlatDomain<TypeNode> type)
+               {
+                       AbstractType abstractType = this.egraph [sv];
+                       if (abstractType.IsZero)
+                               return;
+
+                       this.egraph [sv] = abstractType.With (type);
+               }
+
+               private void SetTypeIfUnknown (SymValue sv, FlatDomain<TypeNode> type)
+               {
+                       AbstractType abstractType = this.egraph [sv];
+
+                       if (!abstractType.IsZero && (!abstractType.Type.IsNormal || abstractType.Type.Equals (MetaDataProvider.System_IntPtr)))
+                               this.egraph [sv] = abstractType.With (type);
+               }
+
+               private void MakeTotallyModified (SymValue dest)
+               {
+                       this.unmodifiedSinceEntry = this.unmodifiedSinceEntry.Remove (dest);
+                       this.unmodifiedFieldsSinceEntry = this.unmodifiedFieldsSinceEntry.Remove (dest);
+               }
+
+               private bool AreUnmodified (IEnumerable<SymValue> values)
+               {
+                       return values.All (IsUnmodified);
+               }
+
+               private bool AnyAreModifiedAtCall (IEnumerable<SymValue> values)
+               {
+                       return values.Any (IsModifiedAtCall);
+               }
+
+               private bool IsModifiedAtCall (SymValue sv)
+               {
+                       return (this.ModifiedAtCall != null && this.ModifiedAtCall.Contains (sv));
+               }
+
+               public Domain GetStateAt (APC pc)
+               {
+                       Domain ifFound;
+                       this.parent.PreStateLookup (pc, out ifFound);
+
+                       return ifFound;
+               }
+
+               public bool TryGetCorrespondingValueAbstraction (int v, out SymbolicValue sv)
+               {
+                       return TryGetCorrespondingValueAbstraction (this.Functions.For (v), out sv);
+               }
+
+               private bool TryGetCorrespondingValueAbstraction (SymFunction v, out SymbolicValue sv)
+               {
+                       if (!IsBottom) {
+                               SymValue loc = TryAddress (v);
+                               if (loc != null) {
+                                       SymValue symbol = TryCorrespondingValue (loc);
+                                       if (symbol != null) {
+                                               sv = new SymbolicValue (symbol);
+                                               return true;
+                                       }
+                               }
+                       }
+
+                       sv = default(SymbolicValue);
+                       return false;
+               }
+
+               private SymValue TryCorrespondingValue (SymValue address)
+               {
+                       if (IsStructAddress (this.egraph [address]))
+                               return address;
+
+                       return TryValue (address);
+               }
+
+               private bool IsStructAddress (AbstractType abstractType)
+               {
+                       if (!abstractType.IsNormal)
+                               return false;
+
+                       TypeNode normalType = abstractType.ConcreteType;
+                       if (MetaDataProvider.IsManagedPointer (normalType))
+                               return !MetaDataProvider.HasValueRepresentation (MetaDataProvider.ElementType (normalType));
+
+                       return false;
+               }
+
+               private SymValue TryAddress (SymFunction c)
+               {
+                       return this.egraph.TryLookup (c);
+               }
+
+               public bool TryGetCorrespondingValueAbstraction (Local v, out SymbolicValue sv)
+               {
+                       return TryGetCorrespondingValueAbstraction (this.Functions.For (v), out sv);
+               }
+
+               public bool TryGetUnboxedValue (int source, out SymbolicValue sv)
+               {
+                       return TryGetUnboxedValue (TryValue (Address (source)), out sv);
+               }
+
+               private bool TryGetUnboxedValue (SymValue box, out SymbolicValue sv)
+               {
+                       if (box != null) {
+                               SymValue symbol = TryValue (box);
+                               if (symbol != null && this.egraph.TryLookup (this.Functions.BoxOperator, symbol) == box) {
+                                       sv = new SymbolicValue (symbol);
+                                       return true;
+                               }
+                       }
+                       sv = new SymbolicValue ();
+                       return false;
+               }
+
+               public SymValue TryValue (SymValue address)
+               {
+                       return this.egraph.TryLookup (this.Functions.ValueOf, address);
+               }
+
+               public AbstractType GetType (SymValue symbol)
+               {
+                       return this.egraph [symbol];
+               }
+
+               public SymValue CreateObject (TypeNode type)
+               {
+                       SymValue sv = this.egraph.FreshSymbol ();
+                       SetType (sv, type);
+                       return sv;
+               }
+
+               public SymValue CreateValue (TypeNode type)
+               {
+                       SymValue sv = this.egraph.FreshSymbol ();
+                       SetType (sv, MetaDataProvider.ManagedPointer (type));
+                       return sv;
+               }
+
+               public void HavocArrayAtIndex (SymValue arrayValue, SymValue indexValue)
+               {
+                       this.egraph.Eliminate (this.Functions.ElementAddress, arrayValue);
+               }
+
+               public SymValue CreateArray (TypeNode type, SymValue len)
+               {
+                       SymValue sv = this.egraph.FreshSymbol ();
+                       this.egraph [this.Functions.Length, sv] = len;
+                       SetType (sv, MetaDataProvider.ArrayType (type, 1));
+                       return sv;
+               }
+
+               public SymValue ElementAddress (SymValue array, SymValue index, TypeNode elementAddressType)
+               {
+                       SymValue objVersion = this.egraph [this.Functions.ObjectVersion, array];
+                       SymValue sv = this.egraph.TryLookup (this.Functions.ElementAddress, objVersion, index);
+                       if (sv == null) {
+                               sv = this.egraph [this.Functions.ElementAddress, objVersion, index];
+                               SetType (sv, elementAddressType);
+                               this.egraph [this.Functions.ResultOfLoadElement, sv] = Zero;
+                       }
+                       return sv;
+               }
+
+               public void CopyValueAndCast (SymValue destAddr, SymValue srcAddr, TypeNode addrType)
+               {
+                       CopyValue (destAddr, srcAddr, addrType, true, true);
+               }
+
+               public void HavocObjectAtCall (SymValue obj, ref IImmutableSet<SymValue> havoced, bool havocFields, bool havocReadonlyFields)
+               {
+                       HavocFields (null, obj, ref havoced, havocReadonlyFields);
+                       HavocUp (obj, ref havoced, havocFields);
+               }
+
+               public bool IsThis (Method currentMethod, int i)
+               {
+                       if (MetaDataProvider.IsStatic (currentMethod))
+                               return false;
+                       return Value (MetaDataProvider.This (currentMethod)) == Value (i);
+               }
+
+               public void AssignValueAndNullnessAtConv_IU (int dest, int source, bool unsigned)
+               {
+                       AbstractType aType = CurrentType (source);
+                       AssignValueAndNullnessAtConv_IU (Address (this.Functions.For (dest)), unsigned, aType);
+               }
+
+               private void AssignValueAndNullnessAtConv_IU (SymValue address, bool unsigned, AbstractType aType)
+               {
+                       Havoc (address);
+                       FlatDomain<TypeNode> type = aType.Type;
+                       if (!IsStructWithFields (type)) {
+                               SymValue ptrValue = this.egraph.FreshSymbol ();
+                               if (type.IsNormal)
+                                       aType = new AbstractType (!unsigned ? MetaDataProvider.System_IntPtr : MetaDataProvider.System_UIntPtr, aType.IsZero);
+                               SetType (address, type.IsNormal ? MetaDataProvider.ManagedPointer (type.Concrete) : type);
+                               this.egraph [ptrValue] = aType;
+                               this.egraph [this.Functions.ValueOf, address] = ptrValue;
+                       } else
+                               SetType (address, type.IsNormal ? MetaDataProvider.ManagedPointer (type.Concrete) : type);
+               }
+
+               public TypeNode UnaryResultType (UnaryOperator op, AbstractType type)
+               {
+                       switch (op) {
+                       case UnaryOperator.Conv_i1:
+                               return MetaDataProvider.System_Int8;
+                       case UnaryOperator.Conv_i2:
+                               return MetaDataProvider.System_Int16;
+                       case UnaryOperator.Conv_i4:
+                               return MetaDataProvider.System_Int32;
+                       case UnaryOperator.Conv_i8:
+                               return MetaDataProvider.System_Int64;
+                       case UnaryOperator.Conv_u1:
+                               return MetaDataProvider.System_UInt8;
+                       case UnaryOperator.Conv_u2:
+                               return MetaDataProvider.System_UInt16;
+                       case UnaryOperator.Conv_u4:
+                               return MetaDataProvider.System_UInt32;
+                       case UnaryOperator.Conv_u8:
+                               return MetaDataProvider.System_UInt64;
+                       default:
+                               if (type.IsNormal)
+                                       return type.ConcreteType;
+                               return MetaDataProvider.System_Int32;
+                       }
+               }
+
+               public void CopyStackAddress (SymValue destAddr, int temporaryForWhichAddressIsTaken)
+               {
+                       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);
+                       SetType (destAddr, t);
+               }
+
+               public SymValue PseudoFieldAddress (SymValue ptr, Method getter)
+               {
+                       TypeNode pseudoFieldAddressType;
+                       return PseudoFieldAddress (ptr, getter, out pseudoFieldAddressType, false);
+               }
+
+               public SymValue PseudoFieldAddress (SymValue sv, Method m, out TypeNode pseudoFieldAddressType, bool materialize)
+               {
+                       pseudoFieldAddressType = MetaDataProvider.ManagedPointer (MetaDataProvider.ReturnType (m));
+                       m = MetaDataProvider.Unspecialized (m);
+                       bool fresh;
+                       SymValue elem = LookupAddressAndManifestType (sv, this.Functions.For (m), pseudoFieldAddressType, out fresh);
+                       if (fresh) {
+                               if (IsUnmodified (sv))
+                                       MakeModified (elem);
+                               if (IsModifiedAtCall (sv))
+                                       this.ModifiedAtCall = this.ModifiedAtCall.Add (elem);
+                               if (materialize)
+                                       MaterializeAccordingToType (elem, pseudoFieldAddressType, 0);
+                       }
+                       return elem;
+               }
+
+               public SymValue FieldAddress (SymValue ptr, Field field)
+               {
+                       TypeNode fieldAddressType;
+                       return FieldAddress (ptr, field, out fieldAddressType);
+               }
+
+               public SymValue FieldAddress (SymValue ptr, Field field, out TypeNode fieldAddressType)
+               {
+                       fieldAddressType = MetaDataProvider.ManagedPointer (MetaDataProvider.FieldType (field));
+                       bool fresh;
+                       SymValue sv = LookupAddressAndManifestType (ptr, this.Functions.For (field), fieldAddressType, out fresh);
+                       if (fresh) {
+                               if (IsUnmodifiedForFields (ptr) || MetaDataProvider.IsReadonly (field))
+                                       MakeUnmodified (sv);
+                               if (IsModifiedAtCall (ptr))
+                                       this.ModifiedAtCall = this.ModifiedAtCall.Add (sv);
+                       }
+                       return sv;
+               }
+
+               public void Assign (Parameter parameter, TypeNode type)
+               {
+                       AssignValue (Address (this.Functions.For (parameter)), type);
+               }
+
+               public SymValue PseudoFieldAddressOfOutParameter (int index, SymValue fieldAddr, TypeNode pType)
+               {
+                       SymValue sv = this.egraph [this.Functions.ForConstant (index, MetaDataProvider.System_Int32), fieldAddr];
+                       MaterializeAccordingToType (sv, pType, 2);
+                       return sv;
+               }
+
+               public SymValue ObjectVersion (SymValue sv)
+               {
+                       return this.egraph [this.Functions.ObjectVersion, sv];
+               }
+
+               public SymValue PseudoFieldAddress (SymValue[] args, Method method, out TypeNode pseudoFieldAddressType, bool materialize)
+               {
+                       if (args.Length == 0 || args.Length == 1)
+                               return PseudoFieldAddress (Globals, method, out pseudoFieldAddressType, materialize);
+                       pseudoFieldAddressType = MetaDataProvider.ManagedPointer (MetaDataProvider.ReturnType (method));
+                       method = MetaDataProvider.Unspecialized (method);
+
+                       bool fresh;
+                       SymValue sv = LookupAddressAndManifestType (args, this.Functions.For (method), pseudoFieldAddressType, out fresh);
+                       if (fresh) {
+                               if (AreUnmodified (args))
+                                       MakeUnmodified (sv);
+                               if (AnyAreModifiedAtCall (args))
+                                       this.ModifiedAtCall = this.ModifiedAtCall.Add (sv);
+                               if (materialize)
+                                       MaterializeAccordingToType (sv, pseudoFieldAddressType, 0);
+                       }
+                       return sv;
+               }
+
+               public void AssignReturnValue (int dest, TypeNode type)
+               {
+                       AssignValue (dest, type);
+                       if (MetaDataProvider.HasValueRepresentation (type))
+                               this.egraph [this.Functions.ResultOfCall, Value (dest)] = Zero;
+                       else
+                               MaterializeAccordingToType (Address (dest), MetaDataProvider.ManagedPointer (type), 0);
+               }
+
+               public void MaterializeAccordingToType (SymValue sv, TypeNode type, int depth)
+               {
+                       SetType (sv, type);
+                       if (depth > 2)
+                               return;
+
+                       if (MetaDataProvider.IsManagedPointer (type)) {
+                               TypeNode elementType = MetaDataProvider.ElementType (type);
+                               if (!MetaDataProvider.HasValueRepresentation (elementType)) {
+                                       ManifestStructId (sv);
+                                       foreach (Field field in MetaDataProvider.Fields (elementType)) {
+                                               if (!MetaDataProvider.IsStatic (field)) {
+                                                       TypeNode fieldAddressType;
+                                                       MaterializeAccordingToType (FieldAddress (sv, field, out fieldAddressType), fieldAddressType, depth + 1);
+                                               }
+                                       }
+                                       foreach (Property property in MetaDataProvider.Properties (elementType)) {
+                                               Method getter;
+                                               if (!MetaDataProvider.IsStatic (property) && MetaDataProvider.HasGetter (property, out getter)) {
+                                                       TypeNode pseudoFieldAddressType;
+                                                       MaterializeAccordingToType (PseudoFieldAddress (sv, getter, out pseudoFieldAddressType, false), pseudoFieldAddressType, depth + 1);
+                                               }
+                                       }
+                               } else
+                                       MaterializeAccordingToType (Value (sv), elementType, depth + 1);
+                       }
+               }
+
+               public void ManifestStructId (SymValue sv)
+               {
+                       StructId (sv);
+               }
+
+               public SymValue StructId (SymValue sv)
+               {
+                       return this.egraph [this.Functions.StructId, sv];
+               }
+
+               private SymValue LookupAddressAndManifestType (SymValue sv, SymFunction c, TypeNode type, out bool fresh)
+               {
+                       SymValue value = this.egraph.TryLookup (c, sv);
+                       if (value != null) {
+                               fresh = false;
+                               return value;
+                       }
+
+                       fresh = true;
+                       value = this.egraph [c, sv];
+                       SetType (value, type);
+
+                       return value;
+               }
+
+               public void HavocFields (SymValue sv, IEnumerable<Field> fields, ref IImmutableSet<SymValue> havoced)
+               {
+                       foreach (Field f in fields)
+                               HavocConstructor (null, sv, this.Functions.For (f), ref havoced, false);
+               }
+
+               private bool IsUnmodifiedForFields (SymValue sv)
+               {
+                       return this.unmodifiedFieldsSinceEntry.Contains (sv);
+               }
+
+               public void HavocUp (SymValue srcAddr, ref IImmutableSet<SymValue> havocedAtCall, bool havocFields)
+               {
+                       foreach (var term in this.egraph.EqTerms (srcAddr)) {
+                               if (term.Function == this.Functions.ValueOf)
+                                       HavocUpField (term.Args [0], ref havocedAtCall, havocFields);
+                       }
+               }
+
+               private void HavocUpField (SymValue sv, ref IImmutableSet<SymValue> havocedAtCall, bool havocFields)
+               {
+                       foreach (var term in this.egraph.EqTerms (sv)) {
+                               SymFunction accessedVia = term.Function;
+                               if (accessedVia is Wrapper<Field>)
+                                       HavocUpObjectVersion (accessedVia, term.Args [0], ref havocedAtCall, havocFields);
+                               else {
+                                       var methodWrapper = accessedVia as Wrapper<Method>;
+                                       Property property;
+                                       if (methodWrapper != null && !MetaDataProvider.IsStatic (methodWrapper.Item) && MetaDataProvider.IsPropertyGetter (methodWrapper.Item, out property))
+                                               HavocUpObjectVersion (accessedVia, term.Args [0], ref havocedAtCall, havocFields);
+                               }
+                       }
+               }
+
+               private void HavocUpObjectVersion (SymFunction accessedVia, SymValue sv, ref IImmutableSet<SymValue> havocedAtCall, bool havocFields)
+               {
+                       if (havocedAtCall.Contains (sv))
+                               return;
+                       this.egraph.Eliminate (this.Functions.ObjectVersion, sv);
+                       if (havocFields)
+                               HavocMutableFields (accessedVia, sv, ref havocedAtCall);
+                       else
+                               HavocPseudoFields (accessedVia, sv, ref havocedAtCall);
+
+                       HavocUp (sv, ref havocedAtCall, false);
+               }
+
+               public void CopyAddress (SymValue destAddr, SymValue srcAddr, TypeNode type)
+               {
+                       this.egraph [this.Functions.ValueOf, destAddr] = srcAddr;
+                       SetType (destAddr, MetaDataProvider.ManagedPointer (type));
+               }
+
+               public void AssignArrayLength (SymValue destAddr, SymValue array)
+               {
+                       SymValue length = this.egraph [this.Functions.Length, array];
+                       SetType (length, MetaDataProvider.System_Int32);
+                       this.egraph [this.Functions.ValueOf, destAddr] = length;
+                       SetType (destAddr, MetaDataProvider.ManagedPointer (MetaDataProvider.System_Int32));
+               }
+
+               public void ResetModifiedAtCall ()
+               {
+                       this.ModifiedAtCall = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+               }
+
+               public SymValue LoadValue (int source)
+               {
+                       return Value (source);
+               }
+
+               public SymbolicValue TryLoadValue (SymValue addr)
+               {
+                       return new SymbolicValue (Value (addr));
+               }
+
+               public bool TryGetArrayLength (SymValue arrayValue, out SymValue length)
+               {
+                       length = this.egraph.TryLookup (this.Functions.Length, arrayValue);
+                       return length != null;
+               }
+
+               public bool TryGetCorrespondingValueAbstraction (Parameter p, out SymbolicValue sv)
+               {
+                       return TryGetCorrespondingValueAbstraction (this.Functions.For (p), out sv);
+               }
+
+               public string GetAccessPath (SymValue sv)
+               {
+                       LispList<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)
+               {
+                       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)
+               {
+                       return this.egraph.LessEqual (that.egraph, out forward, out backward);
+               }
+
+               public bool IsResultEGraph (IMergeInfo mi)
+               {
+                       return mi.IsResultGraph (this.egraph);
+               }
+
+               public bool IsGraph1 (IMergeInfo mi)
+               {
+                       return mi.IsGraph1 (this.egraph);
+               }
+
+               public bool IsGraph2 (IMergeInfo mi)
+               {
+                       return mi.IsGraph2 (this.egraph);
+               }
+
+               public IImmutableMap<SymValue, LispList<SymValue>> GetForwardIdentityMap ()
+               {
+                       return this.egraph.GetForwardIdentityMap ();
+               }
+
+               public Domain Join (Domain that, bool widening, out bool weaker, out IMergeInfo mergeInfo)
+               {
+                       SymGraph<SymFunction, AbstractType> graph = this.egraph.Join (that.egraph, out mergeInfo, widening);
+                       weaker = mergeInfo.Changed;
+
+                       IImmutableSet<SymValue> resultUnmodifiedSinceEntry;
+                       IImmutableSet<SymValue> resultUnmodifiedFieldsSinceEntry;
+                       IImmutableSet<SymValue> resultModifiedAtCall;
+
+                       ComputeJoinOfSets (mergeInfo, this, that, out resultUnmodifiedSinceEntry, out resultUnmodifiedFieldsSinceEntry, out resultModifiedAtCall, ref weaker);
+                       Domain oldDomain = null;
+                       if (OldDomain != null) {
+                               bool oldWeaker;
+                               IMergeInfo oldMergeInfo;
+                               oldDomain = OldDomain.Join (that.OldDomain, widening, out oldWeaker, out oldMergeInfo);
+                       }
+
+                       return new Domain (graph, RecomputeConstantMap (graph), resultUnmodifiedSinceEntry, resultUnmodifiedFieldsSinceEntry, resultModifiedAtCall, this, oldDomain);
+               }
+
+               private IImmutableMap<SymValue, SymFunction> RecomputeConstantMap (SymGraph<SymFunction, AbstractType> graph)
+               {
+                       IImmutableMap<SymValue, SymFunction> result = ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey);
+                       foreach (SymFunction constant in graph.Constants) {
+                               if (this.Functions.IsConstantOrMethod (constant))
+                                       result.Add (graph [constant], constant);
+                       }
+                       return result;
+               }
+
+               private void ComputeJoinOfSets (IMergeInfo mergeInfo, Domain domain, Domain that,
+                                               out IImmutableSet<SymValue> resultUnmodifiedSinceEntry,
+                                               out IImmutableSet<SymValue> resultUnmodifiedFieldsSinceEntry,
+                                               out IImmutableSet<SymValue> resultModifiedAtCall, ref bool weaker)
+               {
+                       resultUnmodifiedSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       resultUnmodifiedFieldsSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+                       resultModifiedAtCall = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
+
+                       foreach (var tuple in mergeInfo.MergeTriples) {
+                               SymValue symValue1 = tuple.Item1;
+                               SymValue symValue2 = tuple.Item2;
+                               SymValue elem = tuple.Item3;
+
+                               bool unmodifiedSinceEntryContains = domain.unmodifiedSinceEntry.ContainsSafe (symValue1);
+                               bool modifiedAtCallContains = domain.ModifiedAtCall.ContainsSafe (symValue1);
+
+                               if (unmodifiedSinceEntryContains) {
+                                       if (that.unmodifiedSinceEntry.ContainsSafe (symValue2))
+                                               resultUnmodifiedSinceEntry = resultUnmodifiedSinceEntry.Add (elem);
+                                       else if (that.unmodifiedFieldsSinceEntry.ContainsSafe (symValue2))
+                                               resultUnmodifiedFieldsSinceEntry = resultUnmodifiedFieldsSinceEntry.Add (elem);
+                               }
+
+                               if (modifiedAtCallContains)
+                                       resultModifiedAtCall = resultModifiedAtCall.Add (elem);
+                       }
+
+                       if (that.unmodifiedSinceEntry.Count () > resultUnmodifiedSinceEntry.Count ()) {
+                               weaker = true;
+                               if (DebugOptions.Debug)
+                                       Console.WriteLine ("---Result changed due to fewer unmodified locations since entry");
+                       } else {
+                               if (that.unmodifiedFieldsSinceEntry.Count () > resultUnmodifiedFieldsSinceEntry.Count ()) {
+                                       weaker = true;
+                                       if (DebugOptions.Debug)
+                                               Console.WriteLine ("---Result changed due to fewer unmodified locations for fields since entry");
+                               }
+                       }
+               }
+
+               #region Implementation of IAbstractDomain<Domain>
+               public Domain Top
+               {
+                       get
+                       {
+                               return new Domain (this.egraph.Top, ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey),
+                                                  ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey), this, null);
+                       }
+               }
+
+               public Domain Bottom
+               {
+                       get
+                       {
+                               if (BottomValue == null) {
+                                       BottomValue = new Domain (this.egraph.Bottom, ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey),
+                                                                 ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey),
+                                                                 this, null);
+                                       BottomValue.ImmutableVersion ();
+                               }
+                               return BottomValue;
+                       }
+               }
+
+               public bool IsTop
+               {
+                       get { return this.egraph.IsTop; }
+               }
+
+               public bool IsBottom
+               {
+                       get
+                       {
+                               if (this == BottomValue || this.egraph.IsBottom)
+                                       return true;
+                               if (OldDomain != null)
+                                       return OldDomain.IsBottom;
+
+                               return false;
+                       }
+               }
+
+               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)
+               {
+                       SymGraph<SymFunction, AbstractType> graph = this.egraph.Meet (that.egraph);
+                       return new Domain (graph, RecomputeConstantMap (graph), this.unmodifiedSinceEntry, this.unmodifiedFieldsSinceEntry, null, this, OldDomain);
+               }
+
+               public bool LessEqual (Domain that)
+               {
+                       return this.egraph.LessEqual (that.egraph);
+               }
+
+               public Domain ImmutableVersion ()
+               {
+                       this.egraph.ImmutableVersion ();
+                       return this;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/FunctionsTable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/FunctionsTable.cs
new file mode 100644 (file)
index 0000000..24ccd37
--- /dev/null
@@ -0,0 +1,185 @@
+// 
+// FunctionsTable.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class FunctionsTable
+       {
+               public readonly SymFunction BoxOperator;
+               public readonly SymFunction ElementAddress;
+               public readonly SymFunction Length;
+               public readonly SymFunction NeZero;
+               public readonly SymFunction NullValue;
+               public readonly SymFunction ObjectVersion;
+               public readonly SymFunction OldValueOf;
+               public readonly SymFunction ResultOfCall;
+               public readonly SymFunction ResultOfLoadElement;
+               public readonly SymFunction StructId;
+               public readonly SymFunction UnaryNot;
+               public readonly SymFunction ValueOf;
+               public readonly SymFunction VoidAddr;
+               public readonly SymFunction ZeroValue;
+               private readonly Dictionary<BinaryOperator, Wrapper<BinaryOperator>> binary_operators;
+               private readonly Dictionary<Field, Wrapper<Field>> fields;
+               private readonly Dictionary<Local, Wrapper<Local>> locals;
+               private readonly IMetaDataProvider meta_data_provider;
+               private readonly Dictionary<Method, Wrapper<Method>> method_pointers;
+               private readonly Dictionary<Parameter, Wrapper<Parameter>> parameters;
+               private readonly Dictionary<object, Wrapper<object>> program_constants;
+               private readonly Dictionary<Method, Wrapper<Method>> pseudo_fields;
+               private readonly Dictionary<string, Wrapper<string>> strings;
+               private readonly Dictionary<int, Wrapper<int>> temp;
+               private readonly Dictionary<UnaryOperator, Wrapper<UnaryOperator>> unary_operators;
+
+               private int id_gen;
+
+               public FunctionsTable(IMetaDataProvider metaDataProvider)
+               {
+                       this.meta_data_provider = metaDataProvider;
+                       this.locals = new Dictionary<Local, Wrapper<Local>> ();
+                       this.parameters = new Dictionary<Parameter, Wrapper<Parameter>> ();
+                       this.fields = new Dictionary<Field, Wrapper<Field>> ();
+                       this.pseudo_fields = new Dictionary<Method, Wrapper<Method>> ();
+                       this.temp = new Dictionary<int, Wrapper<int>> ();
+                       this.strings = new Dictionary<string, Wrapper<string>> ();
+                       this.program_constants = new Dictionary<object, Wrapper<object>> ();
+                       this.method_pointers = new Dictionary<Method, Wrapper<Method>> ();
+                       this.binary_operators = new Dictionary<BinaryOperator, Wrapper<BinaryOperator>> ();
+                       this.unary_operators = new Dictionary<UnaryOperator, Wrapper<UnaryOperator>> ();
+
+                       this.ValueOf = For ("$Value");
+                       this.OldValueOf = For ("$OldValue");
+                       this.StructId = For ("$StructId");
+                       this.ObjectVersion = For ("$ObjectVersion");
+                       this.NullValue = For ("$Null");
+                       this.ElementAddress = For ("$ElementAddress");
+                       this.Length = For ("$Length");
+                       this.VoidAddr = For ("$VoidAddr");
+                       this.UnaryNot = For ("$UnaryNot");
+                       this.NeZero = For ("$NeZero");
+                       this.BoxOperator = For ("$Box");
+                       this.ResultOfCall = For ("$ResultOfCall");
+                       this.ResultOfLoadElement = For ("$ResultOfLoadElement");
+                       this.ZeroValue = ForConstant (0, this.meta_data_provider.System_Int32);
+               }
+
+               private Wrapper<T> For<T>(T key, Dictionary<T, Wrapper<T>> cache)
+               {
+                       Wrapper<T> wrapper;
+                       if (!cache.TryGetValue (key, out wrapper)) {
+                               wrapper = SymFunction.For (key, ref this.id_gen, this.meta_data_provider);
+                               cache.Add (key, wrapper);
+                       }
+                       return wrapper;
+               }
+
+               public SymFunction For(Local v)
+               {
+                       return For (v, this.locals);
+               }
+
+               public SymFunction For(Parameter v)
+               {
+                       return For (v, this.parameters);
+               }
+
+               public SymFunction For(Field v)
+               {
+                       v = this.meta_data_provider.Unspecialized (v);
+                       return For (v, this.fields);
+               }
+
+               public SymFunction For(Method v)
+               {
+                       return For (v, this.pseudo_fields);
+               }
+
+               public SymFunction For(string v)
+               {
+                       return For (v, this.strings);
+               }
+
+               public SymFunction For(int v)
+               {
+                       return For (v, this.temp);
+               }
+
+               public SymFunction For(BinaryOperator v)
+               {
+                       return For (v, this.binary_operators);
+               }
+
+               public SymFunction For(UnaryOperator v)
+               {
+                       return For (v, this.unary_operators);
+               }
+
+               public SymFunction ForConstant(object constant, TypeNode type)
+               {
+                       Wrapper<object> wrapper = For (constant, this.program_constants);
+                       wrapper.Type = type;
+                       return wrapper;
+               }
+
+               public SymFunction ForMethod(Method method, TypeNode type)
+               {
+                       Wrapper<Method> wrapper = For (method, this.method_pointers);
+                       wrapper.Type = type;
+                       return wrapper;
+               }
+
+               public bool IsConstantOrMethod(SymFunction constant)
+               {
+                       var wrapper = constant as Wrapper<object>;
+                       if (wrapper != null && this.program_constants.ContainsKey (wrapper.Item))
+                               return true;
+
+                       var wrapper1 = constant as Wrapper<Method>;
+                       if (wrapper1 != null && this.method_pointers.ContainsKey (wrapper1.Item))
+                               return true;
+
+                       return false;
+               }
+
+               public bool IsConstant(SymFunction c, out TypeNode type, out object value)
+               {
+                       var wrapper = c as Wrapper<object>;
+                       if (wrapper != null && this.program_constants.ContainsKey (wrapper.Item)) {
+                               type = wrapper.Type;
+                               value = wrapper.Item;
+                               return true;
+                       }
+
+                       type = null;
+                       value = null;
+                       return false;
+               }
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..f7015fa
--- /dev/null
@@ -0,0 +1,254 @@
+// 
+// HeapAnalysis.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.IO;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataFlowAnalysis;
+using Mono.CodeContracts.Static.DataStructures;
+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>>> ();
+
+               public readonly Dictionary<APC, IMergeInfo> MergeInfoCache = new Dictionary<APC, IMergeInfo> ();
+               public readonly DoubleDictionary<APC, APC, Dummy> RenamePoints = new DoubleDictionary<APC, APC, Dummy> ();
+               private readonly ICodeLayer<int, int, IStackContextProvider, Dummy> stackLayer;
+               private IFixPointInfo<APC, Domain> fixPointInfo;
+
+               public HeapAnalysis (ICodeLayer<int, int, IStackContextProvider, Dummy> stackLayer)
+               {
+                       this.stackLayer = stackLayer;
+               }
+
+               public IStackContextProvider StackContextProvider
+               {
+                       get { return this.stackLayer.ILDecoder.ContextProvider; }
+               }
+
+               public IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.stackLayer.MetaDataProvider; }
+               }
+
+               public IContractProvider ContractProvider
+               {
+                       get { return this.stackLayer.ContractProvider; }
+               }
+
+               public Method CurrentMethod
+               {
+                       get { return this.StackContextProvider.MethodContext.CurrentMethod; }
+               }
+
+               IILVisitor<APC, int, int, Domain, Domain> IAnalysis<APC, Domain, IILVisitor<APC, int, int, Domain, Domain>, Dummy>.
+                       GetVisitor ()
+               {
+                       return GetVisitor ();
+               }
+
+               public Domain Join (Pair<APC, APC> edge, Domain newstate, Domain prevstate, out bool weaker, bool widen)
+               {
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("-----OPT Join at {0}", edge);
+                               Console.WriteLine ("-----Existing state:");
+                               prevstate.Dump (Console.Out);
+                               Console.WriteLine ("-----New state:");
+                               newstate.Dump (Console.Out);
+                       }
+
+                       IMergeInfo mi;
+                       Domain domain = prevstate.Join (newstate, widen, out weaker, out mi);
+                       if (weaker) {
+                               IMergeInfo mi2;
+                               if (this.MergeInfoCache.TryGetValue (edge.Value, out mi2) && mi2 == null)
+                                       this.MergeInfoCache [edge.Value] = mi;
+                       } else
+                               this.MergeInfoCache [edge.Value] = mi;
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("-----Result state: changed = {0} (widen = {1})", weaker ? 1 : 0, widen ? 1 : 0);
+                               domain.Dump (Console.Out);
+                               Console.WriteLine ("----------------------------------------------");
+                       }
+
+                       return domain;
+               }
+
+               public Domain ImmutableVersion (Domain arg)
+               {
+                       return arg.ImmutableVersion ();
+               }
+
+               public Domain MutableVersion (Domain arg)
+               {
+                       if (arg.IsBottom)
+                               return arg;
+                       return arg.Clone ();
+               }
+
+               public Domain EdgeConversion (APC @from, APC to, bool isJoinPoint, Dummy data, Domain state)
+               {
+                       if (isJoinPoint) {
+                               this.RenamePoints [from, to] = Dummy.Value;
+                               if (!this.MergeInfoCache.ContainsKey (to))
+                                       this.MergeInfoCache.Add (to, null);
+                       }
+
+                       if (DebugOptions.Debug)
+                       {
+                               Console.WriteLine ("----Edge conversion on {0}->{1}------", from, to);
+                               state.Dump (Console.Out);
+                               Console.WriteLine ("-------------------------------------");
+                       }
+
+                       return state;
+               }
+
+               public bool IsBottom (APC pc, Domain state)
+               {
+                       return state.IsBottom;
+               }
+
+               public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, Domain> fixPointInfo)
+               {
+                       this.fixPointInfo = fixPointInfo;
+                       return pc => true;
+               }
+
+               public void Dump (Pair<Domain, TextWriter> pair)
+               {
+                       pair.Key.Dump (pair.Value);
+               }
+
+               private IILVisitor<APC, int, int, Domain, Domain> GetVisitor ()
+               {
+                       return new AnalysisDecoder (this);
+               }
+
+               public Domain InitialValue ()
+               {
+                       return new Domain (this);
+               }
+
+               public IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>> 
+                       GetDecoder<Context>(IILDecoder<APC, int, int, Context, Dummy> underlying)
+                       where Context : IStackContextProvider
+               {
+                       return new ValueDecoder<Context> (this, underlying);
+               }
+
+               public bool IsUnreachable (APC pc)
+               {
+                       Domain domain;
+                       if (!this.fixPointInfo.PreStateLookup (pc, out domain) || domain.IsBottom)
+                               return true;
+
+                       return false;
+               }
+
+               public IImmutableMap<SymbolicValue, LispList<SymbolicValue>> EdgeRenaming (Pair<APC, APC> edge, bool isJoinPoint)
+               {
+                       IImmutableMap<SymbolicValue, LispList<SymbolicValue>> forwardRenaming;
+
+                       if (this.forwardRenamings.TryGetValue (edge, out forwardRenaming))
+                               return forwardRenaming;
+
+                       IImmutableMap<SymbolicValue, LispList<SymbolicValue>> renaming = null;
+                       Domain afterBegin;
+                       PostStateLookup (edge.Key, out afterBegin);
+                       if (afterBegin == null || afterBegin.IsBottom)
+                               return null;
+                       Domain beforeEnd;
+                       PreStateLookup (edge.Value, out beforeEnd);
+                       if (beforeEnd != null) {
+                               IImmutableMap<SymValue, LispList<SymValue>> forward;
+                               if (!TryComputeFromJoinCache (afterBegin, beforeEnd, edge.Value, out forward)) {
+                                       IImmutableMap<SymValue, SymValue> backward;
+                                       if (!afterBegin.LessEqual (beforeEnd, out forward, out backward))
+                                               throw new InvalidOperationException ("Should never happen");
+                                       if (isJoinPoint && forward == null)
+                                               forward = afterBegin.GetForwardIdentityMap ();
+                               }
+                               if (forward != null) {
+                                       renaming = ImmutableIntKeyMap<SymbolicValue, LispList<SymbolicValue>>.Empty (SymbolicValue.GetUniqueKey);
+                                       foreach (SymValue sv in forward.Keys) {
+                                               LispList<SymbolicValue> targets = null;
+                                               foreach (SymValue target in forward [sv].AsEnumerable ())
+                                                       targets = targets.Cons (new SymbolicValue (target));
+                                               if (targets != null)
+                                                       renaming = renaming.Add (new SymbolicValue (sv), targets);
+                                       }
+                               }
+                       }
+                       this.forwardRenamings.Add (edge, renaming);
+                       return renaming;
+               }
+
+               private bool TryComputeFromJoinCache (Domain inDomain, Domain outDomain, APC joinPoint, out IImmutableMap<SymValue, LispList<SymValue>> forward)
+               {
+                       forward = null;
+                       IMergeInfo mi;
+                       if (this.MergeInfoCache.TryGetValue (joinPoint, out mi) && mi != null && outDomain.IsResultEGraph (mi)) {
+                               if (inDomain.IsGraph1 (mi)) {
+                                       forward = mi.ForwardG1Map;
+                                       return true;
+                               }
+                               if (inDomain.IsGraph2 (mi)) {
+                                       forward = mi.ForwardG2Map;
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
+               public Domain GetPreState (APC pc)
+               {
+                       Domain domain;
+                       PreStateLookup (pc, out domain);
+                       return domain;
+               }
+
+               public bool PreStateLookup (APC pc, out Domain ifFound)
+               {
+                       return this.fixPointInfo.PreStateLookup (pc, out ifFound);
+               }
+
+               public bool PostStateLookup (APC pc, out Domain ifFound)
+               {
+                       return this.fixPointInfo.PostStateLookup (pc, out ifFound);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/IAbstractDomainForEGraph.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/IAbstractDomainForEGraph.cs
new file mode 100644 (file)
index 0000000..48ca402
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IAbstractDomainForEGraph.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 Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       interface IAbstractDomainForEGraph<TADomain> : IAbstractDomain<TADomain> {
+               bool HasAllBottomFields { get; }
+               TADomain ForManifestedField ();
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/IConstantInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/IConstantInfo.cs
new file mode 100644 (file)
index 0000000..142b043
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// IConstantInfo.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.Analysis.HeapAnalysis {
+       interface IConstantInfo {
+               bool KeepAsBottomField { get; }
+               bool ManifestField { get; }
+       }
+}
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
new file mode 100644 (file)
index 0000000..7a39cca
--- /dev/null
@@ -0,0 +1,63 @@
+// 
+// ISymGraph.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 Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       interface ISymGraph<TFunc, TADomain, TGraph> : IAbstractDomain<TGraph>
+               where TFunc : IEquatable<TFunc>, IConstantInfo
+               where TADomain : IAbstractDomainForEGraph<TADomain> {
+               SymValue this [TFunc function, SymValue arg] { get; set; }
+               SymValue this [TFunc function] { get; set; }
+               TADomain this [SymValue symbol] { get; set; }
+               IEnumerable<TFunc> Constants { get; }
+               IEnumerable<SymValue> Variables { get; }
+
+               SymValue FreshSymbol ();
+
+               SymValue TryLookup (TFunc function, SymValue arg);
+               SymValue TryLookup (TFunc function);
+
+               IEnumerable<TFunc> Functions (SymValue symbol);
+               IEnumerable<SymGraphTerm<TFunc>> EqTerms (SymValue symbol);
+
+               void AssumeEqual (SymValue v1, SymValue v2);
+               bool IsEqual (SymValue v1, SymValue v2);
+               void Eliminate (TFunc function, SymValue arg);
+               void Eliminate (TFunc function);
+               void EliminateAll (SymValue arg);
+
+               TGraph Join (TGraph that, out IMergeInfo mergeInfo, bool widen);
+
+               bool LessEqual (TGraph that, out IImmutableMap<SymValue, LispList<SymValue>> forward,
+                               out IImmutableMap<SymValue, SymValue> backward);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/LabeledSymbol.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/LabeledSymbol.cs
new file mode 100644 (file)
index 0000000..53bf768
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// LabeledSymbol.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       struct LabeledSymbol<Label, TSymValue> : IEquatable<LabeledSymbol<Label, TSymValue>>
+               where TSymValue : IEquatable<TSymValue> {
+               public readonly Label ReadAt;
+               public readonly TSymValue Symbol;
+
+               public LabeledSymbol (Label readAt, TSymValue symbol)
+               {
+                       this.ReadAt = readAt;
+                       this.Symbol = symbol;
+               }
+
+               #region Implementation of IEquatable<ExternalExpression<Label,SymbolicValue>>
+               public bool Equals (LabeledSymbol<Label, TSymValue> other)
+               {
+                       return this.Symbol.Equals (other.Symbol);
+               }
+               #endregion
+
+               public override bool Equals (object obj)
+               {
+                       return obj is LabeledSymbol<Label, TSymValue> && Equals ((LabeledSymbol<Label, TSymValue>) obj);
+               }
+
+               public override int GetHashCode ()
+               {
+                       return this.Symbol.GetHashCode ();
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("{0}@{1}", this.Symbol, this.ReadAt);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/MethodWrapper.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/MethodWrapper.cs
new file mode 100644 (file)
index 0000000..c48ef13
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+// MethodWrapper.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class MethodWrapper : Wrapper<Method> {
+               public MethodWrapper (Method value, ref int idGen, IMetaDataProvider metaDataProvider)
+                       : base (value, ref idGen, metaDataProvider)
+               {
+               }
+
+               public override bool ActsAsField
+               {
+                       get { return true; }
+               }
+
+               public override TypeNode FieldAddressType ()
+               {
+                       return this.MetaDataProvider.ManagedPointer (this.MetaDataProvider.ReturnType (this.Item));
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ParameterWrapper.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/ParameterWrapper.cs
new file mode 100644 (file)
index 0000000..03ff547
--- /dev/null
@@ -0,0 +1,72 @@
+// 
+// ParameterWrapper.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class ParameterWrapper : Wrapper<Parameter>
+       {
+               private readonly int parameter_index;
+
+               public ParameterWrapper(Parameter parameter, ref int idGen, IMetaDataProvider metaDataProvider)
+                       : base (parameter, ref idGen, metaDataProvider)
+               {
+                       this.parameter_index = metaDataProvider.ParameterIndex (parameter);
+               }
+
+               public override bool ActsAsField
+               {
+                       get { return false; }
+               }
+
+               public override TypeNode FieldAddressType()
+               {
+                       throw new InvalidOperationException ();
+               }
+
+               public override string ToString()
+               {
+                       return this.MetaDataProvider.Name (this.Item);
+               }
+
+               public override bool Equals(object obj)
+               {
+                       var other = obj as ParameterWrapper;
+                       if (other == null)
+                               return false;
+
+                       return other.parameter_index == this.parameter_index;
+               }
+
+               public override int GetHashCode()
+               {
+                       return this.parameter_index;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/StackToSymbolicAdapter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/StackToSymbolicAdapter.cs
new file mode 100644 (file)
index 0000000..814418a
--- /dev/null
@@ -0,0 +1,572 @@
+// 
+// StackToSymbolicAdapter.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       struct StackToSymbolicAdapter<Data, Result, Visitor> : IILVisitor<APC, int, int, Data, Result>
+               where Visitor : IILVisitor<APC, SymbolicValue, SymbolicValue, Data, Result> {
+               private readonly Visitor delegatee;
+               private readonly HeapAnalysis parent;
+
+               public StackToSymbolicAdapter (HeapAnalysis parent, Visitor delegatee)
+               {
+                       this.parent = parent;
+                       this.delegatee = delegatee;
+               }
+
+               private bool PreStateLookup (APC pc, out Domain domain)
+               {
+                       return this.parent.PreStateLookup (pc, out domain);
+               }
+
+               private bool PostStateLookup (APC pc, out Domain domain)
+               {
+                       return this.parent.PostStateLookup (pc, out domain);
+               }
+
+               private SymbolicValue ConvertSource (APC pc, int source)
+               {
+                       Domain domain;
+                       if (!PreStateLookup (pc, out domain) || domain.IsBottom)
+                               return new SymbolicValue ();
+                       if (source < 0)
+                               return new SymbolicValue (domain.VoidAddr);
+
+                       SymbolicValue sv;
+                       domain.TryGetCorrespondingValueAbstraction (source, out sv);
+                       return sv;
+               }
+
+               private SymbolicValue ConvertOldSource (APC pc, int source)
+               {
+                       Domain domain;
+                       if (!PreStateLookup (pc, out domain) || domain.IsBottom)
+                               return new SymbolicValue ();
+
+                       if (source < 0)
+                               return new SymbolicValue (domain.VoidAddr);
+
+                       Domain oldDomain = AnalysisDecoder.FindOldState (pc, domain);
+                       if (oldDomain == null)
+                               return new SymbolicValue (domain.VoidAddr);
+
+                       SymbolicValue sv;
+                       oldDomain.TryGetCorrespondingValueAbstraction (source, out sv);
+                       return sv;
+               }
+
+               private SymbolicValue ConvertDest (APC pc, int dest)
+               {
+                       Domain domain;
+                       if (!PostStateLookup (pc, out domain))
+                               return new SymbolicValue ();
+
+                       SymbolicValue sv;
+                       domain.TryGetCorrespondingValueAbstraction (dest, out sv);
+                       return sv;
+               }
+
+               private SymbolicValue ConvertOldDest (APC pc, int dest)
+               {
+                       SymbolicValue sv = default(SymbolicValue);
+                       Domain domain;
+                       if (!PostStateLookup (pc, out domain))
+                               return sv;
+
+                       domain.OldDomain.TryGetCorrespondingValueAbstraction (dest, out sv);
+                       return sv;
+               }
+
+               private SymbolicValue ConvertSourceDeref (APC pc, int source)
+               {
+                       Domain domain;
+                       if (!PreStateLookup (pc, out domain))
+                               return new SymbolicValue ();
+                       if (source < 0)
+                               return new SymbolicValue (domain.VoidAddr);
+
+                       SymValue addr = domain.LoadValue (source);
+                       if (!PostStateLookup (pc, out domain))
+                               return new SymbolicValue ();
+
+                       return domain.TryLoadValue (addr);
+               }
+
+               private SymbolicValue TryConvertUnbox (APC pc, int source)
+               {
+                       Domain domain;
+                       if (!PreStateLookup (pc, out domain))
+                               return new SymbolicValue ();
+
+                       if (source < 0)
+                               return new SymbolicValue (domain.VoidAddr);
+
+                       SymbolicValue sv;
+                       if (!domain.TryGetUnboxedValue (source, out sv))
+                               domain.TryGetCorrespondingValueAbstraction (source, out sv);
+                       return sv;
+               }
+
+               private ArgumentSourceWrapper<ArgList> ConvertSources<ArgList> (APC pc, ArgList args)
+                       where ArgList : IIndexable<int>
+               {
+                       return new ArgumentSourceWrapper<ArgList> (args, this.parent.GetPreState (pc));
+               }
+
+               private bool InsideOld (APC pc)
+               {
+                       Domain domain;
+                       return PreStateLookup (pc, out domain) && domain.OldDomain != null;
+               }
+
+               #region Implementation of IExpressionILVisitor<APC,int,int,Data,Result>
+               public Result Binary (APC pc, BinaryOperator op, int dest, int operand1, int operand2, Data data)
+               {
+                       if (op != BinaryOperator.Cobjeq) {
+                               return this.delegatee.Binary (pc, op, ConvertDest (pc, dest),
+                                                             ConvertSource (pc, operand1), ConvertSource (pc, operand2),
+                                                             data);
+                       }
+
+                       SymbolicValue op1 = TryConvertUnbox (pc, operand1);
+                       SymbolicValue op2 = TryConvertUnbox (pc, operand2);
+
+                       return this.delegatee.Binary (pc, op, ConvertDest (pc, dest), op1, op2, data);
+               }
+
+               public Result Isinst (APC pc, TypeNode type, int dest, int obj, Data data)
+               {
+                       return this.delegatee.Isinst (pc, type, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               public Result LoadNull (APC pc, int dest, Data polarity)
+               {
+                       return this.delegatee.LoadNull (pc, ConvertDest (pc, dest), polarity);
+               }
+
+               public Result LoadConst (APC pc, TypeNode type, object constant, int dest, Data data)
+               {
+                       return this.delegatee.LoadConst (pc, type, constant, ConvertDest (pc, dest), data);
+               }
+
+               public Result Sizeof (APC pc, TypeNode type, int dest, Data data)
+               {
+                       return this.delegatee.Sizeof (pc, type, ConvertDest (pc, dest), data);
+               }
+
+               public Result Unary (APC pc, UnaryOperator op, bool unsigned, int dest, int source, Data data)
+               {
+                       return this.delegatee.Unary (pc, op, unsigned, ConvertDest (pc, dest), ConvertSource (pc, source), data);
+               }
+               #endregion
+
+               #region Implementation of ISyntheticILVisitor<APC,int,int,Data,Result>
+               public Result Entry (APC pc, Method method, Data data)
+               {
+                       return this.delegatee.Entry (pc, method, data);
+               }
+
+               public Result Assume (APC pc, EdgeTag tag, int source, Data data)
+               {
+                       return this.delegatee.Assume (pc, tag, ConvertSource (pc, source), data);
+               }
+
+               public Result Assert (APC pc, EdgeTag tag, int source, Data data)
+               {
+                       return this.delegatee.Assert (pc, tag, ConvertSource (pc, source), data);
+               }
+
+               public Result BeginOld (APC pc, APC matchingEnd, Data data)
+               {
+                       return this.delegatee.BeginOld (pc, matchingEnd, data);
+               }
+
+               public Result EndOld (APC pc, APC matchingBegin, TypeNode type, int dest, int source, Data data)
+               {
+                       return this.delegatee.Nop (pc, data);
+               }
+
+               public Result LoadStack (APC pc, int offset, int dest, int source, bool isOld, Data data)
+               {
+                       SymbolicValue src = isOld ? ConvertOldSource (pc, source) : ConvertSource (pc, source);
+                       return this.delegatee.LoadStack (pc, offset, ConvertDest (pc, dest), src, isOld, data);
+               }
+
+               public Result LoadStackAddress (APC pc, int offset, int dest, int source, TypeNode type, bool isOld, Data data)
+               {
+                       return this.delegatee.LoadStackAddress (pc, offset, ConvertDest (pc, dest), ConvertSource (pc, source), type, isOld, data);
+               }
+
+               public Result LoadResult (APC pc, TypeNode type, int dest, int source, Data data)
+               {
+                       return this.delegatee.LoadResult (pc, type, ConvertDest (pc, dest), ConvertSource (pc, source), data);
+               }
+               #endregion
+
+               #region Implementation of IILVisitor<APC,int,int,Data,Result>
+               public Result Arglist (APC pc, int dest, Data data)
+               {
+                       return this.delegatee.Arglist (pc, ConvertDest (pc, dest), data);
+               }
+
+               public Result Branch (APC pc, APC target, bool leavesExceptionBlock, Data data)
+               {
+                       return this.delegatee.Branch (pc, target, leavesExceptionBlock, data);
+               }
+
+               public Result BranchCond (APC pc, APC target, BranchOperator bop, int value1, int value2, Data data)
+               {
+                       return this.delegatee.BranchCond (pc, target, bop, ConvertSource (pc, value1), ConvertSource (pc, value2), data);
+               }
+
+               public Result BranchTrue (APC pc, APC target, int cond, Data data)
+               {
+                       return this.delegatee.BranchTrue (pc, target, ConvertSource (pc, cond), data);
+               }
+
+               public Result BranchFalse (APC pc, APC target, int cond, Data data)
+               {
+                       return this.delegatee.BranchFalse (pc, target, ConvertSource (pc, cond), data);
+               }
+
+               public Result Break (APC pc, Data data)
+               {
+                       return this.delegatee.Break (pc, data);
+               }
+
+               public Result Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, int dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       if (!this.parent.MetaDataProvider.IsVoidMethod (method) && InsideOld (pc))
+                               return this.delegatee.LoadStack (pc, 0, ConvertDest (pc, dest), ConvertOldDest (pc, dest), true, data);
+
+                       return DelegateCall (pc, method, virt, extraVarargs, dest, args, data);
+               }
+
+               public Result Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, int dest, int functionPointer, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       if (!this.parent.MetaDataProvider.IsVoid (returnType) && InsideOld (pc))
+                               return this.delegatee.LoadStack (pc, 0, ConvertDest (pc, dest), ConvertOldDest (pc, dest), true, data);
+
+                       return this.delegatee.Calli (pc, returnType, argTypes, instance,
+                                                    ConvertDest (pc, dest), ConvertSource (pc, functionPointer),
+                                                    ConvertSources (pc, args), data);
+               }
+
+               public Result CheckFinite (APC pc, int dest, int source, Data data)
+               {
+                       return this.delegatee.CheckFinite (pc, ConvertDest (pc, dest), ConvertSource (pc, source), data);
+               }
+
+               public Result CopyBlock (APC pc, int destAddress, int srcAddress, int len, Data data)
+               {
+                       return this.delegatee.CopyBlock (pc, ConvertSource (pc, destAddress), ConvertSource (pc, srcAddress), ConvertSource (pc, len), data);
+               }
+
+               public Result EndFilter (APC pc, int decision, Data data)
+               {
+                       return this.delegatee.EndFilter (pc, ConvertSource (pc, decision), data);
+               }
+
+               public Result EndFinally (APC pc, Data data)
+               {
+                       return this.delegatee.EndFinally (pc, data);
+               }
+
+               public Result Jmp (APC pc, Method method, Data data)
+               {
+                       return this.delegatee.Jmp (pc, method, data);
+               }
+
+               public Result LoadArg (APC pc, Parameter argument, bool isOld, int dest, Data data)
+               {
+                       return this.delegatee.LoadArg (pc, argument, isOld, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadArgAddress (APC pc, Parameter argument, bool isOld, int dest, Data data)
+               {
+                       return this.delegatee.LoadArgAddress (pc, argument, isOld, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadLocal (APC pc, Local local, int dest, Data data)
+               {
+                       return this.delegatee.LoadLocal (pc, local, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadLocalAddress (APC pc, Local local, int dest, Data data)
+               {
+                       return this.delegatee.LoadLocalAddress (pc, local, ConvertDest (pc, dest), data);
+               }
+
+               public Result Nop (APC pc, Data data)
+               {
+                       return this.delegatee.Nop (pc, data);
+               }
+
+               public Result Pop (APC pc, int source, Data data)
+               {
+                       return this.delegatee.Pop (pc, ConvertSource (pc, source), data);
+               }
+
+               public Result Return (APC pc, int source, Data data)
+               {
+                       return this.delegatee.Return (pc, ConvertSource (pc, source), data);
+               }
+
+               public Result StoreArg (APC pc, Parameter argument, int source, Data data)
+               {
+                       return this.delegatee.StoreArg (pc, argument, ConvertSource (pc, source), data);
+               }
+
+               public Result StoreLocal (APC pc, Local local, int source, Data data)
+               {
+                       return this.delegatee.StoreLocal (pc, local, ConvertSource (pc, source), data);
+               }
+
+               public Result Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, int value, Data data)
+               {
+                       return this.delegatee.Switch (pc, type, cases, ConvertSource (pc, value), data);
+               }
+
+               public Result Box (APC pc, TypeNode type, int dest, int source, Data data)
+               {
+                       return this.delegatee.Box (pc, type, ConvertDest (pc, dest), ConvertSource (pc, source), data);
+               }
+
+               public Result ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint,
+                                                                     TypeList extraVarargs, int dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       return this.delegatee.ConstrainedCallvirt (pc, method, constraint, extraVarargs,
+                                                                  ConvertDest (pc, dest), ConvertSources (pc, args), data);
+               }
+
+               public Result CastClass (APC pc, TypeNode type, int dest, int obj, Data data)
+               {
+                       return this.delegatee.CastClass (pc, type, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               public Result CopyObj (APC pc, TypeNode type, int destPtr, int sourcePtr, Data data)
+               {
+                       return this.delegatee.CopyObj (pc, type, ConvertSource (pc, destPtr), ConvertSource (pc, sourcePtr), data);
+               }
+
+               public Result Initobj (APC pc, TypeNode type, int ptr, Data data)
+               {
+                       return this.delegatee.Initobj (pc, type, ConvertSource (pc, ptr), data);
+               }
+
+               public Result LoadElement (APC pc, TypeNode type, int dest, int array, int index, Data data)
+               {
+                       if (InsideOld (pc))
+                               return this.delegatee.LoadStack (pc, 0, ConvertDest (pc, dest), ConvertOldDest (pc, dest), true, data);
+                       return this.delegatee.LoadElement (pc, type, ConvertDest (pc, dest), ConvertSource (pc, array), ConvertSource (pc, index), data);
+               }
+
+               public Result LoadField (APC pc, Field field, int dest, int obj, Data data)
+               {
+                       if (InsideOld (pc))
+                               return this.delegatee.LoadStack (pc, 0, ConvertDest (pc, dest), ConvertOldDest (pc, dest), true, data);
+
+                       return this.delegatee.LoadField (pc, field, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               public Result LoadFieldAddress (APC pc, Field field, int dest, int obj, Data data)
+               {
+                       return this.delegatee.LoadFieldAddress (pc, field, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               public Result LoadLength (APC pc, int dest, int array, Data data)
+               {
+                       return this.delegatee.LoadLength (pc, ConvertDest (pc, dest), ConvertSource (pc, array), data);
+               }
+
+               public Result LoadStaticField (APC pc, Field field, int dest, Data data)
+               {
+                       if (InsideOld (pc))
+                               return this.delegatee.LoadStack (pc, 0, ConvertDest (pc, dest), ConvertOldDest (pc, dest), true, data);
+
+                       return this.delegatee.LoadStaticField (pc, field, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadStaticFieldAddress (APC pc, Field field, int dest, Data data)
+               {
+                       return this.delegatee.LoadStaticFieldAddress (pc, field, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadTypeToken (APC pc, TypeNode type, int dest, Data data)
+               {
+                       return this.delegatee.LoadTypeToken (pc, type, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadFieldToken (APC pc, Field type, int dest, Data data)
+               {
+                       return this.delegatee.LoadFieldToken (pc, type, ConvertDest (pc, dest), data);
+               }
+
+               public Result LoadMethodToken (APC pc, Method type, int dest, Data data)
+               {
+                       return this.delegatee.LoadMethodToken (pc, type, ConvertDest (pc, dest), data);
+               }
+
+               public Result NewArray<ArgList> (APC pc, TypeNode type, int dest, ArgList lengths, Data data) where ArgList : IIndexable<int>
+               {
+                       return this.delegatee.NewArray (pc, type, ConvertDest (pc, dest), ConvertSources (pc, lengths), data);
+               }
+
+               public Result NewObj<ArgList> (APC pc, Method ctor, int dest, ArgList args, Data data) where ArgList : IIndexable<int>
+               {
+                       return this.delegatee.NewObj (pc, ctor, ConvertDest (pc, dest), ConvertSources (pc, args), data);
+               }
+
+               public Result MkRefAny (APC pc, TypeNode type, int dest, int obj, Data data)
+               {
+                       return this.delegatee.MkRefAny (pc, type, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               public Result RefAnyType (APC pc, int dest, int source, Data data)
+               {
+                       return this.delegatee.RefAnyType (pc, ConvertDest (pc, dest), ConvertSource (pc, source), data);
+               }
+
+               public Result RefAnyVal (APC pc, TypeNode type, int dest, int source, Data data)
+               {
+                       return this.delegatee.RefAnyVal (pc, type, ConvertDest (pc, dest), ConvertSource (pc, source), data);
+               }
+
+               public Result Rethrow (APC pc, Data data)
+               {
+                       return this.delegatee.Rethrow (pc, data);
+               }
+
+               public Result StoreElement (APC pc, TypeNode type, int array, int index, int value, Data data)
+               {
+                       return this.delegatee.StoreElement (pc, type, ConvertSource (pc, array), ConvertSource (pc, index), ConvertSource (pc, value), data);
+               }
+
+               public Result StoreField (APC pc, Field field, int obj, int value, Data data)
+               {
+                       return this.delegatee.StoreField (pc, field, ConvertSource (pc, obj), ConvertSource (pc, value), data);
+               }
+
+               public Result StoreStaticField (APC pc, Field field, int value, Data data)
+               {
+                       return this.delegatee.StoreStaticField (pc, field, ConvertSource (pc, value), data);
+               }
+
+               public Result Throw (APC pc, int exception, Data data)
+               {
+                       return this.delegatee.Throw (pc, ConvertSource (pc, exception), data);
+               }
+
+               public Result Unbox (APC pc, TypeNode type, int dest, int obj, Data data)
+               {
+                       return this.delegatee.Unbox (pc, type, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               public Result UnboxAny (APC pc, TypeNode type, int dest, int obj, Data data)
+               {
+                       return this.delegatee.UnboxAny (pc, type, ConvertDest (pc, dest), ConvertSource (pc, obj), data);
+               }
+
+               private Result DelegateCall<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, int dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<int>
+               {
+                       TypeNode declaringType = this.parent.MetaDataProvider.DeclaringType (method);
+                       if (args.Count == 2) {
+                               string name = this.parent.MetaDataProvider.Name (method);
+                               if (name == "Equals") {
+                                       return this.delegatee.Binary (pc, BinaryOperator.Cobjeq,
+                                                                     ConvertDest (pc, dest),
+                                                                     TryConvertUnbox (pc, args [0]), TryConvertUnbox (pc, args [1]), data);
+                               }
+
+                               if (this.parent.MetaDataProvider.IsReferenceType (declaringType)) {
+                                       if (name == "op_Inequality") {
+                                               return this.delegatee.Binary (pc, BinaryOperator.Cne_Un,
+                                                                             ConvertDest (pc, dest),
+                                                                             ConvertSource (pc, args [0]), ConvertSource (pc, args [1]), data);
+                                       }
+                                       if (name == "op_Equality") {
+                                               return this.delegatee.Binary (pc, BinaryOperator.Cobjeq,
+                                                                             ConvertDest (pc, dest),
+                                                                             ConvertSource (pc, args [0]), ConvertSource (pc, args [1]), data);
+                                       }
+                               }
+                       }
+
+                       return this.delegatee.Call (pc, method, virt, extraVarargs, ConvertDest (pc, dest), ConvertSources (pc, args), data);
+               }
+               #endregion
+
+               #region Nested type: ArgumentSourceWrapper
+               private struct ArgumentSourceWrapper<ArgList> : IIndexable<SymbolicValue>
+                       where ArgList : IIndexable<int> {
+                       private readonly Domain state;
+                       private readonly ArgList underlying;
+
+                       public ArgumentSourceWrapper (ArgList underlying, Domain state)
+                       {
+                               this.underlying = underlying;
+                               this.state = state;
+                       }
+
+                       #region Implementation of IIndexable<SymbolicValue>
+                       public int Count
+                       {
+                               get { return this.underlying.Count; }
+                       }
+
+                       public SymbolicValue this [int index]
+                       {
+                               get { return Map (this.underlying [index]); }
+                       }
+
+                       private SymbolicValue Map (int i)
+                       {
+                               SymbolicValue sv = default(SymbolicValue);
+                               if (this.state == null)
+                                       return sv;
+
+                               this.state.TryGetCorrespondingValueAbstraction (i, out sv);
+                               return sv;
+                       }
+                       #endregion
+                       }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymFunction.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymFunction.cs
new file mode 100644 (file)
index 0000000..56d178a
--- /dev/null
@@ -0,0 +1,78 @@
+// 
+// SymFunction.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       abstract class SymFunction : IConstantInfo, IEquatable<SymFunction>, IVisibilityCheck<Method> {
+               protected readonly IMetaDataProvider MetaDataProvider;
+
+               protected SymFunction (ref int idGen, IMetaDataProvider metaDataProvider)
+               {
+                       this.MetaDataProvider = metaDataProvider;
+                       idGen++;
+               }
+
+               public abstract bool ActsAsField { get; }
+               public abstract bool IsVirtualMethod { get; }
+               public abstract bool IsStatic { get; }
+
+               #region IConstantInfo Members
+               public abstract bool KeepAsBottomField { get; }
+               public abstract bool ManifestField { get; }
+               #endregion
+
+               #region IVisibilityCheck<Method> Members
+               public abstract bool IfRootIsParameter { get; }
+               public abstract bool IsAsVisibleAs (Method member);
+               public abstract bool IsVisibleFrom (Method member);
+               #endregion
+
+               public abstract TypeNode FieldAddressType ();
+               public abstract PathElementBase ToPathElement (bool tryCompact);
+
+               public static Wrapper<T> For<T> (T value, ref int idGen, IMetaDataProvider metadataDecoder)
+               {
+                       if (value is Parameter)
+                               return (Wrapper<T>) (object) new ParameterWrapper ((Parameter) (object) value, ref idGen, metadataDecoder);
+                       if (value is Method)
+                               return (Wrapper<T>) (object) new MethodWrapper ((Method) (object) value, ref idGen, metadataDecoder);
+
+                       return new Wrapper<T> (value, ref idGen, metadataDecoder);
+               }
+
+               #region Implementation of IEquatable<HeapAnalysis<Local,Parameter,Method,Field,Property,Event,Type,Attribute,Assembly>.Domain.SymFunction>
+               public bool Equals (SymFunction other)
+               {
+                       return ReferenceEquals (this, other);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymValue.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymValue.cs
new file mode 100644 (file)
index 0000000..eb40be0
--- /dev/null
@@ -0,0 +1,79 @@
+// 
+// SymValue.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       sealed class SymValue : IEquatable<SymValue>, IComparable<SymValue>, IComparable {
+               private static int _globalIdGenerator;
+
+               public readonly int UniqueId;
+               public readonly int GlobalId;
+
+               public SymValue (int uniqueId)
+               {
+                       this.UniqueId = uniqueId;
+                       this.GlobalId = ++_globalIdGenerator;
+               }
+
+               #region IComparable Members
+               public int CompareTo (object obj)
+               {
+                       var that = obj as SymValue;
+                       if (that == null)
+                               return 1;
+
+                       return CompareTo (that);
+               }
+               #endregion
+
+               #region Implementation of IEquatable<SymValue>
+               public bool Equals (SymValue other)
+               {
+                       return this == other;
+               }
+               #endregion
+
+               #region IComparable<SymValue> Members
+               public int CompareTo (SymValue other)
+               {
+                       return this.UniqueId - other.UniqueId;
+               }
+               #endregion
+
+               public static int GetUniqueKey (SymValue sv)
+               {
+                       return sv == null ? 0 : sv.GlobalId;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("sv{0} ({1})", this.UniqueId, this.GlobalId);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymbolicValue.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymbolicValue.cs
new file mode 100644 (file)
index 0000000..863d9c7
--- /dev/null
@@ -0,0 +1,99 @@
+// 
+// SymbolicValue.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;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       struct SymbolicValue : IEquatable<SymbolicValue>, IComparable<SymbolicValue>, IComparable {
+               public readonly SymValue Symbol;
+
+               public SymbolicValue (SymValue symbol)
+               {
+                       this.Symbol = symbol;
+               }
+
+               public bool IsNull
+               {
+                       get { return this.Symbol == null; }
+               }
+
+               public int MethodLocalId
+               {
+                       get { return this.Symbol.UniqueId; }
+               }
+
+               #region Implementation of IEquatable<SymbolicValue>
+               public bool Equals (SymbolicValue other)
+               {
+                       return this.Symbol == other.Symbol;
+               }
+               #endregion
+
+               #region Implementation of IComparable<in SymbolicValue>
+               public int CompareTo (SymbolicValue other)
+               {
+                       return this.Symbol.CompareTo (other.Symbol);
+               }
+               #endregion
+
+               #region Implementation of IComparable
+               public int CompareTo (object obj)
+               {
+                       if (!(obj is SymbolicValue))
+                               return 1;
+
+                       return CompareTo ((SymbolicValue) obj);
+               }
+               #endregion
+
+               public override bool Equals (object obj)
+               {
+                       if (obj is SymbolicValue)
+                               return Equals ((SymbolicValue) obj);
+
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return this.Symbol == null ? 0 : this.Symbol.GetHashCode ();
+               }
+
+               public override string ToString ()
+               {
+                       if (this.Symbol == null)
+                               return "<!null!>";
+                       return this.Symbol.ToString ();
+               }
+
+               public static int GetUniqueKey (SymbolicValue arg)
+               {
+                       return SymValue.GetUniqueKey (arg.Symbol);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/TypeCache.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/TypeCache.cs
new file mode 100644 (file)
index 0000000..1da943c
--- /dev/null
@@ -0,0 +1,57 @@
+// 
+// TypeCache.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       struct TypeCache {
+               private readonly string full_name;
+               private TypeNode cache;
+               private bool cache_is_valid;
+               private bool have_type;
+
+               public TypeCache (string fullName)
+               {
+                       this.cache_is_valid = false;
+                       this.have_type = false;
+                       this.cache = default(TypeNode);
+                       this.full_name = fullName;
+               }
+
+               public bool TryGet (IMetaDataProvider mdProvider, out TypeNode type)
+               {
+                       if (!this.cache_is_valid) {
+                               this.cache_is_valid = true;
+                               this.have_type = mdProvider.TryGetSystemType (this.full_name, out this.cache);
+                       }
+
+                       type = this.cache;
+                       return this.have_type;
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..cf3e817
--- /dev/null
@@ -0,0 +1,184 @@
+// 
+// ValueContextProvider.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.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class ValueContextProvider<TContext> : IValueContextProvider<SymbolicValue>, IValueContext<SymbolicValue>
+               where TContext : IStackContextProvider {
+               private readonly HeapAnalysis parent;
+               private readonly TContext underlying;
+
+               public ValueContextProvider (HeapAnalysis parent, TContext underlying)
+               {
+                       this.parent = parent;
+                       this.underlying = underlying;
+               }
+
+               #region Implementation of IMethodContextProvider
+               public IMethodContext MethodContext
+               {
+                       get { return this.underlying.MethodContext; }
+               }
+               #endregion
+
+               #region Implementation of IStackContextProvider
+               public IStackContext StackContext
+               {
+                       get { return this.underlying.StackContext; }
+               }
+               #endregion
+
+               #region Implementation of IValueContextProvider<SymbolicValue>
+               IValueContext<SymbolicValue> IValueContextProvider<SymbolicValue>.ValueContext
+               {
+                       get { return this; }
+               }
+               #endregion
+
+               #region Implementation of IValueContext<SymbolicValue>
+               public FlatDomain<TypeNode> GetType (APC pc, SymbolicValue value)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (pc, out domain) || domain.IsBottom)
+                               return FlatDomain<TypeNode>.TopValue;
+
+                       return domain.GetType (value.Symbol).Type;
+               }
+
+               public bool IsZero (APC at, SymbolicValue value)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               return true;
+
+                       return domain.IsZero (value.Symbol);
+               }
+
+               public bool TryLocalValue (APC at, Local local, out SymbolicValue sv)
+               {
+                       Domain domain;
+                       if (this.parent.PreStateLookup (at, out domain))
+                               return domain.TryGetCorrespondingValueAbstraction (local, out sv);
+
+                       sv = new SymbolicValue ();
+                       return false;
+               }
+
+               public bool TryParameterValue (APC at, Parameter p, out SymbolicValue sv)
+               {
+                       Domain domain;
+                       if (this.parent.PreStateLookup (at, out domain))
+                               return domain.TryGetCorrespondingValueAbstraction (p, out sv);
+
+                       sv = new SymbolicValue ();
+                       return false;
+               }
+
+               public bool TryGetArrayLength (APC at, SymbolicValue array, out SymbolicValue length)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               throw new ArgumentException ("pc wasn't visited");
+                       SymValue lengthValue;
+                       bool arrayLength = domain.TryGetArrayLength (array.Symbol, out lengthValue);
+
+                       length = new SymbolicValue (lengthValue);
+                       return arrayLength;
+               }
+
+               public LispList<PathElement> AccessPathList (APC at, SymbolicValue sv, bool allowLocal, bool preferLocal)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               throw new ArgumentException ("pc wasn't visited");
+
+                       AccessPathFilter<Method> filter = AccessPathFilter<Method>.IsVisibleFrom (MethodContext.CurrentMethod);
+                       return domain.GetAccessPathList (sv.Symbol, filter, allowLocal, preferLocal);
+               }
+
+               public bool IsConstant (APC at, SymbolicValue symbol, out TypeNode type, out object constant)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               throw new ArgumentException ("pc wasn't visited");
+
+                       return domain.IsConstant (symbol.Symbol, out type, out constant);
+               }
+
+               public bool TryStackValue (APC at, int stackIndex, out SymbolicValue sv)
+               {
+                       Domain domain;
+                       if (this.parent.PreStateLookup (at, out domain))
+                               return domain.TryGetCorrespondingValueAbstraction (stackIndex, out sv);
+
+                       sv = new SymbolicValue ();
+                       return false;
+               }
+
+               public bool IsValid (SymbolicValue sv)
+               {
+                       return sv.Symbol != null;
+               }
+
+               public string AccessPath (APC at, SymbolicValue sv)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               throw new ArgumentException ("pc wasn't visited");
+
+                       return domain.GetAccessPath (sv.Symbol);
+               }
+
+               public IEnumerable<LispList<PathElement>> AccessPaths (APC at, SymValue value, AccessPathFilter<Method> filter)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               throw new ArgumentException ("pc wasn't visited");
+
+                       return domain.GetAccessPathsFiltered (value, filter, true).Select (path => path.Coerce<PathElementBase, PathElement> ());
+               }
+
+               public LispList<PathElement> VisibleAccessPathList (APC at, SymbolicValue value)
+               {
+                       Domain domain;
+                       if (!this.parent.PreStateLookup (at, out domain))
+                               throw new ArgumentException ("pc wasn't visited");
+
+                       AccessPathFilter<Method> filter = AccessPathFilter<Method>.FromPrecondition (MethodContext.CurrentMethod);
+                       return domain.GetAccessPathList (value.Symbol, filter, false, false);
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..70f331e
--- /dev/null
@@ -0,0 +1,91 @@
+// 
+// ValueDecoder.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.IO;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class ValueDecoder<TContext> : 
+               IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>>
+               where TContext : IStackContextProvider
+       {
+               private readonly HeapAnalysis parent;
+               private readonly IILDecoder<APC, int, int, TContext, Dummy> stack_decoder;
+               private readonly Lazy<IValueContextProvider<SymbolicValue>> context;
+
+               public ValueDecoder(HeapAnalysis parent, IILDecoder<APC, int, int, TContext, Dummy> stackDecoder)
+               {
+                       this.context = new Lazy<IValueContextProvider<SymbolicValue>> (()=> new ValueContextProvider<TContext>(this.parent, this.stack_decoder.ContextProvider));
+                       this.parent = parent;
+                       this.stack_decoder = stackDecoder;
+               }
+
+               #region Implementation of IILDecoder<APC,SymbolicValue,SymbolicValue,IValueContext<SymbolicValue>,IImmutableMap<SymbolicValue,LispList<SymbolicValue>>>
+               public IValueContextProvider<SymbolicValue> ContextProvider { get { return context.Value; } }
+
+               public Result ForwardDecode<Data, Result, Visitor>(APC pc, Visitor visitor, Data state)
+                       where Visitor : IILVisitor<APC, SymbolicValue, SymbolicValue, Data, Result>
+               {
+                       return this.stack_decoder.ForwardDecode<Data, Result, StackToSymbolicAdapter<Data, Result, Visitor>> 
+                               (pc, new StackToSymbolicAdapter<Data, Result, Visitor> (this.parent, visitor), state);
+               }
+
+               public bool IsUnreachable(APC pc)
+               {
+                       return this.parent.IsUnreachable (pc);
+               }
+
+               public IImmutableMap<SymbolicValue, LispList<SymbolicValue>> EdgeData(APC from, APC to)
+               {
+                       if (!this.parent.RenamePoints.ContainsKey(from, to))
+                               return null;
+                       if (this.parent.MergeInfoCache.ContainsKey(to) && this.parent.MergeInfoCache[to] == null)
+                               return null;
+
+                       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 )
+               {
+                       if (edgeData == null)
+                               return;
+                       edgeData.Visit ((key, targets) => {
+                                               tw.Write ("  {0} -> ", key);
+                                               foreach (var target in targets.AsEnumerable ())
+                                                       tw.Write ("{0} ", target);
+                                               tw.WriteLine ();
+                                               return VisitStatus.ContinueVisit;
+                                       });
+               }
+
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Wrapper.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.HeapAnalysis/Wrapper.cs
new file mode 100644 (file)
index 0000000..587eb95
--- /dev/null
@@ -0,0 +1,191 @@
+// 
+// Wrapper.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
+       class Wrapper<T> : SymFunction {
+               public readonly T Item;
+               protected PathElementBase PathElement = null;
+
+               public Wrapper (T item, ref int idGen, IMetaDataProvider metaDataProvider)
+                       : base (ref idGen, metaDataProvider)
+               {
+                       this.Item = item;
+               }
+
+               #region Overrides of SymFunction
+               public override bool ActsAsField
+               {
+                       get { return this.Item is Field; }
+               }
+
+               public override bool IsVirtualMethod
+               {
+                       get { return this.Item is Method && this.MetaDataProvider.IsVirtual ((Method) (object) this.Item); }
+               }
+
+               public override bool KeepAsBottomField
+               {
+                       get
+                       {
+                               var str = this.Item as string;
+                               if (str == null)
+                                       return true;
+
+                               return str != "$UnaryNot" && str != "$NeZero";
+                       }
+               }
+
+               public override bool ManifestField
+               {
+                       get
+                       {
+                               var str = this.Item as string;
+                               if (str != null)
+                                       return str == "$Value" || str == "$Length";
+
+                               return (this.Item is Field || this.Item is Method);
+                       }
+               }
+
+               public override bool IsStatic
+               {
+                       get
+                       {
+                               if (this.Item is Field)
+                                       return this.MetaDataProvider.IsStatic ((Field) (object) this.Item);
+                               if (this.Item is Method)
+                                       return this.MetaDataProvider.IsStatic ((Method) (object) this.Item);
+
+                               return false;
+                       }
+               }
+
+               public override bool IfRootIsParameter
+               {
+                       get
+                       {
+                               if (this.Item is Field)
+                                       return !this.MetaDataProvider.IsStatic ((Field) (object) this.Item);
+                               if (this.Item is Method)
+                                       return !this.MetaDataProvider.IsStatic ((Method) (object) this.Item);
+                               if (this.Item is Parameter)
+                                       return true;
+                               if (this.Item is Local)
+                                       return false;
+
+                               return true;
+                       }
+               }
+
+               public override bool IsAsVisibleAs (Method method)
+               {
+                       if (this.Item is Field)
+                               return this.MetaDataProvider.IsAsVisibleAs ((Field) (object) this.Item, method);
+                       if (this.Item is Method)
+                               return this.MetaDataProvider.IsAsVisibleAs ((Method) (object) this.Item, method);
+                       if (this.MetaDataProvider.IsConstructor (method) && this.Item is Parameter
+                           && this.MetaDataProvider.Name ((Parameter) (object) this.Item) == "this")
+                               return false;
+
+                       return true;
+               }
+
+               public override bool IsVisibleFrom (Method method)
+               {
+                       TypeNode declaringType = this.MetaDataProvider.DeclaringType (method);
+                       if (this.Item is Field) {
+                               var f = ((Field) (object) this.Item);
+                               return this.MetaDataProvider.IsVisibleFrom (f, declaringType);
+                       }
+
+                       if (this.Item is Method)
+                               this.MetaDataProvider.IsVisibleFrom ((Method) (object) this.Item, declaringType);
+                       if (this.Item is Parameter)
+                               this.MetaDataProvider.Equal (this.MetaDataProvider.DeclaringMethod ((Parameter) (object) this.Item), method);
+                       if (this.Item is Local) {
+                               var local = (Local) (object) this.Item;
+                               IIndexable<Local> locals = this.MetaDataProvider.Locals (method);
+                               for (int i = 0; i < locals.Count; i++) {
+                                       if (locals [i].Equals (local))
+                                               return true;
+                               }
+                               return false;
+                       }
+                       return true;
+               }
+
+               public override TypeNode FieldAddressType ()
+               {
+                       if (this.Item is Field)
+                               return this.MetaDataProvider.ManagedPointer (this.MetaDataProvider.FieldType ((Field) (object) this.Item));
+
+                       throw new InvalidOperationException ();
+               }
+
+               public override PathElementBase ToPathElement (bool tryCompact)
+               {
+                       throw new NotImplementedException ();
+               }
+               #endregion
+
+               public TypeNode Type { get; set; }
+
+               public override string ToString ()
+               {
+                       if (typeof (T).Equals (typeof (int)))
+                               return String.Format ("s{0}", this.Item);
+                       if (this.Item is Field) {
+                               var field = (Field) (object) this.Item;
+                               if (this.MetaDataProvider.IsStatic (field)) {
+                                       return String.Format ("{0}.{1}",
+                                                             this.MetaDataProvider.FullName (this.MetaDataProvider.DeclaringType (field)),
+                                                             this.MetaDataProvider.Name (field));
+                               }
+
+                               return this.MetaDataProvider.Name (field);
+                       }
+                       if (this.Item is Method) {
+                               var method = (Method) (object) this.Item;
+                               if (this.MetaDataProvider.IsStatic (method)) {
+                                       return String.Format ("{0}.{1}",
+                                                             this.MetaDataProvider.FullName (this.MetaDataProvider.DeclaringType (method)),
+                                                             this.MetaDataProvider.Name (method));
+                               }
+
+                               return this.MetaDataProvider.Name (method);
+                       }
+
+                       return this.Item.ToString ();
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..0f67402
--- /dev/null
@@ -0,0 +1,418 @@
+// 
+// Analysis.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.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.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>> ();
+               private readonly IMethodDriver<E, V> method_driver;
+               private IFixPointInfo<APC, Domain<E, V>> fix_point_info;
+
+               public Analysis (IMethodDriver<E, V> mdriver)
+               {
+                       this.method_driver = mdriver;
+               }
+
+               protected internal IExpressionContextProvider<E, V> ContextProvider
+               {
+                       get { return this.method_driver.ContextProvider; }
+               }
+
+               protected IMetaDataProvider MetaDataProvider
+               {
+                       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 ()
+               {
+                       return this;
+               }
+
+               public Domain<E, V> Join (Pair<APC, APC> edge, Domain<E, V> newstate, Domain<E, V> prevstate, out bool weaker, bool widen)
+               {
+                       bool nonNullWeaker;
+                       SetDomain<V> nonNulls = prevstate.NonNulls.Join (newstate.NonNulls, widen, out nonNullWeaker);
+                       bool nullWeaker;
+                       SetDomain<V> nulls = prevstate.Nulls.Join (newstate.Nulls, widen, out nullWeaker);
+
+                       weaker = nonNullWeaker || nullWeaker;
+                       return new Domain<E, V> (nonNulls, nulls);
+               }
+
+               public Domain<E, V> ImmutableVersion (Domain<E, V> state)
+               {
+                       return state;
+               }
+
+               public Domain<E, V> MutableVersion (Domain<E, V> state)
+               {
+                       return state;
+               }
+
+               public Domain<E, V> EdgeConversion (APC from, APC to, bool isJoinPoint, IImmutableMap<V, LispList<V>> data, Domain<E, V> state)
+               {
+                       if (data == null)
+                               return state;
+                       SetDomain<V> oldNonNulls = state.NonNulls;
+                       SetDomain<V> nonNulls = SetDomain<V>.TopValue;
+
+                       SetDomain<V> oldNulls = state.Nulls;
+                       SetDomain<V> nulls = SetDomain<V>.TopValue;
+                       foreach (V variable in data.Keys) {
+                               bool nonNullContains = oldNonNulls.Contains (variable);
+                               bool nullContains = oldNulls.Contains (variable);
+
+                               if (nonNullContains || nullContains) {
+                                       foreach (V anotherVariable in data [variable].AsEnumerable ()) {
+                                               if (nonNullContains)
+                                                       nonNulls = nonNulls.Add (anotherVariable);
+                                               if (nullContains)
+                                                       nulls = nulls.Add (anotherVariable);
+                                       }
+                               }
+                       }
+
+                       return new Domain<E, V> (nonNulls, nulls);
+               }
+
+               public bool IsBottom (APC pc, Domain<E, V> state)
+               {
+                       return state.NonNulls.IsBottom;
+               }
+
+               public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, Domain<E, V>> fixPointInfo)
+               {
+                       this.fix_point_info = fixPointInfo;
+
+                       //todo: implement this
+                       return pc => true;
+               }
+
+               public void Dump (Pair<Domain<E, V>, TextWriter> pair)
+               {
+                       TextWriter tw = pair.Value;
+                       tw.Write ("NonNulls: ");
+                       pair.Key.NonNulls.Dump (tw);
+                       tw.Write ("Nulls: ");
+                       pair.Key.Nulls.Dump (tw);
+               }
+               #endregion
+
+               #region IFactBase<V> Members
+               public ProofOutcome IsNull (APC pc, V variable)
+               {
+                       if (ContextProvider.ValueContext.IsZero (pc, variable))
+                               return ProofOutcome.True;
+
+                       Domain<E, V> domain;
+                       if (!PreStateLookup (pc, out domain) || domain.NonNulls.IsBottom)
+                               return ProofOutcome.Bottom;
+                       if (domain.IsNonNull (variable))
+                               return ProofOutcome.False;
+                       if (domain.IsNull (variable))
+                               return ProofOutcome.True;
+
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsNonNull (APC pc, V variable)
+               {
+                       Domain<E, V> domain;
+                       if (!PreStateLookup (pc, out domain) || domain.NonNulls.IsBottom)
+                               return ProofOutcome.Bottom;
+                       if (domain.IsNonNull (variable))
+                               return ProofOutcome.True;
+                       if (ContextProvider.ValueContext.IsZero (pc, variable) || domain.IsNull (variable))
+                               return ProofOutcome.False;
+
+                       FlatDomain<TypeNode> aType = ContextProvider.ValueContext.GetType (pc, variable);
+                       if (aType.IsNormal && MetaDataProvider.IsManagedPointer (aType.Concrete))
+                               return ProofOutcome.True;
+
+                       return ProofOutcome.Top;
+               }
+
+               public bool IsUnreachable (APC pc)
+               {
+                       Domain<E, V> domain;
+                       if (!PreStateLookup (pc, out domain) || domain.NonNulls.IsBottom)
+                               return true;
+
+                       return false;
+               }
+               #endregion
+
+               public override Domain<E, V> DefaultVisit (APC pc, Domain<E, V> data)
+               {
+                       return data;
+               }
+
+               public static Domain<E, V> AssumeNonNull (V dest, Domain<E, V> before)
+               {
+                       if (!before.NonNulls.Contains (dest))
+                               return new Domain<E, V> (before.NonNulls.Add (dest), before.Nulls);
+                       return before;
+               }
+
+               public static Domain<E, V> AssumeNull (V dest, Domain<E, V> before)
+               {
+                       if (!before.Nulls.Contains (dest))
+                               return new Domain<E, V> (before.NonNulls, before.Nulls.Add (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 Domain<E, V> Assume (APC pc, EdgeTag tag, V condition, Domain<E, 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>>
+                               (expr, new ExpressionAssumeDecoder<E, V> (ContextProvider),
+                                new Pair<bool, Domain<E, 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)
+               {
+                       switch (op) {
+                       case UnaryOperator.Conv_i:
+                       case UnaryOperator.Conv_u:
+                               if (data.IsNonNull (source))
+                                       return AssumeNonNull (dest, data);
+                               break;
+                       }
+                       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)
+               {
+                       this.callSiteCache [pc] = data;
+                       if (!MetaDataProvider.IsStatic (method))
+                               return AssumeNonNull (args [0], data);
+
+                       return data;
+               }
+
+               public override Domain<E, V> CastClass (APC pc, TypeNode type, V dest, V obj, Domain<E, V> data)
+               {
+                       if (data.NonNulls.Contains (obj))
+                               return AssumeNonNull (dest, data);
+
+                       return data;
+               }
+
+               public override Domain<E, V> Entry (APC pc, Method method, Domain<E, V> data)
+               {
+                       APC at = ContextProvider.MethodContext.CFG.Next (pc);
+                       Domain<E, V> domain = data;
+                       IIndexable<Parameter> parameters = MetaDataProvider.Parameters (method);
+                       TypeNode eventArgsType;
+                       bool systemType = MetaDataProvider.TryGetSystemType ("System.EventArgs", out eventArgsType);
+                       for (int i = 0; i < parameters.Count; i++) {
+                               Parameter p = parameters [i];
+                               TypeNode pType = MetaDataProvider.ParameterType (p);
+                               if (MetaDataProvider.IsManagedPointer (pType)) {
+                                       V sv;
+                                       if (ContextProvider.ValueContext.TryParameterValue (at, p, out sv))
+                                               domain = AssumeNonNull (sv, domain);
+                               } else {
+                                       V sv;
+                                       if (i == 0 && parameters.Count == 1 && MetaDataProvider.IsArray (pType)
+                                           && MetaDataProvider.Name (method) == "Main" && MetaDataProvider.IsStatic (method) &&
+                                           ContextProvider.ValueContext.TryParameterValue (pc, p, out sv))
+                                               domain = AssumeNonNull (sv, domain);
+                               }
+                       }
+                       V sv1;
+                       if (systemType && parameters.Count == 2 && MetaDataProvider.Equal (MetaDataProvider.System_Object, MetaDataProvider.ParameterType (parameters [0])) &&
+                           MetaDataProvider.DerivesFrom (MetaDataProvider.ParameterType (parameters [1]), eventArgsType)
+                           && ContextProvider.ValueContext.TryParameterValue (pc, parameters [1], out sv1))
+                               domain = AssumeNonNull (sv1, domain);
+                       if (!MetaDataProvider.IsStatic (method) && ContextProvider.ValueContext.TryParameterValue (pc, MetaDataProvider.This (method), out sv1))
+                               domain = AssumeNonNull (sv1, domain);
+
+                       return domain;
+               }
+
+               public override Domain<E, V> LoadStack (APC pc, int offset, V dest, V source, bool isOld, Domain<E, V> data)
+               {
+                       Domain<E, V> old;
+                       if (isOld && TryFindOldState (pc, out old)) {
+                               if (old.IsNonNull (source))
+                                       return AssumeNonNull (dest, data);
+                               if (old.IsNull (source))
+                                       return AssumeNull (dest, data);
+                       }
+
+                       return data;
+               }
+
+               public override Domain<E, V> Isinst (APC pc, TypeNode type, V dest, V obj, Domain<E, V> data)
+               {
+                       if (data.IsNonNull (obj)) {
+                               FlatDomain<TypeNode> aType = ContextProvider.ValueContext.GetType (pc, obj);
+                               if (aType.IsNormal && MetaDataProvider.DerivesFrom (aType.Concrete, 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)
+               {
+                       return AssumeNonNull (dest, data);
+               }
+
+               public override Domain<E, V> LoadConst (APC pc, TypeNode type, object constant, V dest, Domain<E, V> data)
+               {
+                       if (constant is string)
+                               return AssumeNonNull (dest, data);
+
+                       return data;
+               }
+
+               public override Domain<E, V> LoadElement (APC pc, TypeNode type, V dest, V array, V index, Domain<E, V> data)
+               {
+                       return AssumeNonNull (array, data);
+               }
+
+               public override Domain<E, V> LoadField (APC pc, Field field, V dest, V obj, Domain<E, V> data)
+               {
+                       Domain<E, V> domain = AssumeNonNull (obj, data);
+                       FlatDomain<TypeNode> aType = ContextProvider.ValueContext.GetType (ContextProvider.MethodContext.CFG.Next (pc), dest);
+                       if (aType.IsNormal && MetaDataProvider.IsManagedPointer (aType.Concrete))
+                               domain = AssumeNonNull (dest, domain);
+
+                       return domain;
+               }
+
+               public override Domain<E, V> LoadFieldAddress (APC pc, Field field, V dest, V obj, Domain<E, V> data)
+               {
+                       Domain<E, 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)
+               {
+                       return AssumeNonNull (dest, data);
+               }
+
+               public override Domain<E, V> LoadLength (APC pc, V dest, V array, Domain<E, 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)
+               {
+                       return AssumeNonNull (dest, data);
+               }
+
+               public override Domain<E, V> NewObj<ArgList> (APC pc, Method ctor, V dest, ArgList args, Domain<E, 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)
+               {
+                       return AssumeNonNull (array, data);
+               }
+
+               public override Domain<E, V> StoreField (APC pc, Field field, V obj, V value, Domain<E, V> data)
+               {
+                       return AssumeNonNull (obj, data);
+               }
+
+               private bool TryFindOldState (APC pc, out Domain<E, 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;
+               }
+
+               public Domain<E, V> InitialValue (Func<V, int> keyConverter)
+               {
+                       return new Domain<E, V> (new SetDomain<V> (keyConverter), new SetDomain<V> (keyConverter));
+               }
+
+               #region Implementation of IMethodResult<Variable>
+               public IMethodAnalysis MethodAnalysis { get; set; }
+
+               public void ValidateImplicitAssertions (IFactQuery<BoxedExpression, V> facts, List<string> proofResults)
+               {
+               }
+
+               public IFactQuery<BoxedExpression, V> FactQuery
+               {
+                       get { return new SimpleLogicInference<E, V> (ContextProvider, this, this.method_driver.BasicFacts.IsUnreachable); }
+               }
+
+               public ProofOutcome ValidateExplicitAssertion (APC pc, V value)
+               {
+                       Domain<E, 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 ProofOutcome.Bottom;
+               }
+
+               private bool PreStateLookup (APC pc, out Domain<E, V> domain)
+               {
+                       return this.fix_point_info.PreStateLookup (pc, out domain);
+               }
+               #endregion
+               }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Domain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.NonNull/Domain.cs
new file mode 100644 (file)
index 0000000..84f3956
--- /dev/null
@@ -0,0 +1,58 @@
+// 
+// Domain.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 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);
+
+               public SetDomain<V> NonNulls;
+               public SetDomain<V> Nulls;
+
+               public Domain(SetDomain<V> nonNulls, SetDomain<V> nulls)
+               {
+                       this.NonNulls = nonNulls;
+                       this.Nulls = nulls;
+               }
+
+               public bool IsNonNull(V v)
+               {
+                       return this.NonNulls.Contains (v);
+               }
+
+               public bool IsNull(V v)
+               {
+                       return this.Nulls.Contains (v);
+               }
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..ba6a87b
--- /dev/null
@@ -0,0 +1,133 @@
+// 
+// ExpressionAssertDischarger.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Analysis.NonNull {
+       struct ExpressionAssertDischarger<E, V> 
+               : ISymbolicExpressionVisitor<E, E, V, bool, ProofOutcome> 
+               where E : IEquatable<E> 
+               where V : IEquatable<V> {
+               private readonly Analysis<E, V> analysis;
+               private readonly APC pc;
+
+               public ExpressionAssertDischarger(Analysis<E, V> analysis, APC pc)
+               {
+                       this.analysis = analysis;
+                       this.pc = pc;
+               }
+
+               private IExpressionContextProvider<E, V> ContextProvider
+               {
+                       get { return this.analysis.ContextProvider; }
+               } 
+
+               #region Implementation of IExpressionILVisitor<Expression,Expression,Variable,bool,ProofOutcome>
+               private ProofOutcome Recurse(bool polarity, E expr)
+               {
+                       return this.ContextProvider.ExpressionContext.Decode<bool, ProofOutcome, ExpressionAssertDischarger<E, V>> (expr, this, polarity);
+               }
+
+               public ProofOutcome Binary(E orig, BinaryOperator op, V dest, E operand1, E operand2, bool polarity)
+               {
+                       switch (op) {
+                       case BinaryOperator.Ceq:
+                       case BinaryOperator.Cobjeq:
+                               if (this.ContextProvider.ExpressionContext.IsZero (operand2) || this.ContextProvider.ExpressionContext.IsZero (operand1))
+                                       return this.Recurse (!polarity, operand1);
+                               return ProofOutcome.Top;
+                       case BinaryOperator.Cne_Un:
+                               if (this.ContextProvider.ExpressionContext.IsZero(operand2) || this.ContextProvider.ExpressionContext.IsZero(operand1))
+                                       return this.Recurse (polarity, operand1);
+                               return ProofOutcome.Top;
+                       default:
+                               return this.SymbolicConstant (orig, this.ContextProvider.ExpressionContext.Unrefine (orig), polarity);
+                       }
+               }
+
+               public ProofOutcome 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);
+
+                       return outcome != ProofOutcome.True ? outcome : this.Recurse (true, obj);
+               }
+
+               public ProofOutcome 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)
+               {
+                       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)
+               {
+                       return polarity ? ProofOutcome.True : ProofOutcome.False;
+               }
+
+               public ProofOutcome Unary(E orig, UnaryOperator op, bool unsigned, V dest, E source, bool polarity)
+               {
+                       switch (op) {
+                       case UnaryOperator.Conv_i:
+                       case UnaryOperator.Conv_i1:
+                       case UnaryOperator.Conv_i2:
+                       case UnaryOperator.Conv_i4:
+                       case UnaryOperator.Conv_i8:
+                       case UnaryOperator.Conv_u:
+                       case UnaryOperator.Conv_u1:
+                       case UnaryOperator.Conv_u2:
+                       case UnaryOperator.Conv_u4:
+                       case UnaryOperator.Conv_u8:
+                               return this.Recurse (polarity, source);
+                       case UnaryOperator.Neg:
+                               return this.Recurse(polarity, source);
+                       case UnaryOperator.Not:
+                               return this.Recurse(!polarity, source);
+                       default:
+                               return this.SymbolicConstant (orig, this.ContextProvider.ExpressionContext.Unrefine (orig), polarity);
+                       }
+               }
+               #endregion
+
+               #region Implementation of ISymbolicExpressionVisitor<Expression,Expression,Variable,bool,ProofOutcome>
+               public ProofOutcome SymbolicConstant(E pc, V variable, bool polarity)
+               {
+                       return polarity ? this.analysis.IsNonNull (this.pc, variable) : this.analysis.IsNull(this.pc, variable);
+               }
+               #endregion
+       }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..0feed97
--- /dev/null
@@ -0,0 +1,153 @@
+// 
+// ExpressionAssumeDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+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>>
+               where V : IEquatable<V>
+               where E : IEquatable<E> {
+               private readonly IExpressionContextProvider<E, V> context_provider;
+
+               public ExpressionAssumeDecoder (IExpressionContextProvider<E, V> contextProvider)
+               {
+                       this.context_provider = contextProvider;
+               }
+
+               #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)
+               {
+                       IExpressionContext<E, V> exprCtx = this.context_provider.ExpressionContext;
+                       switch (op) {
+                       case BinaryOperator.Ceq:
+                       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);
+                               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;
+                       case BinaryOperator.Cne_Un:
+                               if (data.Value.IsNull (exprCtx.Unrefine (operand2)) || exprCtx.IsZero (operand2)
+                                   || data.Value.IsNull (exprCtx.Unrefine (operand1)) || exprCtx.IsZero (operand1))
+                                       return Recurse (data, operand1);
+
+                               return data.Value;
+                       default:
+                               return data.Value;
+                       }
+               }
+
+               public Domain<E, V> Isinst (E pc, TypeNode type, V dest, E obj, Pair<bool, Domain<E, V>> data)
+               {
+                       if (data.Key)
+                               return Recurse (new Pair<bool, Domain<E, 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)
+               {
+                       if (data.Key)
+                               return Domain<E, V>.BottomValue;
+                       return data.Value;
+               }
+
+               public Domain<E, V> LoadConst (E pc, TypeNode type, object constant, V dest, Pair<bool, Domain<E, V>> data)
+               {
+                       if (constant is string)
+                               return data.Value;
+
+                       var convertible = constant as IConvertible;
+                       bool isZero = false;
+                       if (convertible != null) {
+                               try {
+                                       isZero = convertible.ToInt32 (null) == 0;
+                               } catch {
+                                       return data.Value;
+                               }
+                       }
+
+                       if (data.Key && isZero || !data.Key && !isZero)
+                               return Domain<E, V>.BottomValue;
+
+                       return data.Value;
+               }
+
+               public Domain<E, V> Sizeof (E pc, TypeNode type, V dest, Pair<bool, Domain<E, 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)
+               {
+                       switch (op) {
+                       case UnaryOperator.Conv_i:
+                       case UnaryOperator.Conv_i1:
+                       case UnaryOperator.Conv_i2:
+                       case UnaryOperator.Conv_i4:
+                       case UnaryOperator.Conv_i8:
+                       case UnaryOperator.Conv_u:
+                       case UnaryOperator.Conv_u1:
+                       case UnaryOperator.Conv_u2:
+                       case UnaryOperator.Conv_u4:
+                       case UnaryOperator.Conv_u8:
+                               return Recurse (data, source);
+                       case UnaryOperator.Neg:
+                               return Recurse (data, source);
+                       case UnaryOperator.Not:
+                               return Recurse (new Pair<bool, Domain<E, 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)
+               {
+                       if (data.Key) {
+                               return !this.context_provider.ExpressionContext.IsZero (orig)
+                                       ? Domain<E, V>.BottomValue
+                                       : Analysis<E, V>.AssumeNonNull (variable, data.Value);
+                       }
+
+                       if (data.Value.NonNulls.Contains (variable))
+                               return Domain<E, V>.BottomValue;
+
+                       return Analysis<E, V>.AssumeNull (variable, data.Value);
+               }
+               #endregion
+
+               private Domain<E, V> Recurse (Pair<bool, Domain<E, V>> pair, E expr)
+               {
+                       return this.context_provider.ExpressionContext.Decode<Pair<bool, Domain<E, V>>, Domain<E, 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
new file mode 100644 (file)
index 0000000..ec5a227
--- /dev/null
@@ -0,0 +1,53 @@
+// 
+// NonNullAnalysisFacade.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 Mono.CodeContracts.Static.Analysis.Drivers;
+
+namespace Mono.CodeContracts.Static.Analysis.NonNull {
+       class NonNullAnalysisFacade : IMethodAnalysis {
+               #region IMethodAnalysis Members
+               public string Name
+               {
+                       get { return "Non-null"; }
+               }
+
+               public IMethodResult<Variable> Analyze<Expression, Variable>
+                       (string fullMethodName, IMethodDriver<Expression, Variable> methodDriver)
+                       where Expression : IEquatable<Expression>
+                       where Variable : IEquatable<Variable>
+               {
+                       var analysis = new Analysis<Expression, Variable> (methodDriver);
+                       methodDriver.HybridLayer.CreateForward (analysis) (analysis.InitialValue (methodDriver.KeyConverter));
+                       analysis.MethodAnalysis = this;
+
+                       return analysis;
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..2f21c67
--- /dev/null
@@ -0,0 +1,92 @@
+// 
+// APCMap.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.Collections.Generic;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.StackAnalysis {
+       class APCMap<T> {
+               private readonly Dictionary<int, T>[] block_map;
+               private IImmutableIntMap<bool> call_on_this_map;
+
+               public APCMap (Subroutine parent)
+               {
+                       this.block_map = new Dictionary<int, T>[parent.BlockCount];
+                       this.call_on_this_map = ImmutableIntMap<bool>.Empty ();
+               }
+
+               public T this [APC key]
+               {
+                       get
+                       {
+                               T value;
+                               if (!TryGetValue (key, out value))
+                                       throw new KeyNotFoundException ();
+                               return value;
+                       }
+               }
+
+               public void Add (APC pc, T value)
+               {
+                       Dictionary<int, T> pcBlockMap = this.block_map [pc.Block.Index];
+                       if (pcBlockMap == null)
+                               this.block_map [pc.Block.Index] = pcBlockMap = new Dictionary<int, T> ();
+
+                       pcBlockMap.Add (pc.Index, value);
+               }
+
+               public bool TryGetValue (APC pc, out T obj)
+               {
+                       Dictionary<int, T> dictionary = this.block_map [pc.Block.Index];
+                       if (dictionary != null)
+                               return dictionary.TryGetValue (pc.Index, out obj);
+
+                       obj = default(T);
+                       return false;
+               }
+
+               public bool ContainsKey (APC pc)
+               {
+                       Dictionary<int, T> dictionary = this.block_map [pc.Block.Index];
+                       if (dictionary == null)
+                               return false;
+                       return dictionary.ContainsKey (pc.Index);
+               }
+
+               public bool IsCallOnThis (APC key)
+               {
+                       return this.call_on_this_map [key.Block.Index];
+               }
+
+               public void AddCallOnThis (APC pc)
+               {
+                       this.call_on_this_map = this.call_on_this_map.Add (pc.Block.Index, true);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/SequenceGenerator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/SequenceGenerator.cs
new file mode 100644 (file)
index 0000000..51dd4e9
--- /dev/null
@@ -0,0 +1,67 @@
+// 
+// SequenceGenerator.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.Collections;
+using System.Collections.Generic;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.StackAnalysis {
+       class SequenceGenerator : IIndexable<int>, IEnumerable<int> {
+               private readonly short count;
+               private readonly short from;
+
+               public SequenceGenerator (int from, int count)
+               {
+                       this.from = checked((short) from);
+                       this.count = checked((short) count);
+               }
+
+               #region Implementation of IIndexable<int>
+               public int Count {
+                       get { return this.count; }
+               }
+
+               public int this [int index] {
+                       get { return this.from + index; }
+               }
+               #endregion
+
+               #region Implementation of IEnumerable
+               public IEnumerator<int> GetEnumerator ()
+               {
+                       for (int i = 0; i < this.count; i++)
+                               yield return this [i];
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..5d0853f
--- /dev/null
@@ -0,0 +1,606 @@
+// 
+// StackDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Analysis.StackAnalysis {
+       struct StackDecoder<TContext, TData, TResult, TVisitor> : IILVisitor<APC, Dummy, Dummy, TData, TResult>
+               where TContext : IMethodContextProvider
+               where TVisitor : IILVisitor<APC, int, int, TData, TResult>
+       {
+               private readonly StackDepthProvider<TContext> parent;
+               private readonly TVisitor visitor;
+
+               public StackDecoder(StackDepthProvider<TContext> parent,
+                                   TVisitor visitor)
+               {
+                       this.parent = parent;
+                       this.visitor = visitor;
+               }
+
+               private int Pop(APC label, int count)
+               {
+                       return this.parent.GlobalStackDepth (label) - 1 - count;
+               }
+
+               private SequenceGenerator PopSequence(APC pc, int args, int offset)
+               {
+                       return new SequenceGenerator (this.parent.GlobalStackDepth (pc) - args - offset, args);
+               }
+
+               private int Push(APC label, int count)
+               {
+                       return this.parent.GlobalStackDepth (label) - count;
+               }
+
+               private int Push(APC label, int args, TypeNode returnType)
+               {
+                       if (this.parent.MetaDataProvider.IsVoid (returnType))
+                               return -1;
+
+                       return Push (label, args);
+               }
+
+               private int GetParametersCount(Method ctor, int extraVarargs)
+               {
+                       int result = extraVarargs + this.parent.MetaDataProvider.Parameters (ctor).Count;
+                       if (!this.parent.MetaDataProvider.IsStatic (ctor))
+                               ++result;
+                       return result;
+               }
+
+               private bool RemapParameterToLoadStack(APC pc, ref Parameter param, out bool isLoadResult, out int loadStackOffset, out bool isOld, out APC lookupPC)
+               {
+                       if (pc.SubroutineContext == null) {
+                               isLoadResult = false;
+                               loadStackOffset = 0;
+                               isOld = false;
+                               lookupPC = pc;
+                               return false;
+                       }
+
+                       if (pc.Block.Subroutine.IsRequires) {
+                               isLoadResult = false;
+                               isOld = false;
+                               lookupPC = pc;
+                               for (LispList<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);
+                                               loadStackOffset = 0;
+                                               return false;
+                                       }
+                                       if (edgeTag.Is (EdgeTag.BeforeMask)) {
+                                               int stackDepth = this.parent.LocalStackDepth (pc);
+                                               loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex (param) + stackDepth;
+                                               return true;
+                                       }
+                               }
+                               throw new InvalidOperationException ();
+                       }
+
+                       if (pc.Block.Subroutine.IsEnsuresOrOldValue) {
+                               isOld = true;
+                               for (LispList<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);
+                                               isLoadResult = false;
+                                               loadStackOffset = 0;
+                                               lookupPC = pc;
+                                               return false;
+                                       }
+
+                                       if (tag == EdgeTag.AfterCall) {
+                                               loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex (param);
+                                               isLoadResult = false;
+                                               lookupPC = new APC (ctx.Head.From, 0, ctx.Tail);
+                                               return true;
+                                       }
+
+                                       if (tag == EdgeTag.AfterNewObj) {
+                                               if (this.parent.MetaDataProvider.ParameterIndex (param) == 0) {
+                                                       loadStackOffset = this.parent.LocalStackDepth (pc);
+                                                       isLoadResult = true;
+                                                       lookupPC = pc;
+                                                       isOld = false;
+                                                       return false;
+                                               }
+
+                                               loadStackOffset = this.parent.MetaDataProvider.ParameterIndex (param);
+                                               isLoadResult = false;
+                                               lookupPC = new APC (ctx.Head.From, 0, ctx.Tail);
+                                               return true;
+                                       }
+                                       if (tag == EdgeTag.OldManifest) {
+                                               param = RemapParameter (param, ctx.Tail.Head.From, pc.Block);
+                                               isOld = false;
+                                               isLoadResult = false;
+                                               loadStackOffset = 0;
+                                               lookupPC = pc;
+                                               return false;
+                                       }
+                               }
+                               throw new InvalidOperationException ();
+                       }
+
+                       if (pc.Block.Subroutine.IsInvariant) {
+                               for (LispList<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;
+                                               if (pc.TryGetContainingMethod (out method)) {
+                                                       param = this.parent.MetaDataProvider.This (method);
+                                                       isLoadResult = false;
+                                                       loadStackOffset = 0;
+                                                       isOld = tag == EdgeTag.Exit;
+                                                       lookupPC = pc;
+                                                       return false;
+                                               }
+                                               isLoadResult = false;
+                                               loadStackOffset = 0;
+                                               isOld = false;
+                                               lookupPC = pc;
+                                               return false;
+                                       }
+                                       if (tag == EdgeTag.AfterCall) {
+                                               Method calledMethod;
+                                               bool isNewObj;
+                                               bool isVirtual;
+                                               list.Head.From.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual);
+                                               int count = this.parent.MetaDataProvider.Parameters (calledMethod).Count;
+                                               loadStackOffset = count;
+                                               isLoadResult = false;
+                                               isOld = true;
+                                               lookupPC = new APC (list.Head.From, 0, list.Tail);
+                                               return true;
+                                       }
+                                       if (tag == EdgeTag.AfterNewObj) {
+                                               isLoadResult = true;
+                                               loadStackOffset = this.parent.LocalStackDepth (pc);
+                                               isOld = false;
+                                               lookupPC = pc;
+                                               return false;
+                                       }
+                                       if (tag.Is (EdgeTag.BeforeMask))
+                                               throw new InvalidOperationException ("this should never happen");
+                               }
+                               throw new InvalidOperationException ("this should never happen");
+                       }
+
+                       isLoadResult = false;
+                       loadStackOffset = 0;
+                       isOld = false;
+                       lookupPC = pc;
+                       return false;
+               }
+
+               private Parameter RemapParameter(Parameter p, CFGBlock parentMethodBlock, CFGBlock subroutineBlock)
+               {
+                       Method parentMethod = ((IMethodInfo) parentMethodBlock.Subroutine).Method;
+                       Method method = ((IMethodInfo) subroutineBlock.Subroutine).Method;
+
+                       if (this.parent.MetaDataProvider.Equal (method, parentMethod))
+                               return p;
+
+                       int index = this.parent.MetaDataProvider.ParameterIndex (p);
+                       if (this.parent.MetaDataProvider.IsStatic (parentMethod) || index != 0)
+                               return this.parent.MetaDataProvider.Parameters (parentMethod)[index];
+
+                       return this.parent.MetaDataProvider.This (parentMethod);
+               }
+
+               private bool IsReferenceType(APC pc, TypeNode type)
+               {
+                       return this.parent.MetaDataProvider.IsReferenceType (type);
+               }
+
+               private TypeNode GetSpecializedType(APC pc, TypeNode type)
+               {
+                       var methodInfo = pc.Block.Subroutine as IMethodInfo;
+                       if (methodInfo == null)
+                               return type;
+
+                       throw new NotImplementedException ();
+               }
+
+               #region Implementation of IExpressionILVisitor<APC,Type,Dummy,Dummy,Data,Result>
+               public TResult Binary(APC pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, TData data)
+               {
+                       return this.visitor.Binary (pc, op, Push (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult Isinst(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.Isinst (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult LoadNull(APC pc, Dummy dest, TData polarity)
+               {
+                       return this.visitor.LoadNull (pc, Push (pc, 0), polarity);
+               }
+
+               public TResult LoadConst(APC pc, TypeNode type, object constant, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadConst (pc, type, constant, Push (pc, 0), data);
+               }
+
+               public TResult Sizeof(APC pc, TypeNode type, Dummy dest, TData data)
+               {
+                       return this.visitor.Sizeof (pc, type, Push (pc, 0), data);
+               }
+
+               public TResult Unary(APC pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, TData data)
+               {
+                       return this.visitor.Unary (pc, op, unsigned, Push (pc, 1), Pop (pc, 0), data);
+               }
+               #endregion
+
+               #region Implementation of ISyntheticILVisitor<APC,Method,Field,Type,Dummy,Dummy,Data,Result>
+               public TResult Entry(APC pc, Method method, TData data)
+               {
+                       return this.visitor.Entry (pc, method, data);
+               }
+
+               public TResult Assume(APC pc, EdgeTag tag, Dummy condition, TData data)
+               {
+                       return this.visitor.Assume (pc, tag, Pop (pc, 0), data);
+               }
+
+               public TResult Assert(APC pc, EdgeTag tag, Dummy condition, TData data)
+               {
+                       return this.visitor.Assert (pc, tag, Pop (pc, 0), data);
+               }
+
+               public TResult BeginOld(APC pc, APC matchingEnd, TData data)
+               {
+                       return this.visitor.BeginOld (pc, matchingEnd, data);
+               }
+
+               public TResult EndOld(APC pc, APC matchingBegin, TypeNode type, Dummy dest, Dummy source, TData data)
+               {
+                       if (pc.InsideOldManifestation)
+                               return this.visitor.LoadStack (pc, 1, Push (matchingBegin, 0), Pop (pc, 0), false, data);
+
+                       return this.visitor.EndOld (pc, matchingBegin, type, Push (matchingBegin, 0), Pop (pc, 0), data);
+               }
+
+               public TResult LoadStack(APC pc, int offset, Dummy dest, Dummy source, bool isOld, TData data)
+               {
+                       return this.visitor.LoadStack (pc, offset, Push (pc, 0), Pop (pc, offset), isOld, data);
+               }
+
+               public TResult LoadStackAddress(APC pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, TData data)
+               {
+                       return this.visitor.LoadStackAddress (pc, offset, Push (pc, 0), Pop (pc, offset), type, isOld, data);
+               }
+
+               public TResult LoadResult(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)
+               {
+                       int offset = this.parent.LocalStackDepth (pc);
+                       return this.visitor.LoadResult (pc, type, Push (pc, 0), Pop (pc, offset), data);
+               }
+               #endregion
+
+               #region Implementation of IILVisitor<APC,Local,Parameter,Method,Field,Type,Dummy,Dummy,Data,Result>
+               public TResult Arglist(APC pc, Dummy dest, TData data)
+               {
+                       return this.visitor.Arglist (pc, Push (pc, 0), data);
+               }
+
+               public TResult Branch(APC pc, APC target, bool leavesExceptionBlock, TData data)
+               {
+                       return this.visitor.Branch (pc, target, leavesExceptionBlock, data);
+               }
+
+               public TResult BranchCond(APC pc, APC target, BranchOperator bop, Dummy value1, Dummy value2, TData data)
+               {
+                       return this.visitor.BranchCond (pc, target, bop, Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult BranchTrue(APC pc, APC target, Dummy cond, TData data)
+               {
+                       return this.visitor.BranchTrue (pc, target, Pop (pc, 0), data);
+               }
+
+               public TResult BranchFalse(APC pc, APC target, Dummy cond, TData data)
+               {
+                       return this.visitor.BranchFalse (pc, target, Pop (pc, 0), data);
+               }
+
+               public TResult Break(APC pc, TData data)
+               {
+                       return this.visitor.Break (pc, data);
+               }
+
+               public TResult Call<TypeList, ArgList>(APC pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, TData data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int argsCount = GetParametersCount (method, extraVarargs == null ? 0 : extraVarargs.Count);
+                       return this.visitor.Call (pc, method, virt, extraVarargs, Push (pc, argsCount, this.parent.MetaDataProvider.ReturnType (method)), PopSequence (pc, argsCount, 0), data);
+               }
+
+               public TResult Calli<TypeList, ArgList>(APC pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, TData data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int argsCount = argTypes.Count + (instance ? 1 : 0);
+                       return this.visitor.Calli (pc, returnType, argTypes, instance, Push (pc, argsCount + 1, returnType), Pop (pc, 0), PopSequence (pc, argsCount, 1), data);
+               }
+
+               public TResult CheckFinite(APC pc, Dummy dest, Dummy source, TData data)
+               {
+                       return this.visitor.CheckFinite (pc, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult CopyBlock(APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, TData data)
+               {
+                       return this.visitor.CopyBlock (pc, Pop (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult EndFilter(APC pc, Dummy decision, TData data)
+               {
+                       return this.visitor.EndFilter (pc, Pop (pc, 0), data);
+               }
+
+               public TResult EndFinally(APC pc, TData data)
+               {
+                       return this.visitor.EndFinally (pc, data);
+               }
+
+               public TResult Jmp(APC pc, Method method, TData data)
+               {
+                       return this.visitor.Jmp (pc, method, data);
+               }
+
+               public TResult LoadArg(APC pc, Parameter argument, bool dummyOld, Dummy dest, TData data)
+               {
+                       Parameter p = argument;
+                       bool isLdResult;
+                       int loadStackOffset;
+                       bool isOld;
+                       APC lookupPC;
+                       if (RemapParameterToLoadStack (pc, ref argument, out isLdResult, out loadStackOffset, out isOld, out lookupPC))
+                               return this.visitor.LoadStack (pc, loadStackOffset, Push (pc, 0), Pop (lookupPC, loadStackOffset), isOld, data);
+
+                       if (argument == null)
+                               argument = p;
+
+                       if (isLdResult) {
+                               if (this.parent.MetaDataProvider.IsStruct (this.parent.MetaDataProvider.DeclaringType (this.parent.MetaDataProvider.DeclaringMethod (argument))))
+                                       return this.visitor.LoadStackAddress (pc, loadStackOffset, Push (pc, 0), Pop (pc, loadStackOffset), this.parent.MetaDataProvider.ParameterType (argument), isOld, data);
+
+                               return this.visitor.LoadResult (pc, this.parent.MetaDataProvider.ParameterType (argument), Push (pc, 0), Pop (pc, loadStackOffset), data);
+                       }
+
+                       return this.visitor.LoadArg (pc, argument, isOld, Push (pc, 0), data);
+               }
+
+               public TResult LoadArgAddress(APC pc, Parameter argument, bool dummyOld, Dummy dest, TData data)
+               {
+                       bool isLoadResult;
+                       int loadStackOffset;
+                       bool isOld;
+                       APC lookupPC;
+                       if (RemapParameterToLoadStack (pc, ref argument, out isLoadResult, out loadStackOffset, out isOld, out lookupPC))
+                               return this.visitor.LoadStackAddress (pc, loadStackOffset, Push (pc, 0), Pop (lookupPC, loadStackOffset), this.parent.MetaDataProvider.ParameterType (argument), isOld, data);
+
+                       if (isLoadResult)
+                               throw new InvalidOperationException ();
+
+                       return this.visitor.LoadArgAddress (pc, argument, isOld, Push (pc, 0), data);
+               }
+
+               public TResult LoadLocal(APC pc, Local local, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadLocal (pc, local, Push (pc, 0), data);
+               }
+
+               public TResult LoadLocalAddress(APC pc, Local local, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadLocalAddress (pc, local, Push (pc, 0), data);
+               }
+
+               public TResult Nop(APC pc, TData data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public TResult Pop(APC pc, Dummy source, TData data)
+               {
+                       return this.visitor.Pop (pc, Pop (pc, 0), data);
+               }
+
+               public TResult Return(APC pc, Dummy source, TData data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public TResult StoreArg(APC pc, Parameter argument, Dummy source, TData data)
+               {
+                       return this.visitor.StoreArg (pc, argument, Pop (pc, 0), data);
+               }
+
+               public TResult StoreLocal(APC pc, Local local, Dummy source, TData data)
+               {
+                       return this.visitor.StoreLocal (pc, local, Pop (pc, 0), data);
+               }
+
+               public TResult Switch(APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, TData data)
+               {
+                       return this.visitor.Switch (pc, type, cases, Pop (pc, 0), data);
+               }
+
+               public TResult Box(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)
+               {
+                       type = GetSpecializedType (pc, type);
+                       if (IsReferenceType (pc, type))
+                               return this.visitor.Nop (pc, data);
+
+                       return this.visitor.Box (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult ConstrainedCallvirt<TypeList, ArgList>(APC pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, TData data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int argsCount = GetParametersCount (method, extraVarargs == null ? 0 : extraVarargs.Count);
+                       return this.visitor.ConstrainedCallvirt (pc, method, constraint, extraVarargs, Push (pc, argsCount, this.parent.MetaDataProvider.ReturnType (method)), PopSequence (pc, argsCount, 0), data);
+               }
+
+               public TResult CastClass(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.CastClass (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult CopyObj(APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, TData data)
+               {
+                       return this.visitor.CopyObj (pc, type, Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult Initobj(APC pc, TypeNode type, Dummy ptr, TData data)
+               {
+                       return this.visitor.Initobj (pc, type, Pop (pc, 0), data);
+               }
+
+               public TResult LoadElement(APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, TData data)
+               {
+                       return this.visitor.LoadElement (pc, type, Push (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult LoadField(APC pc, Field field, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.LoadField (pc, field, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult LoadFieldAddress(APC pc, Field field, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.LoadFieldAddress (pc, field, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult LoadLength(APC pc, Dummy dest, Dummy array, TData data)
+               {
+                       return this.visitor.LoadLength (pc, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult LoadStaticField(APC pc, Field field, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadStaticField (pc, field, Push (pc, 0), data);
+               }
+
+               public TResult LoadStaticFieldAddress(APC pc, Field field, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadStaticFieldAddress (pc, field, Push (pc, 0), data);
+               }
+
+               public TResult LoadTypeToken(APC pc, TypeNode type, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadTypeToken (pc, type, Push (pc, 0), data);
+               }
+
+               public TResult LoadFieldToken(APC pc, Field field, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadFieldToken (pc, field, Push (pc, 0), data);
+               }
+
+               public TResult LoadMethodToken(APC pc, Method method, Dummy dest, TData data)
+               {
+                       return this.visitor.LoadMethodToken (pc, method, Push (pc, 0), data);
+               }
+
+               public TResult NewArray<ArgList>(APC pc, TypeNode type, Dummy dest, ArgList lengths, TData data)
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.NewArray (pc, type, Push (pc, 1), PopSequence (pc, lengths.Count, 0), data);
+               }
+
+               public TResult NewObj<ArgList>(APC pc, Method ctor, Dummy dest, ArgList args, TData data)
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int argsCount = GetParametersCount (ctor, 0) - 1;
+                       return this.visitor.NewObj (pc, ctor, Push (pc, argsCount), PopSequence (pc, argsCount, 0), data);
+               }
+
+               public TResult MkRefAny(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.MkRefAny (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult RefAnyType(APC pc, Dummy dest, Dummy source, TData data)
+               {
+                       return this.visitor.RefAnyType (pc, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult RefAnyVal(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)
+               {
+                       return this.visitor.RefAnyVal (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult Rethrow(APC pc, TData data)
+               {
+                       return this.visitor.Rethrow (pc, data);
+               }
+
+               public TResult StoreElement(APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, TData data)
+               {
+                       return this.visitor.StoreElement (pc, type, Pop (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult StoreField(APC pc, Field field, Dummy obj, Dummy value, TData data)
+               {
+                       return this.visitor.StoreField (pc, field, Pop (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult StoreStaticField(APC pc, Field field, Dummy value, TData data)
+               {
+                       return this.visitor.StoreStaticField (pc, field, Pop (pc, 0), data);
+               }
+
+               public TResult Throw(APC pc, Dummy exception, TData data)
+               {
+                       return this.visitor.Throw (pc, Pop (pc, 0), data);
+               }
+
+               public TResult Unbox(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.Unbox (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+
+               public TResult UnboxAny(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
+               {
+                       return this.visitor.UnboxAny (pc, type, Push (pc, 1), Pop (pc, 0), data);
+               }
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthFactory.cs
new file mode 100644 (file)
index 0000000..adaad9b
--- /dev/null
@@ -0,0 +1,41 @@
+// 
+// StackDepthFactory.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 Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.StackAnalysis {
+       static class StackDepthFactory {
+               public static IILDecoder<APC, int, int, IStackContextProvider, Dummy> Create<TContext> (IILDecoder<APC, Dummy, Dummy, TContext, Dummy> ilDecoder,
+                                                                                               IMetaDataProvider metadataDecoder) where TContext : IMethodContextProvider
+               {
+                       return new StackDepthProvider<TContext> (ilDecoder, metadataDecoder);
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..0ffc461
--- /dev/null
@@ -0,0 +1,707 @@
+// 
+// StackDepthProvider.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.IO;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis.StackAnalysis {
+       class StackDepthProvider<TContext> : IILVisitor<APC, Dummy, Dummy, StackInfo, StackInfo>,
+                                                   IILDecoder<APC, int, int, IStackContextProvider, Dummy>,
+                                                   IStackContextProvider, IStackContext,
+                                                   IMethodContext,
+                                                   ICFG,
+                                                   IStackInfo where TContext : IMethodContextProvider {
+               private readonly IILDecoder<APC, Dummy, Dummy, TContext, Dummy> il_decoder;
+               private int cached_subroutine;
+               private APCMap<int> local_stack_depth_cache;
+               private APCMap<int> stack_depth_mirror_for_end_old;
+               private bool recursion_guard;
+
+               public StackDepthProvider (IILDecoder<APC, Dummy, Dummy, TContext, Dummy> ilDecoder,
+                                          IMetaDataProvider metaDataProvider)
+               {
+                       this.il_decoder = ilDecoder;
+                       MetaDataProvider = metaDataProvider;
+               }
+
+               #region Implementation of IILDecoder<APC,Local,Parameter,Method,Field,Type,int,int,IStackContextProvider<Field,Method>,Dummy>
+               public TResult ForwardDecode<TData, TResult, TVisitor> (APC pc, TVisitor visitor, TData data)
+                       where TVisitor : IILVisitor<APC, int, int, TData, TResult>
+               {
+                       if (pc.Index != 0 || pc.SubroutineContext != null || pc.Block != pc.Block.Subroutine.Exit || !pc.Block.Subroutine.IsMethod)
+                               return this.il_decoder.ForwardDecode<TData, TResult, StackDecoder<TContext, TData, TResult, TVisitor>> (pc, new StackDecoder<TContext, TData, TResult, TVisitor> (this, visitor), data);
+                       if (!pc.Block.Subroutine.HasReturnValue)
+                               return visitor.Return (pc, -1, data);
+
+                       int source = GlobalStackDepth (pc) - 1;
+                       return visitor.Return (pc, source, data);
+               }
+
+               public bool IsUnreachable (APC pc)
+               {
+                       return false;
+               }
+
+               public Dummy EdgeData (APC @from, APC to)
+               {
+                       return Dummy.Value;
+               }
+               #endregion
+
+               public IMetaDataProvider MetaDataProvider { get; private set; }
+
+               private ICFG UnderlyingCFG
+               {
+                       get { return this.il_decoder.ContextProvider.MethodContext.CFG; }
+               }
+
+               #region IILDecoder<APC,int,int,IStackContextProvider,Dummy> Members
+               public IStackContextProvider ContextProvider
+               {
+                       get { return this; }
+               }
+               #endregion
+
+               #region IStackContextProvider Members
+               public IStackContext StackContext
+               {
+                       get { return this; }
+               }
+
+               public IMethodContext MethodContext
+               {
+                       get { return this; }
+               }
+               #endregion
+
+               public int GlobalStackDepth (APC pc)
+               {
+                       int num = LocalStackDepth (pc);
+
+                       if (pc.SubroutineContext == null || !pc.Block.Subroutine.HasContextDependentStackDepth)
+                               return num;
+
+                       CFGBlock block = pc.SubroutineContext.Head.From;
+                       return num + GlobalStackDepth (APC.ForEnd (block, pc.SubroutineContext.Tail));
+               }
+
+               public int LocalStackDepth (APC pc)
+               {
+                       return LocalStackMap (pc.Block.Subroutine) [pc];
+               }
+
+               private int OldStartDepth (Subroutine subroutine)
+               {
+                       Method method = ((IMethodInfo) subroutine).Method;
+                       int count = MetaDataProvider.Parameters (method).Count;
+                       if (!MetaDataProvider.IsConstructor (method) && !MetaDataProvider.IsStatic (method))
+                               ++count;
+                       return count;
+               }
+
+               private APCMap<int> LocalStackMap (Subroutine subroutine)
+               {
+                       if (this.local_stack_depth_cache == null || this.cached_subroutine != subroutine.Id) {
+                               this.local_stack_depth_cache = GetStackDepthMap (subroutine);
+                               this.cached_subroutine = subroutine.Id;
+                       }
+                       return this.local_stack_depth_cache;
+               }
+
+               private APCMap<int> GetStackDepthMap (Subroutine subroutine)
+               {
+                       APCMap<int> result;
+                       var key = new TypedKey ("stackDepthKey");
+                       if (!subroutine.TryGetValue (key, out result)) {
+                               result = ComputeStackDepthMap (subroutine);
+                               subroutine.Add (key, result);
+                       }
+                       return result;
+               }
+
+               private APCMap<int> ComputeStackDepthMap (Subroutine subroutine)
+               {
+                       var startDepths = new Dictionary<int, StackInfo> (subroutine.BlockCount);
+                       APCMap<int> apcMap = this.stack_depth_mirror_for_end_old = new APCMap<int> (subroutine);
+
+                       foreach (CFGBlock block in subroutine.Blocks) {
+                               StackInfo stackInfo;
+                               if (!startDepths.TryGetValue (block.Index, out stackInfo))
+                                       stackInfo = ComputeBlockStartDepth (block);
+                               foreach (APC apc in block.APCs ()) {
+                                       apcMap.Add (apc, stackInfo.Depth);
+                                       stackInfo = this.il_decoder.ForwardDecode<StackInfo, StackInfo, IILVisitor<APC, Dummy, Dummy, StackInfo, StackInfo>> (apc, this, stackInfo);
+                               }
+                               if (!apcMap.ContainsKey (block.Last))
+                                       apcMap.Add (block.Last, stackInfo.Depth);
+                               foreach (CFGBlock successor in subroutine.SuccessorBlocks (block)) {
+                                       bool oldRecursionGuard = this.recursion_guard;
+                                       this.recursion_guard = true;
+                                       try {
+                                               bool isExceptionHandlerEdge;
+                                               foreach (var info in subroutine.EdgeSubroutinesOuterToInner (block, successor, out isExceptionHandlerEdge, null).AsEnumerable ())
+                                                       stackInfo.Adjust (info.Value.StackDelta);
+                                       } finally {
+                                               this.recursion_guard = oldRecursionGuard;
+                                       }
+                                       AddStartDepth (startDepths, successor, stackInfo);
+                               }
+                       }
+                       return apcMap;
+               }
+
+               private StackInfo ComputeBlockStartDepth (CFGBlock block)
+               {
+                       if (block.Subroutine.IsCatchFilterHeader (block))
+                               return new StackInfo (1, 2);
+                       return new StackInfo (0, 4);
+               }
+
+               private void AddStartDepth (Dictionary<int, StackInfo> dict, CFGBlock block, StackInfo stackDepth)
+               {
+                       StackInfo stackInfo;
+                       if (dict.TryGetValue (block.Index, out stackInfo))
+                               return;
+                       dict.Add (block.Index, stackDepth.Clone ());
+               }
+
+               #region Implementation of ICFG
+               APC ICFG.Entry
+               {
+                       get { return UnderlyingCFG.Entry; }
+               }
+
+               APC ICFG.EntryAfterRequires
+               {
+                       get { return UnderlyingCFG.EntryAfterRequires; }
+               }
+
+               APC ICFG.NormalExit
+               {
+                       get { return UnderlyingCFG.NormalExit; }
+               }
+
+               APC ICFG.ExceptionExit
+               {
+                       get { return UnderlyingCFG.ExceptionExit; }
+               }
+
+               Subroutine ICFG.Subroutine
+               {
+                       get { return UnderlyingCFG.Subroutine; }
+               }
+
+               APC ICFG.Next (APC pc)
+               {
+                       APC singleSuccessor;
+                       if (((ICFG) this).HasSingleSuccessor (pc, out singleSuccessor))
+                               return singleSuccessor;
+                       return pc;
+               }
+
+               bool ICFG.HasSingleSuccessor (APC pc, out APC successor)
+               {
+                       DecoratorHelper.Push (this);
+                       try {
+                               return UnderlyingCFG.HasSingleSuccessor (pc, out successor);
+                       } finally {
+                               DecoratorHelper.Pop ();
+                       }
+               }
+
+               bool ICFG.HasSinglePredecessor (APC pc, out APC predecessor)
+               {
+                       DecoratorHelper.Push (this);
+                       try {
+                               return UnderlyingCFG.HasSinglePredecessor (pc, out predecessor);
+                       } finally {
+                               DecoratorHelper.Pop ();
+                       }
+               }
+
+               IEnumerable<APC> ICFG.Successors (APC pc)
+               {
+                       DecoratorHelper.Push (this);
+                       try {
+                               return UnderlyingCFG.Successors (pc);
+                       } finally {
+                               DecoratorHelper.Pop ();
+                       }
+               }
+
+               IEnumerable<APC> ICFG.Predecessors (APC pc)
+               {
+                       DecoratorHelper.Push (this);
+                       try {
+                               return UnderlyingCFG.Predecessors (pc);
+                       } finally {
+                               DecoratorHelper.Pop ();
+                       }
+               }
+
+               bool ICFG.IsJoinPoint (APC pc)
+               {
+                       return UnderlyingCFG.IsJoinPoint (pc);
+               }
+
+               bool ICFG.IsSplitPoint (APC pc)
+               {
+                       return UnderlyingCFG.IsSplitPoint (pc);
+               }
+
+               bool ICFG.IsBlockStart (APC pc)
+               {
+                       return UnderlyingCFG.IsBlockStart (pc);
+               }
+
+               bool ICFG.IsBlockEnd (APC pc)
+               {
+                       return UnderlyingCFG.IsBlockEnd (pc);
+               }
+
+               IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> ICFG.GetDecoder (IMetaDataProvider metaDataProvider)
+               {
+                       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)
+               {
+                       DecoratorHelper.Push (this);
+                       try {
+                               UnderlyingCFG.Print (tw, printer, contextLookup, context);
+                       } finally {
+                               DecoratorHelper.Pop ();
+                       }
+               }
+               #endregion
+
+               #region Implementation of IStackInfo
+               bool IStackInfo.IsCallOnThis (APC pc)
+               {
+                       if (this.recursion_guard)
+                               return false;
+                       return LocalStackMap (pc.Block.Subroutine).IsCallOnThis (pc);
+               }
+               #endregion
+
+               #region Implementation of IStackContext<Field,Method>
+               public int StackDepth (APC pc)
+               {
+                       return GlobalStackDepth (pc);
+               }
+               #endregion
+
+               #region Implementation of IMethodContext<Field,Method>
+               Method IMethodContext.CurrentMethod
+               {
+                       get { return this.il_decoder.ContextProvider.MethodContext.CurrentMethod; }
+               }
+
+               ICFG IMethodContext.CFG
+               {
+                       get { return this; }
+               }
+
+               public IEnumerable<Field> Modifies (Method method)
+               {
+                       return this.il_decoder.ContextProvider.MethodContext.Modifies (method);
+               }
+
+               public IEnumerable<Method> AffectedGetters (Field field)
+               {
+                       return this.il_decoder.ContextProvider.MethodContext.AffectedGetters (field);
+               }
+               #endregion
+
+               #region Implementation of IExpressionILVisitor<APC,Type,Dummy,Dummy,StackInfo,StackInfo>
+               public StackInfo Binary (APC pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, StackInfo data)
+               {
+                       return data.Pop (2).Push ();
+               }
+
+               public StackInfo Isinst (APC pc, TypeNode type, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo LoadNull (APC pc, Dummy dest, StackInfo polarity)
+               {
+                       return polarity.Push ();
+               }
+
+               public StackInfo LoadConst (APC pc, TypeNode type, object constant, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo Sizeof (APC pc, TypeNode type, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo Unary (APC pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+               #endregion
+
+               #region Implementation of ISyntheticILVisitor<APC,Method,Field,Type,Dummy,Dummy,StackInfo,StackInfo>
+               public StackInfo Entry (APC pc, Method method, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo Assume (APC pc, EdgeTag tag, Dummy condition, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo Assert (APC pc, EdgeTag tag, Dummy condition, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo BeginOld (APC pc, APC matchingEnd, StackInfo data)
+               {
+                       return new StackInfo (OldStartDepth (pc.Block.Subroutine), 4);
+               }
+
+
+               public StackInfo EndOld (APC pc, APC matchingBegin, TypeNode type, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return new StackInfo (this.stack_depth_mirror_for_end_old [matchingBegin] + 1, 4);
+               }
+
+               public StackInfo LoadStack (APC pc, int offset, Dummy dest, Dummy source, bool isOld, StackInfo data)
+               {
+                       return data.Push (data [offset]);
+               }
+
+               public StackInfo LoadStackAddress (APC pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadResult (APC pc, TypeNode type, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return data.Push ();
+               }
+               #endregion
+
+               #region Implementation of IILVisitor<APC,Local,Parameter,Method,Field,Type,Dummy,Dummy,StackInfo,StackInfo>
+               public StackInfo Arglist (APC pc, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo Branch (APC pc, APC target, bool leavesExceptionBlock, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo BranchCond (APC pc, APC target, BranchOperator bop, Dummy value1, Dummy value2, StackInfo data)
+               {
+                       return data.Pop (2);
+               }
+
+               public StackInfo BranchTrue (APC pc, APC target, Dummy cond, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo BranchFalse (APC pc, APC target, Dummy cond, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo Break (APC pc, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, StackInfo data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int count = MetaDataProvider.Parameters (method).Count + (extraVarargs == null ? 0 : extraVarargs.Count);
+                       if (!MetaDataProvider.IsStatic (method)) {
+                               if (data.IsThis (count))
+                                       this.stack_depth_mirror_for_end_old.AddCallOnThis (pc);
+                               ++count;
+                       }
+                       data = data.Pop (count);
+                       if (MetaDataProvider.IsVoidMethod (method))
+                               return data;
+                       return data.Push ();
+               }
+
+               public StackInfo Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, StackInfo data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int count = 1;
+                       if (instance)
+                               ++count;
+                       int slots = count + (argTypes == null ? 0 : argTypes.Count);
+                       data.Pop (slots);
+                       if (MetaDataProvider.IsVoid (returnType))
+                               return data;
+                       return data.Push ();
+               }
+
+               public StackInfo CheckFinite (APC pc, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo CopyBlock (APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, StackInfo data)
+               {
+                       return data.Pop (3);
+               }
+
+               public StackInfo EndFilter (APC pc, Dummy decision, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo EndFinally (APC pc, StackInfo data)
+               {
+                       return new StackInfo (0, 0);
+               }
+
+               public StackInfo Jmp (APC pc, Method method, StackInfo data)
+               {
+                       return new StackInfo (0, 0);
+               }
+
+               public StackInfo LoadArg (APC pc, Parameter argument, bool isOld, Dummy dest, StackInfo data)
+               {
+                       if (!MetaDataProvider.IsStatic (MetaDataProvider.DeclaringMethod (argument)) && MetaDataProvider.ParameterIndex (argument) == 0)
+                               return data.PushThis ();
+
+                       return data.Push ();
+               }
+
+               public StackInfo LoadArgAddress (APC pc, Parameter argument, bool isOld, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadLocal (APC pc, Local local, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadLocalAddress (APC pc, Local local, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo Nop (APC pc, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo Pop (APC pc, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo Return (APC pc, Dummy source, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo StoreArg (APC pc, Parameter argument, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo StoreLocal (APC pc, Local local, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo Box (APC pc, TypeNode type, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, StackInfo data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       int paramsCount = MetaDataProvider.Parameters (method).Count + (extraVarargs == null ? 0 : extraVarargs.Count);
+                       if (!MetaDataProvider.IsStatic (method)) {
+                               if (data.IsThis (paramsCount))
+                                       this.stack_depth_mirror_for_end_old.AddCallOnThis (pc);
+                               ++paramsCount;
+                       }
+
+                       data = data.Pop (paramsCount);
+                       if (MetaDataProvider.IsVoid (MetaDataProvider.ReturnType (method)))
+                               return data;
+
+                       return data.Push ();
+               }
+
+               public StackInfo CastClass (APC pc, TypeNode type, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo CopyObj (APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, StackInfo data)
+               {
+                       return data.Pop (2);
+               }
+
+               public StackInfo Initobj (APC pc, TypeNode type, Dummy ptr, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo LoadElement (APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, StackInfo data)
+               {
+                       return data.Pop (2).Push ();
+               }
+
+               public StackInfo LoadField (APC pc, Field field, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo LoadFieldAddress (APC pc, Field field, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo LoadLength (APC pc, Dummy dest, Dummy array, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo LoadStaticField (APC pc, Field field, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadStaticFieldAddress (APC pc, Field field, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadTypeToken (APC pc, TypeNode type, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadFieldToken (APC pc, Field type, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo LoadMethodToken (APC pc, Method type, Dummy dest, StackInfo data)
+               {
+                       return data.Push ();
+               }
+
+               public StackInfo NewArray<ArgList> (APC pc, TypeNode type, Dummy dest, ArgList lengths, StackInfo data) where ArgList : IIndexable<Dummy>
+               {
+                       return data.Pop (lengths.Count).Push ();
+               }
+
+               public StackInfo NewObj<ArgList> (APC pc, Method ctor, Dummy dest, ArgList args, StackInfo data) where ArgList : IIndexable<Dummy>
+               {
+                       int paramsCount = MetaDataProvider.Parameters (ctor).Count;
+                       return data.Pop (paramsCount).Push ();
+               }
+
+               public StackInfo MkRefAny (APC pc, TypeNode type, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data;
+               }
+
+               public StackInfo RefAnyType (APC pc, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo RefAnyVal (APC pc, TypeNode type, Dummy dest, Dummy source, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo Rethrow (APC pc, StackInfo data)
+               {
+                       return new StackInfo (0, 0);
+               }
+
+               public StackInfo StoreElement (APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, StackInfo data)
+               {
+                       return data.Pop (3);
+               }
+
+               public StackInfo StoreField (APC pc, Field field, Dummy obj, Dummy value, StackInfo data)
+               {
+                       return data.Pop (2);
+               }
+
+               public StackInfo StoreStaticField (APC pc, Field field, Dummy value, StackInfo data)
+               {
+                       return data.Pop (1);
+               }
+
+               public StackInfo Throw (APC pc, Dummy exception, StackInfo data)
+               {
+                       return new StackInfo (0, 0);
+               }
+
+               public StackInfo Unbox (APC pc, TypeNode type, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+
+               public StackInfo UnboxAny (APC pc, TypeNode type, Dummy dest, Dummy obj, StackInfo data)
+               {
+                       return data.Pop (1).Push ();
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo.cs
new file mode 100644 (file)
index 0000000..f189530
--- /dev/null
@@ -0,0 +1,127 @@
+// 
+// StackInfo.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.Analysis.StackAnalysis {
+       struct StackInfo {
+               private StackInfo<object> stack;
+
+               public int Depth {
+                       get { return this.stack.Depth; }
+               }
+
+               public object this [int offset] {
+                       get { return this.stack [offset]; }
+               }
+
+               public StackInfo (int depth, int capacity)
+               {
+                       this.stack = new StackInfo<object> (depth, capacity);
+               }
+
+               private StackInfo (StackInfo<object> copy)
+               {
+                       this.stack = copy;
+               }
+
+               public StackInfo Pop (int slots)
+               {
+                       return new StackInfo (this.stack.Pop (slots));
+               }
+
+               public StackInfo Push ()
+               {
+                       this.stack.Push (null);
+                       return this;
+               }
+
+               public StackInfo PushThis ()
+               {
+                       this.stack.Push (true);
+                       return this;
+               }
+
+               public StackInfo Push<T> (T target)
+               {
+                       this.stack.Push (target);
+                       return this;
+               }
+
+               public void Adjust (int delta)
+               {
+                       if (delta == 0)
+                               return;
+                       if (delta < 0)
+                               this.stack.Pop (-delta);
+                       for (int i = 0; i < delta; ++i)
+                               Push ();
+               }
+
+               public bool IsThis (int offset)
+               {
+                       return As<bool> (offset);
+               }
+
+               public bool TryGet<T> (int offset, out T target)
+               {
+                       object o = this [offset];
+                       if (o is T) {
+                               target = (T) o;
+                               return true;
+                       }
+                       target = default(T);
+                       return false;
+               }
+
+               private T As<T> (int offset)
+               {
+                       T res;
+                       TryGetTarget (offset, out res);
+                       return res;
+               }
+
+               public StackInfo Clone ()
+               {
+                       return new StackInfo (new StackInfo<object> (this.stack));
+               }
+
+               public override string ToString ()
+               {
+                       return this.stack.ToString ();
+               }
+
+               public bool TryGetTarget<T> (int offset, out T target)
+               {
+                       if (this [offset] is T) {
+                               target = (T) this [offset];
+                               return true;
+                       }
+                       target = default(T);
+                       return false;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo`1.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo`1.cs
new file mode 100644 (file)
index 0000000..a96a79d
--- /dev/null
@@ -0,0 +1,82 @@
+// 
+// StackInfo`1.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.Analysis.StackAnalysis {
+       struct StackInfo<T> {
+               private readonly T[] stack;
+               private int depth;
+
+               public StackInfo (int depth, int capacity)
+               {
+                       this.depth = depth;
+                       this.stack = new T[capacity];
+               }
+
+               public StackInfo (StackInfo<T> that)
+               {
+                       this.depth = that.depth;
+                       this.stack = (T[]) that.stack.Clone ();
+               }
+
+               public int Depth { 
+                       get { return this.depth; }
+               }
+
+               public T this [int offset] {
+                       get {
+                               int index = this.depth - 1 - offset;
+                               if (index >= 0 && index < this.stack.Length)
+                                       return this.stack [index];
+                               return default(T);
+                       }
+               }
+
+               public StackInfo<T> Pop (int slots)
+               {
+                       for (int i = this.depth - slots; i < this.depth; ++i) {
+                               if (i < this.stack.Length)
+                                       this.stack [i] = default(T);
+                       }
+                       this.depth -= slots;
+                       return this;
+               }
+
+               public void Push (T info)
+               {
+                       int index = this.depth;
+                       if (index < this.stack.Length)
+                               this.stack [index] = info;
+                       ++this.depth;
+               }
+
+               public override string ToString ()
+               {
+                       return this.depth.ToString ();
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/CodeLayer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/CodeLayer.cs
new file mode 100644 (file)
index 0000000..b09ea10
--- /dev/null
@@ -0,0 +1,90 @@
+// 
+// CodeLayer.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 Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataFlowAnalysis;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       class CodeLayer<Expression, Variable, ContextData, EdgeData>
+               : ICodeLayer<Expression, Variable, ContextData, EdgeData>
+               where ContextData : IMethodContextProvider {
+               private readonly Lazy<ILPrinter<APC>> printer;
+
+               public CodeLayer (IILDecoder<APC, Expression, Variable, ContextData, EdgeData> ilDecoder,
+                                 IMetaDataProvider metadataDecoder,
+                                 IContractProvider contractDecoder,
+                                 Func<Expression, string> expressionToString,
+                                 Func<Variable, string> variableToString)
+               {
+                       ExpressionToString = expressionToString;
+                       VariableToString = variableToString;
+                       ILDecoder = ilDecoder;
+                       MetaDataProvider = metadataDecoder;
+                       ContractProvider = contractDecoder;
+
+                       this.printer = new Lazy<ILPrinter<APC>> (() => PrinterFactory.Create (ILDecoder, MetaDataProvider, ExpressionToString, VariableToString));
+               }
+
+               public CodeLayer (IILDecoder<APC, Expression, Variable, ContextData, EdgeData> ilDecoder,
+                                 IMetaDataProvider metadataDecoder,
+                                 IContractProvider contractDecoder,
+                                 Func<Expression, string> expressionToString,
+                                 Func<Variable, string> variableToString, ILPrinter<APC> printer)
+                       : this (ilDecoder, metadataDecoder, contractDecoder, expressionToString, variableToString)
+               {
+                       this.printer = new Lazy<ILPrinter<APC>> (() => printer);
+               }
+
+               public IILDecoder<APC, Expression, Variable, ContextData, EdgeData> ILDecoder { get; private set; }
+
+               public ILPrinter<APC> Printer
+               {
+                       get { return this.printer.Value; }
+               }
+
+               public Func<Expression, string> ExpressionToString { get; private set; }
+
+               public Func<Variable, string> VariableToString { get; private set; }
+
+               public IMetaDataProvider MetaDataProvider { get; private set; }
+               public IContractProvider ContractProvider { get; private set; }
+
+               public Func<AState, IFixPointInfo<APC, AState>> CreateForward<AState> (
+                       IAnalysis<APC, AState, IILVisitor<APC, Expression, Variable, AState, AState>, EdgeData> analysis)
+               {
+                       ForwardAnalysis<AState, EdgeData> solver = ForwardAnalysis<AState, EdgeData>.Make (ILDecoder, analysis);
+                       return (initialState) => {
+                               solver.Run (initialState);
+                               return solver;
+                              };
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/CodeLayerFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/CodeLayerFactory.cs
new file mode 100644 (file)
index 0000000..ee8951e
--- /dev/null
@@ -0,0 +1,57 @@
+// 
+// CodeLayerFactory.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 Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       static class CodeLayerFactory {
+               public static ICodeLayer<Expression, Variable, ContextData, EdgeConversionData>
+                       Create<Expression, Variable, ContextData, EdgeConversionData> (
+                       IILDecoder<APC, Expression, Variable, ContextData, EdgeConversionData> ilDecoder,
+                       IMetaDataProvider metadataDecoder,
+                       IContractProvider contractDecoder, Func<Expression, string> expressionToString, Func<Variable, string> variableToString)
+                       where ContextData : IMethodContextProvider
+               {
+                       return new CodeLayer<Expression, Variable, ContextData, EdgeConversionData>
+                               (ilDecoder, metadataDecoder, contractDecoder, expressionToString, variableToString);
+               }
+
+               public static ICodeLayer<Expression, Variable, ContextData, EdgeConversionData>
+                       Create<Expression, Variable, ContextData, EdgeConversionData> (
+                       IILDecoder<APC, Expression, Variable, ContextData, EdgeConversionData> ilDecoder,
+                       IMetaDataProvider metadataDecoder,
+                       IContractProvider contractDecoder, Func<Expression, string> expressionToString, Func<Variable, string> variableToString, ILPrinter<APC> printer)
+                       where ContextData : IMethodContextProvider
+               {
+                       return new CodeLayer<Expression, Variable, ContextData, EdgeConversionData>
+                               (ilDecoder, metadataDecoder, contractDecoder, expressionToString, variableToString, printer);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ICodeLayer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/ICodeLayer.cs
new file mode 100644 (file)
index 0000000..feab952
--- /dev/null
@@ -0,0 +1,49 @@
+// 
+// ICodeLayer.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 Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataFlowAnalysis;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       interface ICodeLayer<Expression, Variable, ContextData, EdgeData> where ContextData : IMethodContextProvider {
+               IMetaDataProvider MetaDataProvider { get; }
+               IContractProvider ContractProvider { get; }
+               IILDecoder<APC, Expression, Variable, ContextData, EdgeData> ILDecoder { get; }
+
+               ILPrinter<APC> Printer { get; }
+               Func<Expression, string> ExpressionToString { get; }
+               Func<Variable, string> VariableToString { get; }
+
+               Func<AnalysisState, IFixPointInfo<APC, AnalysisState>> CreateForward<AnalysisState> (
+                       IAnalysis<APC, AnalysisState, IILVisitor<APC, Expression, Variable, AnalysisState, AnalysisState>, EdgeData> analysis
+                       );
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContext.cs
new file mode 100644 (file)
index 0000000..4e41b1d
--- /dev/null
@@ -0,0 +1,50 @@
+// 
+// IExpressionContext.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 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 {
+       interface IExpressionContext<Expression, Variable> {
+               Expression Refine (APC pc, Variable variable);
+               Variable Unrefine (Expression expression);
+
+               Result Decode<Data, Result, Visitor> (Expression expr, Visitor visitor, Data data)
+                       where Visitor : ISymbolicExpressionVisitor<Expression, Expression, Variable, Data, Result>;
+
+               FlatDomain<TypeNode> GetType (Expression expr);
+
+               APC GetPC (Expression pc);
+
+               Expression For (Variable variable);
+
+               bool IsZero (Expression expression);
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs
new file mode 100644 (file)
index 0000000..12de0da
--- /dev/null
@@ -0,0 +1,34 @@
+// 
+// IExpressionContextProvider.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.Analysis {
+       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
new file mode 100644 (file)
index 0000000..3f1bc69
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// ILPrinter.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.IO;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       delegate void ILPrinter<Label> (Label label, string prefix, TextWriter tw);
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IMethodContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IMethodContext.cs
new file mode 100644 (file)
index 0000000..c483846
--- /dev/null
@@ -0,0 +1,41 @@
+// 
+// IMethodContext.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       interface IMethodContext
+       {
+               Method CurrentMethod { get; }
+               ICFG CFG { get; }
+               IEnumerable<Field> Modifies(Method method);
+               IEnumerable<Method> AffectedGetters(Field field);
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IMethodContextProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IMethodContextProvider.cs
new file mode 100644 (file)
index 0000000..4b83118
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// IMethodContextProvider.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.Analysis {
+       interface IMethodContextProvider {
+               IMethodContext MethodContext { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IStackContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IStackContext.cs
new file mode 100644 (file)
index 0000000..df295f8
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IStackContext.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 Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       interface IStackContext {
+               int StackDepth (APC pc);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IStackContextProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IStackContextProvider.cs
new file mode 100644 (file)
index 0000000..c2204b2
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// IStackContextProvider.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.Analysis {
+       interface IStackContextProvider : IMethodContextProvider {
+               IStackContext StackContext { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContext.cs
new file mode 100644 (file)
index 0000000..9da3d71
--- /dev/null
@@ -0,0 +1,44 @@
+// 
+// IValueContext.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Lattices;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       interface IValueContext<SymbolicValue> {
+               bool IsZero (APC at, SymbolicValue value);
+               bool TryLocalValue (APC at, Local local, out SymbolicValue sv);
+               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);
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContextProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/IValueContextProvider.cs
new file mode 100644 (file)
index 0000000..295fc48
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// IValueContextProvider.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.Analysis {
+       interface IValueContextProvider<Variable> : IStackContextProvider {
+               IValueContext<Variable> ValueContext { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/PrinterFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Analysis/PrinterFactory.cs
new file mode 100644 (file)
index 0000000..c046789
--- /dev/null
@@ -0,0 +1,469 @@
+// 
+// PrinterFactory.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.IO;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.Analysis {
+       static class PrinterFactory {
+               public static ILPrinter<Label> Create<Label, Source, Dest, Context, EdgeData>
+                       (IILDecoder<Label, Source, Dest, Context, EdgeData> ilDecoder,
+                        IMetaDataProvider metaDataProvider,
+                        Func<Source, string> sourceToString, Func<Dest, string> destToString)
+               {
+                       return new Printer<Label, Source, Dest, Context, EdgeData> (ilDecoder, metaDataProvider, sourceToString, destToString).PrintCodeAt;
+               }
+
+               #region Nested type: Printer
+               private class Printer<Label, Source, Dest, Context, EdgeData> : IILVisitor<Label, Source, Dest, TextWriter, Dummy> {
+                       private readonly Func<Dest, string> dest_to_string;
+                       private readonly IILDecoder<Label, Source, Dest, Context, EdgeData> il_decoder;
+                       private readonly IMetaDataProvider meta_data_provider;
+                       private readonly Func<Source, string> source_to_string;
+                       private string prefix = "";
+
+                       public Printer (IILDecoder<Label, Source, Dest, Context, EdgeData> ilDecoder, IMetaDataProvider metaDataProvider,
+                                       Func<Source, string> sourceToString, Func<Dest, string> destToString)
+                       {
+                               this.il_decoder = ilDecoder;
+                               this.meta_data_provider = metaDataProvider;
+                               this.source_to_string = sourceToString;
+                               this.dest_to_string = destToString;
+                       }
+
+                       #region IILVisitor<Label,Source,Dest,TextWriter,Dummy> Members
+                       public Dummy Binary (Label pc, BinaryOperator op, Dest dest, Source operand1, Source operand2, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{1} = {2} {3} {4}", this.prefix, DestName (dest), SourceName (operand1), op.ToString (), SourceName (operand2));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Isinst (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = isinst {1} {3}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (obj));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadNull (Label pc, Dest dest, TextWriter polarity)
+                       {
+                               polarity.WriteLine ("{0}{1} = ldnull", this.prefix, DestName (dest));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadConst (Label pc, TypeNode type, object constant, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldc ({3}) '{1}'", this.prefix, constant, DestName (dest), this.meta_data_provider.FullName (type));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Sizeof (Label pc, TypeNode type, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = sizeof {1}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Unary (Label pc, UnaryOperator op, bool unsigned, Dest dest, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{3} = {2}{1} {4}", this.prefix, unsigned ? "_un" : null, op, DestName (dest), SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Entry (Label pc, Method method, TextWriter data)
+                       {
+                               data.WriteLine ("{0}method_entry {1}", this.prefix, this.meta_data_provider.FullName (method));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Assume (Label pc, EdgeTag tag, Source condition, TextWriter data)
+                       {
+                               data.WriteLine ("{0}assume({1}) {2}", this.prefix, tag, SourceName (condition));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Assert (Label pc, EdgeTag tag, Source condition, TextWriter data)
+                       {
+                               data.WriteLine ("{0}assert({1}) {2}", this.prefix, tag, SourceName (condition));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy BeginOld (Label pc, Label matchingEnd, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy EndOld (Label pc, Label matchingBegin, TypeNode type, Dest dest, Source source, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy LoadStack (Label pc, int offset, Dest dest, Source source, bool isOld, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{1} = {4}ldstack.{2} {3}", this.prefix, DestName (dest), offset, SourceName (source), isOld ? "old." : null);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadStackAddress (Label pc, int offset, Dest dest, Source source, TypeNode type, bool isOld, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{1} = {4}ldstacka.{2} {3}", this.prefix, DestName (dest), offset, SourceName (source), isOld ? "old." : null);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadResult (Label pc, TypeNode type, Dest dest, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{1} = ldresult {2}", this.prefix, DestName (dest), SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Arglist (Label pc, Dest dest, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy Branch (Label pc, Label target, bool leavesExceptionBlock, TextWriter data)
+                       {
+                               data.WriteLine ("{0}branch", this.prefix);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy BranchCond (Label pc, Label target, BranchOperator bop, Source value1, Source value2, TextWriter data)
+                       {
+                               data.WriteLine ("{0}br.{1} {2},{3}", this.prefix, bop, SourceName (value1), SourceName (value2));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy BranchTrue (Label pc, Label target, Source cond, TextWriter data)
+                       {
+                               data.WriteLine ("{0}br.true {1}", this.prefix, SourceName (cond));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy BranchFalse (Label pc, Label target, Source cond, TextWriter data)
+                       {
+                               data.WriteLine ("{0}br.false {1}", this.prefix, SourceName (cond));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Break (Label pc, TextWriter data)
+                       {
+                               data.WriteLine ("{0}break", this.prefix);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dest dest, ArgList args, TextWriter data) where TypeList : IIndexable<TypeNode>
+                               where ArgList : IIndexable<Source>
+                       {
+                               data.Write ("{0}{3} = call{2} {1}(", this.prefix, this.meta_data_provider.FullName (method), virt ? "virt" : null, DestName (dest));
+                               if (args != null) {
+                                       for (int i = 0; i < args.Count; i++)
+                                               data.Write ("{0} ", SourceName (args [i]));
+                               }
+                               data.WriteLine (")");
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Calli<TypeList, ArgList> (Label pc, TypeNode returnType, TypeList argTypes, bool instance, Dest dest, Source functionPointer, ArgList args, TextWriter data)
+                               where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<Source>
+                       {
+                               data.Write ("{0}{1} = calli {2}(", this.prefix, DestName (dest), SourceName (functionPointer));
+                               if (args != null) {
+                                       for (int i = 0; i < args.Count; i++)
+                                               data.Write ("{0} ", SourceName (args [i]));
+                               }
+                               data.WriteLine (")");
+                               return Dummy.Value;
+                       }
+
+                       public Dummy CheckFinite (Label pc, Dest dest, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{1} = chfinite {2}", this.prefix, DestName (dest), SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy CopyBlock (Label pc, Source destAddress, Source srcAddress, Source len, TextWriter data)
+                       {
+                               data.WriteLine ("{0}cpblk {1} {2} {3}", this.prefix, SourceName (destAddress), SourceName (srcAddress), SourceName (len));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy EndFilter (Label pc, Source decision, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy EndFinally (Label pc, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy Jmp (Label pc, Method method, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy LoadArg (Label pc, Parameter argument, bool isOld, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = {3}ldarg {1}", this.prefix, this.meta_data_provider.Name (argument), DestName (dest), isOld ? "old." : null);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadArgAddress (Label pc, Parameter argument, bool isOld, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = {3}ldarga {1}", this.prefix, this.meta_data_provider.Name (argument), DestName (dest), isOld ? "old." : null);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadLocal (Label pc, Local local, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldloc {1}", this.prefix, this.meta_data_provider.Name (local), DestName (dest));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadLocalAddress (Label pc, Local local, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldloca {1}", this.prefix, this.meta_data_provider.Name (local), DestName (dest));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Nop (Label pc, TextWriter data)
+                       {
+                               data.WriteLine ("{0}nop", this.prefix);
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Pop (Label pc, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}pop {1}", this.prefix, SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Return (Label pc, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}ret {1}", this.prefix, SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy StoreArg (Label pc, Parameter argument, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}starg {1} {2}", this.prefix, this.meta_data_provider.Name (argument), SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy StoreLocal (Label pc, Local local, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}stloc {1} {2}", this.prefix, this.meta_data_provider.Name (local), SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Switch (Label pc, TypeNode type, IEnumerable<Pair<object, Label>> cases, Source value, TextWriter data)
+                       {
+                               data.WriteLine ("{0}switch {1}", this.prefix, SourceName (value));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Box (Label pc, TypeNode type, Dest dest, Source source, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = box {1} {3}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (source));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dest dest, ArgList args, TextWriter data)
+                               where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<Source>
+                       {
+                               data.Write ("{0}{3} = constrained({1}).callvirt {2}(", this.prefix, this.meta_data_provider.FullName (constraint), this.meta_data_provider.FullName (method), DestName (dest));
+                               if (args != null) {
+                                       for (int i = 0; i < args.Count; i++)
+                                               data.Write ("{0} ", SourceName (args [i]));
+                               }
+                               data.WriteLine (")");
+                               return Dummy.Value;
+                       }
+
+                       public Dummy CastClass (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = castclass {1} {3}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (obj));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy CopyObj (Label pc, TypeNode type, Source destPtr, Source sourcePtr, TextWriter data)
+                       {
+                               data.WriteLine ("{0}cpobj {1} {2} {3}", this.prefix, this.meta_data_provider.FullName (type), SourceName (destPtr), SourceName (sourcePtr));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Initobj (Label pc, TypeNode type, Source ptr, TextWriter data)
+                       {
+                               data.WriteLine ("{0}initobj {1} {2}", this.prefix, this.meta_data_provider.FullName (type), SourceName (ptr));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadElement (Label pc, TypeNode type, Dest dest, Source array, Source index, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldelem {1} {3}[{4}]", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (array), SourceName (index));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadField (Label pc, Field field, Dest dest, Source obj, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldfld {1} {3}", this.prefix, this.meta_data_provider.Name (field), DestName (dest), SourceName (obj));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadFieldAddress (Label pc, Field field, Dest dest, Source obj, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldflda {1} {3}", this.prefix, this.meta_data_provider.Name (field), DestName (dest), SourceName (obj));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadLength (Label pc, Dest dest, Source array, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{1} = ldlen {2}", this.prefix, DestName (dest), SourceName (array));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadStaticField (Label pc, Field field, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldsfld {1}", this.prefix, this.meta_data_provider.Name (field), DestName (dest));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadStaticFieldAddress (Label pc, Field field, Dest dest, TextWriter data)
+                       {
+                               data.WriteLine ("{0}{2} = ldsflda {1}", this.prefix, this.meta_data_provider.Name (field), DestName (dest));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy LoadTypeToken (Label pc, TypeNode type, Dest dest, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy LoadFieldToken (Label pc, Field type, Dest dest, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy LoadMethodToken (Label pc, Method type, Dest dest, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy NewArray<ArgList> (Label pc, TypeNode type, Dest dest, ArgList lengths, TextWriter data) where ArgList : IIndexable<Source>
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy NewObj<ArgList> (Label pc, Method ctor, Dest dest, ArgList args, TextWriter data) where ArgList : IIndexable<Source>
+                       {
+                               data.Write ("{0}{2} = newobj {1}(", this.prefix, this.meta_data_provider.FullName (ctor), DestName (dest));
+                               if (args != null) {
+                                       for (int i = 0; i < args.Count; ++i)
+                                               data.Write ("{0} ", SourceName (args [i]));
+                               }
+
+                               data.WriteLine (")");
+                               return Dummy.Value;
+                       }
+
+                       public Dummy MkRefAny (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy RefAnyType (Label pc, Dest dest, Source source, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy RefAnyVal (Label pc, TypeNode type, Dest dest, Source source, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy Rethrow (Label pc, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy StoreElement (Label pc, TypeNode type, Source array, Source index, Source value, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy StoreField (Label pc, Field field, Source obj, Source value, TextWriter data)
+                       {
+                               data.WriteLine ("{0}stfld {1} {2} {3}", this.prefix, this.meta_data_provider.Name (field), SourceName (obj), SourceName (value));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy StoreStaticField (Label pc, Field field, Source value, TextWriter data)
+                       {
+                               data.WriteLine ("{0}stsfld {1} {2}", this.prefix, this.meta_data_provider.Name (field), SourceName (value));
+                               return Dummy.Value;
+                       }
+
+                       public Dummy Throw (Label pc, Source exception, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy Unbox (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public Dummy UnboxAny (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+                       #endregion
+
+                       public void PrintCodeAt (Label label, string prefix, TextWriter tw)
+                       {
+                               this.prefix = prefix;
+                               this.il_decoder.ForwardDecode<TextWriter, Dummy, Printer<Label, Source, Dest, Context, EdgeData>> (label, this, tw);
+                       }
+
+                       private string SourceName (Source src)
+                       {
+                               return this.source_to_string != null ? this.source_to_string (src) : null;
+                       }
+
+                       private string DestName (Dest dest)
+                       {
+                               return this.dest_to_string != null ? this.dest_to_string (dest) : null;
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/ContractExtractor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/ContractExtractor.cs
new file mode 100644 (file)
index 0000000..02054c5
--- /dev/null
@@ -0,0 +1,234 @@
+// 
+// ContractExtractor.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+
+namespace Mono.CodeContracts.Static.ContractExtraction {
+       class ContractExtractor : DefaultNodeVisitor {
+               private readonly AssemblyNode assembly;
+               private readonly ContractNodes contract_nodes;
+               private readonly bool verbose;
+               private readonly Dictionary<Method, Method> visited_methods;
+
+               public ContractExtractor (ContractNodes contractNodes, AssemblyNode assembly)
+                       : this (contractNodes, assembly, DebugOptions.Debug)
+               {
+               }
+
+               public ContractExtractor (ContractNodes contractNodes, AssemblyNode assembly, bool verbose)
+               {
+                       this.visited_methods = new Dictionary<Method, Method> ();
+                       this.contract_nodes = contractNodes;
+                       this.assembly = assembly;
+                       this.verbose = verbose;
+               }
+
+               public override AssemblyNode VisitAssembly (AssemblyNode node)
+               {
+                       if (node == null)
+                               return null;
+                       if (this.verbose)
+                               Console.WriteLine ("Extracting from '{0}'", this.assembly.FullName);
+
+                       return base.VisitAssembly (node);
+               }
+
+               public override Method VisitMethod (Method node)
+               {
+                       if (node == null)
+                               return null;
+
+                       if (this.visited_methods.ContainsKey (node))
+                               return node;
+
+                       this.visited_methods.Add (node, node);
+                       node.ContractProvider = ExtractContractsFromMethod;
+
+                       return node;
+               }
+
+               public void ExtractContractsFromMethod (Method method)
+               {
+                       MethodContract contract = method.MethodContract = new MethodContract (method);
+                       List<Requires> preconditions = null;
+                       List<Ensures> postconditions = null;
+
+                       if (method.IsAbstract)
+                               return;
+
+                       if (method.Body != null && method.Body.Statements != null) {
+                               if (this.verbose)
+                                       Console.WriteLine (method.FullName);
+
+                               ExtractContractsInternal (method, ref preconditions, ref postconditions);
+
+                               contract.Requires = preconditions;
+                               contract.Ensures = postconditions;
+                       }
+               }
+
+               private void ExtractContractsInternal (Method method, ref List<Requires> preconditions, ref List<Ensures> postconditions)
+               {
+                       if (method == null)
+                               return;
+                       if (this.verbose)
+                               Console.WriteLine ("Method: " + method.FullName);
+
+                       Block body = method.Body;
+                       if (body == null || body.Statements == null || body.Statements.Count <= 0)
+                               return;
+
+                       int lastBlockContainingContract;
+                       int lastStatementContainingContract;
+
+                       int begin = 0;
+                       bool contractsFound = FindLastBlockWithContracts (body.Statements, begin,
+                                                                         out lastBlockContainingContract, out lastStatementContainingContract);
+                       if (!contractsFound) {
+                               if (this.verbose)
+                                       Console.WriteLine ("\tNo contracts found");
+                               return;
+                       }
+
+                       List<Statement> contractSection = HelperMethods.ExtractContractBlocks (body.Statements, begin, 0,
+                                                                                              lastBlockContainingContract, lastStatementContainingContract);
+
+                       preconditions = new List<Requires> ();
+                       postconditions = new List<Ensures> ();
+
+                       ExtractPrePostConditionsFromContractSection (contractSection, preconditions, postconditions);
+               }
+
+               private bool ExtractPrePostConditionsFromContractSection (List<Statement> contractSection,
+                                                                         List<Requires> preconditions, List<Ensures> postconditions)
+               {
+                       List<Statement> blocks = contractSection;
+                       int firstBlockIndex = 0;
+                       int blocksCount = blocks.Count;
+                       int firstStmtIndex = HelperMethods.FindNextRealStatement (((Block) blocks [firstBlockIndex]).Statements, 0);
+
+                       bool wasEndContractBlock = false;
+
+                       for (int lastBlockIndex = firstBlockIndex; lastBlockIndex < blocksCount; ++lastBlockIndex) {
+                               var block = (Block) blocks [lastBlockIndex];
+                               if (block == null)
+                                       continue;
+
+                               int cnt = block.Statements == null ? 0 : block.Statements.Count;
+                               for (int lastStmtIndex = 0; lastStmtIndex < cnt; ++lastStmtIndex) {
+                                       Statement s = block.Statements [lastStmtIndex];
+                                       if (s == null)
+                                               continue;
+
+                                       Method calledMethod = HelperMethods.IsMethodCall (s);
+                                       if (!this.contract_nodes.IsContractMethod (calledMethod))
+                                               continue;
+
+                                       if (wasEndContractBlock) {
+                                               if (DebugOptions.Debug)
+                                                       Console.WriteLine ("Contract call after prior ContractBlock");
+                                               break;
+                                       }
+                                       if (this.contract_nodes.IsEndContractBlock (calledMethod)) {
+                                               wasEndContractBlock = true;
+                                               continue;
+                                       }
+
+                                       //here we definitely know that s is ExpressionStatement of (MethodCall). see HelperMethods.IsMethodCall(s)
+                                       var methodCall = ((ExpressionStatement) s).Expression as MethodCall;
+                                       Expression assertionExpression = methodCall.Arguments [0];
+                                       Expression expression;
+                                       if (firstBlockIndex == lastBlockIndex && firstStmtIndex == lastStmtIndex)
+                                               expression = assertionExpression;
+                                       else {
+                                               block.Statements [lastStmtIndex] = new ExpressionStatement (assertionExpression);
+                                               List<Statement> contractBlocks = HelperMethods.ExtractContractBlocks (blocks, firstBlockIndex, firstStmtIndex,
+                                                                                                                     lastBlockIndex, lastStmtIndex);
+                                               var b = new Block (contractBlocks);
+
+                                               expression = new BlockExpression (b);
+                                       }
+
+                                       MethodContractElement methodContractElement = null;
+                                       if (this.contract_nodes.IsPlainPrecondition (calledMethod)) {
+                                               var requires = new Requires (expression);
+
+                                               methodContractElement = requires;
+                                       } else if (this.contract_nodes.IsPostCondition (calledMethod))
+                                               methodContractElement = new Ensures (expression);
+
+                                       if (methodContractElement == null)
+                                               throw new InvalidOperationException ("Unrecognized contract method");
+
+                                       if (methodCall.Arguments.Count > 1) {
+                                               Expression userMessage = methodCall.Arguments [1];
+                                               methodContractElement.UserMessage = userMessage;
+                                       }
+
+                                       switch (methodContractElement.NodeType) {
+                                       case NodeType.Requires:
+                                               var requires = (Requires) methodContractElement;
+                                               preconditions.Add (requires);
+                                               break;
+                                       case NodeType.Ensures:
+                                               var ensures = (Ensures) methodContractElement;
+                                               postconditions.Add (ensures);
+                                               break;
+                                       }
+                               }
+                       }
+
+                       return true;
+               }
+
+               private bool FindLastBlockWithContracts (List<Statement> statements, int beginning,
+                                                        out int lastBlockContainingContract, out int lastStatementContainingContract)
+               {
+                       lastBlockContainingContract = -1;
+                       lastStatementContainingContract = -1;
+                       for (int i = statements.Count - 1; i >= beginning; i--) {
+                               var block = statements [i] as Block;
+                               if (block == null || block.Statements == null || block.Statements.Count <= 0)
+                                       continue;
+
+                               for (int j = block.Statements.Count - 1; j >= 0; j--) {
+                                       if (this.contract_nodes.IsContractCall (block.Statements [j]) == null)
+                                               continue;
+
+                                       lastBlockContainingContract = i;
+                                       lastStatementContainingContract = j;
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/ContractNodes.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/ContractNodes.cs
new file mode 100644 (file)
index 0000000..67a0692
--- /dev/null
@@ -0,0 +1,221 @@
+// 
+// ContractNodes.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.Linq;
+using System.Reflection;
+using Mono.CodeContracts.Static.AST;
+
+namespace Mono.CodeContracts.Static.ContractExtraction {
+       class ContractNodes {
+               public static readonly string ContractNamespace = "System.Diagnostics.Contracts";
+               public static readonly string ContractClassName = "Contract";
+               public static readonly string RequiresName = "Requires";
+               public static readonly string EnsuresName = "Ensures";
+               public static readonly string AssertName = "Assert";
+               public static readonly string AssumeName = "Assume";
+               public static readonly string EndContractBlockName = "EndContractBlock";
+
+               [RepresentationFor ("Contract.Assert(bool)")]
+               public readonly Method AssertMethod;
+
+               [RepresentationFor ("Contract.Assert(bool, string)")]
+               public readonly Method AssertWithMessageMethod;
+
+               [RepresentationFor ("Contract.Assume(bool)")]
+               public readonly Method AssumeMethod;
+
+               [RepresentationFor ("Contract.Assume(bool, string)")]
+               public readonly Method AssumeWithMessageMethod;
+
+               [RepresentationFor ("System.Diagnostics.Contracts.Contract")]
+               public readonly Class ContractClass;
+
+               [RepresentationFor ("Contract.EndContractBlock()")]
+               public readonly Method EndContractBlock;
+
+               [RepresentationFor ("Contract.Ensures(bool)")]
+               public readonly Method EnsuresMethod;
+
+               [RepresentationFor ("Contract.Ensures(bool, string)")]
+               public readonly Method EnsuresWithMessageMethod;
+
+               [RepresentationFor ("Contract.Requires(bool)")]
+               public readonly Method RequiresMethod;
+
+               [RepresentationFor ("Contract.Requires(bool, string)")]
+               public readonly Method RequiresWithMessageMethod;
+
+               private ContractNodes (AssemblyNode assembly, Action<string> errorHandler)
+               {
+                       CoreSystemTypes.ModuleDefinition = assembly.Modules.First ().Definition;
+                       if (errorHandler != null)
+                               ErrorFound += errorHandler;
+                       this.ContractClass = assembly.GetType (ContractNamespace, ContractClassName) as Class;
+                       if (this.ContractClass == null)
+                               return;
+
+
+                       IEnumerable<Method> methods = this.ContractClass.GetMethods (RequiresName, CoreSystemTypes.Instance.TypeBoolean);
+                       foreach (Method method in methods) {
+                               if (method.GenericParameters == null || method.GenericParameters.Count == 0)
+                                       this.RequiresMethod = method;
+                       }
+
+                       if (this.RequiresMethod == null) {
+                               this.ContractClass = null;
+                               return;
+                       }
+
+                       methods = this.ContractClass.GetMethods (RequiresName, CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
+                       foreach (Method method in methods) {
+                               if (method.GenericParameters == null || method.GenericParameters.Count == 0)
+                                       this.RequiresWithMessageMethod = method;
+                       }
+                       this.EnsuresMethod = this.ContractClass.GetMethod (EnsuresName, CoreSystemTypes.Instance.TypeBoolean);
+                       this.EnsuresWithMessageMethod = this.ContractClass.GetMethod (EnsuresName,
+                                                                                     CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
+
+                       this.AssertMethod = this.ContractClass.GetMethod (AssertName, CoreSystemTypes.Instance.TypeBoolean);
+                       this.AssertWithMessageMethod = this.ContractClass.GetMethod (AssertName,
+                                                                                    CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
+
+                       this.AssumeMethod = this.ContractClass.GetMethod (AssumeName, CoreSystemTypes.Instance.TypeBoolean);
+                       this.AssumeWithMessageMethod = this.ContractClass.GetMethod (AssumeName,
+                                                                                    CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
+
+                       this.EndContractBlock = this.ContractClass.GetMethod (EndContractBlockName);
+
+                       foreach (FieldInfo fieldInfo in typeof (ContractNodes).GetFields ()) {
+                               if (fieldInfo.GetValue (this) != null)
+                                       continue;
+
+                               string runtimeName = null;
+                               bool isRequired = false;
+                               object[] attributes = fieldInfo.GetCustomAttributes (typeof (RepresentationForAttribute), false);
+                               foreach (object attribute in attributes) {
+                                       var representationForAttribute = attribute as RepresentationForAttribute;
+                                       if (representationForAttribute != null) {
+                                               runtimeName = representationForAttribute.RuntimeName;
+                                               isRequired = representationForAttribute.IsRequired;
+                                               break;
+                                       }
+                               }
+                               if (isRequired) {
+                                       string message = string.Format ("Could not find contract node for '{0}'", fieldInfo.Name);
+                                       if (runtimeName != null)
+                                               message = string.Format ("Could not find the method/type '{0}'", runtimeName);
+
+                                       FireErrorFound (message);
+                                       ClearFields ();
+                               }
+                       }
+               }
+
+               public static ContractNodes GetContractNodes (AssemblyNode assembly, Action<string> errorHandler)
+               {
+                       var contractNodes = new ContractNodes (assembly, errorHandler);
+                       if (contractNodes.ContractClass != null)
+                               return contractNodes;
+                       return null;
+               }
+
+               private void ClearFields ()
+               {
+                       foreach (FieldInfo fieldInfo in typeof (ContractNodes).GetFields ()) {
+                               object[] customAttributes = fieldInfo.GetCustomAttributes (typeof (RepresentationForAttribute), false);
+                               if (customAttributes.Length == 1)
+                                       fieldInfo.SetValue (this, null);
+                       }
+               }
+
+               public event Action<string> ErrorFound;
+
+               private void FireErrorFound (string message)
+               {
+                       if (ErrorFound == null)
+                               throw new InvalidOperationException (message);
+
+                       ErrorFound (message);
+               }
+
+               public Method IsContractCall (Statement s)
+               {
+                       Method m = HelperMethods.IsMethodCall (s);
+                       if (IsContractMethod (m))
+                               return m;
+
+                       return null;
+               }
+
+               public bool IsContractMethod (Method method)
+               {
+                       if (method == null)
+                               return false;
+                       if (IsPlainPrecondition (method) || IsPostCondition (method) || IsEndContractBlock (method))
+                               return true;
+
+                       return false;
+               }
+
+               public bool IsPostCondition (Method method)
+               {
+                       TypeNode genericArgument;
+                       return IsContractMethod (EnsuresName, method, out genericArgument) && genericArgument == null;
+               }
+
+               public bool IsPlainPrecondition (Method method)
+               {
+                       TypeNode genericArgument;
+                       return IsContractMethod (RequiresName, method, out genericArgument);
+               }
+
+               private bool IsContractMethod (string methodName, Method m, out TypeNode genericArgument)
+               {
+                       genericArgument = null;
+                       if (m == null)
+                               return false;
+                       if (m.HasGenericParameters) {
+                               if (m.GenericParameters == null || m.GenericParameters.Count != 1)
+                                       return false;
+                               genericArgument = m.GenericParameters [0];
+                       }
+
+                       return m.Name != null && m.Name == methodName &&
+                              (m.DeclaringType.Equals (this.ContractClass)
+                               || (m.Parameters != null && m.Parameters.Count == 3 && m.DeclaringType != null && m.DeclaringType.Name != ContractClassName));
+               }
+
+               public bool IsEndContractBlock (Method method)
+               {
+                       TypeNode dummy;
+                       return IsContractMethod (EndContractBlockName, method, out dummy);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/GatherLocals.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/GatherLocals.cs
new file mode 100644 (file)
index 0000000..b82b70d
--- /dev/null
@@ -0,0 +1,91 @@
+// 
+// GatherLocals.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+
+namespace Mono.CodeContracts.Static.ContractExtraction {
+       class GatherLocals : NodeInspector {
+               public HashSet<Local> Locals = new HashSet<Local> ();
+               private Local exempt_result_local;
+
+               public override void VisitLocal (Local node)
+               {
+                       if (!IsLocalExempt (node) && !this.Locals.Contains (node))
+                               this.Locals.Add (node);
+                       base.VisitLocal (node);
+               }
+
+               public override void VisitAssignmentStatement (AssignmentStatement node)
+               {
+                       if (node.Target is Local && IsResultExpression (node.Source))
+                               this.exempt_result_local = (Local) node.Target;
+                       base.VisitAssignmentStatement (node);
+               }
+
+               private bool IsResultExpression (Expression expression)
+               {
+                       var methodCall = expression as MethodCall;
+                       if (methodCall == null)
+                               return false;
+
+                       var memberBinding = methodCall.Callee as MemberBinding;
+                       if (memberBinding == null)
+                               return false;
+
+                       var method = memberBinding.BoundMember as Method;
+                       if (method == null)
+                               return false;
+
+                       return method.HasGenericParameters && method.Name == "Result" && method.DeclaringType != null && method.DeclaringType.Name == "Contract";
+               }
+
+               private bool IsLocalExempt (Local local)
+               {
+                       if (local == this.exempt_result_local)
+                               return true;
+                       bool result = false;
+                       if (local.Name != null && !local.Name.StartsWith ("local"))
+                               result = true;
+                       TypeNode type = local.Type;
+                       if (type == null || HelperMethods.IsCompilerGenerated (type) || local.Name == "_preconditionHolds")
+                               return true;
+
+                       if (result)
+                               return LocalNameIsExempt (local.Name);
+
+                       return true;
+               }
+
+               private bool LocalNameIsExempt (string name)
+               {
+                       return name.StartsWith ("CS$") || name.StartsWith ("VB$");
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/HelperMethods.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/HelperMethods.cs
new file mode 100644 (file)
index 0000000..8a15718
--- /dev/null
@@ -0,0 +1,332 @@
+// 
+// HelperMethods.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 Mono.CodeContracts.Static.AST;
+
+namespace Mono.CodeContracts.Static.ContractExtraction {
+       static class HelperMethods {
+               public static Method IsMethodCall (Statement s)
+               {
+                       if (s == null)
+                               return null;
+
+                       var expressionStatement = s as ExpressionStatement;
+                       if (expressionStatement == null)
+                               return null;
+
+                       var methodCall = expressionStatement.Expression as MethodCall;
+                       if (methodCall == null)
+                               return null;
+
+                       var binding = methodCall.Callee as MemberBinding;
+                       if (binding == null)
+                               return null;
+
+                       return binding.BoundMember as Method;
+               }
+
+               public static Local ExtractPreamble (Method method, ContractNodes contractNodes, Block contractInitializer, out Block postPreamble)
+               {
+                       postPreamble = null;
+                       return null;
+               }
+
+               public static List<Statement> ExtractContractBlocks (List<Statement> blocks, int firstBlockIndex, int firstStmtIndex, int lastBlockIndex, int lastStmtIndex)
+               {
+                       var result = new List<Statement> ();
+                       var firstBlock = (Block) blocks [firstBlockIndex];
+                       var block = new Block (new List<Statement> ());
+                       if (firstBlock != null) {
+                               int cnt = firstBlockIndex == lastBlockIndex ? lastStmtIndex + 1 : firstBlock.Statements.Count;
+                               for (int i = firstStmtIndex; i < cnt; i++) {
+                                       Statement stmt = firstBlock.Statements [i];
+                                       block.Statements.Add (stmt);
+                                       if (stmt != null)
+                                               firstBlock.Statements [i] = null;
+                               }
+                       }
+                       result.Add (block);
+                       int nextIndex = firstBlockIndex + 1;
+                       if (nextIndex > lastBlockIndex)
+                               return result;
+                       Block newLastBlock = null;
+                       int lastFullBlockIndex = lastBlockIndex - 1;
+                       var lastBlock = (Block) blocks [lastBlockIndex];
+                       if (lastBlock != null && lastStmtIndex == lastBlock.Statements.Count - 1)
+                               lastFullBlockIndex = lastBlockIndex;
+                       else {
+                               newLastBlock = new Block (new List<Statement> ());
+                               if (block.Statements != null && block.Statements.Count > 0) {
+                                       var branch = block.Statements [block.Statements.Count - 1] as Branch;
+                                       if (branch != null && branch.Target != null && branch.Target == lastBlock)
+                                               branch.Target = newLastBlock;
+                               }
+                       }
+
+                       for (; nextIndex < lastFullBlockIndex; ++nextIndex) {
+                               var curBlock = (Block) blocks [nextIndex];
+                               result.Add (curBlock);
+                               if (curBlock != null) {
+                                       blocks [nextIndex] = null;
+                                       if (newLastBlock != null && curBlock.Statements != null && curBlock.Statements.Count > 0) {
+                                               var branch = curBlock.Statements [curBlock.Statements.Count - 1] as Branch;
+                                               if (branch != null && branch.Target != null && branch.Target == lastBlock)
+                                                       branch.Target = newLastBlock;
+                                       }
+                               }
+                       }
+
+                       if (newLastBlock != null) {
+                               for (int i = 0; i < lastStmtIndex + 1; i++) {
+                                       newLastBlock.Statements.Add (lastBlock.Statements [i]);
+                                       lastBlock.Statements [i] = null;
+                               }
+
+                               result.Add (newLastBlock);
+                       }
+                       return result;
+               }
+
+               public static bool IsCompilerGenerated (TypeNode type)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public static int FindNextRealStatement (List<Statement> stmts, int beginIndex)
+               {
+                       if (stmts == null || stmts.Count <= beginIndex)
+                               return -1;
+                       int index = beginIndex;
+                       while (index < stmts.Count && (stmts [index] == null || stmts [index].NodeType == NodeType.Nop))
+                               ++index;
+                       return index;
+               }
+
+               public static bool IsReferenceAsVisibleAs (Member member, Member asThisMember)
+               {
+                       var type = member as TypeNode;
+                       if (type != null)
+                               return IsTypeAsVisibleAs (type, asThisMember);
+                       var method = member as Method;
+                       Member member1;
+                       if (method != null) {
+                               if (method.HasGenericParameters)
+                                       throw new NotImplementedException ();
+                               member1 = method;
+                       } else
+                               member1 = Unspecialize (member);
+
+                       return IsDefinitionAsVisibleAs (member1, asThisMember);
+               }
+
+               private static bool IsDefinitionAsVisibleAs (this Member member, Member asThisMember)
+               {
+                       Module memberModule = member.Module;
+                       Module asThisMemberModule = asThisMember.Module;
+
+                       for (Member mbr = member; mbr != null; mbr = mbr.DeclaringType) {
+                               if (!mbr.IsPublic) {
+                                       bool visible = false;
+                                       for (Member mbr1 = asThisMember; mbr1 != null; mbr1 = mbr1.DeclaringType) {
+                                               if (mbr1.IsAssembly) {
+                                                       if ((mbr1.IsPrivate || mbr1.IsAssembly) && memberModule == asThisMemberModule)
+                                                               visible = true;
+                                               } else if (mbr1.IsFamily) {
+                                                       if (mbr.IsPrivate) {
+                                                               if (IsInsideOf (mbr, mbr1) || IsInsideSubclass (mbr, mbr1.DeclaringType))
+                                                                       visible = true;
+                                                       } else if (mbr.IsFamily && (mbr.DeclaringType == mbr1.DeclaringType || IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType)))
+                                                               visible = true;
+                                               } else if (mbr1.IsFamilyOrAssembly) {
+                                                       if (mbr.IsPrivate) {
+                                                               if (memberModule == asThisMemberModule || IsInsideSubclass (mbr, mbr1.DeclaringType))
+                                                                       visible = true;
+                                                       } else if (mbr.IsAssembly) {
+                                                               if (memberModule == asThisMemberModule)
+                                                                       visible = true;
+                                                       } else if (mbr.IsFamily) {
+                                                               if (IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType))
+                                                                       visible = true;
+                                                       } else if (mbr.IsFamilyOrAssembly && memberModule == asThisMemberModule && IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType))
+                                                               visible = true;
+                                               } else if (mbr1.IsPrivate && mbr.IsPrivate && IsInsideOf (mbr, mbr1.DeclaringType))
+                                                       visible = true;
+                                       }
+                                       if (!visible)
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+
+               private static bool IsSubclassOf (this TypeNode thisType, TypeNode thatType)
+               {
+                       if (thatType == null)
+                               return false;
+                       return thisType.IsAssignableTo (thatType);
+               }
+
+               private static bool IsInsideSubclass (this Member member, Member thatValue)
+               {
+                       var targetType = thatValue as TypeNode;
+                       if (targetType == null)
+                               return false;
+
+                       for (TypeNode declaringType = member.DeclaringType; declaringType != null; declaringType = declaringType.DeclaringType) {
+                               if (declaringType.IsAssignableTo (targetType))
+                                       return true;
+                       }
+                       return false;
+               }
+
+               private static bool IsInsideOf (this Member thisValue, Member thatValue)
+               {
+                       var typeNode = thatValue as TypeNode;
+                       if (typeNode == null)
+                               return false;
+                       for (TypeNode declaringType = thisValue.DeclaringType; declaringType != null; declaringType = declaringType.DeclaringType) {
+                               if (declaringType == typeNode)
+                                       return true;
+                       }
+                       return false;
+               }
+
+               private static Member Unspecialize (Member member)
+               {
+                       return member;
+               }
+
+               private static bool IsTypeAsVisibleAs (this TypeNode type, Member asThisMember)
+               {
+                       if (type == null)
+                               return true;
+
+                       switch (type.NodeType) {
+                       case NodeType.Reference:
+                               return ((Reference) type).ElementType.IsTypeAsVisibleAs (asThisMember);
+                       default:
+                               if (type.HasGenericParameters)
+                                       throw new NotImplementedException ();
+
+                               return IsDefinitionAsVisibleAs (type, asThisMember);
+                       }
+               }
+
+               public static bool IsVisibleFrom (this TypeNode type, TypeNode from)
+               {
+                       TypeNode declaringType = type.DeclaringType;
+                       if (declaringType != null) {
+                               if (IsContainedIn (from, declaringType) || IsInheritedFrom (from, type))
+                                       return true;
+                               if (type.IsNestedFamily)
+                                       return IsInheritedFrom (from, declaringType);
+                               if (type.IsNestedPublic)
+                                       return IsVisibleFrom (declaringType, from);
+                               if (type.IsNestedInternal) {
+                                       if (IsInheritedFrom (from, declaringType))
+                                               return true;
+                                       if (declaringType.Module == from.Module)
+                                               return IsVisibleFrom (declaringType, from);
+
+                                       return false;
+                               }
+                               if (type.IsNestedFamilyAndAssembly)
+                                       return from.Module == declaringType.Module && IsInheritedFrom (from, declaringType);
+                               if ((type.IsAssembly || type.IsNestedAssembly) && declaringType.Module == from.Module)
+                                       return IsVisibleFrom (declaringType, from);
+
+                               return false;
+                       }
+
+                       return type.Module == from.Module || type.IsPublic;
+               }
+
+               public static bool IsVisibleFrom (this Member member, TypeNode from)
+               {
+                       var type = member as TypeNode;
+                       if (type != null)
+                               return type.IsVisibleFrom (from);
+
+                       TypeNode declaringType = member.DeclaringType;
+                       if (from.IsContainedIn (declaringType))
+                               return true;
+                       if (member.IsPublic)
+                               return declaringType.IsVisibleFrom (from);
+                       if (member.IsFamily)
+                               return from.IsInheritedFrom (declaringType);
+                       if (member.IsFamilyAndAssembly)
+                               return from.Module == declaringType.Module && from.IsInheritedFrom (declaringType);
+                       if (member.IsFamilyOrAssembly) {
+                               if (from.IsInheritedFrom (declaringType))
+                                       return true;
+                               if (from.Module == declaringType.Module)
+                                       return declaringType.IsVisibleFrom (from);
+
+                               return false;
+                       }
+
+                       return member.IsAssembly && declaringType.Module == from.Module && declaringType.IsVisibleFrom (from);
+               }
+
+               public static bool IsInheritedFrom (this TypeNode type, TypeNode from)
+               {
+                       TypeNode baseClass;
+                       if (type.HasBaseClass (out baseClass)) {
+                               if (baseClass == from || baseClass.IsInheritedFrom (from))
+                                       return true;
+                       }
+
+                       return false;
+               }
+
+               private static bool HasBaseClass (this TypeNode type, out TypeNode baseClass)
+               {
+                       var clazz = type as Class;
+                       if (clazz != null && clazz.BaseType != null) {
+                               baseClass = clazz.BaseType;
+                               return true;
+                       }
+
+                       baseClass = default(TypeNode);
+                       return false;
+               }
+
+               public static bool IsContainedIn (this TypeNode inner, TypeNode outer)
+               {
+                       if (inner == outer)
+                               return true;
+
+                       if (inner.DeclaringType != null)
+                               return inner.DeclaringType.IsContainedIn (outer);
+
+                       return false;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/RepresentationForAttribute.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ContractExtraction/RepresentationForAttribute.cs
new file mode 100644 (file)
index 0000000..aae871c
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+// RepresentationForAttribute.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;
+
+namespace Mono.CodeContracts.Static.ContractExtraction {
+       [AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
+       sealed class RepresentationForAttribute : Attribute {
+               public RepresentationForAttribute (string runtimeName)
+                       : this (runtimeName, true)
+               {
+               }
+
+               private RepresentationForAttribute (string runtimeName, bool isRequired)
+               {
+                       RuntimeName = runtimeName;
+                       IsRequired = isRequired;
+               }
+
+               public string RuntimeName { get; private set; }
+               public bool IsRequired { get; private set; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/AssumeBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/AssumeBlock.cs
new file mode 100644 (file)
index 0000000..e846ba3
--- /dev/null
@@ -0,0 +1,57 @@
+// 
+// AssumeBlock.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 Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class AssumeBlock<Label> : BlockWithLabels<Label> {
+               protected readonly Label BranchLabel;
+               protected readonly EdgeTag Tag;
+
+               public AssumeBlock (SubroutineBase<Label> subroutine, Label label, EdgeTag tag, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+                       this.BranchLabel = label;
+                       this.Tag = tag;
+               }
+
+               public override int Count
+               {
+                       get { return 1; }
+               }
+
+               public override Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+               {
+                       if (pc.Index == 0)
+                               return visitor.Assume (pc, this.Tag, Dummy.Value, data);
+
+                       return visitor.Nop (pc, data);
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/BlockBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/BlockBase.cs
new file mode 100644 (file)
index 0000000..eda815b
--- /dev/null
@@ -0,0 +1,42 @@
+// 
+// BlockBase.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 Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       abstract class BlockBase : CFGBlock {
+               protected BlockBase (Subroutine subroutine, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+               }
+
+               public abstract Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+                       where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result>;
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/BlockWithLabels.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/BlockWithLabels.cs
new file mode 100644 (file)
index 0000000..29ef581
--- /dev/null
@@ -0,0 +1,110 @@
+// 
+// BlockWithLabels.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 Mono.CodeContracts.Static.ControlFlow.Subroutines;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class BlockWithLabels<Label> : BlockBase, IEquatable<BlockWithLabels<Label>> {
+               private readonly List<Label> labels;
+
+               public BlockWithLabels (SubroutineBase<Label> subroutine, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+                       this.labels = new List<Label> ();
+               }
+
+               public override int Count
+               {
+                       get { return this.labels.Count; }
+               }
+
+               protected new SubroutineBase<Label> Subroutine
+               {
+                       get { return (SubroutineBase<Label>) base.Subroutine; }
+               }
+
+               #region IEquatable<BlockWithLabels<Label>> Members
+               public bool Equals (BlockWithLabels<Label> other)
+               {
+                       return this == other;
+               }
+               #endregion
+
+               public override int GetILOffset (APC pc)
+               {
+                       Label label;
+                       if (TryGetLabel (pc.Index, out label))
+                               return Subroutine.GetILOffset (label);
+
+                       return 0;
+               }
+
+               public void AddLabel (Label label)
+               {
+                       this.labels.Add (label);
+               }
+
+               public bool TryGetLastLabel (out Label label)
+               {
+                       if (this.labels.Count > 0) {
+                               label = this.labels [this.labels.Count - 1];
+                               return true;
+                       }
+
+                       label = default(Label);
+                       return false;
+               }
+
+               public virtual bool TryGetLabel (int index, out Label label)
+               {
+                       if (index < this.labels.Count) {
+                               label = this.labels [index];
+                               return true;
+                       }
+
+                       label = default(Label);
+                       return false;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("{0}: {1}", this.Index, GetType ().Name);
+               }
+
+               public override Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+               {
+                       Label label;
+                       if (TryGetLabel (pc.Index, out label))
+                               return Subroutine.CodeProvider.Decode<LabelAdapter<Label, Data, Result, Visitor>, Data, Result> (label, new LabelAdapter<Label, Data, Result, Visitor> (visitor, pc), data);
+
+                       return visitor.Nop (pc, data);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/CatchFilterEntryBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/CatchFilterEntryBlock.cs
new file mode 100644 (file)
index 0000000..8006027
--- /dev/null
@@ -0,0 +1,38 @@
+// 
+// CatchFilterEntryBlock.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 Mono.CodeContracts.Static.ControlFlow.Subroutines;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class CatchFilterEntryBlock<Label> : BlockWithLabels<Label> {
+               public CatchFilterEntryBlock (SubroutineBase<Label> subroutine, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EnsuresBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EnsuresBlock.cs
new file mode 100644 (file)
index 0000000..360499c
--- /dev/null
@@ -0,0 +1,215 @@
+// 
+// EnsuresBlock.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class EnsuresBlock<Label> : BlockWithLabels<Label> {
+               private const uint Mask = 0xC0000000u;
+               private const uint BeginOldMask = 0x80000000u;
+               private const uint EndOldMask = 0x40000000u;
+
+               private List<uint> overridingLabels;
+
+               public EnsuresBlock (SubroutineBase<Label> subroutine, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+               }
+
+               private new EnsuresSubroutine<Label> Subroutine
+               {
+                       get { return (EnsuresSubroutine<Label>) base.Subroutine; }
+               }
+
+               public override int Count
+               {
+                       get
+                       {
+                               if (this.overridingLabels != null)
+                                       return this.overridingLabels.Count;
+                               return base.Count;
+                       }
+               }
+
+               public bool UsesOverriding
+               {
+                       get { return this.overridingLabels != null; }
+               }
+
+               public override bool TryGetLabel (int index, out Label label)
+               {
+                       int originalOffset;
+                       if (IsOriginal (index, out originalOffset))
+                               return base.TryGetLabel (originalOffset, out label);
+                       label = default(Label);
+                       return false;
+               }
+
+               public Result OriginalForwardDecode<Data, Result, Visitor> (int index, Visitor visitor, Data data)
+                       where Visitor : IAggregateVisitor<Label, Data, Result>
+               {
+                       Label label;
+                       if (base.TryGetLabel (index, out label))
+                               return Subroutine.CodeProvider.Decode<Visitor, Data, Result> (label, visitor, data);
+
+                       throw new InvalidOperationException ("should not happen");
+               }
+
+               public override Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+               {
+                       Label label;
+                       if (TryGetLabel (pc.Index, out label))
+                               return base.ForwardDecode<Data, Result, Visitor> (pc, visitor, data);
+
+                       int endOldIndex;
+                       if (IsBeginOld (pc.Index, out endOldIndex)) {
+                               CFGBlock block = Subroutine.InferredBeginEndBijection (pc);
+                               return visitor.BeginOld (pc, new APC (block, endOldIndex, pc.SubroutineContext), data);
+                       }
+
+                       int beginOldIndex;
+                       if (IsEndOld (pc.Index, out beginOldIndex)) {
+                               TypeNode endOldType;
+                               CFGBlock block = Subroutine.InferredBeginEndBijection (pc, out endOldType);
+                               return visitor.EndOld (pc, new APC (block, beginOldIndex, pc.SubroutineContext), endOldType, Dummy.Value, Dummy.Value, data);
+                       }
+
+                       return visitor.Nop (pc, data);
+               }
+
+               private bool IsEndOld (int index, out int beginOldIndex)
+               {
+                       if (this.overridingLabels != null && index < this.overridingLabels.Count && (this.overridingLabels [index] & EndOldMask) != 0) {
+                               beginOldIndex = (int) (this.overridingLabels [index] & (EndOldMask - 1));
+                               return true;
+                       }
+
+                       beginOldIndex = 0;
+                       return false;
+               }
+
+               private bool IsBeginOld (int index, out int endOldIndex)
+               {
+                       if (this.overridingLabels != null && index < this.overridingLabels.Count && (this.overridingLabels [index] & BeginOldMask) != 0) {
+                               endOldIndex = (int) (this.overridingLabels [index] & (EndOldMask - 1));
+                               return true;
+                       }
+
+                       endOldIndex = 0;
+                       return false;
+               }
+
+               private bool IsOriginal (int index, out int originalOffset)
+               {
+                       if (this.overridingLabels == null) {
+                               originalOffset = index;
+                               return true;
+                       }
+                       if (index < this.overridingLabels.Count && (this.overridingLabels [index] & Mask) == 0) {
+                               originalOffset = (int) (this.overridingLabels [index] & (EndOldMask - 1));
+                               return true;
+                       }
+
+                       originalOffset = 0;
+                       return false;
+               }
+
+               public void StartOverridingLabels ()
+               {
+                       this.overridingLabels = new List<uint> ();
+               }
+
+               public void BeginOld (int index)
+               {
+                       if (this.overridingLabels == null) {
+                               StartOverridingLabels ();
+                               for (int i = 0; i < index; ++i)
+                                       this.overridingLabels.Add ((uint) i);
+                       }
+                       this.overridingLabels.Add (BeginOldMask);
+               }
+
+               public void AddInstruction (int index)
+               {
+                       this.overridingLabels.Add ((uint) index);
+               }
+
+               public void EndOld (int index, TypeNode nextEndOldType)
+               {
+                       AddInstruction (index);
+                       EndOldWithoutInstruction (nextEndOldType);
+               }
+
+               public void EndOldWithoutInstruction (TypeNode nextEndOldType)
+               {
+                       int endOldIndex = this.overridingLabels.Count;
+                       CFGBlock beginBlock;
+                       this.overridingLabels.Add ((uint) (EndOldMask | PatchPriorBeginOld (this, endOldIndex, out beginBlock)));
+                       Subroutine.AddInferredOldMap (this.Index, endOldIndex, beginBlock, nextEndOldType);
+               }
+
+               private int PatchPriorBeginOld (CFGBlock endBlock, int endOldIndex, out CFGBlock beginBlock)
+               {
+                       for (int i = this == endBlock ? endOldIndex - 2 : Count - 1; i >= 0; i--) {
+                               int endOldI;
+                               if (IsBeginOld (i, out endOldI)) {
+                                       this.overridingLabels [i] = BeginOldMask | (uint)endOldIndex;
+                                       beginBlock = this;
+                                       Subroutine.AddInferredOldMap (this.Index, i, endBlock, default(TypeNode));
+                                       return i;
+                               }
+                       }
+
+                       IEnumerator<CFGBlock> enumerator = Subroutine.PredecessorBlocks (this).GetEnumerator ();
+                       if (!enumerator.MoveNext ())
+                               throw new InvalidOperationException ("missing begin_old");
+                       int result = PatchPriorBeginOld (endBlock, endOldIndex, enumerator.Current, out beginBlock);
+                       enumerator.MoveNext ();
+                       return result;
+               }
+
+               private int PatchPriorBeginOld (CFGBlock endBlock, int endOldIndex, CFGBlock current, out CFGBlock beginBlock)
+               {
+                       var ensuresBlock = current as EnsuresBlock<Label>;
+                       if (ensuresBlock != null)
+                               return ensuresBlock.PatchPriorBeginOld (endBlock, endOldIndex, out beginBlock);
+                       IEnumerator<CFGBlock> enumerator = current.Subroutine.PredecessorBlocks (current).GetEnumerator ();
+                       if (!enumerator.MoveNext ())
+                               throw new InvalidOperationException ("missing begin_old");
+
+                       int result = PatchPriorBeginOld (endBlock, endOldIndex, enumerator.Current, out beginBlock);
+                       enumerator.MoveNext ();
+                       return result;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EntryBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EntryBlock.cs
new file mode 100644 (file)
index 0000000..68e3251
--- /dev/null
@@ -0,0 +1,47 @@
+// 
+// EntryBlock.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 Mono.CodeContracts.Static.ControlFlow.Subroutines;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class EntryBlock<Label> : EntryExitBlock<Label> {
+               public EntryBlock (SubroutineBase<Label> subroutine, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+               }
+
+               public override Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+               {
+                       if (pc.Index != 0 || pc.SubroutineContext != null || !Subroutine.IsMethod)
+                               return visitor.Nop (pc, data);
+
+                       var methodInfo = Subroutine as IMethodInfo;
+                       return visitor.Entry (pc, methodInfo.Method, data);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EntryExitBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/EntryExitBlock.cs
new file mode 100644 (file)
index 0000000..e6b43b3
--- /dev/null
@@ -0,0 +1,43 @@
+// 
+// EntryExitBlock.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 Mono.CodeContracts.Static.ControlFlow.Subroutines;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class EntryExitBlock<Label> : BlockWithLabels<Label> {
+               public EntryExitBlock (SubroutineBase<Label> subroutine, ref int idGen)
+                       : base (subroutine, ref idGen)
+               {
+               }
+
+               public override int Count
+               {
+                       get { return 1; }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/LabelAdapter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/LabelAdapter.cs
new file mode 100644 (file)
index 0000000..0135d61
--- /dev/null
@@ -0,0 +1,394 @@
+// 
+// LabelAdapter.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       struct LabelAdapter<Label, Data, Result, Visitor> :
+               IAggregateVisitor<Label, Data, Result>
+               where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result> {
+               private readonly APC original_pc;
+               private readonly Visitor visitor;
+
+               public LabelAdapter (Visitor visitor, APC pc)
+               {
+                       this.visitor = visitor;
+                       this.original_pc = pc;
+               }
+
+               #region IAggregateVisitor<Label,Data,Result> Members
+               public Result Binary (Label pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, Data data)
+               {
+                       return this.visitor.Binary (ConvertLabel (pc), op, dest, operand1, operand2, data);
+               }
+
+               public Result Isinst (Label pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.Isinst (ConvertLabel (pc), type, dest, obj, data);
+               }
+
+               public Result LoadNull (Label pc, Dummy dest, Data polarity)
+               {
+                       return this.visitor.LoadNull (ConvertLabel (pc), dest, polarity);
+               }
+
+               public Result LoadConst (Label pc, TypeNode type, object constant, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadConst (ConvertLabel (pc), type, constant, dest, data);
+               }
+
+               public Result Sizeof (Label pc, TypeNode type, Dummy dest, Data data)
+               {
+                       return this.visitor.Sizeof (ConvertLabel (pc), type, dest, data);
+               }
+
+               public Result Unary (Label pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.Unary (ConvertLabel (pc), op, unsigned, dest, source, data);
+               }
+
+               public Result Arglist (Label pc, Dummy dest, Data data)
+               {
+                       return this.visitor.Arglist (ConvertLabel (pc), dest, data);
+               }
+
+               public Result Branch (Label pc, Label target, bool leavesExceptionBlock, Data data)
+               {
+                       return this.visitor.Branch (ConvertLabel (pc), ConvertLabel (target), leavesExceptionBlock, data);
+               }
+
+               public Result BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, Data data)
+               {
+                       return this.visitor.BranchCond (ConvertLabel (pc), ConvertLabel (target), bop, value1, value2, data);
+               }
+
+               public Result BranchTrue (Label pc, Label target, Dummy cond, Data data)
+               {
+                       return this.visitor.BranchTrue (ConvertLabel (pc), ConvertLabel (target), cond, data);
+               }
+
+               public Result BranchFalse (Label pc, Label target, Dummy cond, Data data)
+               {
+                       return this.visitor.BranchFalse (ConvertLabel (pc), ConvertLabel (target), cond, data);
+               }
+
+               public Result Break (Label pc, Data data)
+               {
+                       return this.visitor.Break (ConvertLabel (pc), data);
+               }
+
+               public Result Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.Call (ConvertLabel (pc), method, virt, extraVarargs, dest, args, data);
+               }
+
+               public Result Calli<TypeList, ArgList> (Label pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.Calli (ConvertLabel (pc), returnType, argTypes, instance, dest, functionPointer, args, data);
+               }
+
+               public Result CheckFinite (Label pc, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.CheckFinite (ConvertLabel (pc), dest, source, data);
+               }
+
+               public Result CopyBlock (Label pc, Dummy destAddress, Dummy srcAddress, Dummy len, Data data)
+               {
+                       return this.visitor.CopyBlock (ConvertLabel (pc), destAddress, srcAddress, len, data);
+               }
+
+               public Result EndFilter (Label pc, Dummy decision, Data data)
+               {
+                       return this.visitor.EndFilter (ConvertLabel (pc), decision, data);
+               }
+
+               public Result EndFinally (Label pc, Data data)
+               {
+                       return this.visitor.EndFinally (ConvertLabel (pc), data);
+               }
+
+               public Result Jmp (Label pc, Method method, Data data)
+               {
+                       return this.visitor.Jmp (ConvertLabel (pc), method, data);
+               }
+
+               public Result LoadArg (Label pc, Parameter argument, bool isOld, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadArg (ConvertLabel (pc), argument, isOld, dest, data);
+               }
+
+               public Result LoadArgAddress (Label pc, Parameter argument, bool isOld, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadArgAddress (ConvertLabel (pc), argument, isOld, dest, data);
+               }
+
+               public Result LoadLocal (Label pc, Local local, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadLocal (ConvertLabel (pc), local, dest, data);
+               }
+
+               public Result LoadLocalAddress (Label pc, Local local, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadLocalAddress (ConvertLabel (pc), local, dest, data);
+               }
+
+               public Result Nop (Label pc, Data data)
+               {
+                       return this.visitor.Nop (ConvertLabel (pc), data);
+               }
+
+               public Result Pop (Label pc, Dummy source, Data data)
+               {
+                       return this.visitor.Pop (ConvertLabel (pc), source, data);
+               }
+
+               public Result Return (Label pc, Dummy source, Data data)
+               {
+                       return this.visitor.Return (ConvertLabel (pc), source, data);
+               }
+
+               public Result StoreArg (Label pc, Parameter argument, Dummy source, Data data)
+               {
+                       return this.visitor.StoreArg (ConvertLabel (pc), argument, source, data);
+               }
+
+               public Result StoreLocal (Label pc, Local local, Dummy source, Data data)
+               {
+                       return this.visitor.StoreLocal (ConvertLabel (pc), local, source, data);
+               }
+
+               public Result Switch (Label pc, TypeNode type, IEnumerable<Pair<object, Label>> cases, Dummy value, Data data)
+               {
+                       return this.visitor.Nop (ConvertLabel (pc), data);
+               }
+
+               public Result Box (Label pc, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.Box (ConvertLabel (pc), type, dest, source, data);
+               }
+
+               public Result ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.ConstrainedCallvirt (ConvertLabel (pc), method, constraint, extraVarargs, dest, args, data);
+               }
+
+               public Result CastClass (Label pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.CastClass (ConvertLabel (pc), type, dest, obj, data);
+               }
+
+               public Result CopyObj (Label pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, Data data)
+               {
+                       return this.visitor.CopyObj (ConvertLabel (pc), type, destPtr, sourcePtr, data);
+               }
+
+               public Result Initobj (Label pc, TypeNode type, Dummy ptr, Data data)
+               {
+                       return this.visitor.Initobj (ConvertLabel (pc), type, ptr, data);
+               }
+
+               public Result LoadElement (Label pc, TypeNode type, Dummy dest, Dummy array, Dummy index, Data data)
+               {
+                       return this.visitor.LoadElement (ConvertLabel (pc), type, dest, array, index, data);
+               }
+
+               public Result LoadField (Label pc, Field field, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.LoadField (ConvertLabel (pc), field, dest, obj, data);
+               }
+
+               public Result LoadFieldAddress (Label pc, Field field, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.LoadFieldAddress (ConvertLabel (pc), field, dest, obj, data);
+               }
+
+               public Result LoadLength (Label pc, Dummy dest, Dummy array, Data data)
+               {
+                       return this.visitor.LoadLength (ConvertLabel (pc), dest, array, data);
+               }
+
+               public Result LoadStaticField (Label pc, Field field, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadStaticField (ConvertLabel (pc), field, dest, data);
+               }
+
+               public Result LoadStaticFieldAddress (Label pc, Field field, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadStaticFieldAddress (ConvertLabel (pc), field, dest, data);
+               }
+
+               public Result LoadTypeToken (Label pc, TypeNode type, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadTypeToken (ConvertLabel (pc), type, dest, data);
+               }
+
+               public Result LoadFieldToken (Label pc, Field type, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadFieldToken (ConvertLabel (pc), type, dest, data);
+               }
+
+               public Result LoadMethodToken (Label pc, Method type, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadMethodToken (ConvertLabel (pc), type, dest, data);
+               }
+
+               public Result NewArray<ArgList> (Label pc, TypeNode type, Dummy dest, ArgList lengths, Data data) where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.NewArray (ConvertLabel (pc), type, dest, lengths, data);
+               }
+
+               public Result NewObj<ArgList> (Label pc, Method ctor, Dummy dest, ArgList args, Data data) where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.NewObj (ConvertLabel (pc), ctor, dest, args, data);
+               }
+
+               public Result MkRefAny (Label pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.MkRefAny (ConvertLabel (pc), type, dest, obj, data);
+               }
+
+               public Result RefAnyType (Label pc, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.RefAnyType (ConvertLabel (pc), dest, source, data);
+               }
+
+               public Result RefAnyVal (Label pc, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.RefAnyVal (ConvertLabel (pc), type, dest, source, data);
+               }
+
+               public Result Rethrow (Label pc, Data data)
+               {
+                       return this.visitor.Rethrow (ConvertLabel (pc), data);
+               }
+
+               public Result StoreElement (Label pc, TypeNode type, Dummy array, Dummy index, Dummy value, Data data)
+               {
+                       return this.visitor.StoreElement (ConvertLabel (pc), type, array, index, value, data);
+               }
+
+               public Result StoreField (Label pc, Field field, Dummy obj, Dummy value, Data data)
+               {
+                       return this.visitor.StoreField (ConvertLabel (pc), field, obj, value, data);
+               }
+
+               public Result StoreStaticField (Label pc, Field field, Dummy value, Data data)
+               {
+                       return this.visitor.StoreStaticField (ConvertLabel (pc), field, value, data);
+               }
+
+               public Result Throw (Label pc, Dummy exception, Data data)
+               {
+                       return this.visitor.Throw (ConvertLabel (pc), exception, data);
+               }
+
+               public Result Unbox (Label pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.Unbox (ConvertLabel (pc), type, dest, obj, data);
+               }
+
+               public Result UnboxAny (Label pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.UnboxAny (ConvertLabel (pc), type, dest, obj, data);
+               }
+
+               public Result Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Data data)
+               {
+                       return this.visitor.Nop (ConvertLabel (pc), data);
+               }
+
+               public Result Entry (Label pc, Method method, Data data)
+               {
+                       return this.visitor.Entry (ConvertLabel (pc), method, data);
+               }
+
+               public Result Assume (Label pc, EdgeTag tag, Dummy condition, Data data)
+               {
+                       return this.visitor.Assume (ConvertLabel (pc), tag, condition, data);
+               }
+
+               public Result Assert (Label pc, EdgeTag tag, Dummy condition, Data data)
+               {
+                       return this.visitor.Assert (ConvertLabel (pc), tag, condition, data);
+               }
+
+               public Result BeginOld (Label pc, Label matchingEnd, Data data)
+               {
+                       if (this.original_pc.InsideOldManifestation)
+                               return this.visitor.Nop (ConvertLabel (pc), data);
+
+                       return this.visitor.BeginOld (ConvertLabel (pc), ConvertMatchingEndLabel (matchingEnd), data);
+               }
+
+               public Result EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.EndOld (ConvertLabel (pc), ConvertMatchingBeginLabel (matchingBegin), type, dest, source, data);
+               }
+
+               public Result LoadStack (Label pc, int offset, Dummy dest, Dummy source, bool isOld, Data data)
+               {
+                       return this.visitor.LoadStack (ConvertLabel (pc), offset, dest, source, isOld, data);
+               }
+
+               public Result LoadStackAddress (Label pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, Data data)
+               {
+                       return this.visitor.LoadStackAddress (ConvertLabel (pc), offset, dest, source, type, isOld, data);
+               }
+
+               public Result LoadResult (Label pc, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.LoadResult (ConvertLabel (pc), type, dest, source, data);
+               }
+               #endregion
+
+               private APC ConvertLabel (Label pc)
+               {
+                       return this.original_pc;
+               }
+
+               private APC ConvertMatchingEndLabel (Label matchingEnd)
+               {
+                       return ((OldValueSubroutine<Label>) this.original_pc.Block.Subroutine).EndOldAPC (this.original_pc.SubroutineContext);
+               }
+
+               private APC ConvertMatchingBeginLabel (Label matchingBegin)
+               {
+                       return ((OldValueSubroutine<Label>) this.original_pc.Block.Subroutine).BeginOldAPC (this.original_pc.SubroutineContext);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/MethodCallBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/MethodCallBlock.cs
new file mode 100644 (file)
index 0000000..52af607
--- /dev/null
@@ -0,0 +1,67 @@
+// 
+// MethodCallBlock.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class MethodCallBlock<Label> : BlockWithLabels<Label> {
+               public MethodCallBlock (Method calledMethod, SubroutineBase<Label> subroutine, ref int idGen, int parametersCount, bool isVirtual)
+                       : base (subroutine, ref idGen)
+               {
+                       CalledMethod = calledMethod;
+                       ParameterCount = parametersCount;
+                       IsVirtual = isVirtual;
+               }
+
+               public Method CalledMethod { get; private set; }
+               public bool IsVirtual { get; private set; }
+               public int ParameterCount { get; private set; }
+
+               public virtual bool IsNewObj
+               {
+                       get { return false; }
+               }
+
+               public override bool IsMethodCallBlock<TMethod> (out TMethod calledMethod, out bool isNewObj, out bool isVirtual)
+               {
+                       calledMethod = default (TMethod);
+                       isNewObj = false;
+                       isVirtual = false;
+
+                       if (!(CalledMethod is TMethod))
+                               return false;
+
+                       calledMethod = (TMethod) (object) CalledMethod;
+                       isNewObj = IsNewObj;
+                       isVirtual = IsVirtual;
+
+                       return true;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/NewObjCallBlock.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Blocks/NewObjCallBlock.cs
new file mode 100644 (file)
index 0000000..566360d
--- /dev/null
@@ -0,0 +1,44 @@
+// 
+// NewObjCallBlock.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Blocks {
+       class NewObjCallBlock<Label> : MethodCallBlock<Label> {
+               public NewObjCallBlock (Method calledMethod, int parametersCount, SubroutineBase<Label> subroutine, ref int idGen)
+                       : base (calledMethod, subroutine, ref idGen, parametersCount, false)
+               {
+               }
+
+               public override bool IsNewObj
+               {
+                       get { return true; }
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..23f0cce
--- /dev/null
@@ -0,0 +1,195 @@
+// 
+// BlockBuilder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+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;
+
+               private BlockBuilder (SubroutineBuilder<Label> builder)
+               {
+                       this.builder = builder;
+               }
+
+               private SubroutineBase<Label> 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)
+               {
+                       currentBlock.AddLabel (pc);
+                       CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.Branch, CurrentSubroutine.GetTargetBlock (target));
+
+                       return true;
+               }
+
+               public override bool BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, BlockWithLabels<Label> currentBlock)
+               {
+                       return HandleConditionalBranch (pc, target, true, currentBlock);
+               }
+
+               public override bool BranchFalse (Label pc, Label target, Dummy cond, BlockWithLabels<Label> currentBlock)
+               {
+                       return HandleConditionalBranch (pc, target, false, currentBlock);
+               }
+
+               public override bool BranchTrue (Label pc, Label target, Dummy cond, BlockWithLabels<Label> currentBlock)
+               {
+                       return HandleConditionalBranch (pc, target, true, currentBlock);
+               }
+
+               public override bool Throw (Label pc, Dummy exception, BlockWithLabels<Label> currentBlock)
+               {
+                       currentBlock.AddLabel (pc);
+                       return true;
+               }
+
+               public override bool Rethrow (Label pc, BlockWithLabels<Label> currentBlock)
+               {
+                       currentBlock.AddLabel (pc);
+                       return true;
+               }
+
+               public override bool EndFinally (Label pc, BlockWithLabels<Label> currentBlock)
+               {
+                       currentBlock.AddLabel (pc);
+                       CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.EndSubroutine, CurrentSubroutine.Exit);
+                       return true;
+               }
+
+               public override bool Return (Label pc, Dummy source, BlockWithLabels<Label> currentBlock)
+               {
+                       currentBlock.AddLabel (pc);
+                       CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.Return, CurrentSubroutine.Exit);
+                       CurrentSubroutine.AddReturnBlock (currentBlock);
+
+                       return true;
+               }
+
+               public override bool Nop (Label pc, BlockWithLabels<Label> currentBlock)
+               {
+                       return false;
+               }
+
+               public override bool LoadField (Label pc, Field field, Dummy dest, Dummy obj, BlockWithLabels<Label> data)
+               {
+                       if (CurrentSubroutine.IsMethod) {
+                               var methodInfo = (IMethodInfo) CurrentSubroutine;
+                               Property property;
+                               if (this.builder.MetaDataProvider.IsPropertyGetter (methodInfo.Method, out property))
+                                       this.builder.SubroutineFacade.AddReads (methodInfo.Method, field);
+                       }
+                       this.current_block.AddLabel (pc);
+                       return false;
+               }
+
+               public override bool StoreField (Label pc, Field field, Dummy obj, Dummy value, BlockWithLabels<Label> data)
+               {
+                       if (CurrentSubroutine.IsMethod) {
+                               var methodInfo = (IMethodInfo) CurrentSubroutine;
+                               Property property;
+                               if (this.builder.MetaDataProvider.IsPropertySetter (methodInfo.Method, out property))
+                                       this.builder.SubroutineFacade.AddReads (methodInfo.Method, field);
+                       }
+                       this.current_block.AddLabel (pc);
+                       return false;
+               }
+
+               public override bool EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, BlockWithLabels<Label> 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)
+               {
+                       TraceAggregateSequentally (aggregateStart);
+                       return false;
+               }
+               #endregion
+
+               public static BlockWithLabels<Label> BuildBlocks (Label entry, SubroutineBuilder<Label> subroutineBuilder)
+               {
+                       var blockBuilder = new BlockBuilder<Label> (subroutineBuilder);
+                       blockBuilder.TraceAggregateSequentally (entry);
+                       if (blockBuilder.current_block == null)
+                               return null;
+
+                       SubroutineBase<Label> subroutine = blockBuilder.CurrentSubroutine;
+
+                       subroutine.AddSuccessor (blockBuilder.current_block, EdgeTag.FallThroughReturn, subroutine.Exit);
+                       subroutine.AddReturnBlock (blockBuilder.current_block);
+
+                       return blockBuilder.current_block;
+               }
+
+               private void TraceAggregateSequentally (Label 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))
+                                       this.current_block = null;
+                       } while (this.builder.CodeProvider.Next (currentLabel, out currentLabel));
+               }
+
+               public override bool DefaultVisit (Label pc, BlockWithLabels<Label> currentBlock)
+               {
+                       currentBlock.AddLabel (pc);
+                       return false;
+               }
+
+               private bool HandleConditionalBranch (Label pc, Label target, bool isTrueBranch, BlockWithLabels<Label> 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);
+                       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);
+                       this.builder.RecordInformationSameAsOtherBlock (falseBlock, this.current_block);
+                       CurrentSubroutine.AddSuccessor (currentBlock, falseTag, falseBlock);
+                       this.current_block = falseBlock;
+
+                       return false;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockStartGatherer.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockStartGatherer.cs
new file mode 100644 (file)
index 0000000..d1edc74
--- /dev/null
@@ -0,0 +1,164 @@
+// 
+// BlockStartGatherer.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
+       class BlockStartGatherer<Label> : ILVisitorBase<Label, Dummy, Dummy, Dummy, bool>,
+                                                  IAggregateVisitor<Label, Dummy, bool> {
+               private readonly SubroutineBuilder<Label> parent;
+
+               public BlockStartGatherer (SubroutineBuilder<Label> parent)
+               {
+                       this.parent = parent;
+               }
+
+               #region IAggregateVisitor<Label,Dummy,bool> Members
+               public override bool Branch (Label pc, Label target, bool leavesExceptionBlock, Dummy data)
+               {
+                       AddTargetLabel (target);
+                       return true;
+               }
+
+               public override bool BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, Dummy data)
+               {
+                       AddTargetLabel (target);
+                       return true;
+               }
+
+               public override bool BranchFalse (Label pc, Label target, Dummy cond, Dummy data)
+               {
+                       AddTargetLabel (target);
+                       return true;
+               }
+
+               public override bool BranchTrue (Label pc, Label target, Dummy cond, Dummy data)
+               {
+                       AddTargetLabel (target);
+                       return true;
+               }
+
+               public override bool EndFinally (Label pc, Dummy data)
+               {
+                       return true;
+               }
+
+               public override bool Return (Label pc, Dummy source, Dummy data)
+               {
+                       return true;
+               }
+
+               public override bool Rethrow (Label pc, Dummy data)
+               {
+                       return true;
+               }
+
+               public override bool Throw (Label pc, Dummy exception, Dummy data)
+               {
+                       return true;
+               }
+
+               public override bool Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)
+               {
+                       return CallHelper (pc, method, false, virt);
+               }
+
+               public override bool ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)
+               {
+                       return CallHelper (pc, method, false, true);
+               }
+
+               public override bool NewObj<ArgList> (Label pc, Method ctor, Dummy dest, ArgList args, Dummy data)
+               {
+                       return CallHelper (pc, ctor, true, false);
+               }
+
+               public override bool BeginOld (Label pc, Label matchingEnd, Dummy data)
+               {
+                       AddTargetLabel (pc);
+                       this.parent.BeginOldHook (pc);
+                       return false;
+               }
+
+               public override bool EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, Dummy data)
+               {
+                       this.parent.EndOldHook (pc);
+                       return true;
+               }
+
+               public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Dummy data)
+               {
+                       return TraceAggregateSequentally (aggregateStart);
+               }
+               #endregion
+
+               public override bool DefaultVisit (Label pc, Dummy data)
+               {
+                       return false;
+               }
+
+               private bool CallHelper (Label pc, Method method, bool isNewObj, bool isVirtual)
+               {
+                       AddBlockStart (pc);
+                       if (isNewObj)
+                               this.parent.AddNewObjSite (pc, method);
+                       else
+                               this.parent.AddMethodCallSite (pc, new Pair<Method, bool> (method, isVirtual));
+
+                       return true;
+               }
+
+               public bool TraceAggregateSequentally (Label current)
+               {
+                       bool isCurrentBranches;
+                       bool isCurrentHasSuccessor;
+                       do {
+                               ICodeProvider<Label> codeProvider = this.parent.CodeProvider;
+                               isCurrentBranches = codeProvider.Decode<BlockStartGatherer<Label>, Dummy, bool> (current, this, Dummy.Value);
+                               isCurrentHasSuccessor = codeProvider.Next (current, out current);
+                               if (isCurrentBranches && isCurrentHasSuccessor)
+                                       AddBlockStart (current);
+                       } while (isCurrentHasSuccessor);
+
+                       return isCurrentBranches;
+               }
+
+               private void AddBlockStart (Label target)
+               {
+                       this.parent.AddBlockStart (target);
+               }
+
+               private void AddTargetLabel (Label target)
+               {
+                       this.parent.AddTargetLabel (target);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/EnsuresFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/EnsuresFactory.cs
new file mode 100644 (file)
index 0000000..21ff2ab
--- /dev/null
@@ -0,0 +1,73 @@
+// 
+// EnsuresFactory.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
+       class EnsuresFactory : SubroutineFactory<Method, Pair<Method, IImmutableSet<Subroutine>>> {
+               public EnsuresFactory (SubroutineFacade subroutineFacade) : base (subroutineFacade)
+               {
+               }
+
+               #region Overrides of SubroutineFactory<Method,Pair<Method,IImmutableSet<Subroutine>>>
+               protected override Subroutine BuildNewSubroutine (Method method)
+               {
+                       if (ContractProvider != null) {
+                               IImmutableSet<Subroutine> inheritedEnsures = GetInheritedEnsures (method);
+                               if (ContractProvider.HasEnsures (method))
+                                       return ContractProvider.AccessEnsures (method, this, new Pair<Method, IImmutableSet<Subroutine>> (method, inheritedEnsures));
+                               if (inheritedEnsures.Count > 0) {
+                                       if (inheritedEnsures.Count > 1)
+                                               return new EnsuresSubroutine<Dummy> (this.SubroutineFacade, method, inheritedEnsures);
+                                       return inheritedEnsures.Any;
+                               }
+                       }
+                       return new EnsuresSubroutine<Dummy> (this.SubroutineFacade, method, null);
+               }
+
+               private IImmutableSet<Subroutine> GetInheritedEnsures (Method method)
+               {
+                       IImmutableSet<Subroutine> result = ImmutableSet<Subroutine>.Empty ();
+                       if (MetaDataProvider.IsVirtual (method) && ContractProvider.CanInheritContracts (method)) {
+                               foreach (Method implementedMethod in MetaDataProvider.OverridenAndImplementedMethods (method)) {
+                                       Subroutine subroutine = Get (MetaDataProvider.Unspecialized (implementedMethod));
+                                       if (subroutine != null)
+                                               result = result.Add (subroutine);
+                               }
+                       }
+                       return result;
+               }
+
+               protected override Subroutine Factory<Label> (SimpleSubroutineBuilder<Label> builder, Label entry, Pair<Method, IImmutableSet<Subroutine>> data)
+               {
+                       return new EnsuresSubroutine<Label> (this.SubroutineFacade, data.Key, builder, entry, data.Value);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/RequiresFactory.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/RequiresFactory.cs
new file mode 100644 (file)
index 0000000..ad83681
--- /dev/null
@@ -0,0 +1,83 @@
+// 
+// RequiresFactory.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
+       class RequiresFactory : SubroutineFactory<Method, Pair<Method, IImmutableSet<Subroutine>>> {
+               public RequiresFactory (SubroutineFacade subroutineFacade)
+                       : base (subroutineFacade)
+               {
+               }
+
+               #region Overrides of SubroutineFactory<Method,Pair<Method,IImmutableSet<Subroutine>>>
+               protected override Subroutine BuildNewSubroutine (Method method)
+               {
+                       if (ContractProvider != null) {
+                               IImmutableSet<Subroutine> inheritedRequires = GetInheritedRequires (method);
+                               if (ContractProvider.HasRequires (method))
+                                       return ContractProvider.AccessRequires (method, this, new Pair<Method, IImmutableSet<Subroutine>> (method, inheritedRequires));
+                               if (inheritedRequires.Count > 0) {
+                                       if (inheritedRequires.Count == 1)
+                                               return inheritedRequires.Any;
+
+                                       return new RequiresSubroutine<Dummy> (this.SubroutineFacade, method, inheritedRequires);
+                               }
+                       }
+                       return null;
+               }
+
+               private IImmutableSet<Subroutine> GetInheritedRequires (Method method)
+               {
+                       IImmutableSet<Subroutine> result = ImmutableSet<Subroutine>.Empty ();
+
+                       if (MetaDataProvider.IsVirtual (method) && ContractProvider.CanInheritContracts (method)) {
+                               Method rootMethod;
+                               if (MetaDataProvider.TryGetRootMethod (method, out rootMethod)) {
+                                       Subroutine sub = Get (MetaDataProvider.Unspecialized (method));
+                                       if (sub != null)
+                                               result = result.Add (sub);
+                               }
+                               foreach (Method implMethod in MetaDataProvider.ImplementedMethods (method)) {
+                                       Subroutine sub = Get (MetaDataProvider.Unspecialized (implMethod));
+                                       if (sub != null)
+                                               result = result.Add (sub);
+                               }
+                       }
+
+                       return result;
+               }
+
+               protected override Subroutine Factory<Label> (SimpleSubroutineBuilder<Label> builder, Label entry, Pair<Method, IImmutableSet<Subroutine>> data)
+               {
+                       return new RequiresSubroutine<Label> (this.SubroutineFacade, data.Key, builder, entry, data.Value);
+               }
+               #endregion
+       }
+}
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
new file mode 100644 (file)
index 0000000..9a31945
--- /dev/null
@@ -0,0 +1,100 @@
+// 
+// SimpleSubroutineBuilder.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.Collections.Generic;
+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> ();
+
+               private BlockWithLabels<Label> block_prior_to_old;
+               private OldValueSubroutine<Label> current_old_subroutine;
+               private SubroutineBase<Label> current_subroutine;
+
+               public SimpleSubroutineBuilder (ICodeProvider<Label> codeProvider,
+                                               SubroutineFacade subroutineFacade,
+                                               Label entry)
+                       : base (codeProvider, subroutineFacade, entry)
+               {
+                       Initialize (entry);
+               }
+
+               public override SubroutineBase<Label> CurrentSubroutine
+               {
+                       get
+                       {
+                               if (this.current_old_subroutine != null)
+                                       return this.current_old_subroutine;
+                               return this.current_subroutine;
+                       }
+               }
+
+               public BlockWithLabels<Label> BuildBlocks (Label entry, SubroutineBase<Label> subroutine)
+               {
+                       this.current_subroutine = subroutine;
+
+                       return base.BuildBlocks (entry);
+               }
+
+               public override BlockWithLabels<Label> RecordInformationForNewBlock (Label currentLabel, BlockWithLabels<Label> previousBlock)
+               {
+                       Label label;
+                       if (previousBlock != null && previousBlock.TryGetLastLabel (out label) && this.endOldStart.Contains (label)) {
+                               OldValueSubroutine<Label> oldValueSubroutine = this.current_old_subroutine;
+                               oldValueSubroutine.Commit (previousBlock);
+                               this.current_old_subroutine = null;
+                               BlockWithLabels<Label> 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))
+                               return base.RecordInformationForNewBlock (currentLabel, previousBlock);
+                       this.current_old_subroutine = new OldValueSubroutine<Label> (this.SubroutineFacade,
+                                                                                    ((MethodContractSubroutine<Label>) this.current_subroutine).Method,
+                                                                                    this, currentLabel);
+                       this.block_prior_to_old = previousBlock;
+                       BlockWithLabels<Label> newBlock = base.RecordInformationForNewBlock (currentLabel, null);
+                       this.current_old_subroutine.RegisterBeginBlock (newBlock);
+                       return newBlock;
+               }
+
+               public override void BeginOldHook (Label label)
+               {
+                       this.beginOldStart.Add (label);
+               }
+
+               public override void EndOldHook (Label label)
+               {
+                       this.endOldStart.Add (label);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineBuilder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineBuilder.cs
new file mode 100644 (file)
index 0000000..477d01c
--- /dev/null
@@ -0,0 +1,193 @@
+// 
+// SubroutineBuilder.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
+       abstract class SubroutineBuilder<Label> {
+               public readonly SubroutineFacade SubroutineFacade;
+
+               private readonly Dictionary<Label, Pair<Method, bool>> labels_for_call_sites = new Dictionary<Label, Pair<Method, bool>> ();
+               private readonly Dictionary<Label, Method> labels_for_new_obj_sites = new Dictionary<Label, Method> ();
+               private readonly HashSet<Label> labels_starting_blocks = new HashSet<Label> ();
+               private readonly HashSet<Label> target_labels = new HashSet<Label> ();
+
+               protected SubroutineBuilder (ICodeProvider<Label> codeProvider,
+                                            SubroutineFacade subroutineFacade,
+                                            Label entry)
+               {
+                       this.SubroutineFacade = subroutineFacade;
+                       CodeProvider = codeProvider;
+                       AddTargetLabel (entry);
+               }
+
+               public ICodeProvider<Label> CodeProvider { get; private set; }
+               public abstract SubroutineBase<Label> CurrentSubroutine { get; }
+
+               public IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.SubroutineFacade.MetaDataProvider; }
+               }
+
+               protected IContractProvider ContractProvider
+               {
+                       get { return this.SubroutineFacade.ContractProvider; }
+               }
+
+               public void AddTargetLabel (Label target)
+               {
+                       AddBlockStart (target);
+                       this.target_labels.Add (target);
+               }
+
+               public void AddBlockStart (Label target)
+               {
+                       this.labels_starting_blocks.Add (target);
+               }
+
+               protected void Initialize (Label entry)
+               {
+                       new BlockStartGatherer<Label> (this).TraceAggregateSequentally (entry);
+               }
+
+               public bool IsBlockStart (Label label)
+               {
+                       return this.labels_starting_blocks.Contains (label);
+               }
+
+               public bool IsTargetLabel (Label label)
+               {
+                       return this.target_labels.Contains (label);
+               }
+
+               public bool IsMethodCallSite (Label label, out Pair<Method, bool> methodVirtPair)
+               {
+                       return this.labels_for_call_sites.TryGetValue (label, out methodVirtPair);
+               }
+
+               public bool IsNewObjSite (Label label, out Method constructor)
+               {
+                       return this.labels_for_new_obj_sites.TryGetValue (label, out constructor);
+               }
+
+               protected BlockWithLabels<Label> BuildBlocks (Label entry)
+               {
+                       return BlockBuilder<Label>.BuildBlocks (entry, this);
+               }
+
+               public virtual void RecordInformationSameAsOtherBlock (BlockWithLabels<Label> newBlock, BlockWithLabels<Label> currentBlock)
+               {
+               }
+
+               public virtual BlockWithLabels<Label> RecordInformationForNewBlock (Label currentLabel, BlockWithLabels<Label> previousBlock)
+               {
+                       BlockWithLabels<Label> block = CurrentSubroutine.GetBlock (currentLabel);
+                       if (previousBlock != null) {
+                               BlockWithLabels<Label> newBlock = block;
+                               BlockWithLabels<Label> prevBlock = previousBlock;
+                               if (block is MethodCallBlock<Label> && previousBlock is MethodCallBlock<Label>) {
+                                       BlockWithLabels<Label> ab = CurrentSubroutine.NewBlock ();
+                                       RecordInformationSameAsOtherBlock (ab, previousBlock);
+                                       newBlock = ab;
+                                       prevBlock = ab;
+                                       CurrentSubroutine.AddSuccessor (previousBlock, EdgeTag.FallThrough, ab);
+                                       CurrentSubroutine.AddSuccessor (ab, EdgeTag.FallThrough, block);
+                               } else
+                                       CurrentSubroutine.AddSuccessor (previousBlock, EdgeTag.FallThrough, block);
+
+                               InsertPostConditionEdges (previousBlock, newBlock);
+                               InsertPreConditionEdges (prevBlock, block);
+                       }
+                       return block;
+               }
+
+               protected void InsertPreConditionEdges (BlockWithLabels<Label> previousBlock, BlockWithLabels<Label> newBlock)
+               {
+                       var methodCallBlock = newBlock as MethodCallBlock<Label>;
+                       if (methodCallBlock == null || CurrentSubroutine.IsContract || CurrentSubroutine.IsOldValue)
+                               return;
+
+                       if (CurrentSubroutine.IsMethod) {
+                               var methodInfo = CurrentSubroutine as IMethodInfo;
+                               Property property;
+                               if (methodInfo != null && MetaDataProvider.IsConstructor (methodInfo.Method)
+                                   && MetaDataProvider.IsPropertySetter (methodCallBlock.CalledMethod, out property)
+                                   && MetaDataProvider.IsAutoPropertyMember (methodCallBlock.CalledMethod))
+                                       return;
+                       }
+
+                       EdgeTag callTag = methodCallBlock.IsNewObj ? EdgeTag.BeforeNewObj : EdgeTag.BeforeCall;
+                       Subroutine requires = this.SubroutineFacade.GetRequires (methodCallBlock.CalledMethod);
+
+                       CurrentSubroutine.AddEdgeSubroutine (previousBlock, newBlock, requires, callTag);
+               }
+
+               protected void InsertPostConditionEdges (BlockWithLabels<Label> previousBlock, BlockWithLabels<Label> newBlock)
+               {
+                       var methodCallBlock = previousBlock as MethodCallBlock<Label>;
+                       if (methodCallBlock == null)
+                               return;
+
+                       if (CurrentSubroutine.IsMethod) {
+                               var methodInfo = CurrentSubroutine as IMethodInfo;
+                               Property property;
+                               if (methodInfo != null && MetaDataProvider.IsConstructor (methodInfo.Method)
+                                   && MetaDataProvider.IsPropertyGetter (methodCallBlock.CalledMethod, out property)
+                                   && MetaDataProvider.IsAutoPropertyMember (methodCallBlock.CalledMethod))
+                                       return;
+                       }
+
+                       EdgeTag callTag = methodCallBlock.IsNewObj ? EdgeTag.AfterNewObj : EdgeTag.AfterCall;
+                       Subroutine ensures = this.SubroutineFacade.GetEnsures (methodCallBlock.CalledMethod);
+
+                       CurrentSubroutine.AddEdgeSubroutine (previousBlock, newBlock, ensures, callTag);
+               }
+
+               public virtual void BeginOldHook (Label label)
+               {
+               }
+
+               public virtual void EndOldHook (Label label)
+               {
+               }
+
+               public void AddMethodCallSite (Label pc, Pair<Method, bool> methodVirtPair)
+               {
+                       this.labels_for_call_sites [pc] = methodVirtPair;
+               }
+
+               public void AddNewObjSite (Label pc, Method method)
+               {
+                       this.labels_for_new_obj_sites [pc] = method;
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..a9539d9
--- /dev/null
@@ -0,0 +1,75 @@
+// 
+// SubroutineFactory.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
+       abstract class SubroutineFactory<Key, Data> : ICodeConsumer<Data, Subroutine> {
+               protected readonly SubroutineFacade SubroutineFacade;
+               private readonly Dictionary<Key, Subroutine> cache = new Dictionary<Key, Subroutine> ();
+
+               protected SubroutineFactory (SubroutineFacade subroutineFacade)
+               {
+                       this.SubroutineFacade = subroutineFacade;
+               }
+
+               protected IContractProvider ContractProvider
+               {
+                       get { return this.SubroutineFacade.ContractProvider; }
+               }
+
+               protected IMetaDataProvider MetaDataProvider
+               {
+                       get { return this.SubroutineFacade.MetaDataProvider; }
+               }
+
+               #region ICodeConsumer<Data,Subroutine> Members
+               public Subroutine Accept<Label> (ICodeProvider<Label> codeProvider, Label entryPoint, Data data)
+               {
+                       return Factory (new SimpleSubroutineBuilder<Label> (codeProvider, this.SubroutineFacade, entryPoint), entryPoint, data);
+               }
+               #endregion
+
+               public Subroutine Get (Key key)
+               {
+                       if (this.cache.ContainsKey (key))
+                               return this.cache [key];
+
+                       Subroutine sub = BuildNewSubroutine (key);
+                       this.cache.Add (key, sub);
+                       if (sub != null)
+                               sub.Initialize ();
+                       return sub;
+               }
+
+               protected abstract Subroutine BuildNewSubroutine (Key key);
+               protected abstract Subroutine Factory<Label> (SimpleSubroutineBuilder<Label> builder, Label entry, Data data);
+       }
+}
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
new file mode 100644 (file)
index 0000000..33d0882
--- /dev/null
@@ -0,0 +1,221 @@
+// 
+// SubroutineWithHandlersBuilder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
+       class SubroutineWithHandlersBuilder<Label, Handler> : SubroutineBuilder<Label> {
+               private readonly Dictionary<Label, Handler> handler_starting_at = new Dictionary<Label, Handler> ();
+               private readonly Method method;
+               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;
+
+               public SubroutineWithHandlersBuilder (IMethodCodeProvider<Label, Handler> codeProvider,
+                                                     SubroutineFacade subroutineFacade,
+                                                     Method method,
+                                                     Label entry)
+                       : base (codeProvider, subroutineFacade, entry)
+               {
+                       this.method = method;
+                       ComputeTryBlockStartAndEndInfo (this.method);
+                       Initialize (entry);
+               }
+
+               private new IMethodCodeProvider<Label, Handler> CodeProvider
+               {
+                       get { return (IMethodCodeProvider<Label, Handler>) base.CodeProvider; }
+               }
+
+               protected SubroutineWithHandlers<Label, Handler> CurrentSubroutineWithHandlers
+               {
+                       get { return this.subroutine_stack.Head; }
+               }
+
+               private LispList<Handler> CurrentProtectingHanlders
+               {
+                       get { return CurrentSubroutineWithHandlers.CurrentProtectingHandlers; }
+                       set { CurrentSubroutineWithHandlers.CurrentProtectingHandlers = value; }
+               }
+
+               public override SubroutineBase<Label> CurrentSubroutine
+               {
+                       get { return this.subroutine_stack.Head; }
+               }
+
+               private void ComputeTryBlockStartAndEndInfo (Method method)
+               {
+                       foreach (Handler handler in CodeProvider.GetTryBlocks (method)) {
+                               if (CodeProvider.IsFilterHandler (handler))
+                                       AddTargetLabel (CodeProvider.FilterExpressionStart (handler));
+                               AddTargetLabel (CodeProvider.HandlerStart (handler));
+                               AddTargetLabel (CodeProvider.HandlerEnd (handler));
+                               AddTryStart (handler);
+                               AddTryEnd (handler);
+                               AddHandlerEnd (handler);
+                               this.handler_starting_at.Add (CodeProvider.HandlerStart (handler), handler);
+                       }
+               }
+
+               private void AddHandlerEnd (Handler handler)
+               {
+                       if (!IsFaultOrFinally (handler))
+                               return;
+
+                       Label handlerEnd = CodeProvider.HandlerEnd (handler);
+                       Queue<Handler> queue;
+                       this.subroutine_handler_end_list.TryGetValue (handlerEnd, out queue);
+                       if (queue == null) {
+                               queue = new Queue<Handler> ();
+                               this.subroutine_handler_end_list [handlerEnd] = queue;
+                       }
+                       queue.Enqueue (handler);
+                       AddTargetLabel (handlerEnd);
+               }
+
+               private void AddTryEnd (Handler handler)
+               {
+                       Label tryEnd = CodeProvider.TryEnd (handler);
+                       Queue<Handler> queue;
+                       this.try_end_list.TryGetValue (tryEnd, out queue);
+                       if (queue == null) {
+                               queue = new Queue<Handler> ();
+                               this.try_end_list [tryEnd] = queue;
+                       }
+                       queue.Enqueue (handler);
+                       AddTargetLabel (tryEnd);
+               }
+
+               private void AddTryStart (Handler handler)
+               {
+                       Label tryStart = CodeProvider.TryStart (handler);
+                       Stack<Handler> stack;
+                       this.try_start_list.TryGetValue (tryStart, out stack);
+                       if (stack == null) {
+                               stack = new Stack<Handler> ();
+                               this.try_start_list [tryStart] = stack;
+                       }
+                       stack.Push (handler);
+                       AddTargetLabel (tryStart);
+               }
+
+               public CFGBlock BuildBlocks (Label entry, SubroutineWithHandlers<Label, Handler> subroutine)
+               {
+                       this.subroutine_stack = LispList<SubroutineWithHandlers<Label, Handler>>.Cons (subroutine, null);
+                       return base.BuildBlocks (entry);
+               }
+
+               public override void RecordInformationSameAsOtherBlock (BlockWithLabels<Label> newBlock, BlockWithLabels<Label> currentBlock)
+               {
+                       LispList<Handler> list;
+                       if (!CurrentSubroutineWithHandlers.ProtectingHandlers.TryGetValue (currentBlock, out list))
+                               return;
+                       CurrentSubroutineWithHandlers.ProtectingHandlers.Add (newBlock, list);
+               }
+
+               public override BlockWithLabels<Label> RecordInformationForNewBlock (Label currentLabel, BlockWithLabels<Label> previousBlock)
+               {
+                       BlockWithLabels<Label> result = null;
+                       Queue<Handler> handlerEnd = GetHandlerEnd (currentLabel);
+                       if (handlerEnd != null) {
+                               foreach (Handler handler in handlerEnd) {
+                                       this.subroutine_stack.Head.Commit ();
+                                       this.subroutine_stack = this.subroutine_stack.Tail;
+                                       previousBlock = null;
+                               }
+                       }
+                       Queue<Handler> tryEnd = GetTryEnd (currentLabel);
+                       if (tryEnd != null) {
+                               foreach (Handler handler in tryEnd) {
+                                       if (!Equals (handler, CurrentProtectingHanlders.Head))
+                                               throw new InvalidOperationException ("wrong handler");
+                                       CurrentProtectingHanlders = CurrentProtectingHanlders.Tail;
+                               }
+                       }
+                       Handler handler1;
+                       if (IsHandlerStart (currentLabel, out handler1)) {
+                               if (IsFaultOrFinally (handler1)) {
+                                       SubroutineWithHandlers<Label, Handler> sub = !CodeProvider.IsFaultHandler (handler1)
+                                                                                       ? new FinallySubroutine<Label, Handler> (this.SubroutineFacade, currentLabel, this)
+                                                                                       : (FaultFinallySubroutineBase<Label, Handler>) new FaultSubroutine<Label, Handler> (this.SubroutineFacade, currentLabel, this);
+                                       CurrentSubroutineWithHandlers.FaultFinallySubroutines.Add (handler1, sub);
+                                       this.subroutine_stack = this.subroutine_stack.Cons (sub);
+                                       previousBlock = null;
+                               } else
+                                       result = CurrentSubroutineWithHandlers.CreateCatchFilterHeader (handler1, currentLabel);
+                       }
+                       if (result == null)
+                               result = base.RecordInformationForNewBlock (currentLabel, previousBlock);
+                       Stack<Handler> tryStart = GetTryStart (currentLabel);
+                       if (tryStart != null) {
+                               foreach (Handler handler in tryStart)
+                                       CurrentProtectingHanlders = CurrentProtectingHanlders.Cons (handler);
+                       }
+
+                       CurrentSubroutineWithHandlers.ProtectingHandlers.Add (result, CurrentProtectingHanlders);
+                       return result;
+               }
+
+               private bool IsFaultOrFinally (Handler handler)
+               {
+                       return CodeProvider.IsFaultHandler (handler) || CodeProvider.IsFinallyHandler (handler);
+               }
+
+               private bool IsHandlerStart (Label currentLabel, out Handler handler)
+               {
+                       return this.handler_starting_at.TryGetValue (currentLabel, out handler);
+               }
+
+               private Stack<Handler> GetTryStart (Label currentLabel)
+               {
+                       Stack<Handler> queue;
+                       this.try_start_list.TryGetValue (currentLabel, out queue);
+                       return queue;
+               }
+
+               private Queue<Handler> GetTryEnd (Label currentLabel)
+               {
+                       Queue<Handler> queue;
+                       this.try_end_list.TryGetValue (currentLabel, out queue);
+                       return queue;
+               }
+
+               private Queue<Handler> GetHandlerEnd (Label currentLabel)
+               {
+                       Queue<Handler> queue;
+                       this.subroutine_handler_end_list.TryGetValue (currentLabel, out queue);
+                       return queue;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/EnsuresSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/EnsuresSubroutine.cs
new file mode 100644 (file)
index 0000000..328126a
--- /dev/null
@@ -0,0 +1,152 @@
+// 
+// EnsuresSubroutine.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       sealed class EnsuresSubroutine<Label> : MethodContractSubroutine<Label>, IEquatable<EnsuresSubroutine<Label>> {
+               private readonly Dictionary<int, Pair<CFGBlock, TypeNode>> inferred_old_label_reverse_map;
+
+               public EnsuresSubroutine (SubroutineFacade subroutineFacade,
+                                         Method method, IImmutableSet<Subroutine> inherited) : base (subroutineFacade, method)
+               {
+                       this.inferred_old_label_reverse_map = new Dictionary<int, Pair<CFGBlock, TypeNode>> ();
+                       AddSuccessor (Entry, EdgeTag.Entry, Exit);
+                       AddBaseEnsures (Entry, Exit, inherited);
+                       Commit ();
+               }
+
+               public EnsuresSubroutine (SubroutineFacade subroutineFacade,
+                                         Method method,
+                                         SimpleSubroutineBuilder<Label> builder, Label startLabel, IImmutableSet<Subroutine> inherited)
+                       : base (subroutineFacade, method, builder, startLabel)
+               {
+                       this.inferred_old_label_reverse_map = new Dictionary<int, Pair<CFGBlock, TypeNode>> ();
+                       AddBaseEnsures (Entry, GetTargetBlock (startLabel), inherited);
+               }
+
+               public override SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Ensures; }
+               }
+
+               public override bool IsEnsures
+               {
+                       get { return true; }
+               }
+
+               public override bool IsContract
+               {
+                       get { return true; }
+               }
+
+               #region IEquatable<EnsuresSubroutine<Label>> Members
+               public bool Equals (EnsuresSubroutine<Label> other)
+               {
+                       return Id == other.Id;
+               }
+               #endregion
+
+               private void AddBaseEnsures (CFGBlock from, CFGBlock to, IImmutableSet<Subroutine> inherited)
+               {
+                       if (inherited == null)
+                               return;
+                       foreach (Subroutine subroutine in inherited.Elements)
+                               AddEdgeSubroutine (from, to, subroutine, EdgeTag.Inherited);
+               }
+
+               public override void Initialize ()
+               {
+                       if (Builder == null)
+                               return;
+                       Builder.BuildBlocks (this.StartLabel, this);
+                       Commit ();
+                       Builder = null;
+               }
+
+               public override BlockWithLabels<Label> NewBlock ()
+               {
+                       return new EnsuresBlock<Label> (this, ref this.BlockIdGenerator);
+               }
+
+               public override void Commit ()
+               {
+                       base.Commit ();
+
+                       var visitor = new OldScanStateMachine<Label> (this);
+                       EnsuresBlock<Label> priorBlock = null;
+
+                       foreach (CFGBlock block in Blocks) {
+                               var ensuresBlock = block as EnsuresBlock<Label>;
+                               if (ensuresBlock != null) {
+                                       priorBlock = ensuresBlock;
+                                       int count = ensuresBlock.Count;
+                                       visitor.StartBlock (ensuresBlock);
+
+                                       for (int i = 0; i < count; i++) {
+                                               if (ensuresBlock.OriginalForwardDecode<int, Boolean, OldScanStateMachine<Label>> (i, visitor, i))
+                                                       ensuresBlock.AddInstruction (i);
+                                       }
+                               } else
+                                       visitor.HandlePotentialCallBlock (block as MethodCallBlock<Label>, priorBlock);
+                               foreach (CFGBlock succ in SuccessorBlocks (block))
+                                       visitor.SetStartState (succ);
+                       }
+               }
+
+               public void AddInferredOldMap (int blockIndex, int instructionIndex, CFGBlock otherBlock, TypeNode endOldType)
+               {
+                       this.inferred_old_label_reverse_map.Add (OverlayInstructionKey (blockIndex, instructionIndex), new Pair<CFGBlock, TypeNode> (otherBlock, endOldType));
+               }
+
+               private static int OverlayInstructionKey (int blockIndex, int instructionIndex)
+               {
+                       return (instructionIndex << 16) + blockIndex;
+               }
+
+               public CFGBlock InferredBeginEndBijection (APC pc)
+               {
+                       TypeNode endOldType;
+                       return InferredBeginEndBijection (pc, out endOldType);
+               }
+
+               public CFGBlock InferredBeginEndBijection (APC pc, out TypeNode endOldType)
+               {
+                       Pair<CFGBlock, TypeNode> pair;
+                       if (!this.inferred_old_label_reverse_map.TryGetValue (OverlayInstructionKey (pc.Block.Index, pc.Index), out pair))
+                               throw new InvalidOperationException ("Fatal bug in ensures CFG begin/end old map");
+                       endOldType = pair.Value;
+                       return pair.Key;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultFinallySubroutineBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultFinallySubroutineBase.cs
new file mode 100644 (file)
index 0000000..4da8717
--- /dev/null
@@ -0,0 +1,52 @@
+// 
+// FaultFinallySubroutineBase.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 Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       abstract class FaultFinallySubroutineBase<Label, Handler> : SubroutineWithHandlers<Label, Handler> {
+               protected FaultFinallySubroutineBase (SubroutineFacade subroutineFacade, Label startLabel, SubroutineBuilder<Label> builder)
+                       : base (subroutineFacade, startLabel, builder)
+               {
+               }
+
+               public override bool HasContextDependentStackDepth
+               {
+                       get { return false; }
+               }
+
+               public override bool IsFaultFinally
+               {
+                       get { return true; }
+               }
+
+               public override void Initialize ()
+               {
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultSubroutine.cs
new file mode 100644 (file)
index 0000000..1e259a1
--- /dev/null
@@ -0,0 +1,43 @@
+// 
+// FaultSubroutine.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 Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       class FaultSubroutine<Label, Handler> : FaultFinallySubroutineBase<Label, Handler> {
+               public FaultSubroutine (SubroutineFacade subroutineFacade, Label startLabel,
+                                       SubroutineBuilder<Label> builder) : base (subroutineFacade, startLabel, builder)
+               {
+               }
+
+               public override SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Fault; }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FinallySubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/FinallySubroutine.cs
new file mode 100644 (file)
index 0000000..4351a46
--- /dev/null
@@ -0,0 +1,43 @@
+// 
+// FinallySubroutine.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 Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       class FinallySubroutine<Label, Handler> : FaultFinallySubroutineBase<Label, Handler> {
+               public FinallySubroutine (SubroutineFacade subroutineFacade, Label startLabel, SubroutineBuilder<Label> builder)
+                       : base (subroutineFacade, startLabel, builder)
+               {
+               }
+
+               public override SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Finally; }
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..1509dd5
--- /dev/null
@@ -0,0 +1,63 @@
+// 
+// MethodContractSubroutine.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       abstract class MethodContractSubroutine<Label> : SubroutineBase<Label>, IMethodInfo {
+               private readonly Method method;
+
+               protected MethodContractSubroutine (SubroutineFacade subroutineFacade,
+                                                   Method method) : base (subroutineFacade)
+               {
+                       this.method = method;
+               }
+
+               protected MethodContractSubroutine (SubroutineFacade subroutineFacade,
+                                                   Method method,
+                                                   SimpleSubroutineBuilder<Label> builder,
+                                                   Label startLabel) : base (subroutineFacade, startLabel, builder)
+               {
+                       this.method = method;
+               }
+
+               protected new SimpleSubroutineBuilder<Label> Builder
+               {
+                       get { return (SimpleSubroutineBuilder<Label>) base.Builder; }
+                       set { base.Builder = value; }
+               }
+
+               #region IMethodInfo Members
+               public Method Method
+               {
+                       get { return this.method; }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodSubroutine.cs
new file mode 100644 (file)
index 0000000..78c7866
--- /dev/null
@@ -0,0 +1,136 @@
+// 
+// MethodSubroutine.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       class MethodSubroutine<Label, Handler> : SubroutineWithHandlers<Label, Handler>, IMethodInfo {
+               private readonly Method method;
+               private HashSet<BlockWithLabels<Label>> blocks_ending_in_return_point;
+
+               public MethodSubroutine (SubroutineFacade subroutineFacade, Method method)
+                       : base (subroutineFacade)
+               {
+                       this.method = method;
+               }
+
+               public MethodSubroutine (SubroutineFacade SubroutineFacade,
+                                        Method method, Label startLabel,
+                                        SubroutineWithHandlersBuilder<Label, Handler> builder) : base (SubroutineFacade, startLabel, builder)
+               {
+                       this.method = method;
+                       IMetaDataProvider metaDataProvider = this.SubroutineFacade.MetaDataProvider;
+                       builder.BuildBlocks (startLabel, this);
+                       BlockWithLabels<Label> targetBlock = GetTargetBlock (startLabel);
+                       Commit ();
+
+                       TypeNode type = metaDataProvider.DeclaringType (method);
+                       Subroutine invariant = this.SubroutineFacade.GetInvariant (type);
+                       if (invariant != null && !metaDataProvider.IsConstructor (method) && !metaDataProvider.IsStatic (method)) {
+                               AddEdgeSubroutine (Entry, targetBlock, invariant, EdgeTag.Entry);
+                               Subroutine requires = this.SubroutineFacade.GetRequires (method);
+                               if (requires != null)
+                                       AddEdgeSubroutine (Entry, targetBlock, requires, EdgeTag.Entry);
+                       } else
+                               AddEdgeSubroutine (Entry, targetBlock, this.SubroutineFacade.GetRequires (method), EdgeTag.Entry);
+
+                       if (this.blocks_ending_in_return_point == null)
+                               return;
+
+                       Subroutine ensures = this.SubroutineFacade.GetEnsures (method);
+                       bool putInvariantAfterExit = !metaDataProvider.IsStatic (method) 
+                               && !metaDataProvider.IsFinalizer (method) && !metaDataProvider.IsDispose (method);
+                       foreach (var block in this.blocks_ending_in_return_point) {
+                               if (putInvariantAfterExit)
+                                       AddEdgeSubroutine (block, Exit, invariant, EdgeTag.Exit);
+                               AddEdgeSubroutine (block, Exit, ensures, EdgeTag.Exit);
+                       }
+
+                       if (ensures != null) {
+                               throw new NotImplementedException();
+                       }
+
+                       this.blocks_ending_in_return_point = null;
+               }
+
+               #region Overrides of Subroutine
+               public override void Initialize ()
+               {
+               }
+               #endregion
+
+               #region Overrides of SubroutineBase<Label>
+               public override void AddReturnBlock (BlockWithLabels<Label> block)
+               {
+                       if (this.blocks_ending_in_return_point == null)
+                               this.blocks_ending_in_return_point = new HashSet<BlockWithLabels<Label>> ();
+
+                       this.blocks_ending_in_return_point.Add (block);
+
+                       base.AddReturnBlock (block);
+               }
+               #endregion
+
+               #region Implementation of IMethodInfo<Method>
+               public Method Method
+               {
+                       get { return this.method; }
+               }
+               #endregion
+
+               public override SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Method; }
+               }
+
+               public override bool HasReturnValue
+               {
+                       get { return !this.SubroutineFacade.MetaDataProvider.IsVoidMethod (this.method); }
+               }
+
+               public override bool IsMethod
+               {
+                       get { return true; }
+               }
+
+               public override bool IsConstructor
+               {
+                       get { return this.SubroutineFacade.MetaDataProvider.IsConstructor (this.method); }
+               }
+
+               public override string Name
+               {
+                       get { return this.SubroutineFacade.MetaDataProvider.FullName (this.method); }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldScanStateMachine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/OldScanStateMachine.cs
new file mode 100644 (file)
index 0000000..c7e274a
--- /dev/null
@@ -0,0 +1,160 @@
+// 
+// OldScanStateMachine.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       class OldScanStateMachine<Label> : ILVisitorBase<Label, Dummy, Dummy, int, bool>,
+                                               IAggregateVisitor<Label, int, bool> {
+               private readonly Dictionary<CFGBlock, ScanState> block_start_state = new Dictionary<CFGBlock, ScanState> ();
+               private readonly EnsuresSubroutine<Label> subroutine;
+               private EnsuresBlock<Label> current_block;
+               private TypeNode next_end_old_type;
+               private ScanState state;
+
+               public OldScanStateMachine (EnsuresSubroutine<Label> ensuresSubroutine)
+               {
+                       this.subroutine = ensuresSubroutine;
+                       this.state = ScanState.OutsideOld;
+               }
+
+               #region Overrides of ILVisitorBase<Label,Local,Parameter,Method,Field,Type,Dummy,Dummy,int,bool>
+               public override bool DefaultVisit (Label pc, int index)
+               {
+                       if (this.state != ScanState.InsertingOld)
+                               return this.current_block.UsesOverriding;
+
+                       this.state = ScanState.OutsideOld;
+                       this.current_block.EndOldWithoutInstruction (this.subroutine.SubroutineFacade.MetaDataProvider.ManagedPointer (this.next_end_old_type));
+                       return true;
+               }
+               #endregion
+
+               #region Implementation of ICodeQuery<Label,Local,Parameter,Method,Field,Type,int,bool>
+               public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, int data)
+               {
+                       return Nop (pc, data);
+               }
+               #endregion
+
+               #region IAggregateVisitor<Label,int,bool> Members
+               public override bool Nop (Label pc, int data)
+               {
+                       return this.current_block.UsesOverriding;
+               }
+
+               public override bool BeginOld (Label pc, Label matchingEnd, int data)
+               {
+                       this.state = ScanState.InsideOld;
+                       return this.current_block.UsesOverriding;
+               }
+
+               public override bool EndOld (Label pc, Label matchingEnd, TypeNode type, Dummy dest, Dummy source, int data)
+               {
+                       this.state = ScanState.OutsideOld;
+                       return this.current_block.UsesOverriding;
+               }
+
+               public override bool LoadField (Label pc, Field field, Dummy dest, Dummy obj, int data)
+               {
+                       if (this.state != ScanState.InsertingOld)
+                               return this.current_block.UsesOverriding;
+
+                       this.state = ScanState.OutsideOld;
+                       this.current_block.EndOld (data, this.subroutine.SubroutineFacade.MetaDataProvider.FieldType (field));
+                       return false;
+               }
+
+               public override bool LoadFieldAddress (Label pc, Field field, Dummy dest, Dummy obj, int data)
+               {
+                       if (this.state == ScanState.InsertingOld)
+                               this.next_end_old_type = this.subroutine.SubroutineFacade.MetaDataProvider.FieldType (field);
+                       return this.current_block.UsesOverriding;
+               }
+
+               public override bool Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, int data)
+               {
+                       return false;
+               }
+               #endregion
+
+               public void HandlePotentialCallBlock (MethodCallBlock<Label> block, EnsuresBlock<Label> priorBlock)
+               {
+                       if (block == null || this.state != ScanState.InsertingOld)
+                               return;
+
+                       int count = this.subroutine.SubroutineFacade.MetaDataProvider.Parameters (block.CalledMethod).Count;
+                       if (!this.subroutine.SubroutineFacade.MetaDataProvider.IsStatic (block.CalledMethod))
+                               ++count;
+                       if (count > 1) {
+                               this.state = ScanState.OutsideOld;
+                               TypeNode mp = this.subroutine.SubroutineFacade.MetaDataProvider.ManagedPointer (this.next_end_old_type);
+                               priorBlock.EndOldWithoutInstruction (mp);
+                       } else {
+                               this.state = ScanState.InsertingOldAfterCall;
+                               this.next_end_old_type = this.subroutine.SubroutineFacade.MetaDataProvider.ReturnType (block.CalledMethod);
+                       }
+               }
+
+               public void StartBlock (EnsuresBlock<Label> block)
+               {
+                       if (!this.block_start_state.TryGetValue (block, out this.state)) {
+                               this.state = ScanState.OutsideOld;
+                               this.block_start_state.Add (block, this.state);
+                       }
+                       if (this.state == ScanState.InsertingOld)
+                               block.StartOverridingLabels ();
+                       if (this.state == ScanState.InsertingOldAfterCall) {
+                               block.StartOverridingLabels ();
+                               block.EndOldWithoutInstruction (this.next_end_old_type);
+                               this.state = ScanState.OutsideOld;
+                       }
+                       this.current_block = block;
+               }
+
+               public void SetStartState (CFGBlock succ)
+               {
+                       ScanState sstate;
+                       if (!this.block_start_state.TryGetValue (succ, out sstate))
+                               this.block_start_state.Add (succ, this.state);
+               }
+
+               #region Nested type: ScanState
+               private enum ScanState {
+                       OutsideOld,
+                       InsideOld,
+                       InsertingOld,
+                       InsertingOldAfterCall
+               }
+               #endregion
+                                               }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..1bb0c41
--- /dev/null
@@ -0,0 +1,85 @@
+// 
+// OldValueSubroutine.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+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;
+
+               public OldValueSubroutine (SubroutineFacade subroutineFacade, Method method,
+                                          SimpleSubroutineBuilder<Label> builder, Label startLabel)
+                       : base (subroutineFacade, method, builder, startLabel)
+               {
+               }
+
+               public override SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Old; }
+               }
+
+               public override int StackDelta
+               {
+                       get { return 1; }
+               }
+
+               public override bool IsOldValue
+               {
+                       get { return true; }
+               }
+
+               public override void Initialize ()
+               {
+               }
+
+               public void Commit (BlockWithLabels<Label> endOldBlock)
+               {
+                       this.end_old_block = endOldBlock;
+                       base.Commit ();
+               }
+
+               public void RegisterBeginBlock (BlockWithLabels<Label> beginOldBlock)
+               {
+                       this.begin_old_block = beginOldBlock;
+               }
+
+               public APC BeginOldAPC (LispList<Edge<CFGBlock, EdgeTag>> context)
+               {
+                       return new APC (this.begin_old_block, 0, context);
+               }
+
+               public APC EndOldAPC (LispList<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
new file mode 100644 (file)
index 0000000..18b3e62
--- /dev/null
@@ -0,0 +1,85 @@
+// 
+// RequiresSubroutine.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 Mono.CodeContracts.Static.AST;
+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>>
+       {
+               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,
+                                         Method method,
+                                         IImmutableSet<Subroutine> inherited)
+                       : base(subroutineFacade, method)
+               {
+                       AddSuccessor(Entry, EdgeTag.Entry, Exit);
+                       AddBaseRequires(Exit, inherited);
+                       Commit();
+               }
+
+               public RequiresSubroutine(SubroutineFacade subroutineFacade,
+                                         Method method,
+                                         SimpleSubroutineBuilder<Label> builder,
+                                         Label entryLabel,
+                                         IImmutableSet<Subroutine> inheritedRequires)
+                       : base(subroutineFacade, method, builder, entryLabel)
+               {
+                       AddBaseRequires(this.GetTargetBlock(entryLabel), inheritedRequires);
+               }
+
+               public override void Initialize()
+               {
+                       if (this.Builder == null)
+                               return;
+
+                       this.Builder.BuildBlocks(this.StartLabel, this);
+                       this.Commit();
+
+                       this.Builder = null;
+               }
+
+               private void AddBaseRequires(CFGBlock targetOfEntry, IImmutableSet<Subroutine> inherited)
+               {
+                       foreach (var subroutine in inherited.Elements)
+                               this.AddEdgeSubroutine(this.Entry, targetOfEntry, subroutine, EdgeTag.Inherited);
+               }
+
+               public bool Equals(RequiresSubroutine<Label> that)
+               {
+                       return this.Id == that.Id;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SimpleSubroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow.Subroutines/SimpleSubroutine.cs
new file mode 100644 (file)
index 0000000..58bd922
--- /dev/null
@@ -0,0 +1,58 @@
+// 
+// SimpleSubroutine.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 Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       class SimpleSubroutine<Label> : SubroutineBase<Label> {
+               private readonly int stack_delta;
+
+               public SimpleSubroutine (int stackDelta, SubroutineFacade subroutineFacade, 
+                       Label startLabel, SimpleSubroutineBuilder<Label> builder) 
+                       : base (subroutineFacade, startLabel, builder)
+               {
+                       this.stack_delta = stackDelta;
+                       builder.BuildBlocks (startLabel, this);
+                       Commit ();
+               }
+
+               public override int StackDelta
+               {
+                       get { return this.stack_delta; }
+               }
+
+               public override SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Simple; }
+               }
+
+               public override void Initialize ()
+               {
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..c7ad984
--- /dev/null
@@ -0,0 +1,782 @@
+// 
+// SubroutineBase.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.IO;
+using System.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       abstract class SubroutineBase<Label> : Subroutine, IGraph<CFGBlock, Dummy>, IStackInfo, IEdgeSubroutineAdaptor {
+               private const int UnusedBlockIndex = Int32.MaxValue - 1;
+               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 BlockWithLabels<Label> entry;
+               private readonly BlockWithLabels<Label> entry_after_requires;
+               private readonly BlockWithLabels<Label> exception_exit;
+               private readonly BlockWithLabels<Label> exit;
+
+               private readonly List<Edge<CFGBlock, EdgeTag>> successors = new List<Edge<CFGBlock, EdgeTag>> ();
+               protected int BlockIdGenerator;
+               protected Dictionary<Label, BlockWithLabels<Label>> LabelsThatStartBlocks = new Dictionary<Label, BlockWithLabels<Label>> ();
+
+               private CFGBlock[] blocks;
+               private DepthFirst.Visitor<CFGBlock, Dummy> edge_info;
+               private EdgeMap<EdgeTag> predecessor_edges;
+               private EdgeMap<EdgeTag> successor_edges;
+
+               protected SubroutineBase (SubroutineFacade subroutineFacade)
+               {
+                       this.SubroutineFacade = subroutineFacade;
+                       this.entry = new EntryBlock<Label> (this, ref this.BlockIdGenerator);
+                       this.exit = new EntryExitBlock<Label> (this, ref this.BlockIdGenerator);
+                       this.exception_exit = new CatchFilterEntryBlock<Label> (this, ref this.BlockIdGenerator);
+               }
+
+               protected SubroutineBase (SubroutineFacade SubroutineFacade,
+                                         Label startLabel, SubroutineBuilder<Label> builder)
+                       : this (SubroutineFacade)
+               {
+                       this.StartLabel = startLabel;
+                       Builder = builder;
+                       CodeProvider = builder.CodeProvider;
+                       this.entry_after_requires = GetTargetBlock (startLabel);
+
+                       AddSuccessor (this.entry, EdgeTag.Entry, this.entry_after_requires);
+               }
+
+               public override bool HasContextDependentStackDepth
+               {
+                       get { return true; }
+               }
+
+               public override bool HasReturnValue
+               {
+                       get { return false; }
+               }
+
+               public override int StackDelta
+               {
+                       get { return 0; }
+               }
+
+               protected SubroutineBuilder<Label> Builder { get; set; }
+
+               public override DepthFirst.Visitor<CFGBlock, Dummy> EdgeInfo
+               {
+                       get { return this.edge_info; }
+               }
+
+               public ICodeProvider<Label> CodeProvider { get; private set; }
+
+               public override int BlockCount
+               {
+                       get { return this.blocks.Length; }
+               }
+
+               public override IEnumerable<CFGBlock> Blocks
+               {
+                       get { return this.blocks; }
+               }
+
+               public override string Name
+               {
+                       get { return "SR" + Id; }
+               }
+
+               public override EdgeMap<EdgeTag> SuccessorEdges
+               {
+                       get { return this.successor_edges; }
+               }
+
+               public override EdgeMap<EdgeTag> PredecessorEdges
+               {
+                       get
+                       {
+                               if (this.predecessor_edges == null)
+                                       this.predecessor_edges = this.successor_edges.Reverse ();
+                               return this.predecessor_edges;
+                       }
+               }
+
+               #region Main Blocks
+               public override CFGBlock Entry
+               {
+                       get { return this.entry; }
+               }
+
+               public override CFGBlock EntryAfterRequires
+               {
+                       get
+                       {
+                               if (this.entry_after_requires != null)
+                                       return this.entry_after_requires;
+                               return Entry;
+                       }
+               }
+
+               public override CFGBlock Exit
+               {
+                       get { return this.exit; }
+               }
+
+               public override CFGBlock ExceptionExit
+               {
+                       get { return this.exception_exit; }
+               }
+               #endregion
+
+               #region IEdgeSubroutineAdaptor Members
+               public LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock from, CFGBlock to, LispList<Edge<CFGBlock, EdgeTag>> context)
+               {
+                       LispList<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));
+                       return list;
+               }
+               #endregion
+
+               #region IGraph<CFGBlock,Dummy> Members
+               public IEnumerable<CFGBlock> Nodes
+               {
+                       get { return this.blocks; }
+               }
+
+               public virtual IEnumerable<Pair<Dummy, CFGBlock>> Successors (CFGBlock node)
+               {
+                       foreach (var pair in this.successor_edges [node])
+                               yield return new Pair<Dummy, CFGBlock> (Dummy.Value, pair.Value);
+
+                       if (node != this.exception_exit)
+                               yield return new Pair<Dummy, CFGBlock> (Dummy.Value, this.exception_exit);
+               }
+               #endregion
+
+               #region IStackInfo Members
+               bool IStackInfo.IsCallOnThis (APC apc)
+               {
+                       return false;
+               }
+               #endregion
+
+               public override IEnumerable<CFGBlock> SuccessorBlocks (CFGBlock block)
+               {
+                       return SuccessorEdges [block].Select (it => it.Value);
+               }
+
+               public override bool HasSingleSuccessor (APC point, out APC ifFound)
+               {
+                       if (point.Index < point.Block.Count) {
+                               ifFound = new APC (point.Block, point.Index + 1, point.SubroutineContext);
+                               return true;
+                       }
+
+                       if (IsSubroutineEnd (point.Block)) {
+                               if (point.SubroutineContext == null) {
+                                       ifFound = APC.Dummy;
+                                       return false;
+                               }
+
+                               ifFound = ComputeSubroutineContinuation (point);
+                               return true;
+                       }
+
+                       BlockWithLabels<Label> onlyOne = null;
+                       foreach (BlockWithLabels<Label> successor in point.Block.Subroutine.SuccessorBlocks (point.Block)) {
+                               if (onlyOne == null)
+                                       onlyOne = successor;
+                               else {
+                                       ifFound = APC.Dummy;
+                                       return false;
+                               }
+                       }
+
+                       if (onlyOne != null) {
+                               ifFound = ComputeTargetFinallyContext (point, onlyOne);
+                               return true;
+                       }
+
+                       ifFound = APC.Dummy;
+                       return false;
+               }
+
+               public override bool HasSinglePredecessor (APC point, out APC ifFound)
+               {
+                       if (point.Index > 0) {
+                               ifFound = new APC (point.Block, point.Index - 1, point.SubroutineContext);
+                               return true;
+                       }
+
+                       if (IsSubroutineStart (point.Block)) {
+                               if (point.SubroutineContext == null) {
+                                       ifFound = APC.Dummy;
+                                       return false;
+                               }
+
+                               bool hasSinglePredecessor;
+                               ifFound = ComputeSubroutinePreContinuation (point, out hasSinglePredecessor);
+                               return hasSinglePredecessor;
+                       }
+
+
+                       CFGBlock onlyOne = null;
+                       foreach (CFGBlock predecessor in point.Block.Subroutine.PredecessorBlocks (point.Block)) {
+                               if (onlyOne != null) {
+                                       ifFound = APC.Dummy;
+                                       return false;
+                               }
+                               onlyOne = predecessor;
+                       }
+                       if (onlyOne == null) {
+                               ifFound = APC.Dummy;
+                               return false;
+                       }
+
+                       LispList<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (onlyOne, point.Block, point.SubroutineContext);
+                       if (list.IsEmpty ()) {
+                               ifFound = APC.ForEnd (onlyOne, point.SubroutineContext);
+                               return true;
+                       }
+
+                       var edge = new Edge<CFGBlock, EdgeTag> (onlyOne, point.Block, list.Head.Key);
+                       Subroutine sub = list.Head.Value;
+                       ifFound = APC.ForEnd (sub.Exit, point.SubroutineContext.Cons (edge));
+                       return true;
+               }
+
+               private APC ComputeSubroutinePreContinuation (APC point, out bool hasSinglePredecessor)
+               {
+                       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);
+                       while (flist.Head.Value != this)
+                               flist = flist.Tail;
+                       if (flist.Tail.IsEmpty ()) {
+                               if (isExceptionHandlerEdge && head.From.Count > 1) {
+                                       hasSinglePredecessor = false;
+                                       return APC.Dummy;
+                               }
+
+                               hasSinglePredecessor = true;
+                               return APC.ForEnd (head.From, tail);
+                       }
+                       Pair<EdgeTag, Subroutine> first = flist.Tail.Head;
+                       Subroutine sub = first.Value;
+                       hasSinglePredecessor = true;
+
+                       return APC.ForEnd (sub.Exit, point.SubroutineContext.Cons (new Edge<CFGBlock, EdgeTag> (head.From, head.To, first.Key)));
+               }
+
+               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);
+                       if (outerToInner.Head.Value == this)
+                               return new APC (head.To, 0, tail);
+
+                       while (outerToInner.Tail.Head.Value != this)
+                               outerToInner = outerToInner.Tail;
+
+                       return new APC (outerToInner.Head.Value.Entry, 0, tail.Cons (new Edge<CFGBlock, EdgeTag> (head.From, head.To, outerToInner.Head.Key)));
+               }
+
+               public override IEnumerable<CFGBlock> PredecessorBlocks (CFGBlock block)
+               {
+                       return PredecessorEdges [block].Select (it => it.Value);
+               }
+
+               public override bool IsJoinPoint (CFGBlock block)
+               {
+                       if (IsCatchFilterHeader (block) || IsSubroutineStart (block) || IsSubroutineEnd (block))
+                               return true;
+
+                       return PredecessorEdges [block].Count > 1;
+               }
+
+               public override bool IsSubroutineEnd (CFGBlock block)
+               {
+                       return block == this.exit || block == this.exception_exit;
+               }
+
+               public override bool IsSubroutineStart (CFGBlock block)
+               {
+                       return block == this.entry;
+               }
+
+               public override bool IsSplitPoint (CFGBlock block)
+               {
+                       if (IsSubroutineStart (block) || IsSubroutineEnd (block))
+                               return true;
+
+                       return SuccessorEdges [block].Count > 1;
+               }
+
+               public override bool IsCatchFilterHeader (CFGBlock block)
+               {
+                       return block is CatchFilterEntryBlock<Label>;
+               }
+
+               public void AddSuccessor (CFGBlock from, EdgeTag tag, CFGBlock to)
+               {
+                       AddNormalControlFlowEdge (this.successors, from, tag, to);
+               }
+
+               private void AddNormalControlFlowEdge (List<Edge<CFGBlock, EdgeTag>> succs, CFGBlock from, EdgeTag tag, CFGBlock to)
+               {
+                       succs.Add (new Edge<CFGBlock, EdgeTag> (from, to, tag));
+               }
+
+               public virtual void AddReturnBlock (BlockWithLabels<Label> block)
+               {
+               }
+
+               public BlockWithLabels<Label> GetTargetBlock (Label label)
+               {
+                       return GetBlock (label);
+               }
+
+               public BlockWithLabels<Label> GetBlock (Label label)
+               {
+                       IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider;
+
+                       BlockWithLabels<Label> block;
+                       if (!this.LabelsThatStartBlocks.TryGetValue (label, out block)) {
+                               Pair<Method, bool> methodVirtualPair;
+                               Method constructor;
+
+                               if (Builder == null)
+                                       throw new InvalidOperationException ("Builder must be not null");
+
+                               if (Builder.IsMethodCallSite (label, out methodVirtualPair)) {
+                                       int parametersCount = metadataDecoder.Parameters (methodVirtualPair.Key).Count;
+                                       block = new MethodCallBlock<Label> (methodVirtualPair.Key, this, ref this.BlockIdGenerator, parametersCount, methodVirtualPair.Value);
+                               } else if (Builder.IsNewObjSite (label, out constructor)) {
+                                       int parametersCount = metadataDecoder.Parameters (constructor).Count;
+                                       block = new NewObjCallBlock<Label> (constructor, parametersCount, this, ref this.BlockIdGenerator);
+                               } else
+                                       block = NewBlock ();
+
+                               if (Builder.IsTargetLabel (label))
+                                       this.LabelsThatStartBlocks.Add (label, block);
+                       }
+                       return block;
+               }
+
+               public virtual BlockWithLabels<Label> NewBlock ()
+               {
+                       return new BlockWithLabels<Label> (this, ref this.BlockIdGenerator);
+               }
+
+               public AssumeBlock<Label> NewAssumeBlock (Label pc, EdgeTag tag)
+               {
+                       return new AssumeBlock<Label> (this, pc, tag, ref this.BlockIdGenerator);
+               }
+
+               public override sealed void AddEdgeSubroutine (CFGBlock from, CFGBlock to, Subroutine subroutine, EdgeTag tag)
+               {
+                       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);
+
+                       this.edge_subroutines.TryGetValue (key, out list);
+                       this.edge_subroutines [key] = list.Cons (item);
+               }
+
+               public override IEnumerable<APC> Successors (APC pc)
+               {
+                       APC singleNext;
+                       if (HasSingleSuccessor (pc, out singleNext))
+                               yield return singleNext;
+                       else {
+                               foreach (CFGBlock block in pc.Block.Subroutine.SuccessorBlocks (pc.Block))
+                                       yield return pc.Block.Subroutine.ComputeTargetFinallyContext (pc, block);
+                       }
+               }
+
+               public override IEnumerable<APC> Predecessors (APC pc)
+               {
+                       if (pc.Index > 0)
+                               yield return new APC (pc.Block, pc.Index - 1, pc.SubroutineContext);
+
+                       else if (IsSubroutineStart (pc.Block)) {
+                               if (!pc.SubroutineContext.IsEmpty ()) {
+                                       foreach (APC apc in ComputeSubroutinePreContinuation (pc))
+                                               yield return apc;
+                               }
+                       } else {
+                               foreach (CFGBlock block in pc.Block.Subroutine.PredecessorBlocks (pc.Block)) {
+                                       LispList<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (block, pc.Block, pc.SubroutineContext);
+                                       if (diffs.IsEmpty ())
+                                               yield return APC.ForEnd (block, pc.SubroutineContext);
+                                       else {
+                                               Subroutine sub = diffs.Head.Value;
+                                               var edge = new Edge<CFGBlock, EdgeTag> (block, pc.Block, diffs.Head.Key);
+                                               yield return APC.ForEnd (sub.Exit, pc.SubroutineContext.Cons (edge));
+                                       }
+                               }
+                       }
+               }
+
+               private IEnumerable<APC> ComputeSubroutinePreContinuation (APC point)
+               {
+                       Edge<CFGBlock, EdgeTag> edge = point.SubroutineContext.Head;
+                       LispList<Edge<CFGBlock, EdgeTag>> tail = point.SubroutineContext.Tail;
+
+                       bool isHandlerEdge;
+                       LispList<Pair<EdgeTag, Subroutine>> diffs = EdgeSubroutinesOuterToInner (edge.From, edge.To, out isHandlerEdge, tail);
+                       while (diffs.Head.Value != this)
+                               diffs = diffs.Tail;
+
+                       if (diffs.Tail == null) {
+                               if (isHandlerEdge) {
+                                       for (int i = 0; i < edge.From.Count; i++)
+                                               yield return new APC (edge.From, i, tail);
+                               } else
+                                       yield return APC.ForEnd (edge.From, tail);
+                       } else {
+                               Pair<EdgeTag, Subroutine> first = diffs.Tail.Head;
+                               Subroutine nextSubroutine = first.Value;
+                               yield return APC.ForEnd (nextSubroutine.Exit, point.SubroutineContext.Cons (new Edge<CFGBlock, EdgeTag> (edge.From, edge.To, first.Key)));
+                       }
+               }
+
+               public override APC ComputeTargetFinallyContext (APC pc, CFGBlock succ)
+               {
+                       LispList<Pair<EdgeTag, Subroutine>> list = EdgeSubroutinesOuterToInner (pc.Block, succ, pc.SubroutineContext);
+                       if (list.IsEmpty ())
+                               return new APC (succ, 0, pc.SubroutineContext);
+
+                       Pair<EdgeTag, Subroutine> last = list.Last ();
+                       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)
+               {
+                       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)
+               {
+                       if (from.Subroutine != this)
+                               return from.Subroutine.EdgeSubroutinesOuterToInner (from, succ, out isExceptionHandlerEdge, context);
+
+                       isExceptionHandlerEdge = IsCatchFilterHeader (succ);
+                       return GetOrdinaryEdgeSubroutines (from, succ, context);
+               }
+
+               public override LispList<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock from, CFGBlock to, LispList<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);
+                               if (apc.InsideContract) {
+                                       if (context != null && !list.IsEmpty ()) {
+                                               Method calledMethod;
+                                               bool isNewObj;
+                                               bool isVirtual;
+                                               if (@from.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual) && isVirtual && ((IStackInfo) this).IsCallOnThis (new APC (@from, 0, null))) {
+                                                       TypeNode type = metadataDecoder.DeclaringType (calledMethod);
+                                                       do {
+                                                               if (context.Head.Tag.Is (EdgeTag.InheritedMask) || context.Head.Tag.Is (EdgeTag.ExtraMask) || context.Head.Tag.Is (EdgeTag.OldMask))
+                                                                       context = context.Tail;
+                                                               else {
+                                                                       Method calledMethod2;
+                                                                       bool isNewObj2;
+                                                                       bool isVirtual2;
+                                                                       if (context.Head.Tag.Is (EdgeTag.AfterMask) && context.Head.From.IsMethodCallBlock (out calledMethod2, out isNewObj2, out isVirtual2)) {
+                                                                               TypeNode sub = metadataDecoder.DeclaringType (calledMethod2);
+                                                                               if (metadataDecoder.DerivesFrom (sub, type))
+                                                                                       type = sub;
+                                                                               if (!DecoratorHelper.Dispatch<IStackInfo> (this).IsCallOnThis (new APC (context.Head.From, 0, null)))
+                                                                                       break;
+                                                                       } else if (context.Head.Tag.Is (EdgeTag.BeforeMask) && context.Head.To.IsMethodCallBlock (out calledMethod2, out isNewObj2, out isVirtual2)) {
+                                                                               TypeNode sub = metadataDecoder.DeclaringType (calledMethod2);
+                                                                               if (metadataDecoder.DerivesFrom (sub, type))
+                                                                                       type = sub;
+                                                                               if (!DecoratorHelper.Dispatch<IStackInfo> (this).IsCallOnThis (new APC (context.Head.To, 0, null)))
+                                                                                       break;
+                                                                       } else if (context.Head.Tag == EdgeTag.Exit) {
+                                                                               var methodInfo = context.Head.From.Subroutine as IMethodInfo;
+                                                                               if (methodInfo != null) {
+                                                                                       TypeNode sub = metadataDecoder.DeclaringType (methodInfo.Method);
+                                                                                       if (metadataDecoder.DerivesFrom (sub, type))
+                                                                                               type = sub;
+                                                                               }
+                                                                               break;
+                                                                       } else {
+                                                                               if (context.Head.Tag != EdgeTag.Entry)
+                                                                                       return list;
+                                                                               var methodInfo = context.Head.From.Subroutine as IMethodInfo;
+                                                                               if (methodInfo != null) {
+                                                                                       TypeNode sub = metadataDecoder.DeclaringType (methodInfo.Method);
+                                                                                       if (metadataDecoder.DerivesFrom (sub, type))
+                                                                                               type = sub;
+                                                                               }
+                                                                               break;
+                                                                       }
+                                                                       context = context.Tail;
+                                                               }
+                                                       } while (!context.IsEmpty ());
+                                                       Method implementingMethod;
+                                                       if (!metadataDecoder.Equal (type, metadataDecoder.DeclaringType (calledMethod)) &&
+                                                           metadataDecoder.TryGetImplementingMethod (type, calledMethod, out implementingMethod))
+                                                               list = SpecializedEnsures (list, this.SubroutineFacade.GetEnsures (calledMethod), this.SubroutineFacade.GetEnsures (implementingMethod));
+                                               }
+                                       }
+                               } else {
+                                       Method calledMethod;
+                                       bool isNewObj;
+                                       bool isVirtual;
+                                       if (@from.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual)) {
+                                               if (DecoratorHelper.Dispatch<IStackInfo> (this).IsCallOnThis (new APC (@from, 0, null))) {
+                                                       var methodInfo = @from.Subroutine as IMethodInfo;
+                                                       if (methodInfo != null) {
+                                                               TypeNode bestType = metadataDecoder.DeclaringType (methodInfo.Method);
+                                                               Method implementingMethod;
+                                                               if (isVirtual && metadataDecoder.TryGetImplementingMethod (bestType, calledMethod, out implementingMethod))
+                                                                       list = SpecializedEnsures (list, this.SubroutineFacade.GetEnsures (calledMethod), this.SubroutineFacade.GetEnsures (implementingMethod));
+                                                               list = InsertInvariant (@from, list, calledMethod, ref bestType, context);
+                                                       }
+                                               }
+                                       }
+                               }
+                               return list;
+                       } finally {
+                               DecoratorHelper.Pop ();
+                       }
+               }
+
+               private LispList<Pair<EdgeTag, Subroutine>> InsertInvariant (CFGBlock from, LispList<Pair<EdgeTag, Subroutine>> list,
+                                                                            Method calledMethod, ref TypeNode type,
+                                                                            LispList<Edge<CFGBlock, EdgeTag>> context)
+               {
+                       IMetaDataProvider metadataDecoder = this.SubroutineFacade.MetaDataProvider;
+
+                       Property property;
+                       if (metadataDecoder.IsPropertySetter (calledMethod, out property)
+                           && (metadataDecoder.IsAutoPropertyMember (calledMethod) || WithinConstructor (from, context)))
+                               return list;
+
+                       if (metadataDecoder.IsConstructor (calledMethod))
+                               type = metadataDecoder.DeclaringType (calledMethod);
+
+                       Subroutine invariant = this.SubroutineFacade.GetInvariant (type);
+                       if (invariant != null) {
+                               var methodCallBlock = from as MethodCallBlock<Label>;
+                               if (methodCallBlock != null) {
+                                       EdgeTag first = methodCallBlock.IsNewObj ? EdgeTag.AfterNewObj : EdgeTag.AfterCall;
+                                       return list.Cons (new Pair<EdgeTag, Subroutine> (first, invariant));
+                               }
+                       }
+
+                       return list;
+               }
+
+               private bool WithinConstructor (CFGBlock current, LispList<Edge<CFGBlock, EdgeTag>> context)
+               {
+                       return new APC (current, 0, context).InsideConstructor;
+               }
+
+               private LispList<Pair<EdgeTag, Subroutine>> SpecializedEnsures (LispList<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)
+               {
+                       return (candidate) => {
+                               Subroutine sub = candidate.Value;
+                               if (!sub.IsContract)
+                                       return true;
+                               if (sub == @from.Subroutine)
+                                       return false;
+                               if (context.Any (ctx => sub == ctx.From.Subroutine))
+                                       return false;
+                               return true;
+                              };
+               }
+
+               public abstract override void Initialize ();
+
+               public virtual void Commit ()
+               {
+                       PostProcessBlocks ();
+               }
+
+               protected void PostProcessBlocks ()
+               {
+                       var blockStack = new Stack<CFGBlock> ();
+                       this.successor_edges = new EdgeMap<EdgeTag> (this.successors);
+                       this.edge_info = new DepthFirst.Visitor<CFGBlock, Dummy> (this, null, (block) => blockStack.Push (block), null);
+                       this.edge_info.VisitSubGraphNonRecursive (this.exception_exit);
+                       this.edge_info.VisitSubGraphNonRecursive (this.exit);
+                       this.edge_info.VisitSubGraphNonRecursive (this.entry);
+
+                       foreach (var successorEdge in this.successor_edges) {
+                               int idGen = UnusedBlockIndex;
+                               successorEdge.From.Renumber (ref idGen);
+                       }
+                       int idGen1 = 0;
+                       foreach (CFGBlock cfgBlock in blockStack)
+                               cfgBlock.Renumber (ref idGen1);
+
+                       SuccessorEdges.Filter ((e) => e.From.Index != UnusedBlockIndex);
+                       this.predecessor_edges = this.successor_edges.Reverse ();
+                       int finishTime = 0;
+                       var visitor = new DepthFirst.Visitor<CFGBlock, EdgeTag> (this.predecessor_edges, null, block => block.ReversePostOrderIndex = finishTime++, null);
+                       visitor.VisitSubGraphNonRecursive (this.exit);
+                       foreach (CFGBlock node in blockStack)
+                               visitor.VisitSubGraphNonRecursive (node);
+
+                       SuccessorEdges.Resort ();
+                       this.blocks = blockStack.ToArray ();
+                       this.LabelsThatStartBlocks = null;
+                       Builder = null;
+               }
+
+               public override IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen)
+               {
+                       foreach (var list in this.edge_subroutines.Values) {
+                               foreach (var pair in list.AsEnumerable ()) {
+                                       Subroutine sub = pair.Value;
+                                       if (!alreadySeen.Contains (sub.Id)) {
+                                               alreadySeen.Add (sub.Id);
+                                               yield return sub;
+                                       }
+                               }
+                       }
+               }
+
+               public override IEnumerable<CFGBlock> ExceptionHandlers<Data, TType> (CFGBlock block, Subroutine innerSubroutine,
+                                                                                     Data data, IHandlerFilter<Data> handlerPredicate)
+               {
+                       yield return this.exception_exit;
+               }
+
+
+               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)
+               {
+                       var element = new Pair<Subroutine, LispList<Edge<CFGBlock, EdgeTag>>> (this, context);
+                       if (printed.Contains (element))
+                               return;
+                       printed.Add (element);
+                       var subs = new HashSet<Subroutine> ();
+                       var methodInfo = this as IMethodInfo;
+                       string method = (methodInfo != null) ? String.Format ("({0})", this.SubroutineFacade.MetaDataProvider.FullName (methodInfo.Method)) : null;
+
+                       tw.WriteLine ("Subroutine SR{0} {1} {2}", Id, Kind, method);
+                       tw.WriteLine ("-------------");
+                       foreach (BlockWithLabels<Label> block in this.blocks) {
+                               tw.Write ("Block {0} ({1})", block.Index, block.ReversePostOrderIndex);
+                               if (this.edge_info.DepthFirstInfo (block).TargetOfBackEdge)
+                                       tw.WriteLine (" (target of backedge)");
+                               else if (IsJoinPoint (block))
+                                       tw.WriteLine (" (join point)");
+                               else
+                                       tw.WriteLine ();
+
+                               tw.Write ("  Predecessors: ");
+                               foreach (var edge in block.Subroutine.PredecessorEdges [block])
+                                       tw.Write ("({0}, {1}) ", edge.Key, edge.Value.Index);
+                               tw.WriteLine ();
+                               PrintHandlers (tw, block);
+
+                               tw.WriteLine ("  Code:");
+                               foreach (APC apc in block.APCs ())
+                                       printer (apc, "    ", tw);
+
+                               tw.Write ("  Successors: ");
+                               foreach (var edge in block.Subroutine.SuccessorEdges [block]) {
+                                       tw.Write ("({0}, {1}", edge.Key, edge.Value.Index);
+                                       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) {
+                                               subs.Add (list.Head.Value);
+                                               tw.Write (" SR{0}({1})", list.Head.Value.Id, list.Head.Key);
+                                       }
+                                       tw.Write (") ");
+                               }
+                               tw.WriteLine ();
+                       }
+                       PrintReferencedSubroutines (tw, subs, printer, contextLookup, context, printed);
+               }
+
+               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)
+               {
+                       foreach (Subroutine subroutine in subs) {
+                               if (contextLookup == null)
+                                       subroutine.Print (tw, printer, contextLookup, context, printed);
+                               else {
+                                       foreach (var ctx in contextLookup (subroutine.Entry))
+                                               subroutine.Print (tw, printer, contextLookup, ctx, printed);
+                               }
+                       }
+               }
+
+               protected virtual void PrintHandlers (TextWriter tw, BlockWithLabels<Label> block)
+               {
+                       tw.Write ("  Handlers: ");
+                       if (block != ExceptionExit)
+                               tw.Write ("{0} ", ExceptionExit.Index);
+                       tw.WriteLine ();
+               }
+
+               public int GetILOffset (Label label)
+               {
+                       return CodeProvider.GetILOffset (label);
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..364a305
--- /dev/null
@@ -0,0 +1,130 @@
+// 
+// SubroutineFacade.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       class SubroutineFacade : IMethodCodeConsumer<Dummy, Subroutine> {
+               public readonly IContractProvider ContractProvider;
+               public readonly IMetaDataProvider MetaDataProvider;
+
+//             private readonly EnsuresFactory ensures_factory;
+               private readonly Dictionary<Method, ICFG> method_cache = new Dictionary<Method, ICFG> ();
+               private readonly RequiresFactory requires_factory;
+
+               public SubroutineFacade (IMetaDataProvider metaDataProvider,
+                                        IContractProvider contractProvider)
+               {
+                       this.MetaDataProvider = metaDataProvider;
+                       this.ContractProvider = contractProvider;
+                       this.requires_factory = new RequiresFactory (this);
+//                     this.ensures_factory = new EnsuresFactory (this);
+               }
+
+               #region IMethodCodeConsumer<Dummy,Subroutine> Members
+               Subroutine IMethodCodeConsumer<Dummy, Subroutine>.Accept<Label, Handler> (
+                       IMethodCodeProvider<Label, Handler> codeProvider,
+                       Label entry,
+                       Method method,
+                       Dummy data)
+               {
+                       var builder = new SubroutineWithHandlersBuilder<Label, Handler> (codeProvider, this, method, entry);
+                       return new MethodSubroutine<Label, Handler> (this, method, entry, builder);
+               }
+               #endregion
+
+               public Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+                       where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result>
+               {
+                       var block = pc.Block as BlockBase;
+                       if (block != null)
+                               return block.ForwardDecode<Data, Result, Visitor> (pc, visitor, data);
+
+                       return visitor.Nop (pc, data);
+               }
+
+               public Subroutine GetRequires (Method method)
+               {
+                       method = this.MetaDataProvider.Unspecialized (method);
+                       return this.requires_factory.Get (method);
+               }
+
+               public Subroutine GetEnsures (Method method)
+               {
+                       return null;
+                       //todo: implement handling this in MethodSubroutine and uncomment lines below
+
+//                     method = this.MetaDataProvider.Unspecialized (method);
+//                     return this.ensures_factory.Get (method);
+               }
+
+               public Subroutine GetInvariant (TypeNode type)
+               {
+                       //todo: implement this
+                       return null;
+               }
+
+               public ICFG GetControlFlowGraph (Method method)
+               {
+                       if (this.method_cache.ContainsKey (method))
+                               return this.method_cache [method];
+
+                       if (!this.MetaDataProvider.HasBody (method))
+                               throw new InvalidOperationException ("Method has no body");
+
+                       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
+
+                       return new Method[0];
+               }
+
+               public IEnumerable<Field> GetModifies (Method method)
+               {
+                       //todo: implement this
+                       return new Field[0];
+               }
+       }
+}
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
new file mode 100644 (file)
index 0000000..d41bd34
--- /dev/null
@@ -0,0 +1,208 @@
+// 
+// SubroutineWithHandlers.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.IO;
+using System.Linq;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow.Blocks;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
+       abstract class SubroutineWithHandlers<Label, Handler> : SubroutineBase<Label> {
+               protected readonly Dictionary<Handler, BlockWithLabels<Label>> CatchFilterHeaders = new Dictionary<Handler, BlockWithLabels<Label>> ();
+
+               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;
+
+               protected SubroutineWithHandlers (SubroutineFacade subroutineFacade)
+                       : base (subroutineFacade)
+               {
+               }
+
+               protected SubroutineWithHandlers (SubroutineFacade subroutineFacade,
+                                                 Label startLabel,
+                                                 SubroutineBuilder<Label> builder)
+                       : base (subroutineFacade, startLabel, builder)
+               {
+               }
+
+               protected new IMethodCodeProvider<Label, Handler> CodeProvider
+               {
+                       get { return (IMethodCodeProvider<Label, Handler>) base.CodeProvider; }
+               }
+
+               private bool IsFault (Handler handler)
+               {
+                       return CodeProvider.IsFaultHandler (handler);
+               }
+
+               private LispList<Handler> ProtectingHandlerList (CFGBlock block)
+               {
+                       LispList<Handler> list;
+                       this.ProtectingHandlers.TryGetValue (block, out list);
+                       return list;
+               }
+
+               public BlockWithLabels<Label> CreateCatchFilterHeader (Handler handler, Label label)
+               {
+                       BlockWithLabels<Label> block;
+                       if (!this.LabelsThatStartBlocks.TryGetValue (label, out block)) {
+                               block = new CatchFilterEntryBlock<Label> (this, ref this.BlockIdGenerator);
+
+                               this.CatchFilterHeaders.Add (handler, block);
+                               this.LabelsThatStartBlocks.Add (label, block);
+                               if (CodeProvider.IsFilterHandler (handler)) {
+                                       BlockWithLabels<Label> targetBlock = GetTargetBlock (CodeProvider.FilterExpressionStart (handler));
+                                       this.FilterCodeBlocks.Add (handler, targetBlock);
+                               }
+                       }
+                       return block;
+               }
+
+               public override IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen)
+               {
+                       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)
+               {
+                       if (current.Subroutine != this)
+                               return current.Subroutine.EdgeSubroutinesOuterToInner (current, succ, out isExceptionHandlerEdge, context);
+
+                       LispList<Handler> l1 = ProtectingHandlerList (current);
+                       LispList<Handler> l2 = ProtectingHandlerList (succ);
+                       isExceptionHandlerEdge = IsCatchFilterHeader (succ);
+
+                       LispList<Pair<EdgeTag, Subroutine>> result = GetOrdinaryEdgeSubroutines (current, succ, context);
+
+                       while (l1 != l2) {
+                               if (l1.Length () >= l2.Length ()) {
+                                       Handler head = l1.Head;
+                                       if (IsFaultOrFinally (head) && (!IsFault (head) || isExceptionHandlerEdge))
+                                               result = result.Cons (new Pair<EdgeTag, Subroutine> (EdgeTag.Finally, this.FaultFinallySubroutines [head]));
+                                       l1 = l1.Tail;
+                               } else
+                                       l2 = l2.Tail;
+                       }
+
+                       return result;
+               }
+
+               private bool IsFaultOrFinally (Handler handler)
+               {
+                       return CodeProvider.IsFaultHandler (handler) || CodeProvider.IsFinallyHandler (handler);
+               }
+
+               public override IEnumerable<Pair<Dummy, CFGBlock>> Successors (CFGBlock node)
+               {
+                       foreach (var pair in SuccessorEdges [node])
+                               yield return new Pair<Dummy, CFGBlock> (Dummy.Value, pair.Value);
+
+                       foreach (Handler handler in ProtectingHandlerList (node).AsEnumerable ()) {
+                               if (!IsFaultOrFinally (handler))
+                                       yield return new Pair<Dummy, CFGBlock> (Dummy.Value, this.CatchFilterHeaders [handler]);
+                       }
+                       if (node != ExceptionExit)
+                               yield return new Pair<Dummy, CFGBlock> (Dummy.Value, ExceptionExit);
+               }
+
+               public override IEnumerable<CFGBlock> ExceptionHandlers<Data, TType> (CFGBlock block, Subroutine innerSubroutine,
+                                                                                     Data data, IHandlerFilter<Data> handlerPredicate)
+               {
+                       IHandlerFilter<Data> handleFilter = handlerPredicate;
+                       LispList<Handler> protectingHandlers = ProtectingHandlerList (block);
+                       if (innerSubroutine != null && innerSubroutine.IsFaultFinally) {
+                               for (; protectingHandlers != null; protectingHandlers = protectingHandlers.Tail) {
+                                       if (IsFaultOrFinally (protectingHandlers.Head) && this.FaultFinallySubroutines [protectingHandlers.Head] == innerSubroutine) {
+                                               protectingHandlers = protectingHandlers.Tail;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       for (; protectingHandlers != null; protectingHandlers = protectingHandlers.Tail) {
+                               Handler handler = protectingHandlers.Head;
+                               if (!IsFaultOrFinally (handler)) {
+                                       if (handleFilter != null) {
+                                               bool stopPropagation;
+                                               if (CodeProvider.IsCatchHandler (handler)) {
+                                                       if (handleFilter.Catch (data, CodeProvider.CatchType (handler), out stopPropagation))
+                                                               yield return this.CatchFilterHeaders [handler];
+                                               } else if (handleFilter.Filter (data, new APC (this.FilterCodeBlocks [handler], 0, null), out stopPropagation))
+                                                       yield return this.CatchFilterHeaders [handler];
+                                               if (stopPropagation)
+                                                       yield break;
+                                       } else
+                                               yield return this.CatchFilterHeaders [handler];
+
+                                       if (CodeProvider.IsCatchAllHandler (handler))
+                                               yield break;
+                               }
+                       }
+                       yield return ExceptionExit;
+               }
+
+               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)
+               {
+                       foreach (Subroutine sub in this.FaultFinallySubroutines.Values) {
+                               if (contextLookup == null)
+                                       sub.Print (tw, printer, contextLookup, context, printed);
+                               else {
+                                       foreach (var ctx in contextLookup (sub.Entry))
+                                               sub.Print (tw, printer, contextLookup, ctx, printed);
+                               }
+                       }
+
+                       base.PrintReferencedSubroutines (tw, subs, printer, contextLookup, context, printed);
+               }
+
+               protected override void PrintHandlers (TextWriter tw, BlockWithLabels<Label> block)
+               {
+                       tw.Write ("  Handlers: ");
+                       foreach (Handler handler in ProtectingHandlerList (block).AsEnumerable ()) {
+                               if (IsFaultOrFinally (handler))
+                                       tw.Write ("SR{0} ", this.FaultFinallySubroutines [handler].Id);
+                               else
+                                       tw.Write ("{0} ", this.CatchFilterHeaders [handler].Index);
+                       }
+                       if (block != ExceptionExit)
+                               tw.Write ("{0} ", ExceptionExit.Index);
+                       tw.WriteLine ();
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APC.cs
new file mode 100644 (file)
index 0000000..c323356
--- /dev/null
@@ -0,0 +1,289 @@
+// 
+// APC.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;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       struct APC : IEquatable<APC> {
+               public static readonly APC Dummy = new APC (null, 0, null);
+
+               public readonly CFGBlock Block;
+               public readonly int Index;
+               public readonly LispList<Edge<CFGBlock, EdgeTag>> SubroutineContext;
+
+               public APC (CFGBlock block, int index, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext)
+               {
+                       this.Block = block;
+                       this.Index = index;
+                       this.SubroutineContext = subroutineContext;
+               }
+
+               public IEnumerable<APC> Successors
+               {
+                       get { return this.Block.Subroutine.Successors (this); }
+               }
+
+               public bool InsideContract
+               {
+                       get
+                       {
+                               Subroutine sub = this.Block.Subroutine;
+                               return sub.IsContract || sub.IsOldValue;
+                       }
+               }
+
+               public bool InsideConstructor
+               {
+                       get
+                       {
+                               LispList<Edge<CFGBlock, EdgeTag>> ctx = this.SubroutineContext;
+                               CFGBlock block = this.Block;
+                               while (block != null) {
+                                       Subroutine subroutine = block.Subroutine;
+                                       if (subroutine.IsConstructor)
+                                               return true;
+                                       if (subroutine.IsMethod)
+                                               return false;
+                                       if (ctx != null) {
+                                               block = ctx.Head.From;
+                                               ctx = ctx.Tail;
+                                       } else
+                                               block = null;
+                               }
+                               return false;
+                       }
+               }
+
+               public bool InsideEnsuresInMethod
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsEnsuresOrOldValue || this.SubroutineContext == null)
+                                       return false;
+                               foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
+                                       if (edge.Tag == EdgeTag.Exit || edge.Tag == EdgeTag.Entry || edge.Tag.Is (EdgeTag.AfterMask))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               public bool InsideRequiresAtCall
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null)
+                                       return false;
+
+                               foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
+                                       if (edge.Tag == EdgeTag.Entry)
+                                               return false;
+                                       if (edge.Tag.Is (EdgeTag.BeforeMask))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               public bool InsideEnsuresAtCall
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null)
+                                       return false;
+
+                               foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
+                                       if (edge.Tag == EdgeTag.Exit)
+                                               return false;
+                                       if (edge.Tag.Is (EdgeTag.BeforeMask))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               public bool InsideInvariantOnExit
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsInvariant || this.SubroutineContext == null)
+                                       return false;
+                               foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
+                                       if (edge.Tag == EdgeTag.Exit)
+                                               return true;
+                                       if (edge.Tag == EdgeTag.Entry || edge.Tag.Is (EdgeTag.AfterMask))
+                                               return false;
+                               }
+
+                               return false;
+                       }
+               }
+
+               public bool InsideInvariantInMethod
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsInvariant || this.SubroutineContext == null)
+                                       return false;
+
+                               foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
+                                       if (edge.Tag == EdgeTag.Exit || edge.Tag == EdgeTag.Entry || edge.Tag.Is (EdgeTag.AfterMask))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               public bool InsideInvariantAtCall
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsInvariant || this.SubroutineContext == null)
+                                       return false;
+                               foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
+                                       if (edge.Tag == EdgeTag.Exit || edge.Tag == EdgeTag.Entry)
+                                               return false;
+                                       if (edge.Tag.Is (EdgeTag.AfterMask))
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               public bool InsideOldManifestation
+               {
+                       get { throw new NotImplementedException (); }
+               }
+
+               public bool InsideRequiresAtCallInsideContract
+               {
+                       get
+                       {
+                               if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null)
+                                       return false;
+                               for (LispList<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)) {
+                                               Subroutine sub = list.Head.From.Subroutine;
+                                               return sub.IsEnsuresOrOldValue || sub.IsRequires || sub.IsInvariant;
+                                       }
+                               }
+                               throw new InvalidOperationException ("Should not happen");
+                       }
+               }
+
+               #region IEquatable<APC> Members
+               public bool Equals (APC other)
+               {
+                       return (this.Block == other.Block && this.Index == other.Index && this.SubroutineContext == other.SubroutineContext);
+               }
+               #endregion
+
+               public APC Next ()
+               {
+                       if (this.Index < this.Block.Count)
+                               return new APC (this.Block, this.Index + 1, this.SubroutineContext);
+
+                       return this;
+               }
+
+               public static APC ForEnd (CFGBlock block, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext)
+               {
+                       return new APC (block, block.Count, subroutineContext);
+               }
+
+               public static APC ForStart (CFGBlock block, LispList<Edge<CFGBlock, EdgeTag>> subroutineContext)
+               {
+                       return new APC (block, 0, subroutineContext);
+               }
+
+               public APC LastInBlock ()
+               {
+                       return ForEnd (this.Block, this.SubroutineContext);
+               }
+
+               public bool TryGetContainingMethod (out Method method)
+               {
+                       LispList<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext;
+                       CFGBlock block = this.Block;
+                       while (block != null) {
+                               var mi = block.Subroutine as IMethodInfo;
+                               if (mi != null) {
+                                       method = mi.Method;
+                                       return true;
+                               }
+
+                               if (list != null) {
+                                       block = list.Head.From;
+                                       list = list.Tail;
+                               } else
+                                       block = null;
+                       }
+                       method = default(Method);
+                       return false;
+               }
+
+               public static void ToString (StringBuilder sb, LispList<Edge<CFGBlock, EdgeTag>> context)
+               {
+                       bool wasFirst = false;
+                       for (; context != null; context = context.Tail) {
+                               if (!wasFirst) {
+                                       sb.Append ("{");
+                                       wasFirst = true;
+                               } else
+                                       sb.Append (",");
+                               Edge<CFGBlock, EdgeTag> head = context.Head;
+                               sb.AppendFormat ("(SR{2} {0},{1}) [{3}]", head.From.Index, head.To.Index, head.From.Subroutine.Id, head.Tag);
+                       }
+                       if (!wasFirst)
+                               return;
+                       sb.Append ("}");
+               }
+
+               public override string ToString ()
+               {
+                       var sb = new StringBuilder ();
+                       sb.Append ("[");
+                       sb.AppendFormat ("SR{2} {0},{1}", this.Block.Index, this.Index, this.Block.Subroutine.Id);
+                       ToString (sb, this.SubroutineContext);
+                       sb.Append ("]");
+
+                       return sb.ToString ();
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs
new file mode 100644 (file)
index 0000000..bfe4611
--- /dev/null
@@ -0,0 +1,105 @@
+// 
+// APCDecoder.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       class APCDecoder : IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy>, IMethodContextProvider, IMethodContext {
+               private readonly SubroutineFacade subroutine_facade;
+               private readonly ControlFlowGraph cfg;
+               private readonly IMetaDataProvider meta_data_provider;
+
+               public APCDecoder (ControlFlowGraph underlyingCFG,
+                                  IMetaDataProvider metaDataProvider,
+                                  SubroutineFacade subroutineFacade)
+               {
+                       this.cfg = underlyingCFG;
+                       this.meta_data_provider = metaDataProvider;
+                       this.subroutine_facade = subroutineFacade;
+               }
+
+               #region IILDecoder<APC,Dummy,Dummy,IMethodContextProvider,Dummy> Members
+               public IMethodContextProvider ContextProvider
+               {
+                       get { return this; }
+               }
+
+               public Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data data)
+                       where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result>
+               {
+                       return this.subroutine_facade.ForwardDecode<Data, Result, RemoveBranchDelegator<Data, Result, Visitor>>
+                               (pc, new RemoveBranchDelegator<Data, Result, Visitor> (visitor, this.meta_data_provider), data);
+               }
+
+               public bool IsUnreachable (APC pc)
+               {
+                       return false;
+               }
+
+               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; }
+               }
+
+               public ICFG CFG
+               {
+                       get { return this.cfg; }
+               }
+
+               public IEnumerable<Field> Modifies (Method method)
+               {
+                       return this.subroutine_facade.GetModifies (method);
+               }
+
+               public IEnumerable<Method> AffectedGetters (Field field)
+               {
+                       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
new file mode 100644 (file)
index 0000000..73d06ba
--- /dev/null
@@ -0,0 +1,83 @@
+// 
+// CFGBlock.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.Collections.Generic;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       abstract class CFGBlock {
+               public int Index;
+
+               protected CFGBlock (Subroutine subroutine, ref int idGen)
+               {
+                       this.Index = idGen++;
+                       Subroutine = subroutine;
+               }
+
+               public abstract int Count { get; }
+               public Subroutine Subroutine { get; private set; }
+               public int ReversePostOrderIndex { get; set; }
+
+               public APC First
+               {
+                       get { return APC.ForStart (this, null); }
+               }
+
+               public APC Last
+               {
+                       get { return APC.ForEnd (this, null); }
+               }
+
+               public virtual bool IsMethodCallBlock<TMethod> (out TMethod calledMethod, out bool isNewObj, out bool isVirtual)
+               {
+                       calledMethod = default(TMethod);
+                       isNewObj = false;
+                       isVirtual = false;
+
+                       return false;
+               }
+
+               public void Renumber (ref int idGen)
+               {
+                       this.Index = idGen++;
+               }
+
+               public abstract int GetILOffset (APC pc);
+
+               public IEnumerable<APC> APCs ()
+               {
+                       return APCs (null);
+               }
+
+               private IEnumerable<APC> APCs (LispList<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
new file mode 100644 (file)
index 0000000..2f3d130
--- /dev/null
@@ -0,0 +1,163 @@
+// 
+// ContractFilteredCFG.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.IO;
+using Mono.CodeContracts.Static.Analysis;
+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
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs
new file mode 100644 (file)
index 0000000..19dda21
--- /dev/null
@@ -0,0 +1,194 @@
+// 
+// ControlFlowGraph.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.IO;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow.Subroutines;
+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);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Edge.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Edge.cs
new file mode 100644 (file)
index 0000000..00ff8a9
--- /dev/null
@@ -0,0 +1,52 @@
+// 
+// Edge.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.ControlFlow {
+       struct Edge<TNode, TTag> {
+               public TNode From;
+               public TTag Tag;
+               public TNode To;
+
+               public Edge (TNode from, TNode to, TTag tag)
+               {
+                       this.From = from;
+                       this.To = to;
+                       this.Tag = tag;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("({0} --'{1}'--> {2})", this.From, this.Tag, this.To);
+               }
+
+               public Edge<TNode, TTag> Reversed ()
+               {
+                       return new Edge<TNode, TTag> (this.To, this.From, this.Tag);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeMap.cs
new file mode 100644 (file)
index 0000000..8cbe88c
--- /dev/null
@@ -0,0 +1,222 @@
+// 
+// EdgeMap.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;
+using System.Collections.Generic;
+using System.Linq;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       class EdgeMap<Tag> : IEnumerable<Edge<CFGBlock, Tag>>, IGraph<CFGBlock, Tag> {
+               private readonly List<Edge<CFGBlock, Tag>> edges;
+
+               public EdgeMap (List<Edge<CFGBlock, Tag>> edges)
+               {
+                       this.edges = edges;
+                       Resort ();
+               }
+
+               public ICollection<Pair<Tag, CFGBlock>> this [CFGBlock node]
+               {
+                       get { return new Successors (this, FindStartIndex (node)); }
+               }
+
+               #region IEnumerable<Edge<CFGBlock,Tag>> Members
+               public IEnumerator<Edge<CFGBlock, Tag>> GetEnumerator ()
+               {
+                       return this.edges.GetEnumerator ();
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
+               #endregion
+
+               #region IGraph<CFGBlock,Tag> Members
+               IEnumerable<CFGBlock> IGraph<CFGBlock, Tag>.Nodes
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               IEnumerable<Pair<Tag, CFGBlock>> IGraph<CFGBlock, Tag>.Successors (CFGBlock node)
+               {
+                       return this [node];
+               }
+               #endregion
+
+               public EdgeMap<Tag> Reverse ()
+               {
+                       var newEdges = new List<Edge<CFGBlock, Tag>> (this.edges.Count);
+
+                       newEdges.AddRange (this.edges.Select (edge => edge.Reversed ()));
+
+                       return new EdgeMap<Tag> (newEdges);
+               }
+
+               private static int CompareFirstBlockIndex (Edge<CFGBlock, Tag> edge1, Edge<CFGBlock, Tag> edge2)
+               {
+                       int cmp = edge1.From.Index - edge2.From.Index;
+                       if (cmp == 0)
+                               cmp = edge1.To.Index - edge2.To.Index;
+
+                       return cmp;
+               }
+
+               private int FindStartIndex (CFGBlock from)
+               {
+                       //binary search
+                       int l = 0;
+                       int r = this.edges.Count;
+                       while (l < r) {
+                               int median = (l + r)/2;
+                               int medianBlockIndex = this.edges [median].From.Index;
+
+                               if (medianBlockIndex == from.Index) {
+                                       while (median > 0 && this.edges [median - 1].From.Index == medianBlockIndex)
+                                               --median;
+                                       return median;
+                               }
+
+                               if (medianBlockIndex < from.Index)
+                                       l = median + 1;
+                               else
+                                       r = median;
+                       }
+
+                       return this.edges.Count;
+               }
+
+               public void Filter (Predicate<Edge<CFGBlock, Tag>> keep)
+               {
+                       var notKeepEdges = new List<int> ();
+                       for (int i = 0; i < this.edges.Count; i++) {
+                               if (!keep (this.edges [i]))
+                                       notKeepEdges.Add (i);
+                       }
+
+                       if (notKeepEdges.Count == 0)
+                               return;
+
+                       int ix = 0;
+                       foreach (int i in notKeepEdges) {
+                               this.edges.RemoveAt (i - ix);
+                               ix++;
+                       }
+               }
+
+               public void Resort ()
+               {
+                       this.edges.Sort (CompareFirstBlockIndex);
+               }
+
+               #region Nested type: Successors
+               private struct Successors : ICollection<Pair<Tag, CFGBlock>> {
+                       private readonly int start_index;
+                       private readonly EdgeMap<Tag> underlying;
+
+                       public Successors (EdgeMap<Tag> underlying, int startIndex)
+                       {
+                               this.underlying = underlying;
+                               this.start_index = startIndex;
+                       }
+
+                       #region ICollection<Pair<Tag,CFGBlock>> Members
+                       public IEnumerator<Pair<Tag, CFGBlock>> GetEnumerator ()
+                       {
+                               List<Edge<CFGBlock, Tag>> edges = this.underlying.edges;
+                               if (this.start_index < edges.Count) {
+                                       int index = this.start_index;
+                                       int blockIndex = edges [index].From.Index;
+                                       do {
+                                               yield return new Pair<Tag, CFGBlock> (edges [index].Tag, edges [index].To);
+                                               ++index;
+                                       } while (index < edges.Count && edges [index].From.Index == blockIndex);
+                               }
+                       }
+
+                       IEnumerator IEnumerable.GetEnumerator ()
+                       {
+                               return GetEnumerator ();
+                       }
+
+                       public void Add (Pair<Tag, CFGBlock> item)
+                       {
+                               throw new InvalidOperationException ();
+                       }
+
+                       public void Clear ()
+                       {
+                               throw new InvalidOperationException ();
+                       }
+
+                       public bool Contains (Pair<Tag, CFGBlock> item)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public void CopyTo (Pair<Tag, CFGBlock>[] array, int arrayIndex)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public bool Remove (Pair<Tag, CFGBlock> item)
+                       {
+                               throw new InvalidOperationException ();
+                       }
+
+                       public int Count
+                       {
+                               get
+                               {
+                                       int index = this.start_index;
+                                       List<Edge<CFGBlock, Tag>> edges = this.underlying.edges;
+                                       if (index >= edges.Count)
+                                               return 0;
+                                       int blockIndex = edges [index].From.Index;
+
+                                       int count = 0;
+                                       do {
+                                               ++count;
+                                               ++index;
+                                       } while (index < edges.Count && edges [index].From.Index == blockIndex);
+
+                                       return count;
+                               }
+                       }
+
+                       public bool IsReadOnly
+                       {
+                               get { return true; }
+                       }
+                       #endregion
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs
new file mode 100644 (file)
index 0000000..62e1048
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// EdgeTag.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;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       [Flags]
+       enum EdgeTag : uint {
+               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,
+
+               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/EdgeTagExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeTagExtensions.cs
new file mode 100644 (file)
index 0000000..fc136da
--- /dev/null
@@ -0,0 +1,36 @@
+// 
+// EdgeTagExtensions.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.ControlFlow {
+       static class EdgeTagExtensions {
+               public static bool Is (this EdgeTag current, EdgeTag mask)
+               {
+                       return (current & mask) != EdgeTag.None;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/EdgeVisitor.cs
new file mode 100644 (file)
index 0000000..ef28638
--- /dev/null
@@ -0,0 +1,32 @@
+// 
+// EdgeVisitor.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.ControlFlow
+{
+  delegate void EdgeVisitor<Node, Info>(Node source, Info info, Node target);
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/ICFG.cs
new file mode 100644 (file)
index 0000000..89869ce
--- /dev/null
@@ -0,0 +1,64 @@
+// 
+// ICFG.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.IO;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       interface ICFG {
+               APC Entry { get; }
+               APC EntryAfterRequires { get; }
+               APC NormalExit { get; }
+               APC ExceptionExit { get; }
+               Subroutine Subroutine { get; }
+               
+               APC Next (APC pc);
+               
+               IEnumerable<APC> Successors (APC pc);
+               bool HasSingleSuccessor (APC pc, out APC ifFound);
+
+               IEnumerable<APC> Predecessors (APC pc);
+               bool HasSinglePredecessor (APC pc, out APC ifFound);
+
+               bool IsJoinPoint (APC pc);
+               bool IsSplitPoint (APC pc);
+
+               bool IsBlockStart (APC pc);
+               bool IsBlockEnd (APC pc);
+
+               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);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs
new file mode 100644 (file)
index 0000000..1b333ec
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IConstantInfo.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 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);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IHandlerFilter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IHandlerFilter.cs
new file mode 100644 (file)
index 0000000..e8ce17d
--- /dev/null
@@ -0,0 +1,36 @@
+// 
+// IHandlerFilter.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 Mono.CodeContracts.Static.AST;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       interface IHandlerFilter<Data> {
+               bool Catch (Data data, TypeNode exception, out bool stopPropagation);
+               bool Filter (Data data, APC filterCode, out bool stopPropagation);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IMethodInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IMethodInfo.cs
new file mode 100644 (file)
index 0000000..40dd57a
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IMethodInfo.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 Mono.CodeContracts.Static.AST;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       interface IMethodInfo {
+               Method Method { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IStackInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/IStackInfo.cs
new file mode 100644 (file)
index 0000000..01c8a0d
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// IStackInfo.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.ControlFlow {
+       interface IStackInfo {
+               bool IsCallOnThis (APC pc);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/RemoveBranchDelegator.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/RemoveBranchDelegator.cs
new file mode 100644 (file)
index 0000000..35e12e4
--- /dev/null
@@ -0,0 +1,420 @@
+// 
+// RemoveBranchDelegator.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.DataStructures;
+using Mono.CodeContracts.Static.Providers;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       /// <summary>
+       /// This class wraps underlying visitor.
+       /// Replaces: branches to nop; branchCond to binary.
+       /// 
+       /// EdgeTag.Requires: (inside method) => assume, (outside method) => assert
+       /// EdgeTag.Ensures:  (inside method) => assert, (outside method) => assume
+       /// </summary>
+       struct RemoveBranchDelegator<Data, Result, Visitor> : IILVisitor<APC, Dummy, Dummy, Data, Result>
+               where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result> {
+               private readonly IMetaDataProvider meta_data_provider;
+               private readonly Visitor visitor;
+
+               public RemoveBranchDelegator (Visitor visitor,
+                                             IMetaDataProvider metaDataProvider)
+               {
+                       this.visitor = visitor;
+                       this.meta_data_provider = metaDataProvider;
+               }
+
+               #region IILVisitor<APC,Dummy,Dummy,Data,Result> Members
+               public Result Binary (APC pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, Data data)
+               {
+                       return this.visitor.Binary (pc, op, dest, operand1, operand2, data);
+               }
+
+               public Result Isinst (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.Isinst (pc, type, dest, obj, data);
+               }
+
+               public Result LoadNull (APC pc, Dummy dest, Data polarity)
+               {
+                       return this.visitor.LoadNull (pc, dest, polarity);
+               }
+
+               public Result LoadConst (APC pc, TypeNode type, object constant, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadConst (pc, type, constant, dest, data);
+               }
+
+               public Result Sizeof (APC pc, TypeNode type, Dummy dest, Data data)
+               {
+                       return this.visitor.Sizeof (pc, type, dest, data);
+               }
+
+               public Result Unary (APC pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.Unary (pc, op, unsigned, dest, source, data);
+               }
+
+               public Result Entry (APC pc, Method method, Data data)
+               {
+                       return this.visitor.Entry (pc, method, data);
+               }
+
+               public Result Assume (APC pc, EdgeTag tag, Dummy condition, Data data)
+               {
+                       if (tag == EdgeTag.Requires && pc.InsideRequiresAtCall || tag == EdgeTag.Invariant && pc.InsideInvariantOnExit)
+                               return this.visitor.Assert (pc, tag, condition, data);
+
+                       return this.visitor.Assume (pc, tag, condition, data);
+               }
+
+               public Result Assert (APC pc, EdgeTag tag, Dummy condition, Data data)
+               {
+                       if (pc.InsideEnsuresAtCall)
+                               return this.visitor.Assume (pc, tag, condition, data);
+
+                       return this.visitor.Assert (pc, tag, condition, data);
+               }
+
+               public Result BeginOld (APC pc, APC matchingEnd, Data data)
+               {
+                       return this.visitor.BeginOld (pc, matchingEnd, data);
+               }
+
+               public Result EndOld (APC pc, APC matchingBegin, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.EndOld (pc, matchingBegin, type, dest, source, data);
+               }
+
+               public Result LoadStack (APC pc, int offset, Dummy dest, Dummy source, bool isOld, Data data)
+               {
+                       return this.visitor.LoadStack (pc, offset, dest, source, isOld, data);
+               }
+
+               public Result LoadStackAddress (APC pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, Data data)
+               {
+                       return this.visitor.LoadStackAddress (pc, offset, dest, source, type, isOld, data);
+               }
+
+               public Result LoadResult (APC pc, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.LoadResult (pc, type, dest, source, data);
+               }
+
+               public Result Arglist (APC pc, Dummy dest, Data data)
+               {
+                       return this.visitor.Arglist (pc, dest, data);
+               }
+
+               public Result Branch (APC pc, APC target, bool leavesExceptionBlock, Data data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public Result BranchCond (APC pc, APC target, BranchOperator bop, Dummy value1, Dummy value2, Data data)
+               {
+                       Dummy dest = Dummy.Value;
+                       switch (bop) {
+                       case BranchOperator.Beq:
+                               return this.visitor.Binary (pc, BinaryOperator.Ceq, dest, value1, value2, data);
+                       case BranchOperator.Bge:
+                               return this.visitor.Binary (pc, BinaryOperator.Cge, dest, value1, value2, data);
+                       case BranchOperator.Bge_Un:
+                               return this.visitor.Binary (pc, BinaryOperator.Cge_Un, dest, value1, value2, data);
+                       case BranchOperator.Bgt:
+                               return this.visitor.Binary (pc, BinaryOperator.Cgt, dest, value1, value2, data);
+                       case BranchOperator.Bgt_Un:
+                               return this.visitor.Binary (pc, BinaryOperator.Cgt_Un, dest, value1, value2, data);
+                       case BranchOperator.Ble:
+                               return this.visitor.Binary (pc, BinaryOperator.Cle, dest, value1, value2, data);
+                       case BranchOperator.Ble_Un:
+                               return this.visitor.Binary (pc, BinaryOperator.Cle_Un, dest, value1, value2, data);
+                       case BranchOperator.Blt:
+                               return this.visitor.Binary (pc, BinaryOperator.Clt, dest, value1, value2, data);
+                       case BranchOperator.Blt_Un:
+                               return this.visitor.Binary (pc, BinaryOperator.Clt_Un, dest, value1, value2, data);
+                       case BranchOperator.Bne_un:
+                               return this.visitor.Binary (pc, BinaryOperator.Cne_Un, dest, value1, value2, data);
+                       default:
+                               return this.visitor.Nop (pc, data);
+                       }
+               }
+
+               public Result BranchTrue (APC pc, APC target, Dummy cond, Data data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public Result BranchFalse (APC pc, APC target, Dummy cond, Data data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public Result Break (APC pc, Data data)
+               {
+                       return this.visitor.Break (pc, data);
+               }
+
+               public Result Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       TypeNode declaringType = this.meta_data_provider.DeclaringType (method);
+                       if (MethodIsReferenceEquals (method, args, declaringType))
+                               return this.visitor.Binary (pc, BinaryOperator.Ceq, dest, args [0], args [1], data);
+
+                       return this.visitor.Call (pc, method, virt, extraVarargs, dest, args, data);
+               }
+
+               public Result Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.Calli (pc, returnType, argTypes, instance, dest, functionPointer, args, data);
+               }
+
+               public Result CheckFinite (APC pc, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.CheckFinite (pc, dest, source, data);
+               }
+
+               public Result CopyBlock (APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, Data data)
+               {
+                       return this.visitor.CopyBlock (pc, destAddress, srcAddress, len, data);
+               }
+
+               public Result EndFilter (APC pc, Dummy decision, Data data)
+               {
+                       return this.visitor.EndFilter (pc, decision, data);
+               }
+
+               public Result EndFinally (APC pc, Data data)
+               {
+                       return this.visitor.EndFinally (pc, data);
+               }
+
+               public Result Jmp (APC pc, Method method, Data data)
+               {
+                       return this.visitor.Jmp (pc, method, data);
+               }
+
+               public Result LoadArg (APC pc, Parameter argument, bool isOld, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadArg (pc, argument, isOld, dest, data);
+               }
+
+               public Result LoadArgAddress (APC pc, Parameter argument, bool isOld, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadArgAddress (pc, argument, isOld, dest, data);
+               }
+
+               public Result LoadLocal (APC pc, Local local, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadLocal (pc, local, dest, data);
+               }
+
+               public Result LoadLocalAddress (APC pc, Local local, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadLocalAddress (pc, local, dest, data);
+               }
+
+               public Result LoadElement (APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, Data data)
+               {
+                       return this.visitor.LoadElement (pc, type, dest, array, index, data);
+               }
+
+               public Result LoadField (APC pc, Field field, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.LoadField (pc, field, dest, obj, data);
+               }
+
+               public Result LoadFieldAddress (APC pc, Field field, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.LoadFieldAddress (pc, field, dest, obj, data);
+               }
+
+               public Result LoadLength (APC pc, Dummy dest, Dummy array, Data data)
+               {
+                       return this.visitor.LoadLength (pc, dest, array, data);
+               }
+
+               public Result LoadStaticField (APC pc, Field field, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadStaticField (pc, field, dest, data);
+               }
+
+               public Result LoadStaticFieldAddress (APC pc, Field field, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadStaticFieldAddress (pc, field, dest, data);
+               }
+
+               public Result LoadTypeToken (APC pc, TypeNode type, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadTypeToken (pc, type, dest, data);
+               }
+
+               public Result LoadFieldToken (APC pc, Field type, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadFieldToken (pc, type, dest, data);
+               }
+
+               public Result LoadMethodToken (APC pc, Method type, Dummy dest, Data data)
+               {
+                       return this.visitor.LoadMethodToken (pc, type, dest, data);
+               }
+
+               public Result Nop (APC pc, Data data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public Result Pop (APC pc, Dummy source, Data data)
+               {
+                       return this.visitor.Pop (pc, source, data);
+               }
+
+               public Result Return (APC pc, Dummy source, Data data)
+               {
+                       return this.visitor.Return (pc, source, data);
+               }
+
+               public Result StoreArg (APC pc, Parameter argument, Dummy source, Data data)
+               {
+                       return this.visitor.StoreArg (pc, argument, source, data);
+               }
+
+               public Result StoreLocal (APC pc, Local local, Dummy source, Data data)
+               {
+                       return this.visitor.StoreLocal (pc, local, source, data);
+               }
+
+               public Result StoreElement (APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, Data data)
+               {
+                       return this.visitor.StoreElement (pc, type, array, index, value, data);
+               }
+
+               public Result StoreField (APC pc, Field field, Dummy obj, Dummy value, Data data)
+               {
+                       return this.visitor.StoreField (pc, field, obj, value, data);
+               }
+
+               public Result StoreStaticField (APC pc, Field field, Dummy value, Data data)
+               {
+                       return this.visitor.StoreStaticField (pc, field, value, data);
+               }
+
+               public Result Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, Data data)
+               {
+                       return this.visitor.Nop (pc, data);
+               }
+
+               public Result Box (APC pc, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.Box (pc, type, dest, source, data);
+               }
+
+               public Result ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Data data)
+                       where TypeList : IIndexable<TypeNode>
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.ConstrainedCallvirt (pc, method, constraint, extraVarargs, dest, args, data);
+               }
+
+               public Result CastClass (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.CastClass (pc, type, dest, obj, data);
+               }
+
+               public Result CopyObj (APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, Data data)
+               {
+                       return this.visitor.CopyObj (pc, type, destPtr, sourcePtr, data);
+               }
+
+               public Result Initobj (APC pc, TypeNode type, Dummy ptr, Data data)
+               {
+                       return this.visitor.Initobj (pc, type, ptr, data);
+               }
+
+               public Result NewArray<ArgList> (APC pc, TypeNode type, Dummy dest, ArgList lengths, Data data) where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.NewArray (pc, type, dest, lengths, data);
+               }
+
+               public Result NewObj<ArgList> (APC pc, Method ctor, Dummy dest, ArgList args, Data data) where ArgList : IIndexable<Dummy>
+               {
+                       return this.visitor.NewObj (pc, ctor, dest, args, data);
+               }
+
+               public Result MkRefAny (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.MkRefAny (pc, type, dest, obj, data);
+               }
+
+               public Result RefAnyType (APC pc, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.RefAnyType (pc, dest, source, data);
+               }
+
+               public Result RefAnyVal (APC pc, TypeNode type, Dummy dest, Dummy source, Data data)
+               {
+                       return this.visitor.RefAnyVal (pc, type, dest, source, data);
+               }
+
+               public Result Rethrow (APC pc, Data data)
+               {
+                       return this.visitor.Rethrow (pc, data);
+               }
+
+               public Result Throw (APC pc, Dummy exception, Data data)
+               {
+                       return this.visitor.Throw (pc, exception, data);
+               }
+
+               public Result Unbox (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.Unbox (pc, type, dest, obj, data);
+               }
+
+               public Result UnboxAny (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
+               {
+                       return this.visitor.UnboxAny (pc, type, dest, obj, data);
+               }
+               #endregion
+
+               private bool MethodIsReferenceEquals<ArgList> (Method method, ArgList args, TypeNode declaringType)
+                       where ArgList : IIndexable<Dummy>
+               {
+                       return args.Count == 2 && this.meta_data_provider.IsStatic (method)
+                              && this.meta_data_provider.Equal (declaringType, this.meta_data_provider.System_Object)
+                              && this.meta_data_provider.Name (method) == "ReferenceEquals";
+               }
+               }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/Subroutine.cs
new file mode 100644 (file)
index 0000000..b435122
--- /dev/null
@@ -0,0 +1,186 @@
+// 
+// Subroutine.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.IO;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.ControlFlow {
+       abstract class Subroutine : ITypedProperties, IEquatable<Subroutine> {
+               private static int _subroutineIdGenerator;
+               private readonly TypedProperties properties = new TypedProperties ();
+               private readonly int subroutine_id = _subroutineIdGenerator++;
+
+               public virtual SubroutineKind Kind
+               {
+                       get { return SubroutineKind.Unknown; }
+               }
+
+               public int Id
+               {
+                       get { return this.subroutine_id; }
+               }
+
+               public abstract CFGBlock Entry { get; }
+               public abstract CFGBlock EntryAfterRequires { get; }
+               public abstract CFGBlock Exit { get; }
+               public abstract CFGBlock ExceptionExit { get; }
+               public abstract string Name { get; }
+               public abstract int BlockCount { get; }
+               public abstract IEnumerable<CFGBlock> Blocks { get; }
+
+               public virtual bool IsRequires
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsEnsures
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsOldValue
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsMethod
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsConstructor
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsInvariant
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsContract
+               {
+                       get { return false; }
+               }
+
+               public bool IsEnsuresOrOldValue
+               {
+                       get { return IsEnsures || IsOldValue; }
+               }
+
+               public abstract EdgeMap<EdgeTag> SuccessorEdges { get; }
+               public abstract EdgeMap<EdgeTag> PredecessorEdges { get; }
+               public abstract DepthFirst.Visitor<CFGBlock, Dummy> EdgeInfo { get; }
+
+               public virtual bool IsFaultFinally
+               {
+                       get { return false; }
+               }
+
+               public abstract bool HasReturnValue { get; }
+               public abstract bool HasContextDependentStackDepth { get; }
+
+               public abstract int StackDelta { get; }
+
+               #region ITypedProperties Members
+               public bool TryGetValue<T> (TypedKey key, out T value)
+               {
+                       return this.properties.TryGetValue (key, out value);
+               }
+               #endregion
+
+               #region Implementation of ITypedProperties
+               public bool Contains (TypedKey key)
+               {
+                       return this.properties.Contains (key);
+               }
+
+               public void Add<T> (TypedKey key, T value)
+               {
+                       this.properties.Add (key, value);
+               }
+               #endregion
+
+               public override string ToString ()
+               {
+                       return string.Format ("SR {0}: BlockCount:{1}, Kind:{2}", Id, BlockCount, Kind);
+               }
+
+               public abstract IEnumerable<CFGBlock> SuccessorBlocks (CFGBlock block);
+
+               public IEnumerable<Pair<EdgeTag, CFGBlock>> SuccessorEdgesFor (CFGBlock block)
+               {
+                       return SuccessorEdges [block];
+               }
+
+               public abstract IEnumerable<CFGBlock> PredecessorBlocks (CFGBlock block);
+
+               public abstract bool IsJoinPoint (CFGBlock block);
+               public abstract bool IsSplitPoint (CFGBlock block);
+               public abstract bool HasSingleSuccessor (APC point, out APC ifFound);
+               public abstract bool HasSinglePredecessor (APC point, out APC ifFound);
+
+               public abstract void AddEdgeSubroutine (CFGBlock from, CFGBlock to, Subroutine subroutine, EdgeTag tag);
+
+               public abstract IEnumerable<APC> Successors (APC pc);
+               public abstract IEnumerable<APC> Predecessors (APC pc);
+
+               public abstract bool IsSubroutineEnd (CFGBlock block);
+               public abstract bool IsSubroutineStart (CFGBlock block);
+               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 void Initialize ();
+               public abstract IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen);
+
+               public IEnumerable<Subroutine> UsedSubroutines ()
+               {
+                       return UsedSubroutines (new HashSet<int> ());
+               }
+
+               public abstract IEnumerable<CFGBlock> ExceptionHandlers<Data, Type> (CFGBlock block, Subroutine innerSubroutine,
+                                                                                    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);
+
+               #region Implementation of IEquatable<Subroutine>
+               public bool Equals (Subroutine other)
+               {
+                       return Id == other.Id;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/SubroutineKind.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.ControlFlow/SubroutineKind.cs
new file mode 100644 (file)
index 0000000..d802d04
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// SubroutineKind.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.ControlFlow {
+       enum SubroutineKind {
+               Unknown,
+               Requires,
+               Ensures,
+               Method,
+               Entry,
+               Fault,
+               Finally,
+               Simple,
+               Old
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/DataFlowAnalysisBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/DataFlowAnalysisBase.cs
new file mode 100644 (file)
index 0000000..9dfc61c
--- /dev/null
@@ -0,0 +1,164 @@
+// 
+// DataFlowAnalysisBase.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.IO;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       abstract class DataFlowAnalysisBase<AState> :
+               IEqualityComparer<APC> {
+               protected ICFG CFG;
+               protected Dictionary<APC, AState> JoinState;
+               protected PriorityQueue<APC> pending;
+               private IWidenStrategy widen_strategy;
+
+               protected DataFlowAnalysisBase (ICFG cfg)
+               {
+                       this.CFG = cfg;
+                       this.pending = new PriorityQueue<APC> (WorkingListComparer);
+                       this.JoinState = new Dictionary<APC, AState> (this);
+                       this.widen_strategy = null;
+               }
+
+               #region IEqualityComparer<APC> Members
+               bool IEqualityComparer<APC>.Equals (APC x, APC y)
+               {
+                       return x.Equals (y);
+               }
+
+               int IEqualityComparer<APC>.GetHashCode (APC obj)
+               {
+                       return obj.GetHashCode ();
+               }
+               #endregion
+
+               public void Initialize (APC entryPoint, AState state)
+               {
+                       this.JoinState.Add (entryPoint, state);
+                       this.pending.Enqueue (entryPoint);
+               }
+
+               public virtual void ComputeFixPoint ()
+               {
+                       this.widen_strategy = new EdgeBasedWidening (20);
+
+                       while (this.pending.Count > 0) {
+                               APC next = this.pending.Dequeue ();
+                               AState state = MutableVersion (this.JoinState [next], next);
+
+                               APC cur;
+                               bool repeatOuter = false;
+                               do {
+                                       cur = next;
+                                       if (!IsBottom (cur, state)) {
+                                               state = Transfer (cur, state);
+                                       } else {
+                                               repeatOuter = true;
+                                               break;
+                                       }
+                               } while (HasSingleSuccessor (cur, out next) && !RequiresJoining (next));
+
+                               if (repeatOuter)
+                                       continue;
+
+                               foreach (APC successorAPC in Successors (cur)) {
+                                       if (!IsBottom (successorAPC, state))
+                                               PushState (cur, successorAPC, state);
+                               }
+                       }
+               }
+
+               protected virtual void Dump (AState state)
+               {
+               }
+
+               public IEnumerable<KeyValuePair<APC, AState>> States ()
+               {
+                       return this.JoinState;
+               }
+
+               protected abstract IEnumerable<APC> Successors (APC pc);
+
+               protected virtual void PushState (APC current, APC next, AState state)
+               {
+                       state = ImmutableVersion (state, next);
+                       if (RequiresJoining (next)) {
+                               if (!JoinStateAtBlock (new Pair<APC, APC> (current, next), state))
+                                       return;
+                               this.pending.Enqueue (next);
+                       } else {
+                               this.JoinState [next] = state;
+                               this.pending.Enqueue (next);
+                       }
+               }
+
+               private bool JoinStateAtBlock (Pair<APC, APC> edge, AState state)
+               {
+                       AState existingState;
+                       if (this.JoinState.TryGetValue (edge.Value, out existingState)) {
+                               bool widen = this.widen_strategy.WantToWiden (edge.Key, edge.Value, IsBackEdge (edge.Key, edge.Value));
+                               AState joinedState;
+                               bool result = Join (edge, state, existingState, out joinedState, widen);
+                               if (result)
+                                       this.JoinState [edge.Value] = ImmutableVersion (joinedState, edge.Value);
+                               return result;
+                       }
+
+                       this.JoinState.Add (edge.Value, state);
+                       return true;
+               }
+
+               protected abstract bool IsBackEdge (APC from, APC to);
+
+               protected abstract int WorkingListComparer (APC a, APC b);
+
+               protected abstract bool Join (Pair<APC, APC> edge, AState newState, AState existingState, out AState joinedState, bool widen);
+
+               protected abstract bool RequiresJoining (APC pc);
+
+               protected abstract bool HasSingleSuccessor (APC pc, out APC next);
+
+               protected abstract bool IsBottom (APC pc, AState state);
+
+               protected abstract AState Transfer (APC pc, AState state);
+
+               protected abstract AState MutableVersion (AState state, APC at);
+               protected abstract AState ImmutableVersion (AState state, APC at);
+
+               public void PrintStatesAtJoinPoints (TextWriter tw)
+               {
+                       foreach (APC apc in this.JoinState.Keys) {
+                               string str = this.JoinState [apc].ToString ().Replace (Environment.NewLine, Environment.NewLine + "   ");
+                               tw.WriteLine ("Block {0}, PC {1}: {2}", apc.Block, apc.Index, str);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/EdgeBasedWidening.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/EdgeBasedWidening.cs
new file mode 100644 (file)
index 0000000..22e74f0
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// EdgeBasedWidening.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 Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       class EdgeBasedWidening : StepWidening<Pair<APC, APC>> {
+               public EdgeBasedWidening (int n)
+                       : base (n)
+               {
+               }
+
+               #region Overrides of StepWidening<Pair<APC,APC>>
+               protected override Pair<APC, APC> MakeIndex (APC from, APC to)
+               {
+                       return new Pair<APC, APC> (from, to);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/EdgeConverter.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/EdgeConverter.cs
new file mode 100644 (file)
index 0000000..37d6e33
--- /dev/null
@@ -0,0 +1,31 @@
+// 
+// EdgeConverter.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.DataFlowAnalysis {
+       delegate AbstractState EdgeConverter<Label, AbstractState, EdgeData> (Label from, Label to, bool isJoinPoint, EdgeData data, AbstractState newState);
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs
new file mode 100644 (file)
index 0000000..ec6c23d
--- /dev/null
@@ -0,0 +1,151 @@
+// 
+// ForwardAnalysis.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.IO;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow;
+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;
+               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;
+
+               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, APC, EdgeData> edgeDataGetter,
+                                       Func<APC, AState, bool> isBottom,
+                                       Action<Pair<AState, TextWriter>> dumper) : base (cfg)
+               {
+                       this.transfer = transfer;
+                       this.joiner = joiner;
+                       this.immutable_version = immutableVersion;
+                       this.mutable_version = mutableVersion;
+                       this.edge_converter = edgeConverter;
+                       this.edge_data_getter = edgeDataGetter;
+                       this.is_bottom = isBottom;
+                       this.dumper = dumper;
+               }
+
+               #region IFixPointInfo<APC,AbstractState> Members
+               public bool PreStateLookup (APC pc, out AState state)
+               {
+                       return GetPreState (pc, out state);
+               }
+
+               public bool PostStateLookup (APC pc, out AState state)
+               {
+                       return GetPostState (pc, out state);
+               }
+               #endregion
+
+               public static ForwardAnalysis<AState, EdgeData> Make<Source, Dest, Context> (
+                       IILDecoder<APC, Source, Dest, Context, EdgeData> decoder,
+                       IAnalysis<APC, AState, IILVisitor<APC, Source, Dest, AState, AState>, EdgeData> analysis)
+                       where Context : IMethodContextProvider
+               {
+                       IILVisitor<APC, Source, Dest, AState, AState> visitor = analysis.GetVisitor ();
+                       var forwardAnalysisSolver = new ForwardAnalysis<AState, EdgeData> (
+                               decoder.ContextProvider.MethodContext.CFG,
+                               (pc, state) => decoder.ForwardDecode<AState, AState, IILVisitor<APC, Source, Dest, AState, AState>> (pc, visitor, state),
+                               analysis.Join,
+                               analysis.ImmutableVersion,
+                               analysis.MutableVersion,
+                               analysis.EdgeConversion,
+                               decoder.EdgeData,
+                               (pc, state) => {
+                                       if (!decoder.IsUnreachable (pc))
+                                               return analysis.IsBottom (pc, state);
+
+                                       return true;
+                               }, 
+                               analysis.Dump
+                               );
+
+                       analysis.SaveFixPointInfo (forwardAnalysisSolver);
+                       return forwardAnalysisSolver;
+               }
+
+               protected override void Dump (AState state)
+               {
+                       this.dumper (new Pair<AState, TextWriter> (state, Console.Out));
+               }
+
+               protected override void PushState (APC from, APC next, AState state)
+               {
+                       EdgeData data = this.edge_data_getter (from, next);
+                       AState 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)
+               {
+                       bool weaker;
+                       joinedState = this.joiner (edge, newState, existingState, out weaker, widen);
+
+                       return weaker;
+               }
+
+               protected override bool IsBottom (APC pc, AState state)
+               {
+                       return this.is_bottom (pc, state);
+               }
+
+               protected override AState Transfer (APC pc, AState state)
+               {
+                       AState resultState = this.transfer (pc, state);
+
+                       return resultState;
+               }
+
+               protected override AState MutableVersion (AState state, APC at)
+               {
+                       return this.mutable_version (state);
+               }
+
+               protected override AState ImmutableVersion (AState 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
new file mode 100644 (file)
index 0000000..b82f8f1
--- /dev/null
@@ -0,0 +1,155 @@
+// 
+// ForwardDataFlowAnalysisBase.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.Collections.Generic;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       abstract class ForwardDataFlowAnalysisBase<AState> : DataFlowAnalysisBase<AState> {
+               private readonly Dictionary<APC, AState> post_state = new Dictionary<APC, AState> ();
+
+               protected ForwardDataFlowAnalysisBase (ICFG cfg) : base (cfg)
+               {
+               }
+
+               public bool GetPreState (APC pc, out AState state)
+               {
+                       bool noInfo;
+                       state = GetPreState (pc, default(AState), out noInfo);
+                       return !noInfo;
+               }
+
+               public AState GetPreStateWithDefault (APC apc, AState ifMissing)
+               {
+                       bool noInfo;
+                       AState preState = GetPreState (apc, default(AState), out noInfo);
+                       return noInfo ? ifMissing : preState;
+               }
+
+               private AState GetPreState (APC apc, AState ifMissing, out bool noInfo)
+               {
+                       LispList<APC> rest = null;
+                       APC tmp = apc;
+                       APC singlePredecessor;
+                       AState state;
+                       bool weHaveState;
+                       while (!(weHaveState = this.JoinState.TryGetValue (tmp, out state)) &&
+                              !RequiresJoining (tmp) && this.CFG.HasSinglePredecessor (tmp, out singlePredecessor)) {
+                               tmp = singlePredecessor;
+
+                               rest = rest.Cons (tmp);
+                       }
+
+                       if (!weHaveState) {
+                               noInfo = true;
+                               return ifMissing;
+                       }
+
+                       bool listWasNotEmpty = rest != null;
+                       while (rest != null) {
+                               if (IsBottom (rest.Head, state)) {
+                                       noInfo = false;
+                                       return state;
+                               }
+                               state = MutableVersion (state, rest.Head);
+                               state = Transfer (rest.Head, state);
+                               if (IsBottom (rest.Head, state)) {
+                                       noInfo = false;
+                                       return state;
+                               }
+
+                               rest = rest.Tail;
+                               if (rest != null)
+                                       this.JoinState.Add (rest.Head, ImmutableVersion (state, rest.Head));
+                       }
+
+                       if (listWasNotEmpty)
+                               this.JoinState.Add (apc, ImmutableVersion (state, apc));
+
+                       noInfo = false;
+                       return state;
+               }
+
+               public bool GetPostState (APC apc, out AState result)
+               {
+                       if (this.post_state.TryGetValue (apc, out result))
+                               return true;
+
+                       APC singleSuccessor;
+                       if (apc.Block.Count <= apc.Index)
+                               return GetPreState (apc, out result);
+
+                       if (this.CFG.HasSingleSuccessor (apc, out singleSuccessor) && !RequiresJoining (singleSuccessor))
+                               return GetPreState (singleSuccessor, out result);
+
+                       AState ifFound;
+                       if (!GetPreState (apc, out ifFound))
+                               return false;
+
+                       result = MutableVersion (ifFound, apc);
+                       result = Transfer (apc, result);
+
+                       this.post_state.Add (apc, result);
+                       return true;
+               }
+
+               public void Run (AState startState)
+               {
+                       Initialize (this.CFG.Entry, startState);
+                       ComputeFixPoint ();
+               }
+
+               protected override int WorkingListComparer (APC a, APC b)
+               {
+                       return b.Block.ReversePostOrderIndex - a.Block.ReversePostOrderIndex;
+               }
+
+               protected override bool RequiresJoining (APC pc)
+               {
+                       return this.CFG.IsJoinPoint (pc);
+               }
+
+               protected override bool HasSingleSuccessor (APC pc, out APC next)
+               {
+                       return this.CFG.HasSingleSuccessor (pc, out next);
+               }
+
+               protected override IEnumerable<APC> Successors (APC pc)
+               {
+                       return this.CFG.Successors (pc);
+               }
+
+               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;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs
new file mode 100644 (file)
index 0000000..b3027b8
--- /dev/null
@@ -0,0 +1,45 @@
+// 
+// IAnalysis.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.IO;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       interface IAnalysis<Label, AbstractState, Visitor, EdgeData> {
+               Visitor GetVisitor ();
+               AbstractState Join (Pair<Label, Label> edge, AbstractState newstate, AbstractState prevstate, out bool weaker, bool widen);
+               AbstractState ImmutableVersion (AbstractState arg);
+               AbstractState MutableVersion (AbstractState arg);
+               AbstractState EdgeConversion (APC from, APC to, bool isJoinPoint, EdgeData data, AbstractState state);
+               bool IsBottom (Label pc, AbstractState state);
+               Predicate<Label> SaveFixPointInfo (IFixPointInfo<Label, AbstractState> fixPointInfo);
+               void Dump (Pair<AbstractState, TextWriter> pair);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IFixPointInfo.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IFixPointInfo.cs
new file mode 100644 (file)
index 0000000..b0b4dcf
--- /dev/null
@@ -0,0 +1,34 @@
+// 
+// IFixPointInfo.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.DataFlowAnalysis {
+       interface IFixPointInfo<Label, AState> {
+               bool PreStateLookup (Label pc, out AState state);
+               bool PostStateLookup (Label pc, out AState state);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IWidenStrategy.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/IWidenStrategy.cs
new file mode 100644 (file)
index 0000000..866b4a7
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IWidenStrategy.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 Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       interface IWidenStrategy {
+               bool WantToWiden (APC from, APC to, bool isBackEdge);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/Joiner.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/Joiner.cs
new file mode 100644 (file)
index 0000000..3af5736
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// Joiner.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 Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       delegate AbstractState Joiner<Label, AbstractState> (Pair<Label, Label> edge, AbstractState newState, AbstractState prevState, out bool weaker, bool widen);
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/StepWidening.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataFlowAnalysis/StepWidening.cs
new file mode 100644 (file)
index 0000000..75e844e
--- /dev/null
@@ -0,0 +1,60 @@
+// 
+// StepWidening.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.Collections.Generic;
+using Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.DataFlowAnalysis {
+       abstract class StepWidening<Index> : IWidenStrategy {
+               private readonly int N;
+               private readonly Dictionary<Index, int> widenCounter;
+
+               protected StepWidening (int n)
+               {
+                       this.widenCounter = new Dictionary<Index, int> ();
+                       this.N = n;
+               }
+
+               protected abstract Index MakeIndex (APC from, APC to);
+
+               #region Implementation of IWidenStrategy
+               public bool WantToWiden (APC from, APC to, bool isBackEdge)
+               {
+                       if (!isBackEdge)
+                               return false;
+
+                       Index key = MakeIndex (from, to);
+                       if (this.widenCounter.ContainsKey (key))
+                               this.widenCounter [key] = this.widenCounter [key] + 1;
+                       else
+                               this.widenCounter [key] = 1;
+                       return this.N < this.widenCounter [key];
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/AbstractWorkList.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/AbstractWorkList.cs
new file mode 100644 (file)
index 0000000..26777ad
--- /dev/null
@@ -0,0 +1,75 @@
+// 
+// AbstractWorkList.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       abstract class AbstractWorkList<T> : IWorkList<T> {
+               protected HashSet<T> Elements = new HashSet<T> ();
+               protected abstract IEnumerable<T> Collection { get; }
+
+               public int Count
+               {
+                       get { return this.Elements.Count; }
+               }
+
+               protected abstract void AddToCollection (T o);
+
+               #region Implementation of IWorkList<T>
+               public virtual bool Add (T o)
+               {
+                       if (!this.Elements.Add (o))
+                               return false;
+                       AddToCollection (o);
+                       return true;
+               }
+
+               public virtual bool IsEmpty ()
+               {
+                       return this.Elements.Count == 0;
+               }
+
+               public abstract T Pull ();
+
+               public virtual bool AddAll (IEnumerable<T> objs)
+               {
+                       bool any = false;
+                       foreach (T o in objs) {
+                               if (Add (o))
+                                       any = true;
+                       }
+                       return any;
+               }
+
+               public virtual IEnumerator<T> GetEnumerator ()
+               {
+                       return Collection.GetEnumerator ();
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs
new file mode 100644 (file)
index 0000000..be7a11a
--- /dev/null
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       /// <summary>
+       /// This class is used with subroutines to substitute IStackInfo and IEdgeSubroutineAdapter to desired
+       /// </summary>
+       static class DecoratorHelper {
+               private static readonly List<object> ContextAdapters = new List<object> ();
+
+               private static object Last
+               {
+                       get { return ContextAdapters [ContextAdapters.Count - 1]; }
+               }
+
+               public static void Push<T> (T @this) where T : class
+               {
+                       ContextAdapters.Add (@this);
+               }
+
+               public static void Pop ()
+               {
+                       ContextAdapters.RemoveAt (ContextAdapters.Count - 1);
+               }
+
+               public static T Dispatch<T> (T @this) where T : class
+               {
+                       return FindAdaptorStartingAt (@this, 0);
+               }
+
+               private static T FindAdaptorStartingAt<T> (T @default, int startIndex)
+                       where T : class
+               {
+                       List<object> list = ContextAdapters;
+                       for (int i = startIndex; i < list.Count; ++i) {
+                               var obj = list [i] as T;
+                               if (obj != null)
+                                       return obj;
+                       }
+                       return @default;
+               }
+
+               public static T Inner<T> (T @this) where T : class
+               {
+                       for (int i = 0; i < ContextAdapters.Count; i++) {
+                               if (ContextAdapters [i] == @this) {
+                                       ClearDuplicates (@this, i + 1);
+                                       T inner = FindAdaptorStartingAt (default(T), i + 1);
+                                       if (inner != null)
+                                               return inner;
+
+                                       throw new InvalidOperationException ("No inner context found");
+                               }
+                       }
+
+                       throw new InvalidOperationException ("@this is not current adaptor");
+               }
+
+               private static void ClearDuplicates (object @this, int @from)
+               {
+                       for (int i = from; i < ContextAdapters.Count; i++) {
+                               if (ContextAdapters [i] == @this)
+                                       ContextAdapters [i] = null;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DepthFirst.cs
new file mode 100644 (file)
index 0000000..16ee3b9
--- /dev/null
@@ -0,0 +1,229 @@
+// 
+// DepthFirst.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 DepthFirst {
+               public static void Visit<Node, EdgeInfo> (IGraph<Node, EdgeInfo> graph,
+                                                         Predicate<Node> nodeStartVisitor,
+                                                         EdgeVisitor<Node, EdgeInfo> edgeVisitor)
+               {
+                       new Visitor<Node, EdgeInfo> (graph, nodeStartVisitor, edgeVisitor).VisitAll ();
+               }
+
+               public static void Visit<Node, EdgeInfo> (IGraph<Node, EdgeInfo> graph,
+                                                         Node startNode,
+                                                         Predicate<Node> nodeStartVisitor,
+                                                         EdgeVisitor<Node, EdgeInfo> edgeVisitor)
+               {
+                       new Visitor<Node, EdgeInfo> (graph, nodeStartVisitor, edgeVisitor).VisitSubGraphNonRecursive (startNode);
+               }
+
+               #region Nested type: Info
+               public class Info<Node> {
+                       public readonly Node Parent;
+                       public readonly int StartTime;
+
+                       public int FinishTime;
+                       public bool SourceOfBackEdge;
+                       public bool TargetOfBackEdge;
+
+                       public Info (Node parent, int startTime)
+                       {
+                               this.Parent = parent;
+                               this.StartTime = startTime;
+                       }
+               }
+               #endregion
+
+               #region Nested type: Visitor
+               public class Visitor<Node, Edge> {
+                       private readonly HashSet<Tuple<Node, Edge, Node>> back_edges = new HashSet<Tuple<Node, Edge, Node>> ();
+                       private readonly EdgeVisitor<Node, Edge> edge_visitor;
+                       private readonly IGraph<Node, Edge> graph;
+
+                       private readonly Dictionary<Node, Info<Node>> history = new Dictionary<Node, Info<Node>> ();
+                       private readonly Action<Node> node_finish_visitor;
+                       private readonly Predicate<Node> node_start_visitor;
+                       private readonly Stack<SearchFrame> todo = new Stack<SearchFrame> ();
+                       private int time;
+
+                       public Visitor (IGraph<Node, Edge> graph, Predicate<Node> nodeStartVisitor, EdgeVisitor<Node, Edge> edgeVisitor)
+                               : this (graph, nodeStartVisitor, null, edgeVisitor)
+                       {
+                       }
+
+                       public Visitor (IGraph<Node, Edge> graph, Predicate<Node> nodeStartVisitor)
+                               : this (graph, nodeStartVisitor, null, null)
+                       {
+                       }
+
+                       public Visitor (IGraph<Node, Edge> graph, Predicate<Node> nodeStartVisitor, Action<Node> nodeFinishVisitor, EdgeVisitor<Node, Edge> edgeVisitor)
+                       {
+                               this.graph = graph;
+                               this.node_start_visitor = nodeStartVisitor;
+                               this.node_finish_visitor = nodeFinishVisitor;
+                               this.edge_visitor = edgeVisitor;
+                       }
+
+                       public virtual void VisitAll ()
+                       {
+                               foreach (Node node in this.graph.Nodes)
+                                       VisitSubGraphNonRecursive (node);
+                       }
+
+                       public void VisitSubGraphNonRecursive (Node node)
+                       {
+                               ScheduleNode (node, default(Node));
+                               IterativeDFS ();
+                       }
+
+                       private void IterativeDFS ()
+                       {
+                               while (this.todo.Count > 0) {
+                                       SearchFrame frame = this.todo.Peek ();
+                                       if (frame.Edges.MoveNext ()) {
+                                               Pair<Edge, Node> current = frame.Edges.Current;
+                                               VisitEdgeNonRecursive (frame.Info, frame.Node, current.Key, current.Value);
+                                       } else {
+                                               if (this.node_finish_visitor != null)
+                                                       this.node_finish_visitor (frame.Node);
+                                               frame.Info.FinishTime = ++this.time;
+                                               this.todo.Pop ();
+                                       }
+                               }
+                       }
+
+                       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 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);
+                       }
+
+                       public void VisitSubGraph (Node node, Node parent)
+                       {
+                               if (this.history.ContainsKey (node))
+                                       return;
+
+                               var info = new Info<Node> (parent, ++this.time);
+                               this.history [node] = info;
+
+                               if (this.node_start_visitor != null && !this.node_start_visitor (node))
+                                       return;
+
+                               VisitSuccessors (info, node);
+
+                               if (this.node_finish_visitor != null)
+                                       this.node_finish_visitor (node);
+
+                               info.FinishTime = ++this.time;
+                       }
+
+                       public void ScheduleNode (Node node, Node parent)
+                       {
+                               if (this.history.ContainsKey (node))
+                                       return;
+
+                               var info = new Info<Node> (parent, ++this.time);
+                               this.history [node] = info;
+
+                               if (this.node_start_visitor != null && !this.node_start_visitor (node))
+                                       return;
+
+                               this.todo.Push (new SearchFrame (node, this.graph.Successors (node).GetEnumerator (), info));
+                       }
+
+                       private void VisitSuccessors (Info<Node> info, Node node)
+                       {
+                               foreach (var successor in this.graph.Successors (node))
+                                       VisitEdge (info, node, successor.Key, successor.Value);
+                       }
+
+                       public bool IsVisited (Node node)
+                       {
+                               return this.history.ContainsKey (node);
+                       }
+
+                       public bool IsBackEdge (Node source, Edge info, Node target)
+                       {
+                               return this.back_edges.Contains (new Tuple<Node, Edge, Node> (source, info, target));
+                       }
+
+                       public Info<Node> DepthFirstInfo (Node node)
+                       {
+                               return this.history [node];
+                       }
+
+                       #region Nested type: SearchFrame
+                       private struct SearchFrame {
+                               public readonly IEnumerator<Pair<Edge, Node>> Edges;
+                               public readonly Info<Node> Info;
+                               public readonly Node Node;
+
+                               public SearchFrame (Node node, IEnumerator<Pair<Edge, Node>> edges, Info<Node> info)
+                               {
+                                       this.Node = node;
+                                       this.Edges = edges;
+                                       this.Info = info;
+                               }
+                       }
+                       #endregion
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DoubleDictionary.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DoubleDictionary.cs
new file mode 100644 (file)
index 0000000..75ab912
--- /dev/null
@@ -0,0 +1,90 @@
+// 
+// DoubleDictionary.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.Collections.Generic;
+using System.Linq;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       class DoubleDictionary<A, B, C> : Dictionary<A, Dictionary<B, C>> {
+               public C this [A a, B b]
+               {
+                       get { return base [a] [b]; }
+                       set
+                       {
+                               Dictionary<B, C> dict;
+                               if (!base.TryGetValue (a, out dict)) {
+                                       dict = new Dictionary<B, C> ();
+                                       base.Add (a, dict);
+                               }
+                               dict [b] = value;
+                       }
+               }
+
+               public IEnumerable<A> Keys1
+               {
+                       get { return base.Keys; }
+               }
+
+               public void Add (A a, B b, C value)
+               {
+                       Dictionary<B, C> dict;
+                       if (!base.TryGetValue (a, out dict)) {
+                               dict = new Dictionary<B, C> ();
+                               base.Add (a, dict);
+                       }
+                       dict.Add (b, value);
+               }
+
+               public IEnumerable<B> Keys2 (A a)
+               {
+                       Dictionary<B, C> dict;
+                       if (base.TryGetValue (a, out dict))
+                               return dict.Keys;
+                       return Enumerable.Empty<B> ();
+               }
+
+               public bool ContainsKey (A a, B b)
+               {
+                       Dictionary<B, C> dict;
+                       if (!base.TryGetValue (a, out dict))
+                               return false;
+
+                       return dict.ContainsKey (b);
+               }
+
+               public bool TryGetValue (A a, B b, out C value)
+               {
+                       Dictionary<B, C> dict;
+                       if (base.TryGetValue (a, out dict))
+                               return dict.TryGetValue (b, out value);
+
+                       value = default(C);
+                       return false;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DoubleImmutableMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/DoubleImmutableMap.cs
new file mode 100644 (file)
index 0000000..58b9cb1
--- /dev/null
@@ -0,0 +1,126 @@
+// 
+// DoubleImmutableMap.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 {
+       class DoubleImmutableMap<A, B, C>
+               where A : IEquatable<A>
+               where B : IEquatable<B> {
+               private readonly B[] EmptyCache = new B[0];
+               private readonly IImmutableMap<A, IImmutableMap<B, C>> map;
+
+               private DoubleImmutableMap (IImmutableMap<A, IImmutableMap<B, C>> map)
+               {
+                       this.map = map;
+               }
+
+               public C this [A key1, B key2]
+               {
+                       get
+                       {
+                               IImmutableMap<B, C> inner = this.map [key1];
+                               if (inner == null)
+                                       return default(C);
+                               return inner [key2];
+                       }
+               }
+
+               public int Keys1Count
+               {
+                       get { return this.map.Count; }
+               }
+
+               public IEnumerable<A> Keys1
+               {
+                       get { return this.map.Keys; }
+               }
+
+               public DoubleImmutableMap<A, B, C> Add (A key1, B key2, C value)
+               {
+                       IImmutableMap<B, C> immutableMap = this.map [key1] ?? ImmutableMap<B, C>.Empty;
+                       return new DoubleImmutableMap<A, B, C> (this.map.Add (key1, immutableMap.Add (key2, value)));
+               }
+
+               public DoubleImmutableMap<A, B, C> RemoveAll (A key1)
+               {
+                       return new DoubleImmutableMap<A, B, C> (this.map.Remove (key1));
+               }
+
+               public DoubleImmutableMap<A, B, C> Remove (A key1, B key2)
+               {
+                       IImmutableMap<B, C> inner = this.map [key1];
+                       if (inner == null)
+                               return this;
+                       IImmutableMap<B, C> newInner = inner.Remove (key2);
+                       if (newInner == inner)
+                               return this;
+                       return new DoubleImmutableMap<A, B, C> (this.map.Add (key1, newInner));
+               }
+
+               public static DoubleImmutableMap<A, B, C> Empty (Func<A, int> uniqueIdGenerator)
+               {
+                       return new DoubleImmutableMap<A, B, C> (ImmutableIntKeyMap<A, IImmutableMap<B, C>>.Empty (uniqueIdGenerator));
+               }
+
+               public bool Contains (A key1, B key2)
+               {
+                       IImmutableMap<B, C> inner = this.map [key1];
+                       if (inner == null)
+                               return false;
+                       return inner.ContainsKey (key2);
+               }
+
+               public bool ContainsKey1 (A key1)
+               {
+                       return this.map.ContainsKey (key1);
+               }
+
+               public int Keys2Count (A key1)
+               {
+                       if (key1 == null)
+                               return 0;
+                       IImmutableMap<B, C> inner = this.map [key1];
+                       if (inner == null)
+                               return 0;
+                       return inner.Count;
+               }
+
+               public IEnumerable<B> Keys2 (A key1)
+               {
+                       if (key1 == null)
+                               return this.EmptyCache;
+
+                       IImmutableMap<B, C> inner = this.map [key1];
+                       if (inner == null)
+                               return this.EmptyCache;
+                       return inner.Keys;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Dummy.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Dummy.cs
new file mode 100644 (file)
index 0000000..815928d
--- /dev/null
@@ -0,0 +1,42 @@
+// 
+// Dummy.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;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       struct Dummy : IEquatable<Dummy> {
+               public static readonly Dummy Value = new Dummy ();
+
+               #region IEquatable<Dummy> Members
+               public bool Equals (Dummy other)
+               {
+                       return true;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/EdgeVisitor.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/EdgeVisitor.cs
new file mode 100644 (file)
index 0000000..139fcf4
--- /dev/null
@@ -0,0 +1,31 @@
+// 
+// EdgeVisitor.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.DataStructures {
+       delegate void EdgeVisitor<Node, Info> (Node source, Info info, Node target);
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/GraphWrapper.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/GraphWrapper.cs
new file mode 100644 (file)
index 0000000..1a27020
--- /dev/null
@@ -0,0 +1,55 @@
+// 
+// GraphWrapper.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 {
+       class GraphWrapper<Node, Info> : IGraph<Node, Info> {
+               private readonly IEnumerable<Node> nodes;
+               private readonly Func<Node, IEnumerable<Pair<Info, Node>>> successors;
+
+               public GraphWrapper (IEnumerable<Node> nodes, Func<Node, IEnumerable<Pair<Info, Node>>> successors)
+               {
+                       this.nodes = nodes;
+                       this.successors = successors;
+               }
+
+               #region Implementation of IGraph<Node,Info>
+               public IEnumerable<Node> Nodes
+               {
+                       get { return this.nodes; }
+               }
+
+               public IEnumerable<Pair<Info, Node>> Successors (Node node)
+               {
+                       return this.successors (node);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IGraph.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IGraph.cs
new file mode 100644 (file)
index 0000000..dc50c25
--- /dev/null
@@ -0,0 +1,36 @@
+// 
+// IGraph.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       interface IGraph<Node, EdgeInfo> {
+               IEnumerable<Node> Nodes { get; }
+               IEnumerable<Pair<EdgeInfo, Node>> Successors (Node node);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableIntMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableIntMap.cs
new file mode 100644 (file)
index 0000000..d4e0bb2
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// IImmutableIntMap.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 {
+       interface IImmutableIntMap<T> {
+               T this [int key] { get; }
+               T Any { get; }
+               IEnumerable<T> Values { get; }
+               IEnumerable<int> Keys { get; }
+               int Count { get; }
+               T Lookup (int key);
+               bool Contains (int key);
+               IImmutableIntMap<T> Add (int key, T value);
+               IImmutableIntMap<T> Remove (int key);
+               void Visit (Action<T> action);
+               void Visit (Action<int, T> action);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs
new file mode 100644 (file)
index 0000000..2be8d32
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+// IImmutableMap.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 {
+       interface IImmutableMap<K, V> {
+               V this [K key] { get; }
+
+               K AnyKey { get; }
+
+               IEnumerable<K> Keys { get; }
+               int Count { get; }
+               IImmutableMap<K, V> EmptyMap { get; }
+
+               IImmutableMap<K, V> Add (K key, V value);
+               IImmutableMap<K, V> Remove (K key);
+
+               bool ContainsKey (K key);
+               void Visit (Func<K, V, VisitStatus> func);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs
new file mode 100644 (file)
index 0000000..21873b8
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+// IImmutableSet.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.IO;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       interface IImmutableSet<T>
+               where T : IEquatable<T> {
+               T Any { get; }
+               int Count { get; }
+               IEnumerable<T> Elements { get; }
+               IImmutableSet<T> Add (T item);
+               IImmutableSet<T> Remove (T item);
+               bool Contains (T item);
+               bool IsContainedIn (IImmutableSet<T> that);
+               IImmutableSet<T> Intersect (IImmutableSet<T> that);
+               IImmutableSet<T> Union (IImmutableSet<T> that);
+               void Visit (Action<T> visitor);
+               void Dump (TextWriter tw);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IIndexable.cs
new file mode 100644 (file)
index 0000000..344344f
--- /dev/null
@@ -0,0 +1,34 @@
+// 
+// IIndexable.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.DataStructures {
+       interface IIndexable<T> {
+               int Count { get; }
+               T this [int index] { get; }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ITypedProperties.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ITypedProperties.cs
new file mode 100644 (file)
index 0000000..a4533d0
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// ITypedProperties.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.DataStructures {
+       internal interface ITypedProperties {
+               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/IWorkList.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/IWorkList.cs
new file mode 100644 (file)
index 0000000..877e80e
--- /dev/null
@@ -0,0 +1,35 @@
+// 
+// IWorkList.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.DataStructures {
+       interface IWorkList<T> {
+               bool Add (T o);
+               bool IsEmpty ();
+               T Pull ();
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs
new file mode 100644 (file)
index 0000000..6cbf596
--- /dev/null
@@ -0,0 +1,114 @@
+// 
+// ImmutableIntKeyMap.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.Linq;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       class ImmutableIntKeyMap<K, V> : IImmutableMap<K, V>, IEquatable<IImmutableMap<K, V>> {
+               private readonly IImmutableIntMap<Pair<K, V>> immutable_int_map;
+               private readonly Func<K, int> keyConverter;
+
+               private ImmutableIntKeyMap (IImmutableIntMap<Pair<K, V>> map, Func<K, int> converter)
+               {
+                       this.immutable_int_map = map;
+                       this.keyConverter = converter;
+               }
+
+               #region Implementation of IImmutableMap<K,V>
+               public V this [K key]
+               {
+                       get
+                       {
+                               Pair<K, V> pair = this.immutable_int_map [this.keyConverter (key)];
+                               if (pair != null)
+                                       return pair.Value;
+                               return default(V);
+                       }
+               }
+
+               public K AnyKey
+               {
+                       get { return Keys.First (); }
+               }
+
+               public IEnumerable<K> Keys
+               {
+                       get
+                       {
+                               var res = new List<K> ();
+                               this.immutable_int_map.Visit (data => res.Add (data.Key));
+                               return res;
+                       }
+               }
+
+               public int Count
+               {
+                       get { return this.immutable_int_map.Count; }
+               }
+
+               public IImmutableMap<K, V> EmptyMap
+               {
+                       get { return Empty (this.keyConverter); }
+               }
+
+               public IImmutableMap<K, V> Add (K key, V value)
+               {
+                       return new ImmutableIntKeyMap<K, V> (this.immutable_int_map.Add (this.keyConverter (key), new Pair<K, V> (key, value)), this.keyConverter);
+               }
+
+               public IImmutableMap<K, V> Remove (K key)
+               {
+                       return new ImmutableIntKeyMap<K, V> (this.immutable_int_map.Remove (this.keyConverter (key)), this.keyConverter);
+               }
+
+               public bool ContainsKey (K key)
+               {
+                       return this.immutable_int_map.Contains (this.keyConverter (key));
+               }
+
+               public void Visit (Func<K, V, VisitStatus> func)
+               {
+                       this.immutable_int_map.Visit (data => func (data.Key, data.Value));
+               }
+               #endregion
+
+               #region Implementation of IEquatable<IImmutableMap<K,V>>
+               public bool Equals (IImmutableMap<K, V> other)
+               {
+                       return this == other;
+               }
+               #endregion
+
+               public static IImmutableMap<K, V> Empty (Func<K, int> keyConverter)
+               {
+                       return new ImmutableIntKeyMap<K, V> (ImmutableIntMap<Pair<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
new file mode 100644 (file)
index 0000000..39bb01c
--- /dev/null
@@ -0,0 +1,146 @@
+// 
+// ImmutableIntMap.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.Linq;
+
+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);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableMap.cs
new file mode 100644 (file)
index 0000000..7b62009
--- /dev/null
@@ -0,0 +1,143 @@
+// 
+// ImmutableMap.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.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);
+               private readonly int count;
+               private readonly IImmutableIntMap<LispList<Pair<K, V>>> immutable_int_map;
+               private readonly LispList<K> keys;
+
+               private ImmutableMap (IImmutableIntMap<LispList<Pair<K, V>>> map, int count, LispList<K> keys)
+               {
+                       this.keys = keys;
+                       this.count = count;
+                       this.immutable_int_map = map;
+               }
+
+               #region Implementation of IImmutableMap<K,V>
+               public V this [K key]
+               {
+                       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);
+                       }
+               }
+
+               public K AnyKey
+               {
+                       get { return this.keys.Head; }
+               }
+
+               public IEnumerable<K> Keys
+               {
+                       get { return this.keys.AsEnumerable (); }
+               }
+
+               public int Count
+               {
+                       get { return this.immutable_int_map.Count; }
+               }
+
+               public IImmutableMap<K, V> EmptyMap
+               {
+                       get { return Empty; }
+               }
+
+               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);
+
+                       return new ImmutableMap<K, V> (this.immutable_int_map.Add (hashCode, newList), this.count + diff, newKeys);
+               }
+
+               public IImmutableMap<K, V> Remove (K key)
+               {
+                       int hashCode = key.GetHashCode ();
+                       LispList<Pair<K, V>> from = this.immutable_int_map [hashCode];
+                       if (from == null)
+                               return this;
+                       LispList<Pair<K, V>> newList = Remove (from, key);
+                       if (newList == from)
+                               return this;
+                       LispList<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);
+               }
+
+               public bool ContainsKey (K key)
+               {
+                       return this.immutable_int_map [key.GetHashCode ()].AsEnumerable ().Any (pair => key.Equals (pair.Key));
+               }
+
+               public void Visit (Func<K, V, VisitStatus> func)
+               {
+                       this.immutable_int_map.Visit (list => {
+                                                       foreach (var pair in list.AsEnumerable ())
+                                                               func (pair.Key, pair.Value);
+                                                     });
+               }
+
+               private LispList<Pair<K, V>> Remove (LispList<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);
+                       return tail == from.Tail ? from : tail.Cons (from.Head);
+               }
+
+               private static LispList<K> RemoveKey (K key, LispList<K> keys)
+               {
+                       if (keys == null)
+                               throw new InvalidOperationException ();
+
+                       if (key.Equals (keys.Head))
+                               return keys.Tail;
+
+                       return RemoveKey (key, keys.Tail).Cons (keys.Head);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSet.cs
new file mode 100644 (file)
index 0000000..cc385da
--- /dev/null
@@ -0,0 +1,169 @@
+// 
+// ImmutableSet.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.IO;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       class ImmutableSet<T> : IImmutableSet<T>
+               where T : IEquatable<T> {
+               private readonly IImmutableMap<T, Dummy> underlying;
+
+               public ImmutableSet (IImmutableMap<T, Dummy> immutableMap)
+               {
+                       this.underlying = immutableMap;
+               }
+
+               #region Implementation of IImmutableSet<T>
+               public T Any
+               {
+                       get { return this.underlying.AnyKey; }
+               }
+
+               public int Count
+               {
+                       get { return this.underlying.Count; }
+               }
+
+               public IEnumerable<T> Elements
+               {
+                       get { return this.underlying.Keys; }
+               }
+
+               public IImmutableSet<T> Add (T item)
+               {
+                       return new ImmutableSet<T> (this.underlying.Add (item, Dummy.Value));
+               }
+
+               public IImmutableSet<T> Remove (T item)
+               {
+                       return new ImmutableSet<T> (this.underlying.Remove (item));
+               }
+
+               public bool Contains (T item)
+               {
+                       return this.underlying.ContainsKey (item);
+               }
+
+               public bool IsContainedIn (IImmutableSet<T> that)
+               {
+                       if (Count > that.Count)
+                               return false;
+                       bool result = true;
+                       this.underlying.Visit ((e, dummy) => {
+                                               if (that.Contains (e))
+                                                       return VisitStatus.ContinueVisit;
+
+                                               result = false;
+                                               return VisitStatus.StopVisit;
+                                              });
+                       return result;
+               }
+
+               public IImmutableSet<T> Intersect (IImmutableSet<T> that)
+               {
+                       if (this == that)
+                               return this;
+                       if (Count == 0)
+                               return this;
+                       IImmutableSet<T> set;
+                       IImmutableSet<T> larger;
+                       if (Count < that.Count) {
+                               set = this;
+                               larger = that;
+                       } else {
+                               if (that.Count == 0)
+                                       return that;
+                               set = that;
+                               larger = this;
+                       }
+                       IImmutableSet<T> result = set;
+                       set.Visit ((e) => {
+                                       if (!larger.Contains (e))
+                                               result = result.Remove (e);
+                                  });
+                       return result;
+               }
+
+               public IImmutableSet<T> Union (IImmutableSet<T> that)
+               {
+                       if (this == that)
+                               return this;
+                       if (Count == 0)
+                               return that;
+                       IImmutableSet<T> smaller;
+                       IImmutableSet<T> larger;
+                       if (Count < that.Count) {
+                               smaller = this;
+                               larger = that;
+                       } else {
+                               if (that.Count == 0)
+                                       return this;
+                               smaller = that;
+                               larger = this;
+                       }
+                       IImmutableSet<T> result = larger;
+                       smaller.Visit (e => { result = result.Add (e); });
+                       return result;
+               }
+
+               public void Visit (Action<T> visitor)
+               {
+                       this.underlying.Visit ((elem, dummy) => {
+                                               visitor (elem);
+                                               return VisitStatus.ContinueVisit;
+                                              });
+               }
+
+               public void Dump (TextWriter tw)
+               {
+                       tw.Write ("{");
+                       bool first = true;
+                       foreach (T key in this.underlying.Keys) {
+                               if (!first)
+                                       tw.Write (", ");
+                               else
+                                       first = false;
+                               tw.Write ("{0}", key);
+                       }
+                       tw.WriteLine ("}");
+               }
+
+               public static IImmutableSet<T> Empty ()
+               {
+                       return new ImmutableSet<T> (ImmutableMap<T, Dummy>.Empty);
+               }
+
+               public static IImmutableSet<T> Empty (Func<T, int> keyConverter)
+               {
+                       return new ImmutableSet<T> (ImmutableIntKeyMap<T, Dummy>.Empty (keyConverter));
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSetExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/ImmutableSetExtensions.cs
new file mode 100644 (file)
index 0000000..2be16ee
--- /dev/null
@@ -0,0 +1,51 @@
+// 
+// ImmutableSetExtensions.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;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       static class ImmutableSetExtensions {
+               public static bool ContainsSafe<T> (this IImmutableSet<T> set, T value)
+                       where T : IEquatable<T>
+               {
+                       if (set == null || value == null)
+                               return false;
+
+                       return set.Contains (value);
+               }
+
+               public static int Count<T> (this IImmutableSet<T> set)
+                       where T : IEquatable<T>
+               {
+                       if (set == null)
+                               return 0;
+
+                       return set.Count;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Indexable.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Indexable.cs
new file mode 100644 (file)
index 0000000..87530da
--- /dev/null
@@ -0,0 +1,54 @@
+// 
+// Indexable.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       class Indexable<T> : IIndexable<T> {
+               public static Indexable<T> Empty = new Indexable<T> (null);
+
+               private readonly IList<T> list;
+
+               public Indexable (IList<T> parameters)
+               {
+                       this.list = parameters;
+               }
+
+               #region IIndexable<T> Members
+               public int Count
+               {
+                       get { return this.list == null ? 0 : this.list.Count; }
+               }
+
+               public T this [int index]
+               {
+                       get { return this.list [index]; }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispList.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/LispList.cs
new file mode 100644 (file)
index 0000000..9e5d228
--- /dev/null
@@ -0,0 +1,131 @@
+// 
+// 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
new file mode 100644 (file)
index 0000000..52c5f0c
--- /dev/null
@@ -0,0 +1,116 @@
+// 
+// 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/Optional.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Optional.cs
new file mode 100644 (file)
index 0000000..d96adab
--- /dev/null
@@ -0,0 +1,46 @@
+// 
+// Optional.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.DataStructures {
+       struct Optional<T> {
+               public readonly bool IsValid;
+
+               public Optional (T value) : this ()
+               {
+                       Value = value;
+                       this.IsValid = true;
+               }
+
+               public T Value { get; private set; }
+
+               public static implicit operator Optional<T> (T value)
+               {
+                       return new Optional<T> (value);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/Pair.cs
new file mode 100644 (file)
index 0000000..52a8b34
--- /dev/null
@@ -0,0 +1,71 @@
+// 
+// Pair.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;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       class Pair<K, V> : IEquatable<Pair<K, V>> {
+               private static readonly bool KeyIsReferenceType = default(K) == null;
+               private static readonly bool ValueIsReferenceType = default(V) == null;
+
+               public readonly K Key;
+               public readonly V Value;
+
+               public Pair (K key, V value)
+               {
+                       this.Key = key;
+                       this.Value = value;
+               }
+
+               #region IEquatable<Pair<K,V>> Members
+               public bool Equals (Pair<K, V> other)
+               {
+                       var keyEquatable = ((object) this.Key) as IEquatable<K>;
+                       bool keysAreEqual = keyEquatable != null ? keyEquatable.Equals (other.Key) : Equals (this.Key, other.Key);
+                       if (!keysAreEqual)
+                               return false;
+
+                       var valueEquatable = ((object) this.Value) as IEquatable<V>;
+                       return valueEquatable != null ? valueEquatable.Equals (other.Value) : Equals (this.Value, other.Value);
+               }
+               #endregion
+
+               public override int GetHashCode ()
+               {
+                       return (!KeyIsReferenceType || ((object) this.Key) != null ? this.Key.GetHashCode () : 0)
+                              + 13*(!ValueIsReferenceType || ((object) this.Value) != null ? this.Value.GetHashCode () : 0);
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("({0}, {1})",
+                                             (!KeyIsReferenceType || ((object) this.Key) != null) ? this.Key.ToString () : "<null>",
+                                             (!ValueIsReferenceType || ((object) this.Value) != null) ? this.Value.ToString () : "<null>");
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/PriorityQueue.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/PriorityQueue.cs
new file mode 100644 (file)
index 0000000..146f6b4
--- /dev/null
@@ -0,0 +1,110 @@
+// 
+// PriorityQueue.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 {
+       class PriorityQueue<T> {
+               private readonly Comparison<T> comparison;
+               private readonly List<T> values;
+
+               public PriorityQueue (Comparison<T> compare)
+               {
+                       this.comparison = compare;
+                       this.values = new List<T> ();
+                       this.values.Add (default(T)); //fake cell for start from 1
+               }
+
+               public int Count
+               {
+                       get { return this.values.Count - 1; }
+               }
+
+               public T Peek ()
+               {
+                       if (Count == 0)
+                               return default(T);
+
+                       return this.values [1];
+               }
+
+               public T Dequeue ()
+               {
+                       if (Count == 0)
+                               return default(T);
+
+                       T res = this.values [1];
+                       this.values [1] = this.values [this.values.Count - 1];
+                       this.values.RemoveAt (this.values.Count - 1);
+
+                       BubbleDown (1);
+
+                       return res;
+               }
+
+               public void Enqueue (T item)
+               {
+                       this.values.Add (item);
+                       BubbleUp (this.values.Count - 1);
+               }
+
+               private void BubbleDown (int i)
+               {
+                       int l = i << 1;
+                       int r = (i << 1) + 1;
+
+                       int min = i;
+                       if (l < this.values.Count && this.comparison (this.values [l], this.values [i]) < 0)
+                               min = l;
+                       if (r < this.values.Count && this.comparison (this.values [r], this.values [min]) < 0)
+                               min = r;
+
+                       if (min != i) {
+                               T tmp = this.values [min];
+                               this.values [min] = this.values [i];
+                               this.values [i] = tmp;
+                               BubbleDown (min);
+                       }
+               }
+
+               private void BubbleUp (int i)
+               {
+                       int c = i;
+
+                       while (c/2 != 0 &&
+                              this.comparison (this.values [c >> 1], this.values [c]) > 0) {
+                               T tmp = this.values [c >> 1];
+                               this.values [c >> 1] = this.values [c];
+                               this.values [c] = tmp;
+
+                               c >>= 1;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedKey.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedKey.cs
new file mode 100644 (file)
index 0000000..d91b920
--- /dev/null
@@ -0,0 +1,57 @@
+// 
+// TypedKey.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.DataStructures {
+       struct TypedKey {
+               private readonly string key;
+
+               public TypedKey (string key)
+               {
+                       this.key = key;
+               }
+
+               public bool Equals (TypedKey other)
+               {
+                       return Equals (other.key, this.key);
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (ReferenceEquals (null, obj))
+                               return false;
+                       if (obj.GetType () != typeof (TypedKey))
+                               return false;
+                       return Equals ((TypedKey) obj);
+               }
+
+               public override int GetHashCode ()
+               {
+                       return (this.key != null ? this.key.GetHashCode () : 0);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedProperties.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/TypedProperties.cs
new file mode 100644 (file)
index 0000000..7e4f2da
--- /dev/null
@@ -0,0 +1,60 @@
+// 
+// TypedProperties.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.Collections.Generic;
+
+namespace Mono.CodeContracts.Static.DataStructures {
+       class TypedProperties : ITypedProperties {
+               private readonly Dictionary<object, object> dictionary = new Dictionary<object, object> ();
+
+               #region Implementation of ITypedProperties
+               public bool Contains (TypedKey key)
+               {
+                       return this.dictionary.ContainsKey (key);
+               }
+
+               public void Add<T> (TypedKey key, T value)
+               {
+                       this.dictionary.Add (key, value);
+               }
+
+               public bool TryGetValue<T> (TypedKey key, out T value)
+               {
+                       object result;
+
+                       if (!this.dictionary.TryGetValue (key, out result)) {
+                               value = default(T);
+                               return false;
+                       }
+
+                       value = (T) result;
+                       return true;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/VisitStatus.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/VisitStatus.cs
new file mode 100644 (file)
index 0000000..1062364
--- /dev/null
@@ -0,0 +1,34 @@
+// 
+// VisitStatus.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.DataStructures {
+       enum VisitStatus {
+               ContinueVisit,
+               StopVisit
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/WorkList.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.DataStructures/WorkList.cs
new file mode 100644 (file)
index 0000000..77a4ccd
--- /dev/null
@@ -0,0 +1,61 @@
+// 
+// WorkList.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 {
+       sealed class WorkList<T> : AbstractWorkList<T> {
+               private readonly Queue<T> queue;
+
+               public WorkList ()
+               {
+                       this.queue = new Queue<T> ();
+               }
+
+               #region Overrides of AbstractWorkList<T>
+               protected override IEnumerable<T> Collection
+               {
+                       get { return this.queue; }
+               }
+
+               protected override void AddToCollection (T o)
+               {
+                       this.queue.Enqueue (o);
+               }
+
+               public override T Pull ()
+               {
+                       if (this.queue.Count == 0)
+                               throw new InvalidOperationException ();
+                       T a = this.queue.Dequeue ();
+                       this.Elements.Remove (a);
+                       return a;
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Extensions/Extensions.cs
new file mode 100644 (file)
index 0000000..90da17f
--- /dev/null
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.CodeContracts.Static.Extensions {
+       static class Extensions {
+               public static string ToString<T>(this IEnumerable<T> values, string separator)
+               {
+                       return string.Join (separator, values.Select (v => v.ToString ()));
+               }
+       }
+}
\ 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
new file mode 100644 (file)
index 0000000..555753b
--- /dev/null
@@ -0,0 +1,221 @@
+// 
+// EnvironmentDomain.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.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);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/FlatDomain.cs
new file mode 100644 (file)
index 0000000..6e7417c
--- /dev/null
@@ -0,0 +1,196 @@
+// 
+// FlatDomain.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.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
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs
new file mode 100644 (file)
index 0000000..9825cb6
--- /dev/null
@@ -0,0 +1,80 @@
+// 
+// IAbstractDomain.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.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 empty set (which holds nothing)
+               /// </summary>
+               T Bottom { get; }
+
+               /// <summary>
+               /// Is this value a universe set
+               /// </summary>
+               bool IsTop { 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 an intersection of this and that
+               /// </summary>
+               /// <param name="that"></param>
+               /// <returns></returns>
+               T Meet (T that);
+
+               bool LessEqual (T that);
+
+               T ImmutableVersion ();
+               T Clone ();
+
+               void Dump (TextWriter tw);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Lattices/SetDomain.cs
new file mode 100644 (file)
index 0000000..95c389a
--- /dev/null
@@ -0,0 +1,157 @@
+// 
+// SetDomain.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.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);
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeContractDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeContractDecoder.cs
new file mode 100644 (file)
index 0000000..a0bd3d1
--- /dev/null
@@ -0,0 +1,86 @@
+// 
+// CodeContractDecoder.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+
+namespace Mono.CodeContracts.Static.Providers {
+       class CodeContractDecoder : IContractProvider {
+               public static readonly CodeContractDecoder Instance = new CodeContractDecoder ();
+
+               #region IContractProvider Members
+               public bool VerifyMethod (Method method, bool analyzeNonUserCode)
+               {
+                       //todo: implement this
+                       return true;
+               }
+
+               public bool HasRequires (Method method)
+               {
+                       method = GetMethodWithContractFor (method);
+                       if (method.MethodContract == null)
+                               return false;
+
+                       return method.MethodContract.RequiresCount > 0;
+               }
+
+               public Result AccessRequires<Data, Result> (Method method,
+                                                           ICodeConsumer<Data, Result> consumer, Data data)
+               {
+                       method = GetMethodWithContractFor (method);
+                       return consumer.Accept (CodeProviderImpl.Instance, new CodeProviderImpl.PC (method.MethodContract, 0), data);
+               }
+
+               public bool HasEnsures (Method method)
+               {
+                       method = GetMethodWithContractFor (method);
+                       if (method.MethodContract == null)
+                               return false;
+
+                       return method.MethodContract.EnsuresCount > 0;
+               }
+
+               public Result AccessEnsures<Data, Result> (Method method, ICodeConsumer<Data, Result> consumer, Data data)
+               {
+                       method = GetMethodWithContractFor (method);
+                       return consumer.Accept (CodeProviderImpl.Instance, new CodeProviderImpl.PC (method.MethodContract, method.MethodContract.RequiresCount + 2), data);
+               }
+
+               public bool CanInheritContracts (Method method)
+               {
+                       return false;
+               }
+               #endregion
+
+               private Method GetMethodWithContractFor (Method method)
+               {
+                       //todo: implement this
+                       return method;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs
new file mode 100644 (file)
index 0000000..cce8d55
--- /dev/null
@@ -0,0 +1,543 @@
+// 
+// CodeProviderImpl.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.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Providers {
+       class CodeProviderImpl : IMethodCodeProvider<CodeProviderImpl.PC, ExceptionHandler> {
+               public static readonly CodeProviderImpl Instance = new CodeProviderImpl ();
+
+               #region IMethodCodeProvider<PC,ExceptionHandler> Members
+               public Result Decode<Visitor, Data, Result> (PC pc, Visitor visitor, Data data)
+                       where Visitor : IAggregateVisitor<PC, Data, Result>
+               {
+                       Node nested;
+                       Node node = Decode (pc, out nested);
+                       if (IsAtomicNested (nested))
+                               node = nested;
+                       else if (nested != null)
+                               return visitor.Aggregate (pc, new PC (nested), nested is Block, data);
+
+                       if (node == null)
+                               return visitor.Nop (pc, data);
+
+                       switch (node.NodeType) {
+                       case NodeType.Block:
+                       case NodeType.Nop:
+                               return visitor.Nop (pc, data);
+                       case NodeType.Clt:
+                       case NodeType.Lt:
+                               return visitor.Binary (pc, BinaryOperator.Clt, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Cgt:
+                       case NodeType.Gt:
+                               return visitor.Binary (pc, BinaryOperator.Cgt, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Ceq:
+                       case NodeType.Eq:
+                               return visitor.Binary (pc, BinaryOperator.Ceq, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Ne:
+                               return visitor.Binary (pc, BinaryOperator.Cne_Un, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Ge:
+                               return visitor.Binary (pc, BinaryOperator.Cge, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Le:
+                               return visitor.Binary (pc, BinaryOperator.Cle, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Add:
+                               return visitor.Binary (pc, BinaryOperator.Add, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Sub:
+                               return visitor.Binary (pc, BinaryOperator.Sub, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Rem:
+                               return visitor.Binary (pc, BinaryOperator.Rem, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Rem_Un:
+                               return visitor.Binary (pc, BinaryOperator.Rem_Un, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Mul:
+                               return visitor.Binary (pc, BinaryOperator.Mul, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Div:
+                               return visitor.Binary (pc, BinaryOperator.Div, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Div_Un:
+                               return visitor.Binary (pc, BinaryOperator.Div_Un, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.And:
+                               return visitor.Binary (pc, BinaryOperator.And, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Or:
+                               return visitor.Binary (pc, BinaryOperator.Or, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Shr:
+                               return visitor.Binary (pc, BinaryOperator.Shr, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Xor:
+                               return visitor.Binary (pc, BinaryOperator.Xor, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Shl:
+                               return visitor.Binary (pc, BinaryOperator.Shl, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Shr_Un:
+                               return visitor.Binary (pc, BinaryOperator.Shr_Un, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Literal:
+                               var literal = (Literal) node;
+                               if (literal.Value == null)
+                                       return visitor.LoadNull (pc, Dummy.Value, data);
+                               if (literal.Type == CoreSystemTypes.Instance.TypeBoolean && (bool) literal.Value)
+                                       return visitor.LoadConst (pc, CoreSystemTypes.Instance.TypeInt32, 1, Dummy.Value, data);
+
+                               return visitor.LoadConst (pc, literal.Type, literal.Value, Dummy.Value, data);
+                       case NodeType.This:
+                       case NodeType.Parameter:
+                               return visitor.LoadArg (pc, (Parameter) node, false, Dummy.Value, data);
+                       case NodeType.Local:
+                               return visitor.LoadLocal (pc, (Local) node, Dummy.Value, data);
+                       case NodeType.Branch:
+                               var branch = (Branch) node;
+                               if (branch.Condition != null)
+                                       return visitor.BranchTrue (pc, new PC (branch.Target), Dummy.Value, data);
+                               return visitor.Branch (pc, new PC (branch.Target), branch.LeavesExceptionBlock, data);
+                       case NodeType.ExpressionStatement:
+                               break;
+                       case NodeType.Box:
+                               break;
+                       case NodeType.Return:
+                               return visitor.Return (pc, Dummy.Value, data);
+                       case NodeType.Neg:
+                               return visitor.Unary (pc, UnaryOperator.Neg, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Not:
+                       case NodeType.LogicalNot:
+                               return visitor.Unary (pc, UnaryOperator.Not, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Conv:
+                               break;
+                       case NodeType.Conv_I1:
+                               return visitor.Unary (pc, UnaryOperator.Conv_i1, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Conv_I2:
+                               return visitor.Unary (pc, UnaryOperator.Conv_i2, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Conv_I4:
+                               return visitor.Unary (pc, UnaryOperator.Conv_i4, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Conv_I8:
+                               return visitor.Unary (pc, UnaryOperator.Conv_i8, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Conv_R4:
+                               return visitor.Unary (pc, UnaryOperator.Conv_r4, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.Conv_R8:
+                               return visitor.Unary (pc, UnaryOperator.Conv_r8, false, Dummy.Value, Dummy.Value, data);
+                       case NodeType.MethodContract:
+                               return visitor.Nop (pc, data);
+                       case NodeType.Requires:
+                               return visitor.Assume (pc, EdgeTag.Requires, Dummy.Value, data);
+                       case NodeType.Call:
+                               var call = (MethodCall) node;
+                               Method method = GetMethodFrom (call.Callee);
+                               if (method.HasGenericParameters)
+                                       throw new NotImplementedException ();
+                               if (method.Name != null && method.DeclaringType.Name != null && method.DeclaringType.Name.EndsWith ("Contract")) {
+                                       switch (method.Name) {
+                                       case "Assume":
+                                               if (method.Parameters.Count == 1)
+                                                       return visitor.Assume (pc, EdgeTag.Assume, Dummy.Value, data);
+                                               break;
+                                       case "Assert":
+                                               if (method.Parameters.Count == 1)
+                                                       return visitor.Assert (pc, EdgeTag.Assert, Dummy.Value, data);
+                                               break;
+                                       }
+                               }
+                               Indexable<Dummy> parameters = DummyIndexable (method);
+                               return visitor.Call (pc, method, false, GetVarargs (call, method), Dummy.Value, parameters, data);
+
+                       case NodeType.AssignmentStatement:
+                               var assign = ((AssignmentStatement) node);
+                               var local = assign.Target as Local;
+                               if (local != null)
+                                       return visitor.StoreLocal (pc, local, Dummy.Value, data);
+                               var parameter = assign.Target as Parameter;
+                               if (parameter != null)
+                                       return visitor.StoreArg (pc, parameter, Dummy.Value, data);
+
+                               var binding = assign.Target as MemberBinding;
+                               if (binding != null) {
+                                       if (binding.BoundMember.IsStatic)
+                                               return visitor.StoreStaticField (pc, (Field) binding.BoundMember, Dummy.Value, data);
+                                       else
+                                               return visitor.StoreField (pc, (Field) binding.BoundMember, Dummy.Value, Dummy.Value, data);
+                               }
+
+                               throw new NotImplementedException ();
+                       case NodeType.Construct:
+                               Method ctor = GetMethodFrom (((Construct) node).Constructor);
+                               if (!(ctor.DeclaringType is ArrayTypeNode))
+                                       return visitor.NewObj (pc, ctor, Dummy.Value, DummyIndexable (ctor), data);
+                               var arrayType = (ArrayTypeNode) ctor.DeclaringType;
+                               return visitor.NewArray (pc, arrayType, Dummy.Value, DummyIndexable (ctor), data);
+                       default:
+                               return visitor.Nop (pc, data);
+                       }
+
+                       throw new NotImplementedException ();
+               }
+
+               public bool Next (PC pc, out PC nextLabel)
+               {
+                       Node nested;
+                       if (Decode (pc, out nested) == null && pc.Node != null) {
+                               nextLabel = new PC (pc.Node, pc.Index + 1);
+                               return true;
+                       }
+                       nextLabel = new PC ();
+                       return false;
+               }
+
+               public int GetILOffset (PC current)
+               {
+                       throw new NotImplementedException ();
+               }
+               #endregion
+
+               private static Indexable<Dummy> DummyIndexable (Method method)
+               {
+                       return new Indexable<Dummy> (Enumerable.Range (0, method.Parameters.Count).Select (it => Dummy.Value).ToList ());
+               }
+
+               private static Indexable<TypeNode> GetVarargs (MethodCall call, Method method)
+               {
+                       int methodCount = method.Parameters.Count;
+                       int callCount = call.Arguments.Count;
+
+                       if (callCount <= methodCount)
+                               return new Indexable<TypeNode> (null);
+
+                       var array = new TypeNode[callCount - methodCount];
+                       for (int i = methodCount; i < callCount; i++)
+                               array [i - methodCount] = call.Arguments [i - methodCount].Type;
+
+                       return new Indexable<TypeNode> (array);
+               }
+
+               private Method GetMethodFrom (Expression callee)
+               {
+                       return (Method) ((MemberBinding) callee).BoundMember;
+               }
+
+               private static bool IsAtomicNested (Node nested)
+               {
+                       if (nested == null)
+                               return false;
+                       switch (nested.NodeType) {
+                       case NodeType.Local:
+                       case NodeType.Parameter:
+                       case NodeType.Literal:
+                       case NodeType.This:
+                               return true;
+                       default:
+                               return false;
+                       }
+               }
+
+               private Node Decode (PC pc, out Node nested)
+               {
+                       Node node = DecodeInflate (pc, out nested);
+
+                       return node;
+               }
+
+               /// <summary>
+               /// Decodes pc
+               /// </summary>
+               /// <param name="pc"></param>
+               /// <param name="nested"></param>
+               /// <returns>If node has nested, returns null and (nested = child). If last child given, node equals pc.Node</returns>
+               private static Node DecodeInflate (PC pc, out Node nested)
+               {
+                       Node node = pc.Node;
+                       if (node == null) {
+                               nested = null;
+                               return null;
+                       }
+
+                       int index = pc.Index;
+                       switch (node.NodeType) {
+                       case NodeType.MethodContract:
+                               var methodContract = (MethodContract) node;
+                               if (index < methodContract.RequiresCount) {
+                                       nested = methodContract.Requires [index];
+                                       return null;
+                               }
+                               if (index == methodContract.RequiresCount) {
+                                       nested = null;
+                                       return methodContract;
+                               }
+
+                               //todo: aggregate ensures
+                               nested = null;
+                               return methodContract;
+
+                       case NodeType.Requires:
+                               var requires = (Requires) node;
+                               if (index == 0) {
+                                       nested = requires.Assertion;
+                                       return null;
+                               }
+                               nested = null;
+                               return requires;
+                       case NodeType.Block:
+                               var block = (Block) node;
+                               if (block.Statements == null) {
+                                       nested = null;
+                                       return block;
+                               }
+                               nested = index >= block.Statements.Count ? null : block.Statements [index];
+                               return index + 1 < block.Statements.Count ? null : block;
+                       case NodeType.Return:
+                               var ret = (Return) node;
+                               if (ret.Expression != null && index == 0) {
+                                       nested = ret.Expression;
+                                       return null;
+                               }
+                               nested = null;
+                               return ret;
+                       case NodeType.AssignmentStatement:
+                               var assign = (AssignmentStatement) node;
+                               int innerIndex = index;
+                               {
+                                       var bind = assign.Target as MemberBinding;
+                                       if (bind != null) {
+                                               ++innerIndex;
+                                               if (bind.BoundMember.IsStatic)
+                                                       ++innerIndex;
+                                               if (innerIndex == 1) {
+                                                       nested = bind.TargetObject;
+                                                       return null;
+                                               }
+                                       } else if (assign.Target is Variable)
+                                               innerIndex += 2;
+                                       else {
+                                               nested = null;
+                                               return assign;
+                                       }
+                               }
+                               if (innerIndex == 2) {
+                                       nested = assign.Source;
+                                       return null;
+                               }
+
+                               nested = null;
+                               return assign;
+                       case NodeType.ExpressionStatement:
+                               var expressionStatement = (ExpressionStatement) node;
+                               nested = expressionStatement.Expression;
+                               return expressionStatement;
+                       case NodeType.MethodCall:
+                       case NodeType.Call:
+                       case NodeType.Calli:
+                       case NodeType.CallVirt:
+                               var methodCall = (MethodCall) node;
+                               var binding = (MemberBinding) methodCall.Callee;
+                               if (binding.BoundMember.IsStatic) {
+                                       if (index < methodCall.Arguments.Count) {
+                                               nested = methodCall.Arguments [index];
+                                               return null;
+                                       }
+
+                                       nested = null;
+                                       return methodCall;
+                               }
+
+                               if (index == 0) {
+                                       nested = binding.TargetObject;
+                                       return null;
+                               }
+                               if (index < methodCall.Arguments.Count + 1) {
+                                       nested = methodCall.Arguments [index - 1];
+                                       return null;
+                               }
+                               nested = null;
+                               return methodCall;
+                       case NodeType.MemberBinding:
+                               var bind1 = ((MemberBinding) node);
+                               if (index == 0 && !bind1.BoundMember.IsStatic) {
+                                       nested = bind1.TargetObject;
+                                       return null;
+                               }
+                               nested = null;
+                               return bind1;
+                       case NodeType.Construct:
+                               var construct = (Construct) node;
+                               if (index < construct.Arguments.Count) {
+                                       nested = construct.Arguments [index];
+                                       return null;
+                               }
+                               nested = null;
+                               return construct;
+                       case NodeType.Branch:
+                               var branch = ((Branch) node);
+                               if (branch.Condition != null && index == 0) {
+                                       nested = branch.Condition;
+                                       return null;
+                               }
+                               nested = null;
+                               return branch;
+                       default:
+                               var binary = node as BinaryExpression;
+                               if (binary != null) {
+                                       if (index == 0) {
+                                               nested = binary.Operand1;
+                                               return null;
+                                       }
+                                       if (index == 1) {
+                                               nested = binary.Operand2;
+                                               return null;
+                                       }
+                                       nested = null;
+                                       return binary;
+                               }
+
+                               var unary = node as UnaryExpression;
+                               if (unary != null) {
+                                       if (index == 0) {
+                                               nested = unary.Operand;
+                                               return null;
+                                       }
+
+                                       nested = null;
+                                       return unary;
+                               }
+
+                               //todo: ternary
+                               nested = null;
+                               return node;
+                       }
+               }
+
+               public PC Entry (Method method)
+               {
+                       return new PC (method.Body);
+               }
+
+               #region Implementation of IMethodCodeProvider<PC,Local,Parameter,Method,FieldReference,TypeReference,Dummy>
+               public bool IsFaultHandler (ExceptionHandler handler)
+               {
+                       return handler.HandlerType == NodeType.FaultHandler;
+               }
+
+               public bool IsFilterHandler (ExceptionHandler handler)
+               {
+                       return handler.HandlerType == NodeType.Filter;
+               }
+
+               public bool IsFinallyHandler (ExceptionHandler handler)
+               {
+                       return handler.HandlerType == NodeType.Finally;
+               }
+
+               public PC FilterExpressionStart (ExceptionHandler handler)
+               {
+                       return new PC (handler.FilterExpression);
+               }
+
+               public PC HandlerEnd (ExceptionHandler handler)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public PC HandlerStart (ExceptionHandler handler)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public PC TryStart (ExceptionHandler handler)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public PC TryEnd (ExceptionHandler handler)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public bool IsCatchHandler (ExceptionHandler handler)
+               {
+                       return handler.HandlerType == NodeType.Catch;
+               }
+
+               public TypeNode CatchType (ExceptionHandler handler)
+               {
+                       return handler.FilterType;
+               }
+
+               public bool IsCatchAllHandler (ExceptionHandler handler)
+               {
+                       if (!IsCatchHandler (handler))
+                               return false;
+                       if (handler.FilterType != null)
+                               return false;
+
+                       return true;
+               }
+
+               public IEnumerable<ExceptionHandler> GetTryBlocks (Method method)
+               {
+                       yield break;
+               }
+               #endregion
+
+               #region Nested type: PC
+               public struct PC : IEquatable<PC> {
+                       public readonly int Index;
+                       public readonly Node Node;
+
+                       public PC (Node Node)
+                               : this (Node, 0)
+                       {
+                       }
+
+                       public PC (Node node, int index)
+                       {
+                               this.Node = node;
+                               this.Index = index;
+                       }
+
+                       #region IEquatable<PC> Members
+                       public bool Equals (PC other)
+                       {
+                               return Equals (other.Node, this.Node) && other.Index == this.Index;
+                       }
+                       #endregion
+
+                       public override bool Equals (object obj)
+                       {
+                               if (ReferenceEquals (null, obj))
+                                       return false;
+                               if (obj.GetType () != typeof (PC))
+                                       return false;
+                               return Equals ((PC) obj);
+                       }
+
+                       public override int GetHashCode ()
+                       {
+                               unchecked {
+                                       return ((this.Node != null ? this.Node.GetHashCode () : 0)*397) ^ this.Index;
+                               }
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/ICodeProvider.cs
new file mode 100644 (file)
index 0000000..186f85f
--- /dev/null
@@ -0,0 +1,11 @@
+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>;
+
+               bool Next (Label current, out Label nextLabel);
+               int GetILOffset (Label current);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IContractProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IContractProvider.cs
new file mode 100644 (file)
index 0000000..d2eee26
--- /dev/null
@@ -0,0 +1,44 @@
+// 
+// IContractProvider.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+
+namespace Mono.CodeContracts.Static.Providers {
+       interface IContractProvider {
+               bool VerifyMethod (Method method, bool analyzeNonUserCode);
+
+               bool HasRequires (Method method);
+               Result AccessRequires<Data, Result> (Method method, ICodeConsumer<Data, Result> consumer, Data data);
+
+               bool HasEnsures (Method method);
+               Result AccessEnsures<Data, Result> (Method method, ICodeConsumer<Data, Result> consumer, Data data);
+
+               bool CanInheritContracts (Method method);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IILDecoder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IILDecoder.cs
new file mode 100644 (file)
index 0000000..408623c
--- /dev/null
@@ -0,0 +1,41 @@
+// 
+// IILDecoder.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 Mono.CodeContracts.Static.AST.Visitors;
+
+namespace Mono.CodeContracts.Static.Providers {
+       interface IILDecoder<Label, Source, Dest, TContext, TEdgeData> {
+               TContext ContextProvider { get; }
+
+               Result ForwardDecode<Data, Result, Visitor> (Label pc, Visitor visitor, Data state)
+                       where Visitor : IILVisitor<Label, Source, Dest, Data, Result>;
+
+               bool IsUnreachable (Label pc);
+               TEdgeData EdgeData (Label from, Label to);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs
new file mode 100644 (file)
index 0000000..263f5d6
--- /dev/null
@@ -0,0 +1,169 @@
+// 
+// IMetaDataProvider.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Providers {
+       interface IMetaDataProvider {
+               TypeNode System_Int32 { get; }
+               TypeNode System_String { get; }
+               TypeNode System_Boolean { get; }
+               TypeNode System_IntPtr { get; }
+               TypeNode System_UIntPtr { get; }
+               TypeNode System_Void { get; }
+               TypeNode System_Array { get; }
+               TypeNode System_Object { get; }
+               TypeNode System_Int8 { get; }
+               TypeNode System_Int64 { get; }
+               TypeNode System_Int16 { get; }
+               TypeNode System_UInt8 { get; }
+               TypeNode System_UInt64 { get; }
+               TypeNode System_UInt32 { get; }
+               TypeNode System_UInt16 { get; }
+
+               Result AccessMethodBody<Data, Result> (Method method, IMethodCodeConsumer<Data, Result> consumer, Data data);
+
+               IEnumerable<Method> Methods (AssemblyNode assembly);
+               IEnumerable<Property> Properties (TypeNode type);
+               IEnumerable<Field> Fields (TypeNode type);
+               IEnumerable<TypeNode> Interfaces (TypeNode type);
+               IIndexable<Local> Locals (Method method);
+               IIndexable<Parameter> Parameters (Method method);
+
+               IEnumerable<Method> ImplementedMethods (Method method);
+               IEnumerable<Method> OverridenAndImplementedMethods (Method method);
+
+               Parameter This (Method method);
+
+               string Name (Local local);
+               string Name (Method method);
+               string Name (Field field);
+               string Name (TypeNode type);
+
+               string FullName (Method method);
+               string FullName (TypeNode type);
+
+               TypeNode FieldType (Field field);
+               TypeNode ParameterType (Parameter parameter);
+               TypeNode LocalType (Local local);
+               TypeNode ReturnType (Method method);
+               TypeNode ManagedPointer (TypeNode type);
+               TypeNode ElementType (TypeNode type);
+               TypeNode ArrayType (TypeNode type, int rank);
+
+
+               TypeNode DeclaringType (Method method);
+               TypeNode DeclaringType (Field field);
+
+               bool Equal (Method thisMethod, Method thatMethod);
+
+               bool IsMain (Method method);
+
+               bool IsStatic (Method method);
+               bool IsStatic (Field field);
+               bool IsStatic (Property property);
+
+               bool IsPrivate (Method method);
+
+               bool IsProtected (Method method);
+               bool IsProtected (Field field);
+
+               bool IsPublic (Method method);
+               bool IsPublic (Field field);
+
+               bool IsVirtual (Method method);
+               bool IsNewSlot (Method method);
+               bool IsOverride (Method method);
+               bool IsFinal (Method method);
+               bool IsConstructor (Method method);
+               bool IsAbstract (Method method);
+               bool IsCompilerGenerated (Field field);
+               bool IsCompilerGenerated (Method method);
+
+               bool IsAutoPropertyMember (Method method);
+               bool IsPropertySetter (Method method, out Property property);
+               bool IsPropertyGetter (Method method, out Property property);
+               bool HasSetter (Property property, out Method method);
+               bool HasGetter (Property property, out Method method);
+
+               bool HasBody (Method method);
+               bool DerivesFrom (TypeNode sub, TypeNode type);
+               bool Equal (TypeNode type, TypeNode otherType);
+
+               bool TryGetImplementingMethod (TypeNode type, Method calledMethod, out Method implementingMethod);
+               bool TryGetRootMethod (Method method, out Method rootMethod);
+
+               Field Unspecialized (Field field);
+               Method Unspecialized (Method method);
+               TypeNode Unspecialized (TypeNode type);
+
+               Method DeclaringMethod (Parameter parameter);
+
+               int ParameterIndex (Parameter parameter);
+               int ParameterStackIndex (Parameter parameter);
+
+               bool TryLoadAssembly (string filename, out AssemblyNode assembly, out string reasonOnFailure);
+
+               string Name (Parameter parameter);
+
+               bool IsReferenceType (TypeNode type);
+               bool IsManagedPointer (TypeNode value);
+               bool IsStruct (TypeNode type);
+               bool IsInterface (TypeNode type);
+               bool IsArray (TypeNode type);
+               bool IsVoid (TypeNode type);
+               bool IsReadonly (Field value);
+               bool IsFinalizer (Method method);
+               bool IsDispose (Method method);
+               bool IsVoidMethod (Method method);
+               bool IsOut (Parameter p);
+               bool IsPrimitive (TypeNode type);
+               bool IsClass (TypeNode type);
+
+               bool IsAsVisibleAs (Field value, Method method);
+               bool IsAsVisibleAs (Method value, Method method);
+               bool IsVisibleFrom (Field field, TypeNode declaringType);
+               bool IsVisibleFrom (Method value, TypeNode declaringType);
+               bool IsVisibleFrom (TypeNode type, TypeNode fromType);
+
+               bool TryGetSystemType (string fullName, out TypeNode type);
+
+               bool HasValueRepresentation (TypeNode type);
+
+               void IsSpecialized (Method calledMethod, ref IImmutableMap<TypeNode, TypeNode> specialization);
+               bool IsSpecialized (Method method);
+
+               bool IsFormalTypeParameter (TypeNode type);
+               bool IsMethodFormalTypeParameter (TypeNode type);
+
+               int TypeSize (TypeNode type);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMethodCodeProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/IMethodCodeProvider.cs
new file mode 100644 (file)
index 0000000..954b9f3
--- /dev/null
@@ -0,0 +1,49 @@
+// 
+// IMethodCodeProvider.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.Collections.Generic;
+using Mono.CodeContracts.Static.AST;
+
+namespace Mono.CodeContracts.Static.Providers {
+       interface IMethodCodeProvider<Label, Handler> : ICodeProvider<Label> {
+               bool IsFaultHandler (Handler handler);
+               bool IsFilterHandler (Handler handler);
+               bool IsCatchHandler (Handler handler);
+               bool IsCatchAllHandler (Handler handler);
+               bool IsFinallyHandler (Handler handler);
+
+               TypeNode CatchType (Handler handler);
+               IEnumerable<Handler> GetTryBlocks (Method method);
+
+               Label FilterExpressionStart (Handler handler);
+               Label HandlerEnd (Handler handler);
+               Label HandlerStart (Handler handler);
+               Label TryStart (Handler handler);
+               Label TryEnd (Handler handler);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Providers/MetaDataProvider.cs
new file mode 100644 (file)
index 0000000..a78dfbe
--- /dev/null
@@ -0,0 +1,692 @@
+// 
+// MetaDataProvider.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.Linq;
+using Mono.Cecil;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.ContractExtraction;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Providers {
+       class MetaDataProvider : IMetaDataProvider {
+               public static readonly MetaDataProvider Instance = new MetaDataProvider ();
+
+               #region IMetaDataProvider Members
+               public Result AccessMethodBody<Data, Result> (Method method, IMethodCodeConsumer<Data, Result> consumer, Data data)
+               {
+                       return consumer.Accept (CodeProviderImpl.Instance, CodeProviderImpl.Instance.Entry (method), method, data);
+               }
+
+               public bool IsReferenceType (TypeNode type)
+               {
+                       return (!type.IsValueType);
+               }
+
+               public Method DeclaringMethod (Parameter parameter)
+               {
+                       return parameter.DeclaringMethod;
+               }
+
+               public int ParameterIndex (Parameter parameter)
+               {
+                       return parameter.Index;
+               }
+
+               public bool IsVoidMethod (Method method)
+               {
+                       return IsVoid (method.ReturnType);
+               }
+
+               public bool TryLoadAssembly (string filename, out AssemblyNode assembly, out string reasonOfFailure)
+               {
+                       assembly = AssemblyNode.ReadAssembly (filename);
+                       if (!TryLoadContractNodes (ref assembly)) {
+                               reasonOfFailure = "Couldn't find CodeContracts assembly in referencing assemblies";
+                               return false;
+                       }
+                       reasonOfFailure = null;
+                       return true;
+               }
+
+               public TypeNode ReturnType (Method method)
+               {
+                       return method.ReturnType;
+               }
+
+               public IIndexable<Parameter> Parameters (Method method)
+               {
+                       return new Indexable<Parameter> (method.Parameters);
+               }
+
+               public Parameter This (Method method)
+               {
+                       return method.ThisParameter;
+               }
+
+               public string Name (Method method)
+               {
+                       return method.Name;
+               }
+
+               public string Name (Field field)
+               {
+                       return field.Name;
+               }
+
+               public string Name (TypeNode type)
+               {
+                       return type.Name;
+               }
+
+               public TypeNode FieldType (Field field)
+               {
+                       return field.FieldType;
+               }
+
+               public string FullName (Method method)
+               {
+                       return method.FullName;
+               }
+
+               public string FullName (TypeNode type)
+               {
+                       return type.FullName;
+               }
+
+               public TypeNode DeclaringType (Field field)
+               {
+                       return field.DeclaringType;
+               }
+
+               public bool IsMain (Method method)
+               {
+                       MethodDefinition entryPoint = method.Definition.Module.EntryPoint;
+
+                       return entryPoint != null && entryPoint.Equals (method);
+               }
+
+               public bool IsStatic (Method method)
+               {
+                       return method.IsStatic;
+               }
+
+               public bool IsStatic (Field field)
+               {
+                       return field.IsStatic;
+               }
+
+               public bool IsPrivate (Method method)
+               {
+                       return method.IsPrivate;
+               }
+
+               public bool IsProtected (Method method)
+               {
+                       return method.IsProtected;
+               }
+
+               public bool IsPublic (Method method)
+               {
+                       return method.IsPublic;
+               }
+
+               public bool IsVirtual (Method method)
+               {
+                       return method.IsVirtual;
+               }
+
+               public bool IsNewSlot (Method method)
+               {
+                       return method.IsNewSlot;
+               }
+
+               public bool IsOverride (Method method)
+               {
+                       return !method.IsNewSlot && method.HasOverrides;
+               }
+
+               public bool IsFinal (Method method)
+               {
+                       return method.IsFinal;
+               }
+
+               public bool IsConstructor (Method method)
+               {
+                       return method.IsConstructor;
+               }
+
+               public bool IsAbstract (Method method)
+               {
+                       return method.IsAbstract;
+               }
+
+               public bool IsPropertySetter (Method method, out Property property)
+               {
+                       //todo: implement this
+
+                       property = null;
+                       return false;
+               }
+
+               public bool IsPropertyGetter (Method method, out Property property)
+               {
+                       //todo: implement this
+
+                       property = null;
+                       return false;
+               }
+
+               public TypeNode DeclaringType (Method method)
+               {
+                       return method.DeclaringType;
+               }
+
+               public bool HasBody (Method method)
+               {
+                       return method.HasBody;
+               }
+
+               public bool DerivesFrom (TypeNode sub, TypeNode type)
+               {
+                       return sub.IsAssignableTo (type);
+               }
+
+               public bool Equal (TypeNode type, TypeNode otherType)
+               {
+                       return type == otherType;
+               }
+
+               public bool TryGetImplementingMethod (TypeNode type, Method calledMethod, out Method implementingMethod)
+               {
+                       //todo: implement this
+                       implementingMethod = null;
+                       return false;
+               }
+
+               public Method Unspecialized (Method method)
+               {
+                       if (method.HasGenericParameters)
+                               throw new NotImplementedException ();
+
+                       return method;
+               }
+
+               public IEnumerable<Method> OverridenAndImplementedMethods (Method method)
+               {
+                       //todo: implement this
+                       yield break;
+               }
+
+               public TypeNode ManagedPointer (TypeNode type)
+               {
+                       return type.GetReferenceType ();
+               }
+
+               public bool TryGetRootMethod (Method method, out Method rootMethod)
+               {
+                       //todo: implement this
+                       rootMethod = method;
+                       return true;
+               }
+
+               public IEnumerable<Method> ImplementedMethods (Method method)
+               {
+                       yield break;
+               }
+
+               public bool IsAutoPropertyMember (Method method)
+               {
+                       //todo: implement this
+                       return false;
+               }
+
+               public bool IsFinalizer (Method method)
+               {
+                       return "Finalize" == method.Name;
+               }
+
+               public bool IsDispose (Method method)
+               {
+                       if (method.Name != "Dispose" && method.Name != "System.IDisposable.Dispose")
+                               return false;
+                       if (method.Parameters == null || method.Parameters.Count == 0)
+                               return true;
+                       if (method.Parameters.Count == 1)
+                               return 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
+               {
+                       get { return CoreSystemTypes.Instance.TypeSingle; }
+               }
+
+               public TypeNode System_Type
+               {
+                       get { return CoreSystemTypes.Instance.TypeSystemType; }
+               }
+
+               public TypeNode System_Char
+               {
+                       get { return CoreSystemTypes.Instance.TypeChar; }
+               }
+
+               public TypeNode System_Int32
+               {
+                       get { return CoreSystemTypes.Instance.TypeInt32; }
+               }
+
+               public TypeNode System_String
+               {
+                       get { return CoreSystemTypes.Instance.TypeString; }
+               }
+
+               public TypeNode System_Boolean
+               {
+                       get { return CoreSystemTypes.Instance.TypeBoolean; }
+               }
+
+               public TypeNode System_IntPtr
+               {
+                       get { return CoreSystemTypes.Instance.TypeIntPtr; }
+               }
+
+               public TypeNode System_UIntPtr
+               {
+                       get { return CoreSystemTypes.Instance.TypeUIntPtr; }
+               }
+
+               public TypeNode System_Void
+               {
+                       get { return CoreSystemTypes.Instance.TypeVoid; }
+               }
+
+               public TypeNode System_Array
+               {
+                       get { return CoreSystemTypes.Instance.TypeArray; }
+               }
+
+               public TypeNode System_Object
+               {
+                       get { return CoreSystemTypes.Instance.TypeObject; }
+               }
+
+               public TypeNode System_Int8
+               {
+                       get { return CoreSystemTypes.Instance.TypeSByte; }
+               }
+
+               public TypeNode System_Int64
+               {
+                       get { return CoreSystemTypes.Instance.TypeInt64; }
+               }
+
+               public TypeNode System_Int16
+               {
+                       get { return CoreSystemTypes.Instance.TypeInt16; }
+               }
+
+               public TypeNode System_UInt8
+               {
+                       get { return CoreSystemTypes.Instance.TypeByte; }
+               }
+
+               public TypeNode System_UInt64
+               {
+                       get { return CoreSystemTypes.Instance.TypeUInt64; }
+               }
+
+               public TypeNode System_UInt32
+               {
+                       get { return CoreSystemTypes.Instance.TypeUInt32; }
+               }
+
+               public TypeNode System_UInt16
+               {
+                       get { return CoreSystemTypes.Instance.TypeUInt16; }
+               }
+
+               public IEnumerable<Method> Methods (AssemblyNode assembly)
+               {
+                       return assembly.Modules.SelectMany (a => a.Types).SelectMany (t => t.Methods);
+               }
+
+               public string Name (Parameter parameter)
+               {
+                       return parameter.Name;
+               }
+
+               public TypeNode ParameterType (Parameter parameter)
+               {
+                       return parameter.Type;
+               }
+
+               public TypeNode LocalType (Local local)
+               {
+                       return local.Type;
+               }
+
+               public bool IsStruct (TypeNode type)
+               {
+                       return type.IsValueType;
+               }
+
+               public Field Unspecialized (Field field)
+               {
+                       return field;
+               }
+
+               public bool IsManagedPointer (TypeNode value)
+               {
+                       return value is Reference;
+               }
+
+               public bool IsArray (TypeNode type)
+               {
+                       return type.IsArray;
+               }
+
+               public IEnumerable<TypeNode> Interfaces (TypeNode type)
+               {
+                       return type.Interfaces;
+               }
+
+               public bool TryGetSystemType (string fullName, out TypeNode type)
+               {
+                       int len = fullName.LastIndexOf (".");
+                       string ns = "";
+                       string className = fullName;
+                       if (len > 0) {
+                               ns = fullName.Substring (0, len);
+                               className = fullName.Substring (len + 1);
+                       }
+                       type = CoreSystemTypes.Instance.SystemAssembly.GetType (ns, className);
+                       return type != null;
+               }
+
+               public bool IsInterface (TypeNode type)
+               {
+                       return type.IsInterface;
+               }
+
+               public IEnumerable<Property> Properties (TypeNode type)
+               {
+                       return type.Properties;
+               }
+
+               public bool IsStatic (Property property)
+               {
+                       return property.IsStatic;
+               }
+
+               public bool IsAsVisibleAs (Field value, Method method)
+               {
+                       return HelperMethods.IsReferenceAsVisibleAs (value, method);
+               }
+
+               public bool IsAsVisibleAs (Method value, Method method)
+               {
+                       return HelperMethods.IsReferenceAsVisibleAs (value, method);
+               }
+
+               public bool IsVisibleFrom (Field field, TypeNode declaringType)
+               {
+                       return field.IsVisibleFrom (declaringType);
+               }
+
+               public bool IsVisibleFrom (Method value, TypeNode declaringType)
+               {
+                       return value.IsVisibleFrom (declaringType);
+               }
+
+               public bool Equal (Method thisMethod, Method thatMethod)
+               {
+                       return thisMethod == thatMethod;
+               }
+
+               public IIndexable<Local> Locals (Method method)
+               {
+                       return new Indexable<Local> (method.Locals);
+               }
+
+               public TypeNode ElementType (TypeNode type)
+               {
+                       var reference = type as Reference;
+                       if (reference != null)
+                               return reference.ElementType;
+                       //todo: array
+
+                       throw new NotImplementedException ();
+               }
+
+               public TypeNode Unspecialized (TypeNode type)
+               {
+                       return type;
+               }
+
+               public bool IsProtected (Field field)
+               {
+                       return field.IsFamily || field.IsFamilyAndAssembly || field.IsFamilyOrAssembly;
+               }
+
+               public bool IsPublic (Field field)
+               {
+                       return field.IsPublic;
+               }
+
+               public int ParameterStackIndex (Parameter parameter)
+               {
+                       Method declaringMethod = parameter.DeclaringMethod;
+                       return declaringMethod.Parameters.Count + (declaringMethod.IsStatic ? 0 : 1) - parameter.Index - 1;
+               }
+
+               public bool HasGetter (Property property, out Method method)
+               {
+                       if (property.HasGetter) {
+                               method = property.Getter;
+                               return true;
+                       }
+                       method = null;
+                       return false;
+               }
+
+               public bool HasSetter (Property property, out Method method)
+               {
+                       if (property.HasSetter) {
+                               method = property.Setter;
+                               return true;
+                       }
+                       method = null;
+                       return false;
+               }
+
+               public bool IsReadonly (Field value)
+               {
+                       return value.IsReadonly;
+               }
+
+               public bool HasValueRepresentation (TypeNode type)
+               {
+                       return !IsStruct (type) || IsPrimitive (type) || IsEnum (type);
+               }
+
+               public bool IsVoid (TypeNode type)
+               {
+                       return type.Equals (System_Void);
+               }
+
+               public void IsSpecialized (Method calledMethod, ref IImmutableMap<TypeNode, TypeNode> specialization)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public IEnumerable<Field> Fields (TypeNode type)
+               {
+                       return type.Fields;
+               }
+
+               public bool IsOut (Parameter p)
+               {
+                       return p.IsOut;
+               }
+
+               public bool IsPrimitive (TypeNode type)
+               {
+                       return type.IsPrimitive;
+               }
+
+               public bool IsClass (TypeNode type)
+               {
+                       return type.IsClass;
+               }
+
+               public bool IsVisibleFrom (TypeNode type, TypeNode fromType)
+               {
+                       return type.IsVisibleFrom (fromType);
+               }
+
+               public bool IsCompilerGenerated (Method method)
+               {
+                       return method.IsCompilerGenerated;
+               }
+
+               public bool IsSpecialized (Method method)
+               {
+                       return false;
+               }
+
+               public bool IsFormalTypeParameter (TypeNode type)
+               {
+                       return false;
+               }
+
+               public bool IsMethodFormalTypeParameter (TypeNode type)
+               {
+                       return false;
+               }
+
+               public TypeNode ArrayType (TypeNode type, int rank)
+               {
+                       return type.GetArrayType (rank);
+               }
+
+               public bool IsCompilerGenerated (Field field)
+               {
+                       return field.IsCompilerGenerated;
+               }
+
+               public int TypeSize (TypeNode type)
+               {
+                       int classSize = type.ClassSize;
+                       if (classSize > 0)
+                               return classSize;
+                       int size = TypeSizeHelper (type);
+                       type.ClassSize = size;
+                       return size;
+               }
+
+               public string Name (Local local)
+               {
+                       return local.Name;
+               }
+
+               private int TypeSizeHelper (TypeNode type)
+               {
+                       if (IsManagedPointer (type))
+                               return 4;
+                       if (type == System_Boolean)
+                               return 1;
+                       if (type == System_Char)
+                               return 2;
+                       if (type == System_Int8)
+                               return 1;
+                       if (type == System_Int16)
+                               return 2;
+                       if (type == System_Int32)
+                               return 4;
+                       if (type == System_Int64)
+                               return 8;
+                       if (type == System_IntPtr || type == System_Object || type == System_String || type == System_Type)
+                               return 4;
+
+                       if (type == System_UInt8)
+                               return 1;
+                       if (type == System_UInt16)
+                               return 2;
+                       if (type == System_UInt32)
+                               return 4;
+                       if (type == System_UInt64)
+                               return 8;
+
+                       if (type == System_UIntPtr || type == System_Single)
+                               return 4;
+                       if (type == System_Double)
+                               return 8;
+
+                       return -1;
+               }
+
+               private bool IsEnum (TypeNode type)
+               {
+                       return type.IsEnum;
+               }
+               #endregion
+
+               private bool TryLoadContractNodes (ref AssemblyNode assembly)
+               {
+                       ContractNodes nodes = null;
+                       foreach (Module module in assembly.Modules) {
+                               IAssemblyResolver assemblyResolver = module.Definition.AssemblyResolver;
+                               foreach (AssemblyNameReference reference in module.Definition.AssemblyReferences) {
+                                       AssemblyDefinition def = assemblyResolver.Resolve (reference);
+                                       nodes = ContractNodes.GetContractNodes (new AssemblyNode (def), (s) => { });
+                                       if (nodes != null)
+                                               break;
+                               }
+                       }
+
+                       if (nodes == null)
+                               return false;
+
+                       var extractor = new ContractExtractor (nodes, assembly, true);
+                       assembly = (AssemblyNode) extractor.Visit (assembly);
+                       return true;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/AssertionFinder.cs
new file mode 100644 (file)
index 0000000..0b40151
--- /dev/null
@@ -0,0 +1,140 @@
+// 
+// AssertionFinder.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 Mono.CodeContracts.Static.AST.Visitors;
+using Mono.CodeContracts.Static.Analysis.Drivers;
+using Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Proving {
+       static class AssertionFinder {
+               public static void ValidateAssertions<TExpression, TVariable> (IFactQuery<BoxedExpression, TVariable> facts, IMethodDriver<TExpression, TVariable> driver, List<string> proofResults)
+                       where TExpression : IEquatable<TExpression>
+                       where TVariable : IEquatable<TVariable>
+               {
+                       Bind<TExpression, TVariable>.ValidateAssertions (facts, driver, proofResults);
+               }
+
+               #region Nested type: Bind
+               private static class Bind<TExpression, TVariable>
+                       where TExpression : IEquatable<TExpression>
+                       where TVariable : IEquatable<TVariable> {
+                       public static void ValidateAssertions (IFactQuery<BoxedExpression, TVariable> facts, IMethodDriver<TExpression, TVariable> driver, List<string> proofResults)
+                       {
+                               APC entryAfterRequires = driver.ContextProvider.MethodContext.CFG.EntryAfterRequires;
+                               if (facts.IsUnreachable (entryAfterRequires)) {
+                                       proofResults.Add ("Method precondition is unsatisfiable");
+                                       return;
+                               }
+
+                               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));
+
+                                       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;
+                                       }
+                               }
+                       }
+
+                       private static IEnumerable<AssertionObligation> GetAssertions (IMethodDriver<TExpression, TVariable> driver, out object assertStats)
+                       {
+                               var analysis = new AssertionCrawlerAnalysis ();
+                               List<AssertionObligation> obligations = analysis.Gather (driver);
+
+                               assertStats = null;
+                               return obligations;
+                       }
+
+                       #region Nested type: AssertionCrawlerAnalysis
+                       private class AssertionCrawlerAnalysis : ValueCodeVisitor<TVariable> {
+                               private readonly List<AssertionObligation> Obligations = new List<AssertionObligation> ();
+
+                               public List<AssertionObligation> Gather (IMethodDriver<TExpression, TVariable> driver)
+                               {
+                                       Run (driver.ValueLayer);
+                                       return this.Obligations;
+                               }
+
+                               public override bool Assert (APC pc, EdgeTag tag, TVariable condition, bool data)
+                               {
+                                       if (pc.InsideRequiresAtCallInsideContract)
+                                               return data;
+
+                                       this.Obligations.Add (new AssertionObligation (pc, tag, condition));
+                                       return data;
+                               }
+
+                               public override bool Assume (APC pc, EdgeTag tag, TVariable condition, bool data)
+                               {
+                                       if (!pc.InsideRequiresAtCallInsideContract && tag == EdgeTag.Assume)
+                                               this.Obligations.Add (new AssertionObligation (pc, tag, condition, true));
+
+                                       return data;
+                               }
+                       }
+                       #endregion
+
+                       #region Nested type: AssertionObligation
+                       private class AssertionObligation {
+                               public readonly APC Apc;
+                               public readonly TVariable Condition;
+                               public readonly bool IsAssume;
+                               public readonly EdgeTag Tag;
+
+                               public AssertionObligation (APC pc, EdgeTag tag, TVariable cond)
+                                       : this (pc, tag, cond, false)
+                               {
+                               }
+
+                               public AssertionObligation (APC pc, EdgeTag tag, TVariable cond, bool isAssume)
+                               {
+                                       this.Apc = pc;
+                                       this.Tag = tag;
+                                       this.Condition = cond;
+                                       this.IsAssume = isAssume;
+                               }
+                       }
+                       #endregion
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BasicFacts.cs
new file mode 100644 (file)
index 0000000..4ce37d4
--- /dev/null
@@ -0,0 +1,135 @@
+// 
+// BasicFacts.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 Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Proving {
+       class BasicFacts<Expression, Variable> : IFactQuery<BoxedExpression, Variable> {
+               protected IExpressionContextProvider<Expression, Variable> ContextProvider;
+               protected IFactBase<Variable> FactBase;
+               protected Predicate<APC> isUnreachable;
+
+               public BasicFacts (IExpressionContextProvider<Expression, Variable> contextProvider, IFactBase<Variable> factBase, Predicate<APC> isUnreachable)
+               {
+                       this.ContextProvider = contextProvider;
+                       this.FactBase = factBase;
+                       this.isUnreachable = isUnreachable;
+               }
+
+               #region Implementation of IFactBase<Variable>
+               public ProofOutcome IsNull (APC pc, Variable variable)
+               {
+                       return this.FactBase.IsNull (pc, variable);
+               }
+
+               public ProofOutcome IsNonNull (APC pc, Variable variable)
+               {
+                       return this.FactBase.IsNonNull (pc, variable);
+               }
+
+               public bool IsUnreachable (APC pc)
+               {
+                       if (this.isUnreachable != null && this.isUnreachable (pc))
+                               return true;
+
+                       return this.FactBase.IsUnreachable (pc);
+               }
+
+               protected static bool TryVariable (BoxedExpression e, out Variable v)
+               {
+                       object underlyingVariable = e.UnderlyingVariable;
+                       if (underlyingVariable is Variable) {
+                               v = (Variable) underlyingVariable;
+                               return true;
+                       }
+
+                       v = default(Variable);
+                       return false;
+               }
+               #endregion
+
+               #region Implementation of IFactQuery<BoxedExpression,Variable>
+               public virtual ProofOutcome IsNull (APC pc, BoxedExpression expr)
+               {
+                       Variable v;
+                       if (TryVariable (expr, out v)) {
+                               ProofOutcome outcome = this.FactBase.IsNull (pc, v);
+                               if (outcome != ProofOutcome.Top)
+                                       return outcome;
+                       }
+                       return ProofOutcome.Top;
+               }
+
+               public virtual ProofOutcome IsNonNull (APC pc, BoxedExpression expr)
+               {
+                       Variable v;
+                       if (TryVariable (expr, out v)) {
+                               ProofOutcome outcome = this.FactBase.IsNonNull (pc, v);
+                               if (outcome != ProofOutcome.Top)
+                                       return outcome;
+                       }
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsTrue (APC pc, BoxedExpression expr)
+               {
+                       return IsNonZero (pc, expr);
+               }
+
+               public ProofOutcome IsTrueImply (APC pc, LispList<BoxedExpression> positiveAssumptions, LispList<BoxedExpression> negativeAssumptions, BoxedExpression goal)
+               {
+                       ProofOutcome outcome = IsTrue (pc, goal);
+                       switch (outcome) {
+                       case ProofOutcome.True:
+                       case ProofOutcome.Bottom:
+                               return outcome;
+                       default:
+                               return ProofOutcome.Top;
+                       }
+               }
+
+               public ProofOutcome IsGreaterEqualToZero (APC pc, BoxedExpression expr)
+               {
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsLessThan (APC pc, BoxedExpression expr, BoxedExpression right)
+               {
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsNonZero (APC pc, BoxedExpression expr)
+               {
+                       return IsNonNull (pc, expr);
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpression.cs
new file mode 100644 (file)
index 0000000..a391b6f
--- /dev/null
@@ -0,0 +1,1688 @@
+// 
+// BoxedExpression.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;
+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.ExpressionAnalysis.Decoding;
+using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Proving {
+       internal abstract class BoxedExpression {
+               public virtual bool IsVariable
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsBooleanTyped
+               {
+                       get { return false; }
+               }
+
+               public virtual object UnderlyingVariable
+               {
+                       get { return false; }
+               }
+
+               public virtual PathElement[] AccessPath
+               {
+                       get { return null; }
+               }
+
+               public virtual bool IsConstant
+               {
+                       get { return false; }
+               }
+
+               public virtual object Constant
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual object ConstantType
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual bool IsSizeof
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsUnary
+               {
+                       get { return false; }
+               }
+
+               public virtual UnaryOperator UnaryOperator
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual BoxedExpression UnaryArgument
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual bool IsBinary
+               {
+                       get { return false; }
+               }
+
+               public virtual BinaryOperator BinaryOperator
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual BoxedExpression BinaryLeftArgument
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual BoxedExpression BinaryRightArgument
+               {
+                       get { throw new InvalidOperationException (); }
+               }
+
+               public virtual bool IsIsinst
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsNull
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsCast
+               {
+                       get { return false; }
+               }
+
+               public virtual bool IsResult
+               {
+                       get { return false; }
+               }
+
+               public virtual bool TryGetType (out object type)
+               {
+                       type = null;
+                       return false;
+               }
+
+               public virtual bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
+               {
+                       op = BinaryOperator.Add;
+                       left = null;
+                       right = null;
+                       return false;
+               }
+
+               public virtual bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
+               {
+                       op = UnaryOperator.Conv_i;
+                       argument = null;
+                       return false;
+               }
+
+               public virtual bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
+               {
+                       expr = null;
+                       type = null;
+                       return false;
+               }
+
+               public abstract void AddFreeVariables (HashSet<BoxedExpression> set);
+
+               public virtual BoxedExpression Substitute (BoxedExpression what, BoxedExpression replace)
+               {
+                       if (this == what || Equals (what))
+                               return replace;
+
+                       return RecursiveSubstitute (what, replace);
+               }
+
+               public abstract BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map);
+
+               protected internal virtual BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
+               {
+                       return this;
+               }
+
+               public abstract Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       where Visitor : IILVisitor<PC, Dummy, Dummy, Data, Result>;
+
+               public static BoxedExpression Var (object var)
+               {
+                       return new VariableExpression (var);
+               }
+
+               public static BoxedExpression For<Variable, Expression> (Expression external, IFullExpressionDecoder<Variable, Expression> decoder)
+                       where Expression : IEquatable<Expression>
+               {
+                       return new ExternalBox<Variable, Expression> (external, decoder);
+               }
+
+               public static BoxedExpression MakeIsinst (TypeNode type, BoxedExpression arg)
+               {
+                       return new IsinstExpression (arg, type);
+               }
+
+               public static BoxedExpression Convert<Variable, ExternalExpression> (ExternalExpression expr, IFullExpressionDecoder<Variable, ExternalExpression> decoder)
+               {
+                       TypeNode type;
+                       object value;
+                       if (decoder.IsConstant (expr, out value, out type))
+                               return new ConstantExpression (value, type);
+                       if (decoder.IsNull (expr))
+                               return new ConstantExpression (null, null);
+
+                       object variable;
+                       if (decoder.IsVariable (expr, out variable)) {
+                               LispList<PathElement> variableAccessPath = decoder.GetVariableAccessPath (expr);
+                               return new VariableExpression (variable, variableAccessPath);
+                       }
+
+                       if (decoder.IsSizeof (expr, out type)) {
+                               int sizeAsConstant;
+                               return decoder.TrySizeOfAsConstant (expr, out sizeAsConstant) ? new SizeOfExpression (type, sizeAsConstant) : new SizeOfExpression (type);
+                       }
+
+                       ExternalExpression arg;
+                       if (decoder.IsIsinst (expr, out arg, out type))
+                               return new IsinstExpression (Convert (arg, decoder), type);
+
+                       UnaryOperator op;
+                       if (decoder.IsUnaryExpression (expr, out op, out arg))
+                               return new UnaryExpression (op, Convert (arg, decoder));
+
+                       BinaryOperator bop;
+                       ExternalExpression left;
+                       ExternalExpression right;
+                       if (!decoder.IsBinaryExpression (expr, out bop, out left, out right))
+                               throw new InvalidOperationException ();
+
+                       return new BinaryExpression (bop, Convert (left, decoder), Convert (right, decoder));
+               }
+
+               #region Nested type: AssertExpression
+               public class AssertExpression : ContractExpression {
+                       public AssertExpression (BoxedExpression condition, EdgeTag tag, APC pc) : base (condition, tag, pc)
+                       {
+                       }
+
+                       #region Overrides of ContractExpression
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Assert (pc, this.Tag, Dummy.Value, data);
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression cond = this.Condition.Substitute (map);
+                               if (cond == this.Condition)
+                                       return this;
+                               if (cond == null)
+                                       return null;
+
+                               return new AssertExpression (cond, this.Tag, this.Apc);
+                       }
+                       #endregion
+               }
+               #endregion
+
+               #region Nested type: AssumeExpression
+               public class AssumeExpression : ContractExpression {
+                       public AssumeExpression (BoxedExpression condition, EdgeTag tag, APC pc)
+                               : base (condition, tag, pc)
+                       {
+                       }
+
+                       #region Overrides of ContractExpression
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Assume (pc, this.Tag, Dummy.Value, data);
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression cond = this.Condition.Substitute (map);
+                               if (cond == this.Condition)
+                                       return this;
+                               if (cond == null)
+                                       return null;
+
+                               return new AssumeExpression (cond, this.Tag, this.Apc);
+                       }
+                       #endregion
+               }
+               #endregion
+
+               #region Nested type: BinaryExpression
+               public class BinaryExpression : BoxedExpression {
+                       public readonly BoxedExpression Left;
+                       public readonly BinaryOperator Op;
+                       public readonly BoxedExpression Right;
+
+                       public BinaryExpression (BinaryOperator op, BoxedExpression left, BoxedExpression right)
+                       {
+                               this.Op = op;
+                               this.Left = left;
+                               this.Right = right;
+                       }
+
+                       public override bool IsBinary
+                       {
+                               get { return true; }
+                       }
+
+                       public override BoxedExpression BinaryLeftArgument
+                       {
+                               get { return this.Left; }
+                       }
+
+                       public override BoxedExpression BinaryRightArgument
+                       {
+                               get { return this.Right; }
+                       }
+
+                       public override BinaryOperator BinaryOperator
+                       {
+                               get { return this.Op; }
+                       }
+
+                       public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
+                       {
+                               op = this.Op;
+                               left = this.Left;
+                               right = this.Right;
+                               return true;
+                       }
+
+                       #region Overrides of BoxedExpression
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.Left.AddFreeVariables (set);
+                               this.Right.AddFreeVariables (set);
+                       }
+
+                       protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
+                       {
+                               BoxedExpression left = this.Left.Substitute (what, replace);
+                               BoxedExpression right = this.Right.Substitute (what, replace);
+                               if (left == this.Left && right == this.Right)
+                                       return this;
+
+                               return new BinaryExpression (this.Op, left, right);
+                       }
+
+                       public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression left = this.Left.Substitute (map);
+                               if (left == null)
+                                       return null;
+
+                               BoxedExpression right = this.Right.Substitute (map);
+                               if (right == null)
+                                       return null;
+
+                               if (this.Left == left && this.Right == right)
+                                       return this;
+                               return new BinaryExpression (this.Op, left, right);
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Binary (pc, this.Op, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                       }
+                       #endregion
+               }
+               #endregion
+
+               #region Nested type: CastExpression
+               public class CastExpression : BoxedExpression {
+                       public readonly TypeNode CastToType;
+                       public readonly BoxedExpression Expr;
+
+                       public CastExpression (TypeNode castToType, BoxedExpression expr)
+                       {
+                               this.CastToType = castToType;
+                               this.Expr = expr;
+                       }
+
+                       public override bool IsCast
+                       {
+                               get { return true; }
+                       }
+
+                       public override PathElement[] AccessPath
+                       {
+                               get { return this.Expr.AccessPath; }
+                       }
+
+                       public override BoxedExpression BinaryLeftArgument
+                       {
+                               get { return this.Expr.BinaryLeftArgument; }
+                       }
+
+                       public override BoxedExpression BinaryRightArgument
+                       {
+                               get { return this.Expr.BinaryRightArgument; }
+                       }
+
+                       public override BinaryOperator BinaryOperator
+                       {
+                               get { return this.Expr.BinaryOperator; }
+                       }
+
+                       public override object Constant
+                       {
+                               get { return this.Expr.Constant; }
+                       }
+
+                       public override object ConstantType
+                       {
+                               get { return this.Expr.ConstantType; }
+                       }
+
+                       public override bool IsBinary
+                       {
+                               get { return this.Expr.IsBinary; }
+                       }
+
+                       public override bool IsBooleanTyped
+                       {
+                               get { return this.Expr.IsBooleanTyped; }
+                       }
+
+                       public override bool IsConstant
+                       {
+                               get { return this.Expr.IsConstant; }
+                       }
+
+
+                       public override bool IsSizeof
+                       {
+                               get { return this.Expr.IsSizeof; }
+                       }
+
+                       public override bool IsNull
+                       {
+                               get { return this.Expr.IsNull; }
+                       }
+
+                       public override bool IsIsinst
+                       {
+                               get { return this.Expr.IsIsinst; }
+                       }
+
+                       public override bool IsResult
+                       {
+                               get { return this.Expr.IsResult; }
+                       }
+
+                       public override bool IsUnary
+                       {
+                               get { return this.Expr.IsUnary; }
+                       }
+
+                       public override bool IsVariable
+                       {
+                               get { return this.Expr.IsVariable; }
+                       }
+
+                       public override BoxedExpression UnaryArgument
+                       {
+                               get { return this.Expr.UnaryArgument; }
+                       }
+
+                       public override UnaryOperator UnaryOperator
+                       {
+                               get { return this.Expr.UnaryOperator; }
+                       }
+
+                       public override object UnderlyingVariable
+                       {
+                               get { return this.Expr.UnderlyingVariable; }
+                       }
+
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.Expr.AddFreeVariables (set);
+                       }
+
+                       public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
+                       {
+                               return this.Expr.Substitute (map);
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return this.Expr.ForwardDecode<Data, Result, Visitor> (pc, visitor, data);
+                       }
+
+                       public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
+                       {
+                               return this.Expr.IsBinaryExpression (out op, out left, out right);
+                       }
+
+                       protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
+                       {
+                               return this.Expr.RecursiveSubstitute (what, replace);
+                       }
+
+                       public override BoxedExpression Substitute (BoxedExpression what, BoxedExpression replace)
+                       {
+                               return this.Expr.Substitute (what, replace);
+                       }
+
+                       public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
+                       {
+                               return this.Expr.IsUnaryExpression (out op, out argument);
+                       }
+               }
+               #endregion
+
+               #region Nested type: ConstantExpression
+               public class ConstantExpression : BoxedExpression {
+                       public readonly TypeNode Type;
+                       public readonly object Value;
+                       private readonly bool is_boolean;
+
+                       public ConstantExpression (object value, TypeNode type)
+                               : this (value, type, false)
+                       {
+                       }
+
+                       public ConstantExpression (object value, TypeNode type, bool isBoolean)
+                       {
+                               this.Value = value;
+                               this.Type = type;
+                               this.is_boolean = isBoolean;
+                       }
+
+                       public override bool IsBooleanTyped
+                       {
+                               get { return this.is_boolean; }
+                       }
+
+                       public override bool IsConstant
+                       {
+                               get { return true; }
+                       }
+
+                       public override object Constant
+                       {
+                               get { return this.Value; }
+                       }
+
+                       public override object ConstantType
+                       {
+                               get { return this.Type; }
+                       }
+
+                       public override bool IsNull
+                       {
+                               get
+                               {
+                                       if (this.Value == null)
+                                               return true;
+
+                                       var conv = this.Value as IConvertible;
+                                       if (conv != null) {
+                                               try {
+                                                       if (conv.ToInt32 (null) == 0)
+                                                               return true;
+                                               } catch {
+                                                       return false;
+                                               }
+                                       }
+
+                                       return false;
+                               }
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               return this;
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               if (this.Value == null)
+                                       return visitor.LoadNull (pc, Dummy.Value, data);
+
+                               return visitor.LoadConst (pc, this.Type, this.Value, Dummy.Value, data);
+                       }
+               }
+               #endregion
+
+               #region Nested type: ContractExpression
+               public abstract class ContractExpression : BoxedExpression {
+                       public readonly APC Apc;
+                       public readonly BoxedExpression Condition;
+                       public readonly EdgeTag Tag;
+
+                       public ContractExpression (BoxedExpression condition, EdgeTag tag, APC pc)
+                       {
+                               this.Tag = tag;
+                               this.Condition = condition;
+                               this.Apc = pc;
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.Condition.AddFreeVariables (set);
+                       }
+
+                       public abstract override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data);
+                       public abstract override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map);
+               }
+               #endregion
+
+               #region Nested type: ExternalBox
+               public class ExternalBox<Variable, LabeledSymbol> : BoxedExpression
+                       where LabeledSymbol : IEquatable<LabeledSymbol> {
+                       private readonly IFullExpressionDecoder<Variable, LabeledSymbol> decoder;
+                       private readonly LabeledSymbol expr;
+                       private Optional<Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression>> binary;
+
+                       private Optional<Tuple<bool, object, TypeNode>> constant;
+                       private Optional<Tuple<bool, BoxedExpression, TypeNode>> isInst;
+                       private Optional<Pair<bool, object>> isVar;
+                       private Optional<Pair<bool, TypeNode>> type;
+                       private Optional<Tuple<bool, UnaryOperator, BoxedExpression>> unary;
+                       private Optional<object> var;
+
+                       public ExternalBox (LabeledSymbol external, IFullExpressionDecoder<Variable, LabeledSymbol> decoder)
+                       {
+                               this.expr = external;
+                               this.decoder = decoder;
+                       }
+
+                       public override bool IsBinary
+                       {
+                               get
+                               {
+                                       Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
+                                       TryGetBinaryFromCache (out binary);
+                                       return binary.Item1;
+                               }
+                       }
+
+                       public override BinaryOperator BinaryOperator
+                       {
+                               get
+                               {
+                                       Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
+                                       bool res = TryGetBinaryFromCache (out binary);
+                                       if (!res)
+                                               throw new InvalidOperationException ();
+
+                                       return binary.Item2;
+                               }
+                       }
+
+                       public override BoxedExpression BinaryLeftArgument
+                       {
+                               get
+                               {
+                                       Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
+                                       bool res = TryGetBinaryFromCache (out binary);
+                                       if (!res)
+                                               throw new InvalidOperationException ();
+
+                                       return binary.Item3;
+                               }
+                       }
+
+                       public override BoxedExpression BinaryRightArgument
+                       {
+                               get
+                               {
+                                       Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
+                                       bool res = TryGetBinaryFromCache (out binary);
+                                       if (!res)
+                                               throw new InvalidOperationException ();
+
+                                       return binary.Item4;
+                               }
+                       }
+
+                       public override bool IsConstant
+                       {
+                               get
+                               {
+                                       Tuple<bool, object, TypeNode> consta;
+                                       TryGetConstantFromCache (out consta);
+
+                                       return consta.Item1;
+                               }
+                       }
+
+                       public override object Constant
+                       {
+                               get
+                               {
+                                       Tuple<bool, object, TypeNode> consta;
+                                       if (!TryGetConstantFromCache (out consta))
+                                               throw new InvalidOperationException ();
+
+                                       return consta.Item2;
+                               }
+                       }
+
+                       public override object ConstantType
+                       {
+                               get
+                               {
+                                       Tuple<bool, object, TypeNode> consta;
+                                       if (!TryGetConstantFromCache (out consta))
+                                               throw new InvalidOperationException();
+
+                                       return consta.Item3;
+                               }
+                       }
+
+                       public override bool IsIsinst
+                       {
+                               get
+                               {
+                                       Tuple<bool, BoxedExpression, TypeNode> isinst;
+                                       TryGetIsInstFromCache (out isinst);
+                                       return isinst.Item1;
+                               }
+                       }
+
+                       public override bool IsNull
+                       {
+                               get { return this.decoder.IsNull (this.expr); }
+                       }
+
+                       public override bool IsUnary
+                       {
+                               get
+                               {
+                                       Tuple<bool, UnaryOperator, BoxedExpression> unary;
+                                       TryGetUnaryFromCache (out unary);
+                                       return unary.Item1;
+                               }
+                       }
+
+                       public override UnaryOperator UnaryOperator
+                       {
+                               get
+                               {
+                                       Tuple<bool, UnaryOperator, BoxedExpression> unary;
+                                       if (!TryGetUnaryFromCache (out unary))
+                                               throw new InvalidOperationException();
+                                       return unary.Item2;
+                               }
+                       }
+
+                       public override BoxedExpression UnaryArgument
+                       {
+                               get
+                               {
+                                       Tuple<bool, UnaryOperator, BoxedExpression> unary;
+                                       if (!TryGetUnaryFromCache (out unary))
+                                               throw new InvalidOperationException ();
+                                       return unary.Item3;
+                               }
+                       }
+
+                       public override bool IsSizeof
+                       {
+                               get
+                               {
+                                       TypeNode type;
+                                       return this.decoder.IsSizeof (this.expr, out type);
+                               }
+                       }
+
+                       public override bool IsVariable
+                       {
+                               get
+                               {
+                                       Pair<bool, object> var1;
+                                       TryGetIsVariableFromCache (out var1);
+                                       return var1.Key;
+                               }
+                       }
+
+                       public override object UnderlyingVariable
+                       {
+                               get
+                               {
+                                       if (!this.var.IsValid)
+                                               this.var = this.decoder.UnderlyingVariable (this.expr);
+
+                                       return this.var.Value;
+                               }
+                       }
+
+                       private bool TryGetBinaryFromCache (out Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary)
+                       {
+                               if (this.binary.IsValid) {
+                                       binary = this.binary.Value;
+                                       return true;
+                               }
+                               BinaryOperator op;
+                               LabeledSymbol left;
+                               LabeledSymbol right;
+                               bool res = this.decoder.IsBinaryExpression (this.expr, out op, out left, out right);
+                               this.binary = binary = new Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> (res, op, For (left, this.decoder), For (right, this.decoder));
+
+                               return res;
+                       }
+
+                       private bool TryGetUnaryFromCache (out Tuple<bool, UnaryOperator, BoxedExpression> unary)
+                       {
+                               if (this.unary.IsValid) {
+                                       unary = this.unary.Value;
+                                       return true;
+                               }
+                               UnaryOperator op;
+                               LabeledSymbol arg;
+                               bool res = this.decoder.IsUnaryExpression (this.expr, out op, out arg);
+                               this.unary = unary = new Tuple<bool, UnaryOperator, BoxedExpression> (res, op, For (arg, this.decoder));
+
+                               return res;
+                       }
+
+                       private bool TryGetIsInstFromCache (out Tuple<bool, BoxedExpression, TypeNode> isinst)
+                       {
+                               if (this.isInst.IsValid) {
+                                       isinst = this.isInst.Value;
+                                       return true;
+                               }
+
+                               LabeledSymbol arg;
+                               TypeNode type;
+                               bool res = this.decoder.IsIsinst (this.expr, out arg, out type);
+                               this.isInst = isinst = new Tuple<bool, BoxedExpression, TypeNode> (res, For (arg, this.decoder), type);
+
+                               return res;
+                       }
+
+                       private bool TryGetConstantFromCache (out Tuple<bool, object, TypeNode> result)
+                       {
+                               if (this.constant.IsValid) {
+                                       result = this.constant.Value;
+                                       return true;
+                               }
+                               object value;
+                               TypeNode type;
+                               bool res = this.decoder.IsConstant (this.expr, out value, out type);
+                               this.constant = result = new Tuple<bool, object, TypeNode> (res, value, type);
+
+                               return res;
+                       }
+
+                       private bool TryGetTypeFromCache (out Pair<bool, TypeNode> result)
+                       {
+                               if (this.type.IsValid) {
+                                       result = this.type.Value;
+                                       return true;
+                               }
+
+                               TypeNode type;
+                               bool res = this.decoder.TryGetType (this.expr, out type);
+                               this.type = result = new Pair<bool, TypeNode> (res, type);
+
+                               return res;
+                       }
+
+                       private bool TryGetIsVariableFromCache (out Pair<bool, object> result)
+                       {
+                               if (this.isVar.IsValid) {
+                                       result = this.isVar.Value;
+                                       return true;
+                               }
+
+                               object value;
+                               bool res = this.decoder.IsVariable (this.expr, out value);
+                               this.isVar = result = new Pair<bool, object> (res, value);
+
+                               return res;
+                       }
+
+                       public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
+                       {
+                               Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> bin;
+                               if (!TryGetBinaryFromCache (out bin) || !bin.Item1) {
+                                       op = BinaryOperator.Add;
+                                       left = null;
+                                       right = null;
+                                       return false;
+                               }
+
+                               op = bin.Item2;
+                               left = bin.Item3;
+                               right = bin.Item4;
+                               return true;
+                       }
+
+                       public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
+                       {
+                               Tuple<bool, BoxedExpression, TypeNode> isinst;
+                               if (!TryGetIsInstFromCache (out isinst) || !isinst.Item1) {
+                                       expr = null;
+                                       type = null;
+                                       return false;
+                               }
+
+                               expr = isinst.Item2;
+                               type = isinst.Item3;
+                               return true;
+                       }
+
+                       public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
+                       {
+                               Tuple<bool, UnaryOperator, BoxedExpression> unary;
+                               if (!TryGetUnaryFromCache (out unary) || !unary.Item1) {
+                                       op = UnaryOperator.Conv_i;
+                                       argument = null;
+                                       return false;
+                               }
+
+                               op = unary.Item2;
+                               argument = unary.Item3;
+                               return true;
+                       }
+
+                       protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
+                       {
+                               return Convert (this.expr, this.decoder).Substitute (what, replace);
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.decoder.AddFreeVariables (this.expr, new SetWrapper (set, this.decoder));
+                       }
+
+                       public override BoxedExpression Substitute<V> (Func<V, BoxedExpression, BoxedExpression> map)
+                       {
+                               return Convert (this.expr, this.decoder).Substitute (map);
+                       }
+
+                       public override bool TryGetType (out object type)
+                       {
+                               Pair<bool, TypeNode> result;
+                               if (!TryGetTypeFromCache (out result) || !result.Key) {
+                                       type = null;
+                                       return false;
+                               }
+
+                               type = result.Value;
+                               return true;
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               Tuple<bool, object, TypeNode> constant;
+                               if (TryGetConstantFromCache (out constant)) {
+                                       if (constant.Item2 != null)
+                                               return visitor.LoadConst (pc, constant.Item3, constant, Dummy.Value, data);
+
+                                       return visitor.LoadNull (pc, Dummy.Value, data);
+                               }
+
+                               UnaryOperator op;
+                               LabeledSymbol arg;
+                               if (this.decoder.IsUnaryExpression (this.expr, out op, out arg))
+                                       return visitor.Unary (pc, op, false, Dummy.Value, Dummy.Value, data);
+
+                               BinaryOperator bop;
+                               LabeledSymbol left;
+                               LabeledSymbol right;
+                               if (this.decoder.IsBinaryExpression (this.expr, out bop, out left, out right))
+                                       return visitor.Binary (pc, bop, Dummy.Value, Dummy.Value, Dummy.Value, data);
+                               TypeNode type;
+                               if (this.decoder.IsIsinst (this.expr, out arg, out type))
+                                       return visitor.Isinst (pc, type, Dummy.Value, Dummy.Value, data);
+                               if (this.decoder.IsNull (this.expr))
+                                       return visitor.LoadNull (pc, Dummy.Value, data);
+                               if (this.decoder.IsSizeof (this.expr, out type))
+                                       return visitor.Sizeof (pc, type, Dummy.Value, data);
+
+                               return visitor.Nop (pc, data);
+                       }
+
+                       #region Nested type: SetWrapper
+                       private struct SetWrapper : ISet<LabeledSymbol>, IEnumerable<LabeledSymbol> {
+                               private readonly IFullExpressionDecoder<Variable, LabeledSymbol> decoder;
+                               private readonly HashSet<BoxedExpression> set;
+
+                               #region Implementation of IEnumerable
+                               public IEnumerator<LabeledSymbol> GetEnumerator ()
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               IEnumerator IEnumerable.GetEnumerator ()
+                               {
+                                       return GetEnumerator ();
+                               }
+                               #endregion
+
+                               public SetWrapper (HashSet<BoxedExpression> set, IFullExpressionDecoder<Variable, LabeledSymbol> decoder)
+                               {
+                                       this.set = set;
+                                       this.decoder = decoder;
+                               }
+
+                               #region Implementation of ICollection<ExternalExpression>
+                               public void Add (LabeledSymbol item)
+                               {
+                                       this.set.Add (For (item, this.decoder));
+                               }
+
+                               bool ISet<LabeledSymbol>.Add (LabeledSymbol item)
+                               {
+                                       Add (item);
+                                       return true;
+                               }
+
+                               public void UnionWith (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public void IntersectWith (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public void ExceptWith (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public void SymmetricExceptWith (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool IsSubsetOf (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool IsSupersetOf (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool IsProperSupersetOf (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool IsProperSubsetOf (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool Overlaps (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool SetEquals (IEnumerable<LabeledSymbol> other)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+
+                               public void Clear ()
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool Contains (LabeledSymbol item)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public void CopyTo (LabeledSymbol[] array, int arrayIndex)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public bool Remove (LabeledSymbol item)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public int Count
+                               {
+                                       get { throw new NotImplementedException (); }
+                               }
+
+                               public bool IsReadOnly
+                               {
+                                       get { throw new NotImplementedException (); }
+                               }
+                               #endregion
+                       }
+                       #endregion
+                       }
+               #endregion
+
+               #region Nested type: IsinstExpression
+               public class IsinstExpression : BoxedExpression {
+                       private readonly BoxedExpression arg;
+                       private readonly TypeNode type;
+
+                       public IsinstExpression (BoxedExpression boxedExpression, TypeNode type)
+                       {
+                               this.arg = boxedExpression;
+                               this.type = type;
+                       }
+
+                       public override bool IsIsinst
+                       {
+                               get { return true; }
+                       }
+
+                       public override BoxedExpression UnaryArgument
+                       {
+                               get { return this.arg; }
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Isinst (pc, this.type, Dummy.Value, Dummy.Value, data);
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.arg.AddFreeVariables (set);
+                       }
+
+                       public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression arg = this.arg.Substitute (map);
+                               if (arg == this.arg)
+                                       return this;
+                               if (arg == null)
+                                       return null;
+
+                               return new IsinstExpression (arg, this.type);
+                       }
+               }
+               #endregion
+
+               #region Nested type: OldExpression
+               public class OldExpression : BoxedExpression {
+                       private const string ContractOldValueTemplate = "Contract.OldValue({0})";
+
+                       public readonly BoxedExpression Old;
+                       public readonly TypeNode Type;
+
+                       public OldExpression (BoxedExpression old, TypeNode type)
+                       {
+                               this.Old = old;
+                               this.Type = type;
+                       }
+
+                       #region Overrides of BoxedExpression
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.Old.AddFreeVariables (set);
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression old = this.Old.Substitute (map);
+                               if (old == this.Old)
+                                       return this;
+                               if (old == null)
+                                       return null;
+
+                               return new OldExpression (old, this.Type);
+                       }
+
+                       public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
+                       {
+                               return this.Old.IsBinaryExpression (out op, out left, out right);
+                       }
+
+                       public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
+                       {
+                               return this.Old.IsUnaryExpression (out op, out argument);
+                       }
+
+                       public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
+                       {
+                               return this.Old.IsIsinstExpression (out expr, out type);
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.EndOld (pc, new PC (pc.Node, 0), this.Type, Dummy.Value, Dummy.Value, data);
+                       }
+                       #endregion
+
+                       public override PathElement[] AccessPath
+                       {
+                               get { return this.Old.AccessPath; }
+                       }
+
+                       public override BoxedExpression BinaryLeftArgument
+                       {
+                               get { return this.Old.BinaryLeftArgument; }
+                       }
+
+                       public override BoxedExpression BinaryRightArgument
+                       {
+                               get { return this.Old.BinaryRightArgument; }
+                       }
+
+                       public override BinaryOperator BinaryOperator
+                       {
+                               get { return this.Old.BinaryOperator; }
+                       }
+
+                       public override object Constant
+                       {
+                               get { return this.Old.Constant; }
+                       }
+
+                       public override object ConstantType
+                       {
+                               get { return this.Old.ConstantType; }
+                       }
+
+                       public override bool IsBinary
+                       {
+                               get { return this.Old.IsBinary; }
+                       }
+
+                       public override bool IsConstant
+                       {
+                               get { return this.Old.IsConstant; }
+                       }
+
+                       public override bool IsSizeof
+                       {
+                               get { return this.Old.IsSizeof; }
+                       }
+
+                       public override bool IsNull
+                       {
+                               get { return this.Old.IsNull; }
+                       }
+
+                       public override bool IsIsinst
+                       {
+                               get { return this.Old.IsIsinst; }
+                       }
+
+                       public override bool IsUnary
+                       {
+                               get { return this.Old.IsUnary; }
+                       }
+
+                       public override bool IsVariable
+                       {
+                               get { return this.Old.IsVariable; }
+                       }
+
+                       public override BoxedExpression UnaryArgument
+                       {
+                               get { return this.Old.UnaryArgument; }
+                       }
+
+                       public override UnaryOperator UnaryOperator
+                       {
+                               get { return this.Old.UnaryOperator; }
+                       }
+
+                       public override object UnderlyingVariable
+                       {
+                               get { return this.Old.UnderlyingVariable; }
+                       }
+               }
+               #endregion
+
+               #region Nested type: PC
+               public struct PC {
+                       public readonly int Index;
+                       public readonly BoxedExpression Node;
+
+                       public PC (BoxedExpression expr, int index)
+                       {
+                               this.Node = expr;
+                               this.Index = index;
+                       }
+               }
+               #endregion
+
+               #region Nested type: ResultExpression
+               public class ResultExpression : BoxedExpression {
+                       private const string ContractResultTemplate = "Contract.Result<{0}>()";
+
+                       public readonly TypeNode Type;
+
+                       public ResultExpression (TypeNode type)
+                       {
+                               this.Type = type;
+                       }
+
+                       public override bool IsResult
+                       {
+                               get { return true; }
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               return this;
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.LoadResult (pc, this.Type, Dummy.Value, Dummy.Value, data);
+                       }
+               }
+               #endregion
+
+               #region Nested type: SizeOfExpression
+               public class SizeOfExpression : BoxedExpression {
+                       public readonly int SizeAsConstant;
+                       public readonly TypeNode Type;
+
+                       public SizeOfExpression (TypeNode type, int sizeAsConstant)
+                       {
+                               this.Type = type;
+                               this.SizeAsConstant = sizeAsConstant;
+                       }
+
+                       public SizeOfExpression (TypeNode type)
+                               : this (type, -1)
+                       {
+                       }
+
+                       public override bool IsSizeof
+                       {
+                               get { return true; }
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               return this;
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Sizeof (pc, this.Type, Dummy.Value, data);
+                       }
+               }
+               #endregion
+
+               #region Nested type: UnaryExpression
+               public class UnaryExpression : BoxedExpression {
+                       public readonly BoxedExpression Argument;
+                       public readonly UnaryOperator Op;
+
+                       public UnaryExpression (UnaryOperator op, BoxedExpression argument)
+                       {
+                               this.Op = op;
+                               this.Argument = argument;
+                       }
+
+                       public override bool IsUnary
+                       {
+                               get { return true; }
+                       }
+
+                       public override BoxedExpression UnaryArgument
+                       {
+                               get { return this.Argument; }
+                       }
+
+                       public override UnaryOperator UnaryOperator
+                       {
+                               get { return this.Op; }
+                       }
+
+                       public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
+                       {
+                               op = this.Op;
+                               argument = this.Argument;
+                               return true;
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.Argument.AddFreeVariables (set);
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression argument = this.Argument.Substitute (map);
+                               if (argument == this.Argument)
+                                       return this;
+                               if (argument == null)
+                                       return null;
+
+                               return new UnaryExpression (this.Op, argument);
+                       }
+
+                       protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
+                       {
+                               BoxedExpression argument = this.Argument.Substitute (what, replace);
+
+                               if (argument == this.Argument)
+                                       return this;
+
+                               return new UnaryExpression (this.Op, argument);
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Unary (pc, this.Op, false, Dummy.Value, Dummy.Value, data);
+                       }
+
+                       public override bool Equals (object obj)
+                       {
+                               if (this == obj)
+                                       return true;
+
+                               var unary = obj as UnaryExpression;
+                               return unary != null && this.Op == unary.Op && this.Argument.Equals (unary.Argument);
+                       }
+
+                       public override int GetHashCode ()
+                       {
+                               return this.Op.GetHashCode () * 13 + (this.Argument == null ? 0 : this.Argument.GetHashCode ());
+                       }
+
+               }
+               #endregion
+
+               #region Nested type: ValueAtReturnExpression
+               public class ValueAtReturnExpression : BoxedExpression {
+                       private const string ContractValueAtReturnTemplate = "Contract.ValueAtReturn({0})";
+
+                       public readonly TypeNode Type;
+                       public readonly BoxedExpression Value;
+
+                       public ValueAtReturnExpression (BoxedExpression old, TypeNode type)
+                       {
+                               this.Value = old;
+                               this.Type = type;
+                       }
+
+                       #region Overrides of BoxedExpression
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               this.Value.AddFreeVariables (set);
+                       }
+
+                       public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
+                       {
+                               BoxedExpression value = this.Value.Substitute (map);
+                               if (value == this.Value)
+                                       return this;
+                               if (value == null)
+                                       return null;
+
+                               return new ValueAtReturnExpression (value, this.Type);
+                       }
+
+                       public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
+                       {
+                               return this.Value.IsBinaryExpression (out op, out left, out right);
+                       }
+
+                       public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
+                       {
+                               return this.Value.IsUnaryExpression (out op, out argument);
+                       }
+
+                       public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
+                       {
+                               return this.Value.IsIsinstExpression (out expr, out type);
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               throw new NotImplementedException ();
+                       }
+                       #endregion
+
+                       public override PathElement[] AccessPath
+                       {
+                               get { return this.Value.AccessPath; }
+                       }
+
+                       public override BoxedExpression BinaryLeftArgument
+                       {
+                               get { return this.Value.BinaryLeftArgument; }
+                       }
+
+                       public override BoxedExpression BinaryRightArgument
+                       {
+                               get { return this.Value.BinaryRightArgument; }
+                       }
+
+                       public override BinaryOperator BinaryOperator
+                       {
+                               get { return this.Value.BinaryOperator; }
+                       }
+
+                       public override object Constant
+                       {
+                               get { return this.Value.Constant; }
+                       }
+
+                       public override object ConstantType
+                       {
+                               get { return this.Value.ConstantType; }
+                       }
+
+                       public override bool IsBinary
+                       {
+                               get { return this.Value.IsBinary; }
+                       }
+
+                       public override bool IsConstant
+                       {
+                               get { return this.Value.IsConstant; }
+                       }
+
+                       public override bool IsSizeof
+                       {
+                               get { return this.Value.IsSizeof; }
+                       }
+
+                       public override bool IsNull
+                       {
+                               get { return this.Value.IsNull; }
+                       }
+
+                       public override bool IsIsinst
+                       {
+                               get { return this.Value.IsIsinst; }
+                       }
+
+                       public override bool IsUnary
+                       {
+                               get { return this.Value.IsUnary; }
+                       }
+
+                       public override bool IsVariable
+                       {
+                               get { return this.Value.IsVariable; }
+                       }
+
+                       public override BoxedExpression UnaryArgument
+                       {
+                               get { return this.Value.UnaryArgument; }
+                       }
+
+                       public override UnaryOperator UnaryOperator
+                       {
+                               get { return this.Value.UnaryOperator; }
+                       }
+
+                       public override object UnderlyingVariable
+                       {
+                               get { return this.Value.UnderlyingVariable; }
+                       }
+               }
+               #endregion
+
+               #region Nested type: VariableExpression
+               public class VariableExpression : BoxedExpression {
+                       private readonly PathElement[] Path;
+                       private readonly object UnderlyingVar;
+                       public readonly object VarType;
+
+                       public VariableExpression (object var)
+                               : this (var, (LispList<PathElement>) null)
+                       {
+                       }
+
+                       public VariableExpression (object var, LispList<PathElement> path)
+                       {
+                               this.UnderlyingVar = var;
+                               this.Path = path != null ? path.AsEnumerable ().ToArray () : null;
+                       }
+
+                       public VariableExpression (object var, LispList<PathElement> path, object type)
+                               : this (var, path)
+                       {
+                               this.VarType = type;
+                       }
+
+                       public VariableExpression (object var, PathElement[] path)
+                       {
+                               this.UnderlyingVar = var;
+                               this.Path = path;
+                       }
+
+                       public VariableExpression (object var, PathElement[] path, object type)
+                               : this (var, path)
+                       {
+                               this.VarType = type;
+                       }
+
+                       public override bool IsVariable
+                       {
+                               get { return true; }
+                       }
+
+                       public override object UnderlyingVariable
+                       {
+                               get { return this.UnderlyingVar; }
+                       }
+
+                       public override PathElement[] AccessPath
+                       {
+                               get { return this.Path; }
+                       }
+
+                       public override bool IsBooleanTyped
+                       {
+                               get { return this.Path != null && this.Path [this.Path.Length - 1].IsBooleanTyped; }
+                       }
+
+                       public override bool TryGetType (out object type)
+                       {
+                               type = this.VarType;
+                               return type != null;
+                       }
+
+                       public override void AddFreeVariables (HashSet<BoxedExpression> set)
+                       {
+                               set.Add (this);
+                       }
+
+                       protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
+                       {
+                               var varExpr = what as VariableExpression;
+                               if (varExpr != null && varExpr.UnderlyingVar.Equals (this.UnderlyingVar))
+                                       return replace;
+
+                               return this;
+                       }
+
+                       public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
+                       {
+                               return visitor.Nop (pc, data);
+                       }
+
+                       public override bool Equals (object obj)
+                       {
+                               if (this == obj)
+                                       return true;
+                               var boxedExpression = obj as BoxedExpression;
+                               if (boxedExpression != null && boxedExpression.IsVariable)
+                                       return this.UnderlyingVar.Equals (boxedExpression.UnderlyingVariable);
+
+                               return false;
+                       }
+
+                       public override int GetHashCode ()
+                       {
+                               return this.UnderlyingVariable != null ? 0 : this.UnderlyingVariable.GetHashCode ();
+                       }
+
+                       public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
+                       {
+                               if (!(this.UnderlyingVar is Variable))
+                                       return this;
+                               var variable = ((Variable) this.UnderlyingVar);
+                               return map (variable, this);
+                       }
+               }
+               #endregion
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs
new file mode 100644 (file)
index 0000000..5c82f79
--- /dev/null
@@ -0,0 +1,56 @@
+// 
+// BoxedExpressionExtensions.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;
+
+namespace Mono.CodeContracts.Static.Proving
+{
+       static class BoxedExpressionExtensions
+       {
+               public static bool IsConstantIntOrNull(this BoxedExpression e, out int res)
+               {
+                       res = 0;
+                       if (e.IsConstant) {
+                               IConvertible convertible = e.Constant as IConvertible;
+                               if (convertible != null) {
+                                       if (e.Constant is string || e.Constant is float || e.Constant is double)
+                                               return false;
+
+                                       try {
+                                               res = convertible.ToInt32 (null);
+                                               return true;
+                                       } catch {
+                                       }
+                               }
+                               if (e.Constant == null)
+                                       return true;
+                       }
+                       return false;
+               }
+       }
+}
\ 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
new file mode 100644 (file)
index 0000000..ff5668b
--- /dev/null
@@ -0,0 +1,184 @@
+// 
+// ComposedFactQuery.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.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Proving
+{
+       class ComposedFactQuery<Variable> : IFactQuery<BoxedExpression, Variable>
+       {
+               private List<IFactQuery<BoxedExpression, Variable>> elements = new List<IFactQuery<BoxedExpression, Variable>> ();
+               private Predicate<APC> isUnreachable;
+
+               public ComposedFactQuery(Predicate<APC> isUnreachable )
+               {
+                       this.isUnreachable = isUnreachable;
+               }
+
+               public void Add(IFactQuery<BoxedExpression, Variable> item )
+               {
+                       if (item == null)
+                               return;
+                       this.elements.Add (item);
+               }
+
+               #region Implementation of IFactBase<Variable>
+               public ProofOutcome IsNull(APC pc, Variable variable)
+               {
+                       return elements.Select(fact => fact.IsNull(pc, variable)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+
+               public ProofOutcome IsNonNull(APC pc, Variable variable)
+               {
+                       return elements.Select(fact => fact.IsNonNull(pc, variable)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+
+               public bool IsUnreachable(APC pc)
+               {
+                       if (this.isUnreachable != null && this.isUnreachable(pc))
+                               return true;
+                       return elements.Any (factQuery => factQuery.IsUnreachable (pc));
+               }
+               #endregion
+
+               #region Implementation of IFactQuery<BoxedExpression,Variable>
+               public ProofOutcome IsNull(APC pc, BoxedExpression expr)
+               {
+                       return elements.Select (fact => fact.IsNull (pc, expr)).FirstOrDefault (factResult => factResult != ProofOutcome.Top);
+               }
+
+               public ProofOutcome IsNonNull(APC pc, BoxedExpression expr)
+               {
+                       return elements.Select(fact => fact.IsNonNull(pc, expr)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+
+               public ProofOutcome IsTrue(APC pc, BoxedExpression expr)
+               {
+                       ProofOutcome 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 (res != ProofOutcome.Top)
+                               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) {
+                                       var outcome = this.IsTrue (pc, left);
+                                       switch (outcome) {
+                                               case ProofOutcome.False:
+                                                       return ProofOutcome.True;
+                                               case ProofOutcome.True:
+                                                       return ProofOutcome.False;
+                                               default:
+                                                       return outcome;
+                                       }
+                               }
+                               int leftInt;
+                               int rightInt;
+                               if (op == BinaryOperator.Ceq && left.IsConstantIntOrNull (out leftInt) && right.IsConstantIntOrNull (out rightInt))
+                                       return leftInt == rightInt ? ProofOutcome.True : ProofOutcome.False;
+                       }
+
+                       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 ProofOutcome.Top;
+               }
+
+               private bool IsRelational(BoxedExpression e)
+               {
+                       BinaryOperator op;
+                       BoxedExpression left;
+                       BoxedExpression right;
+                       if (e.IsBinaryExpression (out op, out left, out right))
+                               switch (op) {
+                                       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 true;
+                               }
+                       return false;
+               }
+
+               public ProofOutcome IsTrueImply(APC pc, LispList<BoxedExpression> positiveAssumptions, LispList<BoxedExpression> negativeAssumptions, BoxedExpression goal)
+               {
+                       return elements.Select(fact => fact.IsTrueImply(pc, positiveAssumptions, negativeAssumptions, goal)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+
+               public ProofOutcome IsGreaterEqualToZero(APC pc, BoxedExpression expr)
+               {
+                       return elements.Select(fact => fact.IsGreaterEqualToZero(pc, expr)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+
+               public ProofOutcome IsLessThan(APC pc, BoxedExpression expr, BoxedExpression right)
+               {
+                       return elements.Select(fact => fact.IsLessThan(pc, expr, right)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+
+               public ProofOutcome IsNonZero(APC pc, BoxedExpression expr)
+               {
+                       return elements.Select(fact => fact.IsNonZero(pc, expr)).FirstOrDefault(factResult => factResult != ProofOutcome.Top);
+               }
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs
new file mode 100644 (file)
index 0000000..2d2a99a
--- /dev/null
@@ -0,0 +1,212 @@
+// 
+// ConstantPropagationFactQuery.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.Linq;
+using Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+namespace Mono.CodeContracts.Static.Proving
+{
+       class ConstantPropagationFactQuery<Variable> : IFactQuery<BoxedExpression, Variable>
+       {
+               #region Implementation of IFactBase<Variable>
+               public ProofOutcome IsNull(APC pc, Variable variable)
+               {
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsNonNull(APC pc, Variable variable)
+               {
+                       return ProofOutcome.Top;
+               }
+
+               public bool IsUnreachable(APC pc)
+               {
+                       return false;
+               }
+               #endregion
+
+               #region Implementation of IFactQuery<BoxedExpression,Variable>
+               public ProofOutcome IsNull(APC pc, BoxedExpression expr)
+               {
+                       int num;
+                       if (expr.IsConstantIntOrNull (out num))
+                               return IsTrueOrTop (num == 0);
+
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsNonNull(APC pc, BoxedExpression expr)
+               {
+                       int num;
+                       if (expr.IsConstantIntOrNull (out num))
+                               return IsTrueOrTop (num != 0);
+
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsTrue(APC pc, BoxedExpression expr)
+               {
+                       int num;
+                       if (expr.IsConstantIntOrNull (out num))
+                               return IsTrueOrTop (num != 0);
+
+                       return ConstantFact (expr);
+               }
+
+
+               public ProofOutcome IsTrueImply(APC pc, LispList<BoxedExpression> positiveAssumptions, LispList<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)))
+                               return ProofOutcome.True;
+
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsGreaterEqualToZero(APC pc, BoxedExpression expr)
+               {
+                       int num;
+                       if (expr.IsConstantIntOrNull(out num))
+                               return IsTrueOrTop(num >= 0);
+
+                       return ProofOutcome.Top;
+               }
+
+               public ProofOutcome 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 ProofOutcome.Top;
+               }
+
+               public ProofOutcome IsNonZero(APC pc, BoxedExpression expr)
+               {
+                       int num;
+                       if (expr.IsConstantIntOrNull(out num))
+                               return IsTrueOrTop (num != 0);
+
+                       return ProofOutcome.Top;
+               }
+
+               private static ProofOutcome IsTrueOrTop(bool condition)
+               {
+                       return condition ? ProofOutcome.True : ProofOutcome.Top;
+               }
+
+               private ProofOutcome ConstantFact(BoxedExpression expr)
+               {
+                       BinaryOperator op;
+                       BoxedExpression left;
+                       BoxedExpression right;
+                       if (expr.IsBinaryExpression (out op, out left, out right)) {
+                               int l;
+                               var leftIsInt = left.IsConstantIntOrNull (out l);
+                               
+                               int r;
+                               var rightIsInt = right.IsConstantIntOrNull(out r);
+
+                               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);
+                                               }
+                                       }
+                                       if (op == BinaryOperator.Ceq && (leftIsInt && l == 0 || rightIsInt && r == 0))
+                                               return this.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));
+                                               case BinaryOperator.Cne_Un:
+                                                       return lConst == null ? IsTrueOrTop (rConst != null) : IsTrueOrTop (!lConst.Equals (rConst));
+                                       }
+                               }
+                       }
+
+                       return ProofOutcome.Top;
+               }
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactBase.cs
new file mode 100644 (file)
index 0000000..e626d67
--- /dev/null
@@ -0,0 +1,37 @@
+// 
+// IFactBase.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 Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Proving {
+       interface IFactBase<Variable> {
+               ProofOutcome IsNull (APC pc, Variable variable);
+               ProofOutcome IsNonNull (APC pc, Variable variable);
+               bool IsUnreachable (APC pc);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/IFactQuery.cs
new file mode 100644 (file)
index 0000000..ad641e7
--- /dev/null
@@ -0,0 +1,42 @@
+// 
+// IFactQuery.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 Mono.CodeContracts.Static.ControlFlow;
+using Mono.CodeContracts.Static.DataStructures;
+
+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);
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs
new file mode 100644 (file)
index 0000000..0f1037e
--- /dev/null
@@ -0,0 +1,115 @@
+// 
+// SimpleLogicInference.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 Mono.CodeContracts.Static.AST;
+using Mono.CodeContracts.Static.Analysis;
+using Mono.CodeContracts.Static.ControlFlow;
+
+namespace Mono.CodeContracts.Static.Proving {
+       class SimpleLogicInference<Expression, Variable> : BasicFacts<Expression, Variable> {
+               public SimpleLogicInference (IExpressionContextProvider<Expression, Variable> contextProvider, IFactBase<Variable> factBase, Predicate<APC> isUnreachable)
+                       : base (contextProvider, factBase, isUnreachable)
+               {
+               }
+
+               public override ProofOutcome IsNull (APC pc, BoxedExpression expr)
+               {
+                       Variable v;
+                       if (TryVariable (expr, out v)) {
+                               ProofOutcome proofOutcome = this.FactBase.IsNull (pc, v);
+                               if (proofOutcome != ProofOutcome.Top)
+                                       return proofOutcome;
+                       }
+
+                       if (expr.IsConstant) {
+                               object constant = expr.Constant;
+                               if (constant == null)
+                                       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;
+                                       }
+                               }
+                       }
+
+                       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)
+                                       return IsNonNull (pc, left);
+                               if (op == BinaryOperator.Cne_Un && IsNull (pc, right) == ProofOutcome.True)
+                                       return IsNull (pc, left);
+                       }
+                       return ProofOutcome.Top;
+               }
+
+               public override ProofOutcome IsNonNull (APC pc, BoxedExpression expr)
+               {
+                       Variable v;
+                       if (TryVariable (expr, out v)) {
+                               ProofOutcome proofOutcome = this.FactBase.IsNonNull (pc, v);
+                               if (proofOutcome != ProofOutcome.Top)
+                                       return proofOutcome;
+                       }
+
+                       if (expr.IsConstant) {
+                               object constant = expr.Constant;
+                               if (constant == null)
+                                       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;
+                                       }
+                               }
+                       }
+
+                       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)
+                                       return IsNull (pc, left);
+                               if (op == BinaryOperator.Cne_Un && IsNull (pc, right) == ProofOutcome.True)
+                                       return IsNonNull (pc, left);
+                       }
+                       return ProofOutcome.Top;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/CheckOptions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/CheckOptions.cs
new file mode 100644 (file)
index 0000000..631a546
--- /dev/null
@@ -0,0 +1,44 @@
+// 
+// CheckOptions.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 {
+       public class CheckOptions {
+               public CheckOptions ()
+               {
+               }
+
+               public string Assembly { get; set; }
+               /// <summary>
+               /// Method name constraint
+               /// If specified, check is performed only on methods containing this name as substring
+               /// </summary>
+               public string Method { get; set; }
+
+               public bool ShowDebug { get; set; }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/CheckResults.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/CheckResults.cs
new file mode 100644 (file)
index 0000000..f8975df
--- /dev/null
@@ -0,0 +1,68 @@
+// 
+// CheckResults.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.Collections.Generic;
+using System.Linq;
+
+namespace Mono.CodeContracts.Static {
+       public class CheckResults {
+               private readonly ICollection<string> warnings;
+               private readonly ICollection<string> errors;
+               private readonly IDictionary<string, ICollection<string>> checker_messages; 
+
+               internal static CheckResults Error(string warning)
+               {
+                       return new CheckResults (new[] {warning}, null, null);
+               }
+
+               internal CheckResults (ICollection<string> warnings, ICollection<string> errors, IDictionary<string, ICollection<string>> checkerMessages)
+               {
+                       this.warnings = warnings;
+                       this.errors = errors;
+                       this.checker_messages = checkerMessages;
+               }
+
+               public bool AnyWarnings { get { return this.warnings != null && this.warnings.Count > 0; }}
+               public bool AnyErrors { get { return this.errors != null && this.errors.Count > 0; } }
+
+               public IEnumerable<string> Warnings
+               {
+                       get { return this.warnings ?? Enumerable.Empty<string> (); }
+               }
+
+               public IEnumerable<string> Errors
+               {
+                       get { return this.errors ?? Enumerable.Empty<string> (); }
+               }
+
+               public IDictionary<string, ICollection<string>> Results
+               {
+                       get { return this.checker_messages ?? null; }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/Checker.cs
new file mode 100644 (file)
index 0000000..22bf987
--- /dev/null
@@ -0,0 +1,136 @@
+// 
+// Checker.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 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.ControlFlow;
+using Mono.CodeContracts.Static.Providers;
+using Mono.CodeContracts.Static.Proving;
+
+namespace Mono.CodeContracts.Static {
+       public class Checker {
+               private readonly CheckOptions options;
+               private CodeContractsAnalysisDriver<IMethodResult<SymbolicValue>> analysis_driver;
+               private Dictionary<string, IMethodAnalysis> analyzers;
+
+               private Checker (CheckOptions options)
+               {
+                       this.options = options;
+               }
+
+               public static CheckResults Check (CheckOptions options)
+               {
+                       var checker = new Checker (options);
+                       return checker.Analyze ();
+               }
+
+               private CheckResults Analyze ()
+               {
+                       if (this.options.Assembly == null)
+                               return CheckResults.Error ("No assembly given to check");
+
+                       DebugOptions.Debug = this.options.ShowDebug;
+
+                       this.analyzers = new Dictionary<string, IMethodAnalysis> {{"non-null", new NonNullAnalysisFacade ()}};
+                       this.analysis_driver = new CodeContractsAnalysisDriver<IMethodResult<SymbolicValue>> (
+                               new BasicAnalysisDriver (MetaDataProvider.Instance, CodeContractDecoder.Instance));
+
+                       return AnalyzeAssembly (this.options.Assembly);
+               }
+
+               private CheckResults AnalyzeAssembly (string assemblyPath)
+               {
+                       IMetaDataProvider metadataDecoder = this.analysis_driver.MetaDataProvider;
+                       AssemblyNode assembly;
+                       string reason;
+                       if (!metadataDecoder.TryLoadAssembly (assemblyPath, out assembly, out reason))
+                               return CheckResults.Error (string.Format ("Cannot load assembly: {0}", reason));
+
+                       var proofResults = new Dictionary<string, ICollection<string>> ();
+                       foreach (Method method in metadataDecoder.Methods (assembly))
+                               AnalyzeMethod (method, proofResults);
+                       if (proofResults.Count == 0)
+                               return CheckResults.Error ("No methods found.");
+
+                       return new CheckResults (null, null, proofResults);
+               }
+
+               private void AnalyzeMethod (Method method, Dictionary<string, ICollection<string>> proofResults)
+               {
+                       IMetaDataProvider metadataDecoder = this.analysis_driver.MetaDataProvider;
+                       if (!metadataDecoder.HasBody (method))
+                               return;
+                       if (this.options.Method != null && !metadataDecoder.FullName (method).Contains (this.options.Method))
+                               return;
+
+                       var results = new List<string> ();
+                       proofResults.Add (method.FullName, results);
+                       try {
+                               AnalyzeMethodInternal (method, results);
+                       } catch (Exception e) {
+                               results.Add ("Exception: " + e.Message);
+                               return;
+                       }
+
+                       results.Add (string.Format ("Checked {0} assertions", results.Count));
+               }
+
+               private void AnalyzeMethodInternal (Method method, List<string> proofResults)
+               {
+                       string fullMethodName = method.FullName;
+                       IMethodDriver<LabeledSymbol<APC, SymbolicValue>, SymbolicValue> methodDriver = this.analysis_driver.CreateMethodDriver (method);
+
+                       methodDriver.RunHeapAndExpressionAnalyses ();
+
+                       var results = new List<IMethodResult<SymbolicValue>> (this.analyzers.Values.Count);
+                       foreach (IMethodAnalysis analysis in this.analyzers.Values) {
+                               IMethodResult<SymbolicValue> result = analysis.Analyze (fullMethodName, methodDriver);
+                               results.Add (result);
+                       }
+
+                       ComposedFactQuery<SymbolicValue> facts = CreateFactQuery (methodDriver.BasicFacts.IsUnreachable, results);
+                       foreach (var methodResult in results)
+                               methodResult.ValidateImplicitAssertions (facts, proofResults);
+
+                       AssertionFinder.ValidateAssertions (facts, methodDriver, proofResults);
+               }
+
+               private ComposedFactQuery<Variable> CreateFactQuery<Variable> (Predicate<APC> isUnreachable, IEnumerable<IMethodResult<Variable>> results)
+               {
+                       var res = new ComposedFactQuery<Variable> (isUnreachable);
+                       res.Add (new ConstantPropagationFactQuery<Variable> ());
+                       foreach (var methodResult in results)
+                               res.Add (methodResult.FactQuery);
+                       return res;
+               }
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/DebugOptions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/DebugOptions.cs
new file mode 100644 (file)
index 0000000..0feb972
--- /dev/null
@@ -0,0 +1,33 @@
+// 
+// DebugOptions.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 DebugOptions {
+               public static bool Debug { get; set; }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcome.cs
new file mode 100644 (file)
index 0000000..2d41225
--- /dev/null
@@ -0,0 +1,36 @@
+// 
+// ProofOutcome.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 {
+       public enum ProofOutcome {
+               Top,
+               True,
+               False,
+               Bottom
+       }
+}
diff --git a/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcomeExtensions.cs b/mcs/class/Mono.CodeContracts/Mono.CodeContracts.Static/ProofOutcomeExtensions.cs
new file mode 100644 (file)
index 0000000..c4b1e04
--- /dev/null
@@ -0,0 +1,73 @@
+// 
+// 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;
+               }
+       }
+}
index e9ab18f8883c9240f1acea16ce0024860730ebbd..c0cfb9d803040174695509bbd532c8a12fe2ea4d 100644 (file)
@@ -35,4 +35,286 @@ Mono.CodeContracts.Rewrite.AstVisitors/CompileVisitor.cs
 Mono.CodeContracts.Rewrite.AstVisitors/ExprVisitor.cs
 Mono.CodeContracts.Rewrite.AstVisitors/InstructionExtentVisitor.cs
 Mono.CodeContracts.Rewrite.AstVisitors/SourcePositionVisitor.cs
-
+Mono.CodeContracts.Static.Analysis.Drivers/AnalysisDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/BasicAnalysisDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/BasicMethodDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/CodeContractsAnalysisDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/IBasicAnalysisDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/IBasicMethodDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysis.cs
+Mono.CodeContracts.Static.Analysis.Drivers/IMethodAnalysisFixPoint.cs
+Mono.CodeContracts.Static.Analysis.Drivers/IMethodDriver.cs
+Mono.CodeContracts.Static.Analysis.Drivers/IMethodResult.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/FullExpressionDecoder.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/IFullExpressionDecoder.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/QueryVisitor.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsBinaryExpression.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsInst.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsNull.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForIsUnaryExpression.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForSizeOf.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForUnderlyingVariable.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForValueOf.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariable.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding/VisitorForVariablesIn.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/BinaryExpr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/ConstExpr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/Expr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/IsInstExpr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/NullExpr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/SizeOfExpr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions/UnaryExpr.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AnalysisDecoder.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/AssumeDecoder.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExprDomain.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionAnalysisFacade.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoder.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionDecoderAdapter.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ExpressionPrinterFactory.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ILDecoderAdapter.cs
+Mono.CodeContracts.Static.Analysis.ExpressionAnalysis/ValueAnalysis.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/AccessPathFilter.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/IVisibilityCheck.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/MethodCallPathElement.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/ParameterPathElement.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElementBase.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathElement`1.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/PathExtensions.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElement.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths/SpecialPathElementKind.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/AbstractDomainUpdate.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EdgeUpdate.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EliminateEdgeUpdate.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityPair.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/EqualityUpdate.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/IMergeInfo.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MergeInfo.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdge.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/MultiEdgeUpdate.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraph.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/SymGraphTerm.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph/Update.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/AbstractType.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/AnalysisDecoder.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/Domain.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/FunctionsTable.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/HeapAnalysis.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/IAbstractDomainForEGraph.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/IConstantInfo.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/ISymGraph.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/LabeledSymbol.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/MethodWrapper.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/ParameterWrapper.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/StackToSymbolicAdapter.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymbolicValue.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymFunction.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/SymValue.cs
+Mono.CodeContracts.Static.Analysis.HeapAnalysis/TypeCache.cs
+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/ExpressionAssertDischarger.cs
+Mono.CodeContracts.Static.Analysis.NonNull/ExpressionAssumeDecoder.cs
+Mono.CodeContracts.Static.Analysis.NonNull/NonNullAnalysisFacade.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/APCMap.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/SequenceGenerator.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDecoder.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthFactory.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/StackDepthProvider.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo.cs
+Mono.CodeContracts.Static.Analysis.StackAnalysis/StackInfo`1.cs
+Mono.CodeContracts.Static.Analysis/CodeLayer.cs
+Mono.CodeContracts.Static.Analysis/CodeLayerFactory.cs
+Mono.CodeContracts.Static.Analysis/ICodeLayer.cs
+Mono.CodeContracts.Static.Analysis/IExpressionContext.cs
+Mono.CodeContracts.Static.Analysis/IExpressionContextProvider.cs
+Mono.CodeContracts.Static.Analysis/ILPrinter.cs
+Mono.CodeContracts.Static.Analysis/IMethodContext.cs
+Mono.CodeContracts.Static.Analysis/IMethodContextProvider.cs
+Mono.CodeContracts.Static.Analysis/IStackContext.cs
+Mono.CodeContracts.Static.Analysis/IStackContextProvider.cs
+Mono.CodeContracts.Static.Analysis/IValueContext.cs
+Mono.CodeContracts.Static.Analysis/IValueContextProvider.cs
+Mono.CodeContracts.Static.Analysis/PrinterFactory.cs
+Mono.CodeContracts.Static.AST.Visitors/CodeVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/DefaultNodeVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/IAggregateVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/ICodeConsumer.cs
+Mono.CodeContracts.Static.AST.Visitors/IExpressionILVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/IILVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/ILVisitorBase.cs
+Mono.CodeContracts.Static.AST.Visitors/IMethodCodeConsumer.cs
+Mono.CodeContracts.Static.AST.Visitors/ISymbolicExpressionVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/ISyntheticILVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/NodeInspector.cs
+Mono.CodeContracts.Static.AST.Visitors/NodeVisitor.cs
+Mono.CodeContracts.Static.AST.Visitors/ValueCodeVisitor.cs
+Mono.CodeContracts.Static.AST/ArrayTypeNode.cs
+Mono.CodeContracts.Static.AST/AssemblyNode.cs
+Mono.CodeContracts.Static.AST/AssignmentStatement.cs
+Mono.CodeContracts.Static.AST/BinaryExpression.cs
+Mono.CodeContracts.Static.AST/BinaryOperator.cs
+Mono.CodeContracts.Static.AST/Block.cs
+Mono.CodeContracts.Static.AST/BlockExpression.cs
+Mono.CodeContracts.Static.AST/BodyParser.cs
+Mono.CodeContracts.Static.AST/Branch.cs
+Mono.CodeContracts.Static.AST/CatchFilter.cs
+Mono.CodeContracts.Static.AST/Class.cs
+Mono.CodeContracts.Static.AST/Construct.cs
+Mono.CodeContracts.Static.AST/CoreSystemTypes.cs
+Mono.CodeContracts.Static.AST/EndFinally.cs
+Mono.CodeContracts.Static.AST/Ensures.cs
+Mono.CodeContracts.Static.AST/ExceptionHandler.cs
+Mono.CodeContracts.Static.AST/Expression.cs
+Mono.CodeContracts.Static.AST/ExpressionStatement.cs
+Mono.CodeContracts.Static.AST/FaultHandler.cs
+Mono.CodeContracts.Static.AST/Field.cs
+Mono.CodeContracts.Static.AST/Literal.cs
+Mono.CodeContracts.Static.AST/Local.cs
+Mono.CodeContracts.Static.AST/Member.cs
+Mono.CodeContracts.Static.AST/MemberBinding.cs
+Mono.CodeContracts.Static.AST/Method.cs
+Mono.CodeContracts.Static.AST/MethodCall.cs
+Mono.CodeContracts.Static.AST/MethodContract.cs
+Mono.CodeContracts.Static.AST/MethodContractElement.cs
+Mono.CodeContracts.Static.AST/Module.cs
+Mono.CodeContracts.Static.AST/NaryExpression.cs
+Mono.CodeContracts.Static.AST/Node.cs
+Mono.CodeContracts.Static.AST/NodeType.cs
+Mono.CodeContracts.Static.AST/OperatorExtensions.cs
+Mono.CodeContracts.Static.AST/Parameter.cs
+Mono.CodeContracts.Static.AST/Property.cs
+Mono.CodeContracts.Static.AST/Reference.cs
+Mono.CodeContracts.Static.AST/Requires.cs
+Mono.CodeContracts.Static.AST/Return.cs
+Mono.CodeContracts.Static.AST/Statement.cs
+Mono.CodeContracts.Static.AST/This.cs
+Mono.CodeContracts.Static.AST/TypeNode.cs
+Mono.CodeContracts.Static.AST/UnaryExpression.cs
+Mono.CodeContracts.Static.AST/UnaryOperator.cs
+Mono.CodeContracts.Static.AST/Variable.cs
+Mono.CodeContracts.Static.ContractExtraction/ContractExtractor.cs
+Mono.CodeContracts.Static.ContractExtraction/ContractNodes.cs
+Mono.CodeContracts.Static.ContractExtraction/GatherLocals.cs
+Mono.CodeContracts.Static.ContractExtraction/HelperMethods.cs
+Mono.CodeContracts.Static.ContractExtraction/RepresentationForAttribute.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/AssumeBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/BlockBase.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/BlockWithLabels.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/CatchFilterEntryBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/EnsuresBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/EntryBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/EntryExitBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/LabelAdapter.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/MethodCallBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Blocks/NewObjCallBlock.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockBuilder.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/BlockStartGatherer.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/EnsuresFactory.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/RequiresFactory.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SimpleSubroutineBuilder.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineBuilder.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineFactory.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders/SubroutineWithHandlersBuilder.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/EnsuresSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultFinallySubroutineBase.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/FaultSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/FinallySubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodContractSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/MethodSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/OldScanStateMachine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/OldValueSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/RequiresSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/SimpleSubroutine.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineBase.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineFacade.cs
+Mono.CodeContracts.Static.ControlFlow.Subroutines/SubroutineWithHandlers.cs
+Mono.CodeContracts.Static.ControlFlow/APC.cs
+Mono.CodeContracts.Static.ControlFlow/APCDecoder.cs
+Mono.CodeContracts.Static.ControlFlow/CFGBlock.cs
+Mono.CodeContracts.Static.ControlFlow/ContractFilteredCFG.cs
+Mono.CodeContracts.Static.ControlFlow/ControlFlowGraph.cs
+Mono.CodeContracts.Static.ControlFlow/Edge.cs
+Mono.CodeContracts.Static.ControlFlow/EdgeMap.cs
+Mono.CodeContracts.Static.ControlFlow/EdgeTag.cs
+Mono.CodeContracts.Static.ControlFlow/EdgeTagExtensions.cs
+Mono.CodeContracts.Static.ControlFlow/EdgeVisitor.cs
+Mono.CodeContracts.Static.ControlFlow/ICFG.cs
+Mono.CodeContracts.Static.ControlFlow/IConstantInfo.cs
+Mono.CodeContracts.Static.ControlFlow/IHandlerFilter.cs
+Mono.CodeContracts.Static.ControlFlow/IMethodInfo.cs
+Mono.CodeContracts.Static.ControlFlow/IStackInfo.cs
+Mono.CodeContracts.Static.ControlFlow/RemoveBranchDelegator.cs
+Mono.CodeContracts.Static.ControlFlow/Subroutine.cs
+Mono.CodeContracts.Static.ControlFlow/SubroutineKind.cs
+Mono.CodeContracts.Static.DataFlowAnalysis/DataFlowAnalysisBase.cs
+Mono.CodeContracts.Static.DataFlowAnalysis/EdgeBasedWidening.cs
+Mono.CodeContracts.Static.DataFlowAnalysis/EdgeConverter.cs
+Mono.CodeContracts.Static.DataFlowAnalysis/ForwardAnalysis.cs
+Mono.CodeContracts.Static.DataFlowAnalysis/ForwardDataFlowAnalysisBase.cs
+Mono.CodeContracts.Static.DataFlowAnalysis/IAnalysis.cs
+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/AbstractWorkList.cs
+Mono.CodeContracts.Static.DataStructures/DecoratorHelper.cs
+Mono.CodeContracts.Static.DataStructures/DepthFirst.cs
+Mono.CodeContracts.Static.DataStructures/DoubleDictionary.cs
+Mono.CodeContracts.Static.DataStructures/DoubleImmutableMap.cs
+Mono.CodeContracts.Static.DataStructures/Dummy.cs
+Mono.CodeContracts.Static.DataStructures/EdgeVisitor.cs
+Mono.CodeContracts.Static.DataStructures/GraphWrapper.cs
+Mono.CodeContracts.Static.DataStructures/IGraph.cs
+Mono.CodeContracts.Static.DataStructures/IImmutableIntMap.cs
+Mono.CodeContracts.Static.DataStructures/IImmutableMap.cs
+Mono.CodeContracts.Static.DataStructures/IImmutableSet.cs
+Mono.CodeContracts.Static.DataStructures/IIndexable.cs
+Mono.CodeContracts.Static.DataStructures/ImmutableIntKeyMap.cs
+Mono.CodeContracts.Static.DataStructures/ImmutableIntMap.cs
+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/IWorkList.cs
+Mono.CodeContracts.Static.DataStructures/LispList.cs
+Mono.CodeContracts.Static.DataStructures/LispListExtensions.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/VisitStatus.cs
+Mono.CodeContracts.Static.DataStructures/WorkList.cs
+Mono.CodeContracts.Static.Extensions/Extensions.cs
+Mono.CodeContracts.Static.Lattices/EnvironmentDomain.cs
+Mono.CodeContracts.Static.Lattices/FlatDomain.cs
+Mono.CodeContracts.Static.Lattices/IAbstractDomain.cs
+Mono.CodeContracts.Static.Lattices/SetDomain.cs
+Mono.CodeContracts.Static.Providers/CodeContractDecoder.cs
+Mono.CodeContracts.Static.Providers/CodeProviderImpl.cs
+Mono.CodeContracts.Static.Providers/ICodeProvider.cs
+Mono.CodeContracts.Static.Providers/IContractProvider.cs
+Mono.CodeContracts.Static.Providers/IILDecoder.cs
+Mono.CodeContracts.Static.Providers/IMetaDataProvider.cs
+Mono.CodeContracts.Static.Providers/IMethodCodeProvider.cs
+Mono.CodeContracts.Static.Providers/MetaDataProvider.cs
+Mono.CodeContracts.Static.Proving/AssertionFinder.cs
+Mono.CodeContracts.Static.Proving/BasicFacts.cs
+Mono.CodeContracts.Static.Proving/BoxedExpression.cs
+Mono.CodeContracts.Static.Proving/BoxedExpressionExtensions.cs
+Mono.CodeContracts.Static.Proving/ComposedFactQuery.cs
+Mono.CodeContracts.Static.Proving/ConstantPropagationFactQuery.cs
+Mono.CodeContracts.Static.Proving/IFactBase.cs
+Mono.CodeContracts.Static.Proving/IFactQuery.cs
+Mono.CodeContracts.Static.Proving/SimpleLogicInference.cs
+Mono.CodeContracts.Static/CheckResults.cs
+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
index e0442cccf4586948502970974b2ae09df65a6240..0a52ada1294908a7ec29e67ffe1814c3f59d9517 100644 (file)
@@ -43,6 +43,7 @@ net_4_0_dirs := \
        lc              \
        mono-configuration-crypto \
        ccrewrite       \
+       cccheck         \
        security
 
 net_2_0_dirs := \
diff --git a/mcs/tools/cccheck/Makefile b/mcs/tools/cccheck/Makefile
new file mode 100644 (file)
index 0000000..86c53f6
--- /dev/null
@@ -0,0 +1,9 @@
+thisdir = tools/cccheck
+SUBDIRS = 
+include ../../build/rules.make
+
+PROGRAM = cccheck.exe
+
+LOCAL_MCS_FLAGS = -r:Mono.CodeContracts.dll
+
+include ../../build/executable.make
diff --git a/mcs/tools/cccheck/Program.cs b/mcs/tools/cccheck/Program.cs
new file mode 100644 (file)
index 0000000..ec5b665
--- /dev/null
@@ -0,0 +1,66 @@
+using System;
+using Mono.CodeContracts.Static;
+using Mono.Options;
+
+namespace cccheck {
+       internal class Program {
+               private static void Main (string[] args)
+               {
+                       var options = new CheckOptions ();
+                       bool showOptions = false;
+                       string showMsg = null;
+
+                       var optionSet = new OptionSet {
+                                                       {"help", "Show this help.", v => showOptions = v != null},
+                                                       {"assembly=", "Assembly to check.", v => options.Assembly = v},
+                                                       {"method=", "Method name (if you want to check only it).", v => options.Method = v},
+                                                       {"debug=", "Show debug information", v=> options.ShowDebug = v != null}
+                                                     };
+
+                       try {
+                               optionSet.Parse (args);
+                       } catch (OptionException e) {
+                               showOptions = true;
+                               showMsg = e.Message;
+                       }
+
+                       if (showOptions) {
+                               Console.WriteLine ("cccheck");
+                               Console.WriteLine ();
+                               Console.WriteLine ("Options:");
+                               optionSet.WriteOptionDescriptions (Console.Out);
+                               Console.WriteLine ();
+                               if (showMsg != null) {
+                                       Console.WriteLine (showMsg);
+                                       Console.WriteLine ();
+                               }
+                               return;
+                       }
+
+                       CheckResults results = Checker.Check (options);
+                       Console.WriteLine ();
+                       if (results.AnyErrors) {
+                               foreach (string error in results.Errors)
+                                       Console.WriteLine ("Error: " + error);
+                       }
+
+                       if (results.AnyWarnings) {
+                               foreach (string warning in results.Warnings)
+                                       Console.WriteLine ("Warning: " + warning);
+                       }
+
+                       if (results.Results != null) {
+                               foreach (var methodValidationResults in results.Results) {
+                                       string methodName = methodValidationResults.Key;
+                                       Console.WriteLine ("Method: " + methodName);
+                                       foreach (string result in methodValidationResults.Value)
+                                               Console.WriteLine ("  " + result);
+                                       Console.WriteLine ();
+                               }
+                       }
+
+                       Console.WriteLine ();
+                       Console.WriteLine ("*** done ***");
+               }
+       }
+}
diff --git a/mcs/tools/cccheck/cccheck.exe.sources b/mcs/tools/cccheck/cccheck.exe.sources
new file mode 100644 (file)
index 0000000..7324142
--- /dev/null
@@ -0,0 +1,3 @@
+../../build/common/Consts.cs
+../../class/Mono.Options/Mono.Options/Options.cs
+Program.cs