Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
//
// AbstractInterpretationException.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class AbstractInterpretationException : Exception {
public AbstractInterpretationException (string message)
: base (message)
{
}
}
}

View File

@@ -0,0 +1,52 @@
//
// Analysers.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.Analysis.Drivers;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
static class Analysers {
public enum ArithmeticEnvironmentKind {
Intervals,
DisIntervals
}
public class Arithmetic : IMethodAnalysis {
public string Name { get { return "Arithmetic"; } }
public IMethodResult<TVar> Analyze<TExpr, TVar> (string fullMethodName,
IMethodDriver<TExpr, TVar> methodDriver)
where TVar : IEquatable<TVar>
where TExpr : IEquatable<TExpr>
{
return AnalysisFacade.RunArithmeticAnalysis (fullMethodName, methodDriver);
}
}
}
}

View File

@@ -0,0 +1,150 @@
//
// Analysis.ConstantEvaluator.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.ControlFlow;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Lattices;
using Mono.CodeContracts.Static.Providers;
using Mono.CodeContracts.Static.Proving;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
static partial class AnalysisFacade {
static partial class Bind<TVar, TExpr>
where TExpr : IEquatable<TExpr>
where TVar : IEquatable<TVar> {
class ConstantEvaluator {
readonly IExpressionContextProvider<TExpr, TVar> context_provider;
readonly IMetaDataProvider meta_data_provider;
public ConstantEvaluator (IExpressionContextProvider<TExpr, TVar> contextProvider,
IMetaDataProvider metaDataProvider)
{
context_provider = contextProvider;
meta_data_provider = metaDataProvider;
}
public bool TryEvaluateToConstant (APC pc, TVar dest, BinaryOperator op,
BoxedExpression left, BoxedExpression right,
out long value)
{
var type =
context_provider.ValueContext.GetType (
context_provider.MethodContext.CFG.Post (pc), dest);
long l;
long r;
if (type.IsNormal () && TryEvaluateToConstant (pc, left, out l) &&
TryEvaluateToConstant (pc, right, out r))
return TryEvaluate (type.Value, op, l, r, out value);
return false.Without (out value);
}
bool TryEvaluate (TypeNode type, BinaryOperator op, long l, long r, out long value)
{
if (TryEvaluateIndependent (op, l, r, out value))
return true;
if (meta_data_provider.System_Int32.Equals (type))
return TryEvaluateInt32 (op, (int) l, (int) r, out value);
return false.Without (out value);
}
static bool TryEvaluateInt32 (BinaryOperator op, int l, int r, out long value)
{
int result;
if (EvaluateArithmeticWithOverflow.TryBinary (op.ToExpressionOperator (), l, r,
out result))
return true.With (result, out value);
return false.Without (out value);
}
bool TryEvaluateIndependent (BinaryOperator op, long l, long r, out long result)
{
switch (op) {
case BinaryOperator.And:
return true.With (l & r, out result);
case BinaryOperator.Ceq:
return true.With (ToInt (l == r), out result);
case BinaryOperator.Cne_Un:
return true.With (ToInt (l != r), out result);
case BinaryOperator.Cge:
return true.With (ToInt (l >= r), out result);
case BinaryOperator.Cgt:
return true.With (ToInt (l > r), out result);
case BinaryOperator.Cle:
return true.With (ToInt (l <= r), out result);
case BinaryOperator.Clt:
return true.With (ToInt (l < r), out result);
case BinaryOperator.LogicalAnd:
return true.With (ToInt (l != 0 && r != 0), out result);
case BinaryOperator.LogicalOr:
return true.With (ToInt (l != 0 || r != 0), out result);
case BinaryOperator.Or:
return true.With (l | r, out result);
case BinaryOperator.Xor:
return true.With (l ^ r, out result);
default:
return false.Without (out result);
}
}
static long ToInt (bool value)
{
return value ? 1 : 0;
}
static bool TryEvaluateToConstant (APC pc, BoxedExpression e, out long result)
{
int res;
if (e.IsConstantIntOrNull (out res))
return true.With (res, out result);
long argValue;
if (e.IsUnary && TryEvaluateToConstant (pc, e.UnaryArgument, out argValue)) {
switch (e.UnaryOperator) {
case UnaryOperator.Neg:
return true.With (-argValue, out result);
case UnaryOperator.Not:
return true.With (argValue != 0 ? 0L : 1L, out result);
default:
throw new ArgumentOutOfRangeException ();
}
}
return false.Without (out result);
}
}
}
}
}

View File

@@ -0,0 +1,113 @@
//
// Analysis.GenericNumericalAnalysis.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.Analysis.Drivers;
using Mono.CodeContracts.Static.ControlFlow;
using Mono.CodeContracts.Static.DataFlowAnalysis;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Lattices;
using Mono.CodeContracts.Static.Proving;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
static partial class AnalysisFacade {
static partial class Bind<TVar, TExpr> where TExpr : IEquatable<TExpr> where TVar : IEquatable<TVar> {
class GenericNumericalAnalysis :
GenericValueAnalysis<INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression>> {
readonly Analysers.ArithmeticEnvironmentKind env_kind;
public GenericNumericalAnalysis (string methodName,
IMethodDriver<TExpr, TVar> methodDriver,
Analysers.ArithmeticEnvironmentKind envKind)
: base (methodName, methodDriver)
{
env_kind = envKind;
}
public override INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression>
TopValue ()
{
switch (env_kind) {
case Analysers.ArithmeticEnvironmentKind.Intervals:
return
new IntervalEnvironment<BoxedVariable<TVar>, BoxedExpression> (
ExpressionDecoder);
case Analysers.ArithmeticEnvironmentKind.DisIntervals:
return
new DisIntervalEnvironment<BoxedVariable<TVar>, BoxedExpression>
(ExpressionDecoder);
default:
throw new AbstractInterpretationException (
"Unknown arithmetic environment kind.");
}
}
public override IFactQuery<BoxedExpression, TVar> FactQuery
(IFixPointInfo
<APC, INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression>
> fixpoint)
{
return new ConstantPropagationFactQuery<TVar> ();
}
public override INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> Entry
(APC pc, Method method,
INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> data)
{
foreach (var param in MetaDataProvider.Parameters (method).AsEnumerable ()) {
TVar variable;
var readAt = ContextProvider.MethodContext.CFG.Post (pc);
if (!ContextProvider.ValueContext.TryParameterValue (readAt, param, out variable))
continue;
var abstractType = ContextProvider.ValueContext.GetType (readAt,
variable);
if (abstractType.IsNormal () && MetaDataProvider.IsPrimitive (abstractType.Value))
data = SetInitialRange (variable, abstractType.Value, data);
}
return data;
}
INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> SetInitialRange
(TVar variable, TypeNode type,
INumericalEnvironmentDomain<BoxedVariable<TVar>, BoxedExpression> data)
{
var interval = Interval.Ranges.GetIntervalForType (type,
MetaDataProvider);
if (interval.IsNormal ())
data = data.AssumeVariableIn (new BoxedVariable<TVar> (variable),
interval);
return data;
}
}
}
}
}

