1 // 2 // EdgeMap.cs 3 // 4 // Authors: 5 // Alexander Chebaturkin (chebaturkin@gmail.com) 6 // 7 // Copyright (C) 2011 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.Collections; 31 using System.Collections.Generic; 32 using System.Linq; 33 using Mono.CodeContracts.Static.DataStructures; 34 35 namespace Mono.CodeContracts.Static.ControlFlow { 36 class EdgeMap<Tag> : IEnumerable<Edge<CFGBlock, Tag>>, IGraph<CFGBlock, Tag> { 37 private readonly List<Edge<CFGBlock, Tag>> edges; 38 EdgeMap(List<Edge<CFGBlock, Tag>> edges)39 public EdgeMap (List<Edge<CFGBlock, Tag>> edges) 40 { 41 this.edges = edges; 42 Resort (); 43 } 44 45 public ICollection<Pair<Tag, CFGBlock>> this [CFGBlock node] 46 { 47 get { return new Successors (this, FindStartIndex (node)); } 48 } 49 50 #region IEnumerable<Edge<CFGBlock,Tag>> Members GetEnumerator()51 public IEnumerator<Edge<CFGBlock, Tag>> GetEnumerator () 52 { 53 return this.edges.GetEnumerator (); 54 } 55 IEnumerable.GetEnumerator()56 IEnumerator IEnumerable.GetEnumerator () 57 { 58 return GetEnumerator (); 59 } 60 #endregion 61 62 #region IGraph<CFGBlock,Tag> Members 63 IEnumerable<CFGBlock> IGraph<CFGBlock, Tag>.Nodes 64 { 65 get { throw new InvalidOperationException(); } 66 } 67 Successors(CFGBlock node)68 IEnumerable<Pair<Tag, CFGBlock>> IGraph<CFGBlock, Tag>.Successors (CFGBlock node) 69 { 70 return this [node]; 71 } 72 #endregion 73 Reverse()74 public EdgeMap<Tag> Reverse () 75 { 76 var newEdges = new List<Edge<CFGBlock, Tag>> (this.edges.Count); 77 78 newEdges.AddRange (this.edges.Select (edge => edge.Reversed ())); 79 80 return new EdgeMap<Tag> (newEdges); 81 } 82 CompareFirstBlockIndex(Edge<CFGBlock, Tag> edge1, Edge<CFGBlock, Tag> edge2)83 private static int CompareFirstBlockIndex (Edge<CFGBlock, Tag> edge1, Edge<CFGBlock, Tag> edge2) 84 { 85 int cmp = edge1.From.Index - edge2.From.Index; 86 if (cmp == 0) 87 cmp = edge1.To.Index - edge2.To.Index; 88 89 return cmp; 90 } 91 FindStartIndex(CFGBlock from)92 private int FindStartIndex (CFGBlock from) 93 { 94 //binary search 95 int l = 0; 96 int r = this.edges.Count; 97 while (l < r) { 98 int median = (l + r)/2; 99 int medianBlockIndex = this.edges [median].From.Index; 100 101 if (medianBlockIndex == from.Index) { 102 while (median > 0 && this.edges [median - 1].From.Index == medianBlockIndex) 103 --median; 104 return median; 105 } 106 107 if (medianBlockIndex < from.Index) 108 l = median + 1; 109 else 110 r = median; 111 } 112 113 return this.edges.Count; 114 } 115 Filter(Predicate<Edge<CFGBlock, Tag>> keep)116 public void Filter (Predicate<Edge<CFGBlock, Tag>> keep) 117 { 118 var notKeepEdges = new List<int> (); 119 for (int i = 0; i < this.edges.Count; i++) { 120 if (!keep (this.edges [i])) 121 notKeepEdges.Add (i); 122 } 123 124 if (notKeepEdges.Count == 0) 125 return; 126 127 int ix = 0; 128 foreach (int i in notKeepEdges) { 129 this.edges.RemoveAt (i - ix); 130 ix++; 131 } 132 } 133 Resort()134 public void Resort () 135 { 136 this.edges.Sort (CompareFirstBlockIndex); 137 } 138 139 #region Nested type: Successors 140 private struct Successors : ICollection<Pair<Tag, CFGBlock>> { 141 private readonly int start_index; 142 private readonly EdgeMap<Tag> underlying; 143 SuccessorsMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors144 public Successors (EdgeMap<Tag> underlying, int startIndex) 145 { 146 this.underlying = underlying; 147 this.start_index = startIndex; 148 } 149 150 #region ICollection<Pair<Tag,CFGBlock>> Members GetEnumeratorMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors151 public IEnumerator<Pair<Tag, CFGBlock>> GetEnumerator () 152 { 153 List<Edge<CFGBlock, Tag>> edges = this.underlying.edges; 154 if (this.start_index < edges.Count) { 155 int index = this.start_index; 156 int blockIndex = edges [index].From.Index; 157 do { 158 yield return new Pair<Tag, CFGBlock> (edges [index].Tag, edges [index].To); 159 ++index; 160 } while (index < edges.Count && edges [index].From.Index == blockIndex); 161 } 162 } 163 IEnumerable.GetEnumeratorMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors164 IEnumerator IEnumerable.GetEnumerator () 165 { 166 return GetEnumerator (); 167 } 168 AddMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors169 public void Add (Pair<Tag, CFGBlock> item) 170 { 171 throw new InvalidOperationException (); 172 } 173 ClearMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors174 public void Clear () 175 { 176 throw new InvalidOperationException (); 177 } 178 ContainsMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors179 public bool Contains (Pair<Tag, CFGBlock> item) 180 { 181 throw new NotImplementedException (); 182 } 183 CopyToMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors184 public void CopyTo (Pair<Tag, CFGBlock>[] array, int arrayIndex) 185 { 186 throw new NotImplementedException (); 187 } 188 RemoveMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors189 public bool Remove (Pair<Tag, CFGBlock> item) 190 { 191 throw new InvalidOperationException (); 192 } 193 194 public int Count 195 { 196 get 197 { 198 int index = this.start_index; 199 List<Edge<CFGBlock, Tag>> edges = this.underlying.edges; 200 if (index >= edges.Count) 201 return 0; 202 int blockIndex = edges [index].From.Index; 203 204 int count = 0; 205 do { 206 ++count; 207 ++index; 208 } while (index < edges.Count && edges [index].From.Index == blockIndex); 209 210 return count; 211 } 212 } 213 214 public bool IsReadOnly 215 { 216 get { return true; } 217 } 218 #endregion 219 } 220 #endregion 221 } 222 } 223