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';
$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;
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 ];
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);
}
}