View File

@@ -0,0 +1,275 @@
//
// Analysis.GenericValueAnalysis.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.AST.Visitors;
using Mono.CodeContracts.Static.Analysis.Drivers;
using Mono.CodeContracts.Static.ControlFlow;
using Mono.CodeContracts.Static.DataFlowAnalysis;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Lattices;
using Mono.CodeContracts.Static.Providers;
using Mono.CodeContracts.Static.Proving;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
static partial class AnalysisFacade {
static partial class Bind<TVar, TExpr> where TExpr : IEquatable<TExpr> where TVar : IEquatable<TVar> {
abstract class GenericValueAnalysis<TDomain> :
ILVisitorBase<APC, TVar, TVar, TDomain, TDomain>,
IAbstractAnalysis<TDomain, TVar>,
IMethodResult<TVar>
where TDomain : IEnvironmentDomain<TDomain, BoxedVariable<TVar>, BoxedExpression> {
readonly IMethodDriver<TExpr, TVar> method_driver;
//readonly string method_name;
protected ConstantEvaluator EvaluatorOfConstants;
protected IFixPointInfo<APC, TDomain> FixPointInfo;
BoxedExpressionDecoder<TVar, TExpr> expression_decoder;
protected GenericValueAnalysis (string methodName,
IMethodDriver<TExpr, TVar> methodDriver)
{
ThresholdDB.Reset ();
BoxedVariable<TVar>.ResetFreshVariableCounter ();
// method_name = methodName;
method_driver = methodDriver;
EvaluatorOfConstants = new ConstantEvaluator (ContextProvider,
MetaDataProvider);
}
protected IExpressionContextProvider<TExpr, TVar> ContextProvider { get { return method_driver.ContextProvider; } }
protected IMetaDataProvider MetaDataProvider { get { return method_driver.MetaDataProvider; } }
protected BoxedExpressionDecoder<TVar, TExpr> ExpressionDecoder
{
get
{
if (expression_decoder == null)
expression_decoder =
new BoxedExpressionDecoder<TVar, TExpr> (
new ValueExpressionDecoder<TVar, TExpr> (
MetaDataProvider,
ContextProvider));
return expression_decoder;
}
}
public IILVisitor<APC, TVar, TVar, TDomain, TDomain> GetVisitor ()
{
return this;
}
public TDomain Join (Pair<APC, APC> edge, TDomain newstate, TDomain prevstate,
out bool weaker, bool widen)
{
TDomain result;
if (!widen) {
result = Join (newstate, prevstate, edge);
weaker = true;
}
else {
result = Widen (newstate, prevstate, edge);
weaker = !result.LessEqual (prevstate);
}
return result;
}
public TDomain ImmutableVersion (TDomain arg)
{
return arg;
}
public TDomain MutableVersion (TDomain arg)
{
return arg.Clone ();
}
public virtual TDomain EdgeConversion (APC @from, APC to, bool isJoinPoint,
IImmutableMap<TVar, Sequence<TVar>>
sourceTargetMap, TDomain state)
{
return state;
}
public bool IsBottom (APC pc, TDomain state)
{
return state.IsBottom;
}
public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, TDomain> fixPointInfo)
{
FixPointInfo = fixPointInfo;
return a => false;
}
public void Dump (Pair<TDomain, TextWriter> pair)
{
pair.Value.WriteLine (pair.Key.ToString ());
}
public abstract TDomain TopValue ();
public TDomain BottomValue ()
{
return TopValue ().Bottom;
}
public abstract IFactQuery<BoxedExpression, TVar> FactQuery (
IFixPointInfo<APC, TDomain> fixpoint);
IFactQuery<BoxedExpression, TVar> IMethodAnalysisFixPoint<TVar>.FactQuery { get { return FactQuery (FixPointInfo); } }
public FlatDomain<bool> ValidateExplicitAssertion (APC pc, TVar value)
{
return FlatDomain<bool>.TopValue;
}
public IMethodAnalysis MethodAnalysis { get; set; }
public void ValidateImplicitAssertions (IFactQuery<BoxedExpression, TVar> facts,
List<string> proofResults)
{
}
protected virtual TDomain Widen (TDomain newState, TDomain prevState,
Pair<APC, APC> edge)
{
return newState.Widen (prevState);
}
protected virtual TDomain Join (TDomain newState, TDomain prevState, Pair<APC, APC> edge)
{
return newState.Join (prevState);
}
public override TDomain Assume (APC pc, EdgeTag tag, TVar condition, TDomain data)
{
var boxed = ToBoxedExpression (pc, condition);
if (tag != EdgeTag.False) {
bool value;
if (boxed.IsTrivialCondition (out value))
return !value ? data.Bottom : data;
}
List<int> thresholds;
if (ThresholdDB.TryGetAThreshold (boxed, expression_decoder, out thresholds))
ThresholdDB.Add (thresholds);
TDomain result;
switch (tag) {
case EdgeTag.True:
case EdgeTag.Requires:
case EdgeTag.Assume:
case EdgeTag.Invariant:
result = data.AssumeTrue (boxed);
break;
case EdgeTag.False:
result = data.AssumeFalse (boxed);
break;
default:
result = data;
break;
}
if (tag != EdgeTag.False) {
var abstractType =
ContextProvider.ValueContext.GetType (
ContextProvider.MethodContext.CFG.Post (pc), condition);
if (abstractType.IsNormal () &&
MetaDataProvider.Equal (abstractType.Value,
MetaDataProvider.System_Boolean)) {
var guard =
BoxedExpression.Binary (BinaryOperator.Ceq, boxed,
BoxedExpression.Const (1,
MetaDataProvider
.
System_Int32));
result = result.AssumeTrue (guard);
}
}
return result;
}
public override TDomain Assert (APC pc, EdgeTag tag, TVar condition, TDomain data)
{
var boxed = ToBoxedExpression (pc, condition);
bool result;
if (boxed.IsTrivialCondition (out result))
return result ? data : data.Bottom;
data = data.AssumeTrue (boxed);
var type =
ContextProvider.ValueContext.GetType (
ContextProvider.MethodContext.CFG.Post (pc), condition);
if (type.IsNormal () &&
MetaDataProvider.Equal (type.Value, MetaDataProvider.System_Boolean)) {
var guard =
BoxedExpression.Binary (BinaryOperator.Ceq, boxed,
BoxedExpression.Const (1,
MetaDataProvider.
System_Int32));
data = data.AssumeTrue (guard);
}
return data;
}
public override TDomain DefaultVisit (APC pc, TDomain data)
{
return data;
}
protected BoxedExpression ToBoxedExpression (APC pc, TVar condition)
{
return
BoxedExpression.For (
ContextProvider.ExpressionContext.Refine (pc, condition),
ExpressionDecoder.ExternalDecoder);
}
public IFactQuery<BoxedExpression, TVar> FactQuery ()
{
return FactQuery (FixPointInfo);
}
}
}
}
}

