Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / Mono.CodeContracts / Mono.CodeContracts.Static.Analysis.ExpressionAnalysis / ValueAnalysis.cs
1 // 
2 // ValueAnalysis.cs
3 // 
4 // Authors:
5 //      Alexander Chebaturkin (chebaturkin@gmail.com)
6 // 
7 // Copyright (C) 2012 Alexander Chebaturkin
8 // 
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:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //  
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.
27 //
28
29 using System;
30 using System.IO;
31 using Mono.CodeContracts.Static.AST.Visitors;
32 using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
33 using Mono.CodeContracts.Static.ControlFlow;
34 using Mono.CodeContracts.Static.DataFlowAnalysis;
35 using Mono.CodeContracts.Static.DataStructures;
36 using Mono.CodeContracts.Static.Lattices;
37
38 namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
39         class ValueAnalysis<SymbolicValue, Context, EdgeData> : IAnalysis<APC, ExprDomain<SymbolicValue>,
40                                                                          IILVisitor<APC, SymbolicValue, SymbolicValue, ExprDomain<SymbolicValue>, ExprDomain<SymbolicValue>>, EdgeData>
41                         where SymbolicValue : IEquatable<SymbolicValue> 
42                         where Context : IValueContextProvider<SymbolicValue> 
43                         where EdgeData : IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> {
44                 private readonly ExpressionAnalysisFacade<SymbolicValue, Context, EdgeData> parent;
45
46                 public ValueAnalysis (ExpressionAnalysisFacade<SymbolicValue, Context, EdgeData> parent)
47                 {
48                         this.parent = parent;
49                 }
50
51                 #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>
52                 public ExprDomain<SymbolicValue> EdgeConversion (APC @from, APC to, bool isJoinPoint, EdgeData sourceTargetMap, ExprDomain<SymbolicValue> originalState)
53                 {
54                         if (sourceTargetMap == null)
55                                 return originalState;
56
57                         if (DebugOptions.Debug)
58                         {
59                                 Console.WriteLine ("====Expression analysis Parallel assign====");
60                                 DumpMap (sourceTargetMap);
61                                 DumpExpressions ("original expressions", originalState);
62                         }
63
64                         ExprDomain<SymbolicValue> result = originalState.Empty ();
65                         ExprDomain<SymbolicValue> domain = originalState.Empty ();
66
67                         foreach (SymbolicValue sv in originalState.Keys) {
68                                 Expr<SymbolicValue> expression = originalState [sv].Value.Substitute (sourceTargetMap);
69                                 if (expression != null)
70                                         domain = domain.Add (sv, expression);
71                         }
72
73                         foreach (SymbolicValue sv in sourceTargetMap.Keys) {
74                                 FlatDomain<Expr<SymbolicValue>> expressionDomain = domain [sv];
75                                 if (expressionDomain.IsNormal()) {
76                                         Expr<SymbolicValue> expression = expressionDomain.Value;
77                                         foreach (SymbolicValue sub in sourceTargetMap [sv].AsEnumerable ())
78                                                 result = result.Add (sub, expression);
79                                 }
80                         }
81
82                         if (DebugOptions.Debug)
83                         {
84                                 DumpExpressions ("new expressions", result);
85                         }
86                         return result;
87                 }
88
89                 public IILVisitor<APC, SymbolicValue, SymbolicValue, ExprDomain<SymbolicValue>, ExprDomain<SymbolicValue>> GetVisitor ()
90                 {
91                         return new AnalysisDecoder<SymbolicValue> ();
92                 }
93
94                 public ExprDomain<SymbolicValue> Join (Pair<APC, APC> edge, ExprDomain<SymbolicValue> newstate, ExprDomain<SymbolicValue> prevstate, out bool weaker, bool widen)
95                 {
96                         return prevstate.Join (newstate, widen, out weaker);
97                 }
98
99                 public ExprDomain<SymbolicValue> ImmutableVersion (ExprDomain<SymbolicValue> arg)
100                 {
101                         return arg;
102                 }
103
104                 public ExprDomain<SymbolicValue> MutableVersion (ExprDomain<SymbolicValue> arg)
105                 {
106                         return arg;
107                 }
108
109                 public bool IsBottom (APC pc, ExprDomain<SymbolicValue> state)
110                 {
111                         return state.IsBottom;
112                 }
113
114                 public Predicate<APC> SaveFixPointInfo (IFixPointInfo<APC, ExprDomain<SymbolicValue>> fixPointInfo)
115                 {
116                         this.parent.SaveFixPointInfo (fixPointInfo);
117                         return pc => true;
118                 }
119
120                 public void Dump (Pair<ExprDomain<SymbolicValue>, TextWriter> pair)
121                 {
122                         pair.Key.Dump (pair.Value);
123                 }
124
125                 private void DumpMap (IImmutableMap<SymbolicValue, Sequence<SymbolicValue>> sourceTargetMap)
126                 {
127                         Console.WriteLine ("Source-Target assignment");
128                         foreach (SymbolicValue key in sourceTargetMap.Keys) {
129                                 foreach (SymbolicValue value in sourceTargetMap [key].AsEnumerable ())
130                                         Console.Write ("{0} ", value);
131                                 Console.WriteLine (" := {0}", key);
132                         }
133                 }
134
135                 private void DumpExpressions (string header, ExprDomain<SymbolicValue> state)
136                 {
137                         Console.WriteLine ("--- {0} ---", header);
138                         foreach (SymbolicValue index in state.Keys) {
139                                 FlatDomain<Expr<SymbolicValue>> domain = state [index];
140                                 if (domain.IsNormal())
141                                         Console.WriteLine ("{0} -> {1}", index, domain.Value);
142                                 else if (domain.IsTop)
143                                         Console.WriteLine ("{0} -> (Top)", index);
144                                 else if (domain.IsBottom)
145                                         Console.WriteLine ("{0} -> (Bot)", index);
146                         }
147                 }
148                 #endregion
149         }
150 }