Only in .: blib
Only in .: dc-coderef.patch
diff -ru ../Devel-Cycle-1.07/lib/Devel/Cycle.pm ./lib/Devel/Cycle.pm
--- ../Devel-Cycle-1.07/lib/Devel/Cycle.pm	2006-05-23 21:29:32.000000000 -0500
+++ ./lib/Devel/Cycle.pm	2007-08-30 14:14:59.000000000 -0500
@@ -55,7 +55,7 @@
       _do_report(++$counter,shift)
     }
   }
-  _find_cycle($ref,{},$callback,1,());
+  _find_cycle($ref,{},$callback,1,{},());
 }
 
 sub find_cycle {
@@ -67,7 +67,7 @@
       _do_report(++$counter,shift)
     }
   }
-  _find_cycle($ref,{},$callback,0,());
+  _find_cycle($ref,{},$callback,0,{},());
 }
 
 sub _find_cycle {
@@ -75,59 +75,93 @@
   my $seenit    = shift;
   my $callback  = shift;
   my $inc_weak_refs = shift;
-  my %complain;
+  my $complain  = shift;
   my @report  = @_;
 
   return unless ref $current;
 
-  # note: it seems like you could just do:
-  #
-  #    return if isweak($current);
-  #
-  # but strangely the weak flag doesn't seem to survive the copying,
-  # so the test has to happen directly on the reference in the data
-  # structure being scanned.
-
   if ($seenit->{$current}) {
     $callback->(\@report);
     return;
   }
   $seenit->{$current}++;
 
-  my $type = _get_type($current);
+  _find_cycle_dispatch($current,{%$seenit},$callback,$inc_weak_refs,$complain,@report);
+}
 