View File

@@ -0,0 +1,66 @@
//
// Analysis.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.Analysis.Drivers;
using Mono.CodeContracts.Static.DataFlowAnalysis;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
static partial class AnalysisFacade {
public static IMethodResult<TVar> RunArithmeticAnalysis<TVar, TExpr> (string methodName,
IMethodDriver<TExpr, TVar>
methodDriver)
where TVar : IEquatable<TVar>
where TExpr : IEquatable<TExpr>
{
return Bind<TVar, TExpr>.RunArithmeticAnalysis (methodName, methodDriver);
}
static partial class Bind<TVar, TExpr> where TExpr : IEquatable<TExpr> where TVar : IEquatable<TVar> {
public static IMethodResult<TVar> RunArithmeticAnalysis (string methodName,
IMethodDriver<TExpr, TVar> methodDriver)
{
var analysis = new GenericNumericalAnalysis (methodName, methodDriver,
Analysers.ArithmeticEnvironmentKind.
DisIntervals);
return RunAnalysis (methodName, methodDriver, analysis);
}
public static IMethodResult<TVar> RunAnalysis<TDomain> (string methodName,
IMethodDriver<TExpr, TVar> methodDriver,
IAbstractAnalysis<TDomain, TVar>
analysis)
{
methodDriver.HybridLayer.CreateForward (analysis).Invoke (analysis.TopValue ());
return analysis as IMethodResult<TVar>;
}
}
}
}

View File

@@ -0,0 +1,85 @@
//
// AssumeFalseVisitor.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.Analysis.Numerical {
abstract class AssumeFalseVisitor<TDomain, TVar, TExpr> :
GenericExpressionVisitor<TDomain, TDomain, TVar, TExpr>
where TDomain : IEnvironmentDomain<TDomain, TVar, TExpr> {
protected AssumeFalseVisitor (IExpressionDecoder<TVar, TExpr> decoder)
: base (decoder)
{
}
public AssumeTrueVisitor<TDomain, TVar, TExpr> TrueVisitor { get; set; }
protected override TDomain Default (TDomain data)
{
return data;
}
public override TDomain VisitConstant (TExpr left, TDomain data)
{
bool boolValue;
if (Decoder.TryValueOf (left, ExpressionType.Bool, out boolValue))
return boolValue ? data : data.Bottom;
int intValue;
if (Decoder.TryValueOf (left, ExpressionType.Int32, out intValue))
return intValue != 0 ? data : data.Bottom;
return data;
}
public override TDomain VisitNot (TExpr expr, TDomain data)
{
return TrueVisitor.Visit (expr, data);
}
public override TDomain VisitEqual (TExpr left, TExpr right, TExpr original, TDomain data)
{
int value;
if (Decoder.TryValueOf (right, ExpressionType.Int32, out value) && value == 0)
// test (left :neq: 0) ==> test (left)
return TrueVisitor.Visit (left, data);
return TrueVisitor.VisitNotEqual (left, right, original, data);
}
public override TDomain VisitLessThan (TExpr left, TExpr right, TExpr original, TDomain data)
{
// !(left < right) ==> right <= left
return TrueVisitor.VisitLessEqualThan (right, left, original, data);
}
public override TDomain VisitLessEqualThan (TExpr left, TExpr right, TExpr original, TDomain data)
{
// !(left <= right) ==> right < left
return TrueVisitor.VisitLessThan (right, left, original, data);
}
}
}

View File

