| Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm | 
| Statements | Executed 2319 statements in 10.5ms | 
| Calls | P | F | Exclusive Time  | 
        Inclusive Time  | 
        Subroutine | 
|---|---|---|---|---|---|
| 59 | 2 | 1 | 1.81ms | 1.81ms | Exporter::Tiny::CORE:regcomp (opcode) | 
| 13 | 1 | 1 | 1.01ms | 3.62ms | Exporter::Tiny::_exporter_permitted_regexp | 
| 13 | 1 | 1 | 844µs | 844µs | Exporter::Tiny::CORE:sort (opcode) | 
| 13 | 13 | 12 | 735µs | 8.42ms | Exporter::Tiny::import | 
| 46 | 2 | 2 | 569µs | 676µs | Exporter::Tiny::_exporter_install_sub | 
| 46 | 2 | 2 | 532µs | 824µs | Exporter::Tiny::_exporter_expand_sub | 
| 13 | 1 | 1 | 372µs | 463µs | Exporter::Tiny::__ANON__[:52] | 
| 372 | 4 | 1 | 282µs | 282µs | Exporter::Tiny::CORE:match (opcode) | 
| 13 | 1 | 1 | 134µs | 134µs | Exporter::Tiny::mkopt | 
| 1 | 1 | 1 | 116µs | 116µs | Exporter::Tiny::BEGIN@11 | 
| 1 | 1 | 1 | 56µs | 56µs | Exporter::Tiny::BEGIN@3 | 
| 13 | 1 | 1 | 25µs | 25µs | Exporter::Tiny::CORE:qr (opcode) | 
| 1 | 1 | 1 | 17µs | 29µs | Exporter::Tiny::BEGIN@253 | 
| 13 | 2 | 2 | 14µs | 14µs | Exporter::Tiny::_exporter_validate_opts | 
| 1 | 1 | 1 | 11µs | 28µs | Exporter::Tiny::BEGIN@137 | 
| 1 | 1 | 1 | 11µs | 15µs | Exporter::Tiny::BEGIN@396 | 
| 1 | 1 | 1 | 11µs | 28µs | Exporter::Tiny::BEGIN@5.25 | 
| 1 | 1 | 1 | 11µs | 11µs | Exporter::Tiny::_exporter_expand_tag | 
| 1 | 1 | 1 | 10µs | 20µs | Exporter::Tiny::BEGIN@4 | 
| 1 | 1 | 1 | 9µs | 15µs | Exporter::Tiny::BEGIN@190 | 
| 1 | 1 | 1 | 9µs | 53µs | Exporter::Tiny::BEGIN@5 | 
| 1 | 1 | 1 | 8µs | 19µs | Exporter::Tiny::BEGIN@69 | 
| 1 | 1 | 1 | 7µs | 11µs | Exporter::Tiny::BEGIN@217 | 
| 1 | 1 | 1 | 7µs | 12µs | Exporter::Tiny::BEGIN@347 | 
| 1 | 1 | 1 | 7µs | 23µs | Exporter::Tiny::BEGIN@382 | 
| 1 | 1 | 1 | 6µs | 9µs | Exporter::Tiny::BEGIN@236 | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::__ANON__[:126] | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::__ANON__[:139] | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::__ANON__[:145] | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::__ANON__[:364] | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::__ANON__[:368] | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_carp | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_croak | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_exporter_expand_regexp | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_exporter_fail | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_exporter_lexical_installer | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_exporter_merge_opts | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_exporter_uninstall_sub | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::_exporter_validate_unimport_opts | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::mkopt_hash | 
| 0 | 0 | 0 | 0s | 0s | Exporter::Tiny::unimport | 
| Line | State ments  | 
      Time on line  | 
      Calls | Time in subs  | 
      Code | 