-  if ($type eq 'SCALAR') {
-     return if !$inc_weak_refs && isweak($current);
-    _find_cycle($$current,{%$seenit},$callback,$inc_weak_refs,
-		(@report,['SCALAR',undef,$current => $$current,$inc_weak_refs?isweak($current):()]));
-  }
+sub _find_cycle_dispatch {
+  my $type = _get_type($_[0]);
 
-  elsif ($type eq 'ARRAY') {
-    for (my $i=0; $i<@$current; $i++) {
-      next if !$inc_weak_refs && isweak($current->[$i]);
-      _find_cycle($current->[$i],{%$seenit},$callback,$inc_weak_refs,
-		  (@report,['ARRAY',$i,$current => $current->[$i],$inc_weak_refs?isweak($current->[$i]):()]));
-    }
+  my $sub = do { no strict 'refs'; \&{"_find_cycle_$type"} };
+  die "Invalid type: $type" unless $sub;
+
+  $sub->(@_);
+}
+
+sub _find_cycle_SCALAR {
+  my $current   = shift;
+  my $seenit    = shift;
+  my $callback  = shift;
+  my $inc_weak_refs = shift;
+  my $complain  = shift;
+  my @report  = @_;
+
+  return if !$inc_weak_refs && isweak($current);
+  _find_cycle($$current,{%$seenit},$callback,$inc_weak_refs,$complain,
+              (@report,['SCALAR',undef,$current => $$current,$inc_weak_refs?isweak($current):()]));
+}
+
+sub _find_cycle_ARRAY {
+  my $current   = shift;
+  my $seenit    = shift;
+  my $callback  = shift;
+  my $inc_weak_refs = shift;
+  my $complain  = shift;
+  my @report  = @_;
+
+  for (my $i=0; $i<@$current; $i++) {
+    next if !$inc_weak_refs && isweak($current->[$i]);
+    _find_cycle($current->[$i],{%$seenit},$callback,$inc_weak_refs,$complain,
+                (@report,['ARRAY',$i,$current => $current->[$i],$inc_weak_refs?isweak($current->[$i]):()]));
   }
-  elsif ($type eq 'HASH') {
-    for my $key (sort keys %$current) {
-       next if !$inc_weak_refs && isweak($current->{$key});
-      _find_cycle($current->{$key},{%$seenit},$callback,$inc_weak_refs,
-		  (@report,['HASH',$key,$current => $current->{$key},$inc_weak_refs?isweak($current->{$key}):()]));
-    }
+}
+
+sub _find_cycle_HASH {
+  my $current   = shift;
+  my $seenit    = shift;
+  my $callback  = shift;
+  my $inc_weak_refs = shift;
+  my $complain  = shift;
+  my @report  = @_;
+
+  for my $key (sort keys %$current) {
+    next if !$inc_weak_refs && isweak($current->{$key});
+    _find_cycle($current->{$key},{%$seenit},$callback,$inc_weak_refs,$complain,
+                (@report,['HASH',$key,$current => $current->{$key},$inc_weak_refs?isweak($current->{$key}):()]));
   }
-  elsif ($type eq 'CODE') {
-    if (HAVE_PADWALKER) {
-      my $closed_vars = PadWalker::closed_over( $current );
-      foreach my $varname ( sort keys %$closed_vars ) {
-        my $value = $closed_vars->{$varname};
-        next if !$inc_weak_refs && isweak($$value);
-        _find_cycle( $$value,{%$seenit},$callback,$inc_weak_refs,
-		     (@report,['CODE',$varname,$current => $$value,$inc_weak_refs?isweak($$value):()]));
-      }
-    } elsif (!$complain{$current}++ && !$QUIET) {
+}
+
+sub _find_cycle_CODE {
+  my $current   = shift;
+  my $seenit    = shift;
+  my $callback  = shift;
+  my $inc_weak_refs = shift;
+  my $complain  = shift;
+  my @report  = @_;
+
+  unless (HAVE_PADWALKER) {
+    if (!$complain->{$current}++ && !$QUIET) {
       carp "A code closure was detected in but we cannot check it unless the PadWalker module is installed";
     }
+
+    return;
+  }
+
+  my $closed_vars = PadWalker::closed_over( $current );
+  foreach my $varname ( sort keys %$closed_vars ) {
+    my $value = $closed_vars->{$varname};
+    _find_cycle_dispatch($value,{%$seenit},$callback,$inc_weak_refs,$complain,
+                         (@report,['CODE',$varname,$current => $value]));
   }
 }
 
Only in .: Makefile
Only in .: pm_to_blib
diff -ru ../Devel-Cycle-1.07/t/Devel-Cycle.t ./t/Devel-Cycle.t
--- ../Devel-Cycle-1.07/t/Devel-Cycle.t	2005-01-21 16:58:57.000000000 -0600
+++ ./t/Devel-Cycle.t	2007-08-30 14:12:16.000000000 -0500
@@ -5,9 +5,11 @@
 
 # change 'tests => 1' to 'tests => last_test_to_print';
 
-use Test::More tests => 7;
+use strict;
+
+use Test::More tests => 8;
 use Scalar::Util qw(weaken isweak);
-BEGIN { use_ok('Devel::Cycle') };
+BEGIN{use_ok('Devel::Cycle')}
 
 #########################
 
@@ -57,3 +59,24 @@
 find_weakened_cycle($test,sub {$counter++});
 is($counter,4,'found four cycles (including weakened ones) in $test after second weaken()');
 
+SKIP:
+{
+    skip 'These tests require PadWalker 1.0+', 1
+        unless Devel::Cycle::HAVE_PADWALKER;
+
+    $counter = 0;
+
+    my %cyclical = ( a => [],
+                     b => {},
+                   );
+    $cyclical{a}[0]   = $cyclical{a};
+    $cyclical{b}{key} = $cyclical{a};
+
+    my @cyclical = [];
+    $cyclical[0] = \@cyclical;
+
+    my $sub = sub { return \@cyclical, \%cyclical; };
+
+    find_cycle($sub,sub {$counter++});
+    is($counter,3,'found three cycles in $cyclical closure');
+}