Filename | /usr/share/perl5/Sub/Install.pm |
Statements | Executed 79 statements in 1.49ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 32µs | 70µs | BEGIN@176 | Sub::Install::
1 | 1 | 1 | 22µs | 50µs | __ANON__[:118] | Sub::Install::
1 | 1 | 1 | 14µs | 18µs | __ANON__[:161] | Sub::Install::
3 | 3 | 1 | 13µs | 13µs | __ANON__[:162] | Sub::Install::
3 | 3 | 1 | 13µs | 20µs | _do_with_warn | Sub::Install::
2 | 2 | 2 | 13µs | 13µs | exporter | Sub::Install::
1 | 1 | 1 | 10µs | 23µs | BEGIN@1 | Data::OptList::
1 | 1 | 1 | 10µs | 12µs | BEGIN@125 | Sub::Install::
1 | 1 | 1 | 9µs | 39µs | BEGIN@6 | Sub::Install::
1 | 1 | 1 | 8µs | 10µs | _CODELIKE | Sub::Install::
1 | 1 | 1 | 8µs | 14µs | BEGIN@273 | Sub::Install::
1 | 1 | 1 | 8µs | 58µs | __ANON__[:270] | Sub::Install::
1 | 1 | 1 | 7µs | 12µs | BEGIN@2 | Data::OptList::
1 | 1 | 1 | 7µs | 17µs | BEGIN@170 | Sub::Install::
2 | 2 | 1 | 6µs | 6µs | _build_public_installer | Sub::Install::
1 | 1 | 1 | 5µs | 6µs | BEGIN@134 | Sub::Install::
3 | 3 | 1 | 5µs | 5µs | _installer | Sub::Install::
1 | 1 | 1 | 4µs | 4µs | __ANON__[:173] | Sub::Install::
3 | 3 | 1 | 3µs | 3µs | CORE:qr (opcode) | Sub::Install::
1 | 1 | 1 | 3µs | 3µs | BEGIN@7 | Sub::Install::
0 | 0 | 0 | 0s | 0s | __ANON__[:142] | Sub::Install::
0 | 0 | 0 | 0s | 0s | __ANON__[:159] | Sub::Install::
0 | 0 | 0 | 0s | 0s | __ANON__[:236] | Sub::Install::
0 | 0 | 0 | 0s | 0s | _name_of_code | Sub::Install::
0 | 0 | 0 | 0s | 0s | install_installers | Sub::Install::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | 2 | 25µs | 2 | 35µs | # spent 23µs (10+12) within Data::OptList::BEGIN@1 which was called:
# once (10µs+12µs) by Data::OptList::BEGIN@11 at line 1 # spent 23µs making 1 call to Data::OptList::BEGIN@1
# spent 12µs making 1 call to strict::import |
2 | 2 | 36µs | 2 | 16µs | # spent 12µs (7+4) within Data::OptList::BEGIN@2 which was called:
# once (7µs+4µs) by Data::OptList::BEGIN@11 at line 2 # spent 12µs making 1 call to Data::OptList::BEGIN@2
# spent 4µs making 1 call to warnings::import |
3 | package Sub::Install; | ||||
4 | # ABSTRACT: install subroutines into packages easily | ||||
5 | 1 | 400ns | $Sub::Install::VERSION = '0.928'; | ||
6 | 2 | 22µs | 2 | 69µs | # spent 39µs (9+30) within Sub::Install::BEGIN@6 which was called:
# once (9µs+30µs) by Data::OptList::BEGIN@11 at line 6 # spent 39µs making 1 call to Sub::Install::BEGIN@6
# spent 30µs making 1 call to Exporter::import |
7 | 2 | 350µs | 1 | 3µs | # spent 3µs within Sub::Install::BEGIN@7 which was called:
# once (3µs+0s) by Data::OptList::BEGIN@11 at line 7 # spent 3µs making 1 call to Sub::Install::BEGIN@7 |
8 | |||||
9 | #pod =head1 SYNOPSIS | ||||
10 | #pod | ||||
11 | #pod use Sub::Install; | ||||
12 | #pod | ||||
13 | #pod Sub::Install::install_sub({ | ||||
14 | #pod code => sub { ... }, | ||||
15 | #pod into => $package, | ||||
16 | #pod as => $subname | ||||
17 | #pod }); | ||||
18 | #pod | ||||
19 | #pod =head1 DESCRIPTION | ||||
20 | #pod | ||||
21 | #pod This module makes it easy to install subroutines into packages without the | ||||
22 | #pod unsightly mess of C<no strict> or typeglobs lying about where just anyone can | ||||
23 | #pod see them. | ||||
24 | #pod | ||||
25 | #pod =func install_sub | ||||
26 | #pod | ||||
27 | #pod Sub::Install::install_sub({ | ||||
28 | #pod code => \&subroutine, | ||||
29 | #pod into => "Finance::Shady", | ||||
30 | #pod as => 'launder', | ||||
31 | #pod }); | ||||
32 | #pod | ||||
33 | #pod This routine installs a given code reference into a package as a normal | ||||
34 | #pod subroutine. The above is equivalent to: | ||||
35 | #pod | ||||
36 | #pod no strict 'refs'; | ||||
37 | #pod *{"Finance::Shady" . '::' . "launder"} = \&subroutine; | ||||
38 | #pod | ||||
39 | #pod If C<into> is not given, the sub is installed into the calling package. | ||||
40 | #pod | ||||
41 | #pod If C<code> is not a code reference, it is looked for as an existing sub in the | ||||
42 | #pod package named in the C<from> parameter. If C<from> is not given, it will look | ||||
43 | #pod in the calling package. | ||||
44 | #pod | ||||
45 | #pod If C<as> is not given, and if C<code> is a name, C<as> will default to C<code>. | ||||
46 | #pod If C<as> is not given, but if C<code> is a code ref, Sub::Install will try to | ||||
47 | #pod find the name of the given code ref and use that as C<as>. | ||||
48 | #pod | ||||
49 | #pod That means that this code: | ||||
50 | #pod | ||||
51 | #pod Sub::Install::install_sub({ | ||||
52 | #pod code => 'twitch', | ||||
53 | #pod from => 'Person::InPain', | ||||
54 | #pod into => 'Person::Teenager', | ||||
55 | #pod as => 'dance', | ||||
56 | #pod }); | ||||
57 | #pod | ||||
58 | #pod is the same as: | ||||
59 | #pod | ||||
60 | #pod package Person::Teenager; | ||||
61 | #pod | ||||
62 | #pod Sub::Install::install_sub({ | ||||
63 | #pod code => Person::InPain->can('twitch'), | ||||
64 | #pod as => 'dance', | ||||
65 | #pod }); | ||||
66 | #pod | ||||
67 | #pod =func reinstall_sub | ||||
68 | #pod | ||||
69 | #pod This routine behaves exactly like C<L</install_sub>>, but does not emit a | ||||
70 | #pod warning if warnings are on and the destination is already defined. | ||||
71 | #pod | ||||
72 | #pod =cut | ||||
73 | |||||
74 | sub _name_of_code { | ||||
75 | my ($code) = @_; | ||||
76 | require B; | ||||
77 | my $name = B::svref_2object($code)->GV->NAME; | ||||
78 | return $name unless $name =~ /\A__ANON__/; | ||||
79 | return; | ||||
80 | } | ||||
81 | |||||
82 | # See also Params::Util, to which this code was donated. | ||||
83 | # spent 10µs (8+2) within Sub::Install::_CODELIKE which was called:
# once (8µs+2µs) by Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:118] at line 103 | ||||
84 | 1 | 12µs | 2 | 2µs | (Scalar::Util::reftype($_[0])||'') eq 'CODE' # spent 1µs making 1 call to Scalar::Util::reftype
# spent 500ns making 1 call to Scalar::Util::blessed |
85 | || Scalar::Util::blessed($_[0]) | ||||
86 | && (overload::Method($_[0],'&{}') ? $_[0] : undef); | ||||
87 | } | ||||
88 | |||||
89 | # do the heavy lifting | ||||
90 | sub _build_public_installer { | ||||
91 | 2 | 400ns | my ($installer) = @_; | ||
92 | |||||
93 | # spent 50µs (22+29) within Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:118] which was called:
# once (22µs+29µs) by Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:270] at line 268 | ||||
94 | 1 | 300ns | my ($arg) = @_; | ||
95 | 1 | 3µs | my ($calling_pkg) = caller(0); | ||
96 | |||||
97 | # I'd rather use ||= but I'm whoring for Devel::Cover. | ||||
98 | 3 | 2µs | for (qw(into from)) { $arg->{$_} = $calling_pkg unless $arg->{$_} } | ||
99 | |||||
100 | # This is the only absolutely required argument, in many cases. | ||||
101 | 1 | 200ns | Carp::croak "named argument 'code' is not optional" unless $arg->{code}; | ||
102 | |||||
103 | 1 | 1µs | 1 | 10µs | if (_CODELIKE($arg->{code})) { # spent 10µs making 1 call to Sub::Install::_CODELIKE |
104 | $arg->{as} ||= _name_of_code($arg->{code}); | ||||
105 | } else { | ||||
106 | 1 | 9µs | 1 | 1µs | Carp::croak # spent 1µs making 1 call to UNIVERSAL::can |
107 | "couldn't find subroutine named $arg->{code} in package $arg->{from}" | ||||
108 | unless my $code = $arg->{from}->can($arg->{code}); | ||||
109 | |||||
110 | 1 | 700ns | $arg->{as} = $arg->{code} unless $arg->{as}; | ||
111 | 1 | 700ns | $arg->{code} = $code; | ||
112 | } | ||||
113 | |||||
114 | 1 | 200ns | Carp::croak "couldn't determine name under which to install subroutine" | ||
115 | unless $arg->{as}; | ||||
116 | |||||
117 | 1 | 4µs | 1 | 18µs | $installer->(@$arg{qw(into as code) }); # spent 18µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:161] |
118 | } | ||||
119 | 2 | 10µs | } | ||
120 | |||||
121 | # do the ugly work | ||||
122 | |||||
123 | 1 | 100ns | my $_misc_warn_re; | ||
124 | my $_redef_warn_re; | ||||
125 | # spent 12µs (10+2) within Sub::Install::BEGIN@125 which was called:
# once (10µs+2µs) by Data::OptList::BEGIN@11 at line 131 | ||||
126 | 1 | 7µs | 1 | 2µs | $_misc_warn_re = qr/ # spent 2µs making 1 call to Sub::Install::CORE:qr |
127 | Prototype\ mismatch:\ sub\ .+? | | ||||
128 | Constant subroutine .+? redefined | ||||
129 | /x; | ||||
130 | 1 | 4µs | 1 | 700ns | $_redef_warn_re = qr/Subroutine\ .+?\ redefined/x; # spent 700ns making 1 call to Sub::Install::CORE:qr |
131 | 1 | 31µs | 1 | 12µs | } # spent 12µs making 1 call to Sub::Install::BEGIN@125 |
132 | |||||
133 | my $eow_re; | ||||
134 | 1 | 325µs | 2 | 7µs | # spent 6µs (5+1000ns) within Sub::Install::BEGIN@134 which was called:
# once (5µs+1000ns) by Data::OptList::BEGIN@11 at line 134 # spent 6µs making 1 call to Sub::Install::BEGIN@134
# spent 1µs making 1 call to Sub::Install::CORE:qr |
135 | |||||
136 | sub _do_with_warn { | ||||
137 | 3 | 700ns | my ($arg) = @_; | ||
138 | 3 | 2µs | my $code = delete $arg->{code}; | ||
139 | my $wants_code = sub { | ||||
140 | 3 | 400ns | my $code = shift; | ||
141 | # spent 18µs (14+4) within Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:161] which was called:
# once (14µs+4µs) by Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:118] at line 117 | ||||
142 | 1 | 2µs | my $warn = $SIG{__WARN__} ? $SIG{__WARN__} : sub { warn @_ }; ## no critic | ||
143 | local $SIG{__WARN__} = sub { | ||||
144 | my ($error) = @_; | ||||
145 | for (@{ $arg->{suppress} }) { | ||||
146 | return if $error =~ $_; | ||||
147 | } | ||||
148 | for (@{ $arg->{croak} }) { | ||||
149 | if (my ($base_error) = $error =~ /\A($_) $eow_re/x) { | ||||
150 | Carp::croak $base_error; | ||||
151 | } | ||||
152 | } | ||||
153 | for (@{ $arg->{carp} }) { | ||||
154 | if (my ($base_error) = $error =~ /\A($_) $eow_re/x) { | ||||
155 | return $warn->(Carp::shortmess $base_error); | ||||
156 | } | ||||
157 | } | ||||
158 | ($arg->{default} || $warn)->($error); | ||||
159 | 1 | 3µs | }; | ||
160 | 1 | 8µs | 1 | 4µs | $code->(@_); # spent 4µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:173] |
161 | 3 | 18µs | }; | ||
162 | 3 | 4µs | }; | ||
163 | 3 | 3µs | 1 | 7µs | return $wants_code->($code) if $code; # spent 7µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:162] |
164 | 2 | 7µs | return $wants_code; | ||
165 | } | ||||
166 | |||||
167 | sub _installer { | ||||
168 | # spent 4µs within Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:173] which was called:
# once (4µs+0s) by Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:161] at line 160 | ||||
169 | 1 | 500ns | my ($pkg, $name, $code) = @_; | ||
170 | 2 | 250µs | 2 | 27µs | # spent 17µs (7+10) within Sub::Install::BEGIN@170 which was called:
# once (7µs+10µs) by Data::OptList::BEGIN@11 at line 170 # spent 17µs making 1 call to Sub::Install::BEGIN@170
# spent 10µs making 1 call to strict::unimport |
171 | 1 | 2µs | *{"$pkg\::$name"} = $code; | ||
172 | 1 | 3µs | return $code; | ||
173 | } | ||||
174 | 3 | 9µs | } | ||
175 | |||||
176 | # spent 70µs (32+38) within Sub::Install::BEGIN@176 which was called:
# once (32µs+38µs) by Data::OptList::BEGIN@11 at line 194 | ||||
177 | 1 | 3µs | 1 | 5µs | *_ignore_warnings = _do_with_warn({ # spent 5µs making 1 call to Sub::Install::_do_with_warn |
178 | carp => [ $_misc_warn_re, $_redef_warn_re ] | ||||
179 | }); | ||||
180 | |||||
181 | 1 | 3µs | 3 | 11µs | *install_sub = _build_public_installer(_ignore_warnings(_installer)); # spent 5µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:162]
# spent 4µs making 1 call to Sub::Install::_build_public_installer
# spent 2µs making 1 call to Sub::Install::_installer |
182 | |||||
183 | 1 | 2µs | 1 | 2µs | *_carp_warnings = _do_with_warn({ # spent 2µs making 1 call to Sub::Install::_do_with_warn |
184 | carp => [ $_misc_warn_re ], | ||||
185 | suppress => [ $_redef_warn_re ], | ||||
186 | }); | ||||
187 | |||||
188 | 1 | 2µs | 3 | 6µs | *reinstall_sub = _build_public_installer(_carp_warnings(_installer)); # spent 2µs making 1 call to Sub::Install::_build_public_installer
# spent 2µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:162]
# spent 2µs making 1 call to Sub::Install::_installer |
189 | |||||
190 | 1 | 4µs | 2 | 14µs | *_install_fatal = _do_with_warn({ # spent 12µs making 1 call to Sub::Install::_do_with_warn
# spent 2µs making 1 call to Sub::Install::_installer |
191 | code => _installer, | ||||
192 | croak => [ $_redef_warn_re ], | ||||
193 | }); | ||||
194 | 1 | 252µs | 1 | 70µs | } # spent 70µs making 1 call to Sub::Install::BEGIN@176 |
195 | |||||
196 | #pod =func install_installers | ||||
197 | #pod | ||||
198 | #pod This routine is provided to allow Sub::Install compatibility with | ||||
199 | #pod Sub::Installer. It installs C<install_sub> and C<reinstall_sub> methods into | ||||
200 | #pod the package named by its argument. | ||||
201 | #pod | ||||
202 | #pod Sub::Install::install_installers('Code::Builder'); # just for us, please | ||||
203 | #pod Code::Builder->install_sub({ name => $code_ref }); | ||||
204 | #pod | ||||
205 | #pod Sub::Install::install_installers('UNIVERSAL'); # feeling lucky, punk? | ||||
206 | #pod Anything::At::All->install_sub({ name => $code_ref }); | ||||
207 | #pod | ||||
208 | #pod The installed installers are similar, but not identical, to those provided by | ||||
209 | #pod Sub::Installer. They accept a single hash as an argument. The key/value pairs | ||||
210 | #pod are used as the C<as> and C<code> parameters to the C<install_sub> routine | ||||
211 | #pod detailed above. The package name on which the method is called is used as the | ||||
212 | #pod C<into> parameter. | ||||
213 | #pod | ||||
214 | #pod Unlike Sub::Installer's C<install_sub> will not eval strings into code, but | ||||
215 | #pod will look for named code in the calling package. | ||||
216 | #pod | ||||
217 | #pod =cut | ||||
218 | |||||
219 | sub install_installers { | ||||
220 | my ($into) = @_; | ||||
221 | |||||
222 | for my $method (qw(install_sub reinstall_sub)) { | ||||
223 | my $code = sub { | ||||
224 | my ($package, $subs) = @_; | ||||
225 | my ($caller) = caller(0); | ||||
226 | my $return; | ||||
227 | for (my ($name, $sub) = %$subs) { | ||||
228 | $return = Sub::Install->can($method)->({ | ||||
229 | code => $sub, | ||||
230 | from => $caller, | ||||
231 | into => $package, | ||||
232 | as => $name | ||||
233 | }); | ||||
234 | } | ||||
235 | return $return; | ||||
236 | }; | ||||
237 | install_sub({ code => $code, into => $into, as => $method }); | ||||
238 | } | ||||
239 | } | ||||
240 | |||||
241 | #pod =head1 EXPORTS | ||||
242 | #pod | ||||
243 | #pod Sub::Install exports C<install_sub> and C<reinstall_sub> only if they are | ||||
244 | #pod requested. | ||||
245 | #pod | ||||
246 | #pod =head2 exporter | ||||
247 | #pod | ||||
248 | #pod Sub::Install has a never-exported subroutine called C<exporter>, which is used | ||||
249 | #pod to implement its C<import> routine. It takes a hashref of named arguments, | ||||
250 | #pod only one of which is currently recognize: C<exports>. This must be an arrayref | ||||
251 | #pod of subroutines to offer for export. | ||||
252 | #pod | ||||
253 | #pod This routine is mainly for Sub::Install's own consumption. Instead, consider | ||||
254 | #pod L<Sub::Exporter>. | ||||
255 | #pod | ||||
256 | #pod =cut | ||||
257 | |||||
258 | # spent 13µs within Sub::Install::exporter which was called 2 times, avg 6µs/call:
# once (7µs+0s) by Data::OptList::BEGIN@100 at line 101 of Data/OptList.pm
# once (6µs+0s) by Sub::Install::BEGIN@273 at line 273 | ||||
259 | 2 | 800ns | my ($arg) = @_; | ||
260 | |||||
261 | 2 | 6µs | my %is_exported = map { $_ => undef } @{ $arg->{exports} }; | ||
262 | |||||
263 | # spent 58µs (8+50) within Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:270] which was called:
# once (8µs+50µs) by Class::Load::BEGIN@10 at line 10 of Class/Load.pm | ||||
264 | 1 | 300ns | my $class = shift; | ||
265 | 1 | 600ns | my $target = caller; | ||
266 | 1 | 3µs | for (@_) { | ||
267 | 1 | 300ns | Carp::croak "'$_' is not exported by $class" if !exists $is_exported{$_}; | ||
268 | 1 | 3µs | 1 | 50µs | install_sub({ code => $_, from => $class, into => $target }); # spent 50µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:118] |
269 | } | ||||
270 | } | ||||
271 | 2 | 12µs | } | ||
272 | |||||
273 | 1 | 38µs | 2 | 20µs | # spent 14µs (8+6) within Sub::Install::BEGIN@273 which was called:
# once (8µs+6µs) by Data::OptList::BEGIN@11 at line 273 # spent 14µs making 1 call to Sub::Install::BEGIN@273
# spent 6µs making 1 call to Sub::Install::exporter |
274 | |||||
275 | #pod =head1 SEE ALSO | ||||
276 | #pod | ||||
277 | #pod =over | ||||
278 | #pod | ||||
279 | #pod =item L<Sub::Installer> | ||||
280 | #pod | ||||
281 | #pod This module is (obviously) a reaction to Damian Conway's Sub::Installer, which | ||||
282 | #pod does the same thing, but does it by getting its greasy fingers all over | ||||
283 | #pod UNIVERSAL. I was really happy about the idea of making the installation of | ||||
284 | #pod coderefs less ugly, but I couldn't bring myself to replace the ugliness of | ||||
285 | #pod typeglobs and loosened strictures with the ugliness of UNIVERSAL methods. | ||||
286 | #pod | ||||
287 | #pod =item L<Sub::Exporter> | ||||
288 | #pod | ||||
289 | #pod This is a complete Exporter.pm replacement, built atop Sub::Install. | ||||
290 | #pod | ||||
291 | #pod =back | ||||
292 | #pod | ||||
293 | #pod =head1 EXTRA CREDITS | ||||
294 | #pod | ||||
295 | #pod Several of the tests are adapted from tests that shipped with Damian Conway's | ||||
296 | #pod Sub-Installer distribution. | ||||
297 | #pod | ||||
298 | #pod =cut | ||||
299 | |||||
300 | 1 | 2µs | 1; | ||
301 | |||||
302 | __END__ | ||||
sub Sub::Install::CORE:qr; # opcode |