@@ -0,0 +1,108 @@
//
// AssumeTrueVisitor.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Lattices;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
abstract class AssumeTrueVisitor<TDomain, TVar, TExpr> : GenericExpressionVisitor<TDomain, TDomain, TVar, TExpr>
where TDomain : IEnvironmentDomain<TDomain, TVar, TExpr> {
protected AssumeTrueVisitor (IExpressionDecoder<TVar, TExpr> decoder)
: base (decoder)
{
}
public AssumeFalseVisitor<TDomain, TVar, TExpr> FalseVisitor { get; set; }
protected override TDomain Default (TDomain data)
{
return data;
}
public override TDomain VisitConstant (TExpr left, TDomain data)
{
bool boolValue;
if (Decoder.TryValueOf (left, ExpressionType.Bool, out boolValue))
return boolValue ? data : data.Bottom;
int intValue;
if (Decoder.TryValueOf (left, ExpressionType.Int32, out intValue))
return intValue != 0 ? data : data.Bottom;
return data;
}
public override TDomain VisitLogicalAnd (TExpr left, TExpr right, TExpr original, TDomain data)
{
var leftIsVariable = Decoder.IsVariable (left);
var rightIsVariable = Decoder.IsVariable (right);
var leftIsConstant = Decoder.IsConstant (left);
var rightIsConstant = Decoder.IsConstant (right);
if (leftIsVariable && rightIsConstant || leftIsConstant && rightIsVariable)
return data;
return data.AssumeTrue (left).AssumeTrue (right);
}
public override TDomain VisitLogicalOr (TExpr left, TExpr right, TExpr original, TDomain data)
{
var leftIsVariable = Decoder.IsVariable (left);
var rightIsVariable = Decoder.IsVariable (right);
var leftIsConstant = Decoder.IsConstant (left);
var rightIsConstant = Decoder.IsConstant (right);
if (leftIsVariable && rightIsConstant || leftIsConstant && rightIsVariable)
return data;
var leftBranch = data.AssumeTrue (left);
var rightBranch = data.AssumeTrue (right);
return leftBranch.Join (rightBranch);
}
public override TDomain VisitNot (TExpr expr, TDomain data)
{
return FalseVisitor.Visit (expr, data);
}
protected override bool TryPolarity (TExpr expr, TDomain data, out bool shouldNegate)
{
if (base.TryPolarity (expr, data, out shouldNegate))
return true;
var holds = data.CheckIfHolds (expr);
if (!holds.IsNormal ())
return false.Without (out shouldNegate);
return true.With (!holds.Value, out shouldNegate);
}
}
}

View File

@@ -0,0 +1,291 @@
//
// BoxedExpressionDecoder.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Proving;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class BoxedExpressionDecoder<TVar, TExpr> : IExpressionDecoder<BoxedVariable<TVar>, BoxedExpression> {
public IFullExpressionDecoder<TVar, TExpr> ExternalDecoder { get; private set; }
public BoxedExpressionDecoder (IFullExpressionDecoder<TVar, TExpr> externalDecoder)
{
ExternalDecoder = externalDecoder;
}
public ExpressionOperator OperatorFor (BoxedExpression expr)
{
if (expr.IsVariable)
return ExpressionOperator.Variable;
if (expr.IsConstant)
return ExpressionOperator.Constant;
if (expr.IsSizeof)
return ExpressionOperator.SizeOf;
if (expr.IsUnary)
switch (expr.UnaryOperator) {
case UnaryOperator.Conv_i:
case UnaryOperator.Conv_i4:
case UnaryOperator.Conv_i8:
return ExpressionOperator.ConvertToInt32;
case UnaryOperator.Neg:
return ExpressionOperator.UnaryMinus;
case UnaryOperator.Not:
return ExpressionOperator.Not;
default:
return ExpressionOperator.Unknown;
}
if (!expr.IsBinary)
return ExpressionOperator.Unknown;
switch (expr.BinaryOperator) {
case BinaryOperator.Add:
return ExpressionOperator.Add;
case BinaryOperator.And:
return ExpressionOperator.And;
case BinaryOperator.Ceq:
return ExpressionOperator.Equal;
case BinaryOperator.Cobjeq:
return ExpressionOperator.Equal_Obj;
case BinaryOperator.Cne_Un:
return ExpressionOperator.NotEqual;
case BinaryOperator.Cge:
return ExpressionOperator.GreaterEqualThan;
case BinaryOperator.Cgt:
return ExpressionOperator.GreaterThan;
case BinaryOperator.Cle:
return ExpressionOperator.LessEqualThan;
case BinaryOperator.Clt:
return ExpressionOperator.LessThan;
case BinaryOperator.Div:
return ExpressionOperator.Div;
case BinaryOperator.LogicalAnd:
return ExpressionOperator.LogicalAnd;
case BinaryOperator.LogicalOr:
return ExpressionOperator.LogicalOr;
case BinaryOperator.Mul:
return ExpressionOperator.Mult;
case BinaryOperator.Or:
return ExpressionOperator.Or;
case BinaryOperator.Rem:
return ExpressionOperator.Mod;
case BinaryOperator.Sub:
return ExpressionOperator.Sub;
case BinaryOperator.Xor:
return ExpressionOperator.Xor;
default:
return ExpressionOperator.Unknown;
}
}
public BoxedExpression LeftExpressionFor (BoxedExpression expr)
{
if (expr.IsBinary)
return expr.BinaryLeftArgument;
if (expr.IsUnary)
return expr.UnaryArgument;
throw new InvalidOperationException ();
}
public BoxedExpression RightExpressionFor (BoxedExpression expr)
{
if (expr.IsBinary)
return expr.BinaryRightArgument;
throw new InvalidOperationException ();
}
public ExpressionType TypeOf (BoxedExpression expr)
{
if (expr.IsConstant) {
var constant = expr.Constant;
if (constant == null)
return ExpressionType.Unknown;
var convertible = constant as IConvertible;
if (convertible != null)
switch (convertible.GetTypeCode ()) {
case TypeCode.Boolean:
return ExpressionType.Bool;
case TypeCode.Int32:
return ExpressionType.Int32;
case TypeCode.Single:
return ExpressionType.Float32;
case TypeCode.Double:
return ExpressionType.Float64;
}
return ExpressionType.Unknown;
}
if (expr.IsUnary) {
switch (expr.UnaryOperator) {
case UnaryOperator.Conv_i4:
return ExpressionType.Int32;
case UnaryOperator.Conv_r4:
return ExpressionType.Float32;
case UnaryOperator.Conv_r8:
case UnaryOperator.Conv_r_un:
return ExpressionType.Float64;
case UnaryOperator.Not:
return ExpressionType.Bool;
default:
return ExpressionType.Int32;
}
}
if (expr.IsBinary)
switch (expr.BinaryOperator) {
case BinaryOperator.Add:
case BinaryOperator.Add_Ovf:
case BinaryOperator.Add_Ovf_Un:
case BinaryOperator.Div:
case BinaryOperator.Div_Un:
case BinaryOperator.Mul:
case BinaryOperator.Mul_Ovf:
case BinaryOperator.Mul_Ovf_Un:
case BinaryOperator.Rem:
case BinaryOperator.Rem_Un:
case BinaryOperator.Sub:
case BinaryOperator.Sub_Ovf:
case BinaryOperator.Sub_Ovf_Un:
return Join (TypeOf (expr.BinaryLeftArgument),
TypeOf (expr.BinaryRightArgument));
case BinaryOperator.Ceq:
case BinaryOperator.Cobjeq:
case BinaryOperator.Cne_Un:
case BinaryOperator.Cge:
case BinaryOperator.Cge_Un:
case BinaryOperator.Cgt:
case BinaryOperator.Cgt_Un:
case BinaryOperator.Cle:
case BinaryOperator.Cle_Un:
case BinaryOperator.Clt:
case BinaryOperator.Clt_Un:
return ExpressionType.Bool;
default:
return ExpressionType.Int32;
}
return ExpressionType.Unknown;
}
public BoxedVariable<TVar> UnderlyingVariable (BoxedExpression expr)
{
var uv = expr.UnderlyingVariable;
if (uv is TVar)
return new BoxedVariable<TVar> ((TVar) expr.UnderlyingVariable);
var boxed = uv as BoxedVariable<TVar>;
return boxed ?? BoxedVariable<TVar>.SlackVariable ();
}
public bool IsConstant (BoxedExpression expr)
{
return expr.IsConstant;
}
public bool IsVariable (BoxedExpression expr)
{
return expr.IsVariable;
}
public bool TryValueOf<T> (BoxedExpression expr, ExpressionType type, out T result)
{
if (!expr.IsConstant)
return false.Without (out result);
var constant = expr.Constant;
if (constant == null)
return false.Without (out result);
if (constant is T)
return true.With ((T) constant, out result);
if (constant is string)
return false.Without (out result);
var convertible = constant as IConvertible;
if (convertible != null)
try {
return true.With ((T) convertible.ToType (typeof (T), null), out result);
}
catch {
}
return false.Without (out result);
}
public bool TrySizeOf (BoxedExpression expr, out int size)
{
return expr.Sizeof (out size);
}
public bool IsNull (BoxedExpression expr)
{
return expr.IsConstant && expr.IsNull;
}
public bool IsConstantInt (BoxedExpression expr, out int value)
{
return expr.IsConstantIntOrNull (out value);
}
public string NameOf (BoxedVariable<TVar> variable)
{
return variable.ToString ();
}
public bool IsBinaryExpression (BoxedExpression expr)
{
return expr.IsBinary;
}
ExpressionType Join (ExpressionType left, ExpressionType right)
{
if (left == right)
return left;
if (left == ExpressionType.Unknown)
return right;
if (right == ExpressionType.Unknown)
return left;
if (left == ExpressionType.Float32 || right == ExpressionType.Float32)
return ExpressionType.Float32;
if (left == ExpressionType.Float64 || right == ExpressionType.Float64)
return ExpressionType.Float64;
return left;
}
}
}

