X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FAlgorithm%2FC3.pm;h=cc3b85626e07f1ec150fee8450cac8a1460917f3;hb=2aecbee93d47c5db507b896a87ac53954a6730b5;hp=66c32ffe9cfb16adaace938a221a3b3b203216e4;hpb=f4b986039f6a4af27b3bb385b9b524ba79374b9f;p=gitmo%2FAlgorithm-C3.git diff --git a/lib/Algorithm/C3.pm b/lib/Algorithm/C3.pm index 66c32ff..cc3b856 100644 --- a/lib/Algorithm/C3.pm +++ b/lib/Algorithm/C3.pm @@ -6,13 +6,14 @@ use warnings; use Carp 'confess'; -our $VERSION = '0.06'; +our $VERSION = '0.07'; sub merge { my ($root, $parent_fetcher, $cache) = @_; $cache ||= {}; - my @STACK; # stack for simulating recursion + + my @STACK; # stack for simulating recursion my $pfetcher_is_coderef = ref($parent_fetcher) eq 'CODE'; @@ -32,13 +33,14 @@ sub merge { $new_root = $current_parents->[$i++]; if($seen{$new_root}) { - my @isastack = ( - (map { $_->[0] } @STACK), - $current_root, - $new_root - ); - shift @isastack while $isastack[0] ne $new_root; - my $isastack = join(q{ -> }, @isastack); + my @isastack; + my $reached; + for(my $i = 0; $i < $#STACK; $i += 4) { + if($reached || ($reached = ($STACK[$i] eq $new_root))) { + push(@isastack, $STACK[$i]); + } + } + my $isastack = join(q{ -> }, @isastack, $current_root, $new_root); die "Infinite loop detected in parents of '$root': $isastack"; } $seen{$new_root} = 1; @@ -47,12 +49,7 @@ sub merge { confess "Could not find method $parent_fetcher in $new_root"; } - push(@STACK, [ - $current_root, - $current_parents, - $recurse_mergeout, - $i, - ]); + push(@STACK, $current_root, $current_parents, $recurse_mergeout, $i); $current_root = $new_root; $current_parents = $cache->{pfetch}->{$current_root} ||= [ $current_root->$parent_fetcher ]; @@ -119,10 +116,12 @@ sub merge { return @$mergeout if !@STACK; - ($current_root, $current_parents, $recurse_mergeout, $i) - = @{pop @STACK}; + $i = pop(@STACK); + $recurse_mergeout = pop(@STACK); + $current_parents = pop(@STACK); + $current_root = pop(@STACK); - push(@$recurse_mergeout, $mergeout) if @$mergeout; + push(@$recurse_mergeout, $mergeout); } }