Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// A library to work with graphs. It contains a couple algorithms, including | 5 /// A library to work with graphs. It contains a couple algorithms, including |
| 6 /// Tarjan's algorithm to compute strongest connected components in a graph and | 6 /// Tarjan's algorithm to compute strongly connected components in a graph and |
| 7 /// Cooper et al's dominator algorithm. | 7 /// Cooper et al's dominator algorithm. |
| 8 /// | 8 /// |
| 9 /// Portions of the code in this library was adapted from | 9 /// Portions of the code in this library was adapted from |
| 10 /// `package:analyzer/src/generated/collection_utilities.dart`. | 10 /// `package:analyzer/src/generated/collection_utilities.dart`. |
| 11 // TODO(sigmund): move this into a shared place, like quiver? | 11 // TODO(sigmund): move this into a shared place, like quiver? |
| 12 library dart2js_info.src.graph; | 12 library dart2js_info.src.graph; |
| 13 | 13 |
| 14 import 'dart:math' as math; | 14 import 'dart:math' as math; |
| 15 | 15 |
| 16 abstract class Graph<N> { | 16 abstract class Graph<N> { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 39 } | 39 } |
| 40 return helper(source); | 40 return helper(source); |
| 41 } | 41 } |
| 42 | 42 |
| 43 /// Returns all nodes reachable from [root] in post order. | 43 /// Returns all nodes reachable from [root] in post order. |
| 44 List<N> postOrder(N root) { | 44 List<N> postOrder(N root) { |
| 45 var seen = new Set<N>(); | 45 var seen = new Set<N>(); |
| 46 var result = <N>[]; | 46 var result = <N>[]; |
| 47 helper(n) { | 47 helper(n) { |
| 48 if (!seen.add(n)) return; | 48 if (!seen.add(n)) return; |
| 49 targetsOf(n).forEach(helper); | 49 targetsOf(n).forEach(helper); |
|
Siggi Cherem (dart-lang)
2015/10/16 23:07:41
should we switch this implementation to avoid recu
Harry Terkelsen
2015/10/19 22:11:12
I've refactored it to use yield*, what do you thin
| |
| 50 result.add(n); | 50 result.add(n); |
| 51 } | 51 } |
| 52 helper(root); | 52 helper(root); |
| 53 return result; | 53 return result; |
| 54 } | 54 } |
| 55 | 55 |
| 56 /// Return a list of nodes that form a cycle containing the given node. If the | 56 /// Returns an iterable of all nodes reachable from [root]. |
|
Siggi Cherem (dart-lang)
2015/10/16 23:07:41
maybe indicate that they are in preorder?
Harry Terkelsen
2015/10/19 22:11:12
Done.
| |
| 57 /// node is not part of a cycle in this graph, then a list containing only the | 57 Iterable<N> reachableFrom(N root) sync* { |
|
Siggi Cherem (dart-lang)
2015/10/16 23:07:41
maybe rename this and/or `postOrder` above so we h
Harry Terkelsen
2015/10/19 22:11:12
Done.
| |
| 58 /// node itself will be returned. | 58 var seen = new Set<N>(); |
| 59 var stack = <N>[root]; | |
| 60 while (!stack.isEmpty) { | |
| 61 var next = stack.removeLast(); | |
| 62 seen.add(next); | |
| 63 yield next; | |
|
Siggi Cherem (dart-lang)
2015/10/16 23:07:41
nice use of sync*/yield :)
Harry Terkelsen
2015/10/19 22:11:12
thanks!
| |
| 64 stack.addAll(targetsOf(next).where((x) => !seen.contains(x))); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 /// Returns a list of nodes that form a cycle containing the given node. If | |
| 69 /// the node is not part of a cycle in this graph, then a list containing only | |
| 70 /// the node itself will be returned. | |
| 59 List<N> findCycleContaining(N node) { | 71 List<N> findCycleContaining(N node) { |
| 60 assert(node != null); | 72 assert(node != null); |
| 61 _SccFinder<N> finder = new _SccFinder<N>(this); | 73 _SccFinder<N> finder = new _SccFinder<N>(this); |
| 62 return finder._componentContaining(node); | 74 return finder._componentContaining(node); |
| 63 } | 75 } |
| 64 | 76 |
| 65 /// Returns a dominator tree starting from root. This is a new graph, with the | 77 /// Returns a dominator tree starting from root. This is a new graph, with the |
| 66 /// same nodes as this graph, but where edges exist between a node and the | 78 /// same nodes as this graph, but where edges exist between a node and the |
| 67 /// nodes it immediately dominates. For example, this graph: | 79 /// nodes it immediately dominates. For example, this graph: |
| 68 /// | 80 /// |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 while (postOrderId[finger1] < postOrderId[finger2]) { | 321 while (postOrderId[finger1] < postOrderId[finger2]) { |
| 310 finger1 = immediateDominators[finger1]; | 322 finger1 = immediateDominators[finger1]; |
| 311 } | 323 } |
| 312 while (postOrderId[finger2] < postOrderId[finger1]) { | 324 while (postOrderId[finger2] < postOrderId[finger1]) { |
| 313 finger2 = immediateDominators[finger2]; | 325 finger2 = immediateDominators[finger2]; |
| 314 } | 326 } |
| 315 } | 327 } |
| 316 return finger1; | 328 return finger1; |
| 317 } | 329 } |
| 318 } | 330 } |
| OLD | NEW |