View File

@@ -0,0 +1,149 @@
//
// BoxedExpressionEncoder.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.Providers;
using Mono.CodeContracts.Static.Proving;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class BoxedExpressionEncoder<TVar> : IExpressionEncoder<BoxedVariable<TVar>, BoxedExpression> {
readonly IMetaDataProvider metadata;
public BoxedExpressionEncoder (IMetaDataProvider metadata)
{
this.metadata = metadata;
}
public void ResetFreshVariableCounter ()
{
BoxedVariable<TVar>.ResetFreshVariableCounter ();
}
public BoxedVariable<TVar> FreshVariable ()
{
return BoxedVariable<TVar>.SlackVariable ();
}
public BoxedExpression VariableFor (BoxedVariable<TVar> var)
{
return BoxedExpression.Var (var);
}
public BoxedExpression ConstantFor (object value)
{
if (value is int)
return BoxedExpression.Const (value, metadata.System_Int32);
if (value is long) {
var val = (long) value;
return val < int.MaxValue && val > int.MinValue
? BoxedExpression.Const (val, metadata.System_Int32)
: BoxedExpression.Const (val, metadata.System_Int64);
}
if (value is short)
return BoxedExpression.Const (value, metadata.System_Int16);
if (value is sbyte)
return BoxedExpression.Const (value, metadata.System_Int8);
if (value is bool)
return BoxedExpression.Const (value, metadata.System_Boolean);
throw new NotSupportedException ();
}
public BoxedExpression CompoundFor (ExpressionType type, ExpressionOperator op, BoxedExpression arg)
{
return BoxedExpression.Unary (ToUnaryOperator (op), arg);
}
public BoxedExpression CompoundFor (ExpressionType type, ExpressionOperator op, BoxedExpression left,
BoxedExpression right)
{
return BoxedExpression.Binary (ToBinaryOperator (op), left, right);
}
public static IExpressionEncoder<BoxedVariable<TVar>, BoxedExpression> Encoder (
IMetaDataProvider provider)
{
return new BoxedExpressionEncoder<TVar> (provider);
}
BinaryOperator ToBinaryOperator (ExpressionOperator op)
{
switch (op) {
case ExpressionOperator.And:
return BinaryOperator.And;
case ExpressionOperator.Or:
return BinaryOperator.Or;
case ExpressionOperator.Xor:
return BinaryOperator.Xor;
case ExpressionOperator.Equal:
return BinaryOperator.Ceq;
case ExpressionOperator.Equal_Obj:
return BinaryOperator.Cobjeq;
case ExpressionOperator.NotEqual:
return BinaryOperator.Cne_Un;
case ExpressionOperator.LessThan:
return BinaryOperator.Clt;
case ExpressionOperator.LessEqualThan:
return BinaryOperator.Cle_Un;
case ExpressionOperator.GreaterThan:
return BinaryOperator.Cgt;
case ExpressionOperator.GreaterEqualThan:
return BinaryOperator.Cge;
case ExpressionOperator.Add:
return BinaryOperator.Add;
case ExpressionOperator.Sub:
return BinaryOperator.Sub;
case ExpressionOperator.Mult:
return BinaryOperator.Mul;
case ExpressionOperator.Div:
return BinaryOperator.Div;
case ExpressionOperator.Mod:
return BinaryOperator.Rem;
default:
throw new ArgumentOutOfRangeException ("op");
}
}
UnaryOperator ToUnaryOperator (ExpressionOperator op)
{
switch (op) {
case ExpressionOperator.Not:
return UnaryOperator.Not;
case ExpressionOperator.UnaryMinus:
return UnaryOperator.Neg;
default:
throw new ArgumentOutOfRangeException ("op");
}
}
}
}

