| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Data::Annotation::Expression::Builtin; |
|
2
|
3
|
|
|
3
|
|
8586
|
use v5.24; |
|
|
3
|
|
|
|
|
14
|
|
|
3
|
3
|
|
|
3
|
|
20
|
use utf8; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
23
|
|
|
4
|
3
|
|
|
3
|
|
141
|
use warnings; |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
249
|
|
|
5
|
3
|
|
|
3
|
|
92
|
use experimental qw< signatures >; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
24
|
|
|
6
|
|
|
|
|
|
|
{ our $VERSION = '0.006' } |
|
7
|
|
|
|
|
|
|
|
|
8
|
7
|
|
|
7
|
1
|
13
|
sub factory ($parse_ctx, $name) { |
|
|
7
|
|
|
|
|
14
|
|
|
|
7
|
|
|
|
|
11
|
|
|
|
7
|
|
|
|
|
12
|
|
|
9
|
0
|
|
|
|
|
0
|
state $immediate_for = { |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# numeric comparisons |
|
12
|
0
|
|
|
0
|
|
0
|
'<' => sub ($l, $r) { $l < $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
13
|
0
|
|
|
0
|
|
0
|
'<=' => sub ($l, $r) { $l <= $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
14
|
0
|
|
|
0
|
|
0
|
'>' => sub ($l, $r) { $l > $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
15
|
0
|
|
|
0
|
|
0
|
'>=' => sub ($l, $r) { $l >= $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
16
|
0
|
|
|
0
|
|
0
|
'==' => sub ($l, $r) { $l == $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
17
|
0
|
|
|
0
|
|
0
|
'!=' => sub ($l, $r) { $l != $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
18
|
0
|
|
|
0
|
|
0
|
'<=>' => sub ($l, $r) { $l <=> $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# string comparisons |
|
21
|
0
|
|
|
0
|
|
0
|
lt => sub ($l, $r) { $l lt $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
22
|
0
|
|
|
0
|
|
0
|
le => sub ($l, $r) { $l le $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
23
|
0
|
|
|
0
|
|
0
|
gt => sub ($l, $r) { $l gt $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
24
|
0
|
|
|
0
|
|
0
|
ge => sub ($l, $r) { $l ge $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
25
|
4
|
|
|
4
|
|
17
|
eq => sub ($l, $r) { $l eq $r }, |
|
|
4
|
|
|
|
|
37
|
|
|
|
4
|
|
|
|
|
9
|
|
|
|
4
|
|
|
|
|
7
|
|
|
|
4
|
|
|
|
|
5
|
|
|
26
|
0
|
|
|
0
|
|
0
|
ne => sub ($l, $r) { $l ne $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
27
|
0
|
|
|
0
|
|
0
|
cmp => sub ($l, $r) { $l cmp $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# regular expression match/unmatch |
|
30
|
2
|
|
|
|
|
53
|
match => \&match, |
|
31
|
|
|
|
|
|
|
'=~' => \&match, |
|
32
|
|
|
|
|
|
|
unmatch => \&unmatch, |
|
33
|
|
|
|
|
|
|
'!~' => \&unmatch, |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# boolean operators |
|
36
|
2
|
100
|
|
2
|
|
6
|
and => sub (@os) { for my $o (@os) { return 0 if !$o } ; 1 }, |
|
|
4
|
|
|
|
|
18
|
|
|
|
1
|
|
|
|
|
9
|
|
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
22
|
|
|
37
|
0
|
0
|
|
0
|
|
0
|
or => sub (@os) { for my $o (@os) { return 1 if $o } ; 0 }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
38
|
0
|
|
|
0
|
|
0
|
not => sub ($o) { return !$o }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
39
|
0
|
|
0
|
0
|
|
0
|
xor => sub ($r, @os) { $r = ($r xor $_) for @os; return $r }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# set operations |
|
42
|
0
|
|
|
|
|
0
|
union => \&set_union, |
|
43
|
|
|
|
|
|
|
U => \&set_union, |
|
44
|
|
|
|
|
|
|
'⋃' => \&set_union, |
|
45
|
|
|
|
|
|
|
intersection => \&set_intersection, |
|
46
|
|
|
|
|
|
|
'⋂' => \&set_intersection, |
|
47
|
|
|
|
|
|
|
less => \&set_less, |
|
48
|
|
|
|
|
|
|
symmetric_difference => \&set_symmetric_difference, |
|
49
|
|
|
|
|
|
|
is_superset_of => \&set_is_superset_of, |
|
50
|
|
|
|
|
|
|
'⊇' => \&set_is_superset_of, |
|
51
|
|
|
|
|
|
|
is_subset_of => \&set_is_subset_of, |
|
52
|
|
|
|
|
|
|
'⊆' => \&set_is_subset_of, |
|
53
|
|
|
|
|
|
|
is_element_of => \&set_is_element_of, |
|
54
|
|
|
|
|
|
|
'∈' => \&set_is_element_of, |
|
55
|
|
|
|
|
|
|
contains => \&set_contains, |
|
56
|
|
|
|
|
|
|
'∋' => \&set_contains, |
|
57
|
|
|
|
|
|
|
sets_are_same => \&sets_are_same, |
|
58
|
0
|
|
|
0
|
|
0
|
set_size => sub ($s) { return scalar($s->@*) }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
59
|
0
|
|
|
0
|
|
0
|
set_is_empty => sub ($s) { return scalar($s->@*) == 0 }, |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# other utilities |
|
62
|
0
|
|
|
0
|
|
0
|
array => sub ($x) { |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
63
|
0
|
0
|
|
|
|
0
|
ref($x) eq 'ARRAY' ? $x : defined($x) ? [ $x ] : []; |
|
|
|
0
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
}, |
|
65
|
0
|
|
|
0
|
|
0
|
trim => sub ($x) { |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
0
|
0
|
|
|
|
0
|
return $x =~ s{\A\s+|\s+\z}{}rgmxs unless ref($x) eq 'ARRAY'; |
|
67
|
0
|
|
|
|
|
0
|
return [ map { s{\A\s+|\s+\z}{}rgmxs } $x->@* ]; |
|
|
0
|
|
|
|
|
0
|
|
|
68
|
|
|
|
|
|
|
}, |
|
69
|
|
|
|
|
|
|
|
|
70
|
7
|
|
|
|
|
131
|
}; |
|
71
|
7
|
50
|
|
|
|
41
|
return $immediate_for->{$name} if exists($immediate_for->{$name}); |
|
72
|
0
|
|
|
|
|
0
|
return; # nothing found, sorry! |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
5
|
|
|
5
|
1
|
10
|
sub match ($string, $rx) { scalar($string =~ m{$rx}) } |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
141
|
|
|
76
|
|
|
|
|
|
|
|
|
77
|
0
|
|
|
0
|
1
|
|
sub unmatch ($string, $rx) { scalar($string !~ m{$rx}) } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
|
79
|
0
|
|
|
0
|
1
|
|
sub sets_are_same ($lhs, $rhs) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
|
my %in_lhs = map { $_ => 1 } $lhs->@*; |
|
|
0
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
my %seen_in_rhs; |
|
82
|
0
|
|
|
|
|
|
for my $item ($rhs->@*) { |
|
83
|
0
|
0
|
|
|
|
|
next if $seen_in_rhs{$item}++; |
|
84
|
0
|
0
|
|
|
|
|
return 0 unless exists($in_lhs{$item}); |
|
85
|
0
|
|
|
|
|
|
delete($in_lhs{$item}); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
0
|
|
|
|
|
|
return scalar(keys(%in_lhs)) == 0; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
0
|
|
|
0
|
1
|
|
sub set_contains ($set, $target) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
91
|
0
|
0
|
|
|
|
|
for my $item ($set->@*) { return 1 if $item eq $target } |
|
|
0
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
return 0; |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
0
|
|
|
0
|
1
|
|
sub set_intersection (@lists) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
96
|
0
|
0
|
|
|
|
|
return [] unless @lists; |
|
97
|
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
my $first = shift(@lists); |
|
99
|
0
|
0
|
|
|
|
|
return [ $first->@* ] unless @lists; |
|
100
|
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
my $whole; |
|
102
|
0
|
|
|
|
|
|
$whole->{$_} = 1 for $first->@*; |
|
103
|
0
|
|
|
|
|
|
for my $list (@lists) { |
|
104
|
0
|
0
|
|
|
|
|
return [] unless scalar(keys($whole->%*)); |
|
105
|
0
|
|
|
|
|
|
($whole, my $previous) = ({}, $whole); |
|
106
|
0
|
|
|
|
|
|
for my $item ($list->@*) { |
|
107
|
0
|
0
|
|
|
|
|
$whole->{$item} = 1 if $previous->{$item} |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
} |
|
110
|
0
|
|
|
|
|
|
return set_sorted_result($whole); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
0
|
|
|
0
|
1
|
|
sub set_is_element_of ($elem, $set) { return set_contains($set, $elem) } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
|
115
|
0
|
|
|
0
|
1
|
|
sub set_is_subset_of ($lh, $rh) { return set_is_superset_of($rh, $lh) } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
|
117
|
0
|
|
|
0
|
1
|
|
sub set_is_superset_of ($lhs, $rhs) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
118
|
0
|
|
|
|
|
|
my %in_lhs = map { $_ => 1 } $lhs->@*; |
|
|
0
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
for my $item ($rhs->@*) { |
|
120
|
0
|
0
|
|
|
|
|
return 0 unless exists($in_lhs{$item}); |
|
121
|
|
|
|
|
|
|
} |
|
122
|
0
|
|
|
|
|
|
return 1; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
|
|
125
|
0
|
|
|
0
|
1
|
|
sub set_less ($lhs, $rhs) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
my %in_rhs = map { $_ => 1 } $rhs->@*; |
|
|
0
|
|
|
|
|
|
|
|
127
|
0
|
|
|
|
|
|
my %result = map { $_ => 1 } grep { ! $in_rhs{$_} } $lhs->@*; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
|
return set_sorted_result(\%result); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
0
|
|
|
0
|
1
|
|
sub set_sorted_result ($href) { [ sort { $a cmp $b } keys($href->%*) ] } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
|
133
|
0
|
|
|
0
|
1
|
|
sub set_symmetric_difference ($lhs, $rhs) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
134
|
0
|
|
|
|
|
|
my %result = map { $_ => 1 } $lhs->@*; |
|
|
0
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my %in_rhs = map { $_ => 1 } $rhs->@*; |
|
|
0
|
|
|
|
|
|
|
|
136
|
0
|
|
|
|
|
|
for my $item (keys(%in_rhs)) { |
|
137
|
0
|
0
|
|
|
|
|
if (exists($result{$item})) { delete($result{$item}) } |
|
|
0
|
|
|
|
|
|
|
|
138
|
0
|
|
|
|
|
|
else { $result{$item} = 1 } # add it |
|
139
|
|
|
|
|
|
|
} |
|
140
|
0
|
|
|
|
|
|
return set_sorted_result(\%result); |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
0
|
|
|
0
|
1
|
|
sub set_union (@lists) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
144
|
0
|
|
|
|
|
|
my %whole; |
|
145
|
0
|
|
|
|
|
|
for my $list (@lists) { $whole{$_} = 1 for $list->@* } |
|
|
0
|
|
|
|
|
|
|
|
146
|
0
|
|
|
|
|
|
return set_sorted_result(\%whole); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
1; |