line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Algorithm::C3; |
2
|
|
|
|
|
|
|
|
3
|
11
|
|
|
11
|
|
778597
|
use strict; |
|
11
|
|
|
|
|
115
|
|
|
11
|
|
|
|
|
336
|
|
4
|
11
|
|
|
11
|
|
57
|
use warnings; |
|
11
|
|
|
|
|
20
|
|
|
11
|
|
|
|
|
336
|
|
5
|
|
|
|
|
|
|
|
6
|
11
|
|
|
11
|
|
57
|
use Carp 'confess'; |
|
11
|
|
|
|
|
28
|
|
|
11
|
|
|
|
|
7706
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.11'; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
sub merge { |
11
|
66
|
|
|
66
|
1
|
8178
|
my ($root, $parent_fetcher, $cache) = @_; |
12
|
|
|
|
|
|
|
|
13
|
66
|
|
100
|
|
|
315
|
$cache ||= {}; |
14
|
|
|
|
|
|
|
|
15
|
66
|
|
|
|
|
104
|
my @STACK; # stack for simulating recursion |
16
|
|
|
|
|
|
|
|
17
|
66
|
|
|
|
|
152
|
my $pfetcher_is_coderef = ref($parent_fetcher) eq 'CODE'; |
18
|
|
|
|
|
|
|
|
19
|
66
|
100
|
100
|
|
|
258
|
unless ($pfetcher_is_coderef or $root->can($parent_fetcher)) { |
20
|
1
|
|
|
|
|
245
|
confess "Could not find method $parent_fetcher in $root"; |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
65
|
|
|
|
|
99
|
my $current_root = $root; |
24
|
65
|
|
|
|
|
164
|
my $current_parents = [ $root->$parent_fetcher ]; |
25
|
65
|
|
|
|
|
458
|
my $recurse_mergeout = []; |
26
|
65
|
|
|
|
|
103
|
my $i = 0; |
27
|
65
|
|
|
|
|
147
|
my %seen = ( $root => 1 ); |
28
|
|
|
|
|
|
|
|
29
|
65
|
|
|
|
|
107
|
my ($new_root, $mergeout, %tails); |
30
|
65
|
|
|
|
|
96
|
while(1) { |
31
|
794
|
100
|
|
|
|
1406
|
if($i < @$current_parents) { |
32
|
387
|
|
|
|
|
554
|
$new_root = $current_parents->[$i++]; |
33
|
|
|
|
|
|
|
|
34
|
387
|
100
|
|
|
|
769
|
if($seen{$new_root}) { |
35
|
8
|
|
|
|
|
13
|
my @isastack; |
36
|
|
|
|
|
|
|
my $reached; |
37
|
8
|
|
|
|
|
18
|
for(my $i = 0; $i < $#STACK; $i += 4) { |
38
|
27
|
100
|
100
|
|
|
87
|
if($reached || ($reached = ($STACK[$i] eq $new_root))) { |
39
|
14
|
|
|
|
|
49
|
push(@isastack, $STACK[$i]); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
} |
42
|
8
|
|
|
|
|
24
|
my $isastack = join(q{ -> }, @isastack, $current_root, $new_root); |
43
|
8
|
|
|
|
|
205
|
die "Infinite loop detected in parents of '$root': $isastack"; |
44
|
|
|
|
|
|
|
} |
45
|
379
|
|
|
|
|
573
|
$seen{$new_root} = 1; |
46
|
|
|
|
|
|
|
|
47
|
379
|
100
|
100
|
|
|
880
|
unless ($pfetcher_is_coderef or $new_root->can($parent_fetcher)) { |
48
|
1
|
|
|
|
|
139
|
confess "Could not find method $parent_fetcher in $new_root"; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
378
|
|
|
|
|
644
|
push(@STACK, $current_root, $current_parents, $recurse_mergeout, $i); |
52
|
|
|
|
|
|
|
|
53
|
378
|
|
|
|
|
517
|
$current_root = $new_root; |
54
|
378
|
|
100
|
|
|
981
|
$current_parents = $cache->{pfetch}->{$current_root} ||= [ $current_root->$parent_fetcher ]; |
55
|
378
|
|
|
|
|
1502
|
$recurse_mergeout = []; |
56
|
378
|
|
|
|
|
496
|
$i = 0; |
57
|
378
|
|
|
|
|
506
|
next; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
407
|
|
|
|
|
568
|
$seen{$current_root} = 0; |
61
|
|
|
|
|
|
|
|
62
|
407
|
|
100
|
|
|
851
|
$mergeout = $cache->{merge}->{$current_root} ||= do { |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# This do-block is the code formerly known as the function |
65
|
|
|
|
|
|
|
# that was a perl-port of the python code at |
66
|
|
|
|
|
|
|
# http://www.python.org/2.3/mro.html :) |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Initial set (make sure everything is copied - it will be modded) |
69
|
221
|
|
|
|
|
367
|
my @seqs = map { [@$_] } @$recurse_mergeout; |
|
210
|
|
|
|
|
531
|
|
70
|
221
|
100
|
|
|
|
666
|
push(@seqs, [@$current_parents]) if @$current_parents; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Construct the tail-checking hash (actually, it's cheaper and still |
73
|
|
|
|
|
|
|
# correct to re-use it throughout this function) |
74
|
221
|
|
|
|
|
379
|
foreach my $seq (@seqs) { |
75
|
339
|
|
|
|
|
910
|
$tails{$seq->[$_]}++ for (1..$#$seq); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
221
|
|
|
|
|
424
|
my @res = ( $current_root ); |
79
|
221
|
|
|
|
|
290
|
while (1) { |
80
|
750
|
|
|
|
|
939
|
my $cand; |
81
|
|
|
|
|
|
|
my $winner; |
82
|
750
|
|
|
|
|
1116
|
foreach (@seqs) { |
83
|
1879
|
100
|
|
|
|
2935
|
next if !@$_; |
84
|
1129
|
100
|
|
|
|
1927
|
if(!$winner) { # looking for a winner |
|
|
100
|
|
|
|
|
|
85
|
601
|
|
|
|
|
838
|
$cand = $_->[0]; # seq head is candidate |
86
|
601
|
100
|
|
|
|
1040
|
next if $tails{$cand}; # he loses if in %tails |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# Handy warn to give a output like the ones on |
89
|
|
|
|
|
|
|
# http://www.python.org/download/releases/2.3/mro/ |
90
|
|
|
|
|
|
|
#warn " = " . join(' + ', @res) . " + merge([" . join('] [', map { join(', ', @$_) } grep { @$_ } @seqs) . "])\n"; |
91
|
529
|
|
|
|
|
802
|
push @res => $winner = $cand; |
92
|
529
|
|
|
|
|
669
|
shift @$_; # strip off our winner |
93
|
529
|
100
|
|
|
|
1061
|
$tails{$_->[0]}-- if @$_; # keep %tails sane |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
elsif($_->[0] eq $winner) { |
96
|
296
|
|
|
|
|
381
|
shift @$_; # strip off our winner |
97
|
296
|
100
|
|
|
|
561
|
$tails{$_->[0]}-- if @$_; # keep %tails sane |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Handy warn to give a output like the ones on |
102
|
|
|
|
|
|
|
# http://www.python.org/download/releases/2.3/mro/ |
103
|
|
|
|
|
|
|
#warn " = " . join(' + ', @res) . "\n" if !$cand; |
104
|
|
|
|
|
|
|
|
105
|
750
|
100
|
|
|
|
1654
|
last if !$cand; |
106
|
530
|
100
|
|
|
|
888
|
die q{Inconsistent hierarchy found while merging '} |
107
|
|
|
|
|
|
|
. $current_root . qq{':\n\t} |
108
|
|
|
|
|
|
|
. qq{current merge results [\n\t\t} |
109
|
|
|
|
|
|
|
. (join ",\n\t\t" => @res) |
110
|
|
|
|
|
|
|
. qq{\n\t]\n\t} . qq{merging failed on '$cand'\n} |
111
|
|
|
|
|
|
|
if !$winner; |
112
|
|
|
|
|
|
|
} |
113
|
220
|
|
|
|
|
602
|
\@res; |
114
|
|
|
|
|
|
|
}; |
115
|
|
|
|
|
|
|
|
116
|
406
|
100
|
|
|
|
1348
|
return @$mergeout if !@STACK; |
117
|
|
|
|
|
|
|
|
118
|
351
|
|
|
|
|
465
|
$i = pop(@STACK); |
119
|
351
|
|
|
|
|
500
|
$recurse_mergeout = pop(@STACK); |
120
|
351
|
|
|
|
|
474
|
$current_parents = pop(@STACK); |
121
|
351
|
|
|
|
|
445
|
$current_root = pop(@STACK); |
122
|
|
|
|
|
|
|
|
123
|
351
|
|
|
|
|
515
|
push(@$recurse_mergeout, $mergeout); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
1; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
__END__ |