View File

@@ -0,0 +1,181 @@
//
// BoxedVariable.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class BoxedVariable<TVar> : IEquatable<BoxedVariable<TVar>> {
readonly InnerVariable inner_variable;
readonly VariableKind kind;
readonly TVar variable;
public BoxedVariable (TVar variable)
{
if (variable != null) {
this.variable = variable;
inner_variable = null;
kind = VariableKind.Normal;
}
else {
this.variable = default(TVar);
inner_variable = new InnerVariable ();
kind = VariableKind.Slack;
}
}
BoxedVariable ()
{
variable = default (TVar);
inner_variable = new InnerVariable ();
kind = VariableKind.Slack;
}
public bool Equals (BoxedVariable<TVar> that)
{
if (ReferenceEquals (this, that))
return true;
if (ReferenceEquals (that, null))
return false;
if (inner_variable != null)
return inner_variable.Equals (that.inner_variable);
return variable != null && variable.Equals (that.variable);
}
public override bool Equals (object obj)
{
if (ReferenceEquals (this, obj))
return true;
if (obj is TVar && inner_variable == null)
return variable.Equals (obj);
var that = obj as BoxedVariable<TVar>;
if (that != null) {
if (inner_variable != null)
return inner_variable.Equals (that.inner_variable);
if (variable != null)
return variable.Equals (that.variable);
}
return false;
}
public override int GetHashCode ()
{
return inner_variable != null
? inner_variable.GetHashCode ()
: variable.GetHashCode ();
}
public override string ToString ()
{
if (kind == VariableKind.Slack)
return "s" + inner_variable;
if (inner_variable != null)
return inner_variable.ToString ();
return variable.ToString ();
}
public bool TryUnpackVariable (out TVar value)
{
if (inner_variable != null)
return false.Without (out value);
return true.With (variable, out value);
}
public static BoxedVariable<TVar> SlackVariable ()
{
return new BoxedVariable<TVar> ();
}
public static void ResetFreshVariableCounter ()
{
InnerVariable.ResetFreshVariableCounter ();
}
#region Nested type: InnerVariable
class InnerVariable {
static int count;
static int start_count;
readonly int id;
readonly int start_id;
public InnerVariable ()
{
id = count++;
start_id = start_count++;
}
public override bool Equals (object obj)
{
if (ReferenceEquals (this, obj))
return true;
var innerVariable = obj as InnerVariable;
return innerVariable != null && innerVariable.id == id;
}
public override int GetHashCode ()
{
return id;
}
public override string ToString ()
{
return string.Format ("iv{0}", id - start_id);
}
public static void ResetFreshVariableCounter ()
{
start_count = count;
}
}
#endregion
#region Nested type: VariableKind
enum VariableKind {
Normal,
Slack
}
#endregion
}
}

View File

@@ -0,0 +1,73 @@
//
// ConstToIntervalEvaluator.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class ConstToIntervalEvaluator<TContext, TVar, TExpr, TInterval, TNumeric> :
GenericTypeExpressionVisitor<TVar, TExpr, TContext, TInterval>
where TContext : IntervalContextBase<TInterval, TNumeric>
where TVar : IEquatable<TVar>
where TInterval : IntervalBase<TInterval, TNumeric> {
public ConstToIntervalEvaluator (IExpressionDecoder<TVar, TExpr> decoder)
: base (decoder)
{
}
public override TInterval Visit (TExpr e, TContext ctx)
{
if (!ReferenceEquals (e, null) && Decoder.IsConstant (e))
return base.Visit (e, ctx);
return Default (e, ctx);
}
protected override TInterval VisitBool (TExpr expr, TContext ctx)
{
bool value;
if (Decoder.TryValueOf (expr, ExpressionType.Bool, out value))
return ctx.For (value ? 1L : 0L);
return Default (expr, ctx);
}
protected override TInterval VisitInt32 (TExpr expr, TContext ctx)
{
int value;
if (Decoder.TryValueOf (expr, ExpressionType.Int32, out value))
return ctx.For (value);
return Default (expr, ctx);
}
protected override TInterval Default (TExpr expr, TContext ctx)
{
return ctx.TopValue;
}
}
}

View File

