Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm |
Statements | Executed 2319 statements in 11.1ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
59 | 2 | 1 | 1.66ms | 1.66ms | CORE:regcomp (opcode) | Exporter::Tiny::
13 | 1 | 1 | 804µs | 909µs | __ANON__[:52] | Exporter::Tiny::
13 | 13 | 12 | 790µs | 8.94ms | import | Exporter::Tiny::
13 | 1 | 1 | 775µs | 3.12ms | _exporter_permitted_regexp | Exporter::Tiny::
13 | 1 | 1 | 756µs | 756µs | CORE:sort (opcode) | Exporter::Tiny::
46 | 2 | 2 | 693µs | 719µs | _exporter_install_sub | Exporter::Tiny::
46 | 2 | 2 | 627µs | 993µs | _exporter_expand_sub | Exporter::Tiny::
372 | 4 | 1 | 233µs | 233µs | CORE:match (opcode) | Exporter::Tiny::
13 | 1 | 1 | 159µs | 159µs | mkopt | Exporter::Tiny::
1 | 1 | 1 | 113µs | 113µs | BEGIN@11 | Exporter::Tiny::
1 | 1 | 1 | 36µs | 36µs | BEGIN@3 | Exporter::Tiny::
13 | 1 | 1 | 30µs | 30µs | CORE:qr (opcode) | Exporter::Tiny::
1 | 1 | 1 | 14µs | 21µs | BEGIN@347 | Exporter::Tiny::
1 | 1 | 1 | 14µs | 14µs | _exporter_expand_tag | Exporter::Tiny::
13 | 2 | 2 | 13µs | 13µs | _exporter_validate_opts | Exporter::Tiny::
1 | 1 | 1 | 12µs | 19µs | BEGIN@253 | Exporter::Tiny::
1 | 1 | 1 | 11µs | 20µs | BEGIN@190 | Exporter::Tiny::
1 | 1 | 1 | 10µs | 27µs | BEGIN@137 | Exporter::Tiny::
1 | 1 | 1 | 10µs | 16µs | BEGIN@217 | Exporter::Tiny::
1 | 1 | 1 | 10µs | 14µs | BEGIN@396 | Exporter::Tiny::
1 | 1 | 1 | 10µs | 21µs | BEGIN@69 | Exporter::Tiny::
1 | 1 | 1 | 9µs | 12µs | BEGIN@236 | Exporter::Tiny::
1 | 1 | 1 | 9µs | 28µs | BEGIN@382 | Exporter::Tiny::
1 | 1 | 1 | 9µs | 14µs | BEGIN@4 | Exporter::Tiny::
1 | 1 | 1 | 7µs | 47µs | BEGIN@5 | Exporter::Tiny::
1 | 1 | 1 | 7µs | 28µs | BEGIN@5.25 | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | __ANON__[:126] | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | __ANON__[:139] | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | __ANON__[:145] | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | __ANON__[:364] | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | __ANON__[:368] | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _carp | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _croak | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _exporter_expand_regexp | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _exporter_fail | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _exporter_lexical_installer | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _exporter_merge_opts | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _exporter_uninstall_sub | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | _exporter_validate_unimport_opts | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | mkopt_hash | Exporter::Tiny::
0 | 0 | 0 | 0s | 0s | unimport | Exporter::Tiny::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Exporter::Tiny; | ||||
2 | |||||
3 | 2 | 52µs | 1 | 36µs | # spent 36µs within Exporter::Tiny::BEGIN@3 which was called:
# once (36µs+0s) by List::MoreUtils::BEGIN@24 at line 3 # spent 36µs making 1 call to Exporter::Tiny::BEGIN@3 |
4 | 2 | 29µs | 2 | 19µs | # spent 14µs (9+5) within Exporter::Tiny::BEGIN@4 which was called:
# once (9µs+5µs) by List::MoreUtils::BEGIN@24 at line 4 # spent 14µs making 1 call to Exporter::Tiny::BEGIN@4
# spent 5µs making 1 call to strict::import |
5 | 4 | 180µs | 4 | 136µs | use warnings; no warnings qw(void once uninitialized numeric redefine); # spent 47µs making 1 call to Exporter::Tiny::BEGIN@5
# spent 40µs making 1 call to warnings::import
# spent 28µs making 1 call to Exporter::Tiny::BEGIN@5.25
# spent 21µs making 1 call to warnings::unimport |
6 | |||||
7 | 1 | 1µs | our $AUTHORITY = 'cpan:TOBYINK'; | ||
8 | 1 | 0s | our $VERSION = '1.006000'; | ||
9 | 1 | 2µs | our @EXPORT_OK = qw< mkopt mkopt_hash _croak _carp >; | ||
10 | |||||
11 | # spent 113µs within Exporter::Tiny::BEGIN@11 which was called:
# once (113µs+0s) by List::MoreUtils::BEGIN@24 at line 18 | ||||
12 | *_HAS_NATIVE_LEXICAL_SUB = ( $] ge '5.037002' ) | ||||
13 | ? sub () { !!1 } | ||||
14 | 1 | 2µs | : sub () { !!0 }; | ||
15 | *_HAS_MODULE_LEXICAL_SUB = ( $] ge '5.011002' and eval('require Lexical::Sub') ) | ||||
16 | ? sub () { !!1 } | ||||
17 | 1 | 19µs | : sub () { !!0 }; # spent 94µs executing statements in string eval | ||
18 | 1 | 535µs | 1 | 113µs | }; # spent 113µs making 1 call to Exporter::Tiny::BEGIN@11 |
19 | |||||
20 | sub _croak ($;@) { require Carp; my $fmt = shift; @_ = sprintf($fmt, @_); goto \&Carp::croak } | ||||
21 | sub _carp ($;@) { require Carp; my $fmt = shift; @_ = sprintf($fmt, @_); goto \&Carp::carp } | ||||
22 | |||||
23 | my $_process_optlist = sub | ||||
24 | # spent 909µs (804+105) within Exporter::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm:52] which was called 13 times, avg 70µs/call:
# 13 times (804µs+105µs) by Exporter::Tiny::import at line 71, avg 70µs/call | ||||
25 | 13 | 5µs | my $class = shift; | ||
26 | 13 | 8µs | my ($global_opts, $opts, $want, $not_want) = @_; | ||
27 | |||||
28 | 13 | 41µs | while (@$opts) | ||
29 | { | ||||
30 | 47 | 16µs | my $opt = shift @{$opts}; | ||
31 | 47 | 16µs | my ($name, $value) = @$opt; | ||
32 | |||||
33 | ($name =~ m{\A\!(/.+/[msixpodual]*)\z}) ? | ||||
34 | do { | ||||
35 | my @not = $class->_exporter_expand_regexp("$1", $value, $global_opts); | ||||
36 | ++$not_want->{$_->[0]} for @not; | ||||
37 | } : | ||||
38 | ($name =~ m{\A\\z}) ? | ||||
39 | do { | ||||
40 | my @not = $class->_exporter_expand_tag("$1", $value, $global_opts); | ||||
41 | ++$not_want->{$_->[0]} for @not; | ||||
42 | } : | ||||
43 | ($name =~ m{\A\!(.+)\z}) ? | ||||
44 | 47 | 819µs | 235 | 105µs | (++$not_want->{$1}) : # spent 91µs making 234 calls to Exporter::Tiny::CORE:match, avg 389ns/call
# spent 14µs making 1 call to Exporter::Tiny::_exporter_expand_tag |
45 | ($name =~ m{\A[:-](.+)\z}) ? | ||||
46 | push(@$opts, $class->_exporter_expand_tag("$1", $value, $global_opts)) : | ||||
47 | ($name =~ m{\A/.+/[msixpodual]*\z}) ? | ||||
48 | push(@$opts, $class->_exporter_expand_regexp($name, $value, $global_opts)) : | ||||
49 | # else ? | ||||
50 | push(@$want, $opt); | ||||
51 | } | ||||
52 | 1 | 10µs | }; | ||
53 | |||||
54 | sub import | ||||
55 | # spent 8.94ms (790µs+8.14) within Exporter::Tiny::import which was called 13 times, avg 687µs/call:
# once (190µs+2.77ms) by JSON::Schema::Modern::BEGIN@31 at line 31 of JSON/Schema/Modern.pm
# once (73µs+1.14ms) by JSON::Schema::Modern::Document::BEGIN@24 at line 24 of JSON/Schema/Modern/Document.pm
# once (70µs+792µs) by JSON::Schema::Modern::Error::BEGIN@20 at line 20 of JSON/Schema/Modern/Error.pm
# once (59µs+707µs) by JSON::Schema::Modern::Result::BEGIN@18 at line 18 of JSON/Schema/Modern/Result.pm
# once (57µs+618µs) by JSON::Schema::Modern::Annotation::BEGIN@19 at line 19 of JSON/Schema/Modern/Annotation.pm
# once (44µs+474µs) by File::ShareDir::BEGIN@1 at line 1 of (eval 29)[File/ShareDir.pm:430]
# once (37µs+351µs) by JSON::Schema::Modern::Document::OpenAPI::BEGIN@26 at line 26 of JSON/Schema/Modern/Document/OpenAPI.pm
# once (58µs+252µs) by Eval::TypeTiny::import at line 89 of Eval/TypeTiny.pm
# once (49µs+239µs) by Types::Standard::BEGIN@23 at line 23 of Types/Standard.pm
# once (66µs+211µs) by JSON::Schema::Modern::BEGIN@27 at line 430 of File/ShareDir.pm
# once (33µs+227µs) by OpenAPI::Modern::BEGIN@31 at line 31 of OpenAPI/Modern.pm
# once (20µs+236µs) by Data::Perl::Role::Collection::Array::BEGIN@9 at line 9 of Data/Perl/Role/Collection/Array.pm
# once (34µs+133µs) by Types::Standard::BEGIN@19 at line 19 of Types/Standard.pm | ||||
56 | 13 | 5µs | my $class = shift; | ||
57 | 13 | 20µs | my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () }; | ||
58 | |||||
59 | 13 | 13µs | if ( defined $global_opts->{into} and $global_opts->{into} eq '-lexical' ) { | ||
60 | $global_opts->{lexical} = 1; | ||||
61 | delete $global_opts->{into}; | ||||
62 | } | ||||
63 | 13 | 36µs | if ( not defined $global_opts->{into} ) { | ||
64 | $global_opts->{into} = caller; | ||||
65 | } | ||||
66 | |||||
67 | 13 | 10µs | my @want; | ||
68 | 13 | 15µs | my %not_want; $global_opts->{not} = \%not_want; | ||
69 | 28 | 524µs | 2 | 32µs | # spent 21µs (10+11) within Exporter::Tiny::BEGIN@69 which was called:
# once (10µs+11µs) by List::MoreUtils::BEGIN@24 at line 69 # spent 21µs making 1 call to Exporter::Tiny::BEGIN@69
# spent 11µs making 1 call to strict::unimport |
70 | 13 | 34µs | 13 | 159µs | my $opts = mkopt(\@args); # spent 159µs making 13 calls to Exporter::Tiny::mkopt, avg 12µs/call |
71 | 13 | 33µs | 13 | 909µs | $class->$_process_optlist($global_opts, $opts, \@want, \%not_want); # spent 909µs making 13 calls to Exporter::Tiny::__ANON__[Exporter/Tiny.pm:52], avg 70µs/call |
72 | |||||
73 | $global_opts->{installer} ||= $class->_exporter_lexical_installer( $global_opts ) | ||||
74 | 13 | 7µs | if $global_opts->{lexical}; | ||
75 | |||||
76 | 13 | 49µs | 13 | 3.12ms | my $permitted = $class->_exporter_permitted_regexp($global_opts); # spent 3.12ms making 13 calls to Exporter::Tiny::_exporter_permitted_regexp, avg 240µs/call |
77 | 13 | 48µs | 13 | 198µs | $class->_exporter_validate_opts($global_opts); # spent 192µs making 8 calls to Type::Library::_exporter_validate_opts, avg 24µs/call
# spent 6µs making 5 calls to Exporter::Tiny::_exporter_validate_opts, avg 1µs/call |
78 | |||||
79 | 13 | 129µs | for my $wanted (@want) { | ||
80 | 46 | 22µs | next if $not_want{$wanted->[0]}; | ||
81 | |||||
82 | 46 | 108µs | 46 | 2.05ms | my %symbols = $class->_exporter_expand_sub(@$wanted, $global_opts, $permitted); # spent 1.91ms making 40 calls to Type::Library::_exporter_expand_sub, avg 48µs/call
# spent 137µs making 6 calls to Exporter::Tiny::_exporter_expand_sub, avg 23µs/call |
83 | $class->_exporter_install_sub($_, $wanted->[1], $global_opts, $symbols{$_}) | ||||
84 | 46 | 143µs | 46 | 1.70ms | for keys %symbols; # spent 1.58ms making 40 calls to Type::Library::_exporter_install_sub, avg 40µs/call
# spent 125µs making 6 calls to Exporter::Tiny::_exporter_install_sub, avg 21µs/call |
85 | } | ||||
86 | } | ||||
87 | |||||
88 | sub unimport | ||||
89 | { | ||||
90 | my $class = shift; | ||||
91 | my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () }; | ||||
92 | $global_opts->{is_unimport} = 1; | ||||
93 | |||||
94 | if ( defined $global_opts->{into} and $global_opts->{into} eq '-lexical' ) { | ||||
95 | $global_opts->{lexical} = 1; | ||||
96 | delete $global_opts->{into}; | ||||
97 | } | ||||
98 | if ( not defined $global_opts->{into} ) { | ||||
99 | $global_opts->{into} = caller; | ||||
100 | } | ||||
101 | |||||
102 | my @want; | ||||
103 | my %not_want; $global_opts->{not} = \%not_want; | ||||
104 | my @args = do { our %TRACKED; @_ ? @_ : keys(%{$TRACKED{$class}{$global_opts->{into}}}) }; | ||||
105 | my $opts = mkopt(\@args); | ||||
106 | $class->$_process_optlist($global_opts, $opts, \@want, \%not_want); | ||||
107 | |||||
108 | my $permitted = $class->_exporter_permitted_regexp($global_opts); | ||||
109 | $class->_exporter_validate_unimport_opts($global_opts); | ||||
110 | |||||
111 | my $expando = $class->can('_exporter_expand_sub'); | ||||
112 | $expando = undef if $expando == \&_exporter_expand_sub; | ||||
113 | |||||
114 | for my $wanted (@want) | ||||
115 | { | ||||
116 | next if $not_want{$wanted->[0]}; | ||||
117 | |||||
118 | if ($wanted->[1]) | ||||
119 | { | ||||
120 | _carp("Passing options to unimport '%s' makes no sense", $wanted->[0]) | ||||
121 | unless (ref($wanted->[1]) eq 'HASH' and not keys %{$wanted->[1]}); | ||||
122 | } | ||||
123 | |||||
124 | my %symbols = defined($expando) | ||||
125 | ? $class->$expando(@$wanted, $global_opts, $permitted) | ||||
126 | : ($wanted->[0] => sub { "dummy" }); | ||||
127 | $class->_exporter_uninstall_sub($_, $wanted->[1], $global_opts) | ||||
128 | for keys %symbols; | ||||
129 | } | ||||
130 | } | ||||
131 | |||||
132 | # Returns a coderef suitable to be used as a sub installer for lexical imports. | ||||
133 | # | ||||
134 | sub _exporter_lexical_installer { | ||||
135 | _HAS_NATIVE_LEXICAL_SUB and return sub { | ||||
136 | my ( $sigilname, $sym ) = @{ $_[1] }; | ||||
137 | 2 | 578µs | 2 | 44µs | # spent 27µs (10+17) within Exporter::Tiny::BEGIN@137 which was called:
# once (10µs+17µs) by List::MoreUtils::BEGIN@24 at line 137 # spent 27µs making 1 call to Exporter::Tiny::BEGIN@137
# spent 17µs making 1 call to warnings::unimport |
138 | builtin::export_lexically( $sigilname, $sym ); | ||||
139 | }; | ||||
140 | _HAS_MODULE_LEXICAL_SUB and return sub { | ||||
141 | my ( $sigilname, $sym ) = @{ $_[1] }; | ||||
142 | ( $sigilname =~ /^\w/ ) | ||||
143 | ? 'Lexical::Sub'->import( $sigilname, $sym ) | ||||
144 | : 'Lexical::Var'->import( $sigilname, $sym ); | ||||
145 | }; | ||||
146 | _croak( 'Lexical export requires Perl 5.37.2+ for native support, or Perl 5.11.2+ with the Lexical::Sub module' ); | ||||
147 | } | ||||
148 | |||||
149 | # Called once per import/unimport, passed the "global" import options. | ||||
150 | # Expected to validate the options and carp or croak if there are problems. | ||||
151 | # Can also take the opportunity to do other stuff if needed. | ||||
152 | # | ||||
153 | 13 | 101µs | # spent 13µs within Exporter::Tiny::_exporter_validate_opts which was called 13 times, avg 1µs/call:
# 8 times (7µs+0s) by Type::Library::_exporter_validate_opts at line 36 of Type/Library.pm, avg 875ns/call
# 5 times (6µs+0s) by Exporter::Tiny::import at line 77, avg 1µs/call | ||
154 | sub _exporter_validate_unimport_opts { 1 } | ||||
155 | |||||
156 | # Called after expanding a tag or regexp to merge the tag's options with | ||||
157 | # any sub-specific options. | ||||
158 | # | ||||
159 | sub _exporter_merge_opts | ||||
160 | { | ||||
161 | my $class = shift; | ||||
162 | my ($tag_opts, $global_opts, @stuff) = @_; | ||||
163 | |||||
164 | $tag_opts = {} unless ref($tag_opts) eq q(HASH); | ||||
165 | _croak('Cannot provide an -as option for tags') | ||||
166 | if exists $tag_opts->{-as} && ref $tag_opts->{-as} ne 'CODE'; | ||||
167 | |||||
168 | my $optlist = mkopt(\@stuff); | ||||
169 | for my $export (@$optlist) | ||||
170 | { | ||||
171 | next if defined($export->[1]) && ref($export->[1]) ne q(HASH); | ||||
172 | |||||
173 | my %sub_opts = ( %{ $export->[1] or {} }, %$tag_opts ); | ||||
174 | $sub_opts{-prefix} = sprintf('%s%s', $tag_opts->{-prefix}, $export->[1]{-prefix}) | ||||
175 | if exists($export->[1]{-prefix}) && exists($tag_opts->{-prefix}); | ||||
176 | $sub_opts{-suffix} = sprintf('%s%s', $export->[1]{-suffix}, $tag_opts->{-suffix}) | ||||
177 | if exists($export->[1]{-suffix}) && exists($tag_opts->{-suffix}); | ||||
178 | $export->[1] = \%sub_opts; | ||||
179 | } | ||||
180 | return @$optlist; | ||||
181 | } | ||||
182 | |||||
183 | # Given a tag name, looks it up in %EXPORT_TAGS and returns the list of | ||||
184 | # associated functions. The default implementation magically handles tags | ||||
185 | # "all" and "default". The default implementation interprets any undefined | ||||
186 | # tags as being global options. | ||||
187 | # | ||||
188 | sub _exporter_expand_tag | ||||
189 | # spent 14µs within Exporter::Tiny::_exporter_expand_tag which was called:
# once (14µs+0s) by Exporter::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm:52] at line 44 | ||||
190 | 2 | 161µs | 2 | 29µs | # spent 20µs (11+9) within Exporter::Tiny::BEGIN@190 which was called:
# once (11µs+9µs) by List::MoreUtils::BEGIN@24 at line 190 # spent 20µs making 1 call to Exporter::Tiny::BEGIN@190
# spent 9µs making 1 call to strict::unimport |
191 | |||||
192 | 1 | 1µs | my $class = shift; | ||
193 | 1 | 1µs | my ($name, $value, $globals) = @_; | ||
194 | 1 | 5µs | my $tags = \%{"$class\::EXPORT_TAGS"}; | ||
195 | |||||
196 | return $class->_exporter_merge_opts($value, $globals, $tags->{$name}->($class, @_)) | ||||
197 | 1 | 1µs | if ref($tags->{$name}) eq q(CODE); | ||
198 | |||||
199 | return $class->_exporter_merge_opts($value, $globals, @{$tags->{$name}}) | ||||
200 | 1 | 0s | if exists $tags->{$name}; | ||
201 | |||||
202 | 1 | 1µs | return $class->_exporter_merge_opts($value, $globals, @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"}) | ||
203 | if $name eq 'all'; | ||||
204 | |||||
205 | 1 | 1µs | return $class->_exporter_merge_opts($value, $globals, @{"$class\::EXPORT"}) | ||
206 | if $name eq 'default'; | ||||
207 | |||||
208 | 1 | 1µs | $globals->{$name} = $value || 1; | ||
209 | 1 | 5µs | return; | ||
210 | } | ||||
211 | |||||
212 | # Given a regexp-like string, looks it up in @EXPORT_OK and returns the | ||||
213 | # list of matching functions. | ||||
214 | # | ||||
215 | sub _exporter_expand_regexp | ||||
216 | { | ||||
217 | 2 | 133µs | 2 | 22µs | # spent 16µs (10+6) within Exporter::Tiny::BEGIN@217 which was called:
# once (10µs+6µs) by List::MoreUtils::BEGIN@24 at line 217 # spent 16µs making 1 call to Exporter::Tiny::BEGIN@217
# spent 6µs making 1 call to strict::unimport |
218 | our %TRACKED; | ||||
219 | |||||
220 | my $class = shift; | ||||
221 | my ($name, $value, $globals) = @_; | ||||
222 | my $compiled = eval("qr$name"); | ||||
223 | |||||
224 | my @possible = $globals->{is_unimport} | ||||
225 | ? keys( %{$TRACKED{$class}{$globals->{into}}} ) | ||||
226 | : @{"$class\::EXPORT_OK"}; | ||||
227 | |||||
228 | $class->_exporter_merge_opts($value, $globals, grep /$compiled/, @possible); | ||||
229 | } | ||||
230 | |||||
231 | # Helper for _exporter_expand_sub. Returns a regexp matching all subs in | ||||
232 | # the exporter package which are available for export. | ||||
233 | # | ||||
234 | sub _exporter_permitted_regexp | ||||
235 | # spent 3.12ms (775µs+2.35) within Exporter::Tiny::_exporter_permitted_regexp which was called 13 times, avg 240µs/call:
# 13 times (775µs+2.35ms) by Exporter::Tiny::import at line 76, avg 240µs/call | ||||
236 | 2 | 218µs | 2 | 15µs | # spent 12µs (9+3) within Exporter::Tiny::BEGIN@236 which was called:
# once (9µs+3µs) by List::MoreUtils::BEGIN@24 at line 236 # spent 12µs making 1 call to Exporter::Tiny::BEGIN@236
# spent 3µs making 1 call to strict::unimport |
237 | 13 | 4µs | my $class = shift; | ||
238 | my $re = join "|", map quotemeta, sort { | ||||
239 | length($b) <=> length($a) or $a cmp $b | ||||
240 | 13 | 1.36ms | 13 | 756µs | } @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"}; # spent 756µs making 13 calls to Exporter::Tiny::CORE:sort, avg 58µs/call |
241 | 13 | 1.77ms | 26 | 1.59ms | qr{^(?:$re)$}ms; # spent 1.56ms making 13 calls to Exporter::Tiny::CORE:regcomp, avg 120µs/call
# spent 30µs making 13 calls to Exporter::Tiny::CORE:qr, avg 2µs/call |
242 | } | ||||
243 | |||||
244 | # Given a sub name, returns a hash of subs to install (usually just one sub). | ||||
245 | # Keys are sub names, values are coderefs. | ||||
246 | # | ||||
247 | sub _exporter_expand_sub | ||||
248 | # spent 993µs (627+366) within Exporter::Tiny::_exporter_expand_sub which was called 46 times, avg 22µs/call:
# 40 times (545µs+311µs) by Type::Library::_exporter_expand_sub at line 113 of Type/Library.pm, avg 21µs/call
# 6 times (82µs+55µs) by Exporter::Tiny::import at line 82, avg 23µs/call | ||||
249 | 46 | 6µs | my $class = shift; | ||
250 | 46 | 21µs | my ($name, $value, $globals, $permitted) = @_; | ||
251 | 46 | 5µs | $permitted ||= $class->_exporter_permitted_regexp($globals); | ||
252 | |||||
253 | 2 | 1.06ms | 2 | 26µs | # spent 19µs (12+7) within Exporter::Tiny::BEGIN@253 which was called:
# once (12µs+7µs) by List::MoreUtils::BEGIN@24 at line 253 # spent 19µs making 1 call to Exporter::Tiny::BEGIN@253
# spent 7µs making 1 call to strict::unimport |
254 | |||||
255 | 46 | 16µs | my $sigil = "&"; | ||
256 | 46 | 87µs | 46 | 24µs | if ($name =~ /\A([&\$\%\@\*])(.+)\z/) { # spent 24µs making 46 calls to Exporter::Tiny::CORE:match, avg 522ns/call |
257 | $sigil = $1; | ||||
258 | $name = $2; | ||||
259 | if ($sigil eq '*') { | ||||
260 | _croak("Cannot export symbols with a * sigil"); | ||||
261 | } | ||||
262 | } | ||||
263 | 46 | 21µs | my $sigilname = $sigil eq '&' ? $name : "$sigil$name"; | ||
264 | |||||
265 | 46 | 286µs | 92 | 187µs | if ($sigilname =~ $permitted) # spent 95µs making 46 calls to Exporter::Tiny::CORE:regcomp, avg 2µs/call
# spent 92µs making 46 calls to Exporter::Tiny::CORE:match, avg 2µs/call |
266 | { | ||||
267 | my $generatorprefix = { | ||||
268 | '&' => "_generate_", | ||||
269 | '$' => "_generateScalar_", | ||||
270 | '@' => "_generateArray_", | ||||
271 | '%' => "_generateHash_", | ||||
272 | 46 | 142µs | }->{$sigil}; | ||
273 | |||||
274 | 46 | 221µs | 46 | 118µs | my $generator = $class->can("$generatorprefix$name"); # spent 118µs making 46 calls to UNIVERSAL::can, avg 3µs/call |
275 | 46 | 2µs | return $sigilname => $class->$generator($sigilname, $value, $globals) if $generator; | ||
276 | |||||
277 | 46 | 8µs | if ($sigil eq '&') { | ||
278 | 46 | 107µs | 46 | 37µs | my $sub = $class->can($name); # spent 37µs making 46 calls to UNIVERSAL::can, avg 804ns/call |
279 | 46 | 100µs | return $sigilname => $sub if $sub; | ||
280 | } | ||||
281 | else { | ||||
282 | # Could do this more cleverly, but this works. | ||||
283 | my $evalled = eval "\\${sigil}${class}::${name}"; | ||||
284 | return $sigilname => $evalled if $evalled; | ||||
285 | } | ||||
286 | } | ||||
287 | |||||
288 | $class->_exporter_fail(@_); | ||||
289 | } | ||||
290 | |||||
291 | # Called by _exporter_expand_sub if it is unable to generate a key-value | ||||
292 | # pair for a sub. | ||||
293 | # | ||||
294 | sub _exporter_fail | ||||
295 | { | ||||
296 | my $class = shift; | ||||
297 | my ($name, $value, $globals) = @_; | ||||
298 | return if $globals->{is_unimport}; | ||||
299 | _croak("Could not find sub '%s' exported by %s", $name, $class); | ||||
300 | } | ||||
301 | |||||
302 | # Actually performs the installation of the sub into the target package. This | ||||
303 | # also handles renaming the sub. | ||||
304 | # | ||||
305 | sub _exporter_install_sub | ||||
306 | # spent 719µs (693+26) within Exporter::Tiny::_exporter_install_sub which was called 46 times, avg 16µs/call:
# 40 times (571µs+23µs) by Type::Library::_exporter_install_sub at line 154 of Type/Library.pm, avg 15µs/call
# 6 times (122µs+3µs) by Exporter::Tiny::import at line 84, avg 21µs/call | ||||
307 | 46 | 6µs | my $class = shift; | ||
308 | 46 | 14µs | my ($name, $value, $globals, $sym) = @_; | ||
309 | 46 | 26µs | my $value_hash = ( ref($value) eq 'HASH' ) ? $value : {}; | ||
310 | |||||
311 | 46 | 12µs | my $into = $globals->{into}; | ||
312 | 46 | 13µs | my $installer = $globals->{installer} || $globals->{exporter}; | ||
313 | |||||
314 | $name = | ||||
315 | ref $globals->{as} ? $globals->{as}->($name) : | ||||
316 | ref $value_hash->{-as} ? $value_hash->{-as}->($name) : | ||||
317 | exists $value_hash->{-as} ? $value_hash->{-as} : | ||||
318 | 46 | 20µs | $name; | ||
319 | |||||
320 | 46 | 3µs | return unless defined $name; | ||
321 | |||||
322 | 46 | 6µs | my $sigil = "&"; | ||
323 | 46 | 17µs | unless (ref($name)) { | ||
324 | 46 | 106µs | 46 | 26µs | if ($name =~ /\A([&\$\%\@\*])(.+)\z/) { # spent 26µs making 46 calls to Exporter::Tiny::CORE:match, avg 565ns/call |
325 | $sigil = $1; | ||||
326 | $name = $2; | ||||
327 | if ($sigil eq '*') { | ||||
328 | _croak("Cannot export symbols with a * sigil"); | ||||
329 | } | ||||
330 | } | ||||
331 | 46 | 55µs | my ($prefix) = grep defined, $value_hash->{-prefix}, $globals->{prefix}, q(); | ||
332 | 46 | 31µs | my ($suffix) = grep defined, $value_hash->{-suffix}, $globals->{suffix}, q(); | ||
333 | 46 | 29µs | $name = "$prefix$name$suffix"; | ||
334 | } | ||||
335 | |||||
336 | 46 | 21µs | my $sigilname = $sigil eq '&' ? $name : ( $sigil . $name ); | ||
337 | |||||
338 | # if ({qw/$ SCALAR @ ARRAY % HASH & CODE/}->{$sigil} ne ref($sym)) { | ||||
339 | # warn $sym; | ||||
340 | # warn $sigilname; | ||||
341 | # _croak("Reference type %s does not match sigil %s", ref($sym), $sigil); | ||||
342 | # } | ||||
343 | |||||
344 | 46 | 9µs | return ($$name = $sym) if ref($name) eq q(SCALAR); | ||
345 | 46 | 12µs | return ($into->{$sigilname} = $sym) if ref($into) eq q(HASH); | ||
346 | |||||
347 | 2 | 198µs | 2 | 28µs | # spent 21µs (14+7) within Exporter::Tiny::BEGIN@347 which was called:
# once (14µs+7µs) by List::MoreUtils::BEGIN@24 at line 347 # spent 21µs making 1 call to Exporter::Tiny::BEGIN@347
# spent 7µs making 1 call to strict::unimport |
348 | our %TRACKED; | ||||
349 | |||||
350 | 46 | 150µs | if ( ref($sym) eq 'CODE' | ||
351 | and ref($into) ? exists($into->{$name}) : exists(&{"$into\::$name"}) | ||||
352 | and $sym != ( ref($into) ? $into->{$name} : \&{"$into\::$name"} ) ) | ||||
353 | { | ||||
354 | my ($level) = grep defined, $value_hash->{-replace}, $globals->{replace}, q(0); | ||||
355 | my $action = { | ||||
356 | carp => \&_carp, | ||||
357 | 0 => \&_carp, | ||||
358 | '' => \&_carp, | ||||
359 | warn => \&_carp, | ||||
360 | nonfatal => \&_carp, | ||||
361 | croak => \&_croak, | ||||
362 | fatal => \&_croak, | ||||
363 | die => \&_croak, | ||||
364 | }->{$level} || sub {}; | ||||
365 | |||||
366 | # Don't complain about double-installing the same sub. This isn't ideal | ||||
367 | # because the same named sub might be generated in two different ways. | ||||
368 | $action = sub {} if $TRACKED{$class}{$into}{$sigilname}; | ||||
369 | |||||
370 | $action->( | ||||
371 | $action == \&_croak | ||||
372 | ? "Refusing to overwrite existing sub '%s' with sub '%s' exported by %s" | ||||
373 | : "Overwriting existing sub '%s' with sub '%s' exported by %s", | ||||
374 | ref($into) ? $name : "$into\::$name", | ||||
375 | $_[0], | ||||
376 | $class, | ||||
377 | ); | ||||
378 | } | ||||
379 | |||||
380 | 46 | 44µs | $TRACKED{$class}{$into}{$sigilname} = $sym; | ||
381 | |||||
382 | 2 | 144µs | 2 | 47µs | # spent 28µs (9+19) within Exporter::Tiny::BEGIN@382 which was called:
# once (9µs+19µs) by List::MoreUtils::BEGIN@24 at line 382 # spent 28µs making 1 call to Exporter::Tiny::BEGIN@382
# spent 19µs making 1 call to warnings::unimport |
383 | $installer | ||||
384 | ? $installer->($globals, [$sigilname, $sym]) | ||||
385 | 46 | 189µs | : (*{"$into\::$name"} = $sym); | ||
386 | } | ||||
387 | |||||
388 | sub _exporter_uninstall_sub | ||||
389 | { | ||||
390 | our %TRACKED; | ||||
391 | my $class = shift; | ||||
392 | my ($name, $value, $globals, $sym) = @_; | ||||
393 | my $into = $globals->{into}; | ||||
394 | ref $into and return; | ||||
395 | |||||
396 | 2 | 489µs | 2 | 18µs | # spent 14µs (10+4) within Exporter::Tiny::BEGIN@396 which was called:
# once (10µs+4µs) by List::MoreUtils::BEGIN@24 at line 396 # spent 14µs making 1 call to Exporter::Tiny::BEGIN@396
# spent 4µs making 1 call to strict::unimport |
397 | |||||
398 | my $sigil = "&"; | ||||
399 | if ($name =~ /\A([&\$\%\@\*])(.+)\z/) { | ||||
400 | $sigil = $1; | ||||
401 | $name = $2; | ||||
402 | if ($sigil eq '*') { | ||||
403 | _croak("Cannot export symbols with a * sigil"); | ||||
404 | } | ||||
405 | } | ||||
406 | my $sigilname = $sigil eq '&' ? $name : "$sigil$name"; | ||||
407 | |||||
408 | if ($sigil ne '&') { | ||||
409 | _croak("Unimporting non-code symbols not supported yet"); | ||||
410 | } | ||||
411 | |||||
412 | # Cowardly refuse to uninstall a sub that differs from the one | ||||
413 | # we installed! | ||||
414 | my $our_coderef = $TRACKED{$class}{$into}{$name}; | ||||
415 | my $cur_coderef = exists(&{"$into\::$name"}) ? \&{"$into\::$name"} : -1; | ||||
416 | return unless $our_coderef == $cur_coderef; | ||||
417 | |||||
418 | my $stash = \%{"$into\::"}; | ||||
419 | my $old = delete $stash->{$name}; | ||||
420 | my $full_name = join('::', $into, $name); | ||||
421 | foreach my $type (qw(SCALAR HASH ARRAY IO)) # everything but the CODE | ||||
422 | { | ||||
423 | next unless defined(*{$old}{$type}); | ||||
424 | *$full_name = *{$old}{$type}; | ||||
425 | } | ||||
426 | |||||
427 | delete $TRACKED{$class}{$into}{$name}; | ||||
428 | } | ||||
429 | |||||
430 | sub mkopt | ||||
431 | # spent 159µs within Exporter::Tiny::mkopt which was called 13 times, avg 12µs/call:
# 13 times (159µs+0s) by Exporter::Tiny::import at line 70, avg 12µs/call | ||||
432 | 13 | 4µs | my $in = shift or return []; | ||
433 | 13 | 4µs | my @out; | ||
434 | |||||
435 | 13 | 12µs | $in = [map(($_ => ref($in->{$_}) ? $in->{$_} : ()), sort keys %$in)] | ||
436 | if ref($in) eq q(HASH); | ||||
437 | |||||
438 | 13 | 34µs | for (my $i = 0; $i < @$in; $i++) | ||
439 | { | ||||
440 | 47 | 12µs | my $k = $in->[$i]; | ||
441 | 47 | 3µs | my $v; | ||
442 | |||||
443 | 47 | 27µs | ($i == $#$in) ? ($v = undef) : | ||
444 | !defined($in->[$i+1]) ? (++$i, ($v = undef)) : | ||||
445 | !ref($in->[$i+1]) ? ($v = undef) : | ||||
446 | ($v = $in->[++$i]); | ||||
447 | |||||
448 | 47 | 32µs | push @out, [ $k => $v ]; | ||
449 | } | ||||
450 | |||||
451 | 13 | 53µs | \@out; | ||
452 | } | ||||
453 | |||||
454 | sub mkopt_hash | ||||
455 | { | ||||
456 | my $in = shift or return; | ||||
457 | my %out = map +($_->[0] => $_->[1]), @{ mkopt($in) }; | ||||
458 | \%out; | ||||
459 | } | ||||
460 | |||||
461 | 1 | 6µs | 1; | ||
462 | |||||
463 | __END__ | ||||
# spent 233µs within Exporter::Tiny::CORE:match which was called 372 times, avg 626ns/call:
# 234 times (91µs+0s) by Exporter::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm:52] at line 44, avg 389ns/call
# 46 times (92µs+0s) by Exporter::Tiny::_exporter_expand_sub at line 265, avg 2µs/call
# 46 times (26µs+0s) by Exporter::Tiny::_exporter_install_sub at line 324, avg 565ns/call
# 46 times (24µs+0s) by Exporter::Tiny::_exporter_expand_sub at line 256, avg 522ns/call | |||||
# spent 30µs within Exporter::Tiny::CORE:qr which was called 13 times, avg 2µs/call:
# 13 times (30µs+0s) by Exporter::Tiny::_exporter_permitted_regexp at line 241, avg 2µs/call | |||||
sub Exporter::Tiny::CORE:regcomp; # opcode | |||||
# spent 756µs within Exporter::Tiny::CORE:sort which was called 13 times, avg 58µs/call:
# 13 times (756µs+0s) by Exporter::Tiny::_exporter_permitted_regexp at line 240, avg 58µs/call |