@@ -231,18 +231,30 @@ impl<N: Debug, E: Debug> Graph<N, E> {
231231
232232 // # Iterating over nodes, edges
233233
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+
234246 pub fn each_node < ' a , F > ( & ' a self , mut f : F ) -> bool
235247 where F : FnMut ( NodeIndex , & ' a Node < N > ) -> bool
236248 {
237249 //! 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) )
239251 }
240252
241253 pub fn each_edge < ' a , F > ( & ' a self , mut f : F ) -> bool
242254 where F : FnMut ( EdgeIndex , & ' a Edge < E > ) -> bool
243255 {
244256 //! 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) )
246258 }
247259
248260 pub fn outgoing_edges ( & self , source : NodeIndex ) -> AdjacentEdges < N , E > {
@@ -270,14 +282,11 @@ impl<N: Debug, E: Debug> Graph<N, E> {
270282 self . incoming_edges ( target) . sources ( )
271283 }
272284
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.
281290 pub fn iterate_until_fixed_point < ' a , F > ( & ' a self , mut op : F )
282291 where F : FnMut ( usize , EdgeIndex , & ' a Edge < E > ) -> bool
283292 {
@@ -286,8 +295,8 @@ impl<N: Debug, E: Debug> Graph<N, E> {
286295 while changed {
287296 changed = false ;
288297 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) ;
291300 }
292301 }
293302 }
@@ -298,10 +307,67 @@ impl<N: Debug, E: Debug> Graph<N, E> {
298307 -> DepthFirstTraversal < ' a , N , E > {
299308 DepthFirstTraversal :: with_start_node ( self , start, direction)
300309 }
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+ }
301339}
302340
303341// # Iterators
304342
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+
305371pub struct AdjacentEdges < ' g , N , E >
306372 where N : ' g ,
307373 E : ' g
@@ -336,7 +402,7 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
336402 }
337403}
338404
339- pub struct AdjacentTargets < ' g , N : ' g , E : ' g >
405+ pub struct AdjacentTargets < ' g , N , E >
340406 where N : ' g ,
341407 E : ' g
342408{
@@ -351,7 +417,7 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
351417 }
352418}
353419
354- pub struct AdjacentSources < ' g , N : ' g , E : ' g >
420+ pub struct AdjacentSources < ' g , N , E >
355421 where N : ' g ,
356422 E : ' g
357423{
@@ -366,7 +432,10 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
366432 }
367433}
368434
369- pub struct DepthFirstTraversal < ' g , N : ' g , E : ' g > {
435+ pub struct DepthFirstTraversal < ' g , N , E >
436+ where N : ' g ,
437+ E : ' g
438+ {
370439 graph : & ' g Graph < N , E > ,
371440 stack : Vec < NodeIndex > ,
372441 visited : BitVector ,
0 commit comments