|---|---|---|---|---|---|
| 1 | package Exporter::Tiny; | ||||
| 2 | |||||
| 3 | 2 | 124µs | 1 | 56µs | # spent 56µs within Exporter::Tiny::BEGIN@3 which was called:
#    once (56µs+0s) by List::MoreUtils::BEGIN@24 at line 3 # spent    56µs making 1 call to Exporter::Tiny::BEGIN@3  | 
| 4 | 2 | 41µs | 2 | 30µs | # spent 20µs (10+10) within Exporter::Tiny::BEGIN@4 which was called:
#    once (10µs+10µs) by List::MoreUtils::BEGIN@24 at line 4 # spent    20µs making 1 call to Exporter::Tiny::BEGIN@4
# spent    10µs making 1 call to strict::import  | 
| 5 | 4 | 202µs | 4 | 142µs | use warnings; no warnings qw(void once uninitialized numeric redefine); # spent    53µs making 1 call to Exporter::Tiny::BEGIN@5
# spent    44µs making 1 call to warnings::import
# spent    28µs making 1 call to Exporter::Tiny::BEGIN@5.25
# spent    17µ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 | 1µs | our @EXPORT_OK = qw< mkopt mkopt_hash _croak _carp >; | ||
| 10 | |||||
| 11 | # spent 116µs within Exporter::Tiny::BEGIN@11 which was called:
#    once (116µ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 | 18µs |                 : sub () { !!0 };                 # spent    96µs executing statements in string eval  | ||
| 18 | 1 | 463µs | 1 | 116µs | }; # spent   116µ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 463µs (372+91) within Exporter::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm:52] which was called 13 times, avg 36µs/call:
# 13 times (372µs+91µs) by Exporter::Tiny::import at line 71, avg 36µs/call  | ||||
| 25 | 13 | 2µs | my $class = shift; | ||
| 26 | 13 | 8µs | my ($global_opts, $opts, $want, $not_want) = @_; | ||
| 27 | |||||
| 28 | 13 | 37µs | while (@$opts) | ||
| 29 | { | ||||
| 30 | 47 | 8µs | my $opt = shift @{$opts}; | ||
| 31 | 47 | 9µ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 | 395µs | 235 | 91µs |                         (++$not_want->{$1}) :                         # spent    80µs making 234 calls to Exporter::Tiny::CORE:match, avg 342ns/call
                        # spent    11µ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 | 4µs | }; | ||
| 53 | |||||
| 54 | sub import | ||||
| 55 | # spent 8.42ms (735µs+7.69) within Exporter::Tiny::import which was called 13 times, avg 648µs/call:
#    once (141µs+2.30ms) by JSON::Schema::Modern::BEGIN@31 at line 31 of JSON/Schema/Modern.pm
#    once (56µs+986µs) by JSON::Schema::Modern::Document::BEGIN@24 at line 24 of JSON/Schema/Modern/Document.pm
#    once (65µs+739µs) by JSON::Schema::Modern::Error::BEGIN@20 at line 20 of JSON/Schema/Modern/Error.pm
#    once (75µs+727µs) by JSON::Schema::Modern::Document::OpenAPI::BEGIN@26 at line 26 of JSON/Schema/Modern/Document/OpenAPI.pm
#    once (40µs+642µs) by OpenAPI::Modern::BEGIN@31 at line 31 of OpenAPI/Modern.pm
#    once (34µs+459µs) by File::ShareDir::BEGIN@1 at line 1 of (eval 29)[File/ShareDir.pm:430]
#    once (40µs+389µs) by JSON::Schema::Modern::Result::BEGIN@18 at line 18 of JSON/Schema/Modern/Result.pm
#    once (26µs+368µs) by Data::Perl::Role::Collection::Array::BEGIN@9 at line 9 of Data/Perl/Role/Collection/Array.pm
#    once (28µs+352µs) by JSON::Schema::Modern::Annotation::BEGIN@19 at line 19 of JSON/Schema/Modern/Annotation.pm
#    once (123µs+205µs) by JSON::Schema::Modern::BEGIN@27 at line 430 of File/ShareDir.pm
#    once (45µs+227µs) by Eval::TypeTiny::import at line 89 of Eval/TypeTiny.pm
#    once (33µs+192µs) by Types::Standard::BEGIN@23 at line 23 of Types/Standard.pm
#    once (29µs+105µs) by Types::Standard::BEGIN@19 at line 19 of Types/Standard.pm  | ||||
| 56 | 13 | 4µs | my $class = shift; | ||
| 57 | 13 | 18µs | my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () }; | ||
| 58 | |||||
| 59 | 13 | 9µ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 | 19µs | if ( not defined $global_opts->{into} ) { | ||
| 64 | $global_opts->{into} = caller; | ||||
| 65 | } | ||||
| 66 | |||||
| 67 | 13 | 4µs | my @want; | ||
| 68 | 13 | 11µs | my %not_want; $global_opts->{not} = \%not_want; | ||
| 69 | 28 | 481µs | 2 | 30µs | # spent 19µs (8+11) within Exporter::Tiny::BEGIN@69 which was called:
#    once (8µs+11µs) by List::MoreUtils::BEGIN@24 at line 69         # spent    19µs making 1 call to Exporter::Tiny::BEGIN@69
        # spent    11µs making 1 call to strict::unimport  | 