@@ -0,0 +1,172 @@
//
// ConstantEvaluatorVisitor.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
abstract class ConstantEvaluatorVisitor<In, Out> {
protected virtual bool Default (out Out result)
{
return false.Without (out result);
}
protected bool VisitBinary (ExpressionOperator o, In left, In right, out Out result)
{
try {
switch (o) {
case ExpressionOperator.And:
return VisitAnd (left, right, out result);
case ExpressionOperator.Or:
return VisitOr (left, right, out result);
case ExpressionOperator.Xor:
return VisitXor (left, right, out result);
case ExpressionOperator.LogicalAnd:
return VisitLogicalAnd (left, right, out result);
case ExpressionOperator.LogicalOr:
return VisitLogicalOr (left, right, out result);
case ExpressionOperator.Equal:
case ExpressionOperator.Equal_Obj:
return VisitEqual (left, right, out result);
case ExpressionOperator.NotEqual:
return VisitNotEqual (left, right, out result);
case ExpressionOperator.LessThan:
return VisitLessThan (left, right, out result);
case ExpressionOperator.LessEqualThan:
return VisitLessEqualThan (left, right, out result);
case ExpressionOperator.GreaterThan:
return VisitGreaterThan (left, right, out result);
case ExpressionOperator.GreaterEqualThan:
return VisitGreaterEqualThan (left, right, out result);
case ExpressionOperator.Add:
return VisitAdd (left, right, out result);
case ExpressionOperator.Sub:
return VisitSub (left, right, out result);
case ExpressionOperator.Mult:
return VisitMult (left, right, out result);
case ExpressionOperator.Div:
return VisitDiv (left, right, out result);
case ExpressionOperator.Mod:
return VisitMod (left, right, out result);
case ExpressionOperator.Unknown:
return VisitUnknown (left, out result);
}
throw new ArgumentOutOfRangeException ("not implemented");
}
catch (ArithmeticException) {
return false.Without (out result);
}
}
protected virtual bool VisitMod (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitDiv (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitMult (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitSub (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitGreaterEqualThan (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitGreaterThan (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitLessEqualThan (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitLessThan (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitNotEqual (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitEqual (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitLogicalOr (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitLogicalAnd (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitXor (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitOr (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitAnd (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitAdd (In left, In right, out Out result)
{
return Default (out result);
}
protected virtual bool VisitUnknown (In left, out Out result)
{
return Default (out result);
}
}
}

View File

@@ -0,0 +1,55 @@
//
// Counter.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.Analysis.Numerical {
struct Counter<T> {
public readonly int Count;
public readonly T Env;
public Counter (T env)
: this (env, 0)
{
}
Counter (T env, int count)
{
Env = env;
Count = count;
}
public Counter<T> Incremented ()
{
return new Counter<T> (Env, Count + 1);
}
public override string ToString ()
{
return string.Format ("{0} ({1})", Env, Count);
}
}
}

View File

@@ -0,0 +1,69 @@
//
// DisIntervalAssumer.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class DisIntervalAssumer<Var, Expr> : IntervalRationalAssumerBase<Var, Expr, DisInterval>
where Var : IEquatable<Var> {
public override IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> AssumeNotEqualToZero
(Var var, IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> env)
{
return AssumeEqualToDisInterval (var, DisInterval.NotZero, env);
}
static IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> AssumeEqualToDisInterval
(Var var, DisInterval intv, IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> env)
{
return env.RefineVariable (var, intv);
}
public override IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> AssumeNotEqual
(Expr left, Expr right, IntervalEnvironmentBase<Var, Expr, DisInterval, Rational> env)
{
var result = env;
var rightIntv = env.Eval (right);
if (rightIntv.IsSinglePoint) {
var everythingExcept = DisInterval.EverythingExcept (rightIntv);
result = result.RefineVariable (env.Decoder.UnderlyingVariable (left), everythingExcept);
}
IntervalInference.InferenceResult<Var, DisInterval> resultLeft;
IntervalInference.InferenceResult<Var, DisInterval> resultRight;
IntervalInference.ConstraintsFor.NotEqual (left, right, env.Decoder, result, out resultLeft,
out resultRight);
var join = resultLeft.Join (resultRight);
if (join.IsBottom)
return env.Bottom as IntervalEnvironmentBase<Var, Expr, DisInterval, Rational>;
return AssumeConstraints (join.Constraints, env);
}
}
}

View File

@@ -0,0 +1,139 @@
//
// DisIntervalContext.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.CodeContracts.Static.Lattices;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class DisIntervalContext : IntervalRationalContextBase<DisInterval> {
public static readonly DisIntervalContext Instance = new DisIntervalContext ();
DisIntervalContext ()
{
}
public override DisInterval TopValue { get { return DisInterval.TopValue; } }
public override DisInterval BottomValue { get { return DisInterval.BottomValue; } }
public override DisInterval Zero { get { return DisInterval.For (Interval.For (Rational.Zero)); } }
public override DisInterval One { get { return DisInterval.For (Interval.For (Rational.One)); } }
public override DisInterval Positive { get { return DisInterval.For (Interval.For (Rational.Zero, Rational.PlusInfinity)); } }
public override DisInterval Negative { get { return DisInterval.For (Interval.For (Rational.MinusInfinity, Rational.Zero)); } }
public override DisInterval GreaterEqualThanMinusOne { get { return DisInterval.For (Interval.For (Rational.MinusOne, Rational.PlusInfinity)); } }
public override DisInterval For (long value)
{
return DisInterval.For (Interval.For (value));
}
public override DisInterval For (long lower, long upper)
{
return DisInterval.For (Interval.For (lower, upper));
}
public override DisInterval For (long lower, Rational upper)
{
return DisInterval.For (Interval.For (lower, upper));
}
public override DisInterval For (Rational lower, long upper)
{
return DisInterval.For (Interval.For (lower, upper));
}
public override DisInterval For (Rational value)
{
return DisInterval.For (Interval.For (value));
}
public override DisInterval For (Rational lower, Rational upper)
{
return DisInterval.For (Interval.For (lower, upper));
}
public override DisInterval Add (DisInterval a, DisInterval b)
{
return a + b;
}
public override DisInterval Sub (DisInterval a, DisInterval b)
{
return a - b;
}
public override DisInterval Div (DisInterval a, DisInterval b)
{
return a / b;
}
public override DisInterval Rem (DisInterval a, DisInterval b)
{
return TopValue;
}
public override DisInterval Mul (DisInterval a, DisInterval b)
{
return a * b;
}
public override DisInterval Not (DisInterval value)
{
if (!value.IsNormal ())
return value;
if (value.IsNotZero)
return Zero;
if (value.IsPositiveOrZero)
return Negative;
return TopValue;
}
public override DisInterval UnaryMinus (DisInterval value)
{
return -value;
}
public override DisInterval ApplyConversion (ExpressionOperator conv, DisInterval intv)
{
return intv.Select ((i) => Interval.ApplyConversion (conv, i));
}
public override DisInterval RightOpen (Rational lowerBound)
{
return DisInterval.For (Interval.For (lowerBound, Rational.PlusInfinity));
}
public override DisInterval LeftOpen (Rational lowerBound)
{
return DisInterval.For (Interval.For (Rational.MinusInfinity, lowerBound));
}
}
}

View File

@@ -0,0 +1,73 @@
//
// DisIntervalEnvironment.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.CodeContracts.Static.Lattices;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class DisIntervalEnvironment<TVar, TExpr> :
IntervalEnvironmentBase<TVar, TExpr, DisInterval, Rational> where TVar : IEquatable<TVar> {
static DisIntervalAssumer<TVar, TExpr> cached_assumer;
DisIntervalEnvironment (IExpressionDecoder<TVar, TExpr> decoder,
EnvironmentDomain<TVar, DisInterval> varsToInterval)
: base (decoder, varsToInterval)
{
}
public DisIntervalEnvironment (IExpressionDecoder<TVar, TExpr> decoder)
: base (decoder)
{
}
public override IntervalAssumerBase<TVar, TExpr, DisInterval, Rational> Assumer
{
get
{
return cached_assumer ??
(cached_assumer = new DisIntervalAssumer<TVar, TExpr> ());
}
}
public override IntervalContextBase<DisInterval, Rational> Context { get { return DisIntervalContext.Instance; } }
protected override IntervalEnvironmentBase<TVar, TExpr, DisInterval, Rational> NewInstance (
EnvironmentDomain<TVar, DisInterval> varsToIntervals)
{
return new DisIntervalEnvironment<TVar, TExpr> (Decoder, varsToIntervals);
}
public override IntervalEnvironmentBase<TVar, TExpr, DisInterval, Rational> AssumeVariableIn (TVar var,
Interval
interval)
{
return RefineVariable (var, DisInterval.For (interval));
}
}
}

View File

@@ -0,0 +1,66 @@
//
// EvaluateArithmeticWithOverflow.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
static class EvaluateArithmeticWithOverflow {
public static bool TryBinary (ExpressionOperator op, long left, long right, out int res)
{
return LongToIntegerConstantEvaluator.Evaluate (op, left, right, out res);
}
public static bool TryBinary (ExpressionOperator op, long left, long right, out uint res)
{
return false.Without (out res);
}
public static bool TryBinary<In> (ExpressionType targetType, ExpressionOperator op, In left, In right,
out object res)
where In : struct
{
switch (targetType) {
case ExpressionType.Unknown:
case ExpressionType.Bool:
return false.Without (out res);
case ExpressionType.Int32:
var l = left.ConvertToLong ();
var r = right.ConvertToLong ();
int intValue;
if (l.HasValue && r.HasValue && TryBinary (op, l.Value, r.Value, out intValue))
return true.With (intValue, out res);
break;
}
return false.Without (out res);
}
}
}

View File

@@ -0,0 +1,219 @@
//
// EvaluateExpressionVisitor.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2012 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.Analysis.Numerical {
class EvaluateExpressionVisitor<TEnv, TVar, TExpr, TInterval, TNumeric> :
GenericExpressionVisitor<Counter<TEnv>, TInterval, TVar, TExpr>
where TEnv : IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>
where TVar : IEquatable<TVar>
where TInterval : IntervalBase<TInterval, TNumeric> {
readonly
ConstToIntervalEvaluator
<IntervalContextBase<TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> constToIntv;
readonly VariableOccurences occurences;
public Sequence<TVar> DuplicatedOccurences { get { return occurences.Duplicated; } }
public EvaluateExpressionVisitor (IExpressionDecoder<TVar, TExpr> decoder)
: base (decoder)
{
occurences = new VariableOccurences (decoder);
constToIntv =
new ConstToIntervalEvaluator
<IntervalContextBase<TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> (
decoder);
}
public override TInterval Visit (TExpr expr, Counter<TEnv> data)
{
if (data.Count >= 10) // to avoid recursion if any
return Default (data);
var intv = base.Visit (expr, data.Incremented ());
if (intv == null)
return Default (data);
intv = RefineWithTypeRanges (intv, expr, data.Env);
var var = Decoder.UnderlyingVariable (expr);
TInterval current;
if (data.Env.TryGetValue (var, out current))
intv = intv.Meet (current);
return intv;
}
public override TInterval VisitConstant (TExpr expr, Counter<TEnv> data)
{
return constToIntv.Visit (expr, data.Env.Context);
}
public override TInterval VisitAddition (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Add (l, r));
}
public override TInterval VisitDivision (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Div (l, r));
}
public override TInterval VisitMultiply (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Mul (l, r));
}
public override TInterval VisitSubtraction (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Sub (l, r));
}
public override TInterval VisitEqual (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultComparisons (left, right, data);
}
public override TInterval VisitLessThan (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultComparisons (left, right, data);
}
public override TInterval VisitGreaterEqualThan (TExpr left, TExpr right, TExpr original,
Counter<TEnv> data)
{
return DefaultComparisons (left, right, data);
}
public override TInterval VisitLessEqualThan (TExpr left, TExpr right, TExpr original,
Counter<TEnv> data)
{
return DefaultComparisons (left, right, data);
}
public override TInterval VisitGreaterThan (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
{
return DefaultComparisons (left, right, data);
}
public override TInterval VisitUnknown (TExpr expr, Counter<TEnv> data)
{
occurences.Add (expr);
return Default (data);
}
protected override TInterval Default (Counter<TEnv> data)
{
return data.Env.Context.TopValue;
}
delegate TInterval BinaryEvaluator (Counter<TEnv> env, TInterval left, TInterval right);
TInterval DefaultBinary (TExpr left, TExpr right, Counter<TEnv> data, BinaryEvaluator binop)
{
occurences.Add (left, right);
var incremented = data.Incremented ();
var leftIntv = Visit (left, incremented);
var rightIntv = Visit (right, incremented);
return binop (data, leftIntv, rightIntv);
}
TInterval DefaultComparisons (TExpr left, TExpr right, Counter<TEnv> data)
{
occurences.Add (left, right);
return Default (data);
}
TInterval RefineWithTypeRanges (TInterval intv, TExpr expr, TEnv env)
{
switch (Decoder.TypeOf (expr)) {
case ExpressionType.Int32:
return env.Context.ApplyConversion (ExpressionOperator.ConvertToInt32, intv);
case ExpressionType.Bool:
return env.Context.ApplyConversion (ExpressionOperator.ConvertToInt32, intv);
default:
return intv;
}
}
class VariableOccurences {
readonly Dictionary<TVar, int> occurences;
readonly IExpressionDecoder<TVar, TExpr> decoder;
Sequence<TVar> duplicated;
public VariableOccurences (IExpressionDecoder<TVar, TExpr> decoder)
{
this.decoder = decoder;
occurences = new Dictionary<TVar, int> ();
duplicated = Sequence<TVar>.Empty;
}
public Sequence<TVar> Duplicated { get { return duplicated; } }
void Add (TVar var)
{
int cnt;
if (!occurences.TryGetValue (var, out cnt))
cnt = 0;
occurences[var] = cnt + 1;
if (cnt == 1) // if already was occurence
duplicated = duplicated.Cons (var);
}
public void Add (TExpr e)
{
Add (decoder.UnderlyingVariable (e));
}
public void Add (params TExpr[] exprs)
{
foreach (var expr in exprs)
Add (expr);
}
public override string ToString ()
{
return occurences.ToString ();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More