2 // EvaluateExpressionVisitor.cs
5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2012 Alexander Chebaturkin
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections.Generic;
32 using Mono.CodeContracts.Static.DataStructures;
34 namespace Mono.CodeContracts.Static.Analysis.Numerical {
35 class EvaluateExpressionVisitor<TEnv, TVar, TExpr, TInterval, TNumeric> :
36 GenericExpressionVisitor<Counter<TEnv>, TInterval, TVar, TExpr>
37 where TEnv : IntervalEnvironmentBase<TVar, TExpr, TInterval, TNumeric>
38 where TVar : IEquatable<TVar>
39 where TInterval : IntervalBase<TInterval, TNumeric> {
41 ConstToIntervalEvaluator
42 <IntervalContextBase<TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> constToIntv;
44 readonly VariableOccurences occurences;
46 public Sequence<TVar> DuplicatedOccurences { get { return occurences.Duplicated; } }
48 public EvaluateExpressionVisitor (IExpressionDecoder<TVar, TExpr> decoder)
51 occurences = new VariableOccurences (decoder);
53 new ConstToIntervalEvaluator
54 <IntervalContextBase<TInterval, TNumeric>, TVar, TExpr, TInterval, TNumeric> (
58 public override TInterval Visit (TExpr expr, Counter<TEnv> data)
60 if (data.Count >= 10) // to avoid recursion if any
61 return Default (data);
63 var intv = base.Visit (expr, data.Incremented ());
65 return Default (data);
67 intv = RefineWithTypeRanges (intv, expr, data.Env);
69 var var = Decoder.UnderlyingVariable (expr);
72 if (data.Env.TryGetValue (var, out current))
73 intv = intv.Meet (current);
78 public override TInterval VisitConstant (TExpr expr, Counter<TEnv> data)
80 return constToIntv.Visit (expr, data.Env.Context);
83 public override TInterval VisitAddition (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
85 return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Add (l, r));
88 public override TInterval VisitDivision (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
90 return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Div (l, r));
93 public override TInterval VisitMultiply (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
95 return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Mul (l, r));
98 public override TInterval VisitSubtraction (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
100 return DefaultBinary (left, right, data, (d, l, r) => d.Env.Context.Sub (l, r));
103 public override TInterval VisitEqual (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
105 return DefaultComparisons (left, right, data);
108 public override TInterval VisitLessThan (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
110 return DefaultComparisons (left, right, data);
113 public override TInterval VisitGreaterEqualThan (TExpr left, TExpr right, TExpr original,
116 return DefaultComparisons (left, right, data);
119 public override TInterval VisitLessEqualThan (TExpr left, TExpr right, TExpr original,
122 return DefaultComparisons (left, right, data);
125 public override TInterval VisitGreaterThan (TExpr left, TExpr right, TExpr original, Counter<TEnv> data)
127 return DefaultComparisons (left, right, data);
130 public override TInterval VisitUnknown (TExpr expr, Counter<TEnv> data)
132 occurences.Add (expr);
134 return Default (data);
137 protected override TInterval Default (Counter<TEnv> data)
139 return data.Env.Context.TopValue;
142 delegate TInterval BinaryEvaluator (Counter<TEnv> env, TInterval left, TInterval right);
144 TInterval DefaultBinary (TExpr left, TExpr right, Counter<TEnv> data, BinaryEvaluator binop)
146 occurences.Add (left, right);
148 var incremented = data.Incremented ();
149 var leftIntv = Visit (left, incremented);
150 var rightIntv = Visit (right, incremented);
152 return binop (data, leftIntv, rightIntv);
155 TInterval DefaultComparisons (TExpr left, TExpr right, Counter<TEnv> data)
157 occurences.Add (left, right);
159 return Default (data);
162 TInterval RefineWithTypeRanges (TInterval intv, TExpr expr, TEnv env)
164 switch (Decoder.TypeOf (expr)) {
165 case ExpressionType.Int32:
166 return env.Context.ApplyConversion (ExpressionOperator.ConvertToInt32, intv);
167 case ExpressionType.Bool:
168 return env.Context.ApplyConversion (ExpressionOperator.ConvertToInt32, intv);
174 class VariableOccurences {
175 readonly Dictionary<TVar, int> occurences;
177 readonly IExpressionDecoder<TVar, TExpr> decoder;
179 Sequence<TVar> duplicated;
181 public VariableOccurences (IExpressionDecoder<TVar, TExpr> decoder)
183 this.decoder = decoder;
184 occurences = new Dictionary<TVar, int> ();
185 duplicated = Sequence<TVar>.Empty;
188 public Sequence<TVar> Duplicated { get { return duplicated; } }
193 if (!occurences.TryGetValue (var, out cnt))
196 occurences[var] = cnt + 1;
198 if (cnt == 1) // if already was occurence
199 duplicated = duplicated.Cons (var);
202 public void Add (TExpr e)
204 Add (decoder.UnderlyingVariable (e));
207 public void Add (params TExpr[] exprs)
209 foreach (var expr in exprs)
213 public override string ToString ()
215 return occurences.ToString ();