| 70 | 13 | 22µs | 13 | 134µs |         my $opts = mkopt(\@args);         # spent   134µs making 13 calls to Exporter::Tiny::mkopt, avg 10µs/call  | 
| 71 | 13 | 34µs | 13 | 463µs |         $class->$_process_optlist($global_opts, $opts, \@want, \%not_want);         # spent   463µs making 13 calls to Exporter::Tiny::__ANON__[Exporter/Tiny.pm:52], avg 36µs/call  | 
| 72 | |||||
| 73 | $global_opts->{installer} ||= $class->_exporter_lexical_installer( $global_opts ) | ||||
| 74 | 13 | 5µs | if $global_opts->{lexical}; | ||
| 75 | |||||
| 76 | 13 | 35µs | 13 | 3.62ms |         my $permitted = $class->_exporter_permitted_regexp($global_opts);         # spent  3.62ms making 13 calls to Exporter::Tiny::_exporter_permitted_regexp, avg 278µs/call  | 
| 77 | 13 | 38µs | 13 | 120µs |         $class->_exporter_validate_opts($global_opts);         # spent   116µs making 8 calls to Type::Library::_exporter_validate_opts, avg 14µs/call
        # spent     4µs making 5 calls to Exporter::Tiny::_exporter_validate_opts, avg 800ns/call  | 
