| Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPI/Token/Symbol.pm |
| Statements | Executed 97704 statements in 203ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 7754 | 1 | 1 | 211ms | 362ms | PPI::Token::Symbol::__TOKENIZER__on_char |
| 29489 | 4 | 1 | 26.9ms | 26.9ms | PPI::Token::Symbol::CORE:match (opcode) |
| 1 | 1 | 1 | 11µs | 23µs | PPI::Token::Symbol::BEGIN@30 |
| 1 | 1 | 1 | 8µs | 8µs | PPI::Token::Symbol::BEGIN@35 |
| 1 | 1 | 1 | 7µs | 28µs | PPI::Token::Symbol::BEGIN@31 |
| 1 | 1 | 1 | 6µs | 34µs | PPI::Token::Symbol::BEGIN@34 |
| 1 | 1 | 1 | 3µs | 3µs | PPI::Token::Symbol::BEGIN@32 |
| 0 | 0 | 0 | 0s | 0s | PPI::Token::Symbol::canonical |
| 0 | 0 | 0 | 0s | 0s | PPI::Token::Symbol::raw_type |
| 0 | 0 | 0 | 0s | 0s | PPI::Token::Symbol::symbol |
| 0 | 0 | 0 | 0s | 0s | PPI::Token::Symbol::symbol_type |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package PPI::Token::Symbol; | ||||
| 2 | |||||
| 3 | =pod | ||||
| 4 | |||||
| 5 | =head1 NAME | ||||
| 6 | |||||
| 7 | PPI::Token::Symbol - A token class for variables and other symbols | ||||
| 8 | |||||
| 9 | =head1 INHERITANCE | ||||
| 10 | |||||
| 11 | PPI::Token::Symbol | ||||
| 12 | isa PPI::Token | ||||
| 13 | isa PPI::Element | ||||
| 14 | |||||
| 15 | =head1 DESCRIPTION | ||||
| 16 | |||||
| 17 | The C<PPI::Token::Symbol> class is used to cover all tokens that represent | ||||
| 18 | variables and other things that start with a sigil. | ||||
| 19 | |||||
| 20 | =head1 METHODS | ||||
| 21 | |||||
| 22 | This class has several methods beyond what is provided by its | ||||
| 23 | L<PPI::Token> and L<PPI::Element> parent classes. | ||||
| 24 | |||||
| 25 | Most methods are provided to help work out what the object is actually | ||||
| 26 | pointing at, rather than what it might appear to be pointing at. | ||||
| 27 | |||||
| 28 | =cut | ||||
| 29 | |||||
| 30 | 2 | 28µs | 2 | 35µs | # spent 23µs (11+12) within PPI::Token::Symbol::BEGIN@30 which was called:
# once (11µs+12µs) by PPI::Token::BEGIN@51 at line 30 # spent 23µs making 1 call to PPI::Token::Symbol::BEGIN@30
# spent 12µs making 1 call to strict::import |
| 31 | 2 | 28µs | 2 | 48µs | # spent 28µs (7+21) within PPI::Token::Symbol::BEGIN@31 which was called:
# once (7µs+21µs) by PPI::Token::BEGIN@51 at line 31 # spent 28µs making 1 call to PPI::Token::Symbol::BEGIN@31
# spent 21µs making 1 call to Exporter::import |
| 32 | 2 | 19µs | 1 | 3µs | # spent 3µs within PPI::Token::Symbol::BEGIN@32 which was called:
# once (3µs+0s) by PPI::Token::BEGIN@51 at line 32 # spent 3µs making 1 call to PPI::Token::Symbol::BEGIN@32 |
| 33 | |||||
| 34 | 2 | 41µs | 2 | 63µs | # spent 34µs (6+28) within PPI::Token::Symbol::BEGIN@34 which was called:
# once (6µs+28µs) by PPI::Token::BEGIN@51 at line 34 # spent 34µs making 1 call to PPI::Token::Symbol::BEGIN@34
# spent 28µs making 1 call to vars::import |
| 35 | # spent 8µs within PPI::Token::Symbol::BEGIN@35 which was called:
# once (8µs+0s) by PPI::Token::BEGIN@51 at line 38 | ||||
| 36 | 1 | 300ns | $VERSION = '1.215'; | ||
| 37 | 1 | 9µs | @ISA = 'PPI::Token'; | ||
| 38 | 1 | 528µs | 1 | 8µs | } # spent 8µs making 1 call to PPI::Token::Symbol::BEGIN@35 |
| 39 | |||||
| - - | |||||
| 44 | ##################################################################### | ||||
| 45 | # PPI::Token::Symbol Methods | ||||
| 46 | |||||
| 47 | =pod | ||||
| 48 | |||||
| 49 | =head2 canonical | ||||
| 50 | |||||
| 51 | The C<canonical> method returns a normalized, canonical version of the | ||||
| 52 | symbol. | ||||
| 53 | |||||
| 54 | For example, it converts C<$ ::foo'bar::baz> to C<$main::foo::bar::baz>. | ||||
| 55 | |||||
| 56 | This does not fully resolve the symbol, but merely removes syntax | ||||
| 57 | variations. | ||||
| 58 | |||||
| 59 | =cut | ||||
| 60 | |||||
| 61 | sub canonical { | ||||
| 62 | my $symbol = shift->content; | ||||
| 63 | $symbol =~ s/\s+//; | ||||
| 64 | $symbol =~ s/(?<=[\$\@\%\&\*])::/main::/; | ||||
| 65 | $symbol =~ s/\'/::/g; | ||||
| 66 | $symbol; | ||||
| 67 | } | ||||
| 68 | |||||
| 69 | =pod | ||||
| 70 | |||||
| 71 | =head2 symbol | ||||
| 72 | |||||
| 73 | The C<symbol> method returns the ACTUAL symbol this token refers to. | ||||
| 74 | |||||
| 75 | A token of C<$foo> might actually be referring to C<@foo>, if it is found | ||||
| 76 | in the form C<$foo[1]>. | ||||
| 77 | |||||
| 78 | This method attempts to resolve these issues to determine the actual | ||||
| 79 | symbol. | ||||
| 80 | |||||
| 81 | Returns the symbol as a string. | ||||
| 82 | |||||
| 83 | =cut | ||||
| 84 | |||||
| 85 | 1 | 3µs | my %cast_which_trumps_braces = map { $_ => 1 } qw{ $ @ }; | ||
| 86 | |||||
| 87 | sub symbol { | ||||
| 88 | my $self = shift; | ||||
| 89 | my $symbol = $self->canonical; | ||||
| 90 | |||||
| 91 | # Immediately return the cases where it can't be anything else | ||||
| 92 | my $type = substr( $symbol, 0, 1 ); | ||||
| 93 | return $symbol if $type eq '%'; | ||||
| 94 | return $symbol if $type eq '&'; | ||||
| 95 | |||||
| 96 | # Unless the next significant Element is a structure, it's correct. | ||||
| 97 | my $after = $self->snext_sibling; | ||||
| 98 | return $symbol unless _INSTANCE($after, 'PPI::Structure'); | ||||
| 99 | |||||
| 100 | # Process the rest for cases where it might actually be something else | ||||
| 101 | my $braces = $after->braces; | ||||
| 102 | return $symbol unless defined $braces; | ||||
| 103 | if ( $type eq '$' ) { | ||||
| 104 | |||||
| 105 | # If it is cast to '$' or '@', that trumps any braces | ||||
| 106 | my $before = $self->sprevious_sibling; | ||||
| 107 | return $symbol if $before && | ||||
| 108 | $before->isa( 'PPI::Token::Cast' ) && | ||||
| 109 | $cast_which_trumps_braces{ $before->content }; | ||||
| 110 | |||||
| 111 | # Otherwise the braces rule | ||||
| 112 | substr( $symbol, 0, 1, '@' ) if $braces eq '[]'; | ||||
| 113 | substr( $symbol, 0, 1, '%' ) if $braces eq '{}'; | ||||
| 114 | |||||
| 115 | } elsif ( $type eq '@' ) { | ||||
| 116 | substr( $symbol, 0, 1, '%' ) if $braces eq '{}'; | ||||
| 117 | |||||
| 118 | } | ||||
| 119 | |||||
| 120 | $symbol; | ||||
| 121 | } | ||||
| 122 | |||||
| 123 | =pod | ||||
| 124 | |||||
| 125 | =head2 raw_type | ||||
| 126 | |||||
| 127 | The C<raw_type> method returns the B<apparent> type of the symbol in the | ||||
| 128 | form of its sigil. | ||||
| 129 | |||||
| 130 | Returns the sigil as a string. | ||||
| 131 | |||||
| 132 | =cut | ||||
| 133 | |||||
| 134 | sub raw_type { | ||||
| 135 | substr( $_[0]->content, 0, 1 ); | ||||
| 136 | } | ||||
| 137 | |||||
| 138 | =pod | ||||
| 139 | |||||
| 140 | =head2 symbol_type | ||||
| 141 | |||||
| 142 | The C<symbol_type> method returns the B<actual> type of the symbol in the | ||||
| 143 | form of its sigil. | ||||
| 144 | |||||
| 145 | Returns the sigil as a string. | ||||
| 146 | |||||
| 147 | =cut | ||||
| 148 | |||||
| 149 | sub symbol_type { | ||||
| 150 | substr( $_[0]->symbol, 0, 1 ); | ||||
| 151 | } | ||||
| 152 | |||||
| - - | |||||
| 157 | ##################################################################### | ||||
| 158 | # Tokenizer Methods | ||||
| 159 | |||||
| 160 | # spent 362ms (211+151) within PPI::Token::Symbol::__TOKENIZER__on_char which was called 7754 times, avg 47µs/call:
# 7754 times (211ms+151ms) by PPI::Tokenizer::_process_next_char at line 554 of PPI/Tokenizer.pm, avg 47µs/call | ||||
| 161 | 7754 | 1.32ms | my $t = $_[1]; | ||
| 162 | |||||
| 163 | # Suck in till the end of the symbol | ||||
| 164 | 7754 | 3.84ms | my $line = substr( $t->{line}, $t->{line_cursor} ); | ||
| 165 | 7754 | 40.4ms | 7754 | 8.72ms | if ( $line =~ /^([\w:\']+)/ ) { # spent 8.72ms making 7754 calls to PPI::Token::Symbol::CORE:match, avg 1µs/call |
| 166 | 7217 | 7.16ms | $t->{token}->{content} .= $1; | ||
| 167 | 7217 | 3.74ms | $t->{line_cursor} += length $1; | ||
| 168 | } | ||||
| 169 | |||||
| 170 | # Handle magic things | ||||
| 171 | 7754 | 3.17ms | my $content = $t->{token}->{content}; | ||
| 172 | 7754 | 2.09ms | if ( $content eq '@_' or $content eq '$_' ) { | ||
| 173 | 509 | 949µs | 509 | 4.07ms | $t->{class} = $t->{token}->set_class( 'Magic' ); # spent 4.07ms making 509 calls to PPI::Token::set_class, avg 8µs/call |
| 174 | 509 | 2.08ms | 1018 | 10.8ms | return $t->_finalize_token->__TOKENIZER__on_char( $t ); # spent 9.48ms making 509 calls to PPI::Token::Whitespace::__TOKENIZER__on_char, avg 19µs/call
# spent 1.33ms making 509 calls to PPI::Tokenizer::_finalize_token, avg 3µs/call |
| 175 | } | ||||
| 176 | |||||
| 177 | # Shortcut for most of the X:: symbols | ||||
| 178 | 7245 | 411µs | if ( $content eq '$::' ) { | ||
| 179 | # May well be an alternate form of a Magic | ||||
| 180 | my $nextchar = substr( $t->{line}, $t->{line_cursor}, 1 ); | ||||
| 181 | if ( $nextchar eq '|' ) { | ||||
| 182 | $t->{token}->{content} .= $nextchar; | ||||
| 183 | $t->{line_cursor}++; | ||||
| 184 | $t->{class} = $t->{token}->set_class( 'Magic' ); | ||||
| 185 | } | ||||
| 186 | return $t->_finalize_token->__TOKENIZER__on_char( $t ); | ||||
| 187 | } | ||||
| 188 | 7245 | 25.2ms | 7245 | 2.54ms | if ( $content =~ /^[\$%*@&]::(?:[^\w]|$)/ ) { # spent 2.54ms making 7245 calls to PPI::Token::Symbol::CORE:match, avg 351ns/call |
| 189 | my $current = substr( $content, 0, 3, '' ); | ||||
| 190 | $t->{token}->{content} = $current; | ||||
| 191 | $t->{line_cursor} -= length( $content ); | ||||
| 192 | return $t->_finalize_token->__TOKENIZER__on_char( $t ); | ||||
| 193 | } | ||||
| 194 | 7245 | 24.0ms | 7245 | 5.42ms | if ( $content =~ /^(?:\$|\@)\d+/ ) { # spent 5.42ms making 7245 calls to PPI::Token::Symbol::CORE:match, avg 748ns/call |
| 195 | $t->{class} = $t->{token}->set_class( 'Magic' ); | ||||
| 196 | return $t->_finalize_token->__TOKENIZER__on_char( $t ); | ||||
| 197 | } | ||||
| 198 | |||||
| 199 | # Trim off anything we oversucked... | ||||
| 200 | 7245 | 35.1ms | 7245 | 10.3ms | $content =~ /^( # spent 10.3ms making 7245 calls to PPI::Token::Symbol::CORE:match, avg 1µs/call |
| 201 | [\$@%&*] | ||||
| 202 | (?: : (?!:) | # Allow single-colon non-magic vars | ||||
| 203 | (?: \w+ | \' (?!\d) \w+ | \:: \w+ ) | ||||
| 204 | (?: | ||||
| 205 | # Allow both :: and ' in namespace separators | ||||
| 206 | (?: \' (?!\d) \w+ | \:: \w+ ) | ||||
| 207 | )* | ||||
| 208 | (?: :: )? # Technically a compiler-magic hash, but keep it here | ||||
| 209 | ) | ||||
| 210 | )/x or return undef; | ||||
| 211 | 7245 | 4.82ms | unless ( length $1 eq length $content ) { | ||
| 212 | $t->{line_cursor} += length($1) - length($content); | ||||
| 213 | $t->{token}->{content} = $1; | ||||
| 214 | } | ||||
| 215 | |||||
| 216 | 7245 | 48.0ms | 14490 | 110ms | $t->_finalize_token->__TOKENIZER__on_char( $t ); # spent 88.5ms making 7245 calls to PPI::Token::Whitespace::__TOKENIZER__on_char, avg 12µs/call
# spent 21.2ms making 7245 calls to PPI::Tokenizer::_finalize_token, avg 3µs/call |
| 217 | } | ||||
| 218 | |||||
| 219 | 1 | 3µs | 1; | ||
| 220 | |||||
| 221 | =pod | ||||
| 222 | |||||
| 223 | =head1 SUPPORT | ||||
| 224 | |||||
| 225 | See the L<support section|PPI/SUPPORT> in the main module. | ||||
| 226 | |||||
| 227 | =head1 AUTHOR | ||||
| 228 | |||||
| 229 | Adam Kennedy E<lt>adamk@cpan.orgE<gt> | ||||
| 230 | |||||
| 231 | =head1 COPYRIGHT | ||||
| 232 | |||||
| 233 | Copyright 2001 - 2011 Adam Kennedy. | ||||
| 234 | |||||
| 235 | This program is free software; you can redistribute | ||||
| 236 | it and/or modify it under the same terms as Perl itself. | ||||
| 237 | |||||
| 238 | The full text of the license can be found in the | ||||
| 239 | LICENSE file included with this module. | ||||
| 240 | |||||
| 241 | =cut | ||||
# spent 26.9ms within PPI::Token::Symbol::CORE:match which was called 29489 times, avg 914ns/call:
# 7754 times (8.72ms+0s) by PPI::Token::Symbol::__TOKENIZER__on_char at line 165, avg 1µs/call
# 7245 times (10.3ms+0s) by PPI::Token::Symbol::__TOKENIZER__on_char at line 200, avg 1µs/call
# 7245 times (5.42ms+0s) by PPI::Token::Symbol::__TOKENIZER__on_char at line 194, avg 748ns/call
# 7245 times (2.54ms+0s) by PPI::Token::Symbol::__TOKENIZER__on_char at line 188, avg 351ns/call |