@@ -231,18 +231,30 @@ impl<N: Debug, E: Debug> Graph<N, E> {
231
231
232
232
// # Iterating over nodes, edges
233
233
234
+ pub fn enumerated_nodes ( & self ) -> EnumeratedNodes < N > {
235
+ EnumeratedNodes {
236
+ iter : self . nodes . iter ( ) . enumerate ( )
237
+ }
238
+ }
239
+
240
+ pub fn enumerated_edges ( & self ) -> EnumeratedEdges < E > {
241
+ EnumeratedEdges {
242
+ iter : self . edges . iter ( ) . enumerate ( )
243
+ }
244
+ }
245
+
234
246
pub fn each_node < ' a , F > ( & ' a self , mut f : F ) -> bool
235
247
where F : FnMut ( NodeIndex , & ' a Node < N > ) -> bool
236
248
{
237
249
//! Iterates over all edges defined in the graph.
238
- self . nodes . iter ( ) . enumerate ( ) . all ( |( i , node) | f ( NodeIndex ( i ) , node) )
250
+ self . enumerated_nodes ( ) . all ( |( node_idx , node) | f ( node_idx , node) )
239
251
}
240
252
241
253
pub fn each_edge < ' a , F > ( & ' a self , mut f : F ) -> bool
242
254
where F : FnMut ( EdgeIndex , & ' a Edge < E > ) -> bool
243
255
{
244
256
//! Iterates over all edges defined in the graph
245
- self . edges . iter ( ) . enumerate ( ) . all ( |( i , edge) | f ( EdgeIndex ( i ) , edge) )
257
+ self . enumerated_edges ( ) . all ( |( edge_idx , edge) | f ( edge_idx , edge) )
246
258
}
247
259
248
260
pub fn outgoing_edges ( & self , source : NodeIndex ) -> AdjacentEdges < N , E > {
@@ -270,14 +282,11 @@ impl<N: Debug, E: Debug> Graph<N, E> {
270
282
self . incoming_edges ( target) . sources ( )
271
283
}
272
284
273
- // # Fixed-point iteration
274
- //
275
- // A common use for graphs in our compiler is to perform
276
- // fixed-point iteration. In this case, each edge represents a
277
- // constraint, and the nodes themselves are associated with
278
- // variables or other bitsets. This method facilitates such a
279
- // computation.
280
-
285
+ /// A common use for graphs in our compiler is to perform
286
+ /// fixed-point iteration. In this case, each edge represents a
287
+ /// constraint, and the nodes themselves are associated with
288
+ /// variables or other bitsets. This method facilitates such a
289
+ /// computation.
281
290
pub fn iterate_until_fixed_point < ' a , F > ( & ' a self , mut op : F )
282
291
where F : FnMut ( usize , EdgeIndex , & ' a Edge < E > ) -> bool
283
292
{
@@ -286,8 +295,8 @@ impl<N: Debug, E: Debug> Graph<N, E> {
286
295
while changed {
287
296
changed = false ;
288
297
iteration += 1 ;
289
- for ( i , edge) in self . edges . iter ( ) . enumerate ( ) {
290
- changed |= op ( iteration, EdgeIndex ( i ) , edge) ;
298
+ for ( edge_index , edge) in self . enumerated_edges ( ) {
299
+ changed |= op ( iteration, edge_index , edge) ;
291
300
}
292
301
}
293
302
}
@@ -298,10 +307,67 @@ impl<N: Debug, E: Debug> Graph<N, E> {
298
307
-> DepthFirstTraversal < ' a , N , E > {
299
308
DepthFirstTraversal :: with_start_node ( self , start, direction)
300
309
}
310
+
311
+ /// Whether or not a node can be reached from itself.
312
+ pub fn is_node_cyclic ( & self , starting_node_index : NodeIndex ) -> bool {
313
+ // This is similar to depth traversal below, but we
314
+ // can't use that, because depth traversal doesn't show
315
+ // the starting node a second time.
316
+ let mut visited = BitVector :: new ( self . len_nodes ( ) ) ;
317
+ let mut stack = vec ! [ starting_node_index] ;
318
+
319
+ while let Some ( current_node_index) = stack. pop ( ) {
320
+ visited. insert ( current_node_index. 0 ) ;
321
+
322
+ // Directionality doesn't change the answer,
323
+ // so just use outgoing edges.
324
+ for ( _, edge) in self . outgoing_edges ( current_node_index) {
325
+ let target_node_index = edge. target ( ) ;
326
+
327
+ if target_node_index == starting_node_index {
328
+ return true ;
329
+ }
330
+
331
+ if !visited. contains ( target_node_index. 0 ) {
332
+ stack. push ( target_node_index) ;
333
+ }
334
+ }
335
+ }
336
+
337
+ false
338
+ }
301
339
}
302
340
303
341
// # Iterators
304
342
343
+ pub struct EnumeratedNodes < ' g , N >
344
+ where N : ' g ,
345
+ {
346
+ iter : :: std:: iter:: Enumerate < :: std:: slice:: Iter < ' g , Node < N > > >
347
+ }
348
+
349
+ impl < ' g , N : Debug > Iterator for EnumeratedNodes < ' g , N > {
350
+ type Item = ( NodeIndex , & ' g Node < N > ) ;
351
+
352
+ fn next ( & mut self ) -> Option < ( NodeIndex , & ' g Node < N > ) > {
353
+ self . iter . next ( ) . map ( |( idx, n) | ( NodeIndex ( idx) , n) )
354
+ }
355
+ }
356
+
357
+ pub struct EnumeratedEdges < ' g , E >
358
+ where E : ' g ,
359
+ {
360
+ iter : :: std:: iter:: Enumerate < :: std:: slice:: Iter < ' g , Edge < E > > >
361
+ }
362
+
363
+ impl < ' g , E : Debug > Iterator for EnumeratedEdges < ' g , E > {
364
+ type Item = ( EdgeIndex , & ' g Edge < E > ) ;
365
+
366
+ fn next ( & mut self ) -> Option < ( EdgeIndex , & ' g Edge < E > ) > {
367
+ self . iter . next ( ) . map ( |( idx, e) | ( EdgeIndex ( idx) , e) )
368
+ }
369
+ }
370
+
305
371
pub struct AdjacentEdges < ' g , N , E >
306
372
where N : ' g ,
307
373
E : ' g
@@ -336,7 +402,7 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
336
402
}
337
403
}
338
404
339
- pub struct AdjacentTargets < ' g , N : ' g , E : ' g >
405
+ pub struct AdjacentTargets < ' g , N , E >
340
406
where N : ' g ,
341
407
E : ' g
342
408
{
@@ -351,7 +417,7 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
351
417
}
352
418
}
353
419
354
- pub struct AdjacentSources < ' g , N : ' g , E : ' g >
420
+ pub struct AdjacentSources < ' g , N , E >
355
421
where N : ' g ,
356
422
E : ' g
357
423
{
@@ -366,7 +432,10 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
366
432
}
367
433
}
368
434
369
- pub struct DepthFirstTraversal < ' g , N : ' g , E : ' g > {
435
+ pub struct DepthFirstTraversal < ' g , N , E >
436
+ where N : ' g ,
437
+ E : ' g
438
+ {
370
439
graph : & ' g Graph < N , E > ,
371
440
stack : Vec < NodeIndex > ,
372
441
visited : BitVector ,
0 commit comments