| 78 | |||||
| 79 | 13 | 103µs | for my $wanted (@want) { | ||
| 80 | 46 | 17µs | next if $not_want{$wanted->[0]}; | ||
| 81 | |||||
| 82 | 46 | 107µs | 46 | 1.92ms |                 my %symbols = $class->_exporter_expand_sub(@$wanted, $global_opts, $permitted);                 # spent  1.79ms making 40 calls to Type::Library::_exporter_expand_sub, avg 45µs/call
                # spent   134µs making  6 calls to Exporter::Tiny::_exporter_expand_sub, avg 22µs/call  | 
| 83 | $class->_exporter_install_sub($_, $wanted->[1], $global_opts, $symbols{$_}) | ||||
| 84 | 46 | 196µs | 46 | 1.43ms |                         for keys %symbols;                         # spent  1.34ms making 40 calls to Type::Library::_exporter_install_sub, avg 34µs/call
                        # spent    88µs making  6 calls to Exporter::Tiny::_exporter_install_sub, avg 15µ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 | 426µs | 2 | 45µs | # spent 28µs (11+17) within Exporter::Tiny::BEGIN@137 which was called:
#    once (11µs+17µs) by List::MoreUtils::BEGIN@24 at line 137                 # spent    28µ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 | 51µs | # spent 14µs within Exporter::Tiny::_exporter_validate_opts which was called 13 times, avg 1µs/call:
# 8 times (10µs+0s) by Type::Library::_exporter_validate_opts at line 36 of Type/Library.pm, avg 1µs/call
# 5 times (4µs+0s) by Exporter::Tiny::import at line 77, avg 800ns/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 11µs within Exporter::Tiny::_exporter_expand_tag which was called:
#    once (11µs+0s) by Exporter::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm:52] at line 44  | ||||
| 190 | 2 | 186µs | 2 | 21µs | # spent 15µs (9+6) within Exporter::Tiny::BEGIN@190 which was called:
#    once (9µs+6µs) by List::MoreUtils::BEGIN@24 at line 190         # spent    15µs making 1 call to Exporter::Tiny::BEGIN@190
        # spent     6µ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 | 4µ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 | 0s | 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 | 4µ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 | 116µs | 2 | 15µs | # spent 11µs (7+4) within Exporter::Tiny::BEGIN@217 which was called:
#    once (7µs+4µs) by List::MoreUtils::BEGIN@24 at line 217         # spent    11µs making 1 call to Exporter::Tiny::BEGIN@217
        # spent     4µ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.62ms (1.01+2.61) within Exporter::Tiny::_exporter_permitted_regexp which was called 13 times, avg 278µs/call:
# 13 times (1.01ms+2.61ms) by Exporter::Tiny::import at line 76, avg 278µs/call  | ||||
| 236 | 2 | 216µs | 2 | 12µs | # spent 9µs (6+3) within Exporter::Tiny::BEGIN@236 which was called:
#    once (6µs+3µs) by List::MoreUtils::BEGIN@24 at line 236         # spent     9µs making 1 call to Exporter::Tiny::BEGIN@236
        # spent     3µs making 1 call to strict::unimport  | 
| 237 | 13 | 7µs | my $class = shift; | ||
| 238 | my $re = join "|", map quotemeta, sort { | ||||
| 239 | length($b) <=> length($a) or $a cmp $b | ||||
| 240 | 13 | 1.67ms | 13 | 844µs |         } @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"};         # spent   844µs making 13 calls to Exporter::Tiny::CORE:sort, avg 65µs/call  | 
| 241 | 13 | 1.95ms | 26 | 1.77ms |         qr{^(?:$re)$}ms;         # spent  1.74ms making 13 calls to Exporter::Tiny::CORE:regcomp, avg 134µs/call
        # spent    25µ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 824µs (532+292) within Exporter::Tiny::_exporter_expand_sub which was called 46 times, avg 18µs/call:
# 40 times (440µs+250µs) by Type::Library::_exporter_expand_sub at line 113 of Type/Library.pm, avg 17µs/call
#  6 times (92µs+42µs) by Exporter::Tiny::import at line 82, avg 22µs/call  | ||||
| 249 | 46 | 5µs | my $class = shift; | ||
| 250 | 46 | 14µs | my ($name, $value, $globals, $permitted) = @_; | ||
| 251 | 46 | 8µs | $permitted ||= $class->_exporter_permitted_regexp($globals); | ||
| 252 | |||||
| 253 | 2 | 872µs | 2 | 41µs | # spent 29µs (17+12) within Exporter::Tiny::BEGIN@253 which was called:
#    once (17µs+12µs) by List::MoreUtils::BEGIN@24 at line 253         # spent    29µs making 1 call to Exporter::Tiny::BEGIN@253
        # spent    12µs making 1 call to strict::unimport  | 
| 254 | |||||
| 255 | 46 | 10µs | my $sigil = "&"; | ||
| 256 | 46 | 79µs | 46 | 28µs |         if ($name =~ /\A([&\$\%\@\*])(.+)\z/) {         # spent    28µs making 46 calls to Exporter::Tiny::CORE:match, avg 609ns/call  | 
| 257 | $sigil = $1; | ||||
| 258 | $name = $2; | ||||
| 259 | if ($sigil eq '*') { | ||||
| 260 | _croak("Cannot export symbols with a * sigil"); | ||||
| 261 | } | ||||
| 262 | } | ||||
| 263 | 46 | 19µs | my $sigilname = $sigil eq '&' ? $name : "$sigil$name"; | ||
| 264 | |||||
| 265 | 46 | 227µs | 92 | 138µs |         if ($sigilname =~ $permitted)         # spent    71µs making 46 calls to Exporter::Tiny::CORE:regcomp, avg 2µs/call
        # spent    67µs making 46 calls to Exporter::Tiny::CORE:match, avg 1µs/call  | 
| 266 | { | ||||
| 267 | my $generatorprefix = { | ||||
| 268 | '&' => "_generate_", | ||||
| 269 | '$' => "_generateScalar_", | ||||
| 270 | '@' => "_generateArray_", | ||||
| 271 | '%' => "_generateHash_", | ||||
| 272 | 46 | 90µs | }->{$sigil}; | ||
| 273 | |||||
| 274 | 46 | 181µs | 46 | 91µs |                 my $generator = $class->can("$generatorprefix$name");                 # spent    91µs making 46 calls to UNIVERSAL::can, avg 2µs/call  | 
| 275 | 46 | 6µs | return $sigilname => $class->$generator($sigilname, $value, $globals) if $generator; | ||
| 276 | |||||
| 277 | 46 | 11µs | if ($sigil eq '&') { | ||
| 278 | 46 | 102µs | 46 | 35µs |                         my $sub = $class->can($name);                         # spent    35µs making 46 calls to UNIVERSAL::can, avg 761ns/call  | 
| 279 | 46 | 177µ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 676µs (569+107) within Exporter::Tiny::_exporter_install_sub which was called 46 times, avg 15µs/call:
# 40 times (483µs+105µs) by Type::Library::_exporter_install_sub at line 154 of Type/Library.pm, avg 15µs/call
#  6 times (86µs+2µs) by Exporter::Tiny::import at line 84, avg 15µs/call  | ||||
| 307 | 46 | 14µs | my $class = shift; | ||
| 308 | 46 | 18µs | my ($name, $value, $globals, $sym) = @_; | ||
| 309 | 46 | 19µs | my $value_hash = ( ref($value) eq 'HASH' ) ? $value : {}; | ||
| 310 | |||||
| 311 | 46 | 12µs | my $into = $globals->{into}; | ||
| 312 | 46 | 15µ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 | 18µs | $name; | ||
| 319 | |||||
| 320 | 46 | 10µs | return unless defined $name; | ||
| 321 | |||||
| 322 | 46 | 4µs | my $sigil = "&"; | ||
| 323 | 46 | 19µs | unless (ref($name)) { | ||
| 324 | 46 | 190µs | 46 | 107µs |                 if ($name =~ /\A([&\$\%\@\*])(.+)\z/) {                 # spent   107µs making 46 calls to Exporter::Tiny::CORE:match, avg 2µs/call  | 
| 325 | $sigil = $1; | ||||
| 326 | $name = $2; | ||||
| 327 | if ($sigil eq '*') { | ||||
| 328 | _croak("Cannot export symbols with a * sigil"); | ||||
| 329 | } | ||||
| 330 | } | ||||
| 331 | 46 | 56µs | my ($prefix) = grep defined, $value_hash->{-prefix}, $globals->{prefix}, q(); | ||
| 332 | 46 | 22µs | my ($suffix) = grep defined, $value_hash->{-suffix}, $globals->{suffix}, q(); | ||
| 333 | 46 | 23µs | $name = "$prefix$name$suffix"; | ||
| 334 | } | ||||
| 335 | |||||
| 336 | 46 | 13µ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 | 7µs | return ($into->{$sigilname} = $sym) if ref($into) eq q(HASH); | ||
| 346 | |||||
| 347 | 2 | 178µs | 2 | 17µs | # spent 12µs (7+5) within Exporter::Tiny::BEGIN@347 which was called:
#    once (7µs+5µs) by List::MoreUtils::BEGIN@24 at line 347         # spent    12µs making 1 call to Exporter::Tiny::BEGIN@347
        # spent     5µs making 1 call to strict::unimport  | 
| 348 | our %TRACKED; | ||||
| 349 | |||||
| 350 | 46 | 62µ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 | 29µs | $TRACKED{$class}{$into}{$sigilname} = $sym; | ||
| 381 | |||||
| 382 | 2 | 134µs | 2 | 39µs | # spent 23µs (7+16) within Exporter::Tiny::BEGIN@382 which was called:
#    once (7µs+16µs) by List::MoreUtils::BEGIN@24 at line 382         # spent    23µs making 1 call to Exporter::Tiny::BEGIN@382
        # spent    16µs making 1 call to warnings::unimport  | 
| 383 | $installer | ||||
| 384 | ? $installer->($globals, [$sigilname, $sym]) | ||||
| 385 | 46 | 168µ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 | 448µs | 2 | 19µs | # spent 15µs (11+4) within Exporter::Tiny::BEGIN@396 which was called:
#    once (11µs+4µs) by List::MoreUtils::BEGIN@24 at line 396         # spent    15µ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 134µs within Exporter::Tiny::mkopt which was called 13 times, avg 10µs/call:
# 13 times (134µs+0s) by Exporter::Tiny::import at line 70, avg 10µs/call  | ||||
| 432 | 13 | 7µs | my $in = shift or return []; | ||
| 433 | 13 | 3µs | my @out; | ||
| 434 | |||||
| 435 | 13 | 10µs | $in = [map(($_ => ref($in->{$_}) ? $in->{$_} : ()), sort keys %$in)] | ||
| 436 | if ref($in) eq q(HASH); | ||||
| 437 | |||||
| 438 | 13 | 28µs | for (my $i = 0; $i < @$in; $i++) | ||
| 439 | { | ||||
| 440 | 47 | 12µs | my $k = $in->[$i]; | ||
| 441 | 47 | 2µs | my $v; | ||
| 442 | |||||
| 443 | 47 | 21µ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 | 26µs | push @out, [ $k => $v ]; | ||
| 449 | } | ||||
| 450 | |||||
| 451 | 13 | 48µ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 | 7µs | 1; | ||
| 462 | |||||
| 463 | __END__ | ||||
# spent 282µs within Exporter::Tiny::CORE:match which was called 372 times, avg 758ns/call:
# 234 times (80µs+0s) by Exporter::Tiny::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Exporter/Tiny.pm:52] at line 44, avg 342ns/call
#  46 times (107µs+0s) by Exporter::Tiny::_exporter_install_sub at line 324, avg 2µs/call
#  46 times (67µs+0s) by Exporter::Tiny::_exporter_expand_sub at line 265, avg 1µs/call
#  46 times (28µs+0s) by Exporter::Tiny::_exporter_expand_sub at line 256, avg 609ns/call  | |||||
# spent 25µs within Exporter::Tiny::CORE:qr which was called 13 times, avg 2µs/call:
# 13 times (25µs+0s) by Exporter::Tiny::_exporter_permitted_regexp at line 241, avg 2µs/call  | |||||
sub Exporter::Tiny::CORE:regcomp; # opcode  | |||||
# spent 844µs within Exporter::Tiny::CORE:sort which was called 13 times, avg 65µs/call:
# 13 times (844µs+0s) by Exporter::Tiny::_exporter_permitted_regexp at line 240, avg 65µs/call  |